001package org.eclipse.aether.util.artifact; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.File; 023import java.util.Map; 024import static java.util.Objects.requireNonNull; 025 026import org.eclipse.aether.artifact.AbstractArtifact; 027import org.eclipse.aether.artifact.Artifact; 028 029/** 030 * An artifact whose identity is derived from another artifact. <em>Note:</em> Instances of this class are immutable and 031 * the exposed mutators return new objects rather than changing the current instance. 032 */ 033public final class SubArtifact 034 extends AbstractArtifact 035{ 036 037 private final Artifact mainArtifact; 038 039 private final String classifier; 040 041 private final String extension; 042 043 private final File file; 044 045 private final Map<String, String> properties; 046 047 /** 048 * Creates a new sub artifact. The classifier and extension specified for this artifact may use the asterisk 049 * character "*" to refer to the corresponding property of the main artifact. For instance, the classifier 050 * "*-sources" can be used to refer to the source attachment of an artifact. Likewise, the extension "*.asc" can be 051 * used to refer to the GPG signature of an artifact. 052 * 053 * @param mainArtifact The artifact from which to derive the identity, must not be {@code null}. 054 * @param classifier The classifier for this artifact, may be {@code null} if none. 055 * @param extension The extension for this artifact, may be {@code null} if none. 056 */ 057 public SubArtifact( Artifact mainArtifact, String classifier, String extension ) 058 { 059 this( mainArtifact, classifier, extension, (File) null ); 060 } 061 062 /** 063 * Creates a new sub artifact. The classifier and extension specified for this artifact may use the asterisk 064 * character "*" to refer to the corresponding property of the main artifact. For instance, the classifier 065 * "*-sources" can be used to refer to the source attachment of an artifact. Likewise, the extension "*.asc" can be 066 * used to refer to the GPG signature of an artifact. 067 * 068 * @param mainArtifact The artifact from which to derive the identity, must not be {@code null}. 069 * @param classifier The classifier for this artifact, may be {@code null} if none. 070 * @param extension The extension for this artifact, may be {@code null} if none. 071 * @param file The file for this artifact, may be {@code null} if unresolved. 072 */ 073 public SubArtifact( Artifact mainArtifact, String classifier, String extension, File file ) 074 { 075 this( mainArtifact, classifier, extension, null, file ); 076 } 077 078 /** 079 * Creates a new sub artifact. The classifier and extension specified for this artifact may use the asterisk 080 * character "*" to refer to the corresponding property of the main artifact. For instance, the classifier 081 * "*-sources" can be used to refer to the source attachment of an artifact. Likewise, the extension "*.asc" can be 082 * used to refer to the GPG signature of an artifact. 083 * 084 * @param mainArtifact The artifact from which to derive the identity, must not be {@code null}. 085 * @param classifier The classifier for this artifact, may be {@code null} if none. 086 * @param extension The extension for this artifact, may be {@code null} if none. 087 * @param properties The properties of the artifact, may be {@code null}. 088 */ 089 public SubArtifact( Artifact mainArtifact, String classifier, String extension, Map<String, String> properties ) 090 { 091 this( mainArtifact, classifier, extension, properties, null ); 092 } 093 094 /** 095 * Creates a new sub artifact. The classifier and extension specified for this artifact may use the asterisk 096 * character "*" to refer to the corresponding property of the main artifact. For instance, the classifier 097 * "*-sources" can be used to refer to the source attachment of an artifact. Likewise, the extension "*.asc" can be 098 * used to refer to the GPG signature of an artifact. 099 * 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}