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