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