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