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.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashSet;
27 import java.util.LinkedHashSet;
28 import java.util.List;
29 import java.util.Set;
30 import java.util.stream.Collectors;
31
32 import org.apache.maven.RepositoryUtils;
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
35 import org.apache.maven.execution.MavenSession;
36 import org.apache.maven.model.Dependency;
37 import org.apache.maven.plugin.MojoExecutionException;
38 import org.apache.maven.plugins.annotations.Parameter;
39 import org.apache.maven.plugins.dependency.AbstractDependencyMojo;
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.translators.ArtifactTranslator;
44 import org.apache.maven.plugins.dependency.utils.translators.ClassifierTypeTranslator;
45 import org.apache.maven.project.DefaultProjectBuildingRequest;
46 import org.apache.maven.project.MavenProject;
47 import org.apache.maven.project.ProjectBuilder;
48 import org.apache.maven.project.ProjectBuildingException;
49 import org.apache.maven.project.ProjectBuildingRequest;
50 import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
51 import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
52 import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
53 import org.apache.maven.shared.artifact.filter.collection.ClassifierFilter;
54 import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
55 import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
56 import org.apache.maven.shared.artifact.filter.collection.ProjectTransitivityFilter;
57 import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
58 import org.apache.maven.shared.artifact.filter.collection.TypeFilter;
59 import org.eclipse.aether.repository.RemoteRepository;
60 import org.eclipse.aether.resolution.ArtifactResolutionException;
61 import org.eclipse.aether.resolution.DependencyResolutionException;
62 import org.sonatype.plexus.build.incremental.BuildContext;
63
64
65
66
67
68
69
70 public abstract class AbstractDependencyFilterMojo extends AbstractDependencyMojo {
71
72
73
74
75
76
77 @Parameter(property = "overWriteReleases", defaultValue = "false")
78 protected boolean overWriteReleases;
79
80
81
82
83
84
85 @Parameter(property = "overWriteSnapshots", defaultValue = "false")
86 protected boolean overWriteSnapshots;
87
88
89
90
91
92
93 @Parameter(property = "overWriteIfNewer", defaultValue = "true")
94 protected boolean overWriteIfNewer;
95
96
97
98
99
100
101 @Parameter(property = "excludeTransitive", defaultValue = "false")
102 protected boolean excludeTransitive;
103
104
105
106
107
108
109 @Parameter(property = "includeTypes", defaultValue = "")
110 protected String includeTypes;
111
112
113
114
115
116
117 @Parameter(property = "excludeTypes", defaultValue = "")
118 protected String excludeTypes;
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 @Parameter(property = "includeScope", defaultValue = "")
135 protected String includeScope;
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 @Parameter(property = "excludeScope", defaultValue = "")
156 protected String excludeScope;
157
158
159
160
161
162
163 @Parameter(property = "includeClassifiers", defaultValue = "")
164 protected String includeClassifiers;
165
166
167
168
169
170
171 @Parameter(property = "excludeClassifiers", defaultValue = "")
172 protected String excludeClassifiers;
173
174
175
176
177
178
179 @Parameter(property = "classifier", defaultValue = "")
180 protected String classifier;
181
182
183
184
185
186
187 @Parameter(property = "type", defaultValue = "")
188 protected String type;
189
190
191
192
193
194
195 @Parameter(property = "excludeArtifactIds", defaultValue = "")
196 protected String excludeArtifactIds;
197
198
199
200
201
202
203 @Parameter(property = "includeArtifactIds", defaultValue = "")
204 protected String includeArtifactIds;
205
206
207
208
209
210
211 @Parameter(property = "excludeGroupIds", defaultValue = "")
212 protected String excludeGroupIds;
213
214
215
216
217
218
219 @Parameter(property = "includeGroupIds", defaultValue = "")
220 protected String includeGroupIds;
221
222
223
224
225
226
227 @Parameter(
228 property = "markersDirectory",
229 defaultValue = "${project.build.directory}/dependency-maven-plugin-markers")
230 protected File markersDirectory;
231
232
233
234
235
236
237 @Parameter(property = "mdep.prependGroupId", defaultValue = "false")
238 protected boolean prependGroupId = false;
239
240
241
242
243
244
245
246
247 @Parameter
248 private List<GraphRoot> graphRoots;
249
250 private final ResolverUtil resolverUtil;
251
252 private final ProjectBuilder projectBuilder;
253
254 private final ArtifactHandlerManager artifactHandlerManager;
255
256 @Inject
257 protected AbstractDependencyFilterMojo(
258 MavenSession session,
259 BuildContext buildContext,
260 MavenProject project,
261 ResolverUtil resolverUtil,
262 ProjectBuilder projectBuilder,
263 ArtifactHandlerManager artifactHandlerManager) {
264 super(session, buildContext, project);
265 this.resolverUtil = resolverUtil;
266 this.projectBuilder = projectBuilder;
267 this.artifactHandlerManager = artifactHandlerManager;
268 }
269
270
271
272
273
274
275 protected abstract ArtifactsFilter getMarkedArtifactFilter();
276
277
278
279
280
281
282
283
284 protected Set<Artifact> getResolvedDependencies(boolean stopOnFailure) throws MojoExecutionException {
285
286 DependencyStatusSets status = getDependencySets(stopOnFailure);
287
288 return status.getResolvedDependencies();
289 }
290
291
292
293
294
295
296 protected DependencyStatusSets getDependencySets(boolean stopOnFailure) throws MojoExecutionException {
297 return getDependencySets(stopOnFailure, false);
298 }
299
300
301
302
303
304
305
306
307
308
309 protected DependencyStatusSets getDependencySets(boolean stopOnFailure, boolean includeParents)
310 throws MojoExecutionException {
311
312
313 FilterArtifacts filter = new FilterArtifacts();
314
315 filter.addFilter(new ProjectTransitivityFilter(getProject().getDependencyArtifacts(), this.excludeTransitive));
316
317 if ("test".equals(this.excludeScope)) {
318 throw new MojoExecutionException("Excluding every artifact inside 'test' resolution scope means "
319 + "excluding everything: you probably want includeScope='compile', "
320 + "read parameters documentation for detailed explanations");
321 }
322 filter.addFilter(new ScopeFilter(
323 DependencyUtil.cleanToBeTokenizedString(this.includeScope),
324 DependencyUtil.cleanToBeTokenizedString(this.excludeScope)));
325
326 filter.addFilter(new TypeFilter(
327 DependencyUtil.cleanToBeTokenizedString(this.includeTypes),
328 DependencyUtil.cleanToBeTokenizedString(this.excludeTypes)));
329
330 filter.addFilter(new ClassifierFilter(
331 DependencyUtil.cleanToBeTokenizedString(this.includeClassifiers),
332 DependencyUtil.cleanToBeTokenizedString(this.excludeClassifiers)));
333
334 filter.addFilter(new GroupIdFilter(
335 DependencyUtil.cleanToBeTokenizedString(this.includeGroupIds),
336 DependencyUtil.cleanToBeTokenizedString(this.excludeGroupIds)));
337
338 filter.addFilter(new ArtifactIdFilter(
339 DependencyUtil.cleanToBeTokenizedString(this.includeArtifactIds),
340 DependencyUtil.cleanToBeTokenizedString(this.excludeArtifactIds)));
341
342
343 Set<Artifact> artifacts;
344
345 try {
346 artifacts = collectArtifacts(getProject());
347 } catch (DependencyResolutionException e) {
348 throw new MojoExecutionException("Failed to collect artifacts", e);
349 }
350
351 if (includeParents) {
352
353 for (Artifact dep : new ArrayList<>(artifacts)) {
354 addParentArtifacts(buildProjectFromArtifact(dep), artifacts);
355 }
356
357
358 addParentArtifacts(getProject(), artifacts);
359 }
360
361
362 try {
363 artifacts = filter.filter(artifacts);
364 } catch (ArtifactFilterException e) {
365 throw new MojoExecutionException(e.getMessage(), e);
366 }
367
368
369 DependencyStatusSets status;
370 if (classifier != null && !classifier.isEmpty()) {
371 status = getClassifierTranslatedDependencies(artifacts, stopOnFailure);
372 } else {
373 status = filterMarkedDependencies(artifacts);
374 }
375
376 return status;
377 }
378
379 private MavenProject buildProjectFromArtifact(Artifact artifact) throws MojoExecutionException {
380 try {
381 ProjectBuildingRequest buildingRequest =
382 new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
383 buildingRequest.setProcessPlugins(false);
384 return projectBuilder.build(artifact, buildingRequest).getProject();
385 } catch (ProjectBuildingException e) {
386 throw new MojoExecutionException("Coud not build project for " + artifact.getId(), e);
387 }
388 }
389
390 private void addParentArtifacts(MavenProject project, Set<Artifact> artifacts) throws MojoExecutionException {
391 while (project.hasParent()) {
392 project = project.getParent();
393
394 if (artifacts.contains(project.getArtifact())) {
395
396 break;
397 }
398 try {
399 org.eclipse.aether.artifact.Artifact resolvedArtifact = resolverUtil.resolveArtifact(
400 RepositoryUtils.toArtifact(project.getArtifact()), project.getRemoteProjectRepositories());
401
402 artifacts.add(RepositoryUtils.toArtifact(resolvedArtifact));
403 } catch (ArtifactResolutionException e) {
404 throw new MojoExecutionException(e.getMessage(), e);
405 }
406 }
407 }
408
409
410
411
412
413
414
415
416
417 private DependencyStatusSets getClassifierTranslatedDependencies(Set<Artifact> artifacts, boolean stopOnFailure)
418 throws MojoExecutionException {
419 Set<Artifact> unResolvedArtifacts = new LinkedHashSet<>();
420 Set<Artifact> resolvedArtifacts = artifacts;
421 DependencyStatusSets status = new DependencyStatusSets();
422
423
424
425
426 if (classifier != null && !classifier.isEmpty()) {
427 ArtifactTranslator translator =
428 new ClassifierTypeTranslator(artifactHandlerManager, this.classifier, this.type);
429 Collection<org.eclipse.aether.artifact.Artifact> coordinates = translator.translate(artifacts, getLog());
430
431 status = filterMarkedDependencies(artifacts);
432
433
434 artifacts = status.getResolvedDependencies();
435
436
437 resolvedArtifacts = resolve(new LinkedHashSet<>(coordinates), stopOnFailure);
438
439
440 unResolvedArtifacts.addAll(artifacts);
441 unResolvedArtifacts.removeAll(resolvedArtifacts);
442 }
443
444
445 status.setResolvedDependencies(resolvedArtifacts);
446 status.setUnResolvedDependencies(unResolvedArtifacts);
447
448 return status;
449 }
450
451
452
453
454
455
456
457
458 protected DependencyStatusSets filterMarkedDependencies(Set<Artifact> artifacts) throws MojoExecutionException {
459
460 FilterArtifacts filter = new FilterArtifacts();
461 filter.clearFilters();
462 filter.addFilter(getMarkedArtifactFilter());
463
464 Set<Artifact> unMarkedArtifacts;
465 try {
466 unMarkedArtifacts = filter.filter(artifacts);
467 } catch (ArtifactFilterException e) {
468 throw new MojoExecutionException(e.getMessage(), e);
469 }
470
471
472 Set<Artifact> skippedArtifacts = new LinkedHashSet<>(artifacts);
473 skippedArtifacts.removeAll(unMarkedArtifacts);
474
475 return new DependencyStatusSets(unMarkedArtifacts, null, skippedArtifacts);
476 }
477
478
479
480
481
482
483
484
485 private Set<Artifact> resolve(Set<org.eclipse.aether.artifact.Artifact> artifacts, boolean stopOnFailure)
486 throws MojoExecutionException {
487
488 Set<Artifact> resolvedArtifacts = new LinkedHashSet<>();
489 for (org.eclipse.aether.artifact.Artifact artifact : artifacts) {
490 try {
491 org.eclipse.aether.artifact.Artifact resolveArtifact =
492 resolverUtil.resolveArtifact(artifact, getProject().getRemoteProjectRepositories());
493 resolvedArtifacts.add(RepositoryUtils.toArtifact(resolveArtifact));
494 } catch (ArtifactResolutionException ex) {
495
496 getLog().debug("error resolving: " + artifact, ex);
497 if (stopOnFailure) {
498 throw new MojoExecutionException("error resolving: " + artifact, ex);
499 }
500 }
501 }
502 return resolvedArtifacts;
503 }
504
505 private Set<Artifact> collectArtifacts(MavenProject project) throws DependencyResolutionException {
506 if (graphRoots == null || graphRoots.isEmpty()) {
507
508
509 return project.getArtifacts();
510 } else {
511
512
513 List<DependencyMatcher> filterMatchers =
514 graphRoots.stream().map(GraphRootMatcher::new).collect(Collectors.toList());
515
516 DependencyMatcher subTreeMatcher = new OrDependencyMatcher(filterMatchers);
517
518 Set<Artifact> artifacts = new HashSet<>();
519 for (Dependency dep : project.getDependencies()) {
520 if (subTreeMatcher.matches(dep)) {
521 artifacts.addAll(resolveDependencyArtifacts(dep));
522 }
523 }
524 return artifacts;
525 }
526 }
527
528 private Set<Artifact> resolveDependencyArtifacts(Dependency root) throws DependencyResolutionException {
529 org.eclipse.aether.graph.Dependency dependency = RepositoryUtils.toDependency(
530 root, session.getRepositorySession().getArtifactTypeRegistry());
531
532 List<RemoteRepository> remoteRepositories = getProject().getRemoteProjectRepositories();
533
534 Collection<org.eclipse.aether.artifact.Artifact> depArtifacts =
535 resolverUtil.resolveDependencies(dependency.getArtifact(), remoteRepositories);
536
537 return depArtifacts.stream().map(RepositoryUtils::toArtifact).collect(Collectors.toSet());
538 }
539
540
541
542
543 public File getMarkersDirectory() {
544 return this.markersDirectory;
545 }
546
547
548
549
550 public void setMarkersDirectory(File theMarkersDirectory) {
551 this.markersDirectory = theMarkersDirectory;
552 }
553
554
555
556
557
558
559 public boolean isPrependGroupId() {
560 return prependGroupId;
561 }
562
563
564
565
566 public void setPrependGroupId(boolean prependGroupId) {
567 this.prependGroupId = prependGroupId;
568 }
569
570
571
572
573 protected final ResolverUtil getResolverUtil() {
574 return resolverUtil;
575 }
576 }