1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.maven;
25
26 import java.util.LinkedHashSet;
27 import java.util.Set;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30 import org.modeshape.common.text.TextEncoder;
31 import org.modeshape.common.text.NoOpEncoder;
32 import org.modeshape.common.util.CheckArg;
33 import org.modeshape.common.util.HashCode;
34 import org.modeshape.common.util.StringUtil;
35
36
37
38
39 public class MavenId implements Comparable<MavenId>, Cloneable {
40
41
42
43
44
45
46
47 public static MavenId[] createClasspath( String commaSeparatedCoordinates ) {
48 if (commaSeparatedCoordinates == null) return new MavenId[] {};
49 String[] coordinates = commaSeparatedCoordinates.split(",");
50 return createClasspath(coordinates);
51 }
52
53
54
55
56
57
58
59 public static MavenId[] createClasspath( String... mavenCoordinates ) {
60 if (mavenCoordinates == null) return new MavenId[] {};
61
62 Set<MavenId> result = new LinkedHashSet<MavenId>();
63 for (int i = 0; i < mavenCoordinates.length; i++) {
64 String coordinateStr = mavenCoordinates[i];
65 if (coordinateStr == null) continue;
66 coordinateStr = coordinateStr.trim();
67 if (coordinateStr.length() != 0) {
68 result.add(new MavenId(coordinateStr));
69 }
70 }
71 return result.toArray(new MavenId[result.size()]);
72 }
73
74
75
76
77
78
79 public static MavenId[] createClasspath( MavenId... mavenIds ) {
80
81 Set<MavenId> result = new LinkedHashSet<MavenId>();
82 for (MavenId mavenId : mavenIds) {
83 if (mavenId != null) result.add(mavenId);
84 }
85 return result.toArray(new MavenId[result.size()]);
86 }
87
88 private final String groupId;
89 private final String artifactId;
90 private final Version version;
91 private final String classifier;
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 public MavenId( String coordinates ) {
115 CheckArg.isNotNull(coordinates, "coordinates");
116 coordinates = coordinates.trim();
117 CheckArg.isNotEmpty(coordinates, "coordinates");
118
119
120
121
122
123
124
125
126
127 Pattern urlPattern = Pattern.compile("([^:]+)(:([^:]+)(:([^:]*)(:([^:]*))?)?)?");
128 Matcher matcher = urlPattern.matcher(coordinates);
129 if (!matcher.find()) {
130 throw new IllegalArgumentException(MavenI18n.unsupportedMavenCoordinateFormat.text(coordinates));
131 }
132 String groupId = matcher.group(1);
133 String artifactId = matcher.group(3);
134 String version = matcher.group(5);
135 String classifier = matcher.group(7);
136 CheckArg.isNotEmpty(groupId, "groupId");
137 CheckArg.isNotEmpty(artifactId, "artifactId");
138 this.groupId = groupId.trim();
139 this.artifactId = artifactId.trim();
140 this.classifier = classifier != null ? classifier.trim() : "";
141 this.version = version != null ? new Version(version) : new Version("");
142 }
143
144
145
146
147
148
149
150 public MavenId( String groupId, String artifactId ) {
151 this(groupId, artifactId, null, null);
152 }
153
154
155
156
157
158
159
160
161 public MavenId( String groupId, String artifactId, String version ) {
162 this(groupId, artifactId, version, null);
163 }
164
165
166
167
168
169
170
171
172
173 public MavenId( String groupId, String artifactId, String version, String classifier ) {
174 CheckArg.isNotEmpty(groupId, "groupId");
175 CheckArg.isNotEmpty(artifactId, "artifactId");
176 this.groupId = groupId.trim();
177 this.artifactId = artifactId.trim();
178 this.classifier = classifier != null ? classifier.trim() : "";
179 this.version = version != null ? new Version(version) : new Version("");
180 }
181
182
183
184
185
186
187 public String getGroupId() {
188 return this.groupId;
189 }
190
191
192
193
194
195
196
197 public String getArtifactId() {
198 return this.artifactId;
199 }
200
201
202
203
204 public String getClassifier() {
205 return this.classifier;
206 }
207
208
209
210
211 public String getVersion() {
212 return this.version.toString();
213 }
214
215
216
217
218
219
220 public String getRelativePath() {
221 return getRelativePath(NoOpEncoder.getInstance());
222 }
223
224
225
226
227
228
229
230 public String getRelativePath( TextEncoder escapingStrategy ) {
231 return getRelativePath(NoOpEncoder.getInstance(), true);
232 }
233
234
235
236
237
238
239
240 public String getRelativePath( boolean includeVersion ) {
241 return getRelativePath(NoOpEncoder.getInstance(), includeVersion);
242 }
243
244
245
246
247
248
249
250
251 public String getRelativePath( TextEncoder escapingStrategy, boolean includeVersion ) {
252 StringBuilder sb = new StringBuilder();
253 String[] groupComponents = this.getGroupId().split("[\\.]");
254 for (String groupComponent : groupComponents) {
255 if (sb.length() != 0) sb.append("/");
256 sb.append(escapingStrategy.encode(groupComponent));
257 }
258 sb.append("/").append(escapingStrategy.encode(this.getArtifactId()));
259 if (includeVersion) {
260 sb.append("/").append(escapingStrategy.encode(this.getVersion()));
261 }
262 return sb.toString();
263 }
264
265 public String getCoordinates() {
266 return StringUtil.createString("{0}:{1}:{2}:{3}", this.groupId, this.artifactId, this.version, this.classifier);
267 }
268
269 public static MavenId createFromCoordinates( String coordinates ) {
270 String[] parts = coordinates.split("[:]");
271 String groupId = null;
272 String artifactId = null;
273 String version = null;
274 String classifier = null;
275 if (parts.length > 0) groupId = parts[0];
276 if (parts.length > 1) artifactId = parts[1];
277 if (parts.length > 2) version = parts[2];
278 if (parts.length > 3) classifier = parts[3];
279 return new MavenId(groupId, artifactId, classifier, version);
280 }
281
282 protected boolean isAnyVersion() {
283 return this.version.isAnyVersion();
284 }
285
286
287
288
289 @Override
290 public int hashCode() {
291
292 return HashCode.compute(this.groupId, this.artifactId, this.classifier);
293 }
294
295
296
297
298 @Override
299 public boolean equals( Object obj ) {
300 if (this == obj) return true;
301 if (obj instanceof MavenId) {
302 MavenId that = (MavenId)obj;
303 if (!this.groupId.equalsIgnoreCase(that.groupId)) return false;
304 if (!this.artifactId.equalsIgnoreCase(that.artifactId)) return false;
305 if (!this.version.equals(that.version)) return false;
306 if (!this.classifier.equalsIgnoreCase(that.classifier)) return false;
307 return true;
308 }
309 return false;
310 }
311
312
313
314
315 public int compareTo( MavenId that ) {
316 if (that == null) return 1;
317 if (this == that) return 0;
318
319
320 int diff = this.groupId.compareTo(that.groupId);
321 if (diff != 0) return diff;
322
323
324 diff = this.artifactId.compareTo(that.artifactId);
325 if (diff != 0) return diff;
326
327
328 diff = this.version.compareTo(that.version);
329 if (diff != 0) return diff;
330
331
332 diff = this.classifier.compareTo(that.classifier);
333 return diff;
334 }
335
336
337
338
339 @Override
340 public String toString() {
341 return this.getCoordinates();
342 }
343
344 public class Version implements Comparable<Version> {
345
346 private final String version;
347 private final Object[] components;
348
349 protected Version( String version ) {
350 this.version = version != null ? version.trim() : "";
351 this.components = getVersionComponents(this.version);
352 }
353
354
355
356
357 public Object[] getComponents() {
358 return this.components;
359 }
360
361 public boolean isAnyVersion() {
362 return this.version.length() == 0;
363 }
364
365
366
367
368 @Override
369 public String toString() {
370 return version;
371 }
372
373
374
375
376 @Override
377 public int hashCode() {
378 return this.version.hashCode();
379 }
380
381
382
383
384 public int compareTo( Version that ) {
385 if (that == null) return 1;
386 Object[] thisComponents = this.getComponents();
387 Object[] thatComponents = that.getComponents();
388 int thisLength = thisComponents.length;
389 int thatLength = thatComponents.length;
390 int minLength = Math.min(thisLength, thatLength);
391 for (int i = 0; i != minLength; ++i) {
392 Object thisComponent = thisComponents[i];
393 Object thatComponent = thatComponents[i];
394 int diff = 0;
395 if (thisComponent instanceof Integer && thatComponent instanceof Integer) {
396 diff = ((Integer)thisComponent).compareTo((Integer)thatComponent);
397 } else {
398 String thisString = thisComponent.toString();
399 String thatString = thatComponent.toString();
400 diff = thisString.compareToIgnoreCase(thatString);
401 }
402 if (diff != 0) return diff;
403 }
404 return 0;
405 }
406
407
408
409
410 @Override
411 public boolean equals( Object obj ) {
412 if (obj == this) return true;
413 if (obj instanceof Version) {
414 Version that = (Version)obj;
415 if (this.isAnyVersion() || that.isAnyVersion()) return true;
416 if (!this.version.equalsIgnoreCase(that.version)) return false;
417 return true;
418 }
419 return false;
420 }
421 }
422
423
424
425
426
427
428
429 protected static Object[] getVersionComponents( String version ) {
430 if (version == null) return new Object[] {};
431 version = version.trim();
432 if (version.length() == 0) return new Object[] {};
433 String[] parts = version.split("[\\.\\-/,]");
434 if (parts == null) return new Object[] {};
435 Object[] components = new Object[parts.length];
436 for (int i = 0, len = parts.length; i < len; i++) {
437 String part = parts[i].trim();
438 Object component = part;
439 try {
440 component = Integer.parseInt(part);
441 } catch (NumberFormatException e) {
442
443 }
444 components[i] = component;
445 }
446 return components;
447 }
448
449
450
451
452 @Override
453 public MavenId clone() {
454 return new MavenId(this.groupId, this.artifactId, this.version.toString(), this.classifier);
455 }
456 }