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 return switch (version) {
554
555
556 case "" -> ClassFileConstants.JDK1_6;
557 case "1" -> ClassFileConstants.JDK1_1;
558 case "2" -> ClassFileConstants.JDK1_2;
559 case "3" -> ClassFileConstants.JDK1_3;
560 case "4" -> ClassFileConstants.JDK1_4;
561 case "5" -> ClassFileConstants.JDK1_5;
562 case "6" -> ClassFileConstants.JDK1_6;
563 case "7" -> ClassFileConstants.JDK1_7;
564 case "8" -> ClassFileConstants.JDK1_8;
565 case "9" -> ClassFileConstants.JDK9;
566 case "10" -> ClassFileConstants.JDK10;
567 case "11" -> ClassFileConstants.JDK11;
568 case "12" -> ClassFileConstants.JDK12;
569 case "13" -> ClassFileConstants.JDK13;
570 case "14" -> ClassFileConstants.JDK14;
571 case "15" -> ClassFileConstants.JDK15;
572 case "16" -> ClassFileConstants.JDK16;
573 case "17" -> ClassFileConstants.JDK17;
574 case "18" -> ClassFileConstants.JDK18;
575 case "19" -> ClassFileConstants.JDK19;
576 case "20" -> ClassFileConstants.JDK20;
577 case "21" -> ClassFileConstants.JDK21;
578 default -> throw new CompilerException("Unknown Java source/target version number: " + version);
579 };
580 }
581
582
583
584
585 public String[] createCommandLine(CompilerConfiguration config) throws CompilerException {
586 return null;
587 }
588
589 protected static String[] getSourceFiles(CompilerConfiguration config) {
590 Set<String> sources = new HashSet<>();
591
592 Set<File> sourceFiles = config.getSourceFiles();
593
594 if (sourceFiles != null && !sourceFiles.isEmpty()) {
595 for (File sourceFile : sourceFiles) {
596 if (sourceFile.getName().endsWith(".java")
597 || sourceFile.getName().endsWith(".aj")) {
598 sources.add(sourceFile.getAbsolutePath());
599 }
600 }
601 } else {
602 for (String sourceLocation : config.getSourceLocations()) {
603 sources.addAll(getSourceFilesForSourceRoot(config, sourceLocation));
604 }
605 }
606
607 String[] result;
608
609 if (sources.isEmpty()) {
610 result = new String[0];
611 } else {
612 result = sources.toArray(new String[sources.size()]);
613 }
614
615 return result;
616 }
617
618 protected static Set<String> getSourceFilesForSourceRoot(CompilerConfiguration config, String sourceLocation) {
619 DirectoryScanner scanner = new DirectoryScanner();
620
621 scanner.setBasedir(sourceLocation);
622
623 Set<String> includes = config.getIncludes();
624
625 if (includes != null && !includes.isEmpty()) {
626 String[] inclStrs = includes.toArray(new String[includes.size()]);
627 scanner.setIncludes(inclStrs);
628 } else {
629 scanner.setIncludes(new String[] {"**/*.java", "**/*.aj"});
630 }
631
632 Set<String> excludes = config.getExcludes();
633
634 if (excludes != null && !excludes.isEmpty()) {
635 String[] exclStrs = excludes.toArray(new String[excludes.size()]);
636 scanner.setExcludes(exclStrs);
637 }
638
639 scanner.scan();
640
641 String[] sourceDirectorySources = scanner.getIncludedFiles();
642
643 Set<String> sources = new HashSet<>();
644
645 for (String sourceDirectorySource : sourceDirectorySources) {
646 File f = new File(sourceLocation, sourceDirectorySource);
647
648 sources.add(f.getPath());
649 }
650
651 return sources;
652 }
653 }