1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.util.graph.selector;
20
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.Comparator;
24 import java.util.TreeSet;
25
26 import org.eclipse.aether.artifact.Artifact;
27 import org.eclipse.aether.collection.DependencyCollectionContext;
28 import org.eclipse.aether.collection.DependencySelector;
29 import org.eclipse.aether.graph.Dependency;
30 import org.eclipse.aether.graph.Exclusion;
31
32 import static java.util.Objects.requireNonNull;
33
34
35
36
37
38
39 public final class ExclusionDependencySelector implements DependencySelector {
40
41
42 private final Exclusion[] exclusions;
43
44 private final int hashCode;
45
46
47
48
49 public ExclusionDependencySelector() {
50 this.exclusions = new Exclusion[0];
51 this.hashCode = getClass().hashCode() * 31 + Arrays.hashCode(exclusions);
52 }
53
54
55
56
57
58
59 public ExclusionDependencySelector(Collection<Exclusion> exclusions) {
60 if (exclusions != null && !exclusions.isEmpty()) {
61 TreeSet<Exclusion> sorted = new TreeSet<>(ExclusionComparator.INSTANCE);
62 sorted.addAll(exclusions);
63 this.exclusions = sorted.toArray(new Exclusion[0]);
64 } else {
65 this.exclusions = new Exclusion[0];
66 }
67 this.hashCode = getClass().hashCode() * 31 + Arrays.hashCode(this.exclusions);
68 }
69
70 private ExclusionDependencySelector(Exclusion[] exclusions) {
71 this.exclusions = exclusions;
72 this.hashCode = getClass().hashCode() * 31 + Arrays.hashCode(exclusions);
73 }
74
75 public boolean selectDependency(Dependency dependency) {
76 requireNonNull(dependency, "dependency cannot be null");
77 Artifact artifact = dependency.getArtifact();
78 for (Exclusion exclusion : exclusions) {
79 if (matches(exclusion, artifact)) {
80 return false;
81 }
82 }
83 return true;
84 }
85
86 private boolean matches(Exclusion exclusion, Artifact artifact) {
87 if (!matches(exclusion.getArtifactId(), artifact.getArtifactId())) {
88 return false;
89 }
90 if (!matches(exclusion.getGroupId(), artifact.getGroupId())) {
91 return false;
92 }
93 if (!matches(exclusion.getExtension(), artifact.getExtension())) {
94 return false;
95 }
96 return matches(exclusion.getClassifier(), artifact.getClassifier());
97 }
98
99 private boolean matches(String pattern, String value) {
100 return "*".equals(pattern) || pattern.equals(value);
101 }
102
103 public DependencySelector deriveChildSelector(DependencyCollectionContext context) {
104 requireNonNull(context, "context cannot be null");
105 Dependency dependency = context.getDependency();
106 Collection<Exclusion> exclusions = (dependency != null) ? dependency.getExclusions() : null;
107 if (exclusions == null || exclusions.isEmpty()) {
108 return this;
109 }
110
111 Exclusion[] merged = this.exclusions;
112 int count = merged.length;
113 for (Exclusion exclusion : exclusions) {
114 int index = Arrays.binarySearch(merged, exclusion, ExclusionComparator.INSTANCE);
115 if (index < 0) {
116 index = -(index + 1);
117 if (count >= merged.length) {
118 Exclusion[] tmp = new Exclusion[merged.length + exclusions.size()];
119 System.arraycopy(merged, 0, tmp, 0, index);
120 tmp[index] = exclusion;
121 System.arraycopy(merged, index, tmp, index + 1, count - index);
122 merged = tmp;
123 } else {
124 System.arraycopy(merged, index, merged, index + 1, count - index);
125 merged[index] = exclusion;
126 }
127 count++;
128 }
129 }
130 if (merged == this.exclusions) {
131 return this;
132 }
133 if (merged.length != count) {
134 Exclusion[] tmp = new Exclusion[count];
135 System.arraycopy(merged, 0, tmp, 0, count);
136 merged = tmp;
137 }
138
139 return new ExclusionDependencySelector(merged);
140 }
141
142 @Override
143 public boolean equals(Object obj) {
144 if (this == obj) {
145 return true;
146 } else if (null == obj || !getClass().equals(obj.getClass())) {
147 return false;
148 }
149
150 ExclusionDependencySelector that = (ExclusionDependencySelector) obj;
151 return Arrays.equals(exclusions, that.exclusions);
152 }
153
154 @Override
155 public int hashCode() {
156 return hashCode;
157 }
158
159 @Override
160 public String toString() {
161 StringBuilder builder =
162 new StringBuilder().append(this.getClass().getSimpleName()).append('(');
163 for (int i = 0; i < this.exclusions.length; i++) {
164 builder.append(this.exclusions[i]);
165 if (i < this.exclusions.length - 1) {
166 builder.append(", ");
167 }
168 }
169 return builder.append(')').toString();
170 }
171
172 private static class ExclusionComparator implements Comparator<Exclusion> {
173
174 static final ExclusionComparator INSTANCE = new ExclusionComparator();
175
176 public int compare(Exclusion e1, Exclusion e2) {
177 if (e1 == null) {
178 return (e2 == null) ? 0 : 1;
179 } else if (e2 == null) {
180 return -1;
181 }
182 int rel = e1.getArtifactId().compareTo(e2.getArtifactId());
183 if (rel == 0) {
184 rel = e1.getGroupId().compareTo(e2.getGroupId());
185 if (rel == 0) {
186 rel = e1.getExtension().compareTo(e2.getExtension());
187 if (rel == 0) {
188 rel = e1.getClassifier().compareTo(e2.getClassifier());
189 }
190 }
191 }
192 return rel;
193 }
194 }
195 }