
org.mdkt.compiler.InMemoryJavaCompiler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of InMemoryJavaCompiler Show documentation
Show all versions of InMemoryJavaCompiler Show documentation
Small utility to compile java code in memory
The newest version!
package org.mdkt.compiler;
import java.util.*;
import javax.tools.*;
/**
* Compile Java sources in-memory
*/
public class InMemoryJavaCompiler {
private JavaCompiler javac;
private DynamicClassLoader classLoader;
private Iterable options;
boolean ignoreWarnings = false;
private Map sourceCodes = new HashMap();
public static InMemoryJavaCompiler newInstance() {
return new InMemoryJavaCompiler();
}
private InMemoryJavaCompiler() {
this.javac = ToolProvider.getSystemJavaCompiler();
this.classLoader = new DynamicClassLoader(ClassLoader.getSystemClassLoader());
}
public InMemoryJavaCompiler useParentClassLoader(ClassLoader parent) {
this.classLoader = new DynamicClassLoader(parent);
return this;
}
/**
* @return the class loader used internally by the compiler
*/
public ClassLoader getClassloader() {
return classLoader;
}
/**
* Options used by the compiler, e.g. '-Xlint:unchecked'.
*
* @param options
* @return
*/
public InMemoryJavaCompiler useOptions(String... options) {
this.options = Arrays.asList(options);
return this;
}
/**
* Ignore non-critical compiler output, like unchecked/unsafe operation
* warnings.
*
* @return
*/
public InMemoryJavaCompiler ignoreWarnings() {
ignoreWarnings = true;
return this;
}
/**
* Compile all sources
*
* @return Map containing instances of all compiled classes
* @throws Exception
*/
public Map> compileAll() throws Exception {
if (sourceCodes.size() == 0) {
throw new CompilationException("No source code to compile");
}
Collection compilationUnits = sourceCodes.values();
CompiledCode[] code;
code = new CompiledCode[compilationUnits.size()];
Iterator iter = compilationUnits.iterator();
for (int i = 0; i < code.length; i++) {
code[i] = new CompiledCode(iter.next().getClassName());
}
DiagnosticCollector collector = new DiagnosticCollector<>();
ExtendedStandardJavaFileManager fileManager = new ExtendedStandardJavaFileManager(javac.getStandardFileManager(null, null, null), classLoader);
JavaCompiler.CompilationTask task = javac.getTask(null, fileManager, collector, options, null, compilationUnits);
boolean result = task.call();
if (!result || collector.getDiagnostics().size() > 0) {
StringBuffer exceptionMsg = new StringBuffer();
exceptionMsg.append("Unable to compile the source");
boolean hasWarnings = false;
boolean hasErrors = false;
for (Diagnostic extends JavaFileObject> d : collector.getDiagnostics()) {
switch (d.getKind()) {
case NOTE:
case MANDATORY_WARNING:
case WARNING:
hasWarnings = true;
break;
case OTHER:
case ERROR:
default:
hasErrors = true;
break;
}
exceptionMsg.append("\n").append("[kind=").append(d.getKind());
exceptionMsg.append(", ").append("line=").append(d.getLineNumber());
exceptionMsg.append(", ").append("message=").append(d.getMessage(Locale.US)).append("]");
}
if (hasWarnings && !ignoreWarnings || hasErrors) {
throw new CompilationException(exceptionMsg.toString());
}
}
Map> classes = new HashMap>();
for (String className : sourceCodes.keySet()) {
classes.put(className, classLoader.loadClass(className));
}
return classes;
}
/**
* Compile single source
*
* @param className
* @param sourceCode
* @return
* @throws Exception
*/
public Class> compile(String className, String sourceCode) throws Exception {
return addSource(className, sourceCode).compileAll().get(className);
}
/**
* Add source code to the compiler
*
* @param className
* @param sourceCode
* @return
* @throws Exception
* @see {@link #compileAll()}
*/
public InMemoryJavaCompiler addSource(String className, String sourceCode) throws Exception {
sourceCodes.put(className, new SourceCode(className, sourceCode));
return this;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy