View Javadoc
1   package org.eclipse.aether.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.Collections;
24  import java.util.HashMap;
25  import java.util.Map;
26  import java.util.regex.Matcher;
27  import java.util.regex.Pattern;
28  
29  /**
30   * A skeleton class for artifacts.
31   */
32  public abstract class AbstractArtifact
33      implements Artifact
34  {
35  
36      private static final String SNAPSHOT = "SNAPSHOT";
37  
38      private static final Pattern SNAPSHOT_TIMESTAMP = Pattern.compile( "^(.*-)?([0-9]{8}\\.[0-9]{6}-[0-9]+)$" );
39  
40      public boolean isSnapshot()
41      {
42          return isSnapshot( getVersion() );
43      }
44  
45      private static boolean isSnapshot( String version )
46      {
47          return version.endsWith( SNAPSHOT ) || SNAPSHOT_TIMESTAMP.matcher( version ).matches();
48      }
49  
50      public String getBaseVersion()
51      {
52          return toBaseVersion( getVersion() );
53      }
54  
55      private static String toBaseVersion( String version )
56      {
57          String baseVersion;
58  
59          if ( version == null )
60          {
61              baseVersion = version;
62          }
63          else if ( version.startsWith( "[" ) || version.startsWith( "(" ) )
64          {
65              baseVersion = version;
66          }
67          else
68          {
69              Matcher m = SNAPSHOT_TIMESTAMP.matcher( version );
70              if ( m.matches() )
71              {
72                  if ( m.group( 1 ) != null )
73                  {
74                      baseVersion = m.group( 1 ) + SNAPSHOT;
75                  }
76                  else
77                  {
78                      baseVersion = SNAPSHOT;
79                  }
80              }
81              else
82              {
83                  baseVersion = version;
84              }
85          }
86  
87          return baseVersion;
88      }
89  
90      /**
91       * Creates a new artifact with the specified coordinates, properties and file.
92       * 
93       * @param version The version of the artifact, may be {@code null}.
94       * @param properties The properties of the artifact, may be {@code null} if none. The method may assume immutability
95       *            of the supplied map, i.e. need not copy it.
96       * @param file The resolved file of the artifact, may be {@code null}.
97       * @return The new artifact instance, never {@code null}.
98       */
99      private Artifact newInstance( String version, Map<String, String> properties, File file )
100     {
101         return new DefaultArtifact( getGroupId(), getArtifactId(), getClassifier(), getExtension(), version, file,
102                                     properties );
103     }
104 
105     public Artifact setVersion( String version )
106     {
107         String current = getVersion();
108         if ( current.equals( version ) || ( version == null && current.length() <= 0 ) )
109         {
110             return this;
111         }
112         return newInstance( version, getProperties(), getFile() );
113     }
114 
115     public Artifact setFile( File file )
116     {
117         File current = getFile();
118         if ( ( current == null ) ? file == null : current.equals( file ) )
119         {
120             return this;
121         }
122         return newInstance( getVersion(), getProperties(), file );
123     }
124 
125     public Artifact setProperties( Map<String, String> properties )
126     {
127         Map<String, String> current = getProperties();
128         if ( current.equals( properties ) || ( properties == null && current.isEmpty() ) )
129         {
130             return this;
131         }
132         return newInstance( getVersion(), copyProperties( properties ), getFile() );
133     }
134 
135     public String getProperty( String key, String defaultValue )
136     {
137         String value = getProperties().get( key );
138         return ( value != null ) ? value : defaultValue;
139     }
140 
141     /**
142      * Copies the specified artifact properties. This utility method should be used when creating new artifact instances
143      * with caller-supplied properties.
144      * 
145      * @param properties The properties to copy, may be {@code null}.
146      * @return The copied and read-only properties, never {@code null}.
147      */
148     protected static Map<String, String> copyProperties( Map<String, String> properties )
149     {
150         if ( properties != null && !properties.isEmpty() )
151         {
152             return Collections.unmodifiableMap( new HashMap<String, String>( properties ) );
153         }
154         else
155         {
156             return Collections.emptyMap();
157         }
158     }
159 
160     @Override
161     public String toString()
162     {
163         StringBuilder buffer = new StringBuilder( 128 );
164         buffer.append( getGroupId() );
165         buffer.append( ':' ).append( getArtifactId() );
166         buffer.append( ':' ).append( getExtension() );
167         if ( getClassifier().length() > 0 )
168         {
169             buffer.append( ':' ).append( getClassifier() );
170         }
171         buffer.append( ':' ).append( getVersion() );
172         return buffer.toString();
173     }
174 
175     /**
176      * Compares this artifact with the specified object.
177      * 
178      * @param obj The object to compare this artifact against, may be {@code null}.
179      * @return {@code true} if and only if the specified object is another {@link Artifact} with equal coordinates,
180      *         properties and file, {@code false} otherwise.
181      */
182     @Override
183     public boolean equals( Object obj )
184     {
185         if ( obj == this )
186         {
187             return true;
188         }
189         else if ( !( obj instanceof Artifact ) )
190         {
191             return false;
192         }
193 
194         Artifact that = (Artifact) obj;
195 
196         return getArtifactId().equals( that.getArtifactId() ) && getGroupId().equals( that.getGroupId() )
197             && getVersion().equals( that.getVersion() ) && getExtension().equals( that.getExtension() )
198             && getClassifier().equals( that.getClassifier() ) && eq( getFile(), that.getFile() )
199             && getProperties().equals( that.getProperties() );
200     }
201 
202     private static <T> boolean eq( T s1, T s2 )
203     {
204         return s1 != null ? s1.equals( s2 ) : s2 == null;
205     }
206 
207     /**
208      * Returns a hash code for this artifact.
209      * 
210      * @return A hash code for the artifact.
211      */
212     @Override
213     public int hashCode()
214     {
215         int hash = 17;
216         hash = hash * 31 + getGroupId().hashCode();
217         hash = hash * 31 + getArtifactId().hashCode();
218         hash = hash * 31 + getExtension().hashCode();
219         hash = hash * 31 + getClassifier().hashCode();
220         hash = hash * 31 + getVersion().hashCode();
221         hash = hash * 31 + hash( getFile() );
222         return hash;
223     }
224 
225     private static int hash( Object obj )
226     {
227         return ( obj != null ) ? obj.hashCode() : 0;
228     }
229 
230 }