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