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