001    package org.apache.maven.plugin.plugin;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.maven.artifact.Artifact;
023    import org.apache.maven.artifact.repository.ArtifactRepository;
024    import org.apache.maven.plugin.AbstractMojo;
025    import org.apache.maven.plugin.MojoExecutionException;
026    import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
027    import org.apache.maven.plugin.descriptor.PluginDescriptor;
028    import org.apache.maven.plugins.annotations.Component;
029    import org.apache.maven.plugins.annotations.Parameter;
030    import org.apache.maven.project.MavenProject;
031    import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
032    import org.apache.maven.tools.plugin.PluginToolsRequest;
033    import org.apache.maven.tools.plugin.extractor.ExtractionException;
034    import org.apache.maven.tools.plugin.generator.Generator;
035    import org.apache.maven.tools.plugin.generator.GeneratorException;
036    import org.apache.maven.tools.plugin.generator.GeneratorUtils;
037    import org.apache.maven.tools.plugin.scanner.MojoScanner;
038    import org.codehaus.plexus.util.ReaderFactory;
039    
040    import java.io.File;
041    import java.util.List;
042    import java.util.Set;
043    
044    /**
045     * Abstract class for this Plugin.
046     *
047     * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
048     * @version $Id: AbstractGeneratorMojo.java 1345787 2012-06-03 21:58:22Z hboutemy $
049     */
050    public abstract class AbstractGeneratorMojo
051        extends AbstractMojo
052    {
053        /**
054         * The project currently being built.
055         */
056        @Component
057        protected MavenProject project;
058    
059        /**
060         * The component used for scanning the source tree for mojos.
061         */
062        @Component
063        protected MojoScanner mojoScanner;
064    
065        /**
066         * The file encoding of the source files.
067         *
068         * @since 2.5
069         */
070        @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
071        protected String encoding;
072    
073        /**
074         * The goal prefix that will appear before the ":".
075         */
076        @Parameter
077        protected String goalPrefix;
078    
079        /**
080         * By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the
081         * descriptor generator mojo is bound to generate-resources phase.
082         * But for annotations, the compiled classes are needed, so skip error
083         *
084         * @since 3.0
085         */
086        @Parameter( property = "maven.plugin.skipErrorNoDescriptorsFound", defaultValue = "false" )
087        protected boolean skipErrorNoDescriptorsFound;
088    
089        /**
090         * The role names of mojo extractors to use.
091         * <p/>
092         * If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors
093         * will be used.
094         * <p/>
095         * Example:
096         * <p/>
097         * <pre>
098         *  &lt;!-- Use all mojo extractors --&gt;
099         *  &lt;extractors/&gt;
100         *
101         *  &lt;!-- Use no mojo extractors --&gt;
102         *  &lt;extractors&gt;
103         *      &lt;extractor/&gt;
104         *  &lt;/extractors&gt;
105         *
106         *  &lt;!-- Use only bsh mojo extractor --&gt;
107         *  &lt;extractors&gt;
108         *      &lt;extractor&gt;bsh&lt;/extractor&gt;
109         *  &lt;/extractors&gt;
110         * </pre>
111         */
112        @Parameter
113        protected Set<String> extractors;
114    
115        /**
116         * Set this to "true" to skip invoking any goals or reports of the plugin.
117         *
118         * @since 2.8
119         */
120        @Parameter( defaultValue = "false", property = "maven.plugin.skip" )
121        protected boolean skip;
122    
123        /**
124         * The set of dependencies for the current project
125         *
126         * @since 3.0
127         */
128        @Parameter( defaultValue = "${project.artifacts}", required = true, readonly = true )
129        protected Set<Artifact> dependencies;
130    
131        /**
132         * List of Remote Repositories used by the resolver
133         *
134         * @since 3.0
135         */
136        @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
137        protected List<ArtifactRepository> remoteRepos;
138    
139        /**
140         * Location of the local repository.
141         *
142         * @since 3.0
143         */
144        @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
145        protected ArtifactRepository local;
146    
147        /**
148         * @return the output directory where files will be generated.
149         */
150        protected abstract File getOutputDirectory();
151    
152        /**
153         * @return the wanted <code>Generator</code> implementation.
154         */
155        protected abstract Generator createGenerator();
156    
157        /**
158         * {@inheritDoc}
159         */
160        public void execute()
161            throws MojoExecutionException
162        {
163            if ( !"maven-plugin".equals( project.getPackaging() ) )
164            {
165                return;
166            }
167            if ( skip )
168            {
169                getLog().warn( "Execution skipped" );
170                return;
171            }
172    
173            if ( project.getArtifactId().toLowerCase().startsWith( "maven-" )
174                && project.getArtifactId().toLowerCase().endsWith( "-plugin" ) && !"org.apache.maven.plugins".equals(
175                project.getGroupId() ) )
176            {
177                getLog().error( "\n\nArtifact Ids of the format maven-___-plugin are reserved for \n"
178                                    + "plugins in the Group Id org.apache.maven.plugins\n"
179                                    + "Please change your artifactId to the format ___-maven-plugin\n"
180                                    + "In the future this error will break the build.\n\n" );
181            }
182    
183            String defaultGoalPrefix = PluginDescriptor.getGoalPrefixFromArtifactId( project.getArtifactId() );
184            if ( goalPrefix == null )
185            {
186                goalPrefix = defaultGoalPrefix;
187            }
188            else if ( !goalPrefix.equals( defaultGoalPrefix ) )
189            {
190                getLog().warn(
191                    "\n\nGoal prefix is specified as: '" + goalPrefix + "'. " + "Maven currently expects it to be '"
192                        + defaultGoalPrefix + "'.\n" );
193            }
194    
195            mojoScanner.setActiveExtractors( extractors );
196    
197            // TODO: could use this more, eg in the writing of the plugin descriptor!
198            PluginDescriptor pluginDescriptor = new PluginDescriptor();
199    
200            pluginDescriptor.setGroupId( project.getGroupId() );
201    
202            pluginDescriptor.setArtifactId( project.getArtifactId() );
203    
204            pluginDescriptor.setVersion( project.getVersion() );
205    
206            pluginDescriptor.setGoalPrefix( goalPrefix );
207    
208            pluginDescriptor.setName( project.getName() );
209    
210            pluginDescriptor.setDescription( project.getDescription() );
211    
212            if ( encoding == null || encoding.length() < 1 )
213            {
214                getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
215                                   + " actually) to read mojo metadata, i.e. build is platform dependent!" );
216            }
217            else
218            {
219                getLog().info( "Using '" + encoding + "' encoding to read mojo metadata." );
220            }
221    
222            try
223            {
224                pluginDescriptor.setDependencies( GeneratorUtils.toComponentDependencies( project.getRuntimeDependencies() ) );
225    
226                PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
227                request.setEncoding( encoding );
228                request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound );
229                request.setDependencies( dependencies );
230                request.setLocal( this.local );
231                request.setRemoteRepos( this.remoteRepos );
232    
233                mojoScanner.populatePluginDescriptor( request );
234    
235                getOutputDirectory().mkdirs();
236    
237                createGenerator().execute( getOutputDirectory(), request );
238            }
239            catch ( GeneratorException e )
240            {
241                throw new MojoExecutionException( "Error writing plugin descriptor", e );
242            }
243            catch ( InvalidPluginDescriptorException e )
244            {
245                throw new MojoExecutionException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'",
246                                                  e );
247            }
248            catch ( ExtractionException e )
249            {
250                throw new MojoExecutionException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'",
251                                                  e );
252            }
253            catch ( LinkageError e )
254            {
255                throw new MojoExecutionException( "The API of the mojo scanner is not compatible with this plugin version."
256                                                      + " Please check the plugin dependencies configured in the POM and ensure the versions match.",
257                                                  e );
258            }
259        }
260    
261    }