oms3.compiler.Compiler Maven / Gradle / Ivy
package oms3.compiler;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;
/**
*
*/
public final class Compiler {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
MemoryOutputJavaFileManager fileManager;
ClassLoader loader;
Map> cache = new HashMap>();
List compilerOptions = new ArrayList();
//
private static Compiler instance;
public static synchronized Compiler singleton(URLClassLoader parent) {
if (instance == null) {
instance = new Compiler(parent);
}
return instance;
}
private Compiler(URLClassLoader parent) {
//If not running on JDK, compiler will be null
if (compiler == null) {
throw new Error("Compiler not available. This may happen if "
+ "running on JRE instead of JDK. Please use a full JDK 1.6."
+ "javax.tools.ToolProvider.getSystemJavaCompiler() returned null.");
}
fileManager = new MemoryOutputJavaFileManager(compiler.getStandardFileManager(null, null, null));
loader = new JavaFileManagerClassLoader(fileManager, parent);
// create a classpath for the compiler
StringBuilder b = new StringBuilder();
URL[] cp = parent.getURLs();
for (int i = 0; i < cp.length; i++) {
b.append(File.pathSeparatorChar);
b.append(cp[i].getFile());
}
// set compiler's classpath to be same as the runtime's
compilerOptions.addAll(Arrays.asList("-cp", System.getProperty("java.class.path") + b.toString()));
}
/**
* Compiles a single source file and loads the class with a
* default class loader. The default class loader is the one used
* to load the test case class.
*
* @param name the name of the class to compile.
* @param code the source code of the class.
*
* @return the compiled class.
*/
public synchronized Class compileSource(String name, String code) throws Exception {
Class c = cache.get(name);
if (c == null) {
c = compileSource0(name, code);
cache.put(name, c);
}
return c;
}
public synchronized Class getCompiledClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
try {
return loader.loadClass(name);
} catch (ClassNotFoundException ex) {
return cache.get(name);
}
}
}
/**
* Compiles multiple sources file and loads the classes.
*
* @param sourceFiles the source files to compile.
* @param parentLoader the parent class loader to use when loading classes.
*
* @return a map of compiled classes. This maps class names to
* Class objects.
* @throws Exception
*
*/
private Class compileSource0(String className, String sourceCode) throws Exception {
List compUnits = new ArrayList(1);
compUnits.add(new MemorySourceJavaFileObject(className + ".java", sourceCode));
DiagnosticCollector diag = new DiagnosticCollector();
Boolean result = compiler.getTask(null, fileManager, diag, compilerOptions, null, compUnits).call();
if (result.equals(Boolean.FALSE)) {
throw new RuntimeException(diag.getDiagnostics().toString());
}
try {
String classDotName = className.replace('/', '.');
return Class.forName(classDotName, true, loader);
} catch (ClassNotFoundException e) {
throw e;
}
}
}