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