diff --git a/.travis.yml b/.travis.yml index df6bcdc..2da370c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,8 @@ language: java jdk: - oraclejdk8 + +script: "mvn cobertura:cobertura" + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/README.md b/README.md index 161b9c7..076619e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ **Update 09/22/2017**: I've been silent for long time (I'm into Golang lately hence putting Java aside) despite the fact that there are lots of interests to make this mini tool better. I'll kick off my effort to improve this tool from now on by reviewing outstanding issues and PRs -# InMemoryJavaCompiler [![Build Status](https://travis-ci.org/trung/InMemoryJavaCompiler.svg?branch=master)](https://travis-ci.org/trung/InMemoryJavaCompiler) +# InMemoryJavaCompiler [![Build Status](https://travis-ci.org/trung/InMemoryJavaCompiler.svg?branch=master)](https://travis-ci.org/trung/InMemoryJavaCompiler) [![codecov](https://codecov.io/gh/trung/InMemoryJavaCompiler/branch/master/graph/badge.svg)](https://codecov.io/gh/trung/InMemoryJavaCompiler) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.amrom.workers.dev%2Ftrung%2FInMemoryJavaCompiler.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.amrom.workers.dev%2Ftrung%2FInMemoryJavaCompiler?ref=badge_shield) + Samples with utility classes to compile java source code in memory After taking huge effort to look for example on the internet and found nothing work. I decided to create a very simple version. @@ -9,7 +10,7 @@ After taking huge effort to look for example on the internet and found nothing w E.g.: - StringBuffer sourceCode = new StringBuffer(); + StringBuilder sourceCode = new StringBuilder(); sourceCode.append("package org.mdkt;\n"); sourceCode.append("public class HelloClass {\n"); sourceCode.append(" public String hello() { return \"hello\"; }"); @@ -17,6 +18,8 @@ E.g.: Class helloClass = InMemoryJavaCompiler.newInstance().compile("org.mdkt.HelloClass", sourceCode.toString()); +If you are looking for more examples, please look at unit tests in the `src/test/java` folder + Artifact is pushed to Sonatype OSS Releases Repository https://oss.sonatype.org/content/repositories/releases/ @@ -26,5 +29,9 @@ Maven dependency: org.mdkt.compiler InMemoryJavaCompiler - 1.2 + 1.3.0 + + +## License +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.amrom.workers.dev%2Ftrung%2FInMemoryJavaCompiler.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.amrom.workers.dev%2Ftrung%2FInMemoryJavaCompiler?ref=badge_large) diff --git a/pom.xml b/pom.xml index 4011db2..8c34d98 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.mdkt.compiler InMemoryJavaCompiler - 1.3.0-SNAPSHOT + 1.4.0-SNAPSHOT jar https://github.com/trung/InMemoryJavaCompiler @@ -18,6 +18,10 @@ 1.6.3 2.5.1 gpg2 + + + 1.7.5 + 4.12 @@ -38,7 +42,7 @@ scm:git:git://github.com/trung/InMemoryJavaCompiler scm:git:git@github.com:trung/InMemoryJavaCompiler.git HEAD - + @@ -61,16 +65,39 @@ + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-jdk14 + ${slf4j.version} + test + junit junit - 4.12 + ${junit.version} test + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + html + xml + + + + org.apache.maven.plugins maven-compiler-plugin @@ -128,6 +155,9 @@ jar + + -Xdoclint:none + diff --git a/src/main/java/org/mdkt/compiler/CompilationException.java b/src/main/java/org/mdkt/compiler/CompilationException.java index a9825f8..00c7f7f 100644 --- a/src/main/java/org/mdkt/compiler/CompilationException.java +++ b/src/main/java/org/mdkt/compiler/CompilationException.java @@ -1,25 +1,10 @@ package org.mdkt.compiler; -import java.util.List; -import java.util.Locale; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; - public class CompilationException extends RuntimeException { private static final long serialVersionUID = 5272588827551900536L; - public CompilationException(List> diags) { - super(buildMessage(diags)); + public CompilationException(String msg) { + super(msg); } - private static String buildMessage(List> diags) { - StringBuffer msg = new StringBuffer(); - msg.append("Unable to compile the source."); - for (Diagnostic diag : diags) { - msg.append("\n").append("[kind=").append(diag.getKind()); - msg.append(", ").append("line=").append(diag.getLineNumber()); - msg.append(", ").append("message=").append(diag.getMessage(Locale.US)).append("]"); - } - return msg.toString(); - } } diff --git a/src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java b/src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java index 19f0391..b853590 100644 --- a/src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java +++ b/src/main/java/org/mdkt/compiler/InMemoryJavaCompiler.java @@ -32,27 +32,28 @@ public InMemoryJavaCompiler useParentClassLoader(ClassLoader parent) { /** * @return the class loader used internally by the compiler */ - public ClassLoader getClassloader() - { + public ClassLoader getClassloader() { return classLoader; } /** * Options used by the compiler, e.g. '-Xlint:unchecked'. + * * @param options * @return */ - public InMemoryJavaCompiler useOptions(String... options) - { + public InMemoryJavaCompiler useOptions(String... options) { this.options = Arrays.asList(options); return this; } /** - * Ignore non-critical compiler output, like unchecked/unsafe operation warnings. + * Ignore non-critical compiler output, like unchecked/unsafe operation + * warnings. + * * @return */ - public InMemoryJavaCompiler useIgnoreWarnings() { + public InMemoryJavaCompiler ignoreWarnings() { ignoreWarnings = true; return this; } @@ -65,7 +66,7 @@ public InMemoryJavaCompiler useIgnoreWarnings() { */ public Map> compileAll() throws Exception { if (sourceCodes.size() == 0) { - throw new Exception("No source code to compile"); + throw new CompilationException("No source code to compile"); } Collection compilationUnits = sourceCodes.values(); CompiledCode[] code; @@ -80,15 +81,30 @@ public Map> compileAll() throws Exception { JavaCompiler.CompilationTask task = javac.getTask(null, fileManager, collector, options, null, compilationUnits); boolean result = task.call(); if (!result || collector.getDiagnostics().size() > 0) { - for (Diagnostic 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()); - } + StringBuffer exceptionMsg = new StringBuffer(); + exceptionMsg.append("Unable to compile the source"); + boolean hasWarnings = false; + boolean hasErrors = false; + for (Diagnostic 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>(); diff --git a/src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java b/src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java index 1c58c63..c3c16e8 100644 --- a/src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java +++ b/src/test/java/org/mdkt/compiler/InMemoryJavaCompilerTest.java @@ -7,8 +7,12 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class InMemoryJavaCompilerTest { + private static final Logger logger = LoggerFactory.getLogger(InMemoryJavaCompilerTest.class); + @Rule public ExpectedException thrown = ExpectedException.none(); @@ -69,7 +73,8 @@ public void compile_whenError() throws Exception { InMemoryJavaCompiler.newInstance().compile("org.mdkt.HelloClass", sourceCode.toString()); } - @Test public void compile_FailOnWarnings() throws Exception{ + @Test + public void compile_WhenFailOnWarnings() throws Exception { thrown.expect(CompilationException.class); StringBuffer sourceCode = new StringBuffer(); @@ -80,15 +85,33 @@ public void compile_whenError() throws Exception { InMemoryJavaCompiler.newInstance().compile("org.mdkt.HelloClass", sourceCode.toString()); } - @Test public void compile_CompileAndIgnoreWarnings() throws Exception{ + @Test + public void compile_WhenIgnoreWarnings() throws Exception { StringBuffer sourceCode = new StringBuffer(); sourceCode.append("package org.mdkt;\n"); sourceCode.append("public class HelloClass {\n"); sourceCode.append(" public java.util.List hello() { return new java.util.ArrayList(); }"); sourceCode.append("}"); - Class helloClass = InMemoryJavaCompiler.newInstance().useIgnoreWarnings().compile("org.mdkt.HelloClass", sourceCode.toString()); - List res = (List) helloClass.getMethod("hello").invoke(helloClass.newInstance()); + Class helloClass = InMemoryJavaCompiler.newInstance().ignoreWarnings().compile("org.mdkt.HelloClass", sourceCode.toString()); + List res = (List) helloClass.getMethod("hello").invoke(helloClass.newInstance()); Assert.assertEquals(0, res.size()); } + + @Test + public void compile_WhenWarningsAndErrors() throws Exception { + thrown.expect(CompilationException.class); + StringBuffer sourceCode = new StringBuffer(); + + sourceCode.append("package org.mdkt;\n"); + sourceCode.append("public class HelloClass extends xxx {\n"); + sourceCode.append(" public java.util.List hello() { return new java.util.ArrayList(); }"); + sourceCode.append("}"); + try { + InMemoryJavaCompiler.newInstance().compile("org.mdkt.HelloClass", sourceCode.toString()); + } catch (Exception e) { + logger.info("Exception caught: {}", e); + throw e; + } + } }