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.analyze;
20
21 import java.io.IOException;
22 import java.io.Reader;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.LinkedHashSet;
27 import java.util.List;
28 import java.util.Set;
29 import java.util.stream.Collectors;
30
31 import org.apache.maven.model.Dependency;
32 import org.apache.maven.model.Model;
33 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
34 import org.apache.maven.plugin.AbstractMojo;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.plugin.MojoFailureException;
37 import org.apache.maven.plugins.annotations.Component;
38 import org.apache.maven.plugins.annotations.Mojo;
39 import org.apache.maven.plugins.annotations.Parameter;
40 import org.apache.maven.project.MavenProject;
41 import org.codehaus.plexus.util.xml.XmlStreamReader;
42 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
43
44
45
46
47
48
49
50 @Mojo(name = "analyze-duplicate", aggregator = false, threadSafe = true)
51 public class AnalyzeDuplicateMojo extends AbstractMojo {
52 public static final String MESSAGE_DUPLICATE_DEP_IN_DEPENDENCIES =
53 "List of duplicate dependencies defined in <dependencies/> in your pom.xml:\n";
54
55 public static final String MESSAGE_DUPLICATE_DEP_IN_DEPMGMT =
56 "List of duplicate dependencies defined in <dependencyManagement/> in your pom.xml:\n";
57
58
59
60
61
62
63 @Parameter(property = "mdep.analyze.skip", defaultValue = "false")
64 private boolean skip;
65
66
67
68
69 @Component
70 private MavenProject project;
71
72
73
74
75 @Override
76 public void execute() throws MojoExecutionException, MojoFailureException {
77 if (skip) {
78 getLog().info("Skipping plugin execution");
79 return;
80 }
81
82 MavenXpp3Reader pomReader = new MavenXpp3Reader();
83 Model model;
84 try (Reader reader = new XmlStreamReader(project.getFile())) {
85 model = pomReader.read(reader);
86 } catch (IOException | XmlPullParserException e) {
87 throw new MojoExecutionException("Exception: " + e.getMessage(), e);
88 }
89
90 Set<String> duplicateDependencies = Collections.emptySet();
91 if (model.getDependencies() != null) {
92 duplicateDependencies = findDuplicateDependencies(model.getDependencies());
93 }
94
95 Set<String> duplicateDependenciesManagement = Collections.emptySet();
96 if (model.getDependencyManagement() != null
97 && model.getDependencyManagement().getDependencies() != null) {
98 duplicateDependenciesManagement =
99 findDuplicateDependencies(model.getDependencyManagement().getDependencies());
100 }
101
102 if (getLog().isInfoEnabled()) {
103 StringBuilder sb = new StringBuilder();
104
105 createMessage(duplicateDependencies, sb, MESSAGE_DUPLICATE_DEP_IN_DEPENDENCIES);
106 createMessage(duplicateDependenciesManagement, sb, MESSAGE_DUPLICATE_DEP_IN_DEPMGMT);
107
108 if (sb.length() > 0) {
109 getLog().info(sb.toString());
110 } else {
111 getLog().info("No duplicate dependencies found in <dependencies/> or in <dependencyManagement/>");
112 }
113 }
114 }
115
116 private void createMessage(
117 Set<String> duplicateDependencies, StringBuilder sb, String messageDuplicateDepInDependencies) {
118 if (!duplicateDependencies.isEmpty()) {
119 if (sb.length() > 0) {
120 sb.append("\n");
121 }
122 sb.append(messageDuplicateDepInDependencies);
123 for (Iterator<String> it = duplicateDependencies.iterator(); it.hasNext(); ) {
124 String dup = it.next();
125
126 sb.append("\to ").append(dup);
127 if (it.hasNext()) {
128 sb.append("\n");
129 }
130 }
131 }
132 }
133
134 private Set<String> findDuplicateDependencies(List<Dependency> modelDependencies) {
135 List<String> modelDependencies2 =
136 modelDependencies.stream().map(Dependency::getManagementKey).collect(Collectors.toList());
137
138 modelDependencies2.removeIf(new HashSet<>(modelDependencies2)::remove);
139
140 return new LinkedHashSet<>(modelDependencies2);
141 }
142 }