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