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     @Override
185     public String getClassifier() {
186         return classifier;
187     }
188 
189     @Override
190     public boolean hasClassifier() {
191         return classifier != null && !classifier.isEmpty();
192     }
193 
194     @Override
195     public String getScope() {
196         return scope;
197     }
198 
199     @Override
200     public String getGroupId() {
201         return groupId;
202     }
203 
204     @Override
205     public String getArtifactId() {
206         return artifactId;
207     }
208 
209     @Override
210     public String getVersion() {
211         return version;
212     }
213 
214     @Override
215     public void setVersion(String version) {
216         this.version = version;
217         setBaseVersionInternal(version);
218         versionRange = null;
219     }
220 
221     @Override
222     public String getType() {
223         return type;
224     }
225 
226     @Override
227     public void setFile(File file) {
228         this.file = file;
229     }
230 
231     @Override
232     public File getFile() {
233         return file;
234     }
235 
236     @Override
237     public ArtifactRepository getRepository() {
238         return repository;
239     }
240 
241     @Override
242     public void setRepository(ArtifactRepository repository) {
243         this.repository = repository;
244     }
245 
246     // ----------------------------------------------------------------------
247     //
248     // ----------------------------------------------------------------------
249 
250     @Override
251     public String getId() {
252         return getDependencyConflictId() + ":" + getBaseVersion();
253     }
254 
255     @Override
256     public String getDependencyConflictId() {
257         StringBuilder sb = new StringBuilder(128);
258         sb.append(getGroupId());
259         sb.append(':');
260         appendArtifactTypeClassifierString(sb);
261         return sb.toString();
262     }
263 
264     private void appendArtifactTypeClassifierString(StringBuilder sb) {
265         sb.append(getArtifactId());
266         sb.append(':');
267         sb.append(getType());
268         if (hasClassifier()) {
269             sb.append(':');
270             sb.append(getClassifier());
271         }
272     }
273 
274     @Override
275     public void addMetadata(ArtifactMetadata metadata) {
276         if (metadataMap == null) {
277             metadataMap = new HashMap<>();
278         }
279 
280         ArtifactMetadata m = metadataMap.get(metadata.getKey());
281         if (m != null) {
282             m.merge(metadata);
283         } else {
284             metadataMap.put(metadata.getKey(), metadata);
285         }
286     }
287 
288     @Override
289     public Collection<ArtifactMetadata> getMetadataList() {
290         if (metadataMap == null) {
291             return Collections.emptyList();
292         }
293 
294         return Collections.unmodifiableCollection(metadataMap.values());
295     }
296 
297     // ----------------------------------------------------------------------
298     // Object overrides
299     // ----------------------------------------------------------------------
300 
301     @Override
302     public String toString() {
303         StringBuilder sb = new StringBuilder();
304         if (getGroupId() != null) {
305             sb.append(getGroupId());
306             sb.append(':');
307         }
308         appendArtifactTypeClassifierString(sb);
309         sb.append(':');
310         if (getBaseVersionInternal() != null) {
311             sb.append(getBaseVersionInternal());
312         } else {
313             sb.append(versionRange.toString());
314         }
315         if (scope != null) {
316             sb.append(':');
317             sb.append(scope);
318         }
319         return sb.toString();
320     }
321 
322     @Override
323     public boolean equals(Object o) {
324         if (this == o) {
325             return true;
326         }
327         if (o == null || getClass() != o.getClass()) {
328             return false;
329         }
330         DefaultArtifact that = (DefaultArtifact) o;
331         return Objects.equals(groupId, that.groupId)
332                 && Objects.equals(artifactId, that.artifactId)
333                 && Objects.equals(type, that.type)
334                 && Objects.equals(classifier, that.classifier)
335                 && Objects.equals(version, that.version);
336     }
337 
338     @Override
339     public int hashCode() {
340         return Objects.hash(groupId, artifactId, type, classifier, version);
341     }
342 
343     @Override
344     public String getBaseVersion() {
345         if (baseVersion == null && version != null) {
346             setBaseVersionInternal(version);
347         }
348 
349         return baseVersion;
350     }
351 
352     protected String getBaseVersionInternal() {
353         if ((baseVersion == null) && (version != null)) {
354             setBaseVersionInternal(version);
355         }
356 
357         return baseVersion;
358     }
359 
360     @Override
361     public void setBaseVersion(String baseVersion) {
362         setBaseVersionInternal(baseVersion);
363     }
364 
365     protected void setBaseVersionInternal(String baseVersion) {
366         this.baseVersion = ArtifactUtils.toSnapshotVersion(baseVersion);
367     }
368 
369     @Override
370     public int compareTo(Artifact a) {
371         int result = groupId.compareTo(a.getGroupId());
372         if (result == 0) {
373             result = artifactId.compareTo(a.getArtifactId());
374             if (result == 0) {
375                 result = type.compareTo(a.getType());
376                 if (result == 0) {
377                     if (classifier == null) {
378                         if (a.getClassifier() != null) {
379                             result = 1;
380                         }
381                     } else {
382                         if (a.getClassifier() != null) {
383                             result = classifier.compareTo(a.getClassifier());
384                         } else {
385                             result = -1;
386                         }
387                     }
388                     if (result == 0) {
389                         // We don't consider the version range in the comparison, just the resolved version
390                         result = new DefaultArtifactVersion(version)
391                                 .compareTo(new DefaultArtifactVersion(a.getVersion()));
392                     }
393                 }
394             }
395         }
396         return result;
397     }
398 
399     @Override
400     public void updateVersion(String version, ArtifactRepository localRepository) {
401         setResolvedVersion(version);
402         setFile(new File(localRepository.getBasedir(), localRepository.pathOf(this)));
403     }
404 
405     @Override
406     public String getDownloadUrl() {
407         return downloadUrl;
408     }
409 
410     @Override
411     public void setDownloadUrl(String downloadUrl) {
412         this.downloadUrl = downloadUrl;
413     }
414 
415     @Override
416     public ArtifactFilter getDependencyFilter() {
417         return dependencyFilter;
418     }
419 
420     @Override
421     public void setDependencyFilter(ArtifactFilter artifactFilter) {
422         dependencyFilter = artifactFilter;
423     }
424 
425     @Override
426     public ArtifactHandler getArtifactHandler() {
427         return artifactHandler;
428     }
429 
430     @Override
431     public List<String> getDependencyTrail() {
432         return dependencyTrail;
433     }
434 
435     @Override
436     public void setDependencyTrail(List<String> dependencyTrail) {
437         this.dependencyTrail = dependencyTrail;
438     }
439 
440     @Override
441     public void setScope(String scope) {
442         this.scope = scope;
443     }
444 
445     @Override
446     public VersionRange getVersionRange() {
447         return versionRange;
448     }
449 
450     @Override
451     public void setVersionRange(VersionRange versionRange) {
452         this.versionRange = versionRange;
453         selectVersionFromNewRangeIfAvailable();
454     }
455 
456     private void selectVersionFromNewRangeIfAvailable() {
457         if ((versionRange != null) && (versionRange.getRecommendedVersion() != null)) {
458             selectVersion(versionRange.getRecommendedVersion().toString());
459         } else {
460             version = null;
461             baseVersion = null;
462         }
463     }
464 
465     @Override
466     public void selectVersion(String version) {
467         this.version = version;
468         setBaseVersionInternal(version);
469     }
470 
471     @Override
472     public void setGroupId(String groupId) {
473         this.groupId = groupId;
474     }
475 
476     @Override
477     public void setArtifactId(String artifactId) {
478         this.artifactId = artifactId;
479     }
480 
481     @Override
482     public boolean isSnapshot() {
483         return getBaseVersion() != null
484                 && (getBaseVersion().endsWith(SNAPSHOT_VERSION)
485                         || getBaseVersion().equals(LATEST_VERSION));
486     }
487 
488     @Override
489     public void setResolved(boolean resolved) {
490         this.resolved = resolved;
491     }
492 
493     @Override
494     public boolean isResolved() {
495         return resolved;
496     }
497 
498     @Override
499     public void setResolvedVersion(String version) {
500         this.version = version;
501         // retain baseVersion
502     }
503 
504     @Override
505     public void setArtifactHandler(ArtifactHandler artifactHandler) {
506         this.artifactHandler = artifactHandler;
507     }
508 
509     @Override
510     public void setRelease(boolean release) {
511         this.release = release;
512     }
513 
514     @Override
515     public boolean isRelease() {
516         return release;
517     }
518 
519     @Override
520     public List<ArtifactVersion> getAvailableVersions() {
521         return availableVersions;
522     }
523 
524     @Override
525     public void setAvailableVersions(List<ArtifactVersion> availableVersions) {
526         this.availableVersions = availableVersions;
527     }
528 
529     @Override
530     public boolean isOptional() {
531         return optional;
532     }
533 
534     @Override
535     public ArtifactVersion getSelectedVersion() throws OverConstrainedVersionException {
536         return versionRange.getSelectedVersion(this);
537     }
538 
539     @Override
540     public boolean isSelectedVersionKnown() throws OverConstrainedVersionException {
541         return versionRange.isSelectedVersionKnown(this);
542     }
543 
544     @Override
545     public void setOptional(boolean optional) {
546         this.optional = optional;
547     }
548 }