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