View Javadoc
1   /*
2    * Copyright (C) 2011 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.codehaus.gmavenplus.mojo;
18  
19  import org.apache.maven.plugins.annotations.Parameter;
20  import org.codehaus.gmavenplus.model.IncludeClasspath;
21  import org.codehaus.gmavenplus.model.internal.Version;
22  
23  import java.io.File;
24  import java.lang.reflect.InvocationTargetException;
25  import java.lang.reflect.Method;
26  import java.net.MalformedURLException;
27  import java.security.CodeSource;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Set;
32  
33  import static org.codehaus.gmavenplus.util.ReflectionUtils.findConstructor;
34  import static org.codehaus.gmavenplus.util.ReflectionUtils.findMethod;
35  import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeConstructor;
36  import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeMethod;
37  
38  
39  /**
40   * The base compile mojo, which all compile mojos extend.
41   *
42   * @author Keegan Witt
43   * @since 1.0-beta-1
44   */
45  public abstract class AbstractCompileMojo extends AbstractGroovySourcesMojo {
46  
47      /**
48       * Groovy 5.0.0-alpha-13 version.
49       */
50      protected static final Version GROOVY_5_0_0_ALPHA13 = new Version(5, 0, 0, "alpha-13");
51  
52      /**
53       * Groovy 5.0.0-alpha-11 version.
54       */
55      protected static final Version GROOVY_5_0_0_ALPHA11 = new Version(5, 0, 0, "alpha-11");
56  
57      /**
58       * Groovy 5.0.0-alpha-8 version.
59       */
60      protected static final Version GROOVY_5_0_0_ALPHA8 = new Version(5, 0, 0, "alpha-8");
61  
62      /**
63       * Groovy 5.0.0-alpha-3 version.
64       */
65      protected static final Version GROOVY_5_0_0_ALPHA3 = new Version(5, 0, 0, "alpha-3");
66  
67      /**
68       * Groovy 5.0.0-alpha-1 version.
69       */
70      protected static final Version GROOVY_5_0_0_ALPHA1 = new Version(5, 0, 0, "alpha-1");
71  
72      /**
73       * Groovy 4.0.27 version.
74       */
75      protected static final Version GROOVY_4_0_27 = new Version(4, 0, 27);
76  
77      /**
78       * Groovy 4.0.24 version.
79       */
80      protected static final Version GROOVY_4_0_24 = new Version(4, 0, 24);
81  
82      /**
83       * Groovy 4.0.21 version.
84       */
85      protected static final Version GROOVY_4_0_21 = new Version(4, 0, 21);
86  
87      /**
88       * Groovy 4.0.11 version.
89       */
90      protected static final Version GROOVY_4_0_16 = new Version(4, 0, 16);
91  
92      /**
93       * Groovy 4.0.11 version.
94       */
95      protected static final Version GROOVY_4_0_11 = new Version(4, 0, 11);
96  
97      /**
98       * Groovy 4.0.6 version.
99       */
100     protected static final Version GROOVY_4_0_6 = new Version(4, 0, 6);
101 
102     /**
103      * Groovy 4.0.2 version.
104      */
105     protected static final Version GROOVY_4_0_2 = new Version(4, 0, 2);
106 
107     /**
108      * Groovy 4.0.0 beta-1 version.
109      */
110     protected static final Version GROOVY_4_0_0_BETA1 = new Version(4, 0, 0, "beta-1");
111 
112     /**
113      * Groovy 4.0.0 alpha-3 version.
114      */
115     protected static final Version GROOVY_4_0_0_ALPHA3 = new Version(4, 0, 0, "alpha-3");
116 
117     /**
118      * Groovy 4.0.0 alpha-1 version.
119      */
120     protected static final Version GROOVY_4_0_0_ALPHA1 = new Version(4, 0, 0, "alpha-1");
121 
122     /**
123      * Groovy 3.0.8 version.
124      */
125     protected static final Version GROOVY_3_0_8 = new Version(3, 0, 8);
126 
127     /**
128      * Groovy 3.0.6 version.
129      */
130     protected static final Version GROOVY_3_0_6 = new Version(3, 0, 6);
131 
132     /**
133      * Groovy 3.0.5 version.
134      */
135     protected static final Version GROOVY_3_0_5 = new Version(3, 0, 5);
136 
137     /**
138      * Groovy 3.0.3 version.
139      */
140     protected static final Version GROOVY_3_0_3 = new Version(3, 0, 3);
141 
142     /**
143      * Groovy 3.0.0 beta-2 version.
144      */
145     protected static final Version GROOVY_3_0_0_BETA2 = new Version(3, 0, 0, "beta-2");
146 
147     /**
148      * Groovy 3.0.0 beta-1 version.
149      */
150     protected static final Version GROOVY_3_0_0_BETA1 = new Version(3, 0, 0, "beta-1");
151 
152     /**
153      * Groovy 3.0.0 alpha-4 version.
154      */
155     protected static final Version GROOVY_3_0_0_ALPHA4 = new Version(3, 0, 0, "alpha-4");
156 
157     /**
158      * Groovy 3.0.0 alpha-2 version.
159      */
160     protected static final Version GROOVY_3_0_0_ALPHA2 = new Version(3, 0, 0, "alpha-2");
161 
162     /**
163      * Groovy 3.0.0 alpha-1 version.
164      */
165     protected static final Version GROOVY_3_0_0_ALPHA1 = new Version(3, 0, 0, "alpha-1");
166 
167     /**
168      * Groovy 2.6.0 alpha-4 version.
169      */
170     protected static final Version GROOVY_2_6_0_ALPHA4 = new Version(2, 6, 0, "alpha-4");
171 
172     /**
173      * Groovy 2.6.0 alpha-1 version.
174      */
175     protected static final Version GROOVY_2_6_0_ALPHA1 = new Version(2, 6, 0, "alpha-1");
176 
177     /**
178      * Groovy 2.5.7 version.
179      */
180     protected static final Version GROOVY_2_5_7 = new Version(2, 5, 7);
181 
182     /**
183      * Groovy 2.5.3 version.
184      */
185     protected static final Version GROOVY_2_5_3 = new Version(2, 5, 3);
186 
187     /**
188      * Groovy 2.5.0 alpha-1 version.
189      */
190     protected static final Version GROOVY_2_5_0_ALPHA1 = new Version(2, 5, 0, "alpha-1");
191 
192     /**
193      * Groovy 2.3.3 version.
194      */
195     protected static final Version GROOVY_2_3_3 = new Version(2, 3, 3);
196 
197     /**
198      * Groovy 2.1.3 version.
199      */
200     protected static final Version GROOVY_2_1_3 = new Version(2, 1, 3);
201 
202     /**
203      * Groovy 2.1.0 beta-1 version.
204      */
205     protected static final Version GROOVY_2_1_0_BETA1 = new Version(2, 1, 0, "beta-1");
206 
207     /**
208      * Groovy 2.0.0 beta-3 version.
209      */
210     protected static final Version GROOVY_2_0_0_BETA3 = new Version(2, 0, 0, "beta-3");
211 
212     /**
213      * Groovy 1.6.0 version.
214      */
215     protected static final Version GROOVY_1_6_0 = new Version(1, 6, 0);
216 
217     /**
218      * The encoding of source files.
219      */
220     @Parameter(defaultValue = "${project.build.sourceEncoding}")
221     protected String sourceEncoding;
222 
223     /**
224      * The Groovy compiler bytecode compatibility. One of
225      * <ul>
226      *   <li>1.4 (or 4)</li>
227      *   <li>1.5 (or 5)</li>
228      *   <li>1.6 (or 6)</li>
229      *   <li>1.7 (or 7)</li>
230      *   <li>1.8 (or 8)</li>
231      *   <li>9 (or 1.9)</li>
232      *   <li>10</li>
233      *   <li>11</li>
234      *   <li>12</li>
235      *   <li>13</li>
236      *   <li>14</li>
237      *   <li>15</li>
238      *   <li>16</li>
239      *   <li>17</li>
240      *   <li>18</li>
241      *   <li>19</li>
242      *   <li>20</li>
243      *   <li>21</li>
244      *   <li>22</li>
245      *   <li>23</li>
246      *   <li>24</li>
247      *   <li>25</li>
248      * </ul>
249      * Using 1.6 (or 6) or 1.7 (or 7) requires Groovy &gt;= 2.1.3.
250      * Using 1.8 (or 8) requires Groovy &gt;= 2.3.3.
251      * Using 9 (or 1.9) requires Groovy &gt;= 2.5.3, or Groovy &gt;= 2.6.0 alpha 4, or Groovy &gt;= 3.0.0 alpha 2.
252      * Using 9 (or 1.9) with invokedynamic requires Groovy &gt;= 2.5.3, or Groovy &gt;= 3.0.0 alpha 2, but not any 2.6 versions.
253      * Using 10, 11, or 12 requires Groovy &gt;= 2.5.3, or Groovy &gt;= 3.0.0 alpha 4, but not any 2.6 versions.
254      * Using 13 requires Groovy &gt;= 2.5.7, or Groovy &gt;= 3.0.0-beta-1, but not any 2.6 versions.
255      * Using 14 requires Groovy &gt;= 3.0.0 beta-2.
256      * Using 15 requires Groovy &gt;= 3.0.3.
257      * Using 16 requires Groovy &gt;= 3.0.6.
258      * Using 17 requires Groovy &gt;= 3.0.8 or Groovy &gt; 4.0.0-alpha-3.
259      * Using 18 requires Groovy &gt; 4.0.0-beta-1.
260      * Using 19 requires Groovy &gt; 4.0.2.
261      * Using 20 requires Groovy &gt; 4.0.6.
262      * Using 21 requires Groovy &gt; 4.0.11.
263      * Using 22 requires Groovy &gt; 4.0.16 or Groovy &gt; 5.0.0-alpha-3.
264      * Using 23 requires Groovy &gt; 4.0.21 or Groovy &gt; 5.0.0-alpha-8.
265      * Using 24 requires Groovy &gt; 4.0.24 or Groovy &gt; 5.0.0-alpha-11.
266      * Using 25 requires Groovy &gt; 4.0.27 or Groovy &gt; 5.0.0-alpha-13.
267      */
268     @Parameter(property = "maven.compiler.target", defaultValue = "1.8")
269     protected String targetBytecode;
270 
271     /**
272      * Whether to check that the version of Groovy used is able to use the requested <code>targetBytecode</code>.
273      *
274      * @since 1.9.0
275      */
276     @Parameter(property = "skipBytecodeCheck", defaultValue = "false")
277     protected boolean skipBytecodeCheck;
278 
279     /**
280      * Whether Groovy compiler should be set to debug.
281      */
282     @Parameter(defaultValue = "false")
283     protected boolean debug;
284 
285     /**
286      * Whether Groovy compiler should be set to verbose.
287      */
288     @Parameter(defaultValue = "false")
289     protected boolean verbose;
290 
291     /**
292      * Groovy compiler warning level. Should be one of:
293      * <dl>
294      *   <dt>0</dt>
295      *     <dd>None</dd>
296      *   <dt>1</dt>
297      *     <dd>Likely Errors</dd>
298      *   <dt>2</dt>
299      *     <dd>Possible Errors</dd>
300      *   <dt>3</dt>
301      *     <dd>Paranoia</dd>
302      * </dl>
303      */
304     @Parameter(defaultValue = "1")
305     protected int warningLevel;
306 
307     /**
308      * Groovy compiler error tolerance (the number of non-fatal errors (per unit) that should be tolerated before compilation is aborted).
309      */
310     @Parameter(defaultValue = "0")
311     protected int tolerance;
312 
313     /**
314      * Whether to support invokeDynamic (requires Java 7 or greater and Groovy indy 2.0.0-beta-3 or greater).
315      * Has no effect for Groovy 4, as it is always enabled.
316      */
317     @Parameter(defaultValue = "false")
318     protected boolean invokeDynamic;
319 
320     /**
321      * Whether to enable Groovy's parallel parsing. Requires Groovy 3.0.5.
322      * Is enabled by default for Groovy 4.0.0-alpha-1 or newer.
323      *
324      * @since 1.11.0
325      */
326     @Parameter
327     protected Boolean parallelParsing = null;
328 
329     /**
330      * A <a href="http://groovy-lang.org/dsls.html#compilation-customizers">script</a> for tweaking the configuration options
331      * (requires Groovy 2.1.0-beta-1 or greater). Note that its encoding must match your source encoding.
332      */
333     @Parameter
334     protected File configScript;
335 
336     /**
337      * Generate metadata for reflection on method parameter names using the functionality provided by JEP 118
338      * (requires Java 8 or greater and Groovy 2.5.0-alpha-1 or greater).
339      */
340     @Parameter(defaultValue = "false")
341     protected boolean parameters;
342 
343     /**
344      * What classpath to include. One of
345      * <ul>
346      *   <li>PROJECT_ONLY</li>
347      *   <li>PROJECT_AND_PLUGIN</li>
348      *   <li>PLUGIN_ONLY</li>
349      * </ul>
350      * Uses the same scope as the required dependency resolution of this mojo. Use only if you know what you're doing.
351      *
352      * @since 1.8.0
353      */
354     @Parameter(defaultValue = "PROJECT_ONLY")
355     protected IncludeClasspath includeClasspath;
356 
357     /**
358      * Whether the bytecode version has preview features enabled (JEP 12).
359      * Requires Groovy &gt;= 3.0.0-beta-1 or Groovy &gt;= 2.5.7, but not any 2.6 versions and Java &gt;= 12.
360      *
361      * @since 1.7.1
362      */
363     @Parameter(defaultValue = "false")
364     protected boolean previewFeatures;
365 
366     /**
367      * Performs compilation of compile mojos.
368      *
369      * @param sources                the sources to compile
370      * @param classpath              the classpath to use for compilation
371      * @param compileOutputDirectory the directory to write the compiled class files to
372      * @throws ClassNotFoundException    when a class needed for compilation cannot be found
373      * @throws InstantiationException    when a class needed for compilation cannot be instantiated
374      * @throws IllegalAccessException    when a method needed for compilation cannot be accessed
375      * @throws InvocationTargetException when a reflection invocation needed for compilation cannot be completed
376      * @throws MalformedURLException     when a classpath element provides a malformed URL
377      */
378     @SuppressWarnings({"rawtypes"})
379     protected synchronized void doCompile(final Set<File> sources, final List classpath, final File compileOutputDirectory)
380             throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, MalformedURLException {
381         if (sources == null || sources.isEmpty()) {
382             getLog().info("No sources specified for compilation. Skipping.");
383             return;
384         }
385 
386         setupClassWrangler(classpath, includeClasspath);
387 
388         logPluginClasspath();
389         classWrangler.logGroovyVersion(mojoExecution.getMojoDescriptor().getGoal());
390 
391         if (!groovyVersionSupportsAction()) {
392             getLog().error("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support compilation. The minimum version of Groovy required is " + minGroovyVersion + ". Skipping compiling.");
393             return;
394         }
395 
396         if (!skipBytecodeCheck) {
397             verifyGroovyVersionSupportsTargetBytecode();
398         }
399 
400         // get classes we need with reflection
401         Class<?> compilerConfigurationClass = classWrangler.getClass("org.codehaus.groovy.control.CompilerConfiguration");
402         Class<?> compilationUnitClass = classWrangler.getClass("org.codehaus.groovy.control.CompilationUnit");
403         Class<?> groovyClassLoaderClass = classWrangler.getClass("groovy.lang.GroovyClassLoader");
404 
405         // setup compile options
406         Object compilerConfiguration = setupCompilerConfiguration(compileOutputDirectory, compilerConfigurationClass);
407         Object groovyClassLoader = invokeConstructor(findConstructor(groovyClassLoaderClass, ClassLoader.class, compilerConfigurationClass), classWrangler.getClassLoader(), compilerConfiguration);
408         Object transformLoader = invokeConstructor(findConstructor(groovyClassLoaderClass, ClassLoader.class), classWrangler.getClassLoader());
409 
410         // add Groovy sources
411         Object compilationUnit = setupCompilationUnit(sources, compilerConfigurationClass, compilationUnitClass, groovyClassLoaderClass, compilerConfiguration, groovyClassLoader, transformLoader);
412 
413         // compile the classes
414         invokeMethod(findMethod(compilationUnitClass, "compile"), compilationUnit);
415 
416         // log compiled classes
417         List classes = (List) invokeMethod(findMethod(compilationUnitClass, "getClasses"), compilationUnit);
418         getLog().info("Compiled " + classes.size() + " file" + (classes.size() != 1 ? "s" : "") + ".");
419     }
420 
421     /**
422      * Sets up the CompilationUnit to use for compilation.
423      *
424      * @param sources                    the sources to compile
425      * @param compilerConfigurationClass the CompilerConfiguration class
426      * @param compilationUnitClass       the CompilationUnit class
427      * @param groovyClassLoaderClass     the GroovyClassLoader class
428      * @param compilerConfiguration      the CompilerConfiguration
429      * @param groovyClassLoader          the GroovyClassLoader
430      * @param transformLoader            the GroovyClassLoader to use for transformation
431      * @return the CompilationUnit
432      * @throws InstantiationException    when a class needed for setting up compilation unit cannot be instantiated
433      * @throws IllegalAccessException    when a method needed for setting up compilation unit cannot be accessed
434      * @throws InvocationTargetException when a reflection invocation needed for setting up compilation unit cannot be completed
435      */
436     protected Object setupCompilationUnit(final Set<File> sources, final Class<?> compilerConfigurationClass, final Class<?> compilationUnitClass, final Class<?> groovyClassLoaderClass, final Object compilerConfiguration, final Object groovyClassLoader, final Object transformLoader) throws InvocationTargetException, IllegalAccessException, InstantiationException {
437         Object compilationUnit;
438         if (groovyAtLeast(GROOVY_1_6_0)) {
439             compilationUnit = invokeConstructor(findConstructor(compilationUnitClass, compilerConfigurationClass, CodeSource.class, groovyClassLoaderClass, groovyClassLoaderClass), compilerConfiguration, null, groovyClassLoader, transformLoader);
440         } else {
441             compilationUnit = invokeConstructor(findConstructor(compilationUnitClass, compilerConfigurationClass, CodeSource.class, groovyClassLoaderClass), compilerConfiguration, null, groovyClassLoader);
442         }
443         getLog().debug("Adding Groovy to compile:");
444         Method addSourceMethod = findMethod(compilationUnitClass, "addSource", File.class);
445         for (File source : sources) {
446             getLog().debug("    " + source);
447             invokeMethod(addSourceMethod, compilationUnit, source);
448         }
449 
450         return compilationUnit;
451     }
452 
453     /**
454      * Sets up the CompilationConfiguration to use for compilation.
455      *
456      * @param compileOutputDirectory     the directory to write the compiled classes to
457      * @param compilerConfigurationClass the CompilerConfiguration class
458      * @return the CompilerConfiguration
459      * @throws ClassNotFoundException    when a class needed for setting up CompilerConfiguration cannot be found
460      * @throws InstantiationException    when a class needed for setting up CompilerConfiguration cannot be instantiated
461      * @throws IllegalAccessException    when a method needed for setting up CompilerConfiguration cannot be accessed
462      * @throws InvocationTargetException when a reflection invocation needed for setting up CompilerConfiguration cannot be completed
463      */
464     @SuppressWarnings({"rawtypes", "unchecked"})
465     protected Object setupCompilerConfiguration(final File compileOutputDirectory, final Class<?> compilerConfigurationClass) throws InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException {
466         Object compilerConfiguration = invokeConstructor(findConstructor(compilerConfigurationClass));
467         if (configScript != null) {
468             if (!configScript.exists()) {
469                 getLog().warn("Configuration script file (" + configScript.getAbsolutePath() + ") doesn't exist. Ignoring configScript parameter.");
470             } else if (groovyOlderThan(GROOVY_2_1_0_BETA1)) {
471                 getLog().warn("Requested to use configScript, but your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support it (must be " + GROOVY_2_1_0_BETA1 + " or newer). Ignoring configScript parameter.");
472             } else {
473                 Class<?> bindingClass = classWrangler.getClass("groovy.lang.Binding");
474                 Class<?> importCustomizerClass = classWrangler.getClass("org.codehaus.groovy.control.customizers.ImportCustomizer");
475                 Class<?> groovyShellClass = classWrangler.getClass("groovy.lang.GroovyShell");
476 
477                 Object binding = invokeConstructor(findConstructor(bindingClass));
478                 invokeMethod(findMethod(bindingClass, "setVariable", String.class, Object.class), binding, "configuration", compilerConfiguration);
479                 Object shellCompilerConfiguration = invokeConstructor(findConstructor(compilerConfigurationClass));
480                 Object importCustomizer = invokeConstructor(findConstructor(importCustomizerClass));
481                 invokeMethod(findMethod(importCustomizerClass, "addStaticStar", String.class), importCustomizer, "org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder");
482                 List compilationCustomizers = (List) invokeMethod(findMethod(compilerConfigurationClass, "getCompilationCustomizers"), shellCompilerConfiguration);
483                 compilationCustomizers.add(importCustomizer);
484                 Object shell = invokeConstructor(findConstructor(groovyShellClass, ClassLoader.class, bindingClass, compilerConfigurationClass), classWrangler.getClassLoader(), binding, shellCompilerConfiguration);
485                 getLog().debug("Using configuration script " + configScript + " for compilation.");
486                 invokeMethod(findMethod(groovyShellClass, "evaluate", File.class), shell, configScript);
487             }
488         }
489         invokeMethod(findMethod(compilerConfigurationClass, "setDebug", boolean.class), compilerConfiguration, debug);
490         invokeMethod(findMethod(compilerConfigurationClass, "setVerbose", boolean.class), compilerConfiguration, verbose);
491         invokeMethod(findMethod(compilerConfigurationClass, "setWarningLevel", int.class), compilerConfiguration, warningLevel);
492         invokeMethod(findMethod(compilerConfigurationClass, "setTolerance", int.class), compilerConfiguration, tolerance);
493         invokeMethod(findMethod(compilerConfigurationClass, "setTargetBytecode", String.class), compilerConfiguration, translateJavacTargetToTargetBytecode(targetBytecode));
494         if (previewFeatures) {
495             if (isJavaSupportPreviewFeatures()) {
496                 if (groovyOlderThan(GROOVY_2_5_7) || (groovyAtLeast(GROOVY_2_6_0_ALPHA1) && groovyOlderThan(GROOVY_3_0_0_BETA1))) {
497                     getLog().warn("Requested to use preview features, but your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support it (must be " + GROOVY_2_5_7 + "/" + GROOVY_3_0_0_BETA1 + " or newer. No 2.6 version is supported. Ignoring previewFeatures parameter.");
498                 } else {
499                     invokeMethod(findMethod(compilerConfigurationClass, "setPreviewFeatures", boolean.class), compilerConfiguration, previewFeatures);
500                 }
501             } else {
502                 getLog().warn("Requested to use to use preview features, but your Java version (" + getJavaVersionString() + ") doesn't support it. Ignoring previewFeatures parameter.");
503             }
504         }
505         if (sourceEncoding != null) {
506             invokeMethod(findMethod(compilerConfigurationClass, "setSourceEncoding", String.class), compilerConfiguration, sourceEncoding);
507         }
508         invokeMethod(findMethod(compilerConfigurationClass, "setTargetDirectory", String.class), compilerConfiguration, compileOutputDirectory.getAbsolutePath());
509         if (invokeDynamic || groovyAtLeast(GROOVY_4_0_0_ALPHA1)) {
510             if (groovyAtLeast(GROOVY_2_0_0_BETA3)) {
511                 if (classWrangler.isGroovyIndy()) {
512                     if (isJavaSupportIndy()) {
513                         Map<String, Boolean> optimizationOptions = (Map<String, Boolean>) invokeMethod(findMethod(compilerConfigurationClass, "getOptimizationOptions"), compilerConfiguration);
514                         optimizationOptions.put("indy", true);
515                         optimizationOptions.put("int", false);
516                         getLog().info("invokedynamic enabled.");
517                     } else {
518                         getLog().warn("Requested to use to use invokedynamic, but your Java version (" + getJavaVersionString() + ") doesn't support it. Ignoring invokeDynamic parameter.");
519                     }
520                 } else {
521                     getLog().warn("Requested to use invokedynamic, but your Groovy version doesn't support it (must use have indy classifier). Ignoring invokeDynamic parameter.");
522                 }
523             } else {
524                 getLog().warn("Requested to use invokeDynamic, but your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support it (must be " + GROOVY_2_0_0_BETA3 + " or newer). Ignoring invokeDynamic parameter.");
525             }
526         }
527         if (parameters) {
528             if (groovyAtLeast(GROOVY_2_5_0_ALPHA1)) {
529                 if (isJavaSupportParameters()) {
530                     invokeMethod(findMethod(compilerConfigurationClass, "setParameters", boolean.class), compilerConfiguration, parameters);
531                 } else {
532                     getLog().warn("Requested to use to use parameters, but your Java version (" + getJavaVersionString() + ") doesn't support it. Ignoring parameters parameter.");
533                 }
534             } else {
535                 getLog().warn("Requested to use parameters, but your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support it (must be " + GROOVY_2_5_0_ALPHA1 + " or newer). Ignoring parameters parameter.");
536             }
537         }
538         if (groovyAtLeast(GROOVY_3_0_5)) {
539             if ((parallelParsing == null && groovyAtLeast(GROOVY_4_0_0_ALPHA1)) || (parallelParsing != null && parallelParsing)) {
540                 Map<String, Boolean> optimizationOptions = (Map<String, Boolean>) invokeMethod(findMethod(compilerConfigurationClass, "getOptimizationOptions"), compilerConfiguration);
541                 optimizationOptions.put("parallelParse", true);
542                 getLog().info("Parallel parsing enabled.");
543             } else {
544                 getLog().info("Parallel parsing disabled.");
545             }
546         }
547 
548         return compilerConfiguration;
549     }
550 
551     /**
552      * Throws an exception if targetBytecode is not supported with this version of Groovy. That is, when Groovy added
553      * the option to org.codehaus.groovy.control.CompilerConfiguration and used it in
554      * org.codehaus.groovy.classgen.asm.WriterController.
555      */
556     protected void verifyGroovyVersionSupportsTargetBytecode() {
557         if ("1.5".equals(targetBytecode) || "5".equals(targetBytecode) || "1.6".equals(targetBytecode) || "6".equals(targetBytecode) || "1.7".equals(targetBytecode) || "7".equals(targetBytecode) || "1.8".equals(targetBytecode) || "8".equals(targetBytecode) || "1.9".equals(targetBytecode) || "9".equals(targetBytecode) || "10".equals(targetBytecode)) {
558             if (groovyNewerThan(GROOVY_5_0_0_ALPHA1)) {
559                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " isn't accepted by Groovy " + GROOVY_5_0_0_ALPHA1 + " or newer.");
560             }
561         }
562 
563         if ("25".equals(targetBytecode)) {
564             if (groovyOlderThan(GROOVY_4_0_27)) {
565                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_24 + " or newer.");
566             }
567             if (groovyNewerThan(GROOVY_5_0_0_ALPHA1) && groovyOlderThan(GROOVY_5_0_0_ALPHA13)) {
568                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_5_0_0_ALPHA13 + " or newer.");
569             }
570         } else if ("24".equals(targetBytecode)) {
571             if (groovyOlderThan(GROOVY_4_0_24)) {
572                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_24 + " or newer.");
573             }
574             if (groovyNewerThan(GROOVY_5_0_0_ALPHA1) && groovyOlderThan(GROOVY_5_0_0_ALPHA11)) {
575                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_5_0_0_ALPHA11 + " or newer.");
576             }
577         } else if ("23".equals(targetBytecode)) {
578             if (groovyOlderThan(GROOVY_4_0_21)) {
579                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_21 + " or newer.");
580             }
581             if (groovyNewerThan(GROOVY_5_0_0_ALPHA1) && groovyOlderThan(GROOVY_5_0_0_ALPHA8)) {
582                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_5_0_0_ALPHA8 + " or newer.");
583             }
584         } else if ("22".equals(targetBytecode)) {
585             if (groovyOlderThan(GROOVY_4_0_16)) {
586                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_16 + " or newer.");
587             }
588             if (groovyNewerThan(GROOVY_5_0_0_ALPHA1) && groovyOlderThan(GROOVY_5_0_0_ALPHA3)) {
589                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_5_0_0_ALPHA3 + " or newer.");
590             }
591         } else if ("21".equals(targetBytecode)) {
592             if (groovyOlderThan(GROOVY_4_0_11)) {
593                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_11 + " or newer.");
594             }
595         } else if ("20".equals(targetBytecode)) {
596             if (groovyOlderThan(GROOVY_4_0_6)) {
597                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_6 + " or newer.");
598             }
599         } else if ("19".equals(targetBytecode)) {
600             if (groovyOlderThan(GROOVY_4_0_2)) {
601                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_2 + " or newer.");
602             }
603         } else if ("18".equals(targetBytecode)) {
604             if (groovyOlderThan(GROOVY_4_0_0_BETA1)) {
605                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_0_BETA1 + " or newer.");
606             }
607         } else if ("17".equals(targetBytecode)) {
608             if (groovyOlderThan(GROOVY_3_0_8) || (groovyAtLeast(GROOVY_4_0_0_ALPHA1) && groovyOlderThan(GROOVY_4_0_0_ALPHA3))) {
609                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_3_0_8 + "/" + GROOVY_4_0_0_ALPHA3 + " or newer.");
610             }
611         } else if ("16".equals(targetBytecode)) {
612             if (groovyOlderThan(GROOVY_3_0_6)) {
613                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_3_0_6 + " or newer.");
614             }
615         } else if ("15".equals(targetBytecode)) {
616             if (groovyOlderThan(GROOVY_3_0_3)) {
617                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_3_0_3 + " or newer.");
618             }
619         } else if ("14".equals(targetBytecode)) {
620             if (groovyOlderThan(GROOVY_3_0_0_BETA2)) {
621                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_3_0_0_BETA2 + " or newer.");
622             }
623         } else if ("13".equals(targetBytecode)) {
624             if (groovyOlderThan(GROOVY_2_5_7) || (groovyAtLeast(GROOVY_2_6_0_ALPHA1) && groovyOlderThan(GROOVY_3_0_0_BETA1))) {
625                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_5_7 + "/" + GROOVY_3_0_0_BETA1 + " or newer. No 2.6 version is supported.");
626             }
627         } else if ("12".equals(targetBytecode) || "11".equals(targetBytecode) || "10".equals(targetBytecode)) {
628             if (groovyOlderThan(GROOVY_2_5_3) || (groovyAtLeast(GROOVY_2_6_0_ALPHA1) && groovyOlderThan(GROOVY_3_0_0_ALPHA4))) {
629                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_5_3 + "/" + GROOVY_3_0_0_ALPHA4 + " or newer. No 2.6 version is supported.");
630             }
631         } else if ("9".equals(targetBytecode) || "1.9".equals(targetBytecode)) {
632             if (!isGroovyIndy() && (groovyOlderThan(GROOVY_2_5_3)
633                     || (groovyAtLeast(GROOVY_2_6_0_ALPHA1) && groovyOlderThan(GROOVY_2_6_0_ALPHA4))
634                     || (groovyAtLeast(GROOVY_3_0_0_ALPHA1) && groovyOlderThan(GROOVY_3_0_0_ALPHA2)))) {
635                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_5_3 + "/" + GROOVY_2_6_0_ALPHA4 + "/" + GROOVY_3_0_0_ALPHA2 + " or newer.");
636             } else if (isGroovyIndy() && (groovyOlderThan(GROOVY_2_5_3) || (groovyAtLeast(GROOVY_2_6_0_ALPHA1) && groovyOlderThan(GROOVY_3_0_0_ALPHA4)))) {
637                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_5_3 + "/" + GROOVY_3_0_0_ALPHA4 + " or newer. No 2.6 version is supported.");
638             }
639         } else if ("8".equals(targetBytecode) || "1.8".equals(targetBytecode)) {
640             if (groovyOlderThan(GROOVY_2_3_3)) {
641                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_3_3 + " or newer.");
642             }
643         } else if ("7".equals(targetBytecode) || "1.7".equals(targetBytecode) || "6".equals(targetBytecode) || "1.6".equals(targetBytecode)) {
644             if (groovyOlderThan(GROOVY_2_1_3)) {
645                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_1_3 + " or newer.");
646             }
647         } else if (!"5".equals(targetBytecode) && !"1.5".equals(targetBytecode) && !"4".equals(targetBytecode) && !"1.4".equals(targetBytecode)) {
648             throw new IllegalArgumentException("Unrecognized target bytecode: '" + targetBytecode + "'. This check can be skipped with 'skipBytecodeCheck', but this may result in a different target bytecode being used.");
649         }
650     }
651 
652     protected static String translateJavacTargetToTargetBytecode(String targetBytecode) {
653         Map<String, String> javacTargetToTargetBytecode = new HashMap<>();
654         javacTargetToTargetBytecode.put("5", "1.5");
655         javacTargetToTargetBytecode.put("6", "1.6");
656         javacTargetToTargetBytecode.put("7", "1.7");
657         javacTargetToTargetBytecode.put("8", "1.8");
658         javacTargetToTargetBytecode.put("1.9", "9");
659         return javacTargetToTargetBytecode.getOrDefault(targetBytecode, targetBytecode);
660     }
661 
662 }