View Javadoc
1   package org.eclipse.aether.util.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.Map;
24  import java.util.Objects;
25  
26  import static java.util.Objects.requireNonNull;
27  
28  import org.eclipse.aether.artifact.AbstractArtifact;
29  import org.eclipse.aether.artifact.Artifact;
30  
31  /**
32   * An artifact whose identity is derived from another artifact. <em>Note:</em> Instances of this class are immutable and
33   * the exposed mutators return new objects rather than changing the current instance.
34   */
35  public final class SubArtifact
36      extends AbstractArtifact
37  {
38  
39      private final Artifact mainArtifact;
40  
41      private final String classifier;
42  
43      private final String extension;
44  
45      private final File file;
46  
47      private final Map<String, String> properties;
48  
49      /**
50       * Creates a new sub artifact. The classifier and extension specified for this artifact may use the asterisk
51       * character "*" to refer to the corresponding property of the main artifact. For instance, the classifier
52       * "*-sources" can be used to refer to the source attachment of an artifact. Likewise, the extension "*.asc" can be
53       * used to refer to the GPG signature of an artifact.
54       * 
55       * @param mainArtifact The artifact from which to derive the identity, must not be {@code null}.
56       * @param classifier The classifier for this artifact, may be {@code null} if none.
57       * @param extension The extension for this artifact, may be {@code null} if none.
58       */
59      public SubArtifact( Artifact mainArtifact, String classifier, String extension )
60      {
61          this( mainArtifact, classifier, extension, (File) null );
62      }
63  
64      /**
65       * Creates a new sub artifact. The classifier and extension specified for this artifact may use the asterisk
66       * character "*" to refer to the corresponding property of the main artifact. For instance, the classifier
67       * "*-sources" can be used to refer to the source attachment of an artifact. Likewise, the extension "*.asc" can be
68       * used to refer to the GPG signature of an artifact.
69       * 
70       * @param mainArtifact The artifact from which to derive the identity, must not be {@code null}.
71       * @param classifier The classifier for this artifact, may be {@code null} if none.
72       * @param extension The extension for this artifact, may be {@code null} if none.
73       * @param file The file for this artifact, may be {@code null} if unresolved.
74       */
75      public SubArtifact( Artifact mainArtifact, String classifier, String extension, File file )
76      {
77          this( mainArtifact, classifier, extension, null, file );
78      }
79  
80      /**
81       * Creates a new sub artifact. The classifier and extension specified for this artifact may use the asterisk
82       * character "*" to refer to the corresponding property of the main artifact. For instance, the classifier
83       * "*-sources" can be used to refer to the source attachment of an artifact. Likewise, the extension "*.asc" can be
84       * used to refer to the GPG signature of an artifact.
85       * 
86       * @param mainArtifact The artifact from which to derive the identity, must not be {@code null}.
87       * @param classifier The classifier for this artifact, may be {@code null} if none.
88       * @param extension The extension for this artifact, may be {@code null} if none.
89       * @param properties The properties of the artifact, may be {@code null}.
90       */
91      public SubArtifact( Artifact mainArtifact, String classifier, String extension, Map<String, String> properties )
92      {
93          this( mainArtifact, classifier, extension, properties, null );
94      }
95  
96      /**
97       * Creates a new sub artifact. The classifier and extension specified for this artifact may use the asterisk
98       * character "*" to refer to the corresponding property of the main artifact. For instance, the classifier
99       * "*-sources" can be used to refer to the source attachment of an artifact. Likewise, the extension "*.asc" can be
100      * used to refer to the GPG signature of an artifact.
101      * 
102      * @param mainArtifact The artifact from which to derive the identity, must not be {@code null}.
103      * @param classifier The classifier for this artifact, may be {@code null} if none.
104      * @param extension The extension for this artifact, may be {@code null} if none.
105      * @param properties The properties of the artifact, may be {@code null}.
106      * @param file The file for this artifact, may be {@code null} if unresolved.
107      */
108     public SubArtifact( Artifact mainArtifact, String classifier, String extension, Map<String, String> properties,
109                         File file )
110     {
111         this.mainArtifact = requireNonNull( mainArtifact, "main artifact cannot be null" );
112         this.classifier = classifier;
113         this.extension = extension;
114         this.file = file;
115         this.properties = copyProperties( properties );
116     }
117 
118     private SubArtifact( Artifact mainArtifact, String classifier, String extension, File file,
119                          Map<String, String> properties )
120     {
121         // NOTE: This constructor assumes immutability of the provided properties, for internal use only
122         this.mainArtifact = mainArtifact;
123         this.classifier = classifier;
124         this.extension = extension;
125         this.file = file;
126         this.properties = properties;
127     }
128 
129     public String getGroupId()
130     {
131         return mainArtifact.getGroupId();
132     }
133 
134     public String getArtifactId()
135     {
136         return mainArtifact.getArtifactId();
137     }
138 
139     public String getVersion()
140     {
141         return mainArtifact.getVersion();
142     }
143 
144     public String getBaseVersion()
145     {
146         return mainArtifact.getBaseVersion();
147     }
148 
149     public boolean isSnapshot()
150     {
151         return mainArtifact.isSnapshot();
152     }
153 
154     public String getClassifier()
155     {
156         return expand( classifier, mainArtifact.getClassifier() );
157     }
158 
159     public String getExtension()
160     {
161         return expand( extension, mainArtifact.getExtension() );
162     }
163 
164     public File getFile()
165     {
166         return file;
167     }
168 
169     public Artifact setFile( File file )
170     {
171         if ( Objects.equals( this.file, file ) )
172         {
173             return this;
174         }
175         return new SubArtifact( mainArtifact, classifier, extension, file, properties );
176     }
177 
178     public Map<String, String> getProperties()
179     {
180         return properties;
181     }
182 
183     public Artifact setProperties( Map<String, String> properties )
184     {
185         if ( this.properties.equals( properties ) || ( properties == null && this.properties.isEmpty() ) )
186         {
187             return this;
188         }
189         return new SubArtifact( mainArtifact, classifier, extension, properties, file );
190     }
191 
192     private static String expand( String pattern, String replacement )
193     {
194         String result = "";
195         if ( pattern != null )
196         {
197             result = pattern.replace( "*", replacement );
198 
199             if ( replacement.isEmpty() )
200             {
201                 if ( pattern.startsWith( "*" ) )
202                 {
203                     int i = 0;
204                     for ( ; i < result.length(); i++ )
205                     {
206                         char c = result.charAt( i );
207                         if ( c != '-' && c != '.' )
208                         {
209                             break;
210                         }
211                     }
212                     result = result.substring( i );
213                 }
214                 if ( pattern.endsWith( "*" ) )
215                 {
216                     int i = result.length() - 1;
217                     for ( ; i >= 0; i-- )
218                     {
219                         char c = result.charAt( i );
220                         if ( c != '-' && c != '.' )
221                         {
222                             break;
223                         }
224                     }
225                     result = result.substring( 0, i + 1 );
226                 }
227             }
228         }
229         return result;
230     }
231 
232 }