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