View Javadoc
1   package org.apache.maven.lifecycle.internal;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.execution.MavenSession;
23  import org.apache.maven.model.Plugin;
24  import org.apache.maven.plugin.BuildPluginManager;
25  import org.apache.maven.plugin.InvalidPluginDescriptorException;
26  import org.apache.maven.plugin.MojoNotFoundException;
27  import org.apache.maven.plugin.PluginDescriptorParsingException;
28  import org.apache.maven.plugin.PluginNotFoundException;
29  import org.apache.maven.plugin.PluginResolutionException;
30  import org.apache.maven.plugin.descriptor.MojoDescriptor;
31  import org.apache.maven.plugin.prefix.DefaultPluginPrefixRequest;
32  import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
33  import org.apache.maven.plugin.prefix.PluginPrefixRequest;
34  import org.apache.maven.plugin.prefix.PluginPrefixResolver;
35  import org.apache.maven.plugin.prefix.PluginPrefixResult;
36  import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
37  import org.apache.maven.plugin.version.PluginVersionRequest;
38  import org.apache.maven.plugin.version.PluginVersionResolutionException;
39  import org.apache.maven.plugin.version.PluginVersionResolver;
40  import org.apache.maven.project.MavenProject;
41  import org.codehaus.plexus.component.annotations.Component;
42  import org.codehaus.plexus.component.annotations.Requirement;
43  import org.codehaus.plexus.configuration.PlexusConfiguration;
44  import org.codehaus.plexus.logging.Logger;
45  import org.codehaus.plexus.util.xml.Xpp3Dom;
46  
47  import java.util.ArrayList;
48  import java.util.Collection;
49  import java.util.StringTokenizer;
50  
51  /**
52   * <p>
53   * Resolves dependencies for the artifacts in context of the lifecycle build
54   * </p>
55   * <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
56   *
57   * @since 3.0
58   * @author Benjamin Bentmann
59   * @author Jason van Zyl
60   * @author jdcasey
61   * @author Kristian Rosenvold (extracted class only)
62   */
63  @Component( role = MojoDescriptorCreator.class )
64  public class MojoDescriptorCreator
65  {
66  
67      @Requirement
68      private Logger logger;
69  
70      @Requirement
71      private PluginVersionResolver pluginVersionResolver;
72  
73      @Requirement
74      private BuildPluginManager pluginManager;
75  
76      @Requirement
77      private PluginPrefixResolver pluginPrefixResolver;
78  
79      @Requirement
80      private LifecyclePluginResolver lifecyclePluginResolver;
81  
82      public MojoDescriptorCreator()
83      {
84      }
85  
86      public MojoDescriptorCreator( PluginVersionResolver pluginVersionResolver, BuildPluginManager pluginManager,
87                                    PluginPrefixResolver pluginPrefixResolver,
88                                    LifecyclePluginResolver lifecyclePluginResolver )
89      {
90          this.pluginVersionResolver = pluginVersionResolver;
91          this.pluginManager = pluginManager;
92          this.pluginPrefixResolver = pluginPrefixResolver;
93          this.lifecyclePluginResolver = lifecyclePluginResolver;
94      }
95  
96      private Plugin findPlugin( String groupId, String artifactId, Collection<Plugin> plugins )
97      {
98          for ( Plugin plugin : plugins )
99          {
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             // groupId:artifactId:goal or pluginPrefix:version:goal (since Maven 3.8.8)
180 
181             String firstToken = tok.nextToken();
182             // groupId or pluginPrefix? heuristics: groupId contains dot (.) but not pluginPrefix
183             if ( firstToken.contains( "." ) )
184             {
185                 // We have everything that we need except the version
186                 //
187                 // org.apache.maven.plugins:maven-remote-resources-plugin:???:process
188                 //
189                 // groupId
190                 // artifactId
191                 // ???
192                 // goal
193                 //
194                 plugin = new Plugin();
195                 plugin.setGroupId( firstToken );
196                 plugin.setArtifactId( tok.nextToken() );
197             }
198             else
199             {
200                 // pluginPrefix:version:goal, like remote-resources:3.5.0:process
201                 plugin = findPluginForPrefix( firstToken, session );
202                 plugin.setVersion( tok.nextToken() );
203             }
204             goal = tok.nextToken();
205         }
206         else if ( numTokens <= 2 )
207         {
208             // We have a prefix and goal
209             //
210             // idea:idea
211             //
212             String prefix = tok.nextToken();
213 
214             if ( numTokens == 2 )
215             {
216                 goal = tok.nextToken();
217             }
218             else
219             {
220                 // goal was missing - pass through to MojoNotFoundException
221                 goal = "";
222             }
223 
224             // This is the case where someone has executed a single goal from the command line
225             // of the form:
226             //
227             // mvn remote-resources:process
228             //
229             // From the metadata stored on the server which has been created as part of a standard
230             // Maven plugin deployment we will find the right PluginDescriptor from the remote
231             // repository.
232 
233             plugin = findPluginForPrefix( prefix, session );
234         }
235 
236         int executionIdx = goal.indexOf( '@' );
237         if ( executionIdx > 0 )
238         {
239             goal = goal.substring( 0, executionIdx );
240         }
241 
242         injectPluginDeclarationFromProject( plugin, project );
243 
244         // If there is no version to be found then we need to look in the repository metadata for
245         // this plugin and see what's specified as the latest release.
246         //
247         if ( plugin.getVersion() == null )
248         {
249             resolvePluginVersion( plugin, session, project );
250         }
251 
252         return pluginManager.getMojoDescriptor( plugin, goal, project.getRemotePluginRepositories(),
253                                                 session.getRepositorySession() );
254     }
255 
256     // TODO take repo mans into account as one may be aggregating prefixes of many
257     // TODO collect at the root of the repository, read the one at the root, and fetch remote if something is missing
258     // or the user forces the issue
259 
260     public Plugin findPluginForPrefix( String prefix, MavenSession session )
261         throws NoPluginFoundForPrefixException
262     {
263         // [prefix]:[goal]
264 
265         if ( session.getCurrentProject() != null )
266         {
267             try
268             {
269                 lifecyclePluginResolver.resolveMissingPluginVersions( session.getCurrentProject(), session );
270             }
271             catch ( PluginVersionResolutionException e )
272             {
273                 // not critical here
274                 logger.debug( e.getMessage(), e );
275             }
276         }
277 
278         PluginPrefixRequest prefixRequest = new DefaultPluginPrefixRequest( prefix, session );
279         PluginPrefixResult prefixResult = pluginPrefixResolver.resolve( prefixRequest );
280 
281         Plugin plugin = new Plugin();
282         plugin.setGroupId( prefixResult.getGroupId() );
283         plugin.setArtifactId( prefixResult.getArtifactId() );
284 
285         return plugin;
286     }
287 
288     private void resolvePluginVersion( Plugin plugin, MavenSession session, MavenProject project )
289         throws PluginVersionResolutionException
290     {
291         PluginVersionRequest versionRequest =
292             new DefaultPluginVersionRequest( plugin, session.getRepositorySession(),
293                                              project.getRemotePluginRepositories() );
294         plugin.setVersion( pluginVersionResolver.resolve( versionRequest ).getVersion() );
295     }
296 
297     private void injectPluginDeclarationFromProject( Plugin plugin, MavenProject project )
298     {
299         Plugin pluginInPom = findPlugin( plugin, project.getBuildPlugins() );
300 
301         if ( pluginInPom == null && project.getPluginManagement() != null )
302         {
303             pluginInPom = findPlugin( plugin, project.getPluginManagement().getPlugins() );
304         }
305 
306         if ( pluginInPom != null )
307         {
308             if ( plugin.getVersion() == null )
309             {
310                 plugin.setVersion( pluginInPom.getVersion() );
311             }
312 
313             plugin.setDependencies( new ArrayList<>( pluginInPom.getDependencies() ) );
314         }
315     }
316 
317     private Plugin findPlugin( Plugin plugin, Collection<Plugin> plugins )
318     {
319         return findPlugin( plugin.getGroupId(), plugin.getArtifactId(), plugins );
320     }
321 
322 }