2015-12-13 49 views
0

我第一次來這裏...SimpleJavaFileObject如何導入自定義(由我創建)包?

該任務是在編譯動態類(從字符串創建)和隨後創建實例化。

問題是在輸入我的自定義包/類,放在不同的文件夾,動態類。例如:import controller.*;後出現錯誤:

/CompiledClass.java:4: error: package controller does not exist 

但標準包(庫)已導入很好,沒有任何問題,編譯結束了同樣的方式。

我試着通過發送optionList路徑但沒有成功通過JavaCompiler Api的getTask方法來解決。

那麼如何更正導入自定義包?

這裏是我的代碼:

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;" + 
      '\n' + 
      "import java.io.*;\n" + 
      "import java.util.*;\n" + 
      "import controller.*;\n" + 
      '\n' + 
      "public class " + className +"{\n" + 
      " private Writer out = null;\n" + 
      '\n' + 
      " public " + className +"(Writer out){\n" + 
      "  this.out = out;\n" + 
      //"  this.container = container;" + 
      " }" + 
      " public void " + classMethod + "() throws java.io.IOException{\n" + 
        //inputString + 
      " }\n" + 
      "}\n"); 

    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<String> optionList = new ArrayList<String>(); 
    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<Diagnostic> 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<String,JavaObjectFromByteCode> m = new HashMap<String, JavaObjectFromByteCode>(); 

    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; 
    } 
} 

} 

提前感謝!

回答

0

的問題已經得到解決:

我添加路徑除了System.getProperty("java.class.path")我的罐子controller.jar。

下面是代碼:

optionList.addAll(Arrays.asList("-classpath", System.getProperty("java.class.path") + ";path/to/your/controller.jar"));