1 package org.apache.archiva.repository.maven.content;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
21 import org.apache.archiva.common.utils.VersionUtil;
22 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
23 import org.apache.archiva.model.ArchivaRepositoryMetadata;
24 import org.apache.archiva.model.SnapshotVersion;
25 import org.apache.archiva.repository.content.ItemSelector;
26 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
27 import org.apache.archiva.repository.storage.StorageAsset;
28 import org.apache.commons.lang3.StringUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31 import org.springframework.stereotype.Service;
33 import javax.inject.Inject;
34 import javax.inject.Named;
35 import java.util.LinkedList;
38 * Helper class that contains certain maven specific methods
40 @Service( "MavenContentHelper" )
41 public class MavenContentHelper
44 private static final Logger log = LoggerFactory.getLogger( MavenContentHelper.class );
47 @Named( "metadataReader#maven" )
48 MavenMetadataReader metadataReader;
50 public static final String METADATA_FILENAME = "maven-metadata.xml";
52 public MavenContentHelper() {
57 * Returns the namespace string for a given path in the repository
59 * @param namespacePath the path to the namespace in the directory
60 * @return the namespace string that matches the given path.
62 public static String getNamespaceFromNamespacePath( final StorageAsset namespacePath) {
63 LinkedList<String> names = new LinkedList<>( );
64 StorageAsset current = namespacePath;
65 while (current.hasParent()) {
66 names.addFirst( current.getName() );
68 return String.join( ".", names );
72 * Returns the artifact version for the given artifact directory and the item selector
74 public String getArtifactVersion( StorageAsset artifactDir, ItemSelector selector) {
75 if (selector.hasArtifactVersion()) {
76 return selector.getArtifactVersion();
77 } else if (selector.hasVersion()) {
78 if ( VersionUtil.isGenericSnapshot( selector.getVersion() ) ) {
79 return getLatestArtifactSnapshotVersion( artifactDir, selector.getVersion( ) );
81 return selector.getVersion( );
84 throw new IllegalArgumentException( "No version set on the selector " );
91 * Returns the latest snapshot version that is referenced by the metadata file.
93 * @param artifactDir the directory of the artifact
94 * @param snapshotVersion the generic snapshot version (must end with '-SNAPSHOT')
95 * @return the real version from the metadata
97 public String getLatestArtifactSnapshotVersion( StorageAsset artifactDir, String snapshotVersion) {
98 final StorageAsset metadataFile = artifactDir.resolve( METADATA_FILENAME );
99 StringBuilder version = new StringBuilder( );
102 ArchivaRepositoryMetadata metadata = metadataReader.read( metadataFile );
104 // re-adjust to timestamp if present, otherwise retain the original -SNAPSHOT filename
105 SnapshotVersion metadataVersion = metadata.getSnapshotVersion( );
106 if ( metadataVersion != null )
108 version.append( snapshotVersion, 0, snapshotVersion.length( ) - 8 ); // remove SNAPSHOT from end
109 version.append( metadataVersion.getTimestamp( )).append("-").append( metadataVersion.getBuildNumber( ) );
111 return version.toString( );
113 catch ( RepositoryMetadataException e )
115 // unable to parse metadata - LOGGER it, and continue with the version as the original SNAPSHOT version
116 log.warn( "Invalid metadata: {} - {}", metadataFile, e.getMessage( ) );
117 return snapshotVersion;
123 * Returns a artifact filename that corresponds to the given data.
124 * @param selector the selector data
125 * @param artifactVersion the artifactVersion
126 * @param classifier the artifact classifier
127 * @param extension the file extension
129 static String getArtifactFileName( ItemSelector selector, String artifactVersion,
130 String classifier, String extension )
132 StringBuilder fileName = new StringBuilder( selector.getArtifactId( ) ).append( "-" );
133 fileName.append( artifactVersion );
134 if ( !StringUtils.isEmpty( classifier ) )
136 fileName.append( "-" ).append( classifier );
138 fileName.append( "." ).append( extension );
139 return fileName.toString( );
143 * Returns the classifier for a given selector. If the selector has no classifier, but
144 * a type set. The classifier is generated from the type.
146 * @param selector the artifact selector
147 * @return the classifier or empty string if no classifier was found
149 static String getClassifier( ItemSelector selector )
151 if ( selector.hasClassifier( ) )
153 return selector.getClassifier( );
155 else if ( selector.hasType( ) )
157 return getClassifierFromType( selector.getType( ) );
166 * Returns a classifier for a given type. It returns only classifier for the maven default types
169 * @param type the type of the artifact
170 * @return the classifier if one was found, otherwise a empty string
172 static String getClassifierFromType( final String type )
174 if ( "pom".equalsIgnoreCase( type ) || "jar".equalsIgnoreCase( type )
175 || "maven-plugin".equalsIgnoreCase( type )
176 || "ejb".equalsIgnoreCase( type )
177 || "ear".equalsIgnoreCase( type )
178 || "war".equalsIgnoreCase( type )
179 || "rar".equalsIgnoreCase( type )
181 if ( "test-jar".equalsIgnoreCase( type ) )
185 else if ( "ejb-client".equalsIgnoreCase( type ) )
189 else if ( "java-source".equalsIgnoreCase( type ) )
193 else if ( "javadoc".equalsIgnoreCase( type ) )
204 * Returns the type that matches the given classifier and extension
206 * @param classifierArg the classifier
207 * @param extensionArg the extension
208 * @return the type that matches the combination of classifier and extension
210 static String getTypeFromClassifierAndExtension( String classifierArg, String extensionArg )
212 String extension = extensionArg.toLowerCase( ).trim( );
213 String classifier = classifierArg.toLowerCase( ).trim( );
214 if ( StringUtils.isEmpty( extension ) )
218 else if ( StringUtils.isEmpty( classifier ) )
222 else if ( classifier.equals( "tests" ) && extension.equals( "jar" ) )
226 else if ( classifier.equals( "client" ) && extension.equals( "jar" ) )
230 else if ( classifier.equals( "source" ) && extension.equals( "jar" ) )
232 return "java-source";
234 else if ( classifier.equals( "javadoc" ) && extension.equals( "jar" ) )
245 * If the selector defines a type and no extension, the extension can be derived from
248 * @param selector the item selector
249 * @return the extension that matches the type or the default extension "jar" if the type is not known
251 static String getArtifactExtension( ItemSelector selector )
253 if ( selector.hasExtension( ) )
255 return selector.getExtension( );
257 else if ( selector.hasType( ) )
259 String type = selector.getType( ).toLowerCase( );
260 if ( "test-jar".equals( type ) )
264 else if ( "ejb-client".equals( type ) )
268 else if ( "java-source".equals( type ) )
272 else if ( "javadoc".equals( type ) )