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 {
323             return a.getClassifier() == null
324                     ? classifier == null
325                     : a.getClassifier().equals(classifier);
326         }
327 
328         // We don't consider the version range in the comparison, just the resolved version
329     }
330 
331     public String getBaseVersion() {
332         if (baseVersion == null && version != null) {
333             setBaseVersionInternal(version);
334         }
335 
336         return baseVersion;
337     }
338 
339     protected String getBaseVersionInternal() {
340         if ((baseVersion == null) && (version != null)) {
341             setBaseVersionInternal(version);
342         }
343 
344         return baseVersion;
345     }
346 
347     public void setBaseVersion(String baseVersion) {
348         setBaseVersionInternal(baseVersion);
349     }
350 
351     protected void setBaseVersionInternal(String baseVersion) {
352         this.baseVersion = ArtifactUtils.toSnapshotVersion(baseVersion);
353     }
354 
355     public int compareTo(Artifact a) {
356         int result = groupId.compareTo(a.getGroupId());
357         if (result == 0) {
358             result = artifactId.compareTo(a.getArtifactId());
359             if (result == 0) {
360                 result = type.compareTo(a.getType());
361                 if (result == 0) {
362                     if (classifier == null) {
363                         if (a.getClassifier() != null) {
364                             result = 1;
365                         }
366                     } else {
367                         if (a.getClassifier() != null) {
368                             result = classifier.compareTo(a.getClassifier());
369                         } else {
370                             result = -1;
371                         }
372                     }
373                     if (result == 0) {
374                         // We don't consider the version range in the comparison, just the resolved version
375                         result = new DefaultArtifactVersion(version)
376                                 .compareTo(new DefaultArtifactVersion(a.getVersion()));
377                     }
378                 }
379             }
380         }
381         return result;
382     }
383 
384     public void updateVersion(String version, ArtifactRepository localRepository) {
385         setResolvedVersion(version);
386         setFile(new File(localRepository.getBasedir(), localRepository.pathOf(this)));
387     }
388 
389     public String getDownloadUrl() {
390         return downloadUrl;
391     }
392 
393     public void setDownloadUrl(String downloadUrl) {
394         this.downloadUrl = downloadUrl;
395     }
396 
397     public ArtifactFilter getDependencyFilter() {
398         return dependencyFilter;
399     }
400 
401     public void setDependencyFilter(ArtifactFilter artifactFilter) {
402         dependencyFilter = artifactFilter;
403     }
404 
405     public ArtifactHandler getArtifactHandler() {
406         return artifactHandler;
407     }
408 
409     public List<String> getDependencyTrail() {
410         return dependencyTrail;
411     }
412 
413     public void setDependencyTrail(List<String> dependencyTrail) {
414         this.dependencyTrail = dependencyTrail;
415     }
416 
417     public void setScope(String scope) {
418         this.scope = scope;
419     }
420 
421     public VersionRange getVersionRange() {
422         return versionRange;
423     }
424 
425     public void setVersionRange(VersionRange versionRange) {
426         this.versionRange = versionRange;
427         selectVersionFromNewRangeIfAvailable();
428     }
429 
430     private void selectVersionFromNewRangeIfAvailable() {
431         if ((versionRange != null) && (versionRange.getRecommendedVersion() != null)) {
432             selectVersion(versionRange.getRecommendedVersion().toString());
433         } else {
434             version = null;
435             baseVersion = null;
436         }
437     }
438 
439     public void selectVersion(String version) {
440         this.version = version;
441         setBaseVersionInternal(version);
442     }
443 
444     public void setGroupId(String groupId) {
445         this.groupId = groupId;
446     }
447 
448     public void setArtifactId(String artifactId) {
449         this.artifactId = artifactId;
450     }
451 
452     public boolean isSnapshot() {
453         return getBaseVersion() != null
454                 && (getBaseVersion().endsWith(SNAPSHOT_VERSION)
455                         || getBaseVersion().equals(LATEST_VERSION));
456     }
457 
458     public void setResolved(boolean resolved) {
459         this.resolved = resolved;
460     }
461 
462     public boolean isResolved() {
463         return resolved;
464     }
465 
466     public void setResolvedVersion(String version) {
467         this.version = version;
468         // retain baseVersion
469     }
470 
471     public void setArtifactHandler(ArtifactHandler artifactHandler) {
472         this.artifactHandler = artifactHandler;
473     }
474 
475     public void setRelease(boolean release) {
476         this.release = release;
477     }
478 
479     public boolean isRelease() {
480         return release;
481     }
482 
483     public List<ArtifactVersion> getAvailableVersions() {
484         return availableVersions;
485     }
486 
487     public void setAvailableVersions(List<ArtifactVersion> availableVersions) {
488         this.availableVersions = availableVersions;
489     }
490 
491     public boolean isOptional() {
492         return optional;
493     }
494 
495     public ArtifactVersion getSelectedVersion() throws OverConstrainedVersionException {
496         return versionRange.getSelectedVersion(this);
497     }
498 
499     public boolean isSelectedVersionKnown() throws OverConstrainedVersionException {
500         return versionRange.isSelectedVersionKnown(this);
501     }
502 
503     public void setOptional(boolean optional) {
504         this.optional = optional;
505     }
506 }