View Javadoc
1   package org.codehaus.gmavenplus.util;
2   
3   import org.apache.maven.plugin.logging.Log;
4   import org.codehaus.gmavenplus.model.GroovyCompileConfiguration;
5   import org.codehaus.gmavenplus.model.GroovyDocConfiguration;
6   import org.codehaus.gmavenplus.model.GroovyStubConfiguration;
7   import org.codehaus.gmavenplus.model.Link;
8   import org.apache.maven.shared.model.fileset.FileSet;
9   import org.apache.maven.shared.model.fileset.util.FileSetManager;
10  import org.codehaus.gmavenplus.groovyworkarounds.GroovyDocTemplateInfo;
11  import java.util.ArrayList;
12  import java.util.Properties;
13  import org.codehaus.gmavenplus.model.internal.Version;
14  
15  import java.io.File;
16  import java.lang.reflect.InvocationTargetException;
17  import java.lang.reflect.Method;
18  import java.security.CodeSource;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import static org.codehaus.gmavenplus.util.ReflectionUtils.*;
25  
26  /**
27   * Handles the actual compilation logic, separated from the Mojo to allow forked execution.
28   *
29   * @author Keegan Witt
30   */
31  public class GroovyCompiler {
32  
33      /**
34       * Groovy 5.0.0-beta-1 version.
35       */
36      protected static final Version GROOVY_5_0_0_BETA_1 = new Version(5, 0, 0, "beta-1");
37  
38      /**
39       * Groovy 5.0.0-alpha-13 version.
40       */
41      protected static final Version GROOVY_5_0_0_ALPHA13 = new Version(5, 0, 0, "alpha-13");
42  
43      /**
44       * Groovy 5.0.0-alpha-11 version.
45       */
46      protected static final Version GROOVY_5_0_0_ALPHA11 = new Version(5, 0, 0, "alpha-11");
47  
48      /**
49       * Groovy 5.0.0-alpha-8 version.
50       */
51      protected static final Version GROOVY_5_0_0_ALPHA8 = new Version(5, 0, 0, "alpha-8");
52  
53      /**
54       * Groovy 5.0.0-alpha-3 version.
55       */
56      protected static final Version GROOVY_5_0_0_ALPHA3 = new Version(5, 0, 0, "alpha-3");
57  
58      /**
59       * Groovy 5.0.0-alpha-1 version.
60       */
61      protected static final Version GROOVY_5_0_0_ALPHA1 = new Version(5, 0, 0, "alpha-1");
62  
63      /**
64       * Groovy 4.0.27 version.
65       */
66      protected static final Version GROOVY_4_0_27 = new Version(4, 0, 27);
67  
68      /**
69       * Groovy 4.0.24 version.
70       */
71      protected static final Version GROOVY_4_0_24 = new Version(4, 0, 24);
72  
73      /**
74       * Groovy 4.0.21 version.
75       */
76      protected static final Version GROOVY_4_0_21 = new Version(4, 0, 21);
77  
78      /**
79       * Groovy 4.0.11 version.
80       */
81      protected static final Version GROOVY_4_0_16 = new Version(4, 0, 16);
82  
83      /**
84       * Groovy 4.0.11 version.
85       */
86      protected static final Version GROOVY_4_0_11 = new Version(4, 0, 11);
87  
88      /**
89       * Groovy 4.0.6 version.
90       */
91      protected static final Version GROOVY_4_0_6 = new Version(4, 0, 6);
92  
93      /**
94       * Groovy 4.0.2 version.
95       */
96      protected static final Version GROOVY_4_0_2 = new Version(4, 0, 2);
97  
98      /**
99       * Groovy 4.0.0 beta-1 version.
100      */
101     protected static final Version GROOVY_4_0_0_BETA1 = new Version(4, 0, 0, "beta-1");
102 
103     /**
104      * Groovy 4.0.0 alpha-3 version.
105      */
106     protected static final Version GROOVY_4_0_0_ALPHA3 = new Version(4, 0, 0, "alpha-3");
107 
108     /**
109      * Groovy 4.0.0 alpha-1 version.
110      */
111     protected static final Version GROOVY_4_0_0_ALPHA1 = new Version(4, 0, 0, "alpha-1");
112 
113     /**
114      * Groovy 3.0.8 version.
115      */
116     protected static final Version GROOVY_3_0_8 = new Version(3, 0, 8);
117 
118     /**
119      * Groovy 3.0.6 version.
120      */
121     protected static final Version GROOVY_3_0_6 = new Version(3, 0, 6);
122 
123     /**
124      * Groovy 3.0.5 version.
125      */
126     protected static final Version GROOVY_3_0_5 = new Version(3, 0, 5);
127 
128     /**
129      * Groovy 3.0.3 version.
130      */
131     protected static final Version GROOVY_3_0_3 = new Version(3, 0, 3);
132 
133     /**
134      * Groovy 3.0.0 beta-2 version.
135      */
136     protected static final Version GROOVY_3_0_0_BETA2 = new Version(3, 0, 0, "beta-2");
137 
138     /**
139      * Groovy 3.0.0 beta-1 version.
140      */
141     protected static final Version GROOVY_3_0_0_BETA1 = new Version(3, 0, 0, "beta-1");
142 
143     /**
144      * Groovy 3.0.0 alpha-4 version.
145      */
146     protected static final Version GROOVY_3_0_0_ALPHA4 = new Version(3, 0, 0, "alpha-4");
147 
148     /**
149      * Groovy 3.0.0 alpha-2 version.
150      */
151     protected static final Version GROOVY_3_0_0_ALPHA2 = new Version(3, 0, 0, "alpha-2");
152 
153     /**
154      * Groovy 3.0.0 alpha-1 version.
155      */
156     protected static final Version GROOVY_3_0_0_ALPHA1 = new Version(3, 0, 0, "alpha-1");
157 
158     /**
159      * Groovy 2.6.0 alpha-4 version.
160      */
161     protected static final Version GROOVY_2_6_0_ALPHA4 = new Version(2, 6, 0, "alpha-4");
162 
163     /**
164      * Groovy 2.6.0 alpha-1 version.
165      */
166     protected static final Version GROOVY_2_6_0_ALPHA1 = new Version(2, 6, 0, "alpha-1");
167 
168     /**
169      * Groovy 2.5.7 version.
170      */
171     protected static final Version GROOVY_2_5_7 = new Version(2, 5, 7);
172 
173     /**
174      * Groovy 2.5.3 version.
175      */
176     protected static final Version GROOVY_2_5_3 = new Version(2, 5, 3);
177 
178     /**
179      * Groovy 2.5.0 alpha-1 version.
180      */
181     protected static final Version GROOVY_2_5_0_ALPHA1 = new Version(2, 5, 0, "alpha-1");
182 
183     /**
184      * Groovy 2.3.3 version.
185      */
186     protected static final Version GROOVY_2_3_3 = new Version(2, 3, 3);
187 
188     /**
189      * Groovy 1.8.2 version.
190      */
191     protected static final Version GROOVY_1_8_2 = new Version(1, 8, 2);
192 
193     /**
194      * Groovy 1.8.3 version.
195      */
196     protected static final Version GROOVY_1_8_3 = new Version(1, 8, 3);
197 
198     /**
199      * Groovy 2.1.3 version.
200      */
201     protected static final Version GROOVY_2_1_3 = new Version(2, 1, 3);
202 
203     /**
204      * Groovy 2.1.0 beta-1 version.
205      */
206     protected static final Version GROOVY_2_1_0_BETA1 = new Version(2, 1, 0, "beta-1");
207 
208     /**
209      * Groovy 2.0.0 beta-3 version.
210      */
211     protected static final Version GROOVY_2_0_0_BETA3 = new Version(2, 0, 0, "beta-3");
212 
213     /**
214      * Groovy 1.9.0 beta-1 version.
215      */
216     protected static final Version GROOVY_1_9_0_BETA1 = new Version(1, 9, 0, "beta-1");
217 
218     /**
219      * Groovy 1.9.0 beta-3 version.
220      */
221     protected static final Version GROOVY_1_9_0_BETA3 = new Version(1, 9, 0, "beta-3");
222 
223     /**
224      * Groovy 1.6.0 version.
225      */
226     protected static final Version GROOVY_1_6_0 = new Version(1, 6, 0);
227 
228     /**
229      * Groovy 1.6.0 RC-2 version.
230      */
231     protected static final Version GROOVY_1_6_0_RC2 = new Version(1, 6, 0, "RC-2");
232 
233     /**
234      * Groovy 1.5.2 version.
235      */
236     protected static final Version GROOVY_1_5_2 = new Version(1, 5, 2);
237 
238     /**
239      * Java 1.7 version.
240      */
241     protected static final Version JAVA_1_7 = new Version(1, 7);
242 
243     /**
244      * Java 1.8 version.
245      */
246     protected static final Version JAVA_1_8 = new Version(1, 8);
247 
248     /**
249      * Java 1.8 version.
250      */
251     protected static final Version JAVA_12 = new Version(12);
252 
253     private final ClassWrangler classWrangler;
254     private final Log log;
255 
256     public GroovyCompiler(ClassWrangler classWrangler, Log log) {
257         this.classWrangler = classWrangler;
258         this.log = log;
259     }
260 
261     public void compile(GroovyCompileConfiguration configuration) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
262         if (configuration.getSources() == null || configuration.getSources().isEmpty()) {
263             log.info("No sources specified for compilation. Skipping.");
264             return;
265         }
266 
267         if (!configuration.isSkipBytecodeCheck()) {
268             verifyGroovyVersionSupportsTargetBytecode(configuration.getTargetBytecode());
269         }
270 
271         // get classes we need with reflection
272         Class<?> compilerConfigurationClass = classWrangler.getClass("org.codehaus.groovy.control.CompilerConfiguration");
273         Class<?> compilationUnitClass = classWrangler.getClass("org.codehaus.groovy.control.CompilationUnit");
274         Class<?> groovyClassLoaderClass = classWrangler.getClass("groovy.lang.GroovyClassLoader");
275 
276         // setup compile options
277         Object compilerConfiguration = setupCompilerConfiguration(configuration, compilerConfigurationClass);
278         Object groovyClassLoader = invokeConstructor(findConstructor(groovyClassLoaderClass, ClassLoader.class, compilerConfigurationClass), classWrangler.getClassLoader(), compilerConfiguration);
279         Object transformLoader = invokeConstructor(findConstructor(groovyClassLoaderClass, ClassLoader.class), classWrangler.getClassLoader());
280 
281         // add Groovy sources
282         Object compilationUnit = setupCompilationUnit(configuration.getSources(), compilerConfigurationClass, compilationUnitClass, groovyClassLoaderClass, compilerConfiguration, groovyClassLoader, transformLoader);
283 
284         // compile the classes
285         invokeMethod(findMethod(compilationUnitClass, "compile"), compilationUnit);
286 
287         // log compiled classes
288         List<?> classes = (List<?>) invokeMethod(findMethod(compilationUnitClass, "getClasses"), compilationUnit);
289         log.info("Compiled " + classes.size() + " file" + (classes.size() != 1 ? "s" : "") + ".");
290     }
291 
292     public void generateGroovyDoc(GroovyDocConfiguration configuration) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
293         if (configuration.getSourceDirectories() == null || configuration.getSourceDirectories().length == 0) {
294             log.info("No source directories specified for GroovyDoc generation. Skipping.");
295             return;
296         }
297 
298         // Note: minGroovyVersion check is usually done by caller (Mojo) but strict check is good.
299         // GroovyDoc supports 1.5.2+ generally (LinkArgument) or 1.6+ for properties?
300         // AbstractGroovyDocMojo checks groovyVersionSupportsAction() which uses mojo defined min version.
301         // We can skip strict min version check here and rely on feature detection or caller.
302 
303         // get classes we need with reflection
304         Class<?> groovyDocToolClass = classWrangler.getClass(configuration.getGroovyDocToolClass() == null ? "org.codehaus.groovy.tools.groovydoc.GroovyDocTool" : configuration.getGroovyDocToolClass());
305         Class<?> outputToolClass = classWrangler.getClass(configuration.getOutputToolClass() == null ? "org.codehaus.groovy.tools.groovydoc.OutputTool" : configuration.getOutputToolClass());
306         Class<?> fileOutputToolClass = classWrangler.getClass(configuration.getFileOutputToolClass() == null ? "org.codehaus.groovy.tools.groovydoc.FileOutputTool" : configuration.getFileOutputToolClass());
307         Class<?> resourceManagerClass = classWrangler.getClass(configuration.getResourceManagerClass() == null ? "org.codehaus.groovy.tools.groovydoc.ResourceManager" : configuration.getResourceManagerClass());
308         Class<?> classpathResourceManagerClass = classWrangler.getClass(configuration.getClasspathResourceManagerClass() == null ? "org.codehaus.groovy.tools.groovydoc.ClasspathResourceManager" : configuration.getClasspathResourceManagerClass());
309 
310         // set up GroovyDoc options
311         if (configuration.isAttachGroovyDocAnnotation()) {
312             if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_3_0_0_ALPHA4)) {
313                 System.setProperty("runtimeGroovydoc", "true");
314             } else {
315                 log.warn("Requested to enable attaching GroovyDoc annotation, but your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support it (must be " + GROOVY_3_0_0_ALPHA4 + " or newer). Ignoring enableGroovyDocAnnotation parameter.");
316             }
317         }
318 
319         Object fileOutputTool = invokeConstructor(findConstructor(fileOutputToolClass));
320         Object classpathResourceManager = invokeConstructor(findConstructor(classpathResourceManagerClass));
321         FileSetManager fileSetManager = new FileSetManager();
322         List<String> sourceDirectoriesStrings = new ArrayList<>();
323         for (FileSet sourceDirectory : configuration.getSourceDirectories()) {
324             sourceDirectoriesStrings.add(sourceDirectory.getDirectory());
325         }
326         GroovyDocTemplateInfo groovyDocTemplateInfo = new GroovyDocTemplateInfo(classWrangler.getGroovyVersion());
327 
328         List<?> groovyDocLinks = setupLinks(configuration);
329 
330         if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_1_6_0_RC2) && configuration.getDocProperties() != null && !configuration.getDocProperties().isEmpty()) {
331             log.warn("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support GroovyDoc documentation properties (docTitle, footer, header, displayAuthor, overviewFile, and scope). You need Groovy 1.6-RC-2 or newer to support this. Ignoring properties.");
332         }
333 
334         // prevent Java stubs from overwriting GroovyDoc
335         List<String> groovyDocSources = setupGroovyDocSources(configuration.getSourceDirectories(), fileSetManager);
336 
337         // instantiate GroovyDocTool
338         Object groovyDocTool = createGroovyDocTool(groovyDocToolClass, resourceManagerClass, configuration.getDocProperties(), classpathResourceManager, sourceDirectoriesStrings, groovyDocTemplateInfo, groovyDocLinks, configuration);
339 
340         // generate GroovyDoc
341         performGroovyDocGeneration(configuration.getOutputDirectory(), groovyDocToolClass, outputToolClass, fileOutputTool, groovyDocSources, groovyDocTool);
342     }
343 
344     @SuppressWarnings({"rawtypes", "unchecked"})
345     protected List<?> setupLinks(GroovyDocConfiguration configuration) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
346         List linksList = new ArrayList();
347         if (configuration.getLinks() != null && !configuration.getLinks().isEmpty()) {
348             Class<?> linkArgumentClass = null;
349             if (configuration.getLinkArgumentClass() == null) {
350                 if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_1_6_0_RC2)) {
351                     linkArgumentClass = classWrangler.getClass("org.codehaus.groovy.tools.groovydoc.LinkArgument");
352                 } else if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_1_5_2)) {
353                     linkArgumentClass = classWrangler.getClass("org.codehaus.groovy.ant.Groovydoc$LinkArgument");
354                 }
355             } else {
356                 linkArgumentClass = classWrangler.getClass(configuration.getLinkArgumentClass());
357             }
358             if (linkArgumentClass != null) {
359                 Method setHref = findMethod(linkArgumentClass, "setHref", String.class);
360                 Method setPackages = findMethod(linkArgumentClass, "setPackages", String.class);
361                 for (Link link : configuration.getLinks()) {
362                     Object linkArgument = invokeConstructor(findConstructor(linkArgumentClass));
363                     invokeMethod(setHref, linkArgument, link.getHref());
364                     invokeMethod(setPackages, linkArgument, link.getPackages());
365                     linksList.add(linkArgument);
366                 }
367             } else {
368                 log.warn("Requested to use GroovyDoc links, but your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support it (must be 1.5.2 or newer). Ignoring links parameter.");
369             }
370         }
371         return linksList;
372     }
373 
374     protected Object createGroovyDocTool(final Class<?> groovyDocToolClass, final Class<?> resourceManagerClass, final Properties docProperties, final Object classpathResourceManager, final List<String> sourceDirectories, final GroovyDocTemplateInfo groovyDocTemplateInfo, final List<?> groovyDocLinks, GroovyDocConfiguration configuration) throws InvocationTargetException, IllegalAccessException, InstantiationException {
375         Object groovyDocTool;
376 
377         String[] defaultDocTemplates = configuration.getDefaultDocTemplates();
378         String[] defaultPackageTemplates = configuration.getDefaultPackageTemplates();
379         String[] defaultClassTemplates = configuration.getDefaultClassTemplates();
380 
381         if ((ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_4_0_27) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA1)) || ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_5_0_0_BETA_1)) {
382              groovyDocTool = invokeConstructor(findConstructor(groovyDocToolClass, resourceManagerClass, String[].class, String[].class, String[].class, String[].class, List.class, String.class, Properties.class),
383                     classpathResourceManager,
384                     sourceDirectories.toArray(new String[0]),
385                     defaultDocTemplates == null ? groovyDocTemplateInfo.defaultDocTemplates() : defaultDocTemplates,
386                     defaultPackageTemplates == null ? groovyDocTemplateInfo.defaultPackageTemplates() : defaultPackageTemplates,
387                     defaultClassTemplates == null ? groovyDocTemplateInfo.defaultClassTemplates() : defaultClassTemplates,
388                     groovyDocLinks,
389                     configuration.getLanguageLevel(),
390                     docProperties
391             );
392         } else if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_1_6_0_RC2)) {
393             groovyDocTool = invokeConstructor(findConstructor(groovyDocToolClass, resourceManagerClass, String[].class, String[].class, String[].class, String[].class, List.class, Properties.class),
394                     classpathResourceManager,
395                     sourceDirectories.toArray(new String[0]),
396                     defaultDocTemplates == null ? groovyDocTemplateInfo.defaultDocTemplates() : defaultDocTemplates,
397                     defaultPackageTemplates == null ? groovyDocTemplateInfo.defaultPackageTemplates() : defaultPackageTemplates,
398                     defaultClassTemplates == null ? groovyDocTemplateInfo.defaultClassTemplates() : defaultClassTemplates,
399                     groovyDocLinks,
400                     docProperties
401             );
402         } else if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_1_5_2)) {
403             groovyDocTool = invokeConstructor(findConstructor(groovyDocToolClass, resourceManagerClass, String.class, String[].class, String[].class, String[].class, List.class),
404                     classpathResourceManager,
405                     sourceDirectories.get(0),
406                     defaultDocTemplates == null ? groovyDocTemplateInfo.defaultDocTemplates() : defaultDocTemplates,
407                     defaultPackageTemplates == null ? groovyDocTemplateInfo.defaultPackageTemplates() : defaultPackageTemplates,
408                     defaultClassTemplates == null ? groovyDocTemplateInfo.defaultClassTemplates() : defaultClassTemplates,
409                     groovyDocLinks
410             );
411             if (sourceDirectories.size() > 1) {
412                 log.warn("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support more than one GroovyDoc source directory (must be 1.6-RC-2 or newer). Only using first source directory (" + sourceDirectories.get(0) + ").");
413             }
414         } else {
415             groovyDocTool = invokeConstructor(findConstructor(groovyDocToolClass, resourceManagerClass, String.class, String[].class, String[].class, String[].class),
416                     classpathResourceManager,
417                     sourceDirectories.get(0),
418                     defaultDocTemplates == null ? groovyDocTemplateInfo.defaultDocTemplates() : defaultDocTemplates,
419                     defaultPackageTemplates == null ? groovyDocTemplateInfo.defaultPackageTemplates() : defaultPackageTemplates,
420                     defaultClassTemplates == null ? groovyDocTemplateInfo.defaultClassTemplates() : defaultClassTemplates
421             );
422              if (sourceDirectories.size() > 1) {
423                 log.warn("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support more than one GroovyDoc source directory (must be 1.6-RC-2 or newer). Only using first source directory (" + sourceDirectories.get(0) + ").");
424             }
425         }
426         return groovyDocTool;
427     }
428 
429     protected List<String> setupGroovyDocSources(final FileSet[] sourceDirectories, final FileSetManager fileSetManager) {
430         List<String> javaSources = new ArrayList<>();
431         List<String> groovySources = new ArrayList<>();
432         List<String> possibleGroovyStubs = new ArrayList<>();
433         for (FileSet sourceDirectory : sourceDirectories) {
434             String[] sources = fileSetManager.getIncludedFiles(sourceDirectory);
435             for (String source : sources) {
436                 if (source.endsWith(".java") && !javaSources.contains(source)) {
437                     javaSources.add(source);
438                 } else if (!groovySources.contains(source)) {
439                     groovySources.add(source);
440                     possibleGroovyStubs.add(source.replaceFirst("\\." + FileUtils.getFileExtension(source), ".java"));
441                 }
442             }
443         }
444         javaSources.removeAll(possibleGroovyStubs);
445         List<String> groovyDocSources = new ArrayList<>();
446         groovyDocSources.addAll(javaSources);
447         groovyDocSources.addAll(groovySources);
448 
449         return groovyDocSources;
450     }
451 
452     protected void performGroovyDocGeneration(final File outputDirectory, final Class<?> groovyDocToolClass, final Class<?> outputToolClass, final Object fileOutputTool, final List<String> groovyDocSources, final Object groovyDocTool) throws InvocationTargetException, IllegalAccessException {
453         log.debug("Adding sources to generate GroovyDoc for:");
454         if (log.isDebugEnabled()) {
455             for (String groovyDocSource : groovyDocSources) {
456                 log.debug("    " + groovyDocSource);
457             }
458         }
459         if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_1_6_0_RC2)) {
460             invokeMethod(findMethod(groovyDocToolClass, "add", List.class), groovyDocTool, groovyDocSources);
461         } else {
462             Method add = findMethod(groovyDocToolClass, "add", String.class);
463             for (String groovyDocSource : groovyDocSources) {
464                 invokeMethod(add, groovyDocTool, groovyDocSource);
465             }
466         }
467         invokeMethod(findMethod(groovyDocToolClass, "renderToOutput", outputToolClass, String.class), groovyDocTool, fileOutputTool, outputDirectory.getAbsolutePath());
468     }
469 
470     public void generateStubs(GroovyStubConfiguration configuration) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
471 
472         if (configuration.getStubSources() == null || configuration.getStubSources().isEmpty()) {
473             log.info("No sources specified for stub generation. Skipping.");
474             return;
475         }
476 
477         if (!supportsStubGeneration()) {
478             log.error("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support stub generation. The minimum version of Groovy required is 1.8.2. Skipping stub generation.");
479             return;
480         }
481 
482         if (!configuration.isSkipBytecodeCheck()) {
483             verifyGroovyVersionSupportsTargetBytecode(configuration.getTargetBytecode());
484         }
485 
486         // get classes we need with reflection
487         Class<?> compilerConfigurationClass = classWrangler.getClass("org.codehaus.groovy.control.CompilerConfiguration");
488         Class<?> javaStubCompilationUnitClass = classWrangler.getClass("org.codehaus.groovy.tools.javac.JavaStubCompilationUnit");
489         Class<?> groovyClassLoaderClass = classWrangler.getClass("groovy.lang.GroovyClassLoader");
490 
491         // setup stub generation options
492         Object compilerConfiguration = setupStubCompilerConfiguration(configuration, compilerConfigurationClass);
493         Object groovyClassLoader = invokeConstructor(findConstructor(groovyClassLoaderClass, ClassLoader.class, compilerConfigurationClass), classWrangler.getClassLoader(), compilerConfiguration);
494         Object javaStubCompilationUnit = invokeConstructor(findConstructor(javaStubCompilationUnitClass, compilerConfigurationClass, groovyClassLoaderClass, File.class), compilerConfiguration, groovyClassLoader, configuration.getOutputDirectory());
495 
496         // add Groovy sources
497         addGroovySources(configuration.getStubSources(), compilerConfigurationClass, javaStubCompilationUnitClass, compilerConfiguration, javaStubCompilationUnit);
498 
499         // generate the stubs
500         invokeMethod(findMethod(javaStubCompilationUnitClass, "compile"), javaStubCompilationUnit);
501     }
502 
503     protected Object setupStubCompilerConfiguration(final GroovyStubConfiguration configuration, final Class<?> compilerConfigurationClass) throws InvocationTargetException, IllegalAccessException, InstantiationException {
504         Object compilerConfiguration = invokeConstructor(findConstructor(compilerConfigurationClass));
505         invokeMethod(findMethod(compilerConfigurationClass, "setDebug", boolean.class), compilerConfiguration, configuration.isDebug());
506         invokeMethod(findMethod(compilerConfigurationClass, "setVerbose", boolean.class), compilerConfiguration, configuration.isVerbose());
507         invokeMethod(findMethod(compilerConfigurationClass, "setWarningLevel", int.class), compilerConfiguration, configuration.getWarningLevel());
508         invokeMethod(findMethod(compilerConfigurationClass, "setTolerance", int.class), compilerConfiguration, configuration.getTolerance());
509         invokeMethod(findMethod(compilerConfigurationClass, "setTargetBytecode", String.class), compilerConfiguration, translateJavacTargetToTargetBytecode(configuration.getTargetBytecode()));
510         if (configuration.getSourceEncoding() != null) {
511             invokeMethod(findMethod(compilerConfigurationClass, "setSourceEncoding", String.class), compilerConfiguration, configuration.getSourceEncoding());
512         }
513         Map<String, Object> options = new HashMap<>();
514         options.put("stubDir", configuration.getOutputDirectory());
515         options.put("keepStubs", Boolean.TRUE);
516         invokeMethod(findMethod(compilerConfigurationClass, "setJointCompilationOptions", Map.class), compilerConfiguration, options);
517 
518         return compilerConfiguration;
519     }
520 
521     protected void addGroovySources(final Set<File> stubSources, final Class<?> compilerConfigurationClass, final Class<?> javaStubCompilationUnitClass, final Object compilerConfiguration, final Object javaStubCompilationUnit) throws InvocationTargetException, IllegalAccessException {
522         // Since we don't have FileUtils here easily without dependencies, we can just use simple extension check.
523         // Wait, FileUtils is in util/FileUtils.java in this project.
524         // I should check if I can assume it is available. It is in the same package or similar.
525         // It's org.codehaus.gmavenplus.util.FileUtils.
526         // I will use it.
527 
528         Set<String> scriptExtensions = new java.util.HashSet<>();
529         for (File stubSource : stubSources) {
530             scriptExtensions.add(FileUtils.getFileExtension(stubSource));
531         }
532         log.debug("Detected Groovy file extensions: " + scriptExtensions + ".");
533         if (supportsSettingExtensions()) {
534             invokeMethod(findMethod(compilerConfigurationClass, "setScriptExtensions", Set.class), compilerConfiguration, scriptExtensions);
535         }
536         log.debug("Adding Groovy to generate stubs for:");
537         Method addSource = findMethod(javaStubCompilationUnitClass, "addSource", File.class);
538         for (File stubSource : stubSources) {
539             log.debug("    " + stubSource);
540             if (supportsSettingExtensions()) {
541                 invokeMethod(addSource, javaStubCompilationUnit, stubSource);
542             } else {
543                 // DotGroovyFile is in groovyworkarounds package.
544                 // org.codehaus.gmavenplus.groovyworkarounds.DotGroovyFile
545                 // I need to import it or use reflection? It is compiled code in this project, so I can import it.
546                 org.codehaus.gmavenplus.groovyworkarounds.DotGroovyFile dotGroovyFile = new org.codehaus.gmavenplus.groovyworkarounds.DotGroovyFile(stubSource).setScriptExtensions(scriptExtensions);
547                 invokeMethod(addSource, javaStubCompilationUnit, dotGroovyFile);
548             }
549         }
550     }
551 
552     protected boolean supportsStubGeneration() {
553         return ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_1_8_2);
554     }
555 
556     protected boolean supportsSettingExtensions() {
557         return ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_1_8_3) && (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_1_9_0_BETA1) || ClassWrangler.groovyNewerThan(classWrangler.getGroovyVersion(), GROOVY_1_9_0_BETA3));
558     }
559 
560     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 {
561         Object compilationUnit;
562         if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_1_6_0)) {
563             compilationUnit = invokeConstructor(findConstructor(compilationUnitClass, compilerConfigurationClass, CodeSource.class, groovyClassLoaderClass, groovyClassLoaderClass), compilerConfiguration, null, groovyClassLoader, transformLoader);
564         } else {
565             compilationUnit = invokeConstructor(findConstructor(compilationUnitClass, compilerConfigurationClass, CodeSource.class, groovyClassLoaderClass), compilerConfiguration, null, groovyClassLoader);
566         }
567         log.debug("Adding Groovy to compile:");
568         Method addSourceMethod = findMethod(compilationUnitClass, "addSource", File.class);
569         for (File source : sources) {
570             log.debug("    " + source);
571             invokeMethod(addSourceMethod, compilationUnit, source);
572         }
573 
574         return compilationUnit;
575     }
576 
577     @SuppressWarnings({"rawtypes", "unchecked"})
578     protected Object setupCompilerConfiguration(final GroovyCompileConfiguration configuration, final Class<?> compilerConfigurationClass) throws InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException {
579         Object compilerConfiguration = invokeConstructor(findConstructor(compilerConfigurationClass));
580         if (configuration.getConfigScript() != null) {
581             if (!configuration.getConfigScript().exists()) {
582                 log.warn("Configuration script file (" + configuration.getConfigScript().getAbsolutePath() + ") doesn't exist. Ignoring configScript parameter.");
583             } else if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_1_0_BETA1)) {
584                 log.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.");
585             } else {
586                 Class<?> bindingClass = classWrangler.getClass("groovy.lang.Binding");
587                 Class<?> importCustomizerClass = classWrangler.getClass("org.codehaus.groovy.control.customizers.ImportCustomizer");
588                 Class<?> groovyShellClass = classWrangler.getClass("groovy.lang.GroovyShell");
589 
590                 Object binding = invokeConstructor(findConstructor(bindingClass));
591                 invokeMethod(findMethod(bindingClass, "setVariable", String.class, Object.class), binding, "configuration", compilerConfiguration);
592                 Object shellCompilerConfiguration = invokeConstructor(findConstructor(compilerConfigurationClass));
593                 Object importCustomizer = invokeConstructor(findConstructor(importCustomizerClass));
594                 invokeMethod(findMethod(importCustomizerClass, "addStaticStar", String.class), importCustomizer, "org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder");
595                 List compilationCustomizers = (List) invokeMethod(findMethod(compilerConfigurationClass, "getCompilationCustomizers"), shellCompilerConfiguration);
596                 compilationCustomizers.add(importCustomizer);
597                 Object shell = invokeConstructor(findConstructor(groovyShellClass, ClassLoader.class, bindingClass, compilerConfigurationClass), classWrangler.getClassLoader(), binding, shellCompilerConfiguration);
598                 log.debug("Using configuration script " + configuration.getConfigScript() + " for compilation.");
599                 invokeMethod(findMethod(groovyShellClass, "evaluate", File.class), shell, configuration.getConfigScript());
600             }
601         }
602         invokeMethod(findMethod(compilerConfigurationClass, "setDebug", boolean.class), compilerConfiguration, configuration.isDebug());
603         invokeMethod(findMethod(compilerConfigurationClass, "setVerbose", boolean.class), compilerConfiguration, configuration.isVerbose());
604         invokeMethod(findMethod(compilerConfigurationClass, "setWarningLevel", int.class), compilerConfiguration, configuration.getWarningLevel());
605         invokeMethod(findMethod(compilerConfigurationClass, "setTolerance", int.class), compilerConfiguration, configuration.getTolerance());
606         invokeMethod(findMethod(compilerConfigurationClass, "setTargetBytecode", String.class), compilerConfiguration, translateJavacTargetToTargetBytecode(configuration.getTargetBytecode()));
607         if (configuration.isPreviewFeatures()) {
608             if (isJavaSupportPreviewFeatures()) {
609                 if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_5_7) || (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_2_6_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_0_BETA1))) {
610                     log.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.");
611                 } else {
612                     invokeMethod(findMethod(compilerConfigurationClass, "setPreviewFeatures", boolean.class), compilerConfiguration, configuration.isPreviewFeatures());
613                 }
614             } else {
615                 log.warn("Requested to use to use preview features, but your Java version (" + getJavaVersionString() + ") doesn't support it. Ignoring previewFeatures parameter.");
616             }
617         }
618         if (configuration.getSourceEncoding() != null) {
619             invokeMethod(findMethod(compilerConfigurationClass, "setSourceEncoding", String.class), compilerConfiguration, configuration.getSourceEncoding());
620         }
621         invokeMethod(findMethod(compilerConfigurationClass, "setTargetDirectory", String.class), compilerConfiguration, configuration.getCompileOutputDirectory().getAbsolutePath());
622         if (configuration.isInvokeDynamic() || ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_4_0_0_ALPHA1)) {
623             if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_2_0_0_BETA3)) {
624                 if (classWrangler.isGroovyIndy()) {
625                     if (isJavaSupportIndy()) {
626                         Map<String, Boolean> optimizationOptions = (Map<String, Boolean>) invokeMethod(findMethod(compilerConfigurationClass, "getOptimizationOptions"), compilerConfiguration);
627                         optimizationOptions.put("indy", true);
628                         optimizationOptions.put("int", false);
629                         log.info("invokedynamic enabled.");
630                     } else {
631                         log.warn("Requested to use to use invokedynamic, but your Java version (" + getJavaVersionString() + ") doesn't support it. Ignoring invokeDynamic parameter.");
632                     }
633                 } else {
634                     log.warn("Requested to use invokedynamic, but your Groovy version doesn't support it (must use have indy classifier). Ignoring invokeDynamic parameter.");
635                 }
636             } else {
637                 log.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.");
638             }
639         }
640         if (configuration.isParameters()) {
641             if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_2_5_0_ALPHA1)) {
642                 if (isJavaSupportParameters()) {
643                     invokeMethod(findMethod(compilerConfigurationClass, "setParameters", boolean.class), compilerConfiguration, configuration.isParameters());
644                 } else {
645                     log.warn("Requested to use to use parameters, but your Java version (" + getJavaVersionString() + ") doesn't support it. Ignoring parameters parameter.");
646                 }
647             } else {
648                 log.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.");
649             }
650         }
651         if (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_3_0_5)) {
652             if ((configuration.getParallelParsing() == null && ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_4_0_0_ALPHA1)) || (configuration.getParallelParsing() != null && configuration.getParallelParsing())) {
653                 Map<String, Boolean> optimizationOptions = (Map<String, Boolean>) invokeMethod(findMethod(compilerConfigurationClass, "getOptimizationOptions"), compilerConfiguration);
654                 optimizationOptions.put("parallelParse", true);
655                 log.info("Parallel parsing enabled.");
656             } else {
657                 log.info("Parallel parsing disabled.");
658             }
659         }
660 
661         return compilerConfiguration;
662     }
663 
664     protected void verifyGroovyVersionSupportsTargetBytecode(String targetBytecode) {
665         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)) {
666             if (ClassWrangler.groovyNewerThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA1)) {
667                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " isn't accepted by Groovy " + GROOVY_5_0_0_ALPHA1 + " or newer.");
668             }
669         }
670 
671         if ("25".equals(targetBytecode)) {
672             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_27)) {
673                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_27 + " or newer.");
674             }
675             if (ClassWrangler.groovyNewerThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA13)) {
676                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_5_0_0_ALPHA13 + " or newer.");
677             }
678         } else if ("24".equals(targetBytecode)) {
679             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_24)) {
680                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_24 + " or newer.");
681             }
682             if (ClassWrangler.groovyNewerThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA11)) {
683                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_5_0_0_ALPHA11 + " or newer.");
684             }
685         } else if ("23".equals(targetBytecode)) {
686             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_21)) {
687                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_21 + " or newer.");
688             }
689             if (ClassWrangler.groovyNewerThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA8)) {
690                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_5_0_0_ALPHA8 + " or newer.");
691             }
692         } else if ("22".equals(targetBytecode)) {
693             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_16)) {
694                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_16 + " or newer.");
695             }
696             if (ClassWrangler.groovyNewerThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_5_0_0_ALPHA3)) {
697                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_5_0_0_ALPHA3 + " or newer.");
698             }
699         } else if ("21".equals(targetBytecode)) {
700             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_11)) {
701                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_11 + " or newer.");
702             }
703         } else if ("20".equals(targetBytecode)) {
704             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_6)) {
705                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_6 + " or newer.");
706             }
707         } else if ("19".equals(targetBytecode)) {
708             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_2)) {
709                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_2 + " or newer.");
710             }
711         } else if ("18".equals(targetBytecode)) {
712             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_0_BETA1)) {
713                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_4_0_0_BETA1 + " or newer.");
714             }
715         } else if ("17".equals(targetBytecode)) {
716             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_8) || (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_4_0_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_4_0_0_ALPHA3))) {
717                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_3_0_8 + "/" + GROOVY_4_0_0_ALPHA3 + " or newer.");
718             }
719         } else if ("16".equals(targetBytecode)) {
720             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_6)) {
721                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_3_0_6 + " or newer.");
722             }
723         } else if ("15".equals(targetBytecode)) {
724             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_3)) {
725                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_3_0_3 + " or newer.");
726             }
727         } else if ("14".equals(targetBytecode)) {
728             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_0_BETA2)) {
729                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_3_0_0_BETA2 + " or newer.");
730             }
731         } else if ("13".equals(targetBytecode)) {
732             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_5_7) || (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_2_6_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_0_BETA1))) {
733                 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.");
734             }
735         } else if ("12".equals(targetBytecode) || "11".equals(targetBytecode) || "10".equals(targetBytecode)) {
736             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_5_3) || (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_2_6_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_0_ALPHA4))) {
737                 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.");
738             }
739         } else if ("9".equals(targetBytecode) || "1.9".equals(targetBytecode)) {
740             if (!classWrangler.isGroovyIndy() && (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_5_3)
741                     || (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_2_6_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_6_0_ALPHA4))
742                     || (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_3_0_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_0_ALPHA2)))) {
743                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_5_3 + "/" + GROOVY_2_6_0_ALPHA4 + "/" + GROOVY_3_0_0_ALPHA2 + " or newer.");
744             } else if (classWrangler.isGroovyIndy() && (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_5_3) || (ClassWrangler.groovyAtLeast(classWrangler.getGroovyVersion(), GROOVY_2_6_0_ALPHA1) && ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_3_0_0_ALPHA4)))) {
745                 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.");
746             }
747         } else if ("8".equals(targetBytecode) || "1.8".equals(targetBytecode)) {
748             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_3_3)) {
749                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_3_3 + " or newer.");
750             }
751         } else if ("7".equals(targetBytecode) || "1.7".equals(targetBytecode) || "6".equals(targetBytecode) || "1.6".equals(targetBytecode)) {
752             if (ClassWrangler.groovyOlderThan(classWrangler.getGroovyVersion(), GROOVY_2_1_3)) {
753                 throw new IllegalArgumentException("Target bytecode " + targetBytecode + " requires Groovy " + GROOVY_2_1_3 + " or newer.");
754             }
755         } else if (!"5".equals(targetBytecode) && !"1.5".equals(targetBytecode) && !"4".equals(targetBytecode) && !"1.4".equals(targetBytecode)) {
756             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.");
757         }
758     }
759 
760     public static String translateJavacTargetToTargetBytecode(String targetBytecode) {
761         Map<String, String> javacTargetToTargetBytecode = new HashMap<>();
762         javacTargetToTargetBytecode.put("5", "1.5");
763         javacTargetToTargetBytecode.put("6", "1.6");
764         javacTargetToTargetBytecode.put("7", "1.7");
765         javacTargetToTargetBytecode.put("8", "1.8");
766         javacTargetToTargetBytecode.put("1.9", "9");
767         return javacTargetToTargetBytecode.getOrDefault(targetBytecode, targetBytecode);
768     }
769 
770     protected boolean isJavaSupportIndy() {
771         return getJavaVersion().compareTo(JAVA_1_7, false) >= 0;
772     }
773 
774     protected boolean isJavaSupportPreviewFeatures() {
775         return getJavaVersion().compareTo(JAVA_12, false) >= 0;
776     }
777 
778     protected boolean isJavaSupportParameters() {
779         return getJavaVersion().compareTo(JAVA_1_8, false) >= 0;
780     }
781 
782     protected Version getJavaVersion() {
783         return Version.parseFromString(getJavaVersionString());
784     }
785 
786     protected String getJavaVersionString() {
787         return System.getProperty("java.version");
788     }
789 
790 }