001package org.apache.maven.lifecycle.internal;
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.execution.MavenSession;
023import org.apache.maven.model.Plugin;
024import org.apache.maven.plugin.BuildPluginManager;
025import org.apache.maven.plugin.InvalidPluginDescriptorException;
026import org.apache.maven.plugin.MojoNotFoundException;
027import org.apache.maven.plugin.PluginDescriptorParsingException;
028import org.apache.maven.plugin.PluginNotFoundException;
029import org.apache.maven.plugin.PluginResolutionException;
030import org.apache.maven.plugin.descriptor.MojoDescriptor;
031import org.apache.maven.plugin.prefix.DefaultPluginPrefixRequest;
032import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
033import org.apache.maven.plugin.prefix.PluginPrefixRequest;
034import org.apache.maven.plugin.prefix.PluginPrefixResolver;
035import org.apache.maven.plugin.prefix.PluginPrefixResult;
036import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
037import org.apache.maven.plugin.version.PluginVersionRequest;
038import org.apache.maven.plugin.version.PluginVersionResolutionException;
039import org.apache.maven.plugin.version.PluginVersionResolver;
040import org.apache.maven.project.MavenProject;
041import org.codehaus.plexus.component.annotations.Component;
042import org.codehaus.plexus.component.annotations.Requirement;
043import org.codehaus.plexus.configuration.PlexusConfiguration;
044import org.codehaus.plexus.logging.Logger;
045import org.codehaus.plexus.util.xml.Xpp3Dom;
046
047import java.util.ArrayList;
048import java.util.Collection;
049import java.util.StringTokenizer;
050
051/**
052 * Resolves dependencies for the artifacts in context of the lifecycle build
053 *
054 * @since 3.0
055 * @author Benjamin Bentmann
056 * @author Jason van Zyl
057 * @author jdcasey
058 * @author Kristian Rosenvold (extracted class only)
059 *         <p/>
060 *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
061 */
062@Component( role = MojoDescriptorCreator.class )
063public class MojoDescriptorCreator
064{
065
066    @Requirement
067    private Logger logger;
068
069    @Requirement
070    private PluginVersionResolver pluginVersionResolver;
071
072    @Requirement
073    private BuildPluginManager pluginManager;
074
075    @Requirement
076    private PluginPrefixResolver pluginPrefixResolver;
077
078    @Requirement
079    private LifecyclePluginResolver lifecyclePluginResolver;
080
081    public MojoDescriptorCreator()
082    {
083    }
084
085    public MojoDescriptorCreator( PluginVersionResolver pluginVersionResolver, BuildPluginManager pluginManager,
086                                  PluginPrefixResolver pluginPrefixResolver,
087                                  LifecyclePluginResolver lifecyclePluginResolver )
088    {
089        this.pluginVersionResolver = pluginVersionResolver;
090        this.pluginManager = pluginManager;
091        this.pluginPrefixResolver = pluginPrefixResolver;
092        this.lifecyclePluginResolver = lifecyclePluginResolver;
093    }
094
095    private Plugin findPlugin( String groupId, String artifactId, Collection<Plugin> plugins )
096    {
097        for ( Plugin plugin : plugins )
098        {
099            if ( artifactId.equals( plugin.getArtifactId() ) && groupId.equals( plugin.getGroupId() ) )
100            {
101                return plugin;
102            }
103        }
104
105        return null;
106    }
107
108    public static Xpp3Dom convert( MojoDescriptor mojoDescriptor )
109    {
110        Xpp3Dom dom = new Xpp3Dom( "configuration" );
111
112        PlexusConfiguration c = mojoDescriptor.getMojoConfiguration();
113
114        PlexusConfiguration[] ces = c.getChildren();
115
116        if ( ces != null )
117        {
118            for ( PlexusConfiguration ce : ces )
119            {
120                String value = ce.getValue( null );
121                String defaultValue = ce.getAttribute( "default-value", null );
122                if ( value != null || defaultValue != null )
123                {
124                    Xpp3Dom e = new Xpp3Dom( ce.getName() );
125                    e.setValue( value );
126                    if ( defaultValue != null )
127                    {
128                        e.setAttribute( "default-value", defaultValue );
129                    }
130                    dom.addChild( e );
131                }
132            }
133        }
134
135        return dom;
136    }
137
138    // org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process@executionId
139
140    public MojoDescriptor getMojoDescriptor( String task, MavenSession session, MavenProject project )
141        throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
142        MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
143        PluginVersionResolutionException
144    {
145        String goal = null;
146
147        Plugin plugin = null;
148
149        StringTokenizer tok = new StringTokenizer( task, ":" );
150
151        int numTokens = tok.countTokens();
152
153        if ( numTokens >= 4 )
154        {
155            // We have everything that we need
156            //
157            // org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
158            //
159            // groupId
160            // artifactId
161            // version
162            // goal
163            //
164            plugin = new Plugin();
165            plugin.setGroupId( tok.nextToken() );
166            plugin.setArtifactId( tok.nextToken() );
167            plugin.setVersion( tok.nextToken() );
168            goal = tok.nextToken();
169
170            // This won't be valid, but it constructs something easy to read in the error message
171            while ( tok.hasMoreTokens() )
172            {
173                goal += ":" + tok.nextToken();
174            }
175        }
176        else if ( numTokens == 3 )
177        {
178            // We have everything that we need except the version
179            //
180            // org.apache.maven.plugins:maven-remote-resources-plugin:???:process
181            //
182            // groupId
183            // artifactId
184            // ???
185            // goal
186            //
187            plugin = new Plugin();
188            plugin.setGroupId( tok.nextToken() );
189            plugin.setArtifactId( tok.nextToken() );
190            goal = tok.nextToken();
191        }
192        else if ( numTokens <= 2 )
193        {
194            // We have a prefix and goal
195            //
196            // idea:idea
197            //
198            String prefix = tok.nextToken();
199
200            if ( numTokens == 2 )
201            {
202                goal = tok.nextToken();
203            }
204            else
205            {
206                // goal was missing - pass through to MojoNotFoundException
207                goal = "";
208            }
209
210            // This is the case where someone has executed a single goal from the command line
211            // of the form:
212            //
213            // mvn remote-resources:process
214            //
215            // From the metadata stored on the server which has been created as part of a standard
216            // Maven plugin deployment we will find the right PluginDescriptor from the remote
217            // repository.
218
219            plugin = findPluginForPrefix( prefix, session );
220        }
221
222        int executionIdx = goal.indexOf( '@' );
223        if ( executionIdx > 0 )
224        {
225            goal = goal.substring( 0, executionIdx );
226        }
227
228        injectPluginDeclarationFromProject( plugin, project );
229
230        // If there is no version to be found then we need to look in the repository metadata for
231        // this plugin and see what's specified as the latest release.
232        //
233        if ( plugin.getVersion() == null )
234        {
235            resolvePluginVersion( plugin, session, project );
236        }
237
238        return pluginManager.getMojoDescriptor( plugin, goal, project.getRemotePluginRepositories(),
239                                                session.getRepositorySession() );
240    }
241
242    // TODO: take repo mans into account as one may be aggregating prefixes of many
243    // TODO: collect at the root of the repository, read the one at the root, and fetch remote if something is missing
244    // or the user forces the issue
245
246    public Plugin findPluginForPrefix( String prefix, MavenSession session )
247        throws NoPluginFoundForPrefixException
248    {
249        // [prefix]:[goal]
250
251        if ( session.getCurrentProject() != null )
252        {
253            try
254            {
255                lifecyclePluginResolver.resolveMissingPluginVersions( session.getCurrentProject(), session );
256            }
257            catch ( PluginVersionResolutionException e )
258            {
259                // not critical here
260                logger.debug( e.getMessage(), e );
261            }
262        }
263
264        PluginPrefixRequest prefixRequest = new DefaultPluginPrefixRequest( prefix, session );
265        PluginPrefixResult prefixResult = pluginPrefixResolver.resolve( prefixRequest );
266
267        Plugin plugin = new Plugin();
268        plugin.setGroupId( prefixResult.getGroupId() );
269        plugin.setArtifactId( prefixResult.getArtifactId() );
270
271        return plugin;
272    }
273
274    private void resolvePluginVersion( Plugin plugin, MavenSession session, MavenProject project )
275        throws PluginVersionResolutionException
276    {
277        PluginVersionRequest versionRequest =
278            new DefaultPluginVersionRequest( plugin, session.getRepositorySession(),
279                                             project.getRemotePluginRepositories() );
280        plugin.setVersion( pluginVersionResolver.resolve( versionRequest ).getVersion() );
281    }
282
283    private void injectPluginDeclarationFromProject( Plugin plugin, MavenProject project )
284    {
285        Plugin pluginInPom = findPlugin( plugin, project.getBuildPlugins() );
286
287        if ( pluginInPom == null && project.getPluginManagement() != null )
288        {
289            pluginInPom = findPlugin( plugin, project.getPluginManagement().getPlugins() );
290        }
291
292        if ( pluginInPom != null )
293        {
294            if ( plugin.getVersion() == null )
295            {
296                plugin.setVersion( pluginInPom.getVersion() );
297            }
298
299            plugin.setDependencies( new ArrayList<>( pluginInPom.getDependencies() ) );
300        }
301    }
302
303    private Plugin findPlugin( Plugin plugin, Collection<Plugin> plugins )
304    {
305        return findPlugin( plugin.getGroupId(), plugin.getArtifactId(), plugins );
306    }
307
308}