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