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