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