1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.basepom.mojo.duplicatefinder;
16
17 import static com.google.common.base.Preconditions.checkNotNull;
18
19 import org.basepom.mojo.duplicatefinder.artifact.MavenCoordinates;
20
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.LinkedHashSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.regex.Pattern;
29
30 import com.google.common.collect.ImmutableList;
31 import org.apache.maven.artifact.Artifact;
32 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
33 import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
34 import org.apache.maven.model.Dependency;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38
39
40
41 public class ConflictingDependency {
42
43 private static final Logger LOG = LoggerFactory.getLogger(ConflictingDependency.class);
44
45 private final Set<MavenCoordinates> conflictingDependencies = new LinkedHashSet<>();
46 private final Set<String> classes = new HashSet<>();
47 private final Set<String> packages = new HashSet<>();
48 private final Set<String> resources = new HashSet<>();
49 private Pattern[] matchingResources = new Pattern[0];
50 private boolean currentProject = false;
51 private boolean currentProjectIncluded = false;
52
53
54 public void setConflictingDependencies(final Dependency... conflictingDependencies) throws InvalidVersionSpecificationException {
55 for (Dependency conflictingDependency : conflictingDependencies) {
56 this.conflictingDependencies.add(new MavenCoordinates(conflictingDependency));
57 }
58 }
59
60
61 public void setResourcePatterns(final String... resourcePatterns) {
62 this.matchingResources = new Pattern[resourcePatterns.length];
63 for (int i = 0; i < resourcePatterns.length; i++) {
64 this.matchingResources[i] = Pattern.compile(resourcePatterns[i], Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
65 }
66 }
67
68 public String[] getClasses() {
69 return classes.toArray(new String[0]);
70 }
71
72
73 public void setClasses(final String... classes) {
74 this.classes.addAll(Arrays.asList(classes));
75 }
76
77 public String[] getPackages() {
78 return packages.toArray(new String[0]);
79 }
80
81
82 public void setPackages(final String... packages) {
83 this.packages.addAll(Arrays.asList(packages));
84 }
85
86 public String[] getResources() {
87 return resources.toArray(new String[0]);
88 }
89
90
91 public void setResources(final String... resources) {
92 this.resources.addAll(Arrays.asList(resources));
93 }
94
95
96 public void setCurrentProject(final boolean currentProject) {
97 this.currentProject = currentProject;
98 }
99
100 boolean hasCurrentProject() {
101 return currentProject;
102 }
103
104
105
106 @Deprecated
107 public void setBootClasspath(final boolean bootClasspath) {
108 LOG.warn("<bootClasspath> attribute is deprecated and has no function!");
109 }
110
111 boolean isCurrentProjectIncluded() {
112 return currentProjectIncluded;
113 }
114
115 void addProjectMavenCoordinates(final MavenCoordinates projectMavenCoordinates) {
116 this.currentProjectIncluded = conflictingDependencies.contains(projectMavenCoordinates);
117 if (this.currentProject) {
118
119
120 conflictingDependencies.add(projectMavenCoordinates);
121 }
122 }
123
124 List<MavenCoordinates> getDependencies() {
125 return ImmutableList.copyOf(conflictingDependencies);
126 }
127
128 @SuppressWarnings("PMD.MethodReturnsInternalArray")
129 Pattern[] getResourcePatterns() {
130 return matchingResources;
131 }
132
133 public List<String> getDependencyNames() {
134 final List<String> result = new ArrayList<>(conflictingDependencies.size());
135
136 for (final MavenCoordinates conflictingDependency : conflictingDependencies) {
137 result.add(conflictingDependency.toString());
138 }
139
140 Collections.sort(result);
141 return result;
142 }
143
144 public boolean isForArtifacts(final Set<Artifact> artifacts) throws OverConstrainedVersionException {
145 checkNotNull(artifacts, "artifacts is null");
146
147
148
149
150 if (artifacts.size() > conflictingDependencies.size()) {
151 return false;
152 }
153
154
155 int numMatches = artifacts.size();
156
157 for (final Artifact artifact : artifacts) {
158 for (final MavenCoordinates conflictingDependency : conflictingDependencies) {
159 if (conflictingDependency.matches(artifact)) {
160 if (--numMatches == 0) {
161 return true;
162 } else {
163 break;
164 }
165 }
166 }
167 }
168 return false;
169 }
170
171 boolean isWildcard() {
172 return classes.isEmpty() && packages.isEmpty() && resources.isEmpty() && matchingResources.length == 0;
173 }
174
175 public boolean containsClass(final String className) {
176 if (isWildcard()) {
177
178 return true;
179 }
180
181 if (classes.contains(className)) {
182 return true;
183 } else {
184 for (final String packageName : packages) {
185 final String pkgName = packageName.endsWith(".") ? packageName : packageName + ".";
186 if (className.startsWith(pkgName)) {
187 return true;
188 }
189 }
190 return false;
191 }
192 }
193
194 public boolean containsResource(final String resource) {
195 if (isWildcard()) {
196
197 return true;
198 }
199
200 final String resourceAsRelative = resource.startsWith("/") || resource.startsWith("\\") ? resource.substring(1) : resource;
201
202 if (resources.contains(resourceAsRelative)
203 || resources.contains("/" + resourceAsRelative)
204 || resources.contains("\\" + resourceAsRelative)) {
205
206 return true;
207 }
208
209 for (Pattern matchingResource : matchingResources) {
210 if (matchingResource.matcher(resourceAsRelative).matches()) {
211 return true;
212 }
213 }
214
215 return false;
216 }
217 }