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 }