diff --git a/src/main/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreter.java b/src/main/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreter.java index 3617572..abadea2 100644 --- a/src/main/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreter.java +++ b/src/main/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreter.java @@ -42,6 +42,8 @@ class GroovyScriptInterpreter implements ScriptInterpreter { private final RootLoader childFirstLoader = new RootLoader(new URL[] {}, Thread.currentThread().getContextClassLoader()); + private String targetBytecode; + @Override public void setClassPath(List classPath) { if (classPath == null || classPath.isEmpty()) { @@ -51,6 +53,11 @@ public void setClassPath(List classPath) { classPath.stream().map(this::toUrl).forEach(childFirstLoader::addURL); } + @Override + public void setTargetBytecode(String version) { + this.targetBytecode = version; + } + private URL toUrl(String path) { try { return new File(path).toURI().toURL(); @@ -59,6 +66,27 @@ private URL toUrl(String path) { } } + /** + * Maps a Maven-style release value (for example "8") to the version string Groovy's + * {@link CompilerConfiguration#setTargetBytecode(String)} expects (for example "1.8"). Groovy uses + * the "1.x" form for JDK 4 through 8, and bare version numbers from JDK 9 onward. + * + * @param version The Maven-style release value, must not be null. + * @return The Groovy-compatible bytecode version string. + */ + static String normalizeTargetBytecode(String version) { + switch (version) { + case "4": + case "5": + case "6": + case "7": + case "8": + return "1." + version; + default: + return version; + } + } + /** * {@inheritDoc} */ @@ -76,10 +104,13 @@ public Object evaluateScript(String script, Map globalVariables, Prin System.setOut(scriptOutput); } - GroovyShell interpreter = new GroovyShell( - childFirstLoader, - new Binding(globalVariables), - new CompilerConfiguration(CompilerConfiguration.DEFAULT)); + CompilerConfiguration compilerConfiguration = new CompilerConfiguration(CompilerConfiguration.DEFAULT); + if (targetBytecode != null) { + compilerConfiguration.setTargetBytecode(normalizeTargetBytecode(targetBytecode)); + } + + GroovyShell interpreter = + new GroovyShell(childFirstLoader, new Binding(globalVariables), compilerConfiguration); Thread.currentThread().setContextClassLoader(childFirstLoader); return interpreter.evaluate(script); diff --git a/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptInterpreter.java b/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptInterpreter.java index 01cc14d..3ddcff8 100644 --- a/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptInterpreter.java +++ b/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptInterpreter.java @@ -41,6 +41,16 @@ public interface ScriptInterpreter extends Closeable { */ void setClassPath(List classPath); + /** + * Sets the target bytecode version for interpreters that support bytecode-level compilation. Interpreters + * that do not compile to a specific bytecode level (for example BeanShell) may ignore this. + * + * @param version The target bytecode version, may be null to use the interpreter's own default. + */ + default void setTargetBytecode(String version) { + // no-op by default + } + /** * Evaluates the specified script. * diff --git a/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java b/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java index a1ed3e8..2ef2f8e 100644 --- a/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java +++ b/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java @@ -104,6 +104,18 @@ public void setClassPath(List classPath) { } } + /** + * Sets the target bytecode version for the hook scripts, for interpreters that support bytecode-level + * compilation. + * + * @param version The target bytecode version, may be null to use each interpreter's own default. + */ + public void setTargetBytecode(String version) { + if (version != null) { + scriptInterpreters.values().forEach(scriptInterpreter -> scriptInterpreter.setTargetBytecode(version)); + } + } + /** * Sets the file encoding of the hook scripts. * diff --git a/src/test/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreterTest.java b/src/test/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreterTest.java index 3bee0fa..fa78fdb 100644 --- a/src/test/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreterTest.java +++ b/src/test/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreterTest.java @@ -96,4 +96,24 @@ void evaluateScriptVars() throws Exception { } assertEquals("data", out.toString()); } + + @Test + void evaluateScriptWithTargetBytecode() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try (ScriptInterpreter interpreter = new GroovyScriptInterpreter()) { + interpreter.setTargetBytecode("8"); + assertEquals( + Boolean.TRUE, + interpreter.evaluateScript("print \"Test\"\nreturn true", null, new PrintStream(out))); + } + assertEquals("Test", out.toString()); + } + + @Test + void normalizeTargetBytecodeMapsOldJdksToDotForm() { + assertEquals("1.4", GroovyScriptInterpreter.normalizeTargetBytecode("4")); + assertEquals("1.8", GroovyScriptInterpreter.normalizeTargetBytecode("8")); + assertEquals("9", GroovyScriptInterpreter.normalizeTargetBytecode("9")); + assertEquals("17", GroovyScriptInterpreter.normalizeTargetBytecode("17")); + } }