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