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 org.apache.maven.artifact.handler.ArtifactHandler;
28  import org.apache.maven.artifact.metadata.ArtifactMetadata;
29  import org.apache.maven.artifact.repository.ArtifactRepository;
30  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
31  import org.apache.maven.artifact.versioning.ArtifactVersion;
32  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
33  import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
34  import org.apache.maven.artifact.versioning.VersionRange;
35  import org.codehaus.plexus.util.StringUtils;
36  
37  /**
38   * @author Jason van Zyl
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      public DefaultArtifact(
99              String groupId,
100             String artifactId,
101             VersionRange versionRange,
102             String scope,
103             String type,
104             String classifier,
105             ArtifactHandler artifactHandler) {
106         this(groupId, artifactId, versionRange, scope, type, classifier, artifactHandler, false);
107     }
108 
109     @SuppressWarnings("checkstyle:parameternumber")
110     public DefaultArtifact(
111             String groupId,
112             String artifactId,
113             VersionRange versionRange,
114             String scope,
115             String type,
116             String classifier,
117             ArtifactHandler artifactHandler,
118             boolean optional) {
119         this.groupId = groupId;
120 
121         this.artifactId = artifactId;
122 
123         this.versionRange = versionRange;
124 
125         selectVersionFromNewRangeIfAvailable();
126 
127         this.artifactHandler = artifactHandler;
128 
129         this.scope = scope;
130 
131         this.type = type;
132 
133         if (classifier == null) {
134             classifier = artifactHandler.getClassifier();
135         }
136 
137         this.classifier = classifier;
138 
139         this.optional = optional;
140 
141         validateIdentity();
142     }
143 
144     private void validateIdentity() {
145         if (empty(groupId)) {
146             throw new InvalidArtifactRTException(
147                     groupId, artifactId, getVersion(), type, "The groupId cannot be empty.");
148         }
149 
150         if (artifactId == null) {
151             throw new InvalidArtifactRTException(
152                     groupId, artifactId, getVersion(), type, "The artifactId cannot be empty.");
153         }
154 
155         if (type == null) {
156             throw new InvalidArtifactRTException(groupId, artifactId, getVersion(), type, "The type cannot be empty.");
157         }
158 
159         if ((version == null) && (versionRange == null)) {
160             throw new InvalidArtifactRTException(
161                     groupId, artifactId, getVersion(), type, "The version cannot be empty.");
162         }
163     }
164 
165     private boolean empty(String value) {
166         return (value == null) || (value.trim().length() < 1);
167     }
168 
169     public String getClassifier() {
170         return classifier;
171     }
172 
173     public boolean hasClassifier() {
174         return StringUtils.isNotEmpty(classifier);
175     }
176 
177     public String getScope() {
178         return scope;
179     }
180 
181     public String getGroupId() {
182         return groupId;
183     }
184 
185     public String getArtifactId() {
186         return artifactId;
187     }
188 
189     public String getVersion() {
190         return version;
191     }
192 
193     public void setVersion(String version) {
194         this.version = version;
195         setBaseVersionInternal(version);
196         versionRange = null;
197     }
198 
199     public String getType() {
200         return type;
201     }
202 
203     public void setFile(File file) {
204         this.file = file;
205     }
206 
207     public File getFile() {
208         return file;
209     }
210 
211     public ArtifactRepository getRepository() {
212         return repository;
213     }
214 
215     public void setRepository(ArtifactRepository repository) {
216         this.repository = repository;
217     }
218 
219     // ----------------------------------------------------------------------
220     //
221     // ----------------------------------------------------------------------
222 
223     public String getId() {
224         return getDependencyConflictId() + ":" + getBaseVersion();
225     }
226 
227     public String getDependencyConflictId() {
228         StringBuilder sb = new StringBuilder(128);
229         sb.append(getGroupId());
230         sb.append(':');
231         appendArtifactTypeClassifierString(sb);
232         return sb.toString();
233     }
234 
235     private void appendArtifactTypeClassifierString(StringBuilder sb) {
236         sb.append(getArtifactId());
237         sb.append(':');
238         sb.append(getType());
239         if (hasClassifier()) {
240             sb.append(':');
241             sb.append(getClassifier());
242         }
243     }
244 
245     public void addMetadata(ArtifactMetadata metadata) {
246         if (metadataMap == null) {
247             metadataMap = new HashMap<>();
248         }
249 
250         ArtifactMetadata m = metadataMap.get(metadata.getKey());
251         if (m != null) {
252             m.merge(metadata);
253         } else {
254             metadataMap.put(metadata.getKey(), metadata);
255         }
256     }
257 
258     public Collection<ArtifactMetadata> getMetadataList() {
259         if (metadataMap == null) {
260             return Collections.emptyList();
261         }
262 
263         return Collections.unmodifiableCollection(metadataMap.values());
264     }
265 
266     // ----------------------------------------------------------------------
267     // Object overrides
268     // ----------------------------------------------------------------------
269 
270     public String toString() {
271         StringBuilder sb = new StringBuilder();
272         if (getGroupId() != null) {
273             sb.append(getGroupId());
274             sb.append(':');
275         }
276         appendArtifactTypeClassifierString(sb);
277         sb.append(':');
278         if (getBaseVersionInternal() != null) {
279             sb.append(getBaseVersionInternal());
280         } else {
281             sb.append(versionRange.toString());
282         }
283         if (scope != null) {
284             sb.append(':');
285             sb.append(scope);
286         }
287         return sb.toString();
288     }
289 
290     public int hashCode() {
291         int result = 17;
292         result = 37 * result + groupId.hashCode();
293         result = 37 * result + artifactId.hashCode();
294         result = 37 * result + type.hashCode();
295         if (version != null) {
296             result = 37 * result + version.hashCode();
297         }
298         result = 37 * result + (classifier != null ? classifier.hashCode() : 0);
299         return result;
300     }
301 
302     public boolean equals(Object o) {
303         if (o == this) {
304             return true;
305         }
306 
307         if (!(o instanceof Artifact)) {
308             return false;
309         }
310 
311         Artifact a = (Artifact) o;
312 
313         if (!a.getGroupId().equals(groupId)) {
314             return false;
315         } else if (!a.getArtifactId().equals(artifactId)) {
316             return false;
317         } else if (!a.getVersion().equals(version)) {
318             return false;
319         } else if (!a.getType().equals(type)) {
320             return false;
321         } else {
322             return a.getClassifier() == null
323                     ? classifier == null
324                     : a.getClassifier().equals(classifier);
325         }
326 
327         // We don't consider the version range in the comparison, just the resolved version
328     }
329 
330     public String getBaseVersion() {
331         if (baseVersion == null && version != null) {
332             setBaseVersionInternal(version);
333         }
334 
335         return baseVersion;
336     }
337 
338     protected String getBaseVersionInternal() {
339         if ((baseVersion == null) && (version != null)) {
340             setBaseVersionInternal(version);
341         }
342 
343         return baseVersion;
344     }
345 
346     public void setBaseVersion(String baseVersion) {
347         setBaseVersionInternal(baseVersion);
348     }
349 
350     protected void setBaseVersionInternal(String baseVersion) {
351         this.baseVersion = ArtifactUtils.toSnapshotVersion(baseVersion);
352     }
353 
354     public int compareTo(Artifact a) {
355         int result = groupId.compareTo(a.getGroupId());
356         if (result == 0) {
357             result = artifactId.compareTo(a.getArtifactId());
358             if (result == 0) {
359                 result = type.compareTo(a.getType());
360                 if (result == 0) {
361                     if (classifier == null) {
362                         if (a.getClassifier() != null) {
363                             result = 1;
364                         }
365                     } else {
366                         if (a.getClassifier() != null) {
367                             result = classifier.compareTo(a.getClassifier());
368                         } else {
369                             result = -1;
370                         }
371                     }
372                     if (result == 0) {
373                         // We don't consider the version range in the comparison, just the resolved version
374                         result = new DefaultArtifactVersion(version)
375                                 .compareTo(new DefaultArtifactVersion(a.getVersion()));
376                     }
377                 }
378             }
379         }
380         return result;
381     }
382 
383     public void updateVersion(String version, ArtifactRepository localRepository) {
384         setResolvedVersion(version);
385         setFile(new File(localRepository.getBasedir(), localRepository.pathOf(this)));
386     }
387 
388     public String getDownloadUrl() {
389         return downloadUrl;
390     }
391 
392     public void setDownloadUrl(String downloadUrl) {
393         this.downloadUrl = downloadUrl;
394     }
395 
396     public ArtifactFilter getDependencyFilter() {
397         return dependencyFilter;
398     }
399 
400     public void setDependencyFilter(ArtifactFilter artifactFilter) {
401         dependencyFilter = artifactFilter;
402     }
403 
404     public ArtifactHandler getArtifactHandler() {
405         return artifactHandler;
406     }
407 
408     public List<String> getDependencyTrail() {
409         return dependencyTrail;
410     }
411 
412     public void setDependencyTrail(List<String> dependencyTrail) {
413         this.dependencyTrail = dependencyTrail;
414     }
415 
416     public void setScope(String scope) {
417         this.scope = scope;
418     }
419 
420     public VersionRange getVersionRange() {
421         return versionRange;
422     }
423 
424     public void setVersionRange(VersionRange versionRange) {
425         this.versionRange = versionRange;
426         selectVersionFromNewRangeIfAvailable();
427     }
428 
429     private void selectVersionFromNewRangeIfAvailable() {
430         if ((versionRange != null) && (versionRange.getRecommendedVersion() != null)) {
431             selectVersion(versionRange.getRecommendedVersion().toString());
432         } else {
433             version = null;
434             baseVersion = null;
435         }
436     }
437 
438     public void selectVersion(String version) {
439         this.version = version;
440         setBaseVersionInternal(version);
441     }
442 
443     public void setGroupId(String groupId) {
444         this.groupId = groupId;
445     }
446 
447     public void setArtifactId(String artifactId) {
448         this.artifactId = artifactId;
449     }
450 
451     public boolean isSnapshot() {
452         return getBaseVersion() != null
453                 && (getBaseVersion().endsWith(SNAPSHOT_VERSION)
454                         || getBaseVersion().equals(LATEST_VERSION));
455     }
456 
457     public void setResolved(boolean resolved) {
458         this.resolved = resolved;
459     }
460 
461     public boolean isResolved() {
462         return resolved;
463     }
464 
465     public void setResolvedVersion(String version) {
466         this.version = version;
467         // retain baseVersion
468     }
469 
470     public void setArtifactHandler(ArtifactHandler artifactHandler) {
471         this.artifactHandler = artifactHandler;
472     }
473 
474     public void setRelease(boolean release) {
475         this.release = release;
476     }
477 
478     public boolean isRelease() {
479         return release;
480     }
481 
482     public List<ArtifactVersion> getAvailableVersions() {
483         return availableVersions;
484     }
485 
486     public void setAvailableVersions(List<ArtifactVersion> availableVersions) {
487         this.availableVersions = availableVersions;
488     }
489 
490     public boolean isOptional() {
491         return optional;
492     }
493 
494     public ArtifactVersion getSelectedVersion() throws OverConstrainedVersionException {
495         return versionRange.getSelectedVersion(this);
496     }
497 
498     public boolean isSelectedVersionKnown() throws OverConstrainedVersionException {
499         return versionRange.isSelectedVersionKnown(this);
500     }
501 
502     public void setOptional(boolean optional) {
503         this.optional = optional;
504     }
505 }