diff --git a/org/codehaus/gmavenplus/SomeClass.class b/org/codehaus/gmavenplus/SomeClass.class new file mode 100644 index 000000000..abf3d10d5 Binary files /dev/null and b/org/codehaus/gmavenplus/SomeClass.class differ diff --git a/src/it/forkMode/invoker.properties b/src/it/forkMode/invoker.properties new file mode 100644 index 000000000..d3182cae9 --- /dev/null +++ b/src/it/forkMode/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=clean test -e -ntp -Dmaven.plugin.validation=verbose +#invoker.debug = true diff --git a/src/it/forkMode/pom.xml b/src/it/forkMode/pom.xml new file mode 100644 index 000000000..3ef779d03 --- /dev/null +++ b/src/it/forkMode/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + + org.codehaus.gmavenplus + gmavenplus-plugin-it-root + testing + ../pom.xml + + + gmavenplus-plugin-it-forkCompile + testing + GMavenPlus Plugin Fork Compile Test + The simplest compile with fork. + + + + + junit + junit + + + @groovyGroupId@ + groovy + + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + + true + true + + + + + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + diff --git a/src/it/forkMode/src/main/groovy/org/codehaus/gmavenplus/SomeClass.groovy b/src/it/forkMode/src/main/groovy/org/codehaus/gmavenplus/SomeClass.groovy new file mode 100644 index 000000000..6cc5dc909 --- /dev/null +++ b/src/it/forkMode/src/main/groovy/org/codehaus/gmavenplus/SomeClass.groovy @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.codehaus.gmavenplus + + +class SomeClass { + + void someMethod(String param1, String param2) {} + +} diff --git a/src/it/forkMode/src/test/java/org/codehaus/gmavenplus/SomeClassTest.java b/src/it/forkMode/src/test/java/org/codehaus/gmavenplus/SomeClassTest.java new file mode 100644 index 000000000..291397e33 --- /dev/null +++ b/src/it/forkMode/src/test/java/org/codehaus/gmavenplus/SomeClassTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.codehaus.gmavenplus; + +import groovy.lang.GroovySystem; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Arrays; +import java.util.List; + + +public class SomeClassTest { + + @Test + public void testSomeMethod() throws NoSuchMethodException { + Method method = SomeClass.class.getDeclaredMethod("someMethod", String.class, String.class); + List parameterNames = Arrays.asList(method.getParameters()); + + Assert.assertEquals(2, parameterNames.size()); + + if (GroovySystem.getVersion().startsWith("1.5") + || GroovySystem.getVersion().startsWith("1.6") + || GroovySystem.getVersion().startsWith("1.7") + || GroovySystem.getVersion().startsWith("1.8") + || GroovySystem.getVersion().startsWith("1.9") + || GroovySystem.getVersion().startsWith("2.0") + || GroovySystem.getVersion().startsWith("2.1") + || GroovySystem.getVersion().startsWith("2.2") + || GroovySystem.getVersion().startsWith("2.3") + || GroovySystem.getVersion().startsWith("2.4")) { + Assert.assertEquals("arg0", parameterNames.get(0).getName()); + Assert.assertEquals("arg1", parameterNames.get(1).getName()); + } else { + Assert.assertEquals("param1", parameterNames.get(0).getName()); + Assert.assertEquals("param2", parameterNames.get(1).getName()); + } + } + +} diff --git a/src/main/java/org/codehaus/gmavenplus/mojo/AbstractCompileMojo.java b/src/main/java/org/codehaus/gmavenplus/mojo/AbstractCompileMojo.java index 12f6f3df8..77e04280d 100644 --- a/src/main/java/org/codehaus/gmavenplus/mojo/AbstractCompileMojo.java +++ b/src/main/java/org/codehaus/gmavenplus/mojo/AbstractCompileMojo.java @@ -16,11 +16,16 @@ package org.codehaus.gmavenplus.mojo; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Locale; import java.util.NoSuchElementException; import java.util.Optional; +import java.util.stream.Collectors; +import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Parameter; import org.codehaus.gmavenplus.model.IncludeClasspath; import org.codehaus.gmavenplus.model.internal.Version; @@ -34,7 +39,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.codehaus.gmavenplus.mojo.GroovycLogger.LogTarget; +import static java.util.stream.Collectors.joining; import static org.codehaus.gmavenplus.util.ReflectionUtils.findConstructor; import static org.codehaus.gmavenplus.util.ReflectionUtils.findMethod; import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeConstructor; @@ -340,7 +347,7 @@ public abstract class AbstractCompileMojo extends AbstractGroovySourcesMojo { */ @SuppressWarnings({"rawtypes"}) protected synchronized void doCompile(final Set sources, final List classpath, final File compileOutputDirectory) - throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, MalformedURLException { + throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, MalformedURLException, MojoExecutionException { if (sources == null || sources.isEmpty()) { getLog().info("No sources specified for compilation. Skipping."); return; @@ -354,11 +361,109 @@ protected synchronized void doCompile(final Set sources, final List classp doCompileLibrary(sources, classpath, compileOutputDirectory); } - private void doCompileProcess(Set sources, List classpath, File compileOutputDirectory) { + private void doCompileProcess(Set sources, List classpath, File compileOutputDirectory) + throws MojoExecutionException { Path groovyc = getGroovyc(); - // TODO: implement - throw new UnsupportedOperationException( - "not yet implemented: [org.codehaus.gmavenplus.mojo.AbstractCompileMojo::doCompileProcess]."); + + List args = new ArrayList<>(); + args.add(groovyc.toAbsolutePath().toString()); + final String delimitedCp = getClassPathString(classpath); + args.add("--classpath="+delimitedCp); + + if (this.sourceEncoding != null && !this.sourceEncoding.trim().isEmpty()) { + args.add("--encoding=" + this.sourceEncoding); + } + + if (this.parameters) { + args.add("--parameters"); + } + + if (this.previewFeatures) { + args.add("--enable-preview"); + } + + if (this.targetBytecode != null) { + args.add("-Jtarget=" + this.targetBytecode); + } + + // missing: + // this.debug + // this.includeClasspath + // this.configScript (available as --configscript=) + // this.parallelParsing + // this.invokeDynamic + // this.tolerance + // this.warningLevel + // this.verbose + // this.skipBytecodeCheck + // as well as: + // --compile-static + // --type-checked + // --temp= + + + final String compileMessage = String.format( + Locale.ROOT, + "Compiling %d source files with groovyc %s to %s", + sources.size(), + args.stream().skip(2).collect(Collectors.toList()), + project.getBasedir().toPath().relativize(compileOutputDirectory.toPath())); + getLog().info(compileMessage); + args.addAll(sources.stream().map(File::getAbsolutePath).collect(Collectors.toList())); + + final ProcessBuilder processBuilder = new ProcessBuilder() + .directory(compileOutputDirectory) + .command(args) + .inheritIO() + ; + + getLog().debug("Running groovyc via: " + args); + + try { + final Path compileOutputDirectoryPath = compileOutputDirectory.toPath(); + if (!Files.exists(compileOutputDirectoryPath)) { + Files.createDirectories(compileOutputDirectoryPath); + } + if (!Files.isDirectory(compileOutputDirectoryPath)) { + throw new MojoExecutionException( + "Target directory [" + compileOutputDirectoryPath + "] is not a directory."); + } + final Process groovycProcess = processBuilder.start(); + + final GroovycLogger outputLogger = new GroovycLogger(groovycProcess.getInputStream(), + getLog(), LogTarget.INFO); + final GroovycLogger errorLogger = new GroovycLogger(groovycProcess.getErrorStream(), + getLog(), LogTarget.ERROR); + final Thread outputLoggerThread = new Thread(outputLogger); + outputLoggerThread.start(); + final Thread errorLoggerThread = new Thread(errorLogger); + errorLoggerThread.start(); + + final int groovycRc = groovycProcess.waitFor(); + outputLoggerThread.join(); + errorLoggerThread.join(); + + if (groovycRc != 0) { + throw new MojoExecutionException("Groovy exited with RC=" + groovycRc); + } + } catch (final IOException ioException) { + throw new MojoExecutionException("Error compiling", ioException); + } catch (InterruptedException interruptedException) { + Thread.currentThread().interrupt(); + throw new MojoExecutionException("Compilation interrupted", interruptedException); + } + } + + private static String getClassPathString(List classpath) { + for (Object cp : classpath) { + if (!(cp instanceof String)) { + throw new IllegalArgumentException("Classpath element [" + cp + "] is not a string!"); + } + } + + return classpath.stream() + .map(obj -> (String) obj) + .collect(joining(File.pathSeparator)); } private Path getGroovyc() { diff --git a/src/main/java/org/codehaus/gmavenplus/mojo/GroovycLogger.java b/src/main/java/org/codehaus/gmavenplus/mojo/GroovycLogger.java new file mode 100644 index 000000000..4791ee7b3 --- /dev/null +++ b/src/main/java/org/codehaus/gmavenplus/mojo/GroovycLogger.java @@ -0,0 +1,43 @@ +package org.codehaus.gmavenplus.mojo; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import org.apache.maven.plugin.logging.Log; + +public class GroovycLogger implements Runnable { + + private final InputStream inputStream; + private final Log log; + private final LogTarget level; + + public GroovycLogger(InputStream inputStream, Log log, LogTarget level) { + this.inputStream = inputStream; + this.log = log; + this.level = level; + } + + @Override + public void run() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(this.inputStream))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + if (this.level == LogTarget.ERROR) { + this.log.error(line); + + } else { + this.log.info(line); + } + } + } catch (IOException ioException) { + this.log.error(ioException); + } + } + + public enum LogTarget { + INFO, + ERROR; + } +}