1 package org.codehaus.plexus.compiler.ajc;
2
3 import javax.inject.Named;
4
5 import java.io.File;
6 import java.io.IOException;
7 import java.net.MalformedURLException;
8 import java.net.URL;
9 import java.net.URLClassLoader;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.HashSet;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17
18 import org.aspectj.ajdt.ajc.BuildArgParser;
19 import org.aspectj.ajdt.internal.core.builder.AjBuildConfig;
20 import org.aspectj.ajdt.internal.core.builder.AjBuildManager;
21 import org.aspectj.bridge.AbortException;
22 import org.aspectj.bridge.IMessage;
23 import org.aspectj.bridge.ISourceLocation;
24 import org.aspectj.bridge.MessageHandler;
25 import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
26 import org.aspectj.tools.ajc.Main;
27 import org.codehaus.plexus.compiler.AbstractCompiler;
28 import org.codehaus.plexus.compiler.CompilerConfiguration;
29 import org.codehaus.plexus.compiler.CompilerException;
30 import org.codehaus.plexus.compiler.CompilerMessage;
31 import org.codehaus.plexus.compiler.CompilerOutputStyle;
32 import org.codehaus.plexus.compiler.CompilerResult;
33 import org.codehaus.plexus.util.DirectoryScanner;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290 @Named("aspectj")
291 public class AspectJCompiler extends AbstractCompiler {
292
293
294
295
296
297 public AspectJCompiler() {
298
299
300 super(CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE, "", ".class", null);
301 }
302
303 @Override
304 public String getCompilerId() {
305 return "aspectj";
306 }
307
308 public CompilerResult performCompile(CompilerConfiguration config) throws CompilerException {
309 File destinationDir = new File(config.getOutputLocation());
310
311 if (!destinationDir.exists()) {
312 destinationDir.mkdirs();
313 }
314
315 String[] sourceFiles = getSourceFiles(config);
316
317 if (sourceFiles.length == 0) {
318 return new CompilerResult();
319 }
320
321 logCompiling(sourceFiles, config);
322
323
324 AjBuildConfig buildConfig = buildCompilerConfig(config);
325 return new CompilerResult().compilerMessages(compileInProcess(buildConfig));
326 }
327
328 private static class AspectJMessagePrinter extends Main.MessagePrinter {
329 public AspectJMessagePrinter(boolean verbose) {
330 super(verbose);
331 }
332 }
333
334 private AjBuildConfig buildCompilerConfig(CompilerConfiguration config) throws CompilerException {
335 BuildArgParser buildArgParser = new BuildArgParser(new AspectJMessagePrinter(config.isVerbose()));
336 AjBuildConfig buildConfig = new AjBuildConfig(buildArgParser);
337
338 buildArgParser.populateBuildConfig(buildConfig, new String[0], true, null);
339 buildConfig.setIncrementalMode(false);
340
341 String[] files = getSourceFiles(config);
342 if (files != null) {
343 buildConfig.setFiles(buildFileList(Arrays.asList(files)));
344 }
345
346 String releaseVersion = config.getReleaseVersion();
347 setSourceVersion(buildConfig, releaseVersion == null ? config.getSourceVersion() : releaseVersion);
348 setTargetVersion(buildConfig, releaseVersion == null ? config.getTargetVersion() : releaseVersion);
349
350 if (config.isDebug()) {
351 buildConfig.getOptions().produceDebugAttributes =
352 ClassFileConstants.ATTR_SOURCE + ClassFileConstants.ATTR_LINES + ClassFileConstants.ATTR_VARS;
353 }
354
355 Map<String, String> javaOpts = config.getCustomCompilerArgumentsAsMap();
356 if (javaOpts != null && !javaOpts.isEmpty()) {
357
358
359 }
360
361 List<String> cp = new LinkedList<>(config.getClasspathEntries());
362
363 File javaHomeDir = new File(System.getProperty("java.home"));
364 File[] jars = new File(javaHomeDir, "lib").listFiles();
365 if (jars != null) {
366 for (File jar : jars) {
367 if (jar.getName().endsWith(".jar") || jar.getName().endsWith(".zip")) {
368 cp.add(0, jar.getAbsolutePath());
369 }
370 }
371 }
372 jars = new File(javaHomeDir, "../Classes").listFiles();
373 if (jars != null) {
374 for (File jar : jars) {
375 if (jar.getName().endsWith(".jar") || jar.getName().endsWith(".zip")) {
376 cp.add(0, jar.getAbsolutePath());
377 }
378 }
379 }
380
381 checkForAspectJRT(cp);
382 if (cp != null && !cp.isEmpty()) {
383 List<String> elements = new ArrayList<>(cp.size());
384 for (String path : cp) {
385 elements.add((new File(path)).getAbsolutePath());
386 }
387
388 buildConfig.setClasspath(elements);
389 }
390
391 String outputLocation = config.getOutputLocation();
392 if (outputLocation != null) {
393 File outDir = new File(outputLocation);
394 if (!outDir.exists()) {
395 outDir.mkdirs();
396 }
397
398 buildConfig.setOutputDir(outDir);
399 }
400
401 if (config instanceof AspectJCompilerConfiguration) {
402 AspectJCompilerConfiguration ajCfg = (AspectJCompilerConfiguration) config;
403
404 Map<String, File> sourcePathResources = ajCfg.getSourcePathResources();
405 if (sourcePathResources != null && !sourcePathResources.isEmpty()) {
406 buildConfig.setSourcePathResources(sourcePathResources);
407 }
408
409 Map<String, String> ajOptions = ajCfg.getAJOptions();
410 if (ajOptions != null && !ajOptions.isEmpty()) {
411
412
413 }
414
415 List<File> aspectPath = buildFileList(ajCfg.getAspectPath());
416 if (aspectPath != null && !aspectPath.isEmpty()) {
417 buildConfig.setAspectpath(buildFileList(ajCfg.getAspectPath()));
418 }
419
420 List<File> inJars = buildFileList(ajCfg.getInJars());
421 if (inJars != null && !inJars.isEmpty()) {
422 buildConfig.setInJars(buildFileList(ajCfg.getInJars()));
423 }
424
425 List<File> inPaths = buildFileList(ajCfg.getInPath());
426 if (inPaths != null && !inPaths.isEmpty()) {
427 buildConfig.setInPath(buildFileList(ajCfg.getInPath()));
428 }
429
430 String outJar = ajCfg.getOutputJar();
431 if (outJar != null) {
432 buildConfig.setOutputJar(new File(ajCfg.getOutputJar()));
433 }
434 }
435
436 return buildConfig;
437 }
438
439 private List<CompilerMessage> compileInProcess(AjBuildConfig buildConfig) throws CompilerException {
440
441 MessageHandler messageHandler = new MessageHandler();
442
443 AjBuildManager manager = new AjBuildManager(messageHandler);
444
445 try {
446 manager.batchBuild(buildConfig, messageHandler);
447 } catch (AbortException | IOException e) {
448 throw new CompilerException("Unknown error while compiling", e);
449 }
450
451
452
453
454
455
456
457
458
459
460 boolean errors = messageHandler.hasAnyMessage(IMessage.ERROR, true);
461
462 List<CompilerMessage> messages = new ArrayList<>();
463 if (errors) {
464 IMessage[] errorMessages = messageHandler.getMessages(IMessage.ERROR, true);
465
466 for (IMessage m : errorMessages) {
467 ISourceLocation sourceLocation = m.getSourceLocation();
468 CompilerMessage error;
469
470 if (sourceLocation == null) {
471 error = new CompilerMessage(m.getMessage(), true);
472 } else {
473 error = new CompilerMessage(
474 sourceLocation.getSourceFile().getPath(),
475 true,
476 sourceLocation.getLine(),
477 sourceLocation.getColumn(),
478 sourceLocation.getEndLine(),
479 sourceLocation.getColumn(),
480 m.getMessage());
481 }
482 messages.add(error);
483 }
484 }
485
486 return messages;
487 }
488
489 private void checkForAspectJRT(List<String> cp) {
490 if (cp == null || cp.isEmpty()) {
491 throw new IllegalStateException("AspectJ Runtime not found in supplied classpath");
492 } else {
493 try {
494 URL[] urls = new URL[cp.size()];
495 for (int i = 0; i < urls.length; i++) {
496 urls[i] = (new File(cp.get(i))).toURL();
497 }
498
499 URLClassLoader cloader = new URLClassLoader(urls);
500
501 cloader.loadClass("org.aspectj.lang.JoinPoint");
502 } catch (MalformedURLException e) {
503 throw new IllegalArgumentException("Invalid classpath entry");
504 } catch (ClassNotFoundException e) {
505 throw new IllegalStateException("AspectJ Runtime not found in supplied classpath");
506 }
507 }
508 }
509
510 private List<File> buildFileList(List<String> locations) {
511 List<File> fileList = new LinkedList<>();
512 for (String location : locations) {
513 fileList.add(new File(location));
514 }
515
516 return fileList;
517 }
518
519
520
521
522
523
524
525 private void setSourceVersion(AjBuildConfig buildConfig, String sourceVersion) throws CompilerException {
526 buildConfig.getOptions().sourceLevel = versionStringToMajorMinor(sourceVersion);
527 }
528
529
530
531
532
533
534
535 private void setTargetVersion(AjBuildConfig buildConfig, String targetVersion) throws CompilerException {
536 buildConfig.getOptions().targetJDK = versionStringToMajorMinor(targetVersion);
537 }
538
539 private static long versionStringToMajorMinor(String version) throws CompilerException {
540 if (version == null) {
541 version = "";
542 }
543
544
545
546
547 version = version.trim()
548
549 .replaceFirst("^1[.]", "")
550
551 .replaceFirst("[.]0$", "");
552
553 switch (version) {
554
555
556 case "":
557 return ClassFileConstants.JDK1_6;
558 case "1":
559 return ClassFileConstants.JDK1_1;
560 case "2":
561 return ClassFileConstants.JDK1_2;
562 case "3":
563 return ClassFileConstants.JDK1_3;
564 case "4":
565 return ClassFileConstants.JDK1_4;
566 case "5":
567 return ClassFileConstants.JDK1_5;
568 case "6":
569 return ClassFileConstants.JDK1_6;
570 case "7":
571 return ClassFileConstants.JDK1_7;
572 case "8":
573 return ClassFileConstants.JDK1_8;
574 case "9":
575 return ClassFileConstants.JDK9;
576 case "10":
577 return ClassFileConstants.JDK10;
578 case "11":
579 return ClassFileConstants.JDK11;
580 case "12":
581 return ClassFileConstants.JDK12;
582 case "13":
583 return ClassFileConstants.JDK13;
584 case "14":
585 return ClassFileConstants.JDK14;
586 case "15":
587 return ClassFileConstants.JDK15;
588 case "16":
589 return ClassFileConstants.JDK16;
590 }
591 throw new CompilerException("Unknown Java source/target version number: " + version);
592 }
593
594
595
596
597 public String[] createCommandLine(CompilerConfiguration config) throws CompilerException {
598 return null;
599 }
600
601 protected static String[] getSourceFiles(CompilerConfiguration config) {
602 Set<String> sources = new HashSet<>();
603
604 Set<File> sourceFiles = config.getSourceFiles();
605
606 if (sourceFiles != null && !sourceFiles.isEmpty()) {
607 for (File sourceFile : sourceFiles) {
608 if (sourceFile.getName().endsWith(".java")
609 || sourceFile.getName().endsWith(".aj")) {
610 sources.add(sourceFile.getAbsolutePath());
611 }
612 }
613 } else {
614 for (String sourceLocation : config.getSourceLocations()) {
615 sources.addAll(getSourceFilesForSourceRoot(config, sourceLocation));
616 }
617 }
618
619 String[] result;
620
621 if (sources.isEmpty()) {
622 result = new String[0];
623 } else {
624 result = sources.toArray(new String[sources.size()]);
625 }
626
627 return result;
628 }
629
630 protected static Set<String> getSourceFilesForSourceRoot(CompilerConfiguration config, String sourceLocation) {
631 DirectoryScanner scanner = new DirectoryScanner();
632
633 scanner.setBasedir(sourceLocation);
634
635 Set<String> includes = config.getIncludes();
636
637 if (includes != null && !includes.isEmpty()) {
638 String[] inclStrs = includes.toArray(new String[includes.size()]);
639 scanner.setIncludes(inclStrs);
640 } else {
641 scanner.setIncludes(new String[] {"**/*.java", "**/*.aj"});
642 }
643
644 Set<String> excludes = config.getExcludes();
645
646 if (excludes != null && !excludes.isEmpty()) {
647 String[] exclStrs = excludes.toArray(new String[excludes.size()]);
648 scanner.setExcludes(exclStrs);
649 }
650
651 scanner.scan();
652
653 String[] sourceDirectorySources = scanner.getIncludedFiles();
654
655 Set<String> sources = new HashSet<>();
656
657 for (String sourceDirectorySource : sourceDirectorySources) {
658 File f = new File(sourceLocation, sourceDirectorySource);
659
660 sources.add(f.getPath());
661 }
662
663 return sources;
664 }
665 }