View Javadoc
1   package org.apache.maven.plugins.dependency;
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 java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.regex.Matcher;
27  import java.util.regex.Pattern;
28  
29  import org.apache.maven.artifact.handler.ArtifactHandler;
30  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
31  import org.apache.maven.artifact.repository.ArtifactRepository;
32  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
33  import org.apache.maven.artifact.repository.MavenArtifactRepository;
34  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
35  import org.apache.maven.execution.MavenSession;
36  import org.apache.maven.plugin.AbstractMojo;
37  import org.apache.maven.plugin.MojoExecutionException;
38  import org.apache.maven.plugin.MojoFailureException;
39  import org.apache.maven.plugins.annotations.Component;
40  import org.apache.maven.plugins.annotations.Mojo;
41  import org.apache.maven.plugins.annotations.Parameter;
42  import org.apache.maven.project.DefaultProjectBuildingRequest;
43  import org.apache.maven.project.ProjectBuildingRequest;
44  import org.apache.maven.shared.artifact.ArtifactCoordinate;
45  import org.apache.maven.shared.artifact.DefaultArtifactCoordinate;
46  import org.apache.maven.shared.artifact.resolve.ArtifactResolver;
47  import org.apache.maven.shared.artifact.resolve.ArtifactResolverException;
48  import org.apache.maven.shared.dependencies.DefaultDependableCoordinate;
49  import org.apache.maven.shared.dependencies.DependableCoordinate;
50  import org.apache.maven.shared.dependencies.resolve.DependencyResolver;
51  import org.apache.maven.shared.dependencies.resolve.DependencyResolverException;
52  import org.codehaus.plexus.util.StringUtils;
53  
54  /**
55   * Resolves a single artifact, eventually transitively, from the specified remote repositories. Caveat: will always
56   * check the central repository defined in the super pom. You could use a mirror entry in your <code>settings.xml</code>
57   */
58  @Mojo( name = "get", requiresProject = false, threadSafe = true )
59  public class GetMojo
60      extends AbstractMojo
61  {
62      private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile( "(.+)::(.*)::(.+)" );
63  
64      @Parameter( defaultValue = "${session}", required = true, readonly = true )
65      private MavenSession session;
66  
67      /**
68       *
69       */
70      @Component
71      private ArtifactResolver artifactResolver;
72  
73      /**
74      *
75      */
76      @Component
77      private DependencyResolver dependencyResolver;
78  
79      @Component
80      private ArtifactHandlerManager artifactHandlerManager;
81  
82      /**
83       * Map that contains the layouts.
84       */
85      @Component( role = ArtifactRepositoryLayout.class )
86      private Map<String, ArtifactRepositoryLayout> repositoryLayouts;
87  
88      private DefaultDependableCoordinate coordinate = new DefaultDependableCoordinate();
89  
90      /**
91       * The groupId of the artifact to download. Ignored if {@link #artifact} is used.
92       */
93      @Parameter( property = "groupId" )
94      private String groupId;
95  
96      /**
97       * The artifactId of the artifact to download. Ignored if {@link #artifact} is used.
98       */
99      @Parameter( property = "artifactId" )
100     private String artifactId;
101 
102     /**
103      * The version of the artifact to download. Ignored if {@link #artifact} is used.
104      */
105     @Parameter( property = "version" )
106     private String version;
107 
108     /**
109      * The classifier of the artifact to download. Ignored if {@link #artifact} is used.
110      *
111      * @since 2.3
112      */
113     @Parameter( property = "classifier" )
114     private String classifier;
115 
116     /**
117      * The packaging of the artifact to download. Ignored if {@link #artifact} is used.
118      */
119     @Parameter( property = "packaging", defaultValue = "jar" )
120     private String packaging = "jar";
121 
122     /**
123      * Repositories in the format id::[layout]::url or just url, separated by comma. ie.
124      * central::default::http://repo1.maven.apache.org/maven2,myrepo::::http://repo.acme.com,http://repo.acme2.com
125      */
126     @Parameter( property = "remoteRepositories" )
127     private String remoteRepositories;
128 
129     /**
130      * A string of the form groupId:artifactId:version[:packaging[:classifier]].
131      */
132     @Parameter( property = "artifact" )
133     private String artifact;
134 
135     /**
136      *
137      */
138     @Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true )
139     private List<ArtifactRepository> pomRemoteRepositories;
140 
141     /**
142      * Download transitively, retrieving the specified artifact and all of its dependencies.
143      */
144     @Parameter( property = "transitive", defaultValue = "true" )
145     private boolean transitive = true;
146 
147     /**
148      * Skip plugin execution completely.
149      *
150      * @since 2.7
151      */
152     @Parameter( property = "mdep.skip", defaultValue = "false" )
153     private boolean skip;
154 
155     @Override
156     public void execute()
157         throws MojoExecutionException, MojoFailureException
158     {
159         if ( isSkip() )
160         {
161             getLog().info( "Skipping plugin execution" );
162             return;
163         }
164 
165         if ( coordinate.getArtifactId() == null && artifact == null )
166         {
167             throw new MojoFailureException( "You must specify an artifact, "
168                 + "e.g. -Dartifact=org.apache.maven.plugins:maven-downloader-plugin:1.0" );
169         }
170         if ( artifact != null )
171         {
172             String[] tokens = StringUtils.split( artifact, ":" );
173             if ( tokens.length < 3 || tokens.length > 5 )
174             {
175                 throw new MojoFailureException( "Invalid artifact, you must specify "
176                     + "groupId:artifactId:version[:packaging[:classifier]] " + artifact );
177             }
178             coordinate.setGroupId( tokens[0] );
179             coordinate.setArtifactId( tokens[1] );
180             coordinate.setVersion( tokens[2] );
181             if ( tokens.length >= 4 )
182             {
183                 coordinate.setType( tokens[3] );
184             }
185             if ( tokens.length == 5 )
186             {
187                 coordinate.setClassifier( tokens[4] );
188             }
189         }
190 
191         ArtifactRepositoryPolicy always =
192             new ArtifactRepositoryPolicy( true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS,
193                                           ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
194 
195         List<ArtifactRepository> repoList = new ArrayList<ArtifactRepository>();
196 
197         if ( pomRemoteRepositories != null )
198         {
199             repoList.addAll( pomRemoteRepositories );
200         }
201 
202         if ( remoteRepositories != null )
203         {
204             // Use the same format as in the deploy plugin id::layout::url
205             List<String> repos = Arrays.asList( StringUtils.split( remoteRepositories, "," ) );
206             for ( String repo : repos )
207             {
208                 repoList.add( parseRepository( repo, always ) );
209             }
210         }
211 
212         try
213         {
214             ProjectBuildingRequest buildingRequest =
215                 new DefaultProjectBuildingRequest( session.getProjectBuildingRequest() );
216 
217             buildingRequest.setRemoteRepositories( repoList );
218 
219             if ( transitive )
220             {
221                 getLog().info( "Resolving " + coordinate + " with transitive dependencies" );
222                 dependencyResolver.resolveDependencies( buildingRequest, coordinate, null );
223             }
224             else
225             {
226                 getLog().info( "Resolving " + coordinate );
227                 artifactResolver.resolveArtifact( buildingRequest, toArtifactCoordinate( coordinate ) );
228             }
229         }
230         catch ( ArtifactResolverException e )
231         {
232             throw new MojoExecutionException( "Couldn't download artifact: " + e.getMessage(), e );
233         }
234         catch ( DependencyResolverException e )
235         {
236             throw new MojoExecutionException( "Couldn't download artifact: " + e.getMessage(), e );
237         }
238     }
239 
240     private ArtifactCoordinate toArtifactCoordinate( DependableCoordinate dependableCoordinate )
241     {
242         ArtifactHandler artifactHandler = artifactHandlerManager.getArtifactHandler( dependableCoordinate.getType() );
243         DefaultArtifactCoordinate artifactCoordinate = new DefaultArtifactCoordinate();
244         artifactCoordinate.setGroupId( dependableCoordinate.getGroupId() );
245         artifactCoordinate.setArtifactId( dependableCoordinate.getArtifactId() );
246         artifactCoordinate.setVersion( dependableCoordinate.getVersion() );
247         artifactCoordinate.setClassifier( dependableCoordinate.getClassifier() );
248         artifactCoordinate.setExtension( artifactHandler.getExtension() );
249         return artifactCoordinate;
250     }
251 
252     ArtifactRepository parseRepository( String repo, ArtifactRepositoryPolicy policy )
253         throws MojoFailureException
254     {
255         // if it's a simple url
256         String id = "temp";
257         ArtifactRepositoryLayout layout = getLayout( "default" );
258         String url = repo;
259 
260         // if it's an extended repo URL of the form id::layout::url
261         if ( repo.contains( "::" ) )
262         {
263             Matcher matcher = ALT_REPO_SYNTAX_PATTERN.matcher( repo );
264             if ( !matcher.matches() )
265             {
266                 throw new MojoFailureException( repo, "Invalid syntax for repository: " + repo,
267                                                 "Invalid syntax for repository. Use \"id::layout::url\" or \"URL\"." );
268             }
269 
270             id = matcher.group( 1 ).trim();
271             if ( !StringUtils.isEmpty( matcher.group( 2 ) ) )
272             {
273                 layout = getLayout( matcher.group( 2 ).trim() );
274             }
275             url = matcher.group( 3 ).trim();
276         }
277         return new MavenArtifactRepository( id, url, layout, policy, policy );
278     }
279 
280     private ArtifactRepositoryLayout getLayout( String id )
281         throws MojoFailureException
282     {
283         ArtifactRepositoryLayout layout = repositoryLayouts.get( id );
284 
285         if ( layout == null )
286         {
287             throw new MojoFailureException( id, "Invalid repository layout", "Invalid repository layout: " + id );
288         }
289 
290         return layout;
291     }
292 
293     protected boolean isSkip()
294     {
295         return skip;
296     }
297 
298     // @Parameter( alias = "groupId" )
299     public void setGroupId( String groupId )
300     {
301         this.coordinate.setGroupId( groupId );
302     }
303 
304     // @Parameter( alias = "artifactId" )
305     public void setArtifactId( String artifactId )
306     {
307         this.coordinate.setArtifactId( artifactId );
308     }
309 
310     // @Parameter( alias = "version" )
311     public void setVersion( String version )
312     {
313         this.coordinate.setVersion( version );
314     }
315 
316     // @Parameter( alias = "classifier" )
317     public void setClassifier( String classifier )
318     {
319         this.coordinate.setClassifier( classifier );
320     }
321 
322     // @Parameter( alias = "packaging" )
323     public void setPackaging( String type )
324     {
325         this.coordinate.setType( type );
326     }
327 
328 }