View Javadoc
1   package org.apache.maven.plugin.dependency.fromDependencies;
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.artifact.Artifact;
23  import org.apache.maven.artifact.installer.ArtifactInstallationException;
24  import org.apache.maven.artifact.installer.ArtifactInstaller;
25  import org.apache.maven.artifact.repository.ArtifactRepository;
26  import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
27  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.plugin.dependency.utils.DependencyStatusSets;
30  import org.apache.maven.plugin.dependency.utils.DependencyUtil;
31  import org.apache.maven.plugin.dependency.utils.filters.DestFileFilter;
32  import org.apache.maven.plugins.annotations.Component;
33  import org.apache.maven.plugins.annotations.LifecyclePhase;
34  import org.apache.maven.plugins.annotations.Mojo;
35  import org.apache.maven.plugins.annotations.Parameter;
36  import org.apache.maven.plugins.annotations.ResolutionScope;
37  import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
38  
39  import java.io.File;
40  import java.net.MalformedURLException;
41  import java.util.Map;
42  import java.util.Set;
43  
44  /**
45   * Goal that copies the project dependencies from the repository to a defined
46   * location.
47   *
48   * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
49   * @version $Id: CopyDependenciesMojo.html 937155 2015-01-21 21:53:50Z khmarbaise $
50   * @since 1.0
51   */
52  @Mojo( name = "copy-dependencies", requiresDependencyResolution = ResolutionScope.TEST,
53         defaultPhase = LifecyclePhase.PROCESS_SOURCES, threadSafe = true )
54  public class CopyDependenciesMojo
55      extends AbstractFromDependenciesMojo
56  {
57      /**
58       * Also copy the pom of each artifact.
59       *
60       * @since 2.0
61       */
62      @Parameter( property = "mdep.copyPom", defaultValue = "false" )
63      protected boolean copyPom = true;
64  
65      /**
66       *
67       */
68      @Component
69      protected ArtifactInstaller installer;
70  
71      /**
72       *
73       */
74      @Component
75      protected ArtifactRepositoryFactory repositoryFactory;
76  
77      /**
78       *
79       */
80      @Component( role = ArtifactRepositoryLayout.class )
81      private Map<String, ArtifactRepositoryLayout> repositoryLayouts;
82  
83  
84      /**
85       * Either append the artifact's baseVersion or uniqueVersion to the filename.
86       * Will only be used if {@link #isStripVersion()} is {@code false}.
87       * @since 2.6
88       */
89      @Parameter( property = "mdep.useBaseVersion", defaultValue = "true" )
90      protected boolean useBaseVersion = true;
91  
92      /**
93       * Add parent poms to the list of copied dependencies (both current project pom parents and dependencies parents).
94       * @since 2.8
95       */
96      @Parameter( property = "mdep.addParentPoms", defaultValue = "false" )
97      protected boolean addParentPoms;
98  
99      /**
100      * <i>not used in this goal</i>
101      */
102     @Parameter
103     protected boolean useJvmChmod = true;
104 
105     /**
106      * <i>not used in this goal</i>
107      */
108     @Parameter
109     protected boolean ignorePermissions;
110 
111     /**
112      * Main entry into mojo. Gets the list of dependencies and iterates through
113      * calling copyArtifact.
114      *
115      * @throws MojoExecutionException with a message if an error occurs.
116      * @see #getDependencies
117      * @see #copyArtifact(Artifact, boolean)
118      */
119     protected void doExecute()
120         throws MojoExecutionException
121     {
122         DependencyStatusSets dss = getDependencySets( this.failOnMissingClassifierArtifact, addParentPoms );
123         Set<Artifact> artifacts = dss.getResolvedDependencies();
124 
125         if ( !useRepositoryLayout )
126         {
127             for ( Artifact artifact : artifacts )
128             {
129                 copyArtifact( artifact, isStripVersion(), this.prependGroupId, this.useBaseVersion,
130                               this.stripClassifier );
131             }
132         }
133         else
134         {
135             try
136             {
137                 ArtifactRepository targetRepository =
138                     repositoryFactory.createDeploymentArtifactRepository( "local",
139                                                                           outputDirectory.toURL().toExternalForm(),
140                                                                           repositoryLayouts.get( "default" ),
141                                                                           false /* uniqueVersion */ );
142                 for ( Artifact artifact : artifacts )
143                 {
144                     installArtifact( artifact, targetRepository );
145                 }
146             }
147             catch ( MalformedURLException e )
148             {
149                 throw new MojoExecutionException( "Could not create outputDirectory repository", e );
150             }
151         }
152 
153         Set<Artifact> skippedArtifacts = dss.getSkippedDependencies();
154         for ( Artifact artifact : skippedArtifacts )
155         {
156             getLog().info( artifact.getId() + " already exists in destination." ) ;
157         }
158 
159         if ( isCopyPom() && !useRepositoryLayout )
160         {
161             copyPoms( getOutputDirectory(), artifacts, this.stripVersion );
162             copyPoms( getOutputDirectory(), skippedArtifacts,
163                       this.stripVersion, this.stripClassifier );  // Artifacts that already exist may not yet have poms
164         }
165     }
166 
167     /**
168      * install the artifact and the corresponding pom if copyPoms=true
169      * 
170      * @param artifact
171      * @param targetRepository
172      */
173     private void installArtifact( Artifact artifact, ArtifactRepository targetRepository )
174     {
175         try
176         {
177             if ( "pom".equals( artifact.getType() ) )
178             {
179                 installer.install( artifact.getFile(), artifact, targetRepository );
180                 installBaseSnapshot( artifact, targetRepository );
181             }
182             else
183             {
184                 installer.install( artifact.getFile(), artifact, targetRepository );
185                 installBaseSnapshot( artifact, targetRepository );
186 
187                 if ( isCopyPom() )
188                 {
189                     Artifact pomArtifact = getResolvedPomArtifact( artifact );
190                     if ( pomArtifact.getFile() != null && pomArtifact.getFile().exists() )
191                     {
192                         installer.install( pomArtifact.getFile(), pomArtifact, targetRepository );
193                         installBaseSnapshot( pomArtifact, targetRepository );
194                     }
195                 }
196             }
197         }
198         catch ( ArtifactInstallationException e )
199         {
200             getLog().warn( "unable to install " + artifact, e );
201         }
202     }
203 
204     private void installBaseSnapshot( Artifact artifact, ArtifactRepository targetRepository )
205         throws ArtifactInstallationException
206     {
207         if ( artifact.isSnapshot() && !artifact.getBaseVersion().equals( artifact.getVersion() ) )
208         {
209             Artifact baseArtifact =
210                 this.factory.createArtifact( artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion(),
211                                              artifact.getScope(), artifact.getType() );
212             installer.install( artifact.getFile(), baseArtifact, targetRepository );
213         }
214     }
215 
216     /**
217      * Copies the Artifact after building the destination file name if
218      * overridden. This method also checks if the classifier is set and adds it
219      * to the destination file name if needed.
220      *
221      * @param artifact       representing the object to be copied.
222      * @param removeVersion  specifies if the version should be removed from the file name
223      *                       when copying.
224      * @param prependGroupId specifies if the groupId should be prepend to the file while copying.
225      * @param useBaseVersion specifies if the baseVersion of the artifact should be used instead of the version.
226      * @throws MojoExecutionException with a message if an error occurs.
227      * @see DependencyUtil#copyFile(File, File, Log)
228      * @see DependencyUtil#getFormattedFileName(Artifact, boolean)
229      */
230     protected void copyArtifact( Artifact artifact, boolean removeVersion, boolean prependGroupId,
231                                  boolean useBaseVersion )
232         throws MojoExecutionException
233     {
234         copyArtifact( artifact, removeVersion, prependGroupId, useBaseVersion, false );
235     }
236 
237     /**
238      * Copies the Artifact after building the destination file name if
239      * overridden. This method also checks if the classifier is set and adds it
240      * to the destination file name if needed.
241      *
242      * @param artifact       representing the object to be copied.
243      * @param removeVersion  specifies if the version should be removed from the file name
244      *                       when copying.
245      * @param prependGroupId specifies if the groupId should be prepend to the file while copying.
246      * @param useBaseVersion specifies if the baseVersion of the artifact should be used instead of the version.
247      * @param removeClassifier specifies if the classifier should be removed from the file name when copying.
248      * @throws MojoExecutionException with a message if an error occurs.
249      * @see DependencyUtil#copyFile(File, File, Log)
250      * @see DependencyUtil#getFormattedFileName(Artifact, boolean)
251      */
252     protected void copyArtifact( Artifact artifact, boolean removeVersion, boolean prependGroupId,
253                                  boolean useBaseVersion, boolean removeClassifier )
254         throws MojoExecutionException
255     {
256 
257         String destFileName = DependencyUtil.getFormattedFileName( artifact, removeVersion, prependGroupId, 
258                 useBaseVersion, removeClassifier );
259 
260         File destDir;
261         destDir = DependencyUtil.getFormattedOutputDirectory( useSubDirectoryPerScope, useSubDirectoryPerType,
262                                                               useSubDirectoryPerArtifact, useRepositoryLayout,
263                                                               stripVersion, outputDirectory, artifact );
264         File destFile = new File( destDir, destFileName );
265 
266         copyFile( artifact.getFile(), destFile );
267     }
268     
269     /**
270      * Copy the pom files associated with the artifacts.
271      */
272     public void copyPoms( File destDir, Set<Artifact> artifacts, boolean removeVersion )
273         throws MojoExecutionException
274 
275     {
276         copyPoms( destDir, artifacts, removeVersion, false );
277     }
278     
279     /**
280      * Copy the pom files associated with the artifacts.
281      */
282     public void copyPoms( File destDir, Set<Artifact> artifacts, boolean removeVersion, boolean removeClassifier )
283         throws MojoExecutionException
284 
285     {
286         for ( Artifact artifact : artifacts )
287         {
288             Artifact pomArtifact = getResolvedPomArtifact( artifact );
289 
290             // Copy the pom
291             if ( pomArtifact.getFile() != null && pomArtifact.getFile().exists() )
292             {
293                 File pomDestFile =
294                     new File( destDir, DependencyUtil.getFormattedFileName( pomArtifact, removeVersion, prependGroupId,
295                                                                             useBaseVersion, removeClassifier ) );
296                 if ( !pomDestFile.exists() )
297                 {
298                     copyFile( pomArtifact.getFile(), pomDestFile );
299                 }
300             }
301         }
302     }
303 
304     protected Artifact getResolvedPomArtifact( Artifact artifact )
305     {
306         Artifact pomArtifact =
307             this.factory.createArtifact( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), "",
308                                          "pom" );
309         // Resolve the pom artifact using repos
310         try
311         {
312             this.resolver.resolve( pomArtifact, this.remoteRepos, this.getLocal() );
313         }
314         catch ( Exception e )
315         {
316             getLog().info( e.getMessage() );
317         }
318         return pomArtifact;
319     }
320 
321     protected ArtifactsFilter getMarkedArtifactFilter()
322     {
323         return new DestFileFilter( this.overWriteReleases, this.overWriteSnapshots, this.overWriteIfNewer,
324                                    this.useSubDirectoryPerArtifact, this.useSubDirectoryPerType,
325                                    this.useSubDirectoryPerScope, this.useRepositoryLayout, this.stripVersion,
326                                    this.outputDirectory );
327     }
328 
329     /**
330      * @return true, if the pom of each artifact must be copied
331      */
332     public boolean isCopyPom()
333     {
334         return this.copyPom;
335     }
336 
337     /**
338      * @param copyPom - true if the pom of each artifact must be copied
339      */
340     public void setCopyPom( boolean copyPom )
341     {
342         this.copyPom = copyPom;
343     }
344 }