View Javadoc
1   package org.apache.maven.artifact;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.regex.Matcher;
29  
30  import org.apache.maven.artifact.handler.ArtifactHandler;
31  import org.apache.maven.artifact.metadata.ArtifactMetadata;
32  import org.apache.maven.artifact.repository.ArtifactRepository;
33  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
34  import org.apache.maven.artifact.versioning.ArtifactVersion;
35  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
36  import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
37  import org.apache.maven.artifact.versioning.VersionRange;
38  import org.codehaus.plexus.util.StringUtils;
39  
40  /**
41   * @author Jason van Zyl
42   */
43  public class DefaultArtifact
44      implements Artifact
45  {
46      private String groupId;
47  
48      private String artifactId;
49  
50      private String baseVersion;
51  
52      private final String type;
53  
54      private final String classifier;
55  
56      private volatile String scope;
57  
58      private volatile File file;
59  
60      private ArtifactRepository repository;
61  
62      private String downloadUrl;
63  
64      private ArtifactFilter dependencyFilter;
65  
66      private ArtifactHandler artifactHandler;
67  
68      private List<String> dependencyTrail;
69  
70      private volatile String version;
71  
72      private VersionRange versionRange;
73  
74      private volatile boolean resolved;
75  
76      private boolean release;
77  
78      private List<ArtifactVersion> availableVersions;
79  
80      private Map<Object, ArtifactMetadata> metadataMap;
81  
82      private boolean optional;
83  
84      public DefaultArtifact( String groupId, String artifactId, String version, String scope, String type,
85                              String classifier, ArtifactHandler artifactHandler )
86      {
87          this( groupId, artifactId, VersionRange.createFromVersion( version ), scope, type, classifier, artifactHandler,
88                false );
89      }
90  
91      public DefaultArtifact( String groupId, String artifactId, VersionRange versionRange, String scope, String type,
92                              String classifier, ArtifactHandler artifactHandler )
93      {
94          this( groupId, artifactId, versionRange, scope, type, classifier, artifactHandler, false );
95      }
96  
97      public DefaultArtifact( String groupId, String artifactId, VersionRange versionRange, String scope, String type,
98                              String classifier, ArtifactHandler artifactHandler, boolean optional )
99      {
100         this.groupId = groupId;
101 
102         this.artifactId = artifactId;
103 
104         this.versionRange = versionRange;
105 
106         selectVersionFromNewRangeIfAvailable();
107 
108         this.artifactHandler = artifactHandler;
109 
110         this.scope = scope;
111 
112         this.type = type;
113 
114         if ( classifier == null )
115         {
116             classifier = artifactHandler.getClassifier();
117         }
118 
119         this.classifier = classifier;
120 
121         this.optional = optional;
122 
123         validateIdentity();
124     }
125 
126     private void validateIdentity()
127     {
128         if ( empty( groupId ) )
129         {
130             throw new InvalidArtifactRTException( groupId, artifactId, getVersion(), type,
131                 "The groupId cannot be empty." );
132         }
133 
134         if ( artifactId == null )
135         {
136             throw new InvalidArtifactRTException( groupId, artifactId, getVersion(), type,
137                 "The artifactId cannot be empty." );
138         }
139 
140         if ( type == null )
141         {
142             throw new InvalidArtifactRTException( groupId, artifactId, getVersion(), type,
143                 "The type cannot be empty." );
144         }
145 
146         if ( ( version == null ) && ( versionRange == null ) )
147         {
148             throw new InvalidArtifactRTException( groupId, artifactId, getVersion(), type,
149                 "The version cannot be empty." );
150         }
151     }
152 
153     private boolean empty( String value )
154     {
155         return ( value == null ) || ( value.trim().length() < 1 );
156     }
157 
158     public String getClassifier()
159     {
160         return classifier;
161     }
162 
163     public boolean hasClassifier()
164     {
165         return StringUtils.isNotEmpty( classifier );
166     }
167 
168     public String getScope()
169     {
170         return scope;
171     }
172 
173     public String getGroupId()
174     {
175         return groupId;
176     }
177 
178     public String getArtifactId()
179     {
180         return artifactId;
181     }
182 
183     public String getVersion()
184     {
185         return version;
186     }
187 
188     public void setVersion( String version )
189     {
190         this.version = version;
191         setBaseVersionInternal( version );
192         versionRange = null;
193     }
194 
195     public String getType()
196     {
197         return type;
198     }
199 
200     public void setFile( File file )
201     {
202         this.file = file;
203     }
204 
205     public File getFile()
206     {
207         return file;
208     }
209 
210     public ArtifactRepository getRepository()
211     {
212         return repository;
213     }
214 
215     public void setRepository( ArtifactRepository repository )
216     {
217         this.repository = repository;
218     }
219 
220     // ----------------------------------------------------------------------
221     //
222     // ----------------------------------------------------------------------
223 
224     public String getId()
225     {
226         return getDependencyConflictId() + ":" + getBaseVersion();
227     }
228 
229     public String getDependencyConflictId()
230     {
231         StringBuilder sb = new StringBuilder( 128 );
232         sb.append( getGroupId() );
233         sb.append( ':' );
234         appendArtifactTypeClassifierString( sb );
235         return sb.toString();
236     }
237 
238     private void appendArtifactTypeClassifierString( StringBuilder sb )
239     {
240         sb.append( getArtifactId() );
241         sb.append( ':' );
242         sb.append( getType() );
243         if ( hasClassifier() )
244         {
245             sb.append( ':' );
246             sb.append( getClassifier() );
247         }
248     }
249 
250     public void addMetadata( ArtifactMetadata metadata )
251     {
252         if ( metadataMap == null )
253         {
254             metadataMap = new HashMap<>();
255         }
256 
257         ArtifactMetadata m = metadataMap.get( metadata.getKey() );
258         if ( m != null )
259         {
260             m.merge( metadata );
261         }
262         else
263         {
264             metadataMap.put( metadata.getKey(), metadata );
265         }
266     }
267 
268     public Collection<ArtifactMetadata> getMetadataList()
269     {
270         if ( metadataMap == null )
271         {
272             return Collections.emptyList();
273         }
274 
275         return metadataMap.values();
276     }
277 
278     // ----------------------------------------------------------------------
279     // Object overrides
280     // ----------------------------------------------------------------------
281 
282     public String toString()
283     {
284         StringBuilder sb = new StringBuilder();
285         if ( getGroupId() != null )
286         {
287             sb.append( getGroupId() );
288             sb.append( ':' );
289         }
290         appendArtifactTypeClassifierString( sb );
291         sb.append( ':' );
292         if ( getBaseVersionInternal() != null )
293         {
294             sb.append( getBaseVersionInternal() );
295         }
296         else
297         {
298             sb.append( versionRange.toString() );
299         }
300         if ( scope != null )
301         {
302             sb.append( ':' );
303             sb.append( scope );
304         }
305         return sb.toString();
306     }
307 
308     public int hashCode()
309     {
310         int result = 17;
311         result = 37 * result + groupId.hashCode();
312         result = 37 * result + artifactId.hashCode();
313         result = 37 * result + type.hashCode();
314         if ( version != null )
315         {
316             result = 37 * result + version.hashCode();
317         }
318         result = 37 * result + ( classifier != null ? classifier.hashCode() : 0 );
319         return result;
320     }
321 
322     public boolean equals( Object o )
323     {
324         if ( o == this )
325         {
326             return true;
327         }
328 
329         if ( !( o instanceof Artifact ) )
330         {
331             return false;
332         }
333 
334         Artifact a = (Artifact) o;
335 
336         if ( !a.getGroupId().equals( groupId ) )
337         {
338             return false;
339         }
340         else if ( !a.getArtifactId().equals( artifactId ) )
341         {
342             return false;
343         }
344         else if ( !a.getVersion().equals( version ) )
345         {
346             return false;
347         }
348         else if ( !a.getType().equals( type ) )
349         {
350             return false;
351         }
352         else if ( a.getClassifier() == null ? classifier != null : !a.getClassifier().equals( classifier ) )
353         {
354             return false;
355         }
356 
357         // We don't consider the version range in the comparison, just the resolved version
358 
359         return true;
360     }
361 
362     public String getBaseVersion()
363     {
364         if ( baseVersion == null && version != null )
365         {
366             setBaseVersionInternal( version );
367         }
368 
369         return baseVersion;
370     }
371 
372     protected String getBaseVersionInternal()
373     {
374         if ( ( baseVersion == null ) && ( version != null ) )
375         {
376             setBaseVersionInternal( version );
377         }
378 
379         return baseVersion;
380     }
381 
382     public void setBaseVersion( String baseVersion )
383     {
384         setBaseVersionInternal( baseVersion );
385     }
386 
387     protected void setBaseVersionInternal( String baseVersion )
388     {
389         Matcher m = VERSION_FILE_PATTERN.matcher( baseVersion );
390 
391         if ( m.matches() )
392         {
393             this.baseVersion = m.group( 1 ) + "-" + SNAPSHOT_VERSION;
394         }
395         else
396         {
397             this.baseVersion = baseVersion;
398         }
399     }
400 
401     public int compareTo( Artifact a )
402     {
403         int result = groupId.compareTo( a.getGroupId() );
404         if ( result == 0 )
405         {
406             result = artifactId.compareTo( a.getArtifactId() );
407             if ( result == 0 )
408             {
409                 result = type.compareTo( a.getType() );
410                 if ( result == 0 )
411                 {
412                     if ( classifier == null )
413                     {
414                         if ( a.getClassifier() != null )
415                         {
416                             result = 1;
417                         }
418                     }
419                     else
420                     {
421                         if ( a.getClassifier() != null )
422                         {
423                             result = classifier.compareTo( a.getClassifier() );
424                         }
425                         else
426                         {
427                             result = -1;
428                         }
429                     }
430                     if ( result == 0 )
431                     {
432                         // We don't consider the version range in the comparison, just the resolved version
433                         result = new DefaultArtifactVersion( version ).compareTo(
434                             new DefaultArtifactVersion( a.getVersion() ) );
435                     }
436                 }
437             }
438         }
439         return result;
440     }
441 
442     public void updateVersion( String version, ArtifactRepository localRepository )
443     {
444         setResolvedVersion( version );
445         setFile( new File( localRepository.getBasedir(), localRepository.pathOf( this ) ) );
446     }
447 
448     public String getDownloadUrl()
449     {
450         return downloadUrl;
451     }
452 
453     public void setDownloadUrl( String downloadUrl )
454     {
455         this.downloadUrl = downloadUrl;
456     }
457 
458     public ArtifactFilter getDependencyFilter()
459     {
460         return dependencyFilter;
461     }
462 
463     public void setDependencyFilter( ArtifactFilter artifactFilter )
464     {
465         dependencyFilter = artifactFilter;
466     }
467 
468     public ArtifactHandler getArtifactHandler()
469     {
470         return artifactHandler;
471     }
472 
473     public List<String> getDependencyTrail()
474     {
475         return dependencyTrail;
476     }
477 
478     public void setDependencyTrail( List<String> dependencyTrail )
479     {
480         this.dependencyTrail = dependencyTrail;
481     }
482 
483     public void setScope( String scope )
484     {
485         this.scope = scope;
486     }
487 
488     public VersionRange getVersionRange()
489     {
490         return versionRange;
491     }
492 
493     public void setVersionRange( VersionRange versionRange )
494     {
495         this.versionRange = versionRange;
496         selectVersionFromNewRangeIfAvailable();
497     }
498 
499     private void selectVersionFromNewRangeIfAvailable()
500     {
501         if ( ( versionRange != null ) && ( versionRange.getRecommendedVersion() != null ) )
502         {
503             selectVersion( versionRange.getRecommendedVersion().toString() );
504         }
505         else
506         {
507             version = null;
508             baseVersion = null;
509         }
510     }
511 
512     public void selectVersion( String version )
513     {
514         this.version = version;
515         setBaseVersionInternal( version );
516     }
517 
518     public void setGroupId( String groupId )
519     {
520         this.groupId = groupId;
521     }
522 
523     public void setArtifactId( String artifactId )
524     {
525         this.artifactId = artifactId;
526     }
527 
528     public boolean isSnapshot()
529     {
530         return getBaseVersion() != null
531             && ( getBaseVersion().endsWith( SNAPSHOT_VERSION ) || getBaseVersion().equals( LATEST_VERSION ) );
532     }
533 
534     public void setResolved( boolean resolved )
535     {
536         this.resolved = resolved;
537     }
538 
539     public boolean isResolved()
540     {
541         return resolved;
542     }
543 
544     public void setResolvedVersion( String version )
545     {
546         this.version = version;
547         // retain baseVersion
548     }
549 
550     public void setArtifactHandler( ArtifactHandler artifactHandler )
551     {
552         this.artifactHandler = artifactHandler;
553     }
554 
555     public void setRelease( boolean release )
556     {
557         this.release = release;
558     }
559 
560     public boolean isRelease()
561     {
562         return release;
563     }
564 
565     public List<ArtifactVersion> getAvailableVersions()
566     {
567         return availableVersions;
568     }
569 
570     public void setAvailableVersions( List<ArtifactVersion> availableVersions )
571     {
572         this.availableVersions = availableVersions;
573     }
574 
575     public boolean isOptional()
576     {
577         return optional;
578     }
579 
580     public ArtifactVersion getSelectedVersion()
581         throws OverConstrainedVersionException
582     {
583         return versionRange.getSelectedVersion( this );
584     }
585 
586     public boolean isSelectedVersionKnown()
587         throws OverConstrainedVersionException
588     {
589         return versionRange.isSelectedVersionKnown( this );
590     }
591 
592     public void setOptional( boolean optional )
593     {
594         this.optional = optional;
595     }
596 
597 }