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 private static final String SIGNATURE_EXTENSION = ".asc";
231
232
233
234
235
236
237
238
239
240
241
242
243
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 }