1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.compiler;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26 import java.nio.charset.Charset;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collections;
33 import java.util.Date;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.LinkedHashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Properties;
40 import java.util.Set;
41
42 import org.apache.maven.artifact.handler.ArtifactHandler;
43 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
44 import org.apache.maven.execution.MavenExecutionRequest;
45 import org.apache.maven.execution.MavenSession;
46 import org.apache.maven.plugin.AbstractMojo;
47 import org.apache.maven.plugin.MojoExecution;
48 import org.apache.maven.plugin.MojoExecutionException;
49 import org.apache.maven.plugins.annotations.Component;
50 import org.apache.maven.plugins.annotations.Parameter;
51 import org.apache.maven.project.MavenProject;
52 import org.apache.maven.shared.incremental.IncrementalBuildHelper;
53 import org.apache.maven.shared.incremental.IncrementalBuildHelperRequest;
54 import org.apache.maven.shared.utils.ReaderFactory;
55 import org.apache.maven.shared.utils.StringUtils;
56 import org.apache.maven.shared.utils.io.DirectoryScanResult;
57 import org.apache.maven.shared.utils.io.DirectoryScanner;
58 import org.apache.maven.shared.utils.io.FileUtils;
59 import org.apache.maven.shared.utils.logging.MessageBuilder;
60 import org.apache.maven.shared.utils.logging.MessageUtils;
61 import org.apache.maven.toolchain.Toolchain;
62 import org.apache.maven.toolchain.ToolchainManager;
63 import org.codehaus.plexus.compiler.Compiler;
64 import org.codehaus.plexus.compiler.CompilerConfiguration;
65 import org.codehaus.plexus.compiler.CompilerException;
66 import org.codehaus.plexus.compiler.CompilerMessage;
67 import org.codehaus.plexus.compiler.CompilerOutputStyle;
68 import org.codehaus.plexus.compiler.CompilerResult;
69 import org.codehaus.plexus.compiler.manager.CompilerManager;
70 import org.codehaus.plexus.compiler.manager.NoSuchCompilerException;
71 import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
72 import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
73 import org.codehaus.plexus.compiler.util.scan.mapping.SingleTargetSourceMapping;
74 import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
75 import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
76 import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
77 import org.codehaus.plexus.languages.java.version.JavaVersion;
78 import org.eclipse.aether.RepositorySystem;
79 import org.eclipse.aether.artifact.Artifact;
80 import org.eclipse.aether.artifact.DefaultArtifact;
81 import org.eclipse.aether.collection.CollectRequest;
82 import org.eclipse.aether.graph.Dependency;
83 import org.eclipse.aether.graph.Exclusion;
84 import org.eclipse.aether.resolution.ArtifactResult;
85 import org.eclipse.aether.resolution.DependencyRequest;
86 import org.eclipse.aether.resolution.DependencyResult;
87 import org.eclipse.aether.util.artifact.JavaScopes;
88 import org.objectweb.asm.ClassWriter;
89 import org.objectweb.asm.Opcodes;
90
91
92
93
94
95
96
97
98
99
100
101 public abstract class AbstractCompilerMojo extends AbstractMojo {
102 protected static final String PS = System.getProperty("path.separator");
103
104 private static final String INPUT_FILES_LST_FILENAME = "inputFiles.lst";
105
106 static final String DEFAULT_SOURCE = "1.8";
107
108 static final String DEFAULT_TARGET = "1.8";
109
110
111 static final String MODULE_INFO_TARGET = "1.9";
112
113
114
115
116
117
118
119
120
121
122 @Parameter(property = "maven.compiler.failOnError", defaultValue = "true")
123 private boolean failOnError = true;
124
125
126
127
128
129
130 @Parameter(property = "maven.compiler.failOnWarning", defaultValue = "false")
131 private boolean failOnWarning;
132
133
134
135
136 @Parameter(property = "maven.compiler.debug", defaultValue = "true")
137 private boolean debug = true;
138
139
140
141
142
143 @Parameter(property = "maven.compiler.parameters", defaultValue = "false")
144 private boolean parameters;
145
146
147
148
149
150 @Parameter(property = "maven.compiler.enablePreview", defaultValue = "false")
151 private boolean enablePreview;
152
153
154
155
156 @Parameter(property = "maven.compiler.verbose", defaultValue = "false")
157 private boolean verbose;
158
159
160
161
162 @Parameter(property = "maven.compiler.showDeprecation", defaultValue = "false")
163 private boolean showDeprecation;
164
165
166
167
168
169 @Deprecated
170 @Parameter(property = "maven.compiler.optimize", defaultValue = "false")
171 private boolean optimize;
172
173
174
175
176 @Parameter(property = "maven.compiler.showWarnings", defaultValue = "true")
177 private boolean showWarnings;
178
179
180
181
182
183
184
185
186
187 @Parameter(property = "maven.compiler.source", defaultValue = DEFAULT_SOURCE)
188 protected String source;
189
190
191
192
193
194
195
196
197
198 @Parameter(property = "maven.compiler.target", defaultValue = DEFAULT_TARGET)
199 protected String target;
200
201
202
203
204
205
206 @Parameter(property = "maven.compiler.release")
207 protected String release;
208
209
210
211
212
213
214 @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
215 private String encoding;
216
217
218
219
220
221 @Parameter(property = "lastModGranularityMs", defaultValue = "0")
222 private int staleMillis;
223
224
225
226
227
228 @Parameter(property = "maven.compiler.compilerId", defaultValue = "javac")
229 private String compilerId;
230
231
232
233
234 @Parameter(property = "maven.compiler.compilerVersion")
235 private String compilerVersion;
236
237
238
239
240
241 @Parameter(property = "maven.compiler.fork", defaultValue = "false")
242 private boolean fork;
243
244
245
246
247
248
249
250 @Parameter(property = "maven.compiler.meminitial")
251 private String meminitial;
252
253
254
255
256
257
258
259 @Parameter(property = "maven.compiler.maxmem")
260 private String maxmem;
261
262
263
264
265 @Parameter(property = "maven.compiler.executable")
266 private String executable;
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 @Parameter
282 private String proc;
283
284
285
286
287
288
289
290
291
292 @Parameter
293 private String[] annotationProcessors;
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330 @Parameter
331 private List<DependencyCoordinate> annotationProcessorPaths;
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359 @Parameter
360 @Deprecated
361 protected Map<String, String> compilerArguments;
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382 @Parameter
383 protected List<String> compilerArgs;
384
385
386
387
388
389
390
391
392
393
394
395
396
397 @Parameter
398 protected String compilerArgument;
399
400
401
402
403
404
405
406 @Parameter
407 private String outputFileName;
408
409
410
411
412
413
414
415
416
417 @Parameter(property = "maven.compiler.debuglevel")
418 private String debuglevel;
419
420
421
422
423
424
425 @Parameter(property = "maven.compiler.implicit")
426 private String implicit;
427
428
429
430
431 @Component
432 private ToolchainManager toolchainManager;
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463 @Parameter
464 private Map<String, String> jdkToolchain;
465
466
467
468
469
470
471
472
473 @Parameter(defaultValue = "${basedir}", required = true, readonly = true)
474 private File basedir;
475
476
477
478
479 @Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true)
480 private File buildDirectory;
481
482
483
484
485 @Component
486 private CompilerManager compilerManager;
487
488
489
490
491 @Parameter(defaultValue = "${session}", readonly = true, required = true)
492 private MavenSession session;
493
494
495
496
497
498 @Parameter(defaultValue = "${project}", readonly = true, required = true)
499 private MavenProject project;
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514 @Parameter(defaultValue = "${reuseCreated}", property = "maven.compiler.compilerReuseStrategy")
515 private String compilerReuseStrategy = "reuseCreated";
516
517
518
519
520 @Parameter(defaultValue = "false", property = "maven.compiler.skipMultiThreadWarning")
521 private boolean skipMultiThreadWarning;
522
523
524
525
526
527
528
529 @Parameter(defaultValue = "false", property = "maven.compiler.forceJavacCompilerUse")
530 private boolean forceJavacCompilerUse;
531
532
533
534
535 @Parameter(defaultValue = "${mojoExecution}", readonly = true, required = true)
536 private MojoExecution mojoExecution;
537
538
539
540
541
542
543
544 @Parameter
545 private List<String> fileExtensions;
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563 @Parameter(defaultValue = "true", property = "maven.compiler.useIncrementalCompilation")
564 private boolean useIncrementalCompilation = true;
565
566
567
568
569
570
571
572
573
574
575 @Parameter(defaultValue = "true", property = "maven.compiler.createMissingPackageInfoClass")
576 private boolean createMissingPackageInfoClass = true;
577
578 @Parameter(defaultValue = "false", property = "maven.compiler.showCompilationChanges")
579 private boolean showCompilationChanges = false;
580
581
582
583 @Component
584 private RepositorySystem repositorySystem;
585
586
587
588
589 @Component
590 private ArtifactHandlerManager artifactHandlerManager;
591
592 protected abstract SourceInclusionScanner getSourceInclusionScanner(int staleMillis);
593
594 protected abstract SourceInclusionScanner getSourceInclusionScanner(String inputFileEnding);
595
596 protected abstract List<String> getClasspathElements();
597
598 protected abstract List<String> getModulepathElements();
599
600 protected abstract Map<String, JavaModuleDescriptor> getPathElements();
601
602 protected abstract List<String> getCompileSourceRoots();
603
604 protected abstract void preparePaths(Set<File> sourceFiles);
605
606 protected abstract File getOutputDirectory();
607
608 protected abstract String getSource();
609
610 protected abstract String getTarget();
611
612 protected abstract String getRelease();
613
614 protected abstract String getCompilerArgument();
615
616 protected abstract Map<String, String> getCompilerArguments();
617
618 protected abstract File getGeneratedSourcesDirectory();
619
620 protected abstract String getDebugFileName();
621
622 protected final MavenProject getProject() {
623 return project;
624 }
625
626 private boolean targetOrReleaseSet;
627
628 @Override
629 public void execute() throws MojoExecutionException, CompilationFailureException {
630
631
632
633
634
635
636 Compiler compiler;
637
638 getLog().debug("Using compiler '" + compilerId + "'.");
639
640 try {
641 compiler = compilerManager.getCompiler(compilerId);
642 } catch (NoSuchCompilerException e) {
643 throw new MojoExecutionException("No such compiler '" + e.getCompilerId() + "'.");
644 }
645
646
647
648 Toolchain tc = getToolchain();
649 if (tc != null) {
650 getLog().info("Toolchain in maven-compiler-plugin: " + tc);
651 if (executable != null) {
652 getLog().warn("Toolchains are ignored, 'executable' parameter is set to " + executable);
653 } else {
654 fork = true;
655
656 executable = tc.findTool(compilerId);
657 }
658 }
659
660
661
662
663 List<String> compileSourceRoots = removeEmptyCompileSourceRoots(getCompileSourceRoots());
664
665 if (compileSourceRoots.isEmpty()) {
666 getLog().info("No sources to compile");
667
668 return;
669 }
670
671
672 if (!targetOrReleaseSet) {
673 MessageBuilder mb = MessageUtils.buffer()
674 .a("No explicit value set for target or release! ")
675 .a("To ensure the same result even after upgrading this plugin, please add ")
676 .newline()
677 .newline();
678
679 writePlugin(mb);
680
681 getLog().warn(mb.toString());
682 }
683
684
685
686
687
688 CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
689
690 compilerConfiguration.setOutputLocation(getOutputDirectory().getAbsolutePath());
691
692 compilerConfiguration.setOptimize(optimize);
693
694 compilerConfiguration.setDebug(debug);
695
696 compilerConfiguration.setDebugFileName(getDebugFileName());
697
698 compilerConfiguration.setImplicitOption(implicit);
699
700 if (debug && StringUtils.isNotEmpty(debuglevel)) {
701 String[] split = StringUtils.split(debuglevel, ",");
702 for (String aSplit : split) {
703 if (!(aSplit.equalsIgnoreCase("none")
704 || aSplit.equalsIgnoreCase("lines")
705 || aSplit.equalsIgnoreCase("vars")
706 || aSplit.equalsIgnoreCase("source"))) {
707 throw new IllegalArgumentException("The specified debug level: '" + aSplit + "' is unsupported. "
708 + "Legal values are 'none', 'lines', 'vars', and 'source'.");
709 }
710 }
711 compilerConfiguration.setDebugLevel(debuglevel);
712 }
713
714 compilerConfiguration.setParameters(parameters);
715
716 compilerConfiguration.setEnablePreview(enablePreview);
717
718 compilerConfiguration.setVerbose(verbose);
719
720 compilerConfiguration.setShowWarnings(showWarnings);
721
722 compilerConfiguration.setFailOnWarning(failOnWarning);
723
724 if (failOnWarning && !showWarnings) {
725 getLog().warn("The property failOnWarning is set to true, but showWarnings is set to false.");
726 getLog().warn("With compiler's warnings silenced the failOnWarning has no effect.");
727 }
728
729 compilerConfiguration.setShowDeprecation(showDeprecation);
730
731 compilerConfiguration.setSourceVersion(getSource());
732
733 compilerConfiguration.setTargetVersion(getTarget());
734
735 compilerConfiguration.setReleaseVersion(getRelease());
736
737 compilerConfiguration.setProc(proc);
738
739 File generatedSourcesDirectory = getGeneratedSourcesDirectory();
740 compilerConfiguration.setGeneratedSourcesDirectory(
741 generatedSourcesDirectory != null ? generatedSourcesDirectory.getAbsoluteFile() : null);
742
743 if (generatedSourcesDirectory != null) {
744 if (!generatedSourcesDirectory.exists()) {
745 generatedSourcesDirectory.mkdirs();
746 }
747
748 String generatedSourcesPath = generatedSourcesDirectory.getAbsolutePath();
749
750 compileSourceRoots.add(generatedSourcesPath);
751
752 if (isTestCompile()) {
753 getLog().debug("Adding " + generatedSourcesPath + " to test-compile source roots:\n "
754 + StringUtils.join(project.getTestCompileSourceRoots().iterator(), "\n "));
755
756 project.addTestCompileSourceRoot(generatedSourcesPath);
757
758 getLog().debug("New test-compile source roots:\n "
759 + StringUtils.join(project.getTestCompileSourceRoots().iterator(), "\n "));
760 } else {
761 getLog().debug("Adding " + generatedSourcesPath + " to compile source roots:\n "
762 + StringUtils.join(project.getCompileSourceRoots().iterator(), "\n "));
763
764 project.addCompileSourceRoot(generatedSourcesPath);
765
766 getLog().debug("New compile source roots:\n "
767 + StringUtils.join(project.getCompileSourceRoots().iterator(), "\n "));
768 }
769 }
770
771 compilerConfiguration.setSourceLocations(compileSourceRoots);
772
773 compilerConfiguration.setAnnotationProcessors(annotationProcessors);
774
775 compilerConfiguration.setProcessorPathEntries(resolveProcessorPathEntries());
776
777 compilerConfiguration.setSourceEncoding(encoding);
778
779 compilerConfiguration.setFork(fork);
780
781 if (fork) {
782 if (!StringUtils.isEmpty(meminitial)) {
783 String value = getMemoryValue(meminitial);
784
785 if (value != null) {
786 compilerConfiguration.setMeminitial(value);
787 } else {
788 getLog().info("Invalid value for meminitial '" + meminitial + "'. Ignoring this option.");
789 }
790 }
791
792 if (!StringUtils.isEmpty(maxmem)) {
793 String value = getMemoryValue(maxmem);
794
795 if (value != null) {
796 compilerConfiguration.setMaxmem(value);
797 } else {
798 getLog().info("Invalid value for maxmem '" + maxmem + "'. Ignoring this option.");
799 }
800 }
801 }
802
803 compilerConfiguration.setExecutable(executable);
804
805 compilerConfiguration.setWorkingDirectory(basedir);
806
807 compilerConfiguration.setCompilerVersion(compilerVersion);
808
809 compilerConfiguration.setBuildDirectory(buildDirectory);
810
811 compilerConfiguration.setOutputFileName(outputFileName);
812
813 if (CompilerConfiguration.CompilerReuseStrategy.AlwaysNew.getStrategy().equals(this.compilerReuseStrategy)) {
814 compilerConfiguration.setCompilerReuseStrategy(CompilerConfiguration.CompilerReuseStrategy.AlwaysNew);
815 } else if (CompilerConfiguration.CompilerReuseStrategy.ReuseSame.getStrategy()
816 .equals(this.compilerReuseStrategy)) {
817 if (getRequestThreadCount() > 1) {
818 if (!skipMultiThreadWarning) {
819 getLog().warn("You are in a multi-thread build and compilerReuseStrategy is set to reuseSame."
820 + " This can cause issues in some environments (os/jdk)!"
821 + " Consider using reuseCreated strategy."
822 + System.getProperty("line.separator")
823 + "If your env is fine with reuseSame, you can skip this warning with the "
824 + "configuration field skipMultiThreadWarning "
825 + "or -Dmaven.compiler.skipMultiThreadWarning=true");
826 }
827 }
828 compilerConfiguration.setCompilerReuseStrategy(CompilerConfiguration.CompilerReuseStrategy.ReuseSame);
829 } else {
830
831 compilerConfiguration.setCompilerReuseStrategy(CompilerConfiguration.CompilerReuseStrategy.ReuseCreated);
832 }
833
834 getLog().debug("CompilerReuseStrategy: "
835 + compilerConfiguration.getCompilerReuseStrategy().getStrategy());
836
837 compilerConfiguration.setForceJavacCompilerUse(forceJavacCompilerUse);
838
839 boolean canUpdateTarget;
840
841 IncrementalBuildHelper incrementalBuildHelper = new IncrementalBuildHelper(mojoExecution, session);
842
843 final Set<File> sources;
844
845 IncrementalBuildHelperRequest incrementalBuildHelperRequest = null;
846
847 if (useIncrementalCompilation) {
848 getLog().debug("useIncrementalCompilation enabled");
849 try {
850 canUpdateTarget = compiler.canUpdateTarget(compilerConfiguration);
851
852 sources = getCompileSources(compiler, compilerConfiguration);
853
854 preparePaths(sources);
855
856 incrementalBuildHelperRequest = new IncrementalBuildHelperRequest().inputFiles(sources);
857
858 DirectoryScanResult dsr = computeInputFileTreeChanges(incrementalBuildHelper, sources);
859
860 boolean idk = compiler.getCompilerOutputStyle()
861 .equals(CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES)
862 && !canUpdateTarget;
863 boolean dependencyChanged = isDependencyChanged();
864 boolean sourceChanged = isSourceChanged(compilerConfiguration, compiler);
865 boolean inputFileTreeChanged = hasInputFileTreeChanged(dsr);
866
867 if (idk || dependencyChanged || sourceChanged || inputFileTreeChanged)
868
869 {
870 String cause = idk
871 ? "idk"
872 : (dependencyChanged ? "dependency" : (sourceChanged ? "source" : "input tree"));
873 getLog().info("Changes detected - recompiling the module! :" + cause);
874 if (showCompilationChanges) {
875 for (String fileAdded : dsr.getFilesAdded()) {
876 getLog().info("\t+ " + fileAdded);
877 }
878 for (String fileRemoved : dsr.getFilesRemoved()) {
879 getLog().info("\t- " + fileRemoved);
880 }
881 }
882
883 compilerConfiguration.setSourceFiles(sources);
884 } else {
885 getLog().info("Nothing to compile - all classes are up to date");
886
887 return;
888 }
889 } catch (CompilerException e) {
890 throw new MojoExecutionException("Error while computing stale sources.", e);
891 }
892 } else {
893 getLog().debug("useIncrementalCompilation disabled");
894
895 Set<File> staleSources;
896 try {
897 staleSources =
898 computeStaleSources(compilerConfiguration, compiler, getSourceInclusionScanner(staleMillis));
899
900 canUpdateTarget = compiler.canUpdateTarget(compilerConfiguration);
901
902 if (compiler.getCompilerOutputStyle().equals(CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES)
903 && !canUpdateTarget) {
904 getLog().info("RESCANNING!");
905
906 String inputFileEnding = compiler.getInputFileEnding(compilerConfiguration);
907
908 staleSources = computeStaleSources(
909 compilerConfiguration, compiler, getSourceInclusionScanner(inputFileEnding));
910 }
911
912 } catch (CompilerException e) {
913 throw new MojoExecutionException("Error while computing stale sources.", e);
914 }
915
916 if (staleSources.isEmpty()) {
917 getLog().info("Nothing to compile - all classes are up to date");
918
919 return;
920 }
921
922 compilerConfiguration.setSourceFiles(staleSources);
923
924 try {
925
926 sources = getCompileSources(compiler, compilerConfiguration);
927
928 if (getLog().isDebugEnabled()) {
929 getLog().debug("#sources: " + sources.size());
930 for (File file : sources) {
931 getLog().debug(file.getPath());
932 }
933 }
934
935 preparePaths(sources);
936 } catch (CompilerException e) {
937 throw new MojoExecutionException("Error while computing stale sources.", e);
938 }
939 }
940
941
942 compilerConfiguration.setClasspathEntries(getClasspathElements());
943
944 compilerConfiguration.setModulepathEntries(getModulepathElements());
945
946 compilerConfiguration.setIncludes(getIncludes());
947
948 compilerConfiguration.setExcludes(getExcludes());
949
950 Map<String, String> effectiveCompilerArguments = getCompilerArguments();
951
952 String effectiveCompilerArgument = getCompilerArgument();
953
954 if ((effectiveCompilerArguments != null) || (effectiveCompilerArgument != null) || (compilerArgs != null)) {
955 if (effectiveCompilerArguments != null) {
956 for (Map.Entry<String, String> me : effectiveCompilerArguments.entrySet()) {
957 String key = me.getKey();
958 String value = me.getValue();
959 if (!key.startsWith("-")) {
960 key = "-" + key;
961 }
962
963 if (key.startsWith("-A") && StringUtils.isNotEmpty(value)) {
964 compilerConfiguration.addCompilerCustomArgument(key + "=" + value, null);
965 } else {
966 compilerConfiguration.addCompilerCustomArgument(key, value);
967 }
968 }
969 }
970 if (!StringUtils.isEmpty(effectiveCompilerArgument)) {
971 compilerConfiguration.addCompilerCustomArgument(effectiveCompilerArgument, null);
972 }
973 if (compilerArgs != null) {
974 for (String arg : compilerArgs) {
975 compilerConfiguration.addCompilerCustomArgument(arg, null);
976 }
977 }
978 }
979
980
981
982
983 if (getLog().isDebugEnabled()) {
984 getLog().debug("Classpath:");
985
986 for (String s : getClasspathElements()) {
987 getLog().debug(" " + s);
988 }
989
990 if (!getModulepathElements().isEmpty()) {
991 getLog().debug("Modulepath:");
992 for (String s : getModulepathElements()) {
993 getLog().debug(" " + s);
994 }
995 }
996
997 getLog().debug("Source roots:");
998
999 for (String root : getCompileSourceRoots()) {
1000 getLog().debug(" " + root);
1001 }
1002
1003 try {
1004 if (fork) {
1005 if (compilerConfiguration.getExecutable() != null) {
1006 getLog().debug("Excutable: ");
1007 getLog().debug(" " + compilerConfiguration.getExecutable());
1008 }
1009 }
1010
1011 String[] cl = compiler.createCommandLine(compilerConfiguration);
1012 if (cl != null && cl.length > 0) {
1013 StringBuilder sb = new StringBuilder();
1014 sb.append(cl[0]);
1015 for (int i = 1; i < cl.length; i++) {
1016 sb.append(" ");
1017 sb.append(cl[i]);
1018 }
1019 getLog().debug("Command line options:");
1020 getLog().debug(sb);
1021 }
1022 } catch (CompilerException ce) {
1023 getLog().debug(ce);
1024 }
1025 }
1026
1027 List<String> jpmsLines = new ArrayList<>();
1028
1029
1030 final List<String> runtimeArgs = Arrays.asList(
1031 "--upgrade-module-path", "--add-exports", "--add-reads", "--add-modules", "--limit-modules");
1032
1033
1034 Iterator<Map.Entry<String, String>> entryIter =
1035 compilerConfiguration.getCustomCompilerArgumentsEntries().iterator();
1036 while (entryIter.hasNext()) {
1037 Map.Entry<String, String> entry = entryIter.next();
1038
1039 if (runtimeArgs.contains(entry.getKey())) {
1040 jpmsLines.add(entry.getKey());
1041
1042 String value = entry.getValue();
1043 if (value == null) {
1044 entry = entryIter.next();
1045 value = entry.getKey();
1046 }
1047 jpmsLines.add(value);
1048 } else if ("--patch-module".equals(entry.getKey())) {
1049 String value = entry.getValue();
1050 if (value == null) {
1051 entry = entryIter.next();
1052 value = entry.getKey();
1053 }
1054
1055 String[] values = value.split("=");
1056
1057 StringBuilder patchModule = new StringBuilder(values[0]);
1058 patchModule.append('=');
1059
1060 Set<String> patchModules = new LinkedHashSet<>();
1061 Set<Path> sourceRoots = new HashSet<>(getCompileSourceRoots().size());
1062 for (String sourceRoot : getCompileSourceRoots()) {
1063 sourceRoots.add(Paths.get(sourceRoot));
1064 }
1065
1066 String[] files = values[1].split(PS);
1067
1068 for (String file : files) {
1069 Path filePath = Paths.get(file);
1070 if (getOutputDirectory().toPath().equals(filePath)) {
1071 patchModules.add("_");
1072 } else if (getOutputDirectory().toPath().startsWith(filePath)) {
1073
1074 continue;
1075 } else if (sourceRoots.contains(filePath)) {
1076 patchModules.add("_");
1077 } else {
1078 JavaModuleDescriptor descriptor = getPathElements().get(file);
1079
1080 if (descriptor == null) {
1081 if (Files.isDirectory(filePath)) {
1082 patchModules.add(file);
1083 } else {
1084 getLog().warn("Can't locate " + file);
1085 }
1086 } else if (!values[0].equals(descriptor.name())) {
1087 patchModules.add(descriptor.name());
1088 }
1089 }
1090 }
1091
1092 StringBuilder sb = new StringBuilder();
1093
1094 if (!patchModules.isEmpty()) {
1095 for (String mod : patchModules) {
1096 if (sb.length() > 0) {
1097 sb.append(", ");
1098 }
1099
1100 sb.append(mod);
1101 }
1102
1103 jpmsLines.add("--patch-module");
1104 jpmsLines.add(patchModule + sb.toString());
1105 }
1106 }
1107 }
1108
1109 if (!jpmsLines.isEmpty()) {
1110 Path jpmsArgs = Paths.get(getOutputDirectory().getAbsolutePath(), "META-INF/jpms.args");
1111 try {
1112 Files.createDirectories(jpmsArgs.getParent());
1113
1114 Files.write(jpmsArgs, jpmsLines, Charset.defaultCharset());
1115 } catch (IOException e) {
1116 getLog().warn(e.getMessage());
1117 }
1118 }
1119
1120
1121
1122
1123
1124 if (StringUtils.isEmpty(compilerConfiguration.getSourceEncoding())) {
1125 getLog().warn("File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
1126 + ", i.e. build is platform dependent!");
1127 }
1128
1129 CompilerResult compilerResult;
1130
1131 if (useIncrementalCompilation) {
1132 incrementalBuildHelperRequest.outputDirectory(getOutputDirectory());
1133
1134 incrementalBuildHelper.beforeRebuildExecution(incrementalBuildHelperRequest);
1135
1136 getLog().debug("incrementalBuildHelper#beforeRebuildExecution");
1137 }
1138
1139 try {
1140 compilerResult = compiler.performCompile(compilerConfiguration);
1141 } catch (Exception e) {
1142
1143 throw new MojoExecutionException("Fatal error compiling", e);
1144 }
1145
1146 if (createMissingPackageInfoClass
1147 && compilerResult.isSuccess()
1148 && compiler.getCompilerOutputStyle() == CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE) {
1149 try {
1150 SourceMapping sourceMapping = getSourceMapping(compilerConfiguration, compiler);
1151 createMissingPackageInfoClasses(compilerConfiguration, sourceMapping, sources);
1152 } catch (Exception e) {
1153 getLog().warn("Error creating missing package info classes", e);
1154 }
1155 }
1156
1157 if (useIncrementalCompilation) {
1158 if (incrementalBuildHelperRequest.getOutputDirectory().exists()) {
1159 getLog().debug("incrementalBuildHelper#afterRebuildExecution");
1160
1161 incrementalBuildHelper.afterRebuildExecution(incrementalBuildHelperRequest);
1162 } else {
1163 getLog().debug(
1164 "skip incrementalBuildHelper#afterRebuildExecution as the output directory doesn't exist");
1165 }
1166 }
1167
1168 List<CompilerMessage> warnings = new ArrayList<>();
1169 List<CompilerMessage> errors = new ArrayList<>();
1170 List<CompilerMessage> others = new ArrayList<>();
1171 for (CompilerMessage message : compilerResult.getCompilerMessages()) {
1172 if (message.getKind() == CompilerMessage.Kind.ERROR) {
1173 errors.add(message);
1174 } else if (message.getKind() == CompilerMessage.Kind.WARNING
1175 || message.getKind() == CompilerMessage.Kind.MANDATORY_WARNING) {
1176 warnings.add(message);
1177 } else {
1178 others.add(message);
1179 }
1180 }
1181
1182 if (failOnError && !compilerResult.isSuccess()) {
1183 for (CompilerMessage message : others) {
1184 assert message.getKind() != CompilerMessage.Kind.ERROR
1185 && message.getKind() != CompilerMessage.Kind.WARNING
1186 && message.getKind() != CompilerMessage.Kind.MANDATORY_WARNING;
1187 getLog().info(message.toString());
1188 }
1189 if (!warnings.isEmpty()) {
1190 getLog().info("-------------------------------------------------------------");
1191 getLog().warn("COMPILATION WARNING : ");
1192 getLog().info("-------------------------------------------------------------");
1193 for (CompilerMessage warning : warnings) {
1194 getLog().warn(warning.toString());
1195 }
1196 getLog().info(warnings.size() + ((warnings.size() > 1) ? " warnings " : " warning"));
1197 getLog().info("-------------------------------------------------------------");
1198 }
1199
1200 if (!errors.isEmpty()) {
1201 getLog().info("-------------------------------------------------------------");
1202 getLog().error("COMPILATION ERROR : ");
1203 getLog().info("-------------------------------------------------------------");
1204 for (CompilerMessage error : errors) {
1205 getLog().error(error.toString());
1206 }
1207 getLog().info(errors.size() + ((errors.size() > 1) ? " errors " : " error"));
1208 getLog().info("-------------------------------------------------------------");
1209 }
1210
1211 if (!errors.isEmpty()) {
1212 throw new CompilationFailureException(errors);
1213 } else {
1214 throw new CompilationFailureException(warnings);
1215 }
1216 } else {
1217 for (CompilerMessage message : compilerResult.getCompilerMessages()) {
1218 switch (message.getKind()) {
1219 case NOTE:
1220 case OTHER:
1221 getLog().info(message.toString());
1222 break;
1223
1224 case ERROR:
1225 getLog().error(message.toString());
1226 break;
1227
1228 case MANDATORY_WARNING:
1229 case WARNING:
1230 default:
1231 getLog().warn(message.toString());
1232 break;
1233 }
1234 }
1235 }
1236 }
1237
1238 private void createMissingPackageInfoClasses(
1239 CompilerConfiguration compilerConfiguration, SourceMapping sourceMapping, Set<File> sources)
1240 throws InclusionScanException, IOException {
1241 for (File source : sources) {
1242 String path = source.toString();
1243 if (path.endsWith(File.separator + "package-info.java")) {
1244 for (String root : getCompileSourceRoots()) {
1245 root = root + File.separator;
1246 if (path.startsWith(root)) {
1247 String rel = path.substring(root.length());
1248 Set<File> files = sourceMapping.getTargetFiles(getOutputDirectory(), rel);
1249 for (File file : files) {
1250 if (!file.exists()) {
1251 File parentFile = file.getParentFile();
1252
1253 if (!parentFile.exists()) {
1254 Files.createDirectories(parentFile.toPath());
1255 }
1256
1257 byte[] bytes = generatePackage(compilerConfiguration, rel);
1258 Files.write(file.toPath(), bytes);
1259 }
1260 }
1261 }
1262 }
1263 }
1264 }
1265 }
1266
1267 private byte[] generatePackage(CompilerConfiguration compilerConfiguration, String javaFile) {
1268 int version = getOpcode(compilerConfiguration);
1269 String internalPackageName = javaFile.substring(0, javaFile.length() - ".java".length());
1270 if (File.separatorChar != '/') {
1271 internalPackageName = internalPackageName.replace(File.separatorChar, '/');
1272 }
1273 ClassWriter cw = new ClassWriter(0);
1274 cw.visit(
1275 version,
1276 Opcodes.ACC_SYNTHETIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
1277 internalPackageName,
1278 null,
1279 "java/lang/Object",
1280 null);
1281 cw.visitSource("package-info.java", null);
1282 return cw.toByteArray();
1283 }
1284
1285 private int getOpcode(CompilerConfiguration compilerConfiguration) {
1286 String version = compilerConfiguration.getReleaseVersion();
1287 if (version == null) {
1288 version = compilerConfiguration.getTargetVersion();
1289 if (version == null) {
1290 version = "1.5";
1291 }
1292 }
1293 if (version.startsWith("1.")) {
1294 version = version.substring(2);
1295 }
1296 int iVersion = Integer.parseInt(version);
1297 if (iVersion < 2) {
1298 throw new IllegalArgumentException("Unsupported java version '" + version + "'");
1299 }
1300 return iVersion - 2 + Opcodes.V1_2;
1301 }
1302
1303 protected boolean isTestCompile() {
1304 return false;
1305 }
1306
1307
1308
1309
1310 private Set<File> getCompileSources(Compiler compiler, CompilerConfiguration compilerConfiguration)
1311 throws MojoExecutionException, CompilerException {
1312 String inputFileEnding = compiler.getInputFileEnding(compilerConfiguration);
1313 if (StringUtils.isEmpty(inputFileEnding)) {
1314
1315
1316 inputFileEnding = ".*";
1317 }
1318 SourceInclusionScanner scanner = getSourceInclusionScanner(inputFileEnding);
1319
1320 SourceMapping mapping = getSourceMapping(compilerConfiguration, compiler);
1321
1322 scanner.addSourceMapping(mapping);
1323
1324 Set<File> compileSources = new HashSet<>();
1325
1326 for (String sourceRoot : getCompileSourceRoots()) {
1327 File rootFile = new File(sourceRoot);
1328
1329 if (!rootFile.isDirectory()
1330 || rootFile.getAbsoluteFile().equals(compilerConfiguration.getGeneratedSourcesDirectory())) {
1331 continue;
1332 }
1333
1334 try {
1335 compileSources.addAll(scanner.getIncludedSources(rootFile, null));
1336 } catch (InclusionScanException e) {
1337 throw new MojoExecutionException(
1338 "Error scanning source root: '" + sourceRoot + "' for stale files to recompile.", e);
1339 }
1340 }
1341
1342 return compileSources;
1343 }
1344
1345 protected abstract Set<String> getIncludes();
1346
1347 protected abstract Set<String> getExcludes();
1348
1349
1350
1351
1352
1353
1354 private boolean isSourceChanged(CompilerConfiguration compilerConfiguration, Compiler compiler)
1355 throws CompilerException, MojoExecutionException {
1356 Set<File> staleSources =
1357 computeStaleSources(compilerConfiguration, compiler, getSourceInclusionScanner(staleMillis));
1358
1359 if (getLog().isDebugEnabled() || showCompilationChanges) {
1360 for (File f : staleSources) {
1361 if (showCompilationChanges) {
1362 getLog().info("Stale source detected: " + f.getAbsolutePath());
1363 } else {
1364 getLog().debug("Stale source detected: " + f.getAbsolutePath());
1365 }
1366 }
1367 }
1368 return !staleSources.isEmpty();
1369 }
1370
1371
1372
1373
1374
1375
1376 protected int getRequestThreadCount() {
1377 return session.getRequest().getDegreeOfConcurrency();
1378 }
1379
1380 protected Date getBuildStartTime() {
1381 MavenExecutionRequest request = session.getRequest();
1382 Date buildStartTime = request == null ? new Date() : request.getStartTime();
1383 return buildStartTime == null ? new Date() : buildStartTime;
1384 }
1385
1386 private String getMemoryValue(String setting) {
1387 String value = null;
1388
1389
1390 if (isDigits(setting)) {
1391 value = setting + "m";
1392 } else if ((isDigits(setting.substring(0, setting.length() - 1)))
1393 && (setting.toLowerCase().endsWith("m"))) {
1394 value = setting;
1395 }
1396 return value;
1397 }
1398
1399
1400
1401 protected final Toolchain getToolchain() {
1402 Toolchain tc = null;
1403
1404 if (jdkToolchain != null) {
1405
1406 try {
1407 Method getToolchainsMethod = toolchainManager
1408 .getClass()
1409 .getMethod("getToolchains", MavenSession.class, String.class, Map.class);
1410
1411 @SuppressWarnings("unchecked")
1412 List<Toolchain> tcs =
1413 (List<Toolchain>) getToolchainsMethod.invoke(toolchainManager, session, "jdk", jdkToolchain);
1414
1415 if (tcs != null && !tcs.isEmpty()) {
1416 tc = tcs.get(0);
1417 }
1418 } catch (NoSuchMethodException
1419 | SecurityException
1420 | IllegalAccessException
1421 | IllegalArgumentException
1422 | InvocationTargetException e) {
1423
1424 }
1425 }
1426
1427 if (tc == null) {
1428 tc = toolchainManager.getToolchainFromBuildContext("jdk", session);
1429 }
1430
1431 return tc;
1432 }
1433
1434 private boolean isDigits(String string) {
1435 for (int i = 0; i < string.length(); i++) {
1436 if (!Character.isDigit(string.charAt(i))) {
1437 return false;
1438 }
1439 }
1440 return true;
1441 }
1442
1443 private Set<File> computeStaleSources(
1444 CompilerConfiguration compilerConfiguration, Compiler compiler, SourceInclusionScanner scanner)
1445 throws MojoExecutionException, CompilerException {
1446 SourceMapping mapping = getSourceMapping(compilerConfiguration, compiler);
1447
1448 File outputDirectory;
1449 CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
1450 if (outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES) {
1451 outputDirectory = buildDirectory;
1452 } else {
1453 outputDirectory = getOutputDirectory();
1454 }
1455
1456 scanner.addSourceMapping(mapping);
1457
1458 Set<File> staleSources = new HashSet<>();
1459
1460 for (String sourceRoot : getCompileSourceRoots()) {
1461 File rootFile = new File(sourceRoot);
1462
1463 if (!rootFile.isDirectory()) {
1464 continue;
1465 }
1466
1467 try {
1468 staleSources.addAll(scanner.getIncludedSources(rootFile, outputDirectory));
1469 } catch (InclusionScanException e) {
1470 throw new MojoExecutionException(
1471 "Error scanning source root: \'" + sourceRoot + "\' for stale files to recompile.", e);
1472 }
1473 }
1474
1475 return staleSources;
1476 }
1477
1478 private SourceMapping getSourceMapping(CompilerConfiguration compilerConfiguration, Compiler compiler)
1479 throws CompilerException, MojoExecutionException {
1480 CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
1481
1482 SourceMapping mapping;
1483 if (outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE) {
1484 mapping = new SuffixMapping(
1485 compiler.getInputFileEnding(compilerConfiguration),
1486 compiler.getOutputFileEnding(compilerConfiguration));
1487 } else if (outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES) {
1488 mapping = new SingleTargetSourceMapping(
1489 compiler.getInputFileEnding(compilerConfiguration), compiler.getOutputFile(compilerConfiguration));
1490
1491 } else {
1492 throw new MojoExecutionException("Unknown compiler output style: '" + outputStyle + "'.");
1493 }
1494 return mapping;
1495 }
1496
1497
1498
1499
1500
1501 private static List<String> removeEmptyCompileSourceRoots(List<String> compileSourceRootsList) {
1502 List<String> newCompileSourceRootsList = new ArrayList<>();
1503 if (compileSourceRootsList != null) {
1504
1505 for (String srcDir : compileSourceRootsList) {
1506 if (!newCompileSourceRootsList.contains(srcDir) && new File(srcDir).exists()) {
1507 newCompileSourceRootsList.add(srcDir);
1508 }
1509 }
1510 }
1511 return newCompileSourceRootsList;
1512 }
1513
1514
1515
1516
1517
1518
1519
1520
1521 protected boolean isDependencyChanged() {
1522 if (session == null) {
1523
1524 getLog().info("Cannot determine build start date, skipping incremental build detection.");
1525 return false;
1526 }
1527
1528 if (fileExtensions == null || fileExtensions.isEmpty()) {
1529 fileExtensions = Collections.unmodifiableList(Arrays.asList("class", "jar"));
1530 }
1531
1532 Date buildStartTime = getBuildStartTime();
1533
1534 List<String> pathElements = new ArrayList<>();
1535 pathElements.addAll(getClasspathElements());
1536 pathElements.addAll(getModulepathElements());
1537
1538 for (String pathElement : pathElements) {
1539 File artifactPath = new File(pathElement);
1540 if (artifactPath.isDirectory() || artifactPath.isFile()) {
1541 if (!artifactPath.equals(getOutputDirectory()) && hasNewFile(artifactPath, buildStartTime)) {
1542 if (showCompilationChanges) {
1543 getLog().info("New dependency detected: " + artifactPath.getAbsolutePath());
1544 } else {
1545 getLog().debug("New dependency detected: " + artifactPath.getAbsolutePath());
1546 }
1547 return true;
1548 }
1549 }
1550 }
1551
1552
1553 return false;
1554 }
1555
1556
1557
1558
1559
1560
1561 private boolean hasNewFile(File classPathEntry, Date buildStartTime) {
1562 if (!classPathEntry.exists()) {
1563 return false;
1564 }
1565
1566 if (classPathEntry.isFile()) {
1567 return classPathEntry.lastModified() >= buildStartTime.getTime()
1568 && fileExtensions.contains(FileUtils.getExtension(classPathEntry.getName()));
1569 }
1570
1571 File[] children = classPathEntry.listFiles();
1572
1573 for (File child : children) {
1574 if (hasNewFile(child, buildStartTime)) {
1575 return true;
1576 }
1577 }
1578
1579 return false;
1580 }
1581
1582 private List<String> resolveProcessorPathEntries() throws MojoExecutionException {
1583 if (annotationProcessorPaths == null || annotationProcessorPaths.isEmpty()) {
1584 return null;
1585 }
1586
1587 Set<String> elements = new LinkedHashSet<>();
1588 try {
1589 List<Dependency> dependencies = convertToDependencies(annotationProcessorPaths);
1590 CollectRequest collectRequest =
1591 new CollectRequest(dependencies, Collections.emptyList(), project.getRemoteProjectRepositories());
1592 DependencyRequest dependencyRequest = new DependencyRequest();
1593 dependencyRequest.setCollectRequest(collectRequest);
1594 DependencyResult dependencyResult =
1595 repositorySystem.resolveDependencies(session.getRepositorySession(), dependencyRequest);
1596
1597 for (ArtifactResult resolved : dependencyResult.getArtifactResults()) {
1598 elements.add(resolved.getArtifact().getFile().getAbsolutePath());
1599 }
1600 return new ArrayList<>(elements);
1601 } catch (Exception e) {
1602 throw new MojoExecutionException(
1603 "Resolution of annotationProcessorPath dependencies failed: " + e.getLocalizedMessage(), e);
1604 }
1605 }
1606
1607 private List<Dependency> convertToDependencies(List<DependencyCoordinate> annotationProcessorPaths) {
1608 List<Dependency> dependencies = new ArrayList<>();
1609 for (DependencyCoordinate annotationProcessorPath : annotationProcessorPaths) {
1610 ArtifactHandler handler = artifactHandlerManager.getArtifactHandler(annotationProcessorPath.getType());
1611 Artifact artifact = new DefaultArtifact(
1612 annotationProcessorPath.getGroupId(),
1613 annotationProcessorPath.getArtifactId(),
1614 annotationProcessorPath.getClassifier(),
1615 handler.getExtension(),
1616 annotationProcessorPath.getVersion());
1617 Set<Exclusion> exclusions = convertToAetherExclusions(annotationProcessorPath.getExclusions());
1618 dependencies.add(new Dependency(artifact, JavaScopes.RUNTIME, false, exclusions));
1619 }
1620 return dependencies;
1621 }
1622
1623 private Set<Exclusion> convertToAetherExclusions(Set<DependencyExclusion> exclusions) {
1624 if (exclusions == null || exclusions.isEmpty()) {
1625 return Collections.emptySet();
1626 }
1627 Set<Exclusion> aetherExclusions = new HashSet<>();
1628 for (DependencyExclusion exclusion : exclusions) {
1629 Exclusion aetherExclusion = new Exclusion(
1630 exclusion.getGroupId(),
1631 exclusion.getArtifactId(),
1632 exclusion.getClassifier(),
1633 exclusion.getExtension());
1634 aetherExclusions.add(aetherExclusion);
1635 }
1636 return aetherExclusions;
1637 }
1638
1639 private void writePlugin(MessageBuilder mb) {
1640 mb.a(" <plugin>").newline();
1641 mb.a(" <groupId>org.apache.maven.plugins</groupId>").newline();
1642 mb.a(" <artifactId>maven-compiler-plugin</artifactId>").newline();
1643
1644 String version = getMavenCompilerPluginVersion();
1645 if (version != null) {
1646 mb.a(" <version>").a(version).a("</version>").newline();
1647 }
1648 writeConfig(mb);
1649
1650 mb.a(" </plugin>").newline();
1651 }
1652
1653 private void writeConfig(MessageBuilder mb) {
1654 mb.a(" <configuration>").newline();
1655
1656 if (release != null) {
1657 mb.a(" <release>").a(release).a("</release>").newline();
1658 } else if (JavaVersion.JAVA_VERSION.isAtLeast("9")) {
1659 String rls = target.replaceAll(".\\.", "");
1660
1661 mb.a(" <release>").a(rls).a("</release>").newline();
1662 } else {
1663 mb.a(" <source>").a(source).a("</source>").newline();
1664 mb.a(" <target>").a(target).a("</target>").newline();
1665 }
1666 mb.a(" </configuration>").newline();
1667 }
1668
1669 private String getMavenCompilerPluginVersion() {
1670 Properties pomProperties = new Properties();
1671
1672 try (InputStream is = AbstractCompilerMojo.class.getResourceAsStream(
1673 "/META-INF/maven/org.apache.maven.plugins/maven-compiler-plugin/pom.properties")) {
1674 if (is != null) {
1675 pomProperties.load(is);
1676 }
1677 } catch (IOException e) {
1678
1679 }
1680
1681 return pomProperties.getProperty("version");
1682 }
1683
1684 private DirectoryScanResult computeInputFileTreeChanges(IncrementalBuildHelper ibh, Set<File> inputFiles)
1685 throws MojoExecutionException {
1686 File mojoConfigBase = ibh.getMojoStatusDirectory();
1687 File mojoConfigFile = new File(mojoConfigBase, INPUT_FILES_LST_FILENAME);
1688
1689 String[] oldInputFiles = new String[0];
1690
1691 if (mojoConfigFile.exists()) {
1692 try {
1693 oldInputFiles = FileUtils.fileReadArray(mojoConfigFile);
1694 } catch (IOException e) {
1695 throw new MojoExecutionException("Error reading old mojo status " + mojoConfigFile, e);
1696 }
1697 }
1698
1699 String[] inputFileNames = inputFiles.stream().map(File::getAbsolutePath).toArray(String[]::new);
1700
1701 DirectoryScanResult dsr = DirectoryScanner.diffFiles(oldInputFiles, inputFileNames);
1702
1703 try {
1704 FileUtils.fileWriteArray(mojoConfigFile, inputFileNames);
1705 } catch (IOException e) {
1706 throw new MojoExecutionException("Error while storing the mojo status", e);
1707 }
1708
1709 return dsr;
1710 }
1711
1712 private boolean hasInputFileTreeChanged(DirectoryScanResult dsr) {
1713 return (dsr.getFilesAdded().length > 0 || dsr.getFilesRemoved().length > 0);
1714 }
1715
1716 public void setTarget(String target) {
1717 this.target = target;
1718 targetOrReleaseSet = true;
1719 }
1720
1721 public void setRelease(String release) {
1722 this.release = release;
1723 targetOrReleaseSet = true;
1724 }
1725
1726 final String getImplicit() {
1727 return implicit;
1728 }
1729 }