View Javadoc
1   package org.apache.maven.plugin.plugin;
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.repository.ArtifactRepository;
24  import org.apache.maven.plugin.AbstractMojo;
25  import org.apache.maven.plugin.MojoExecutionException;
26  import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
27  import org.apache.maven.plugin.descriptor.PluginDescriptor;
28  import org.apache.maven.plugins.annotations.Component;
29  import org.apache.maven.plugins.annotations.Parameter;
30  import org.apache.maven.project.MavenProject;
31  import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
32  import org.apache.maven.tools.plugin.PluginToolsRequest;
33  import org.apache.maven.tools.plugin.extractor.ExtractionException;
34  import org.apache.maven.tools.plugin.generator.Generator;
35  import org.apache.maven.tools.plugin.generator.GeneratorException;
36  import org.apache.maven.tools.plugin.generator.GeneratorUtils;
37  import org.apache.maven.tools.plugin.scanner.MojoScanner;
38  import org.codehaus.plexus.component.repository.ComponentDependency;
39  import org.codehaus.plexus.util.ReaderFactory;
40  
41  import java.io.File;
42  import java.util.Arrays;
43  import java.util.List;
44  import java.util.Set;
45  
46  /**
47   * Abstract class for this Plugin.
48   *
49   * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
50   * @version $Id: AbstractGeneratorMojo.html 934731 2015-01-01 22:17:21Z hboutemy $
51   */
52  public abstract class AbstractGeneratorMojo
53      extends AbstractMojo
54  {
55      /**
56       * The project currently being built.
57       */
58      @Parameter( defaultValue = "${project}", readonly = true )
59      protected MavenProject project;
60  
61      /**
62       * The component used for scanning the source tree for mojos.
63       */
64      @Component
65      protected MojoScanner mojoScanner;
66  
67      /**
68       * The file encoding of the source files.
69       *
70       * @since 2.5
71       */
72      @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
73      protected String encoding;
74  
75      /**
76       * The goal prefix that will appear before the ":".
77       */
78      @Parameter
79      protected String goalPrefix;
80  
81      /**
82       * By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the
83       * descriptor generator mojo is bound to generate-resources phase.
84       * But for annotations, the compiled classes are needed, so skip error
85       *
86       * @since 3.0
87       */
88      @Parameter( property = "maven.plugin.skipErrorNoDescriptorsFound", defaultValue = "false" )
89      protected boolean skipErrorNoDescriptorsFound;
90  
91      /**
92       * The role names of mojo extractors to use.
93       * <p/>
94       * If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors
95       * will be used.
96       * <p/>
97       * Example:
98       * <p/>
99       * <pre>
100      *  &lt;!-- Use all mojo extractors --&gt;
101      *  &lt;extractors/&gt;
102      *
103      *  &lt;!-- Use no mojo extractors --&gt;
104      *  &lt;extractors&gt;
105      *      &lt;extractor/&gt;
106      *  &lt;/extractors&gt;
107      *
108      *  &lt;!-- Use only bsh mojo extractor --&gt;
109      *  &lt;extractors&gt;
110      *      &lt;extractor&gt;bsh&lt;/extractor&gt;
111      *  &lt;/extractors&gt;
112      * </pre>
113      */
114     @Parameter
115     protected Set<String> extractors;
116 
117     /**
118      * Set this to "true" to skip invoking any goals or reports of the plugin.
119      *
120      * @since 2.8
121      */
122     @Parameter( defaultValue = "false", property = "maven.plugin.skip" )
123     protected boolean skip;
124 
125     /**
126      * The set of dependencies for the current project
127      *
128      * @since 3.0
129      */
130     @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true )
131     protected Set<Artifact> dependencies;
132 
133     /**
134      * List of Remote Repositories used by the resolver
135      *
136      * @since 3.0
137      */
138     @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
139     protected List<ArtifactRepository> remoteRepos;
140 
141     /**
142      * Location of the local repository.
143      *
144      * @since 3.0
145      */
146     @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
147     protected ArtifactRepository local;
148 
149     /**
150      * Maven plugin packaging types. Default is single "maven-plugin".
151      * 
152      * @since 3.3
153      */
154     @Parameter
155     protected List<String> packagingTypes = Arrays.asList( "maven-plugin" );
156 
157     /**
158      * @return the output directory where files will be generated.
159      */
160     protected abstract File getOutputDirectory();
161 
162     /**
163      * @return the wanted <code>Generator</code> implementation.
164      */
165     protected abstract Generator createGenerator();
166 
167     /**
168      * {@inheritDoc}
169      */
170     public void execute()
171         throws MojoExecutionException
172     {
173         if ( !packagingTypes.contains( project.getPackaging() ) )
174         {
175             getLog().warn( "Unsupported packaging type " + project.getPackaging() + ", execution skipped" );
176             return;
177         }
178         if ( skip )
179         {
180             getLog().warn( "Execution skipped" );
181             return;
182         }
183 
184         if ( project.getArtifactId().toLowerCase().startsWith( "maven-" )
185             && project.getArtifactId().toLowerCase().endsWith( "-plugin" ) && !"org.apache.maven.plugins".equals(
186             project.getGroupId() ) )
187         {
188             getLog().error( "\n\nArtifact Ids of the format maven-___-plugin are reserved for \n"
189                                 + "plugins in the Group Id org.apache.maven.plugins\n"
190                                 + "Please change your artifactId to the format ___-maven-plugin\n"
191                                 + "In the future this error will break the build.\n\n" );
192         }
193 
194         String defaultGoalPrefix = PluginDescriptor.getGoalPrefixFromArtifactId( project.getArtifactId() );
195         if ( goalPrefix == null )
196         {
197             goalPrefix = defaultGoalPrefix;
198         }
199         else if ( !goalPrefix.equals( defaultGoalPrefix ) )
200         {
201             getLog().warn(
202                 "\n\nGoal prefix is specified as: '" + goalPrefix + "'. " + "Maven currently expects it to be '"
203                     + defaultGoalPrefix + "'.\n" );
204         }
205 
206         mojoScanner.setActiveExtractors( extractors );
207 
208         // TODO: could use this more, eg in the writing of the plugin descriptor!
209         PluginDescriptor pluginDescriptor = new PluginDescriptor();
210 
211         pluginDescriptor.setGroupId( project.getGroupId() );
212 
213         pluginDescriptor.setArtifactId( project.getArtifactId() );
214 
215         pluginDescriptor.setVersion( project.getVersion() );
216 
217         pluginDescriptor.setGoalPrefix( goalPrefix );
218 
219         pluginDescriptor.setName( project.getName() );
220 
221         pluginDescriptor.setDescription( project.getDescription() );
222 
223         if ( encoding == null || encoding.length() < 1 )
224         {
225             getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
226                                + " actually) to read mojo metadata, i.e. build is platform dependent!" );
227         }
228         else
229         {
230             getLog().info( "Using '" + encoding + "' encoding to read mojo metadata." );
231         }
232 
233         try
234         {
235             List<ComponentDependency> deps = GeneratorUtils.toComponentDependencies( project.getRuntimeDependencies() );
236             pluginDescriptor.setDependencies( deps );
237 
238             PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
239             request.setEncoding( encoding );
240             request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound );
241             request.setDependencies( dependencies );
242             request.setLocal( this.local );
243             request.setRemoteRepos( this.remoteRepos );
244 
245             mojoScanner.populatePluginDescriptor( request );
246 
247             getOutputDirectory().mkdirs();
248 
249             createGenerator().execute( getOutputDirectory(), request );
250         }
251         catch ( GeneratorException e )
252         {
253             throw new MojoExecutionException( "Error writing plugin descriptor", e );
254         }
255         catch ( InvalidPluginDescriptorException e )
256         {
257             throw new MojoExecutionException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'",
258                                               e );
259         }
260         catch ( ExtractionException e )
261         {
262             throw new MojoExecutionException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'",
263                                               e );
264         }
265         catch ( LinkageError e )
266         {
267             throw new MojoExecutionException( "The API of the mojo scanner is not compatible with this plugin version."
268                 + " Please check the plugin dependencies configured in the POM and ensure the versions match.", e );
269         }
270     }
271 
272 }