I am currently developing a program that can execute JUnit test cases on external classes. These external classes are sent in by students and we would like to evaluate them.
I have the following test case
import static org.junit.Assert.*;
import org.junit.Test;
public class Task1Test {
#Test
public void testAdd() {
Task1 t = new Task1();
int a = 5;
int b = 11;
assertEquals("Wrong add result", a+b, t.add(a,b));
}
}
and I compiled it with:
$ javac -cp .:../lib/junit/junit-4.11.jar Task1Test.java
The Task1 will be a student's class, but for now it is just a sample class with an add method that will return a wrong result. The file Task1.java is located in the same folder as Task1Test.java.
In my program I load the test case class and try to run it with JUnitCore:
String testsPath = "/path/to/classes";
String junitJar = "/path/to/junit-4.11.jar"
URL taskUrl = new File(testsPath).toURI().toURL();
URL[] urls = new URL[] {taskUrl,junitJar};
#SuppressWarnings("resource")
ClassLoader loader = new URLClassLoader(urls);
Class<?> clazz = loader.loadClass(task);
Result res = JUnitCore.runClasses(clazz);
if(!res.wasSuccessful()) {
for(Failure f : res.getFailures()) {
System.out.println(f.toString());
}
}
However, it does not work as expected. When I run this code, I get this message:
initializationError(Task1Test): No runnable methods
When I look into the loaded class using reflections, I can see that the method testAdd has no annotation (i.e. method.getAnnotation(org.junit.Test.class) returns null).
Does anyone have an idea? Did I forget a compiler switch or anything?
I am using Java 1.7.0_11 and the code is run in an web application on Glassfish 3.1.2.2
EDIT:
I can run the test case from command line with:
$ java -cp .:../../code/lib/junit/junit-4.11.jar:../../code/lib/junit/hamcrest-core-1.3.jar org.junit.runner.JUnitCore Task1Test
I found a solution from this answer
I did not set a parent class loader, which seems to have caused the trouble. Setting it as it was said in the other answer it now executes the test.
Related
I have a project in RAD. Package is inputFileEdit, and the java class I need is InputFileTest.java.
package inputFileEdit;
public class InputFileTest {
public static void main(String[] args) {
String var1 = args[0];
String var2 = args[1].toLowerCase();
// do stuff with args
}
}
I want to create a new package / java program that can call or instantiate the class InputFileTest above, with arguments, multiple times in parallel. I'm basically going to be bringing back a String list, looping through that list to create parallel threads, each row on the list calling InputFileTest.
Question 1) What's the best way to call InputFileTest? I'm using RAD and I created a new Project, a package called CallerPackage, and a Caller.java inside that package? I also including a "Jar" of the whole InputFileEdit project under /lib via Java Build Path -> Libraries -> Add External Jars. I don't know how to call the class with parameters (I tried something like InputFileEdit ifeObj = new InputFileEdit("parm 1", "parm 2"); or InputFileEdit ifeObj = new InputFileEdit("parm 1 parm 2");) but neither worked so then I tried to just call the jar like Process p = Runtime.getRuntime().exec("java -jar /lib/InputFileEdit.jar parm1 parm2"); or since I want the actual Class InputFileTest, Process p = Runtime.getRuntime().exec(new String[]{"java","-cp","/lib/InputFileEdit.jar", "InputFileTest", "parm1","parm1"});:
package CallerPackage;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
//import inputFileEdit.*;
public class Caller {
static int i = 0;
public static void main(String args[]) throws IOException, InterruptedException {
try {
System.out.println("Calling jar");
Process p = Runtime.getRuntime().exec("java -jar /lib/InputFileEdit.jar parm1 parm2");
BufferedInputStream errStrm = new BufferedInputStream(p.getErrorStream());
// get the error stream of the process and print it
for (int i = 0; i < errStrm.available(); i++) {
System.out.println("" + errStrm.read());
}
System.out.println("Called jar");
p.destroy();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
but this doesn't seem to work either or print out anything helpful. Any ideas of the best way to go about this? I'm only trying to get 1 call to work for now before I loop through my list and call them in parallel. Eventually it'll be calling the jar/class looping through a string arraylist.
you should be able to call the main method in InputFileTest the same way you would call any other static method: InputFileTest.main(args);
However, generally directly calling main is frowned upon. If you are able, I would advise you to take the code in InputFileTest's main, and put it into another, more descriptively named method, something like processFiles.
I want to call the Groovy scripts from Java and refresh the Groovy scripts periodically.
For example ,
public class AppTest {
public static void main(String args[]) throws Exception {
TestVO test = new TestVO();
AnotherInput input = new AnotherInput();
test.setName("Maruthi");
input.setCity("Newark");
GroovyClassLoader loader = new GroovyClassLoader(AppTest.class.getClassLoader());
Class groovyClass = loader.parseClass(new File("src/main/resources/groovy/MyTestGroovy.groovy"));
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
Object[] inputs = {test,null};
Map<String,String> result = (Map<String, String>)groovyObject.invokeMethod("checkInput", inputs);
System.out.println(result);
}
}
And my Groovy script is
class MyTestGroovy {
def x = "Maruthi";
def checkInput = { TestVO input,AnotherInput city ->
if(input.getName().equals(x)) {
input.setName("Deepan");
println "Name changed Please check the name";
} else {
println "Still Maruthi Rocks";
}
Map<String, String> result = new HashMap<String,String>();
result.put("Status", "Success");
if(city != null && city.getCity().equalsIgnoreCase("Newark")) {
result.put("requested_State", "Newark");
}
return result;
}
def executeTest = {
println("Test Executed");
}
}
How efficient my memory would be managed when I create multiple instances of groovy script and execute the script. Is it advisable to use a number of Groovy scripts as my customized rule engine. Please advise.
It is usually better to have several instances of the same script, than parsing the class every time you want to create an instance. Performance wise that is because compiling the script takes some time, you have to pay in addition to creating an instance. Memory wise you use up the number of available classes up faster. Even if old classes are collected, if you have many scripts active, it can happen... though that normally means hundreds or even thousands of them (depends on the jvm version and your memory settings)
Of course, once the script changed, you will have to recompile the class anyway. So if in your scenario you will have only one instance of the class active at the same time, and a new instance is only required after a change to the source, you can recompile every time.
I mention that especially, because you might even be able to write the script in a way, that let's you reuse the same instance. But it is of course beyond the scope of this question.
This is a bit tricky to explain. I have a class A:
public class A {
private Integer a1;
private Integer a2;
// getters and setters.
}
There is a static class B that returns my class A:
public static class B {
public static A getCurrentA() {
return a;
}
}
I need to find all usages of class A returned by B. So let's say class C calls c.setA(B.getCurrentA()) and then further along there's a call to c.getA().getA2();, I'd want to find all of these.
In the real scenario, I have 217 different classes that call B.getCurrentA(). I can't manually follow all the calls in Eclipse and find out which methods are getting called.
Eclipse call hierarchy view only shows me all calls to B.getCurrentA().
How can I achieve this?
EDIT
Chris Hayes understood what I want to do. In order to refactor some really bad legacy code without breaking the whole system, I need to first fine-tune some queries using Hibernate's projections (every mapped entity in the system is eagerly loaded, and many entities are related, so some queries take a LONG time fetching everything). But first I need to find which properties are used so that I don't get a NullPointerException somewhere...
Here's an example of what I'd have to do manually:
Use Eclipse's Search to find all calls to B.getCurrentA();
Open the first method found, let's say it's the one below:
public class CController {
C c = new C();
CFacade facade = new CFacade();
List<C> Cs = new ArrayList<C>();
public void getAllCs() {
c.setA(B.getCurrentA()); // found it!
facade.search(c);
}
}
Open the search method in the CFacade class:
public class CFacade {
CBusinessObject cBo = new CBusinessObject();
public List<C> search(C c) {
// doing stuff...
cBo.verifyA(c);
cBo.search(c); // yes, the system is that complicated
}
}
Open the verifyA method in the CBusinessObject class and identify that field a2 is used:
public class CBusinessObject {
public void verifyA(c) {
if (Integer.valueOf(1).equals(c.getA().getA2())) {
// do stuff
else {
// something else
}
}
}
Repeat steps 2-4 for the next 216 matches... Yay.
Please help.
If you want to make any source code changes/refactoring you will have to manually find all usages and apply your code changes;
Any way, I have two different aproach
Static search
You can simply do Text Search in eclipse to find the occurance of getA2() . It will directly take you to the Caller method (here CBusinessObject.verifyA()) -but it will give you every getA2() occurances, may be from different class
Run time search
Use java instrumentation API to change the byte code at run time on your required method to find invoking class and run as java agent - Enable you to identify the caller with out touching the existing code base and very useful especially when you don't have access to source code.
Here you go how to implement
Step 1- Write Agent main class to initiate instrumentation
public class BasicAgent {
public static void premain(String agentArguments, Instrumentation instrumentation){
System.out.println("Simple Agent");
FindUsageTransformer transformer = new FindUsageTransformer ();
instrumentation.addTransformer(transformer,true);
}
}
Step 2 -Write a ClassFileTransformer implementation and capture the method
public class FindUsageTransformer implements ClassFileTransformer{
Class clazz = null;
public byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
if(className.equals("A")){
doClass(className, classBeingRedefined, classfileBuffer);
}
return classfileBuffer;
}
private byte[] doClass(String name, Class clazz, byte[] b) {
ClassPool pool = ClassPool.getDefault();
CtClass cl = null;
try {
cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
CtMethod method = cl.getDeclaredMethod("getA2");
// here you have lot of options to explore
method.insertBefore("System.out.println(Thread.currentThread().getStackTrace()[0].getClassName()+ Thread.currentThread().getStackTrace()[0].getMethodName());");
b = cl.toBytecode();
} catch (Exception e) {
System.err.println("Could not instrument " + name
+ ", exception : " + e.getMessage());
} finally {
if (cl != null) {
cl.detach();
}
}
return b;
}
Step 3- create jar file for agent classes ( you have to set manifest file with premain class, and add javaassit jar) snippet of build file is given - you can do it by manually as well
<jar destfile="build/jar/BasicAgent.jar" basedir="build/classes">
<manifest>
<attribute name="Manifest-Version" value="1.0"/>
<attribute name="Premain-Class" value="com.sk.agent.basic.BasicAgent"/>
<attribute name="Boot-Class-Path" value="../lib/javassist.jar"/>
</manifest>
</jar>
Step 4- Run your main application with java agent - before that set VM arguments to load agent
-`javaagent:D:\softwares\AgentProject\AgentLib\build\jar\BasicAgent.jar`
Pre requisite : you would need javassist.jar in the class path.
Depending on the IDE you are using this problem is simpler to find.
Eclipse IDE has one of the most potential Call Hierarchy modules existing, you just need to put the mouse in the method declaration that you want to find and execute Ctrl + Alt + H
This will give you the entire hierarchy of which method is using the method you want to analyze.
Also the Call Hierarchy module offers a mode where you can find the methods that your method is calling.
Some extra info: http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Freference%2Fcdt_u_call_hierarchy_view.htm
In IntelliJ IDEA, if you want to find usages of c.getA().getA2(); right-click on A.a2 and choose "find usages." Similarly for A.a1 and B.getCurrentA(). Unused fields and methods show up in a different color in IDEA. I've heard that IntelliJ has more refactoring power than Eclipse, but I bet Eclipse does the same thing, just slightly differently.
Also, using grep, find, and sed, you can search for the appropriate methods, just in files that are in the same package as A or that import A, or spell it out by name.
I hope I understood your question correctly. I think you can use grep -Irns function to find the calls. You can grep for getA().getA2(). That will return lines from where functions are called along with line numbers.
Rather than scanning for all references to the method getCurrentA do a scan for all references to the Class A.
This will show you everywhere that class is used within your program and you will probably find it is easier to go through and scan that list by hand and decide if you need to act on each result found than trying to do anything fancy.
The easiest way to find Call Usage is using references in eclipse,but there is a funny way
:
Change method name to B.getCurrentAA()
Build your Project
Your Project compiles with error
Go to Marks Part and see usage Error And Find Usage Of your method
I think IntelliJ can solve your problem. It have an "Analyze dataflow" feature and I think it is doing what you are looking for:
Here is my sample code:
public class Main {
private static A a = new A(); //nevermind the way it is initialized
public static A getA(){
return a;
}
public void method(){
A myA = getA();
Integer a1 = myA.getA1(); //this line is found
Integer a2 = myA.getA2(); //this line is found
}
public void anotherMethod(){
A myA = new A();
Integer a1 = myA.getA1(); //this line is NOT found
Integer a2 = myA.getA2(); //this line is NOT found
}
}
Running the "Analyze dataflow from here" (with cursor on return a; line) give me this:
Sorry to provide you only a solution with IntelliJ (tested with IntelliJ-13 Ultimate Edition)
I'm trying to do something similar to Question 4617364 but for Python - load a class from python script file, where said class implements a Java interface and hand it over to some Java code that can use its methods - but calls to the object method return invalid values and printing from the initializer doesn't seem to do anything.
My implementation looks like this:
Interface:
package some.package;
import java.util.List;
public interface ScriptDemoIf {
int fibonacci(int d);
List<String> filterLength(List<String> source, int maxlen);
}
Python Implementation:
from some.package import ScriptDemoIf
class ScriptDemo(ScriptDemoIf):
""" Class ScriptDemo implementing ScriptDemoIf """
def __init__(self):
print "Script Demo init"
def fibonacci(self, d):
if d < 2:
return d
else:
return self.fibonacci(d-1) + self.fibonacci(d-2)
def filterLength(self, source, maxlen):
return [ str for str in source if len(str) <= maxlen ]
Class loader:
public ScriptDemoIf load(String filename) throws ScriptException {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("jython");
FileReader script = new FileReader(filename);
try {
engine.eval(new FileReader(script));
} catch (FileNotFoundException e) {
throw new ScriptException("Failed to load " + filename);
}
return (ScriptDemoIf) engine.eval("ScriptDemo()");
}
public void run() {
ScriptDemoIf test = load("ScriptDemo.py");
System.out.println(test.fibonacci(30));
}
(Obviously the loader is a bit more generic in real life - it doesn't assume that the implementation class name is "ScriptDemo" - this is just for simplicity).
When the code is being ran, I don't see the print from the Python's __init__ (though if I put a print in the body of the script then I do see that), but the test variable in run() look like a valid jython "proxy object" and I get no casting errors. When I try to run the fibonacci() method I always get 0 (even if I change the method to always return a fixed number) and the filterLength() method always returns null (probably something to do with defaults according to the Java interface).
what am I doing wrong?
What version of jython are you using? You might have run into the JSR223 Jython bug : http://bugs.jython.org/issue1681
From the bug description:
Calling methods from an embedded Jython script does nothing when
using JSR-223 and Jython 2.5.2rc2, while Jython 2.2.1 just works fine.
I am running an executable jar and wish to find a list of classes WITHIN the jar so that I can decide at run-time which to run. It's possible that I don't know the name of the jar file so cannot unzip it
You can not enumerate classes from a package of jar using Reflection API. This is also made clear in the related questions how-can-i-enumerate-all-classes-in-a-package and
can-i-list-the-resources-in-a-given-package. I once wrote a tool that lists all classes found in a certain classpath. It's too long to paste here, but here is the general approach:
find the used classpath. This is shown nicely by eirikma in another answer.
add other places where the ClassLoader might search for classes, e.g. bootclasspath, endorsed lib in JRE etc. (If you just have a simple app, then 1 + 2 are easy, just take the class path from property.)
readAllFromSystemClassPath("sun.boot.class.path");
readAllFromSystemClassPath("java.endorsed.dirs");
readAllFromSystemClassPath("java.ext.dirs");
readAllFromSystemClassPath("java.class.path");
Scan the classpath and split folders from JARs.
StringTokenizer pathTokenizer = new StringTokenizer(pPath, File.pathSeparator);
Scan the folders with File.listFiles and open the JARs with ZipFile.entries. Pay attention to inner classes and package access classes, you propably do not want them.
isInner = (pClassName.indexOf('$') > -1);
Convert the file name or path in the JAR to a proper classname (/ -> .)
final int i = fullName.lastIndexOf(File.separatorChar);
path = fullName.substring(0, i).replace(File.separatorChar, '.');
name = fullName.substring(i + 1);
Now you can use Reflection to load that class and have a look into it. If you just want to know stuff of about the class you can load it without resolving, or use a byte code engineering library like BCEL to open the class without loading it into the JVM.
ClassLoader.getSystemClassLoader().loadClass(name).getModifiers() & Modifier.PUBLIC
I am not sure if there is a way to list all classes visible to the current classloader.
Lacking that, you could
a) try to find out the name of the jar file from the classpath, and then look at its contents.
or
b) supposing that you have a candidate list of classes you are looking for, try each of them with Class.forName().
you can use a simple program to get a list of all the class files from jar and dump it in a property file on runtime and then in your program you can load req. class as and when req.; without using reflections.
You can get the actual classpath from the classloader. this must include the jar file, otherwise the program wouldn't run. Look throug the classpath URLs to find a URL that ends with ".jar" and contains something that is never changing in the name of you jar file (preferably after the last "/"). After that you open it as a regular jar (or zip) file and read the contents.
There are several methods available for obtaining the classpath. None of them works in every context and with every setup, so you must try them one by one until you find one that works in all the situations you need it to work. Also, sometimes you might need to tweak the runtime context, like (often needed) substituting maven surefire-plugin's classloading mechanism to one of optional (non-default) ones.
Obtaining the classpath 1: from system property:
static String[] getClasspathFromProperty() {
return System.getProperty("java.class.path").split(File.pathSeparator);
}
Obtaining the classpath 2: from classloader (with maven warning):
String[] getClasspathFromClassloader() {
URLClassLoader classLoader = (URLClassLoader) (getClass().getClassLoader());
URL[] classpath = classLoader.getURLs();
if (classpath.length == 1
&& classpath[0].toExternalForm().indexOf("surefirebooter") >= 0)
{
// todo: read classpath from manifest in surefireXXXX.jar
System.err.println("NO PROPER CLASSLOADER HERE!");
System.err.println(
"Run maven with -Dsurefire.useSystemClassLoader=false "
+"-Dsurefire.useManifestOnlyJar=false to enable proper classloaders");
return null;
}
String[] classpathLocations = new String[classpath.length];
for (int i = 0; i < classpath.length; i++) {
// you must repair the path strings: "\.\" => "/" etc.
classpathLocations[i] = cleanClasspathUrl(classpath[i].toExternalform());
}
return classpathLocations;
}
Obtaining the classpath 3: from current thread context: This is similar to method 2, except the first line of the method should read like this:
URLClassLoader classLoader
= (URLClassLoader)(Thread.currentThread().getContextClassLoader());
Good luck!
I would use a bytecode inspector library like ASM. This ClassVisitor can be used to look for the main method:
import org.objectweb.asm.*;
import org.objectweb.asm.commons.EmptyVisitor;
public class MainFinder extends ClassAdapter {
private String name;
private boolean isMainClass;
public MainFinder() {
super(new EmptyVisitor());
}
#Override
public void visit(int version, int access, String name,
String signature, String superName,
String[] interfaces) {
this.name = name;
super.visit(version, access, name, signature,
superName, interfaces);
}
#Override
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
if ((access & Opcodes.ACC_PUBLIC) != 0
&& (access & Opcodes.ACC_STATIC) != 0
&& "main".equals(name)
&& "([Ljava/lang/String;)V".equals(desc)) {
isMainClass = true;
}
return super.visitMethod(access, name, desc, signature,
exceptions);
}
public String getName() {
return name;
}
public boolean isMainClass() {
return isMainClass;
}
}
Note that you might want to alter the code to confirm that classes are public, etc.
This sample app uses the above class on a command-line-specified JAR:
import java.io.*;
import java.util.Enumeration;
import java.util.jar.*;
import org.objectweb.asm.ClassReader;
public class FindMainMethods {
private static void walk(JarFile jar) throws IOException {
Enumeration<? extends JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
MainFinder visitor = new MainFinder();
JarEntry entry = entries.nextElement();
if (!entry.getName().endsWith(".class")) {
continue;
}
InputStream stream = jar.getInputStream(entry);
try {
ClassReader reader = new ClassReader(stream);
reader.accept(visitor, ClassReader.SKIP_CODE);
if (visitor.isMainClass()) {
System.out.println(visitor.getName());
}
} finally {
stream.close();
}
}
}
public static void main(String[] args) throws IOException {
JarFile jar = new JarFile(args[0]);
walk(jar);
}
}
You may also want to look at the "java.class.path" system property.
System.getProperty("java.class.path");
It is possible to use reflection to obtain similar results, but that approach may have some unfortunate side-effects - like causing static initializers to be run, or keeping unused classes in memory (they will probably stay loaded until their ClassLoader is garbage collected).