I'm not an expert in Java and I'm pretty new to the whole concept of compiling and running dynamic generated code, which is so simple in other languages, expecially script languages like Javascript and PHP.
I'm following this snippet of code:
http://www.java2s.com/Code/Java/JDK-6/CompilingfromMemory.htm
and I made something like this:
private final String = "GeneratedClass_" + Long.toHexString(random.nextLong());
private Method compileCode(String code) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) return null;
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
JavaFileObject source = new JavaSource(className, code);
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(source);
CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
if (!task.call()) return null;
try {
return Class.forName(className).getDeclaredMethods()[0];
} catch (ClassNotFoundException e) {}
return null;
}
private class JavaSource extends SimpleJavaFileObject {
final String code;
JavaSource(String name, String code) {
super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
this.code = code;
}
#Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {return code;}
}
Just imagine that the string code is something like
"public class GeneratedClass_65ce701239c32ce0 {
public String hello() {
return "Hello, world!";
}
}"
It works well until that Class.forName which throws a ClassNotFoundException. I'm puzzled since it doesn't seem I cut something important from the snippet: so, the class was compiled but where has it gone?
I read something about using a different class loader, but since, like I said, I'm pretty new to all this stuff I don't know where to head and how to use it, and how should I define my own extension of ClassLoader.
The only thing I know is that everything seems quite complicated to me...
Using Eclipse Indigo in Windows 7 and JDK 1.7.
One important thing you cut was all the error output and diagnostic information. You'd never know if something went wrong. However, everything looks correct. Your problem is most likely just that you didn't send any options to the compiler, so it'll write the class file out to wherever it feels like (current working directory is the default, I believe), and that's probably not on your classpath, especially in an IDE. Try running it from the command line to prove to yourself it works. This should work:
mkdir tmp
javac -d tmp <path your main class .java file>
java -cp .;tmp <your main class name>
If you're not familiar with the command-line tools, the argument to javac has to be a file system path to the .java file, and the argument to java needs to be the .-separated, fully-qualifed class name, like com.foo.Main. Doing that should:
Compile your class to the tmp directory.
Write your dynamically-generated class to the current directory.
Successfully load the newly compiled class from the current directory because it's on the classpath.
Related
I'm trying to run a groovy(2.4.3) script on windows that calls a goovy class xxxxx.groovy. I've tried a number of variations using classpath and various scripts, some examples below, always getting MultipleCompliationErrorsException.... unable to resolve class
classfile is firstclass.groovy
import org.apache.commons.io.FilenameUtils
class firstclassstart {
def wluid, wlpwd, wlserver, port
private wlconnection, connectString, jmxConnector, Filpath, Filpass, Filname, OSRPDpath, Passphrase
// object constructor
firstclassstart(wluid, wlpwd, wlserver, port) {
this.wluid = wluid
this.wlpwd = wlpwd
this.wlserver = wlserver
this.port = port
}
def isFile(Filpath) {
// Create a File object representing the folder 'A/B'
def folder = new File(Filpath)
if (!org.apache.commons.io.FilenameUtils.isExtension(Filpath, "txt")) {
println "bad extension"
return false
} else if (!folder.exists()) {
// Create all folders up-to and including B
println " path is wrong"
return false
} else
println "file found"
return true
}
}
cmd line script test.groovy
import firstclass
def sample = new firstclass.firstclassstart("weblogic", "Admin123", "x.com", "7002")
//def sample = new firstclassstart("weblogic", "Admin123", "x.com", "7002")
sample.isFile("./firstclass.groovy")
..\groovy -cp "firstclass.groovy;commons-io-1.3.2.jar" testfc.groovy
script test.groovy
GroovyShell shell = new GroovyShell()
def script = shell.parse(new File('mylib/firstclass.groovy'))
firstclass sample = new script.firstclass("uid", "pwd", "url", "port")
sample.getstatus()
c:>groovy test.groovy
script test.groovy v2 put firstclass.groovy in directory test below script
import test.firstclass
firstclass sample = new script.firstclass("uid", "pwd", "url", "port")
sample.getstatus()
c:>groovy test.groovy
just looking for a bullet proof, portable way to oranize my java classes, .groovy classess, etc. and scripts.
Thanks
I think that you can do using for example your first approach:
groovy -cp mylib/firstclass.groovy mylib/test.groovy
However I see some problems in your code which are probably causing MultipleCompliationErrorsException.
Since you're including firstclass.groovy in your classpath, you've to add the import firstclass in the test.groovy.
Why are you using script.firstclass in test.groovy? you're class is called simply firstclass.
In your firstclass.groovy you're using import org.apache.commons.io.FilenameUtils and probably other, however you're not including it in the classpath.
So finally I think that, you've to change your test.groovy for something like:
import firstclass
firstclass sample = new firstclass("uid", "pwd", "url", "port")
sample.getstatus()
And in your command add the remaining includes for apache Commons IO to the classpath.
groovy -cp "mylib/firstclass.groovy;commons-io-2.4.jar;" mylib/testexe.groovy
Hope this helps,
UPDATE BASED ON OP CHANGES:
After the changes you've some things wrong, I try to enumerate it:
If your file is called firstclass.groovy your class must be class firstclass not class firstclassstart.
In your test.groovy use new firstclass not new firstclass.firstclassstart.
So the thing is, your code must be:
class file firstclass.groovy:
import org.apache.commons.io.FilenameUtils
class firstclass {
def wluid, wlpwd, wlserver, port
private wlconnection, connectString, jmxConnector, Filpath, Filpass, Filname, OSRPDpath, Passphrase
// object constructor
firstclass(wluid, wlpwd, wlserver, port) {
this.wluid = wluid
this.wlpwd = wlpwd
this.wlserver = wlserver
this.port = port
}
def isFile(Filpath) {
// Create a File object representing the folder 'A/B'
def folder = new File(Filpath)
if (!org.apache.commons.io.FilenameUtils.isExtension(Filpath, "txt")) {
println "bad extension"
return false
} else if (!folder.exists()) {
// Create all folders up-to and including B
println " path is wrong"
return false
} else
println "file found"
return true
}
}
script test.groovy:
import firstclass
def sample = new firstclass("weblogic", "Admin123", "x.com", "7002")
sample.isFile("./firstclass.groovy")
Finally the command to execute it:
groovy -cp "firstclass.groovy;commons-io-1.3.2.jar" test.groovy
With this changes your code must works, I try it and works as expected.
I have a file.py as follows :
import unittest
from com.bahmanm import Greeter
class A(unittest.TestCase, Greeter):
def test_A(self):
self.greet("Bahman")
if __name__ == "__main__":
unittest.main()
In above case, Greeter is a java file as:
package com.bahmanm;
public class Greeter
{
private String msg;
public Greeter()
{
msg = "Hello, ";
}
public void greet(String name)
{
System.out.println(msg + name);
}
}
The code executes successfully, but I am not able to navigate from python code to java code (in PyDev) at line self.greet("Bahman") in the file.py code.
Though, I am able to view the contents of Greeter file from line
from com.bahmanm import Greeter. But unable to check the code flow at the function call.
I am using jython interpreter (grammar 2.5, default interpreter,jython.jar 2.5.3). I have also added the Java src path to PYTHONPATH in Eclipse. Also I have added Java project in the
PYTHON PROJECT->RIGHT CLICK->PROPERTIES-> PROJECT REFERENCES
Any suggestion regarding the above navigation will be of great help.
I am writing an application that will load Java scripts. I currently have a GUI which utilizes a JFileChooser to allow the user to select a script from their machine. The script file can be anywhere. It is not on the classpath. Having only a File object to represent that script file, how can I obtain a Class representation of it?
I know that to load a class you need its binary name, so in.this.format. However, the problem with that is I don't know how the script writer may have packaged it. For example, he/she may have, while developing it, put the script file in the package foo.bar. After I download this script and place it in my documents (i.e., not in foo/bar), I can't load the script without knowing that it was packaged in foo.bar. If the class name is Test and I try to create a URLClassLoader pointing to the script file by doing new URLClassLoader(new URL[] { new URL(scriptFile.toURI().toURL()) }) and I do classLoader.loadClass("Test") I will get an exception saying that the class had the wrong name, and the correct name is foo.bar.Test. But how am I supposed to know that ahead of time?
This is what I have right now:
public class ScriptClassLoader extends URLClassLoader {
private final File script;
public ScriptClassLoader(File script) throws MalformedURLException {
super(new URL[] { script.toURI().toURL() });
this.script = script;
}
public Class<?> load() throws ClassNotFoundException {
String fileName = script.getName();
String className = fileName.substring(0, fileName.indexOf(".class"));
return loadClass(className);
}
}
How do people load scripts at runtime that are not part of the program's classpath, and the binary name of the class is not known?
If you just need to load a class from a given .class file, no matter how this classes is named, you can load the data yourself and then call ClassLoader's defineClass() method:
RandomAccessFile raf = new RandomAccessFile(script, "r");
try {
byte[] classData = new byte[(int) raf.length()];
raf.readFully(classData);
return super.defineClass(null, classData, 0, classData.length);
} finally {
raf.close();
}
I'm using JavaCompiler to compile a class. I have jar dependency, where I used to give it in class path, I have a class (class1) file in the same directly, which is a dependent for another class (class2).
Simply
Class1.class
Class2.java
I want to compile Class2.java, in Class2 have a code like
Class1.sayHi();
When I compile it its saying
error: cannot find symbol
How can I include Class1.class while compiling Class2
My compiler code
String fileToCompile = classFile;
System.setProperty("java.home", RuntimeCompiler.getJDKPath());
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationSource =
fileManager.getJavaFileObjects(fileToCompile);
List<String> optionList = new ArrayList<String>();
optionList.addAll(Arrays.asList("-classpath",dynamicClassPath));
try{
compiler.getTask(null, null, null, optionList, null, compilationSource).call();
return true;
}catch (Exception e) {
return false;
}
You can specify multiple files/classes on the class path. Just separate them with either a colon or semicolon, depending on your platform.
Have you verified that it will compile using just the javac command? If this works then it must be something in your procedure and not the class path.
The class path for a particular compiled class can be given as
-classpath "full_folder_Path_Till_Package"
Ex:
dynamicClassPath = "C:/work/sample1/core"
in core directory you will have package folder "com" inside that dependant class.
I'm building a video game and I've built a launcher for my video game as well. The launcher downloads .jar files and stores them in the %appdata% folder for each person who buys the game and downloads the launcher and then runs it.
I need to be able to write a few lines of code to tell the launcher to get the .jar file from the user's computer and run a file from there. The .jar is already compiled and everything is okay and whatnot, but I'm not quite sure how to get the .class file to work with.
Something like this might help:
import System.getPropery("user.home") + "/AppData/Roaming/GameNameHere/bin/game.jar" + ".runGame.class"
And then I could possible do something like this:
if (credentials == true) {
runGame game = new runGame();
game.start();
}
How would I do something like this? Thanks in advance.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So, I looked the ClassLoader.java class and messed around with it for a bit, but nothing really worked well. What am I doing wrong?
private String location = System.getProperty("user.home") + "\\Desktop\\myJar.jar";
URL url = new URL(location);
public Load() throws Exception {
ClassLoader loader = URLClassLoader.newInstance(new URL[]{url}, getClass().getClassLoader());
Class<?> clazz = Class.forName("gumptastic.MyClass", true, loader);
Method method = clazz.getMethod("output");
method.invoke(this);
}
public static void main(String[] args) {
try {
new Load();
} catch (Exception exc) {
exc.printStackTrace();
}
}
Not sure if you're familiar with this but
I think you should look at class loaders.
http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html
I guess you would need to write a simple one for your particular needs.
Alternatively, it would be even easier if you just use URLClassLoader.
Below is a simple example. This program has no idea of the Gson class
at compile time. But it can successfully load it, create an instance of it,
and use it at runtime. It was tested on Windows 7.
You can download Google Gson from here.
http://code.google.com/p/google-gson/downloads/list
Then place the gson-2.2.4.jar file anywhere you like
on your computer, then point this program to it by
setting arr[0] in the proper way.
Then observe the magic that is taking place :)
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
public class Test007 {
public static void main(String[] args) throws Exception {
URL[] arr = new URL[1];
arr[0] = new URL("file:///dir1/dir2/dir3/gson-2.2.4.jar");
URLClassLoader loader = new URLClassLoader(arr);
Class cls = loader.loadClass("com.google.gson.Gson");
System.out.println(cls);
Constructor constructor = cls.getConstructor(new Class[0]);
Object obj = constructor.newInstance(new Object[0]);
System.out.println(obj);
if (obj!=null){
System.out.println("OK, so now we have an instance of:");
System.out.println(obj.getClass().getName());
}
}
}