Приветствую!
Задача заключается в компиляции динамического класса(созданного из строкового представления) и дальнейшем инстанцировании.
Проблема заключается в импортировании моего пакета/классов, хранящихся в отличных от стандартных java-директорий (lib), в динамический класс. К примеру: после выполнения строки import controller.*; возникает ошибка:
/CompiledClass.java:4: error: package controller does not exist
но стандартные пакеты/классы импортируются без ошибок, и компиляция соответственно выполняется тоже без ошибок.
Пробовал решить через getTask метод JavaCompiler Api путем отправки optionList с параметрами, но в итоге не успешно.
Как правильно импортировать в динамический класс свои пакет/классы?
Мой код:
package view;
import controller.*;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URI;
import java.security.SecureClassLoader;
import java.util.*;
import javax.tools.*;
import javax.tools.JavaCompiler.*;
import javax.tools.JavaFileObject.Kind;
public class CompileJavaManager {
public static void compileJavaFileObject(StringBuilder inputString, Writer jspOut) throws Exception {
String className = "CompiledClass";
String classMethod = "methodOf" + className;
Class compiledClass = null;
//Class c = Class.forName(className);
StringBuilder javaFileContents =
new StringBuilder("" +
//"package compiled;" +
'
' +
"import java.io.*;
" +
"import java.util.*;
" +
"import controller.*;
" +
'
' +
"public class " + className +"{
" +
" private Writer out = null;
" +
'
' +
" public " + className +"(Writer out){
" +
" this.out = out;
" +
//" this.container = container;" +
" }" +
" public void " + classMethod + "() throws java.io.IOException{
" +
//inputString +
" }
" +
"}
");
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector diagnosticsCollector = new DiagnosticCollector();
StandardJavaFileManager standardJavaFileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
SpecialClassLoader classLoader = new SpecialClassLoader();
SpecialJavaFileManager fileManager = new SpecialJavaFileManager(standardJavaFileManager, classLoader);
List
JavaObjectFromString javaObjectFromString = new JavaObjectFromString(className, javaFileContents.toString());
Iterable fileObjects = Arrays.asList(javaObjectFromString);
Iterable classes = null;
Writer out = new PrintWriter(jspOut);
CompilationTask task = compiler.getTask(out, fileManager, diagnosticsCollector, optionList, classes, fileObjects);
Boolean result = task.call();
List
if (result) {
compiledClass = classLoader.findClass(className);
Constructor constructor = compiledClass.getConstructor(Writer.class);
Object instance = constructor.newInstance(jspOut);
//call the method, pass a null params
Method instanceMethod = compiledClass.getDeclaredMethod(classMethod, null);
instanceMethod.invoke(instance, null);
//System.out.println(instance);
} else {
// Compilation fails
for (Diagnostic d : diagnostics) {
System.out.println(d);
}
}
}
private static class JavaObjectFromString extends SimpleJavaFileObject {
private String sourceCode = null;
public JavaObjectFromString(String className, String sourceCode) throws Exception {
super(URI.create("file:///" + className + Kind.SOURCE.extension), Kind.SOURCE);
this.sourceCode = sourceCode;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return sourceCode;
}
@Override
public OutputStream openOutputStream() {
throw new IllegalStateException();
}
@Override
public InputStream openInputStream() {
return new ByteArrayInputStream(sourceCode.getBytes());
}
}
private static class JavaObjectFromByteCode extends SimpleJavaFileObject {
private ByteArrayOutputStream baos;
public JavaObjectFromByteCode(String name) {
super(URI.create("byte:///" + name + Kind.CLASS.extension), Kind.CLASS);
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
throw new IllegalStateException();
}
@Override
public OutputStream openOutputStream() {
baos = new ByteArrayOutputStream();
return baos;
}
@Override
public InputStream openInputStream() {
throw new IllegalStateException();
}
public byte[] getBytes() {
return baos.toByteArray();
}
}
private static class SpecialClassLoader extends ClassLoader {
private Map
protected Class findClass(String name) throws ClassNotFoundException {
JavaObjectFromByteCode jobc = m.get(name);
if (jobc==null){
jobc = m.get(name.replace(".","/"));
if (jobc==null){
return super.findClass(name);
}
}
return defineClass(name, jobc.getBytes(), 0, jobc.getBytes().length);
}
public void addClass(String name, JavaObjectFromByteCode jobc) {
m.put(name, jobc);
}
}
private static class SpecialJavaFileManager extends ForwardingJavaFileManager {
private SpecialClassLoader scl;
public SpecialJavaFileManager(StandardJavaFileManager sjfm, SpecialClassLoader scl) {
super(sjfm);
this.scl = scl;
}
public JavaFileObject getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
JavaObjectFromByteCode jobc = new JavaObjectFromByteCode(name);
scl.addClass(name, jobc);
return jobc;
}
public ClassLoader getClassLoader(Location location) {
return scl;
}
}
}
Заранее спасибо!
Ответ
Во время компиляции ты указал
optionList.addAll(Arrays.asList("-classpath", System.getProperty("java.class.path")));
Это значит, что компилятор во время компиляции видит только jar'ники из стандартной библиотеки. Твой jar'ник с пакетом controller наверняка лежит отдельно. Поэтому надо испльзовать
optionList.addAll(Arrays.asList("-classpath", System.getProperty("java.class.path")+";путь/где/лежит/jar/с/пакетом/controller.jar"));
Комментариев нет:
Отправить комментарий