Страницы

Поиск по вопросам

вторник, 25 июня 2019 г.

SimpleJavaFileObject импорт кастом пакета/классов

Приветствую!
Задача заключается в компиляции динамического класса(созданного из строкового представления) и дальнейшем инстанцировании.
Проблема заключается в импортировании моего пакета/классов, хранящихся в отличных от стандартных 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 optionList = new ArrayList(); optionList.addAll(Arrays.asList("-classpath", System.getProperty("java.class.path")));
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 diagnostics = diagnosticsCollector.getDiagnostics();
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 m = new HashMap();
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"));

Комментариев нет:

Отправить комментарий