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 }