/******************************************************************************* * Copyright (c) 2010, 2013 Sonatype, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Sonatype, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.aether.artifact; import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A simple artifact. Note: Instances of this class are immutable and the exposed mutators return new objects * rather than changing the current instance. */ public final class DefaultArtifact extends AbstractArtifact { private final String groupId; private final String artifactId; private final String version; private final String classifier; private final String extension; private final File file; private final Map properties; /** * Creates a new artifact with the specified coordinates. If not specified in the artifact coordinates, the * artifact's extension defaults to {@code jar} and classifier to an empty string. * * @param coords The artifact coordinates in the format * {@code :[:[:]]:}, must not be {@code null}. */ public DefaultArtifact( String coords ) { this( coords, Collections. emptyMap() ); } /** * Creates a new artifact with the specified coordinates and properties. If not specified in the artifact * coordinates, the artifact's extension defaults to {@code jar} and classifier to an empty string. * * @param coords The artifact coordinates in the format * {@code :[:[:]]:}, must not be {@code null}. * @param properties The artifact properties, may be {@code null}. */ public DefaultArtifact( String coords, Map properties ) { Pattern p = Pattern.compile( "([^: ]+):([^: ]+)(:([^: ]*)(:([^: ]+))?)?:([^: ]+)" ); Matcher m = p.matcher( coords ); if ( !m.matches() ) { throw new IllegalArgumentException( "Bad artifact coordinates " + coords + ", expected format is :[:[:]]:" ); } groupId = m.group( 1 ); artifactId = m.group( 2 ); extension = get( m.group( 4 ), "jar" ); classifier = get( m.group( 6 ), "" ); version = m.group( 7 ); file = null; this.properties = copyProperties( properties ); } private static String get( String value, String defaultValue ) { return ( value == null || value.length() <= 0 ) ? defaultValue : value; } /** * Creates a new artifact with the specified coordinates and no classifier. Passing {@code null} for any of the * coordinates is equivalent to specifying an empty string. * * @param groupId The group identifier of the artifact, may be {@code null}. * @param artifactId The artifact identifier of the artifact, may be {@code null}. * @param extension The file extension of the artifact, may be {@code null}. * @param version The version of the artifact, may be {@code null}. */ public DefaultArtifact( String groupId, String artifactId, String extension, String version ) { this( groupId, artifactId, "", extension, version ); } /** * Creates a new artifact with the specified coordinates. Passing {@code null} for any of the coordinates is * equivalent to specifying an empty string. * * @param groupId The group identifier of the artifact, may be {@code null}. * @param artifactId The artifact identifier of the artifact, may be {@code null}. * @param classifier The classifier of the artifact, may be {@code null}. * @param extension The file extension of the artifact, may be {@code null}. * @param version The version of the artifact, may be {@code null}. */ public DefaultArtifact( String groupId, String artifactId, String classifier, String extension, String version ) { this( groupId, artifactId, classifier, extension, version, null, (File) null ); } /** * Creates a new artifact with the specified coordinates. Passing {@code null} for any of the coordinates is * equivalent to specifying an empty string. The optional artifact type provided to this constructor will be used to * determine the artifact's classifier and file extension if the corresponding arguments for this constructor are * {@code null}. * * @param groupId The group identifier of the artifact, may be {@code null}. * @param artifactId The artifact identifier of the artifact, may be {@code null}. * @param classifier The classifier of the artifact, may be {@code null}. * @param extension The file extension of the artifact, may be {@code null}. * @param version The version of the artifact, may be {@code null}. * @param type The artifact type from which to query classifier, file extension and properties, may be {@code null}. */ public DefaultArtifact( String groupId, String artifactId, String classifier, String extension, String version, ArtifactType type ) { this( groupId, artifactId, classifier, extension, version, null, type ); } /** * Creates a new artifact with the specified coordinates and properties. Passing {@code null} for any of the * coordinates is equivalent to specifying an empty string. The optional artifact type provided to this constructor * will be used to determine the artifact's classifier and file extension if the corresponding arguments for this * constructor are {@code null}. If the artifact type specifies properties, those will get merged with the * properties passed directly into the constructor, with the latter properties taking precedence. * * @param groupId The group identifier of the artifact, may be {@code null}. * @param artifactId The artifact identifier of the artifact, may be {@code null}. * @param classifier The classifier of the artifact, may be {@code null}. * @param extension The file extension of the artifact, may be {@code null}. * @param version The version of the artifact, may be {@code null}. * @param properties The properties of the artifact, may be {@code null} if none. * @param type The artifact type from which to query classifier, file extension and properties, may be {@code null}. */ public DefaultArtifact( String groupId, String artifactId, String classifier, String extension, String version, Map properties, ArtifactType type ) { this.groupId = emptify( groupId ); this.artifactId = emptify( artifactId ); if ( classifier != null || type == null ) { this.classifier = emptify( classifier ); } else { this.classifier = emptify( type.getClassifier() ); } if ( extension != null || type == null ) { this.extension = emptify( extension ); } else { this.extension = emptify( type.getExtension() ); } this.version = emptify( version ); this.file = null; this.properties = merge( properties, ( type != null ) ? type.getProperties() : null ); } private static Map merge( Map dominant, Map recessive ) { Map properties; if ( ( dominant == null || dominant.isEmpty() ) && ( recessive == null || recessive.isEmpty() ) ) { properties = Collections.emptyMap(); } else { properties = new HashMap(); if ( recessive != null ) { properties.putAll( recessive ); } if ( dominant != null ) { properties.putAll( dominant ); } properties = Collections.unmodifiableMap( properties ); } return properties; } /** * Creates a new artifact with the specified coordinates, properties and file. Passing {@code null} for any of the * coordinates is equivalent to specifying an empty string. * * @param groupId The group identifier of the artifact, may be {@code null}. * @param artifactId The artifact identifier of the artifact, may be {@code null}. * @param classifier The classifier of the artifact, may be {@code null}. * @param extension The file extension of the artifact, may be {@code null}. * @param version The version of the artifact, may be {@code null}. * @param properties The properties of the artifact, may be {@code null} if none. * @param file The resolved file of the artifact, may be {@code null}. */ public DefaultArtifact( String groupId, String artifactId, String classifier, String extension, String version, Map properties, File file ) { this.groupId = emptify( groupId ); this.artifactId = emptify( artifactId ); this.classifier = emptify( classifier ); this.extension = emptify( extension ); this.version = emptify( version ); this.file = file; this.properties = copyProperties( properties ); } DefaultArtifact( String groupId, String artifactId, String classifier, String extension, String version, File file, Map properties ) { // NOTE: This constructor assumes immutability of the provided properties, for internal use only this.groupId = emptify( groupId ); this.artifactId = emptify( artifactId ); this.classifier = emptify( classifier ); this.extension = emptify( extension ); this.version = emptify( version ); this.file = file; this.properties = properties; } private static String emptify( String str ) { return ( str == null ) ? "" : str; } public String getGroupId() { return groupId; } public String getArtifactId() { return artifactId; } public String getVersion() { return version; } public String getClassifier() { return classifier; } public String getExtension() { return extension; } public File getFile() { return file; } public Map getProperties() { return properties; } }