]> source.dussan.org Git - archiva.git/blob
00070c6615b4443e519d0d25d12015098617c0db
[archiva.git] /
1 package org.apache.maven.archiva.repository.layout;
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 org.apache.commons.lang.StringUtils;
23 import org.apache.maven.archiva.common.utils.VersionUtil;
24
25 /**
26  * RepositoryLayoutUtils - utility methods common for most BidirectionalRepositoryLayout implementation. 
27  *
28  * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
29  * @version $Id$
30  */
31 public class RepositoryLayoutUtils
32 {
33     /**
34      * Complex 2+ part extensions.
35      * Do not include initial "." character in extension names here.
36      */
37     private static final String ComplexExtensions[] = new String[] { "tar.gz", "tar.bz2" };
38
39     /**
40      * Filename Parsing Mode - Artifact Id.
41      */
42     private static final int ARTIFACTID = 1;
43
44     /**
45      * Filename Parsing Mode - Version.
46      */
47     private static final int VERSION = 2;
48
49     /**
50      * Filename Parsing Mode - Classifier.
51      */
52     private static final int CLASSIFIER = 3;
53
54     /**
55      * Split the provided filename into 4 String parts. Simply delegate to 
56      * splitFilename( filename, possibleArtifactId, possibleVersion ) with no possibleVersion
57      * proposal.
58      *
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
64      */
65     public static FilenameParts splitFilename( String filename, String possibleArtifactId ) throws LayoutException
66     {
67         return splitFilename( filename, possibleArtifactId, null );
68     }
69
70     /**
71      * Split the provided filename into 4 String parts.
72      *
73      * <pre>
74      * String part[] = splitFilename( filename );
75      * artifactId = part[0];
76      * version = part[1];
77      * classifier = part[2];
78      * extension = part[3];
79      * </pre>
80      *
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
88      */
89     public static FilenameParts splitFilename( String filename, String possibleArtifactId,
90                                                String possibleVersion ) throws LayoutException
91     {
92         if ( StringUtils.isBlank( filename ) )
93         {
94             throw new IllegalArgumentException( "Unable to split blank filename." );
95         }
96
97         String filestring = filename.trim();
98
99         FilenameParts parts = new FilenameParts();
100         // I like working backwards.
101
102         // Find the extension.
103
104         // Work on multipart extensions first.
105         boolean found = false;
106
107         String lowercaseFilename = filestring.toLowerCase();
108         for ( int i = 0; i < ComplexExtensions.length && !found; i++ )
109         {
110             if ( lowercaseFilename.endsWith( "." + ComplexExtensions[i] ) )
111             {
112                 parts.extension = ComplexExtensions[i];
113                 filestring = filestring.substring( 0, filestring.length() - ComplexExtensions[i].length() - 1 );
114                 found = true;
115             }
116         }
117
118         if ( !found )
119         {
120             // Default to 1 part extension.
121
122             int index = filestring.lastIndexOf( '.' );
123             if ( index <= 0 )
124             {
125                 // Bad Filename - No Extension
126                 throw new LayoutException( "Unable to determine extension from filename " + filename );
127             }
128             parts.extension = filestring.substring( index + 1 );
129             filestring = filestring.substring( 0, index );
130         }
131
132         // Work on version string.
133         int mode = ARTIFACTID;
134
135         if ( startsWith( filename, possibleArtifactId ) )
136         {
137             parts.artifactId = possibleArtifactId;
138             filestring = filestring.substring( possibleArtifactId.length() + 1 );
139             mode = VERSION;
140         }
141
142         if ( startsWith( filestring, possibleVersion ) )
143         {
144             if ( filestring.length() > possibleVersion.length() )
145             {
146                 filestring = filestring.substring( possibleVersion.length() );
147             }
148             else
149             {
150                 filestring = "";
151             }
152             parts.version = possibleVersion;
153             mode = CLASSIFIER;
154         }
155
156         String fileParts[] = StringUtils.split( filestring, '-' );
157
158         int versionStart = -1;
159         int versionEnd = -1;
160         for ( int i = 0; i < fileParts.length; i++ )
161         {
162             String part = fileParts[i];
163
164             if ( VersionUtil.isSimpleVersionKeyword( part ) )
165             {
166                 // It is a potential version part.
167                 if ( versionStart < 0 )
168                 {
169                     versionStart = i;
170                 }
171
172                 versionEnd = i;
173             }
174         }
175
176         if ( versionStart < 0 && parts.version == null )
177         {
178             // Assume rest of string is the version Id.
179
180             if ( fileParts.length > 0 )
181             {
182                 versionStart = 0;
183                 versionEnd = fileParts.length;
184             }
185             else
186             {
187                 throw new LayoutException( "Unable to determine version from filename " + filename );
188             }
189         }
190
191         // Gather up the ArtifactID - Version - Classifier pieces found.
192
193         for ( int i = 0; i < fileParts.length; i++ )
194         {
195             String part = fileParts[i];
196
197             if ( ( mode == ARTIFACTID ) && ( i >= versionStart ) )
198             {
199                 if ( StringUtils.isBlank( parts.artifactId ) )
200                 {
201                     throw new LayoutException( "No Artifact Id detected." );
202                 }
203                 mode = VERSION;
204             }
205
206             switch ( mode )
207             {
208                 case ARTIFACTID:
209                     parts.appendArtifactId( part );
210                     break;
211                 case VERSION:
212                     parts.appendVersion( part );
213                     break;
214                 case CLASSIFIER:
215                     parts.appendClassifier( part );
216                     break;
217             }
218
219             if ( i >= versionEnd )
220             {
221                 mode = CLASSIFIER;
222             }
223         }
224
225         return parts;
226     }
227
228     /**
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
234      */
235     private static boolean startsWith( String string, String possible )
236     {
237         if (possible == null)
238         {
239             return false;
240         }
241         int length = possible.length();
242         return string.startsWith( possible ) && ( string.length() == length || string.charAt( length ) == '-' );
243     }
244 }