1 package org.apache.maven.archiva.repository.layout;
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
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
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.maven.archiva.common.utils.VersionUtil;
26 * RepositoryLayoutUtils - utility methods common for most BidirectionalRepositoryLayout implementation.
28 * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
31 public class RepositoryLayoutUtils
34 * Complex 2+ part extensions.
35 * Do not include initial "." character in extension names here.
37 private static final String ComplexExtensions[] = new String[] { "tar.gz", "tar.bz2" };
40 * Filename Parsing Mode - Artifact Id.
42 private static final int ARTIFACTID = 1;
45 * Filename Parsing Mode - Version.
47 private static final int VERSION = 2;
50 * Filename Parsing Mode - Classifier.
52 private static final int CLASSIFIER = 3;
55 * Split the provided filename into 4 String parts. Simply delegate to
56 * splitFilename( filename, possibleArtifactId, possibleVersion ) with no possibleVersion
59 * @param filename the filename to split.
60 * @param possibleArtifactId the optional artifactId to aide in splitting the filename.
61 * (null to allow algorithm to calculate one)
62 * @return the parts of the filename.
63 * @throws LayoutException
65 public static FilenameParts splitFilename( String filename, String possibleArtifactId ) throws LayoutException
67 return splitFilename( filename, possibleArtifactId, null );
71 * Split the provided filename into 4 String parts.
74 * String part[] = splitFilename( filename );
75 * artifactId = part[0];
77 * classifier = part[2];
78 * extension = part[3];
81 * @param filename the filename to split.
82 * @param possibleArtifactId the optional artifactId to aide in splitting the filename.
83 * (null to allow algorithm to calculate one)
84 * @param possibleVersion the optional version to aide in splitting the filename.
85 * (null to allow algorithm to calculate one)
86 * @return the parts of the filename.
87 * @throws LayoutException
89 public static FilenameParts splitFilename( String filename, String possibleArtifactId,
90 String possibleVersion ) throws LayoutException
92 if ( StringUtils.isBlank( filename ) )
94 throw new IllegalArgumentException( "Unable to split blank filename." );
97 String filestring = filename.trim();
99 FilenameParts parts = new FilenameParts();
100 // I like working backwards.
102 // Find the extension.
104 // Work on multipart extensions first.
105 boolean found = false;
107 String lowercaseFilename = filestring.toLowerCase();
108 for ( int i = 0; i < ComplexExtensions.length && !found; i++ )
110 if ( lowercaseFilename.endsWith( "." + ComplexExtensions[i] ) )
112 parts.extension = ComplexExtensions[i];
113 filestring = filestring.substring( 0, filestring.length() - ComplexExtensions[i].length() - 1 );
120 // Default to 1 part extension.
122 int index = filestring.lastIndexOf( '.' );
125 // Bad Filename - No Extension
126 throw new LayoutException( "Unable to determine extension from filename " + filename );
128 parts.extension = filestring.substring( index + 1 );
129 filestring = filestring.substring( 0, index );
132 // Work on version string.
133 int mode = ARTIFACTID;
135 if ( startsWith( filename, possibleArtifactId ) )
137 parts.artifactId = possibleArtifactId;
138 filestring = filestring.substring( possibleArtifactId.length() + 1 );
142 if ( startsWith( filestring, possibleVersion ) )
144 if ( filestring.length() > possibleVersion.length() )
146 filestring = filestring.substring( possibleVersion.length() );
152 parts.version = possibleVersion;
156 String fileParts[] = StringUtils.split( filestring, '-' );
158 int versionStart = -1;
160 for ( int i = 0; i < fileParts.length; i++ )
162 String part = fileParts[i];
164 if ( VersionUtil.isSimpleVersionKeyword( part ) )
166 // It is a potential version part.
167 if ( versionStart < 0 )
176 if ( versionStart < 0 && parts.version == null )
178 // Assume rest of string is the version Id.
180 if ( fileParts.length > 0 )
183 versionEnd = fileParts.length;
187 throw new LayoutException( "Unable to determine version from filename " + filename );
191 // Gather up the ArtifactID - Version - Classifier pieces found.
193 for ( int i = 0; i < fileParts.length; i++ )
195 String part = fileParts[i];
197 if ( ( mode == ARTIFACTID ) && ( i >= versionStart ) )
199 if ( StringUtils.isBlank( parts.artifactId ) )
201 throw new LayoutException( "No Artifact Id detected." );
209 parts.appendArtifactId( part );
212 parts.appendVersion( part );
215 parts.appendClassifier( part );
219 if ( i >= versionEnd )
229 * Check if the string starts with the proposed token, with no more char
230 * expeect the '-' separator.
231 * @param string string to test
232 * @param possible proposed startOf
233 * @return true if the possible matches
235 private static boolean startsWith( String string, String possible )
237 if (possible == null)
241 int length = possible.length();
242 return string.startsWith( possible ) && ( string.length() == length || string.charAt( length ) == '-' );