diff --git a/README.md b/README.md index b0ce5d8..c6151ea 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,12 @@ E.g.: Class helloClass = InMemoryJavaCompiler.compile("org.mdkt.HelloClass", sourceCode.toString()); + String classNames[] = new String[]{"com.compile.test.A", "com.compile.test.B"}; + String sources[] = new String[]{"package com.compile.test;import com.compile.test.B;public class A{ B b;int i;}", + "package com.compile.test; public class B{String a;}"}; + + Class[] classes = InMemoryJavaCompiler.mutilCompile(classNames, sources); + Artifact is pushed to Sonatype OSS Releases Repository https://oss.sonatype.org/content/repositories/releases/ diff --git a/src/main/java/org/mdkt/compiler/DynamicClassLoader.java b/src/main/java/org/mdkt/compiler/DynamicClassLoader.java index ebda934..1585856 100644 --- a/src/main/java/org/mdkt/compiler/DynamicClassLoader.java +++ b/src/main/java/org/mdkt/compiler/DynamicClassLoader.java @@ -18,6 +18,14 @@ public void setCode(CompiledCode cc) { customCompiledCode.put(cc.getName(), cc); } + public CompiledCode getCompiledCode(String className) { + return customCompiledCode.get(className); + } + + public Map getCustomCompiledCode() { + return customCompiledCode; + } + @Override protected Class findClass(String name) throws ClassNotFoundException { CompiledCode cc = customCompiledCode.get(name); @@ -27,4 +35,8 @@ protected Class findClass(String name) throws ClassNotFoundException { byte[] byteCode = cc.getByteCode(); return defineClass(name, byteCode, 0, byteCode.length); } + + public Class getClass(String name, byte[] data) throws Exception { + return defineClass(name, data, 0, data.length); + } } diff --git a/src/main/java/org/mdkt/compiler/ExtendedStandardJavaFileManager.java b/src/main/java/org/mdkt/compiler/ExtendedStandardJavaFileManager.java index 4e1cd0b..ad8f75d 100644 --- a/src/main/java/org/mdkt/compiler/ExtendedStandardJavaFileManager.java +++ b/src/main/java/org/mdkt/compiler/ExtendedStandardJavaFileManager.java @@ -27,9 +27,25 @@ protected ExtendedStandardJavaFileManager(JavaFileManager fileManager, CompiledC this.cl.setCode(compiledCode); } + /** + * Creates a new instance of ForwardingJavaFileManager. + * + * @param fileManager + * @param compiledCodes + * @param cl + */ + protected ExtendedStandardJavaFileManager(JavaFileManager fileManager, CompiledCode[] compiledCodes, DynamicClassLoader cl) { + super(fileManager); + this.compiledCode = compiledCode; + this.cl = cl; + for (CompiledCode compiledCode : compiledCodes) { + this.cl.setCode(compiledCode); + } + } + @Override public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { - return compiledCode; + return cl.getCompiledCode(className); } @Override diff --git a/src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java b/src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java index 865fd4a..6b53b2f 100644 --- a/src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java +++ b/src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java @@ -3,7 +3,10 @@ import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.ToolProvider; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; +import java.util.Map; /** * Created by trung on 5/3/15. @@ -21,4 +24,37 @@ public static Class compile(String className, String sourceCodeInText) throws boolean result = task.call(); return cl.loadClass(className); } + + public static Class[] mutilCompile(String[] classNames, String[] sourceCodeInTexts) throws Exception { + if (javac == null) { + throw new Exception("ToolProvider.getSystemJavaCompiler()==null,java.home = " + + System.getProperty("java.home") + " try to find tool.jar"); + } + if (classNames.length != sourceCodeInTexts.length) { + throw new Exception("classNames length != sourceCodeInTexts length!"); + } + List compilationUnits = new ArrayList(); + CompiledCode compiledCodes[] = new CompiledCode[classNames.length]; + for (int i = 0; i < classNames.length; i++) { + String className = classNames[i]; + String sourceCodeInText = sourceCodeInTexts[i]; + SourceCode sourceCode = new SourceCode(className, sourceCodeInText); + compiledCodes[i] = new CompiledCode(className); + compilationUnits.add(sourceCode); + } + DynamicClassLoader cl = new DynamicClassLoader(ClassLoader.getSystemClassLoader()); + ExtendedStandardJavaFileManager fileManager = new ExtendedStandardJavaFileManager(javac.getStandardFileManager(null, null, null), + compiledCodes, cl); + JavaCompiler.CompilationTask task = javac.getTask(null, fileManager, null, null, null, compilationUnits); + boolean result = task.call(); + if (!result) { + throw new Exception("Compile error!!!!"); + } + Map map = cl.getCustomCompiledCode(); + List> list = new ArrayList>(); + for (String key : map.keySet()) { + list.add(cl.findClass(key)); + } + return list.toArray(new Class[map.keySet().size()]); + } } diff --git a/src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java b/src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java index b20d169..93a1ef4 100644 --- a/src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java +++ b/src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java @@ -21,4 +21,15 @@ public void compile_whenTypical() throws Exception { Assert.assertNotNull(helloClass); Assert.assertEquals(1, helloClass.getDeclaredMethods().length); } + + @Test + public void compile_mutil_classes() throws Exception { + String classNames[] = new String[]{"com.compile.test.A", "com.compile.test.B"}; + String sources[] = new String[]{"package com.compile.test;import com.compile.test.B;public class A{ B b;int i;}", + "package com.compile.test; public class B{String a;}"}; + + Class[] classes = InMemoryJavaCompiler.mutilCompile(classNames, sources); + Assert.assertNotNull(classes); + Assert.assertEquals(classes.length, 2); + } }