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