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 org.apache.maven.artifact.Artifact;
23  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.plugins.dependency.utils.DependencyStatusSets;
26  import org.apache.maven.plugins.dependency.utils.DependencyUtil;
27  import org.apache.maven.plugins.dependency.utils.filters.DestFileFilter;
28  import org.apache.maven.plugins.annotations.Component;
29  import org.apache.maven.plugins.annotations.LifecyclePhase;
30  import org.apache.maven.plugins.annotations.Mojo;
31  import org.apache.maven.plugins.annotations.Parameter;
32  import org.apache.maven.plugins.annotations.ResolutionScope;
33  import org.apache.maven.project.ProjectBuildingRequest;
34  import org.apache.maven.shared.artifact.DefaultArtifactCoordinate;
35  import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
36  import org.apache.maven.shared.artifact.install.ArtifactInstaller;
37  import org.apache.maven.shared.artifact.install.ArtifactInstallerException;
38  import org.apache.maven.shared.artifact.resolve.ArtifactResolverException;
39  
40  import java.io.File;
41  import java.util.Collections;
42  import java.util.Map;
43  import java.util.Set;
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             for ( Artifact artifact : artifacts )
135             {
136                 installArtifact( artifact, buildingRequest );
137             }
138         }
139 
140         Set<Artifact> skippedArtifacts = dss.getSkippedDependencies();
141         for ( Artifact artifact : skippedArtifacts )
142         {
143             getLog().info( artifact.getId() + " already exists in destination." );
144         }
145 
146         if ( isCopyPom() && !useRepositoryLayout )
147         {
148             copyPoms( getOutputDirectory(), artifacts, this.stripVersion );
149             copyPoms( getOutputDirectory(), skippedArtifacts, this.stripVersion, this.stripClassifier ); // Artifacts
150                                                                                                          // that already
151                                                                                                          // exist may
152                                                                                                          // not yet have
153                                                                                                          // poms
154         }
155     }
156 
157     /**
158      * install the artifact and the corresponding pom if copyPoms=true
159      * 
160      * @param artifact
161      * @param targetRepository
162      */
163     private void installArtifact( Artifact artifact, ProjectBuildingRequest buildingRequest )
164     {
165         try
166         {
167             installer.install( buildingRequest, Collections.singletonList( artifact ) );
168             installBaseSnapshot( artifact, buildingRequest );
169 
170             if ( !"pom".equals( artifact.getType() ) && isCopyPom() )
171             {
172                 Artifact pomArtifact = getResolvedPomArtifact( artifact );
173                 if ( pomArtifact != null && pomArtifact.getFile() != null && pomArtifact.getFile().exists() )
174                 {
175                     installer.install( buildingRequest, Collections.singletonList( pomArtifact ) );
176                     installBaseSnapshot( pomArtifact, buildingRequest );
177                 }
178             }
179         }
180         catch ( ArtifactInstallerException e )
181         {
182             getLog().warn( "unable to install " + artifact, e );
183         }
184     }
185 
186     private void installBaseSnapshot( Artifact artifact, ProjectBuildingRequest buildingRequest )
187         throws ArtifactInstallerException
188     {
189         if ( artifact.isSnapshot() && !artifact.getBaseVersion().equals( artifact.getVersion() ) )
190         {
191             String version = artifact.getVersion();
192             try
193             {
194                 artifact.setVersion( artifact.getBaseVersion() );
195                 installer.install( buildingRequest, Collections.singletonList( artifact ) );
196             }
197             finally
198             {
199                 artifact.setVersion( version );
200             }
201         }
202     }
203 
204     /**
205      * Copies the Artifact after building the destination file name if overridden. This method also checks if the
206      * classifier is set and adds it to the destination file name if needed.
207      *
208      * @param artifact representing the object to be copied.
209      * @param removeVersion specifies if the version should be removed from the file name when copying.
210      * @param prependGroupId specifies if the groupId should be prepend to the file while copying.
211      * @param theUseBaseVersion specifies if the baseVersion of the artifact should be used instead of the version.
212      * @throws MojoExecutionException with a message if an error occurs.
213      * @see #copyArtifact(Artifact, boolean, boolean, boolean, boolean)
214      */
215     protected void copyArtifact( Artifact artifact, boolean removeVersion, boolean prependGroupId,
216                                  boolean theUseBaseVersion )
217         throws MojoExecutionException
218     {
219         copyArtifact( artifact, removeVersion, prependGroupId, theUseBaseVersion, false );
220     }
221 
222     /**
223      * Copies the Artifact after building the destination file name if overridden. This method also checks if the
224      * classifier is set and adds it to the destination file name if needed.
225      *
226      * @param artifact representing the object to be copied.
227      * @param removeVersion specifies if the version should be removed from the file name when copying.
228      * @param prependGroupId specifies if the groupId should be prepend to the file while copying.
229      * @param theUseBaseVersion specifies if the baseVersion of the artifact should be used instead of the version.
230      * @param removeClassifier specifies if the classifier should be removed from the file name when copying.
231      * @throws MojoExecutionException with a message if an error occurs.
232      * @see #copyFile(File, File)
233      * @see DependencyUtil#getFormattedOutputDirectory(boolean, boolean, boolean, boolean, boolean, File, Artifact)
234      */
235     protected void copyArtifact( Artifact artifact, boolean removeVersion, boolean prependGroupId,
236                                  boolean theUseBaseVersion, boolean removeClassifier )
237         throws MojoExecutionException
238     {
239 
240         String destFileName = DependencyUtil.getFormattedFileName( artifact, removeVersion, prependGroupId,
241                                                                    theUseBaseVersion, removeClassifier );
242 
243         File destDir;
244         destDir = DependencyUtil.getFormattedOutputDirectory( useSubDirectoryPerScope, useSubDirectoryPerType,
245                                                               useSubDirectoryPerArtifact, useRepositoryLayout,
246                                                               stripVersion, outputDirectory, artifact );
247         File destFile = new File( destDir, destFileName );
248 
249         copyFile( artifact.getFile(), destFile );
250     }
251 
252     /**
253      * Copy the pom files associated with the artifacts.
254      * 
255      * @param destDir The destination directory {@link File}.
256      * @param artifacts The artifacts {@link Artifact}.
257      * @param removeVersion remove version or not.
258      * @throws MojoExecutionException in case of errors.
259      */
260     public void copyPoms( File destDir, Set<Artifact> artifacts, boolean removeVersion )
261         throws MojoExecutionException
262 
263     {
264         copyPoms( destDir, artifacts, removeVersion, false );
265     }
266 
267     /**
268      * Copy the pom files associated with the artifacts.
269      * 
270      * @param destDir The destination directory {@link File}.
271      * @param artifacts The artifacts {@link Artifact}.
272      * @param removeVersion remove version or not.
273      * @param removeClassifier remove the classifier or not.
274      * @throws MojoExecutionException in case of errors.
275      */
276     public void copyPoms( File destDir, Set<Artifact> artifacts, boolean removeVersion, boolean removeClassifier )
277         throws MojoExecutionException
278 
279     {
280         for ( Artifact artifact : artifacts )
281         {
282             Artifact pomArtifact = getResolvedPomArtifact( artifact );
283 
284             // Copy the pom
285             if ( pomArtifact != null && pomArtifact.getFile() != null && pomArtifact.getFile().exists() )
286             {
287                 File pomDestFile =
288                     new File( destDir, DependencyUtil.getFormattedFileName( pomArtifact, removeVersion, prependGroupId,
289                                                                             useBaseVersion, removeClassifier ) );
290                 if ( !pomDestFile.exists() )
291                 {
292                     copyFile( pomArtifact.getFile(), pomDestFile );
293                 }
294             }
295         }
296     }
297 
298     /**
299      * @param artifact {@link Artifact}
300      * @return {@link Artifact}
301      */
302     protected Artifact getResolvedPomArtifact( Artifact artifact )
303     {
304         DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate();
305         coordinate.setGroupId( artifact.getGroupId() );
306         coordinate.setArtifactId( artifact.getArtifactId() );
307         coordinate.setVersion( artifact.getVersion() );
308         coordinate.setExtension( "pom" );
309 
310         Artifact pomArtifact = null;
311         // Resolve the pom artifact using repos
312         try
313         {
314             ProjectBuildingRequest buildingRequest = newResolveArtifactProjectBuildingRequest();
315 
316             pomArtifact = getArtifactResolver().resolveArtifact( buildingRequest, coordinate ).getArtifact();
317         }
318         catch ( ArtifactResolverException e )
319         {
320             getLog().info( e.getMessage() );
321         }
322         return pomArtifact;
323     }
324 
325     @Override
326     protected ArtifactsFilter getMarkedArtifactFilter()
327     {
328         return new DestFileFilter( this.overWriteReleases, this.overWriteSnapshots, this.overWriteIfNewer,
329                                    this.useSubDirectoryPerArtifact, this.useSubDirectoryPerType,
330                                    this.useSubDirectoryPerScope, this.useRepositoryLayout, this.stripVersion,
331                                    this.prependGroupId, this.useBaseVersion, this.outputDirectory );
332     }
333 
334     /**
335      * @return true, if the pom of each artifact must be copied
336      */
337     public boolean isCopyPom()
338     {
339         return this.copyPom;
340     }
341 
342     /**
343      * @param copyPom - true if the pom of each artifact must be copied
344      */
345     public void setCopyPom( boolean copyPom )
346     {
347         this.copyPom = copyPom;
348     }
349 }