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