Skip to content

Commit 39b32c1

Browse files
committed
Merge branch 'turpid-monkey-master'
2 parents a6bfc19 + fe47f01 commit 39b32c1

4 files changed

Lines changed: 128 additions & 33 deletions

File tree

pom.xml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818
<nexus-staging-maven-plugin.version>1.6.3</nexus-staging-maven-plugin.version>
1919
<maven-release-plugin.version>2.5.1</maven-release-plugin.version>
2020
<gpg.executable>gpg2</gpg.executable>
21+
22+
<!-- dependencies -->
23+
<slf4j.version>1.7.5</slf4j.version>
24+
<junit.version>4.12</junit.version>
2125
</properties>
22-
26+
2327
<licenses>
2428
<license>
2529
<name>Apache License, Version 2.0</name>
@@ -38,7 +42,7 @@
3842
<connection>scm:git:git://github.com/trung/InMemoryJavaCompiler</connection>
3943
<developerConnection>scm:git:git@github.com:trung/InMemoryJavaCompiler.git</developerConnection>
4044
<tag>HEAD</tag>
41-
</scm>
45+
</scm>
4246

4347
<distributionManagement>
4448
<snapshotRepository>
@@ -61,10 +65,21 @@
6165
</developers>
6266

6367
<dependencies>
68+
<dependency>
69+
<groupId>org.slf4j</groupId>
70+
<artifactId>slf4j-api</artifactId>
71+
<version>${slf4j.version}</version>
72+
</dependency>
73+
<dependency>
74+
<groupId>org.slf4j</groupId>
75+
<artifactId>slf4j-jdk14</artifactId>
76+
<version>${slf4j.version}</version>
77+
<scope>test</scope>
78+
</dependency>
6479
<dependency>
6580
<groupId>junit</groupId>
6681
<artifactId>junit</artifactId>
67-
<version>4.12</version>
82+
<version>${junit.version}</version>
6883
<scope>test</scope>
6984
</dependency>
7085
</dependencies>
Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,10 @@
11
package org.mdkt.compiler;
22

3-
import java.util.List;
4-
import java.util.Locale;
5-
import javax.tools.Diagnostic;
6-
import javax.tools.JavaFileObject;
7-
83
public class CompilationException extends RuntimeException {
94
private static final long serialVersionUID = 5272588827551900536L;
105

11-
public CompilationException(List<Diagnostic<? extends JavaFileObject>> diags) {
12-
super(buildMessage(diags));
6+
public CompilationException(String msg) {
7+
super(msg);
138
}
149

15-
private static String buildMessage(List<Diagnostic<? extends JavaFileObject>> diags) {
16-
StringBuffer msg = new StringBuffer();
17-
msg.append("Unable to compile the source.");
18-
for (Diagnostic<?> diag : diags) {
19-
msg.append("\n").append("[kind=").append(diag.getKind());
20-
msg.append(", ").append("line=").append(diag.getLineNumber());
21-
msg.append(", ").append("message=").append(diag.getMessage(Locale.US)).append("]");
22-
}
23-
return msg.toString();
24-
}
2510
}

src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
package org.mdkt.compiler;
22

3-
import java.util.Collection;
4-
import java.util.HashMap;
5-
import java.util.Iterator;
6-
import java.util.Map;
3+
import java.util.*;
74

8-
import javax.tools.DiagnosticCollector;
9-
import javax.tools.JavaCompiler;
10-
import javax.tools.JavaFileObject;
11-
import javax.tools.ToolProvider;
5+
import javax.tools.*;
126

137
/**
14-
* Complile Java sources in-memory
8+
* Compile Java sources in-memory
159
*/
1610
public class InMemoryJavaCompiler {
1711
private JavaCompiler javac;
1812
private DynamicClassLoader classLoader;
13+
private Iterable<String> options;
14+
boolean ignoreWarnings = false;
1915

2016
private Map<String, SourceCode> sourceCodes = new HashMap<String, SourceCode>();
2117

@@ -34,14 +30,43 @@ public InMemoryJavaCompiler useParentClassLoader(ClassLoader parent) {
3430
}
3531

3632
/**
37-
* Compile all sources
33+
* @return the class loader used internally by the compiler
34+
*/
35+
public ClassLoader getClassloader() {
36+
return classLoader;
37+
}
38+
39+
/**
40+
* Options used by the compiler, e.g. '-Xlint:unchecked'.
3841
*
42+
* @param options
3943
* @return
44+
*/
45+
public InMemoryJavaCompiler useOptions(String... options) {
46+
this.options = Arrays.asList(options);
47+
return this;
48+
}
49+
50+
/**
51+
* Ignore non-critical compiler output, like unchecked/unsafe operation
52+
* warnings.
53+
*
54+
* @return
55+
*/
56+
public InMemoryJavaCompiler ignoreWarnings() {
57+
ignoreWarnings = true;
58+
return this;
59+
}
60+
61+
/**
62+
* Compile all sources
63+
*
64+
* @return Map containing instances of all compiled classes
4065
* @throws Exception
4166
*/
4267
public Map<String, Class<?>> compileAll() throws Exception {
4368
if (sourceCodes.size() == 0) {
44-
throw new Exception("No source code to compile");
69+
throw new CompilationException("No source code to compile");
4570
}
4671
Collection<SourceCode> compilationUnits = sourceCodes.values();
4772
CompiledCode[] code;
@@ -53,10 +78,33 @@ public Map<String, Class<?>> compileAll() throws Exception {
5378
}
5479
DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>();
5580
ExtendedStandardJavaFileManager fileManager = new ExtendedStandardJavaFileManager(javac.getStandardFileManager(null, null, null), classLoader);
56-
JavaCompiler.CompilationTask task = javac.getTask(null, fileManager, collector, null, null, compilationUnits);
81+
JavaCompiler.CompilationTask task = javac.getTask(null, fileManager, collector, options, null, compilationUnits);
5782
boolean result = task.call();
5883
if (!result || collector.getDiagnostics().size() > 0) {
59-
throw new CompilationException(collector.getDiagnostics());
84+
StringBuffer exceptionMsg = new StringBuffer();
85+
exceptionMsg.append("Unable to compile the source");
86+
boolean hasWarnings = false;
87+
boolean hasErrors = false;
88+
for (Diagnostic<? extends JavaFileObject> d : collector.getDiagnostics()) {
89+
switch (d.getKind()) {
90+
case NOTE:
91+
case MANDATORY_WARNING:
92+
case WARNING:
93+
hasWarnings = true;
94+
break;
95+
case OTHER:
96+
case ERROR:
97+
default:
98+
hasErrors = true;
99+
break;
100+
}
101+
exceptionMsg.append("\n").append("[kind=").append(d.getKind());
102+
exceptionMsg.append(", ").append("line=").append(d.getLineNumber());
103+
exceptionMsg.append(", ").append("message=").append(d.getMessage(Locale.US)).append("]");
104+
}
105+
if (hasWarnings && !ignoreWarnings || hasErrors) {
106+
throw new CompilationException(exceptionMsg.toString());
107+
}
60108
}
61109

62110
Map<String, Class<?>> classes = new HashMap<String, Class<?>>();

src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package org.mdkt.compiler;
22

3+
import java.util.List;
34
import java.util.Map;
45

56
import org.junit.Assert;
67
import org.junit.Rule;
78
import org.junit.Test;
89
import org.junit.rules.ExpectedException;
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
912

1013
public class InMemoryJavaCompilerTest {
14+
private static final Logger logger = LoggerFactory.getLogger(InMemoryJavaCompilerTest.class);
15+
1116
@Rule
1217
public ExpectedException thrown = ExpectedException.none();
1318

@@ -67,4 +72,46 @@ public void compile_whenError() throws Exception {
6772
sourceCode.append("}");
6873
InMemoryJavaCompiler.newInstance().compile("org.mdkt.HelloClass", sourceCode.toString());
6974
}
75+
76+
@Test
77+
public void compile_WhenFailOnWarnings() throws Exception {
78+
thrown.expect(CompilationException.class);
79+
StringBuffer sourceCode = new StringBuffer();
80+
81+
sourceCode.append("package org.mdkt;\n");
82+
sourceCode.append("public class HelloClass {\n");
83+
sourceCode.append(" public java.util.List<String> hello() { return new java.util.ArrayList(); }");
84+
sourceCode.append("}");
85+
InMemoryJavaCompiler.newInstance().compile("org.mdkt.HelloClass", sourceCode.toString());
86+
}
87+
88+
@Test
89+
public void compile_WhenIgnoreWarnings() throws Exception {
90+
StringBuffer sourceCode = new StringBuffer();
91+
92+
sourceCode.append("package org.mdkt;\n");
93+
sourceCode.append("public class HelloClass {\n");
94+
sourceCode.append(" public java.util.List<String> hello() { return new java.util.ArrayList(); }");
95+
sourceCode.append("}");
96+
Class<?> helloClass = InMemoryJavaCompiler.newInstance().ignoreWarnings().compile("org.mdkt.HelloClass", sourceCode.toString());
97+
List<?> res = (List<?>) helloClass.getMethod("hello").invoke(helloClass.newInstance());
98+
Assert.assertEquals(0, res.size());
99+
}
100+
101+
@Test
102+
public void compile_WhenWarningsAndErrors() throws Exception {
103+
thrown.expect(CompilationException.class);
104+
StringBuffer sourceCode = new StringBuffer();
105+
106+
sourceCode.append("package org.mdkt;\n");
107+
sourceCode.append("public class HelloClass extends xxx {\n");
108+
sourceCode.append(" public java.util.List<String> hello() { return new java.util.ArrayList(); }");
109+
sourceCode.append("}");
110+
try {
111+
InMemoryJavaCompiler.newInstance().compile("org.mdkt.HelloClass", sourceCode.toString());
112+
} catch (Exception e) {
113+
logger.info("Exception caught: {}", e);
114+
throw e;
115+
}
116+
}
70117
}

0 commit comments

Comments
 (0)