View Javadoc
1   package org.apache.maven.plugin.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 org.apache.commons.io.FileUtils;
23  import org.apache.maven.artifact.Artifact;
24  import org.apache.maven.artifact.factory.ArtifactFactory;
25  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
26  import org.apache.maven.artifact.repository.ArtifactRepository;
27  import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
28  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
29  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
30  import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException;
31  import org.apache.maven.artifact.resolver.ArtifactResolver;
32  import org.apache.maven.plugin.AbstractMojo;
33  import org.apache.maven.plugin.MojoExecutionException;
34  import org.apache.maven.plugin.MojoFailureException;
35  import org.apache.maven.plugins.annotations.Component;
36  import org.apache.maven.plugins.annotations.Mojo;
37  import org.apache.maven.plugins.annotations.Parameter;
38  import org.codehaus.plexus.util.StringUtils;
39  
40  import java.io.File;
41  import java.io.IOException;
42  import java.util.ArrayList;
43  import java.util.Arrays;
44  import java.util.Collections;
45  import java.util.List;
46  import java.util.Map;
47  import java.util.regex.Matcher;
48  import java.util.regex.Pattern;
49  
50  /**
51   * Resolves a single artifact, eventually transitively, from the specified remote repositories.
52   * Caveat: will always check thecentral repository defined in the super pom. You could use a mirror entry in your
53   * <code>settings.xml</code>
54   */
55  @Mojo( name = "get", requiresProject = false, threadSafe = true )
56  public class GetMojo
57      extends AbstractMojo
58  {
59      private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile( "(.+)::(.*)::(.+)" );
60  
61      /**
62       *
63       */
64      @Component
65      private ArtifactFactory artifactFactory;
66  
67      /**
68       *
69       */
70      @Component
71      private ArtifactResolver artifactResolver;
72  
73      /**
74       *
75       */
76      @Component
77      private ArtifactRepositoryFactory artifactRepositoryFactory;
78  
79      /**
80       * Map that contains the layouts.
81       */
82      @Component( role = ArtifactRepositoryLayout.class )
83      private Map<String, ArtifactRepositoryLayout> repositoryLayouts;
84  
85      /**
86       *
87       */
88      @Component
89      private ArtifactMetadataSource source;
90  
91      /**
92       *
93       */
94      @Parameter( defaultValue = "${localRepository}", readonly = true )
95      private ArtifactRepository localRepository;
96  
97      /**
98       * The groupId of the artifact to download. Ignored if {@link #artifact} is used.
99       */
100     @Parameter( property = "groupId" )
101     private String groupId;
102 
103     /**
104      * The artifactId of the artifact to download. Ignored if {@link #artifact} is used.
105      */
106     @Parameter( property = "artifactId" )
107     private String artifactId;
108 
109     /**
110      * The version of the artifact to download. Ignored if {@link #artifact} is used.
111      */
112     @Parameter( property = "version" )
113     private String version;
114 
115     /**
116      * The classifier of the artifact to download. Ignored if {@link #artifact} is used.
117      *
118      * @since 2.3
119      */
120     @Parameter( property = "classifier" )
121     private String classifier;
122 
123     /**
124      * The packaging of the artifact to download. Ignored if {@link #artifact} is used.
125      */
126     @Parameter( property = "packaging", defaultValue = "jar" )
127     private String packaging = "jar";
128 
129     /**
130      * The id of the repository from which we'll download the artifact
131      *
132      * @deprecated Use remoteRepositories
133      */
134     @Parameter( property = "repoId", defaultValue = "temp" )
135     private String repositoryId = "temp";
136 
137     /**
138      * The url of the repository from which we'll download the artifact. DEPRECATED Use remoteRepositories
139      *
140      * @deprecated Use remoteRepositories
141      */
142     @Parameter( property = "repoUrl" )
143     private String repositoryUrl;
144 
145     /**
146      * Repositories in the format id::[layout]::url or just url, separated by comma.
147      * ie. central::default::http://repo1.maven.apache.org/maven2,myrepo::::http://repo.acme.com,http://repo.acme2.com
148      */
149     @Parameter( property = "remoteRepositories" )
150     private String remoteRepositories;
151 
152     /**
153      * A string of the form groupId:artifactId:version[:packaging][:classifier].
154      */
155     @Parameter( property = "artifact" )
156     private String artifact;
157 
158     /**
159      * The destination file or directory to copy the artifact to, if other than the local repository
160      *
161      * @since 2.4
162      * @deprecated if you need to copy the resolved artifact, use dependency:copy
163      */
164     @Parameter( property = "dest" )
165     private String destination;
166 
167     /**
168      *
169      */
170     @Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true )
171     private List<ArtifactRepository> pomRemoteRepositories;
172 
173     /**
174      * Download transitively, retrieving the specified artifact and all of its dependencies.
175      */
176     @Parameter( property = "transitive", defaultValue = "true" )
177     private boolean transitive = true;
178 
179     /**
180      * Skip plugin execution completely.
181      *
182      * @since 2.7
183      */
184     @Parameter( property = "mdep.skip", defaultValue = "false" )
185     private boolean skip;
186 
187     public void execute()
188         throws MojoExecutionException, MojoFailureException
189     {
190         if ( isSkip() )
191         {
192             getLog().info( "Skipping plugin execution" );
193             return;
194         }
195 
196         if ( artifactId == null && artifact == null )
197         {
198             throw new MojoFailureException( "You must specify an artifact, "
199                 + "e.g. -Dartifact=org.apache.maven.plugins:maven-downloader-plugin:1.0" );
200         }
201         if ( artifact != null )
202         {
203             String[] tokens = StringUtils.split( artifact, ":" );
204             if ( tokens.length < 3 || tokens.length > 5 )
205             {
206                 throw new MojoFailureException(
207                     "Invalid artifact, you must specify groupId:artifactId:version[:packaging][:classifier] "
208                         + artifact );
209             }
210             groupId = tokens[0];
211             artifactId = tokens[1];
212             version = tokens[2];
213             if ( tokens.length >= 4 )
214             {
215                 packaging = tokens[3];
216             }
217             if ( tokens.length == 5 )
218             {
219                 classifier = tokens[4];
220             }
221             else
222             {
223                 classifier = null;
224             }
225         }
226 
227         Artifact toDownload = classifier == null
228             ? artifactFactory.createBuildArtifact( groupId, artifactId, version, packaging )
229             : artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, packaging, classifier );
230         Artifact dummyOriginatingArtifact =
231             artifactFactory.createBuildArtifact( "org.apache.maven.plugins", "maven-downloader-plugin", "1.0", "jar" );
232 
233         ArtifactRepositoryPolicy always =
234             new ArtifactRepositoryPolicy( true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS,
235                                           ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
236 
237         List<ArtifactRepository> repoList = new ArrayList<ArtifactRepository>();
238 
239         if ( pomRemoteRepositories != null )
240         {
241             repoList.addAll( pomRemoteRepositories );
242         }
243 
244         if ( remoteRepositories != null )
245         {
246             // Use the same format as in the deploy plugin id::layout::url
247             List<String> repos = Arrays.asList( StringUtils.split( remoteRepositories, "," ) );
248             for ( String repo : repos )
249             {
250                 repoList.add( parseRepository( repo, always ) );
251             }
252         }
253 
254         if ( repositoryUrl != null )
255         {
256             getLog().warn( "repositoryUrl parameter is deprecated. Use remoteRepositories instead" );
257             ArtifactRepository remoteRepo =
258                 artifactRepositoryFactory.createArtifactRepository( repositoryId, repositoryUrl, getLayout( "default" ),
259                                                                     always, always );
260             repoList.add( remoteRepo );
261         }
262 
263         try
264         {
265             if ( transitive )
266             {
267                 getLog().info( "Resolving " + toDownload + " with transitive dependencies" );
268                 artifactResolver.resolveTransitively( Collections.singleton( toDownload ), dummyOriginatingArtifact,
269                                                       repoList, localRepository, source );
270             }
271             else
272             {
273                 getLog().info( "Resolving " + toDownload );
274                 artifactResolver.resolve( toDownload, repoList, localRepository );
275             }
276         }
277         catch ( AbstractArtifactResolutionException e )
278         {
279             throw new MojoExecutionException( "Couldn't download artifact: " + e.getMessage(), e );
280         }
281 
282         if ( destination != null )
283         {
284             getLog().warn( "destination/dest parameter is deprecated: it will disappear in future version." );
285 
286             File src = toDownload.getFile();
287             File dest = new File( destination );
288 
289             getLog().info( "Copying " + src.getAbsolutePath() + " to " + dest.getAbsolutePath() );
290             if ( transitive )
291             {
292                 getLog().warn( "Notice transitive dependencies won't be copied." );
293             }
294 
295             try
296             {
297                 if ( dest.isDirectory() )
298                 {
299                     FileUtils.copyFileToDirectory( src, dest );
300                 }
301                 else
302                 {
303                     FileUtils.copyFile( src, dest );
304                 } 
305             }
306             catch ( IOException e )
307             {
308                 throw new MojoExecutionException(
309                     "Couldn't copy downloaded artifact from " + src.getAbsolutePath() + " to " + dest.getAbsolutePath()
310                         + " : " + e.getMessage(), e );
311             }
312         }
313     }
314 
315     ArtifactRepository parseRepository( String repo, ArtifactRepositoryPolicy policy )
316         throws MojoFailureException
317     {
318         // if it's a simple url
319         String id = repositoryId;
320         ArtifactRepositoryLayout layout = getLayout( "default" );
321         String url = repo;
322 
323         // if it's an extended repo URL of the form id::layout::url
324         if ( repo.contains( "::" ) )
325         {
326             Matcher matcher = ALT_REPO_SYNTAX_PATTERN.matcher( repo );
327             if ( !matcher.matches() )
328             {
329                 throw new MojoFailureException( repo, "Invalid syntax for repository: " + repo,
330                                                 "Invalid syntax for repository. Use \"id::layout::url\" or \"URL\"." );
331             }
332 
333             id = matcher.group( 1 ).trim();
334             if ( !StringUtils.isEmpty( matcher.group( 2 ) ) )
335             {
336                 layout = getLayout( matcher.group( 2 ).trim() );
337             }
338             url = matcher.group( 3 ).trim();
339         }
340         return artifactRepositoryFactory.createArtifactRepository( id, url, layout, policy, policy );
341     }
342 
343     private ArtifactRepositoryLayout getLayout( String id )
344         throws MojoFailureException
345     {
346         ArtifactRepositoryLayout layout = repositoryLayouts.get( id );
347 
348         if ( layout == null )
349         {
350             throw new MojoFailureException( id, "Invalid repository layout", "Invalid repository layout: " + id );
351         }
352 
353         return layout;
354     }
355 
356     public boolean isSkip()
357     {
358         return skip;
359 }
360 
361     public void setSkip( boolean skip )
362     {
363         this.skip = skip;
364     }
365 
366 }