forked from trung/InMemoryJavaCompiler
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInMemoryJavaCompiler.java
More file actions
126 lines (110 loc) · 3.45 KB
/
InMemoryJavaCompiler.java
File metadata and controls
126 lines (110 loc) · 3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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<String> options;
boolean ignoreWarnings = false;
private Map<String, SourceCode> sourceCodes = new HashMap<String, SourceCode>();
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 useIgnoreWarnings() {
ignoreWarnings = true;
return this;
}
/**
* Compile all sources
*
* @return Map containing instances of all compiled classes
* @throws Exception
*/
public Map<String, Class<?>> compileAll() throws Exception {
if (sourceCodes.size() == 0) {
throw new Exception("No source code to compile");
}
Collection<SourceCode> compilationUnits = sourceCodes.values();
CompiledCode[] code;
code = new CompiledCode[compilationUnits.size()];
Iterator<SourceCode> iter = compilationUnits.iterator();
for (int i = 0; i < code.length; i++) {
code[i] = new CompiledCode(iter.next().getClassName());
}
DiagnosticCollector<JavaFileObject> 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) {
for (Diagnostic<? extends JavaFileObject> d : collector.getDiagnostics()) {
if (ignoreWarnings &&
(d.getKind() == Diagnostic.Kind.NOTE || d.getKind() == Diagnostic.Kind.MANDATORY_WARNING || d.getKind() == Diagnostic.Kind.WARNING))
continue;
else {
throw new CompilationException(collector.getDiagnostics());
}
}
}
Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
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;
}
}