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