View Javadoc
1   package org.apache.maven.plugin.compiler;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.artifact.Artifact;
23  import org.apache.maven.artifact.DefaultArtifact;
24  import org.apache.maven.artifact.handler.ArtifactHandler;
25  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
26  import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
27  import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
28  import org.apache.maven.artifact.resolver.ResolutionErrorHandler;
29  import org.apache.maven.artifact.versioning.VersionRange;
30  import org.apache.maven.execution.MavenSession;
31  import org.apache.maven.plugin.AbstractMojo;
32  import org.apache.maven.plugin.MojoExecution;
33  import org.apache.maven.plugin.MojoExecutionException;
34  import org.apache.maven.plugins.annotations.Component;
35  import org.apache.maven.plugins.annotations.Parameter;
36  import org.apache.maven.project.MavenProject;
37  import org.apache.maven.repository.RepositorySystem;
38  import org.apache.maven.shared.incremental.IncrementalBuildHelper;
39  import org.apache.maven.shared.incremental.IncrementalBuildHelperRequest;
40  import org.apache.maven.shared.utils.ReaderFactory;
41  import org.apache.maven.shared.utils.StringUtils;
42  import org.apache.maven.shared.utils.io.FileUtils;
43  import org.apache.maven.toolchain.Toolchain;
44  import org.apache.maven.toolchain.ToolchainManager;
45  import org.codehaus.plexus.compiler.Compiler;
46  import org.codehaus.plexus.compiler.CompilerConfiguration;
47  import org.codehaus.plexus.compiler.CompilerError;
48  import org.codehaus.plexus.compiler.CompilerException;
49  import org.codehaus.plexus.compiler.CompilerMessage;
50  import org.codehaus.plexus.compiler.CompilerNotImplementedException;
51  import org.codehaus.plexus.compiler.CompilerOutputStyle;
52  import org.codehaus.plexus.compiler.CompilerResult;
53  import org.codehaus.plexus.compiler.manager.CompilerManager;
54  import org.codehaus.plexus.compiler.manager.NoSuchCompilerException;
55  import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
56  import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
57  import org.codehaus.plexus.compiler.util.scan.mapping.SingleTargetSourceMapping;
58  import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
59  import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
60  
61  import java.io.File;
62  import java.lang.reflect.Method;
63  import java.util.ArrayList;
64  import java.util.Date;
65  import java.util.HashSet;
66  import java.util.LinkedHashMap;
67  import java.util.LinkedHashSet;
68  import java.util.List;
69  import java.util.Map;
70  import java.util.Set;
71  
72  /**
73   * TODO: At least one step could be optimized, currently the plugin will do two
74   * scans of all the source code if the compiler has to have the entire set of
75   * sources. This is currently the case for at least the C# compiler and most
76   * likely all the other .NET compilers too.
77   *
78   * @author others
79   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
80   * @version $Id: AbstractCompilerMojo.html 979705 2016-02-06 19:10:36Z agudian $
81   * @since 2.0
82   */
83  public abstract class AbstractCompilerMojo
84      extends AbstractMojo
85  {
86  
87      // ----------------------------------------------------------------------
88      // Configurables
89      // ----------------------------------------------------------------------
90  
91      /**
92       * Indicates whether the build will continue even if there are compilation errors.
93       *
94       * @since 2.0.2
95       */
96      @Parameter( property = "maven.compiler.failOnError", defaultValue = "true" )
97      private boolean failOnError = true;
98  
99      /**
100      * Set to <code>true</code> to include debugging information in the compiled class files.
101      */
102     @Parameter( property = "maven.compiler.debug", defaultValue = "true" )
103     private boolean debug = true;
104 
105     /**
106      * Set to <code>true</code> to show messages about what the compiler is doing.
107      */
108     @Parameter( property = "maven.compiler.verbose", defaultValue = "false" )
109     private boolean verbose;
110 
111     /**
112      * Sets whether to show source locations where deprecated APIs are used.
113      */
114     @Parameter( property = "maven.compiler.showDeprecation", defaultValue = "false" )
115     private boolean showDeprecation;
116 
117     /**
118      * Set to <code>true</code> to optimize the compiled code using the compiler's optimization methods.
119      */
120     @Parameter( property = "maven.compiler.optimize", defaultValue = "false" )
121     private boolean optimize;
122 
123     /**
124      * Set to <code>true</code> to show compilation warnings.
125      */
126     @Parameter( property = "maven.compiler.showWarnings", defaultValue = "false" )
127     private boolean showWarnings;
128 
129     /**
130      * The -source argument for the Java compiler.
131      */
132     @Parameter( property = "maven.compiler.source", defaultValue = "1.5" )
133     protected String source;
134 
135     /**
136      * The -target argument for the Java compiler.
137      */
138     @Parameter( property = "maven.compiler.target", defaultValue = "1.5" )
139     protected String target;
140 
141     /**
142      * The -encoding argument for the Java compiler.
143      *
144      * @since 2.1
145      */
146     @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
147     private String encoding;
148 
149     /**
150      * Sets the granularity in milliseconds of the last modification
151      * date for testing whether a source needs recompilation.
152      */
153     @Parameter( property = "lastModGranularityMs", defaultValue = "0" )
154     private int staleMillis;
155 
156     /**
157      * The compiler id of the compiler to use. See this
158      * <a href="non-javac-compilers.html">guide</a> for more information.
159      */
160     @Parameter( property = "maven.compiler.compilerId", defaultValue = "javac" )
161     private String compilerId;
162 
163     /**
164      * Version of the compiler to use, ex. "1.3", "1.5", if {@link #fork} is set to <code>true</code>.
165      */
166     @Parameter( property = "maven.compiler.compilerVersion" )
167     private String compilerVersion;
168 
169     /**
170      * Allows running the compiler in a separate process.
171      * If <code>false</code> it uses the built in compiler, while if <code>true</code> it will use an executable.
172      */
173     @Parameter( property = "maven.compiler.fork", defaultValue = "false" )
174     private boolean fork;
175 
176     /**
177      * Initial size, in megabytes, of the memory allocation pool, ex. "64", "64m"
178      * if {@link #fork} is set to <code>true</code>.
179      *
180      * @since 2.0.1
181      */
182     @Parameter( property = "maven.compiler.meminitial" )
183     private String meminitial;
184 
185     /**
186      * Sets the maximum size, in megabytes, of the memory allocation pool, ex. "128", "128m"
187      * if {@link #fork} is set to <code>true</code>.
188      *
189      * @since 2.0.1
190      */
191     @Parameter( property = "maven.compiler.maxmem" )
192     private String maxmem;
193 
194     /**
195      * Sets the executable of the compiler to use when {@link #fork} is <code>true</code>.
196      */
197     @Parameter( property = "maven.compiler.executable" )
198     private String executable;
199 
200     /**
201      * <p>
202      * Sets whether annotation processing is performed or not. Only applies to JDK 1.6+
203      * If not set, both compilation and annotation processing are performed at the same time.
204      * </p>
205      * <p>Allowed values are:</p>
206      * <ul>
207      * <li><code>none</code> - no annotation processing is performed.</li>
208      * <li><code>only</code> - only annotation processing is done, no compilation.</li>
209      * </ul>
210      *
211      * @since 2.2
212      */
213     @Parameter
214     private String proc;
215 
216     /**
217      * <p>
218      * Names of annotation processors to run. Only applies to JDK 1.6+
219      * If not set, the default annotation processors discovery process applies.
220      * </p>
221      *
222      * @since 2.2
223      */
224     @Parameter
225     private String[] annotationProcessors;
226 
227     /**
228      * <p>
229      * Classpath elements to supply as annotation processor path. If specified, the compiler will detect annotation
230      * processors only in those classpath elements. If omitted, the default classpath is used to detect annotation
231      * processors. The detection itself depends on the configuration of {@code annotationProcessors}.
232      * </p>
233      * <p>
234      * Each classpath element is specified using their Maven coordinates (groupId, artifactId, version, classifier,
235      * type). Transitive dependencies are added automatically. Example:
236      * </p>
237      *
238      * <pre>
239      * &lt;configuration&gt;
240      *   &lt;annotationProcessorPaths&gt;
241      *     &lt;path&gt;
242      *       &lt;groupId&gt;org.sample&lt;/groupId&gt;
243      *       &lt;artifactId&gt;sample-annotation-processor&lt;/artifactId&gt;
244      *       &lt;version&gt;1.2.3&lt;/version&gt;
245      *     &lt;/path&gt;
246      *     &lt;!-- ... more ... --&gt;
247      *   &lt;/annotationProcessorPaths&gt;
248      * &lt;/configuration&gt;
249      * </pre>
250      *
251      * @since 3.5
252      */
253     @Parameter
254     private List<DependencyCoordinate> annotationProcessorPaths;
255 
256     /**
257      * <p>
258      * Sets the arguments to be passed to the compiler (prepending a dash) if {@link #fork} is set to <code>true</code>.
259      * </p>
260      * <p>
261      * This is because the list of valid arguments passed to a Java compiler varies based on the compiler version.
262      * </p>
263      * <p>
264      * To pass <code>-Xmaxerrs 1000 -Xlint -Xlint:-path -Averbose=true</code> you should include the following:
265      * </p>
266      *
267      * <pre>
268      * &lt;compilerArguments&gt;
269      *   &lt;Xmaxerrs&gt;1000&lt;/Xmaxerrs&gt;
270      *   &lt;Xlint/&gt;
271      *   &lt;Xlint:-path/&gt;
272      *   &lt;Averbose&gt;true&lt;/Averbose&gt;
273      * &lt;/compilerArguments&gt;
274      * </pre>
275      *
276      * @since 2.0.1
277      * @deprecated use {@link #compilerArgs} instead.
278      */
279     @Parameter
280     @Deprecated
281     protected Map<String, String> compilerArguments;
282 
283     /**
284      * <p>
285      * Sets the arguments to be passed to the compiler if {@link #fork} is set to <code>true</code>.
286      * Example:
287      * <pre>
288      * &lt;compilerArgs&gt;
289      *   &lt;arg&gt;-Xmaxerrs=1000&lt;/arg&gt;
290      *   &lt;arg&gt;-Xlint&lt;/arg&gt;
291      *   &lt;arg&gt;-J-Duser.language=en_us&lt;/arg&gt;
292      * &lt;/compilerArgs&gt;
293      * </pre>
294      *
295      * @since 3.1
296      */
297     @Parameter
298     protected List<String> compilerArgs;
299 
300     /**
301      * <p>
302      * Sets the unformatted single argument string to be passed to the compiler if {@link #fork} is set to
303      * <code>true</code>. To pass multiple arguments such as <code>-Xmaxerrs 1000</code> (which are actually two
304      * arguments) you have to use {@link #compilerArguments}.
305      * </p>
306      * <p>
307      * This is because the list of valid arguments passed to a Java compiler varies based on the compiler version.
308      * </p>
309      */
310     @Parameter
311     protected String compilerArgument;
312 
313     /**
314      * Sets the name of the output file when compiling a set of
315      * sources to a single file.
316      * <p/>
317      * expression="${project.build.finalName}"
318      */
319     @Parameter
320     private String outputFileName;
321 
322     /**
323      * Keyword list to be appended to the <code>-g</code> command-line switch. Legal values are none or a
324      * comma-separated list of the following keywords: <code>lines</code>, <code>vars</code>, and <code>source</code>.
325      * If debug level is not specified, by default, nothing will be appended to <code>-g</code>.
326      * If debug is not turned on, this attribute will be ignored.
327      *
328      * @since 2.1
329      */
330     @Parameter( property = "maven.compiler.debuglevel" )
331     private String debuglevel;
332 
333     /**
334      *
335      */
336     @Component
337     private ToolchainManager toolchainManager;
338 
339     // ----------------------------------------------------------------------
340     // Read-only parameters
341     // ----------------------------------------------------------------------
342 
343     /**
344      * The directory to run the compiler from if fork is true.
345      */
346     @Parameter( defaultValue = "${basedir}", required = true, readonly = true )
347     private File basedir;
348 
349     /**
350      * The target directory of the compiler if fork is true.
351      */
352     @Parameter( defaultValue = "${project.build.directory}", required = true, readonly = true )
353     private File buildDirectory;
354 
355     /**
356      * Plexus compiler manager.
357      */
358     @Component
359     private CompilerManager compilerManager;
360 
361     /**
362      * The current build session instance. This is used for toolchain manager API calls.
363      */
364     @Parameter( defaultValue = "${session}", readonly = true, required = true )
365     private MavenSession session;
366 
367     /**
368      * The current project instance. This is used for propagating generated-sources paths as compile/testCompile source
369      * roots.
370      */
371     @Parameter( defaultValue = "${project}", readonly = true, required = true )
372     private MavenProject project;
373 
374     /**
375      * Strategy to re use javacc class created:
376      * <ul>
377      * <li><code>reuseCreated</code> (default): will reuse already created but in case of multi-threaded builds, each
378      * thread will have its own instance</li>
379      * <li><code>reuseSame</code>: the same Javacc class will be used for each compilation even for multi-threaded build
380      * </li>
381      * <li><code>alwaysNew</code>: a new Javacc class will be created for each compilation</li>
382      * </ul>
383      * Note this parameter value depends on the os/jdk you are using, but the default value should work on most of env.
384      *
385      * @since 2.5
386      */
387     @Parameter( defaultValue = "${reuseCreated}", property = "maven.compiler.compilerReuseStrategy" )
388     private String compilerReuseStrategy = "reuseCreated";
389 
390     /**
391      * @since 2.5
392      */
393     @Parameter( defaultValue = "false", property = "maven.compiler.skipMultiThreadWarning" )
394     private boolean skipMultiThreadWarning;
395 
396     /**
397      * compiler can now use javax.tools if available in your current jdk, you can disable this feature
398      * using -Dmaven.compiler.forceJavacCompilerUse=true or in the plugin configuration
399      *
400      * @since 3.0
401      */
402     @Parameter( defaultValue = "false", property = "maven.compiler.forceJavacCompilerUse" )
403     private boolean forceJavacCompilerUse;
404 
405     /**
406      * @since 3.0 needed for storing the status for the incremental build support.
407      */
408     @Parameter( defaultValue = "${mojoExecution}", readonly = true, required = true )
409     private MojoExecution mojoExecution;
410 
411     /**
412      * file extensions to check timestamp for incremental build
413      * <b>default contains only <code>.class</code></b>
414      *
415      * @since 3.1
416      */
417     @Parameter
418     private List<String> fileExtensions;
419 
420     /**
421      * to enable/disable incrementation compilation feature
422      * @since 3.1
423      */
424     @Parameter( defaultValue = "true", property = "maven.compiler.useIncrementalCompilation" )
425     private boolean useIncrementalCompilation = true;
426 
427     /**
428      * Resolves the artifacts needed.
429      */
430     @Component
431     private RepositorySystem repositorySystem;
432 
433     /**
434      * Artifact handler manager.
435      */
436     @Component
437     private ArtifactHandlerManager artifactHandlerManager;
438 
439     /**
440      * Throws an exception on artifact resolution errors.
441      */
442     @Component
443     private ResolutionErrorHandler resolutionErrorHandler;
444 
445     protected abstract SourceInclusionScanner getSourceInclusionScanner( int staleMillis );
446 
447     protected abstract SourceInclusionScanner getSourceInclusionScanner( String inputFileEnding );
448 
449     protected abstract List<String> getClasspathElements();
450 
451     protected abstract List<String> getCompileSourceRoots();
452 
453     protected abstract File getOutputDirectory();
454 
455     protected abstract String getSource();
456 
457     protected abstract String getTarget();
458 
459     protected abstract String getCompilerArgument();
460 
461     protected abstract Map<String, String> getCompilerArguments();
462 
463     protected abstract File getGeneratedSourcesDirectory();
464 
465     @Override
466     public void execute()
467         throws MojoExecutionException, CompilationFailureException
468     {
469         // ----------------------------------------------------------------------
470         // Look up the compiler. This is done before other code than can
471         // cause the mojo to return before the lookup is done possibly resulting
472         // in misconfigured POMs still building.
473         // ----------------------------------------------------------------------
474 
475         Compiler compiler;
476 
477         getLog().debug( "Using compiler '" + compilerId + "'." );
478 
479         try
480         {
481             compiler = compilerManager.getCompiler( compilerId );
482         }
483         catch ( NoSuchCompilerException e )
484         {
485             throw new MojoExecutionException( "No such compiler '" + e.getCompilerId() + "'." );
486         }
487 
488         //-----------toolchains start here ----------------------------------
489         //use the compilerId as identifier for toolchains as well.
490         Toolchain tc = getToolchain();
491         if ( tc != null )
492         {
493             getLog().info( "Toolchain in maven-compiler-plugin: " + tc );
494             if ( executable != null )
495             {
496                 getLog().warn( "Toolchains are ignored, 'executable' parameter is set to " + executable );
497             }
498             else
499             {
500                 fork = true;
501                 //TODO somehow shaky dependency between compilerId and tool executable.
502                 executable = tc.findTool( compilerId );
503             }
504         }
505         // ----------------------------------------------------------------------
506         //
507         // ----------------------------------------------------------------------
508 
509         List<String> compileSourceRoots = removeEmptyCompileSourceRoots( getCompileSourceRoots() );
510 
511         if ( compileSourceRoots.isEmpty() )
512         {
513             getLog().info( "No sources to compile" );
514 
515             return;
516         }
517 
518         if ( getLog().isDebugEnabled() )
519         {
520             getLog().debug( "Source directories: " + compileSourceRoots.toString().replace( ',', '\n' ) );
521             getLog().debug( "Classpath: " + getClasspathElements().toString().replace( ',', '\n' ) );
522             getLog().debug( "Output directory: " + getOutputDirectory() );
523         }
524 
525         // ----------------------------------------------------------------------
526         // Create the compiler configuration
527         // ----------------------------------------------------------------------
528 
529         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
530 
531         compilerConfiguration.setOutputLocation( getOutputDirectory().getAbsolutePath() );
532 
533         compilerConfiguration.setClasspathEntries( getClasspathElements() );
534 
535         compilerConfiguration.setOptimize( optimize );
536 
537         compilerConfiguration.setDebug( debug );
538 
539         if ( debug && StringUtils.isNotEmpty( debuglevel ) )
540         {
541             String[] split = StringUtils.split( debuglevel, "," );
542             for ( String aSplit : split )
543             {
544                 if ( !( aSplit.equalsIgnoreCase( "none" ) || aSplit.equalsIgnoreCase( "lines" )
545                     || aSplit.equalsIgnoreCase( "vars" ) || aSplit.equalsIgnoreCase( "source" ) ) )
546                 {
547                     throw new IllegalArgumentException( "The specified debug level: '" + aSplit + "' is unsupported. "
548                         + "Legal values are 'none', 'lines', 'vars', and 'source'." );
549                 }
550             }
551             compilerConfiguration.setDebugLevel( debuglevel );
552         }
553 
554         compilerConfiguration.setVerbose( verbose );
555 
556         compilerConfiguration.setShowWarnings( showWarnings );
557 
558         compilerConfiguration.setShowDeprecation( showDeprecation );
559 
560         compilerConfiguration.setSourceVersion( getSource() );
561 
562         compilerConfiguration.setTargetVersion( getTarget() );
563 
564         compilerConfiguration.setProc( proc );
565 
566         File generatedSourcesDirectory = getGeneratedSourcesDirectory();
567         compilerConfiguration.setGeneratedSourcesDirectory( generatedSourcesDirectory != null
568                         ? generatedSourcesDirectory.getAbsoluteFile() : null );
569 
570         if ( generatedSourcesDirectory != null )
571         {
572             String generatedSourcesPath = generatedSourcesDirectory.getAbsolutePath();
573 
574             compileSourceRoots.add( generatedSourcesPath );
575 
576             if ( isTestCompile() )
577             {
578                 getLog().debug( "Adding " + generatedSourcesPath + " to test-compile source roots:\n  "
579                                     + StringUtils.join( project.getTestCompileSourceRoots()
580                                                                .iterator(), "\n  " ) );
581 
582                 project.addTestCompileSourceRoot( generatedSourcesPath );
583 
584                 getLog().debug( "New test-compile source roots:\n  "
585                                     + StringUtils.join( project.getTestCompileSourceRoots()
586                                                                .iterator(), "\n  " ) );
587             }
588             else
589             {
590                 getLog().debug( "Adding " + generatedSourcesPath + " to compile source roots:\n  "
591                                     + StringUtils.join( project.getCompileSourceRoots()
592                                                                .iterator(), "\n  " ) );
593 
594                 project.addCompileSourceRoot( generatedSourcesPath );
595 
596                 getLog().debug( "New compile source roots:\n  " + StringUtils.join( project.getCompileSourceRoots()
597                                                                                            .iterator(), "\n  " ) );
598             }
599         }
600 
601         compilerConfiguration.setSourceLocations( compileSourceRoots );
602 
603         compilerConfiguration.setAnnotationProcessors( annotationProcessors );
604 
605         compilerConfiguration.setProcessorPathEntries( resolveProcessorPathEntries() );
606 
607         compilerConfiguration.setSourceEncoding( encoding );
608 
609         Map<String, String> effectiveCompilerArguments = getCompilerArguments();
610 
611         String effectiveCompilerArgument = getCompilerArgument();
612 
613         if ( ( effectiveCompilerArguments != null ) || ( effectiveCompilerArgument != null )
614                         || ( compilerArgs != null ) )
615         {
616             LinkedHashMap<String, String> cplrArgsCopy = new LinkedHashMap<String, String>();
617             if ( effectiveCompilerArguments != null )
618             {
619                 for ( Map.Entry<String, String> me : effectiveCompilerArguments.entrySet() )
620                 {
621                     String key = me.getKey();
622                     String value = me.getValue();
623                     if ( !key.startsWith( "-" ) )
624                     {
625                         key = "-" + key;
626                     }
627 
628                     if ( key.startsWith( "-A" ) && StringUtils.isNotEmpty( value ) )
629                     {
630                         cplrArgsCopy.put( key + "=" + value, null );
631                     }
632                     else
633                     {
634                         cplrArgsCopy.put( key, value );
635                     }
636                 }
637             }
638             if ( !StringUtils.isEmpty( effectiveCompilerArgument ) )
639             {
640                 cplrArgsCopy.put( effectiveCompilerArgument, null );
641             }
642             if ( compilerArgs != null )
643             {
644                 for ( String arg : compilerArgs )
645                 {
646                     cplrArgsCopy.put( arg, null );
647                 }
648             }
649             compilerConfiguration.setCustomCompilerArguments( cplrArgsCopy );
650         }
651 
652         compilerConfiguration.setFork( fork );
653 
654         if ( fork )
655         {
656             if ( !StringUtils.isEmpty( meminitial ) )
657             {
658                 String value = getMemoryValue( meminitial );
659 
660                 if ( value != null )
661                 {
662                     compilerConfiguration.setMeminitial( value );
663                 }
664                 else
665                 {
666                     getLog().info( "Invalid value for meminitial '" + meminitial + "'. Ignoring this option." );
667                 }
668             }
669 
670             if ( !StringUtils.isEmpty( maxmem ) )
671             {
672                 String value = getMemoryValue( maxmem );
673 
674                 if ( value != null )
675                 {
676                     compilerConfiguration.setMaxmem( value );
677                 }
678                 else
679                 {
680                     getLog().info( "Invalid value for maxmem '" + maxmem + "'. Ignoring this option." );
681                 }
682             }
683         }
684 
685         compilerConfiguration.setExecutable( executable );
686 
687         compilerConfiguration.setWorkingDirectory( basedir );
688 
689         compilerConfiguration.setCompilerVersion( compilerVersion );
690 
691         compilerConfiguration.setBuildDirectory( buildDirectory );
692 
693         compilerConfiguration.setOutputFileName( outputFileName );
694 
695         if ( CompilerConfiguration.CompilerReuseStrategy.AlwaysNew.getStrategy().equals( this.compilerReuseStrategy ) )
696         {
697             compilerConfiguration.setCompilerReuseStrategy( CompilerConfiguration.CompilerReuseStrategy.AlwaysNew );
698         }
699         else if ( CompilerConfiguration.CompilerReuseStrategy.ReuseSame.getStrategy().equals(
700             this.compilerReuseStrategy ) )
701         {
702             if ( getRequestThreadCount() > 1 )
703             {
704                 if ( !skipMultiThreadWarning )
705                 {
706                     getLog().warn( "You are in a multi-thread build and compilerReuseStrategy is set to reuseSame."
707                                        + " This can cause issues in some environments (os/jdk)!"
708                                        + " Consider using reuseCreated strategy."
709                                        + System.getProperty( "line.separator" )
710                                        + "If your env is fine with reuseSame, you can skip this warning with the "
711                                        + "configuration field skipMultiThreadWarning "
712                                        + "or -Dmaven.compiler.skipMultiThreadWarning=true" );
713                 }
714             }
715             compilerConfiguration.setCompilerReuseStrategy( CompilerConfiguration.CompilerReuseStrategy.ReuseSame );
716         }
717         else
718         {
719 
720             compilerConfiguration.setCompilerReuseStrategy( CompilerConfiguration.CompilerReuseStrategy.ReuseCreated );
721         }
722 
723         getLog().debug( "CompilerReuseStrategy: " + compilerConfiguration.getCompilerReuseStrategy().getStrategy() );
724 
725         compilerConfiguration.setForceJavacCompilerUse( forceJavacCompilerUse );
726 
727         boolean canUpdateTarget;
728 
729         IncrementalBuildHelper incrementalBuildHelper = new IncrementalBuildHelper( mojoExecution, session );
730 
731         Set<File> sources;
732 
733         IncrementalBuildHelperRequest incrementalBuildHelperRequest = null;
734 
735         if ( useIncrementalCompilation )
736         {
737             getLog().debug( "useIncrementalCompilation enabled" );
738             try
739             {
740                 canUpdateTarget = compiler.canUpdateTarget( compilerConfiguration );
741 
742                 sources = getCompileSources( compiler, compilerConfiguration );
743 
744                 incrementalBuildHelperRequest = new IncrementalBuildHelperRequest().inputFiles( sources );
745 
746                 // CHECKSTYLE_OFF: LineLength
747                 if ( ( compiler.getCompilerOutputStyle().equals( CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES ) && !canUpdateTarget )
748                     || isDependencyChanged()
749                     || isSourceChanged( compilerConfiguration, compiler )
750                     || incrementalBuildHelper.inputFileTreeChanged( incrementalBuildHelperRequest ) )
751                     // CHECKSTYLE_ON: LineLength
752                 {
753                     getLog().info( "Changes detected - recompiling the module!" );
754 
755                     compilerConfiguration.setSourceFiles( sources );
756                 }
757                 else
758                 {
759                     getLog().info( "Nothing to compile - all classes are up to date" );
760 
761                     return;
762                 }
763             }
764             catch ( CompilerException e )
765             {
766                 throw new MojoExecutionException( "Error while computing stale sources.", e );
767             }
768         }
769         else
770         {
771             getLog().debug( "useIncrementalCompilation disabled" );
772             Set<File> staleSources;
773             try
774             {
775                 staleSources =
776                     computeStaleSources( compilerConfiguration, compiler, getSourceInclusionScanner( staleMillis ) );
777 
778                 canUpdateTarget = compiler.canUpdateTarget( compilerConfiguration );
779 
780                 if ( compiler.getCompilerOutputStyle().equals( CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
781                     && !canUpdateTarget )
782                 {
783                     getLog().info( "RESCANNING!" );
784                     // TODO: This second scan for source files is sub-optimal
785                     String inputFileEnding = compiler.getInputFileEnding( compilerConfiguration );
786 
787                     sources = computeStaleSources( compilerConfiguration, compiler,
788                                                              getSourceInclusionScanner( inputFileEnding ) );
789 
790                     compilerConfiguration.setSourceFiles( sources );
791                 }
792                 else
793                 {
794                     compilerConfiguration.setSourceFiles( staleSources );
795                 }
796             }
797             catch ( CompilerException e )
798             {
799                 throw new MojoExecutionException( "Error while computing stale sources.", e );
800             }
801 
802             if ( staleSources.isEmpty() )
803             {
804                 getLog().info( "Nothing to compile - all classes are up to date" );
805 
806                 return;
807             }
808         }
809         // ----------------------------------------------------------------------
810         // Dump configuration
811         // ----------------------------------------------------------------------
812 
813         if ( getLog().isDebugEnabled() )
814         {
815             getLog().debug( "Classpath:" );
816 
817             for ( String s : getClasspathElements() )
818             {
819                 getLog().debug( " " + s );
820             }
821 
822             getLog().debug( "Source roots:" );
823 
824             for ( String root : getCompileSourceRoots() )
825             {
826                 getLog().debug( " " + root );
827             }
828 
829             try
830             {
831                 if ( fork )
832                 {
833                     if ( compilerConfiguration.getExecutable() != null )
834                     {
835                         getLog().debug( "Excutable: " );
836                         getLog().debug( " " + compilerConfiguration.getExecutable() );
837                     }
838                 }
839 
840                 String[] cl = compiler.createCommandLine( compilerConfiguration );
841                 if ( cl != null && cl.length > 0 )
842                 {
843                     StringBuilder sb = new StringBuilder();
844                     sb.append( cl[0] );
845                     for ( int i = 1; i < cl.length; i++ )
846                     {
847                         sb.append( " " );
848                         sb.append( cl[i] );
849                     }
850                     getLog().debug( "Command line options:" );
851                     getLog().debug( sb );
852                 }
853             }
854             catch ( CompilerException ce )
855             {
856                 getLog().debug( ce );
857             }
858         }
859 
860         // ----------------------------------------------------------------------
861         // Compile!
862         // ----------------------------------------------------------------------
863 
864         if ( StringUtils.isEmpty( compilerConfiguration.getSourceEncoding() ) )
865         {
866             getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
867                                + ", i.e. build is platform dependent!" );
868         }
869 
870         CompilerResult compilerResult;
871 
872 
873         if ( useIncrementalCompilation )
874         {
875             incrementalBuildHelperRequest.outputDirectory( getOutputDirectory() );
876 
877             incrementalBuildHelper.beforeRebuildExecution( incrementalBuildHelperRequest );
878 
879             getLog().debug( "incrementalBuildHelper#beforeRebuildExecution" );
880         }
881 
882         try
883         {
884             try
885             {
886                 compilerResult = compiler.performCompile( compilerConfiguration );
887             }
888             catch ( CompilerNotImplementedException cnie )
889             {
890                 List<CompilerError> messages = compiler.compile( compilerConfiguration );
891                 compilerResult = convertToCompilerResult( messages );
892             }
893         }
894         catch ( Exception e )
895         {
896             // TODO: don't catch Exception
897             throw new MojoExecutionException( "Fatal error compiling", e );
898         }
899 
900         if ( useIncrementalCompilation )
901         {
902             if ( incrementalBuildHelperRequest.getOutputDirectory().exists() )
903             {
904                 getLog().debug( "incrementalBuildHelper#afterRebuildExecution" );
905                 // now scan the same directory again and create a diff
906                 incrementalBuildHelper.afterRebuildExecution( incrementalBuildHelperRequest );
907             }
908             else
909             {
910                 getLog().debug(
911                     "skip incrementalBuildHelper#afterRebuildExecution as the output directory doesn't exist" );
912             }
913         }
914 
915         List<CompilerMessage> warnings = new ArrayList<CompilerMessage>();
916         List<CompilerMessage> errors = new ArrayList<CompilerMessage>();
917         List<CompilerMessage> others = new ArrayList<CompilerMessage>();
918         for ( CompilerMessage message : compilerResult.getCompilerMessages() )
919         {
920             if ( message.getKind() == CompilerMessage.Kind.ERROR )
921             {
922                 errors.add( message );
923             }
924             else if ( message.getKind() == CompilerMessage.Kind.WARNING
925                 || message.getKind() == CompilerMessage.Kind.MANDATORY_WARNING )
926             {
927                 warnings.add( message );
928             }
929             else
930             {
931                 others.add( message );
932             }
933         }
934 
935         if ( failOnError && !compilerResult.isSuccess() )
936         {
937             for ( CompilerMessage message : others )
938             {
939                 assert message.getKind() != CompilerMessage.Kind.ERROR
940                     && message.getKind() != CompilerMessage.Kind.WARNING
941                     && message.getKind() != CompilerMessage.Kind.MANDATORY_WARNING;
942                 getLog().info( message.toString() );
943             }
944             if ( !warnings.isEmpty() )
945             {
946                 getLog().info( "-------------------------------------------------------------" );
947                 getLog().warn( "COMPILATION WARNING : " );
948                 getLog().info( "-------------------------------------------------------------" );
949                 for ( CompilerMessage warning : warnings )
950                 {
951                     getLog().warn( warning.toString() );
952                 }
953                 getLog().info( warnings.size() + ( ( warnings.size() > 1 ) ? " warnings " : " warning" ) );
954                 getLog().info( "-------------------------------------------------------------" );
955             }
956 
957             if ( !errors.isEmpty() )
958             {
959                 getLog().info( "-------------------------------------------------------------" );
960                 getLog().error( "COMPILATION ERROR : " );
961                 getLog().info( "-------------------------------------------------------------" );
962                 for ( CompilerMessage error : errors )
963                 {
964                     getLog().error( error.toString() );
965                 }
966                 getLog().info( errors.size() + ( ( errors.size() > 1 ) ? " errors " : " error" ) );
967                 getLog().info( "-------------------------------------------------------------" );
968             }
969 
970             if ( !errors.isEmpty() )
971             {
972                 throw new CompilationFailureException( errors );
973             }
974             else
975             {
976                 throw new CompilationFailureException( warnings );
977             }
978         }
979         else
980         {
981             for ( CompilerMessage message : compilerResult.getCompilerMessages() )
982             {
983                 switch ( message.getKind() )
984                 {
985                     case NOTE:
986                     case OTHER:
987                         getLog().info( message.toString() );
988                         break;
989 
990                     case ERROR:
991                         getLog().error( message.toString() );
992                         break;
993 
994                     case MANDATORY_WARNING:
995                     case WARNING:
996                     default:
997                         getLog().warn( message.toString() );
998                         break;
999                 }
1000             }
1001         }
1002     }
1003 
1004     protected boolean isTestCompile()
1005     {
1006         return false;
1007     }
1008 
1009     protected CompilerResult convertToCompilerResult( List<CompilerError> compilerErrors )
1010     {
1011         if ( compilerErrors == null )
1012         {
1013             return new CompilerResult();
1014         }
1015         List<CompilerMessage> messages = new ArrayList<CompilerMessage>( compilerErrors.size() );
1016         boolean success = true;
1017         for ( CompilerError compilerError : compilerErrors )
1018         {
1019             messages.add(
1020                 new CompilerMessage( compilerError.getFile(), compilerError.getKind(), compilerError.getStartLine(),
1021                                      compilerError.getStartColumn(), compilerError.getEndLine(),
1022                                      compilerError.getEndColumn(), compilerError.getMessage() ) );
1023             if ( compilerError.isError() )
1024             {
1025                 success = false;
1026             }
1027         }
1028 
1029         return new CompilerResult( success, messages );
1030     }
1031 
1032     /**
1033      * @return all source files for the compiler
1034      */
1035     private Set<File> getCompileSources( Compiler compiler, CompilerConfiguration compilerConfiguration )
1036         throws MojoExecutionException, CompilerException
1037     {
1038         String inputFileEnding = compiler.getInputFileEnding( compilerConfiguration );
1039         if ( StringUtils.isEmpty( inputFileEnding ) )
1040         {
1041             // see MCOMPILER-199 GroovyEclipseCompiler doesn't set inputFileEnding
1042             // so we can presume it's all files from the source directory
1043             inputFileEnding = ".*";
1044         }
1045         SourceInclusionScanner scanner = getSourceInclusionScanner( inputFileEnding );
1046 
1047         SourceMapping mapping = getSourceMapping( compilerConfiguration, compiler );
1048 
1049         scanner.addSourceMapping( mapping );
1050 
1051         Set<File> compileSources = new HashSet<File>();
1052 
1053         for ( String sourceRoot : getCompileSourceRoots() )
1054         {
1055             File rootFile = new File( sourceRoot );
1056 
1057             if ( !rootFile.isDirectory()
1058                 || rootFile.getAbsoluteFile().equals( compilerConfiguration.getGeneratedSourcesDirectory() ) )
1059             {
1060                 continue;
1061             }
1062 
1063             try
1064             {
1065                 compileSources.addAll( scanner.getIncludedSources( rootFile, null ) );
1066             }
1067             catch ( InclusionScanException e )
1068             {
1069                 throw new MojoExecutionException(
1070                     "Error scanning source root: \'" + sourceRoot + "\' for stale files to recompile.", e );
1071             }
1072         }
1073 
1074         return compileSources;
1075     }
1076 
1077     /**
1078      * @param compilerConfiguration
1079      * @param compiler
1080      * @return <code>true</code> if at least a single source file is newer than it's class file
1081      */
1082     private boolean isSourceChanged( CompilerConfiguration compilerConfiguration, Compiler compiler )
1083         throws CompilerException, MojoExecutionException
1084     {
1085         Set<File> staleSources =
1086             computeStaleSources( compilerConfiguration, compiler, getSourceInclusionScanner( staleMillis ) );
1087 
1088         if ( getLog().isDebugEnabled() )
1089         {
1090             for ( File f : staleSources )
1091             {
1092                 getLog().debug( "Stale source detected: " + f.getAbsolutePath() );
1093             }
1094         }
1095         return staleSources != null && staleSources.size() > 0;
1096     }
1097 
1098 
1099     /**
1100      * try to get thread count if a Maven 3 build, using reflection as the plugin must not be maven3 api dependent
1101      *
1102      * @return number of thread for this build or 1 if not multi-thread build
1103      */
1104     protected int getRequestThreadCount()
1105     {
1106         try
1107         {
1108             Method getRequestMethod = session.getClass().getMethod( "getRequest" );
1109             Object mavenExecutionRequest = getRequestMethod.invoke( this.session );
1110             Method getThreadCountMethod = mavenExecutionRequest.getClass().getMethod( "getThreadCount" );
1111             String threadCount = (String) getThreadCountMethod.invoke( mavenExecutionRequest );
1112             return Integer.valueOf( threadCount );
1113         }
1114         catch ( Exception e )
1115         {
1116             getLog().debug( "unable to get threadCount for the current build: " + e.getMessage() );
1117         }
1118         return 1;
1119     }
1120 
1121     protected Date getBuildStartTime()
1122     {
1123         Date buildStartTime = null;
1124         try
1125         {
1126             Method getRequestMethod = session.getClass().getMethod( "getRequest" );
1127             Object mavenExecutionRequest = getRequestMethod.invoke( session );
1128             Method getStartTimeMethod = mavenExecutionRequest.getClass().getMethod( "getStartTime" );
1129             buildStartTime = (Date) getStartTimeMethod.invoke( mavenExecutionRequest );
1130         }
1131         catch ( Exception e )
1132         {
1133             getLog().debug( "unable to get start time for the current build: " + e.getMessage() );
1134         }
1135 
1136         if ( buildStartTime == null )
1137         {
1138             return new Date();
1139         }
1140 
1141         return buildStartTime;
1142     }
1143 
1144 
1145     private String getMemoryValue( String setting )
1146     {
1147         String value = null;
1148 
1149         // Allow '128' or '128m'
1150         if ( isDigits( setting ) )
1151         {
1152             value = setting + "m";
1153         }
1154         else if ( ( isDigits( setting.substring( 0, setting.length() - 1 ) ) )
1155             && ( setting.toLowerCase().endsWith( "m" ) ) )
1156         {
1157             value = setting;
1158         }
1159         return value;
1160     }
1161 
1162     //TODO remove the part with ToolchainManager lookup once we depend on
1163     //3.0.9 (have it as prerequisite). Define as regular component field then.
1164     private Toolchain getToolchain()
1165     {
1166         Toolchain tc = null;
1167         if ( toolchainManager != null )
1168         {
1169             tc = toolchainManager.getToolchainFromBuildContext( "jdk", session );
1170         }
1171         return tc;
1172     }
1173 
1174     private boolean isDigits( String string )
1175     {
1176         for ( int i = 0; i < string.length(); i++ )
1177         {
1178             if ( !Character.isDigit( string.charAt( i ) ) )
1179             {
1180                 return false;
1181             }
1182         }
1183         return true;
1184     }
1185 
1186     private Set<File> computeStaleSources( CompilerConfiguration compilerConfiguration, Compiler compiler,
1187                                            SourceInclusionScanner scanner )
1188         throws MojoExecutionException, CompilerException
1189     {
1190         SourceMapping mapping = getSourceMapping( compilerConfiguration, compiler );
1191 
1192         File outputDirectory;
1193         CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
1194         if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
1195         {
1196             outputDirectory = buildDirectory;
1197         }
1198         else
1199         {
1200             outputDirectory = getOutputDirectory();
1201         }
1202 
1203         scanner.addSourceMapping( mapping );
1204 
1205         Set<File> staleSources = new HashSet<File>();
1206 
1207         for ( String sourceRoot : getCompileSourceRoots() )
1208         {
1209             File rootFile = new File( sourceRoot );
1210 
1211             if ( !rootFile.isDirectory() )
1212             {
1213                 continue;
1214             }
1215 
1216             try
1217             {
1218                 staleSources.addAll( scanner.getIncludedSources( rootFile, outputDirectory ) );
1219             }
1220             catch ( InclusionScanException e )
1221             {
1222                 throw new MojoExecutionException(
1223                     "Error scanning source root: \'" + sourceRoot + "\' for stale files to recompile.", e );
1224             }
1225         }
1226 
1227         return staleSources;
1228     }
1229 
1230     private SourceMapping getSourceMapping( CompilerConfiguration compilerConfiguration, Compiler compiler )
1231         throws CompilerException, MojoExecutionException
1232     {
1233         CompilerOutputStyle outputStyle = compiler.getCompilerOutputStyle();
1234 
1235         SourceMapping mapping;
1236         if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_PER_INPUT_FILE )
1237         {
1238             mapping = new SuffixMapping( compiler.getInputFileEnding( compilerConfiguration ),
1239                                          compiler.getOutputFileEnding( compilerConfiguration ) );
1240         }
1241         else if ( outputStyle == CompilerOutputStyle.ONE_OUTPUT_FILE_FOR_ALL_INPUT_FILES )
1242         {
1243             mapping = new SingleTargetSourceMapping( compiler.getInputFileEnding( compilerConfiguration ),
1244                                                      compiler.getOutputFile( compilerConfiguration ) );
1245 
1246         }
1247         else
1248         {
1249             throw new MojoExecutionException( "Unknown compiler output style: '" + outputStyle + "'." );
1250         }
1251         return mapping;
1252     }
1253 
1254     /**
1255      * @todo also in ant plugin. This should be resolved at some point so that it does not need to
1256      * be calculated continuously - or should the plugins accept empty source roots as is?
1257      */
1258     private static List<String> removeEmptyCompileSourceRoots( List<String> compileSourceRootsList )
1259     {
1260         List<String> newCompileSourceRootsList = new ArrayList<String>();
1261         if ( compileSourceRootsList != null )
1262         {
1263             // copy as I may be modifying it
1264             for ( String srcDir : compileSourceRootsList )
1265             {
1266                 if ( !newCompileSourceRootsList.contains( srcDir ) && new File( srcDir ).exists() )
1267                 {
1268                     newCompileSourceRootsList.add( srcDir );
1269                 }
1270             }
1271         }
1272         return newCompileSourceRootsList;
1273     }
1274 
1275     /**
1276      * We just compare the timestamps of all local dependency files (inter-module dependency classpath) and the own
1277      * generated classes and if we got a file which is &gt;= the buid-started timestamp, then we catched a file which
1278      * got changed during this build.
1279      *
1280      * @return <code>true</code> if at least one single dependency has changed.
1281      */
1282     protected boolean isDependencyChanged()
1283     {
1284         if ( session == null )
1285         {
1286             // we just cannot determine it, so don't do anything beside logging
1287             getLog().info( "Cannot determine build start date, skipping incremental build detection." );
1288             return false;
1289         }
1290 
1291         if ( fileExtensions == null || fileExtensions.isEmpty() )
1292         {
1293             fileExtensions = new ArrayList<String>();
1294             fileExtensions.add( ".class" );
1295         }
1296 
1297         Date buildStartTime = getBuildStartTime();
1298 
1299         for ( String classPathElement : getClasspathElements() )
1300         {
1301             // ProjectArtifacts are artifacts which are available in the local project
1302             // that's the only ones we are interested in now.
1303             File artifactPath = new File( classPathElement );
1304             if ( artifactPath.isDirectory() )
1305             {
1306                 if ( hasNewFile( artifactPath, buildStartTime ) )
1307                 {
1308                     getLog().debug( "New dependency detected: " + artifactPath.getAbsolutePath() );
1309                     return true;
1310                 }
1311             }
1312         }
1313 
1314         // obviously there was no new file detected.
1315         return false;
1316     }
1317 
1318     /**
1319      * @param classPathEntry entry to check
1320      * @param buildStartTime time build start
1321      * @return if any changes occurred
1322      */
1323     private boolean hasNewFile( File classPathEntry, Date buildStartTime )
1324     {
1325         if ( !classPathEntry.exists() )
1326         {
1327             return false;
1328         }
1329 
1330         if ( classPathEntry.isFile() )
1331         {
1332             return classPathEntry.lastModified() >= buildStartTime.getTime()
1333                 && fileExtensions.contains( FileUtils.getExtension( classPathEntry.getName() ) );
1334         }
1335 
1336         File[] children = classPathEntry.listFiles();
1337 
1338         for ( File child : children )
1339         {
1340             if ( hasNewFile( child, buildStartTime ) )
1341             {
1342                 return true;
1343             }
1344         }
1345 
1346         return false;
1347     }
1348 
1349     private List<String> resolveProcessorPathEntries()
1350         throws MojoExecutionException
1351     {
1352         if ( annotationProcessorPaths == null || annotationProcessorPaths.isEmpty() )
1353         {
1354             return null;
1355         }
1356 
1357         try
1358         {
1359             Set<Artifact> requiredArtifacts = new LinkedHashSet<Artifact>();
1360 
1361             for ( DependencyCoordinate coord : annotationProcessorPaths )
1362             {
1363                 ArtifactHandler handler = artifactHandlerManager.getArtifactHandler( coord.getType() );
1364 
1365                 Artifact artifact = new DefaultArtifact(
1366                      coord.getGroupId(),
1367                      coord.getArtifactId(),
1368                      VersionRange.createFromVersionSpec( coord.getVersion() ),
1369                      Artifact.SCOPE_RUNTIME,
1370                      coord.getType(),
1371                      coord.getClassifier(),
1372                      handler,
1373                      false );
1374 
1375                 requiredArtifacts.add( artifact );
1376             }
1377 
1378             ArtifactResolutionRequest request = new ArtifactResolutionRequest()
1379                             .setArtifact( requiredArtifacts.iterator().next() )
1380                             .setResolveRoot( true )
1381                             .setResolveTransitively( true )
1382                             .setArtifactDependencies( requiredArtifacts )
1383                             .setLocalRepository( session.getLocalRepository() )
1384                             .setRemoteRepositories( project.getRemoteArtifactRepositories() );
1385 
1386             ArtifactResolutionResult resolutionResult = repositorySystem.resolve( request );
1387 
1388             resolutionErrorHandler.throwErrors( request, resolutionResult );
1389 
1390             List<String> elements = new ArrayList<String>( resolutionResult.getArtifacts().size() );
1391 
1392             for ( Object resolved : resolutionResult.getArtifacts() )
1393             {
1394                 elements.add( ( (Artifact) resolved ).getFile().getAbsolutePath() );
1395             }
1396 
1397             return elements;
1398         }
1399         catch ( Exception e )
1400         {
1401             throw new MojoExecutionException( "Resolution of annotationProcessorPath dependencies failed: "
1402                 + e.getLocalizedMessage(), e );
1403         }
1404     }
1405 }