1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.plugins.dependency.fromDependencies;
20  
21  import javax.inject.Inject;
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.util.Collections;
26  import java.util.HashMap;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import org.apache.maven.RepositoryUtils;
31  import org.apache.maven.artifact.Artifact;
32  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
33  import org.apache.maven.execution.MavenSession;
34  import org.apache.maven.plugin.MojoExecutionException;
35  import org.apache.maven.plugins.annotations.LifecyclePhase;
36  import org.apache.maven.plugins.annotations.Mojo;
37  import org.apache.maven.plugins.annotations.Parameter;
38  import org.apache.maven.plugins.annotations.ResolutionScope;
39  import org.apache.maven.plugins.dependency.utils.CopyUtil;
40  import org.apache.maven.plugins.dependency.utils.DependencyStatusSets;
41  import org.apache.maven.plugins.dependency.utils.DependencyUtil;
42  import org.apache.maven.plugins.dependency.utils.ResolverUtil;
43  import org.apache.maven.plugins.dependency.utils.filters.DestFileFilter;
44  import org.apache.maven.project.MavenProject;
45  import org.apache.maven.project.ProjectBuilder;
46  import org.apache.maven.project.ProjectBuildingRequest;
47  import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
48  import org.apache.maven.shared.transfer.artifact.install.ArtifactInstaller;
49  import org.apache.maven.shared.transfer.artifact.install.ArtifactInstallerException;
50  import org.apache.maven.shared.transfer.repository.RepositoryManager;
51  import org.eclipse.aether.resolution.ArtifactResolutionException;
52  import org.eclipse.aether.util.artifact.SubArtifact;
53  import org.sonatype.plexus.build.incremental.BuildContext;
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  @Mojo(
65          name = "copy-dependencies",
66          requiresDependencyResolution = ResolutionScope.TEST,
67          defaultPhase = LifecyclePhase.PROCESS_SOURCES,
68          threadSafe = true)
69  public class CopyDependenciesMojo extends AbstractFromDependenciesMojo {
70      
71  
72  
73  
74  
75      @Parameter(property = "mdep.copyPom", defaultValue = "false")
76      protected boolean copyPom;
77  
78      private final CopyUtil copyUtil;
79  
80      private final ArtifactInstaller installer;
81  
82      private final RepositoryManager repositoryManager;
83  
84      
85  
86  
87  
88  
89  
90      @Parameter(property = "mdep.useBaseVersion", defaultValue = "true")
91      protected boolean useBaseVersion = true;
92  
93      
94  
95  
96  
97  
98      @Parameter(property = "mdep.addParentPoms", defaultValue = "false")
99      protected boolean addParentPoms;
100 
101     
102 
103 
104 
105 
106     @Parameter(property = "mdep.copySignatures", defaultValue = "false")
107     protected boolean copySignatures;
108 
109     @Inject
110     @SuppressWarnings("checkstyle:ParameterNumber")
111     public CopyDependenciesMojo(
112             MavenSession session,
113             BuildContext buildContext,
114             MavenProject project,
115             ResolverUtil resolverUtil,
116             RepositoryManager repositoryManager,
117             ProjectBuilder projectBuilder,
118             ArtifactHandlerManager artifactHandlerManager,
119             CopyUtil copyUtil,
120             ArtifactInstaller installer) {
121         super(session, buildContext, project, resolverUtil, projectBuilder, artifactHandlerManager);
122         this.copyUtil = copyUtil;
123         this.installer = installer;
124         this.repositoryManager = repositoryManager;
125     }
126 
127     
128 
129 
130 
131 
132 
133 
134     @Override
135     protected void doExecute() throws MojoExecutionException {
136         DependencyStatusSets dss = getDependencySets(this.failOnMissingClassifierArtifact, addParentPoms);
137         Set<Artifact> artifacts = dss.getResolvedDependencies();
138 
139         if (!useRepositoryLayout) {
140             Map<String, Integer> copies = new HashMap<>();
141             for (Artifact artifactItem : artifacts) {
142                 String destFileName = DependencyUtil.getFormattedFileName(
143                         artifactItem, stripVersion, prependGroupId, useBaseVersion, stripClassifier);
144                 int numCopies = copies.getOrDefault(destFileName, 0);
145                 copies.put(destFileName, numCopies + 1);
146             }
147             for (Map.Entry<String, Integer> entry : copies.entrySet()) {
148                 if (entry.getValue() > 1) {
149                     getLog().warn("Multiple files with the name " + entry.getKey() + " in the dependency tree.");
150                     getLog().warn(
151                                     "Not all JARs will be available. Consider using prependGroupId, useSubDirectoryPerArtifact, or useRepositoryLayout.");
152                 }
153             }
154 
155             for (Artifact artifact : artifacts) {
156                 copyArtifact(
157                         artifact, isStripVersion(), this.prependGroupId, this.useBaseVersion, this.stripClassifier);
158             }
159         } else {
160             ProjectBuildingRequest buildingRequest =
161                     repositoryManager.setLocalRepositoryBasedir(session.getProjectBuildingRequest(), outputDirectory);
162 
163             artifacts.forEach(artifact -> installArtifact(artifact, buildingRequest));
164         }
165 
166         Set<Artifact> skippedArtifacts = dss.getSkippedDependencies();
167         for (Artifact artifact : skippedArtifacts) {
168             getLog().info(artifact.getId() + " already exists in destination.");
169         }
170 
171         if (isCopyPom() && !useRepositoryLayout) {
172             copyPoms(getOutputDirectory(), artifacts, this.stripVersion);
173             copyPoms(getOutputDirectory(), skippedArtifacts, this.stripVersion, this.stripClassifier);
174             
175         }
176     }
177 
178     
179 
180 
181     private void installArtifact(Artifact artifact, ProjectBuildingRequest buildingRequest) {
182         try {
183             installer.install(buildingRequest, Collections.singletonList(artifact));
184             installBaseSnapshot(artifact, buildingRequest);
185 
186             if (!"pom".equals(artifact.getType()) && isCopyPom()) {
187                 Artifact pomArtifact = getResolvedPomArtifact(artifact);
188                 if (pomArtifact != null
189                         && pomArtifact.getFile() != null
190                         && pomArtifact.getFile().exists()) {
191                     installer.install(buildingRequest, Collections.singletonList(pomArtifact));
192                     installBaseSnapshot(pomArtifact, buildingRequest);
193                 }
194             }
195         } catch (ArtifactInstallerException e) {
196             getLog().warn("unable to install " + artifact, e);
197         }
198     }
199 
200     private void installBaseSnapshot(Artifact artifact, ProjectBuildingRequest buildingRequest)
201             throws ArtifactInstallerException {
202         if (artifact.isSnapshot() && !artifact.getBaseVersion().equals(artifact.getVersion())) {
203             String version = artifact.getVersion();
204             try {
205                 artifact.setVersion(artifact.getBaseVersion());
206                 installer.install(buildingRequest, Collections.singletonList(artifact));
207             } finally {
208                 artifact.setVersion(version);
209             }
210         }
211     }
212 
213     
214 
215 
216 
217 
218 
219 
220 
221 
222 
223 
224     protected void copyArtifact(
225             Artifact artifact, boolean removeVersion, boolean prependGroupId, boolean theUseBaseVersion)
226             throws MojoExecutionException {
227         copyArtifact(artifact, removeVersion, prependGroupId, theUseBaseVersion, false);
228     }
229 
230     
231 
232 
233 
234 
235 
236 
237 
238 
239 
240 
241 
242 
243     private static final String SIGNATURE_EXTENSION = ".asc";
244 
245     protected void copyArtifact(
246             Artifact artifact,
247             boolean removeVersion,
248             boolean prependGroupId,
249             boolean useBaseVersion,
250             boolean removeClassifier)
251             throws MojoExecutionException {
252 
253         String destFileName = DependencyUtil.getFormattedFileName(
254                 artifact, removeVersion, prependGroupId, useBaseVersion, removeClassifier);
255 
256         File destDir = DependencyUtil.getFormattedOutputDirectory(
257                 useSubDirectoryPerScope,
258                 useSubDirectoryPerType,
259                 useSubDirectoryPerArtifact,
260                 useRepositoryLayout,
261                 stripVersion,
262                 stripType,
263                 outputDirectory,
264                 artifact);
265         File destFile = new File(destDir, destFileName);
266         if (destFile.exists()) {
267             getLog().warn("Overwriting " + destFile);
268         }
269         try {
270             copyUtil.copyArtifactFile(artifact, destFile);
271 
272             
273             if (copySignatures) {
274                 copySignatureFile(artifact, destDir, destFileName);
275             }
276 
277         } catch (IOException e) {
278             throw new MojoExecutionException(
279                     "Failed to copy artifact '" + artifact + "' (" + artifact.getFile() + ") to " + destFile, e);
280         }
281     }
282 
283     
284 
285 
286 
287 
288 
289 
290 
291     private void copySignatureFile(Artifact artifact, File destDir, String destFileName) {
292         File signatureFile = new File(artifact.getFile().getAbsolutePath() + SIGNATURE_EXTENSION);
293 
294         if (!signatureFile.exists()) {
295             try {
296                 org.eclipse.aether.artifact.Artifact aArtifact = RepositoryUtils.toArtifact(artifact);
297                 org.eclipse.aether.artifact.Artifact aSignatureArtifact =
298                         new SubArtifact(aArtifact, null, "jar" + SIGNATURE_EXTENSION);
299                 org.eclipse.aether.artifact.Artifact resolvedSignature = getResolverUtil()
300                         .resolveArtifact(aSignatureArtifact, getProject().getRemoteProjectRepositories());
301                 signatureFile = resolvedSignature.getFile();
302             } catch (ArtifactResolutionException e) {
303                 getLog().warn("Failed to resolve signature file for artifact: " + artifact, e);
304             }
305         }
306 
307         if (signatureFile != null && signatureFile.exists()) {
308             File signatureDestFile = new File(destDir, destFileName + SIGNATURE_EXTENSION);
309             try {
310                 copyUtil.copyFile(signatureFile, signatureDestFile);
311             } catch (IOException e) {
312                 getLog().warn("Failed to copy signature file: " + signatureFile, e);
313             }
314         } else {
315             getLog().warn("Signature file for artifact " + artifact + " not found and could not be resolved.");
316         }
317     }
318 
319     
320 
321 
322 
323 
324 
325 
326 
327     public void copyPoms(File destDir, Set<Artifact> artifacts, boolean removeVersion) throws MojoExecutionException {
328 
329         copyPoms(destDir, artifacts, removeVersion, false);
330     }
331 
332     
333 
334 
335 
336 
337 
338 
339 
340 
341     public void copyPoms(File destDir, Set<Artifact> artifacts, boolean removeVersion, boolean removeClassifier)
342             throws MojoExecutionException {
343 
344         for (Artifact artifact : artifacts) {
345             Artifact pomArtifact = getResolvedPomArtifact(artifact);
346 
347             
348             if (pomArtifact != null
349                     && pomArtifact.getFile() != null
350                     && pomArtifact.getFile().exists()) {
351                 File pomDestFile = new File(
352                         destDir,
353                         DependencyUtil.getFormattedFileName(
354                                 pomArtifact, removeVersion, prependGroupId, useBaseVersion, removeClassifier));
355                 if (!pomDestFile.exists()) {
356                     try {
357                         copyUtil.copyArtifactFile(pomArtifact, pomDestFile);
358                     } catch (IOException e) {
359                         throw new MojoExecutionException(
360                                 "Failed to copy artifact '" + pomArtifact + "' (" + pomArtifact.getFile() + ") to "
361                                         + pomDestFile,
362                                 e);
363                     }
364                 }
365             }
366         }
367     }
368 
369     
370 
371 
372 
373     protected Artifact getResolvedPomArtifact(Artifact artifact) {
374 
375         Artifact pomArtifact = null;
376         
377         try {
378             org.eclipse.aether.artifact.Artifact aArtifact = RepositoryUtils.toArtifact(artifact);
379             org.eclipse.aether.artifact.Artifact aPomArtifact = new SubArtifact(aArtifact, null, "pom");
380             org.eclipse.aether.artifact.Artifact resolvedPom =
381                     getResolverUtil().resolveArtifact(aPomArtifact, getProject().getRemoteProjectRepositories());
382             pomArtifact = RepositoryUtils.toArtifact(resolvedPom);
383         } catch (ArtifactResolutionException e) {
384             getLog().info(e.getMessage());
385         }
386         return pomArtifact;
387     }
388 
389     @Override
390     protected ArtifactsFilter getMarkedArtifactFilter() {
391         return new DestFileFilter(
392                 this.overWriteReleases,
393                 this.overWriteSnapshots,
394                 this.overWriteIfNewer,
395                 this.useSubDirectoryPerArtifact,
396                 this.useSubDirectoryPerType,
397                 this.useSubDirectoryPerScope,
398                 this.useRepositoryLayout,
399                 this.stripVersion,
400                 this.prependGroupId,
401                 this.useBaseVersion,
402                 this.outputDirectory);
403     }
404 
405     
406 
407 
408     public boolean isCopyPom() {
409         return this.copyPom;
410     }
411 
412     
413 
414 
415     public void setCopyPom(boolean copyPom) {
416         this.copyPom = copyPom;
417     }
418 }