View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.artifact;
20  
21  import java.io.File;
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Objects;
28  
29  import org.apache.maven.artifact.handler.ArtifactHandler;
30  import org.apache.maven.artifact.metadata.ArtifactMetadata;
31  import org.apache.maven.artifact.repository.ArtifactRepository;
32  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
33  import org.apache.maven.artifact.versioning.ArtifactVersion;
34  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
35  import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
36  import org.apache.maven.artifact.versioning.VersionRange;
37  
38  /**
39   */
40  public class DefaultArtifact implements Artifact {
41      private String groupId;
42  
43      private String artifactId;
44  
45      private String baseVersion;
46  
47      private final String type;
48  
49      private final String classifier;
50  
51      private volatile String scope;
52  
53      private volatile File file;
54  
55      private ArtifactRepository repository;
56  
57      private String downloadUrl;
58  
59      private ArtifactFilter dependencyFilter;
60  
61      private ArtifactHandler artifactHandler;
62  
63      private List<String> dependencyTrail;
64  
65      private volatile String version;
66  
67      private VersionRange versionRange;
68  
69      private volatile boolean resolved;
70  
71      private boolean release;
72  
73      private List<ArtifactVersion> availableVersions;
74  
75      private Map<Object, ArtifactMetadata> metadataMap;
76  
77      private boolean optional;
78  
79      public DefaultArtifact(
80              String groupId,
81              String artifactId,
82              String version,
83              String scope,
84              String type,
85              String classifier,
86              ArtifactHandler artifactHandler) {
87          this(
88                  groupId,
89                  artifactId,
90                  VersionRange.createFromVersion(version),
91                  scope,
92                  type,
93                  classifier,
94                  artifactHandler,
95                  false);
96      }
97  
98      @SuppressWarnings("checkstyle:ParameterNumber")
99      public DefaultArtifact(
100             String groupId,
101             String artifactId,
102             String version,
103             String scope,
104             String type,
105             String classifier,
106             ArtifactHandler artifactHandler,
107             boolean optional) {
108         this(
109                 groupId,
110                 artifactId,
111                 VersionRange.createFromVersion(version),
112                 scope,
113                 type,
114                 classifier,
115                 artifactHandler,
116                 optional);
117     }
118 
119     public DefaultArtifact(
120             String groupId,
121             String artifactId,
122             VersionRange versionRange,
123             String scope,
124             String type,
125             String classifier,
126             ArtifactHandler artifactHandler) {
127         this(groupId, artifactId, versionRange, scope, type, classifier, artifactHandler, false);
128     }
129 
130     @SuppressWarnings("checkstyle:parameternumber")
131     public DefaultArtifact(
132             String groupId,
133             String artifactId,
134             VersionRange versionRange,
135             String scope,
136             String type,
137             String classifier,
138             ArtifactHandler artifactHandler,
139             boolean optional) {
140         this.groupId = groupId;
141 
142         this.artifactId = artifactId;
143 
144         this.versionRange = versionRange;
145 
146         selectVersionFromNewRangeIfAvailable();
147 
148         this.artifactHandler = artifactHandler;
149 
150         this.scope = scope;
151 
152         this.type = type;
153 
154         if (classifier == null) {
155             classifier = artifactHandler.getClassifier();
156         }
157 
158         this.classifier = classifier;
159 
160         this.optional = optional;
161 
162         validateIdentity();
163     }
164 
165     private void validateIdentity() {
166         if (empty(groupId)) {
167             throw new InvalidArtifactRTException(
168                     groupId, artifactId, getVersion(), type, "The groupId cannot be empty.");
169         }
170 
171         if (empty(artifactId)) {
172             throw new InvalidArtifactRTException(
173                     groupId, artifactId, getVersion(), type, "The artifactId cannot be empty.");
174         }
175 
176         if (empty(type)) {
177             throw new InvalidArtifactRTException(groupId, artifactId, getVersion(), type, "The type cannot be empty.");
178         }
179 
180         if ((empty(version)) && (versionRange == null)) {
181             throw new InvalidArtifactRTException(
182                     groupId, artifactId, getVersion(), type, "The version cannot be empty.");
183         }
184     }
185 
186     public static boolean empty(String value) {
187         return (value == null) || (value.trim().length() < 1);
188     }
189 
190     @Override
191     public String getClassifier() {
192         return classifier;
193     }
194 
195     @Override
196     public boolean hasClassifier() {
197         return classifier != null && !classifier.isEmpty();
198     }
199 
200     @Override
201     public String getScope() {
202         return scope;
203     }
204 
205     @Override
206     public String getGroupId() {
207         return groupId;
208     }
209 
210     @Override
211     public String getArtifactId() {
212         return artifactId;
213     }
214 
215     @Override
216     public String getVersion() {
217         return version;
218     }
219 
220     @Override
221     public void setVersion(String version) {
222         this.version = version;
223         setBaseVersionInternal(version);
224         versionRange = null;
225     }
226 
227     @Override
228     public String getType() {
229         return type;
230     }
231 
232     @Override
233     public void setFile(File file) {
234         this.file = file;
235     }
236 
237     @Override
238     public File getFile() {
239         return file;
240     }
241 
242     @Override
243     public ArtifactRepository getRepository() {
244         return repository;
245     }
246 
247     @Override
248     public void setRepository(ArtifactRepository repository) {
249         this.repository = repository;
250     }
251 
252     // ----------------------------------------------------------------------
253     //
254     // ----------------------------------------------------------------------
255 
256     @Override
257     public String getId() {
258         return getDependencyConflictId() + ":" + getBaseVersion();
259     }
260 
261     @Override
262     public String getDependencyConflictId() {
263         StringBuilder sb = new StringBuilder(128);
264         sb.append(getGroupId());
265         sb.append(':');
266         appendArtifactTypeClassifierString(sb);
267         return sb.toString();
268     }
269 
270     private void appendArtifactTypeClassifierString(StringBuilder sb) {
271         sb.append(getArtifactId());
272         sb.append(':');
273         sb.append(getType());
274         if (hasClassifier()) {
275             sb.append(':');
276             sb.append(getClassifier());
277         }
278     }
279 
280     @Override
281     public void addMetadata(ArtifactMetadata metadata) {
282         if (metadataMap == null) {
283             metadataMap = new HashMap<>();
284         }
285 
286         ArtifactMetadata m = metadataMap.get(metadata.getKey());
287         if (m != null) {
288             m.merge(metadata);
289         } else {
290             metadataMap.put(metadata.getKey(), metadata);
291         }
292     }
293 
294     @Override
295     public Collection<ArtifactMetadata> getMetadataList() {
296         if (metadataMap == null) {
297             return Collections.emptyList();
298         }
299 
300         return Collections.unmodifiableCollection(metadataMap.values());
301     }
302 
303     // ----------------------------------------------------------------------
304     // Object overrides
305     // ----------------------------------------------------------------------
306 
307     @Override
308     public String toString() {
309         StringBuilder sb = new StringBuilder();
310         if (getGroupId() != null) {
311             sb.append(getGroupId());
312             sb.append(':');
313         }
314         appendArtifactTypeClassifierString(sb);
315         sb.append(':');
316         if (getBaseVersionInternal() != null) {
317             sb.append(getBaseVersionInternal());
318         } else {
319             sb.append(versionRange.toString());
320         }
321         if (scope != null) {
322             sb.append(':');
323             sb.append(scope);
324         }
325         return sb.toString();
326     }
327 
328     @Override
329     public boolean equals(Object o) {
330         if (this == o) {
331             return true;
332         }
333         if (o == null || getClass() != o.getClass()) {
334             return false;
335         }
336         DefaultArtifact that = (DefaultArtifact) o;
337         return Objects.equals(groupId, that.groupId)
338                 && Objects.equals(artifactId, that.artifactId)
339                 && Objects.equals(type, that.type)
340                 && Objects.equals(classifier, that.classifier)
341                 && Objects.equals(version, that.version);
342     }
343 
344     @Override
345     public int hashCode() {
346         return Objects.hash(groupId, artifactId, type, classifier, version);
347     }
348 
349     @Override
350     public String getBaseVersion() {
351         if (baseVersion == null && version != null) {
352             setBaseVersionInternal(version);
353         }
354 
355         return baseVersion;
356     }
357 
358     protected String getBaseVersionInternal() {
359         if ((baseVersion == null) && (version != null)) {
360             setBaseVersionInternal(version);
361         }
362 
363         return baseVersion;
364     }
365 
366     @Override
367     public void setBaseVersion(String baseVersion) {
368         setBaseVersionInternal(baseVersion);
369     }
370 
371     protected void setBaseVersionInternal(String baseVersion) {
372         this.baseVersion = ArtifactUtils.toSnapshotVersion(baseVersion);
373     }
374 
375     @Override
376     public int compareTo(Artifact a) {
377         int result = groupId.compareTo(a.getGroupId());
378         if (result == 0) {
379             result = artifactId.compareTo(a.getArtifactId());
380             if (result == 0) {
381                 result = type.compareTo(a.getType());
382                 if (result == 0) {
383                     if (classifier == null) {
384                         if (a.getClassifier() != null) {
385                             result = 1;
386                         }
387                     } else {
388                         if (a.getClassifier() != null) {
389                             result = classifier.compareTo(a.getClassifier());
390                         } else {
391                             result = -1;
392                         }
393                     }
394                     if (result == 0) {
395                         // We don't consider the version range in the comparison, just the resolved version
396                         result = new DefaultArtifactVersion(version)
397                                 .compareTo(new DefaultArtifactVersion(a.getVersion()));
398                     }
399                 }
400             }
401         }
402         return result;
403     }
404 
405     @Override
406     public void updateVersion(String version, ArtifactRepository localRepository) {
407         setResolvedVersion(version);
408         setFile(new File(localRepository.getBasedir(), localRepository.pathOf(this)));
409     }
410 
411     @Override
412     public String getDownloadUrl() {
413         return downloadUrl;
414     }
415 
416     @Override
417     public void setDownloadUrl(String downloadUrl) {
418         this.downloadUrl = downloadUrl;
419     }
420 
421     @Override
422     public ArtifactFilter getDependencyFilter() {
423         return dependencyFilter;
424     }
425 
426     @Override
427     public void setDependencyFilter(ArtifactFilter artifactFilter) {
428         dependencyFilter = artifactFilter;
429     }
430 
431     @Override
432     public ArtifactHandler getArtifactHandler() {
433         return artifactHandler;
434     }
435 
436     @Override
437     public List<String> getDependencyTrail() {
438         return dependencyTrail;
439     }
440 
441     @Override
442     public void setDependencyTrail(List<String> dependencyTrail) {
443         this.dependencyTrail = dependencyTrail;
444     }
445 
446     @Override
447     public void setScope(String scope) {
448         this.scope = scope;
449     }
450 
451     @Override
452     public VersionRange getVersionRange() {
453         return versionRange;
454     }
455 
456     @Override
457     public void setVersionRange(VersionRange versionRange) {
458         this.versionRange = versionRange;
459         selectVersionFromNewRangeIfAvailable();
460     }
461 
462     private void selectVersionFromNewRangeIfAvailable() {
463         if ((versionRange != null) && (versionRange.getRecommendedVersion() != null)) {
464             selectVersion(versionRange.getRecommendedVersion().toString());
465         } else {
466             version = null;
467             baseVersion = null;
468         }
469     }
470 
471     @Override
472     public void selectVersion(String version) {
473         this.version = version;
474         setBaseVersionInternal(version);
475     }
476 
477     @Override
478     public void setGroupId(String groupId) {
479         this.groupId = groupId;
480     }
481 
482     @Override
483     public void setArtifactId(String artifactId) {
484         this.artifactId = artifactId;
485     }
486 
487     @Override
488     public boolean isSnapshot() {
489         return getBaseVersion() != null
490                 && (getBaseVersion().endsWith(SNAPSHOT_VERSION)
491                         || getBaseVersion().equals(LATEST_VERSION));
492     }
493 
494     @Override
495     public void setResolved(boolean resolved) {
496         this.resolved = resolved;
497     }
498 
499     @Override
500     public boolean isResolved() {
501         return resolved;
502     }
503 
504     @Override
505     public void setResolvedVersion(String version) {
506         this.version = version;
507         // retain baseVersion
508     }
509 
510     @Override
511     public void setArtifactHandler(ArtifactHandler artifactHandler) {
512         this.artifactHandler = artifactHandler;
513     }
514 
515     @Override
516     public void setRelease(boolean release) {
517         this.release = release;
518     }
519 
520     @Override
521     public boolean isRelease() {
522         return release;
523     }
524 
525     @Override
526     public List<ArtifactVersion> getAvailableVersions() {
527         return availableVersions;
528     }
529 
530     @Override
531     public void setAvailableVersions(List<ArtifactVersion> availableVersions) {
532         this.availableVersions = availableVersions;
533     }
534 
535     @Override
536     public boolean isOptional() {
537         return optional;
538     }
539 
540     @Override
541     public ArtifactVersion getSelectedVersion() throws OverConstrainedVersionException {
542         return versionRange.getSelectedVersion(this);
543     }
544 
545     @Override
546     public boolean isSelectedVersionKnown() throws OverConstrainedVersionException {
547         return versionRange.isSelectedVersionKnown(this);
548     }
549 
550     @Override
551     public void setOptional(boolean optional) {
552         this.optional = optional;
553     }
554 }