]> source.dussan.org Git - archiva.git/blob
b41cef5538c757269f91e740048e19b64818e9b9
[archiva.git] /
1 package org.apache.maven.repository.discovery;
2
3 /*
4  * Copyright 2005-2006 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 import org.apache.maven.artifact.Artifact;
20 import org.apache.maven.artifact.factory.ArtifactFactory;
21
22 import java.io.File;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Iterator;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.StringTokenizer;
29
30 /**
31  * Artifact discoverer for the legacy repository layout (Maven 1.x).
32  *
33  * @author John Casey
34  * @author Brett Porter
35  */
36 public class LegacyArtifactDiscoverer
37     extends AbstractArtifactDiscoverer
38 {
39     private ArtifactFactory artifactFactory;
40
41     public List discoverArtifacts( File repositoryBase, String blacklistedPatterns, boolean includeSnapshots )
42     {
43         List artifacts = new ArrayList();
44
45         String[] artifactPaths = scanForArtifactPaths( repositoryBase, blacklistedPatterns );
46
47         for ( int i = 0; i < artifactPaths.length; i++ )
48         {
49             String path = artifactPaths[i];
50
51             Artifact artifact = buildArtifact( path );
52             if ( artifact != null )
53             {
54                 if ( includeSnapshots || !artifact.isSnapshot() )
55                 {
56                     artifacts.add( artifact );
57                 }
58             }
59         }
60
61         return artifacts;
62     }
63
64     private Artifact buildArtifact( String path )
65     {
66         StringTokenizer tokens = new StringTokenizer( path, "/\\" );
67
68         int numberOfTokens = tokens.countTokens();
69
70         if ( numberOfTokens != 3 )
71         {
72             addKickedOutPath( path );
73
74             return null;
75         }
76
77         String groupId = tokens.nextToken();
78
79         String type = tokens.nextToken();
80
81         if ( !type.endsWith( "s" ) )
82         {
83             addKickedOutPath( path );
84
85             return null;
86         }
87         type = type.substring( 0, type.length() - 1 );
88
89         // contains artifactId, version, classifier, and extension.
90         String avceGlob = tokens.nextToken();
91
92         LinkedList avceTokenList = new LinkedList();
93
94         StringTokenizer avceTokenizer = new StringTokenizer( avceGlob, "-" );
95         while ( avceTokenizer.hasMoreTokens() )
96         {
97             avceTokenList.addLast( avceTokenizer.nextToken() );
98         }
99
100         String lastAvceToken = (String) avceTokenList.removeLast();
101
102         // TODO: share with other discoverer, use artifact handlers instead
103         if ( lastAvceToken.endsWith( ".tar.gz" ) )
104         {
105             type = "distribution-tgz";
106
107             lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".tar.gz".length() );
108
109             avceTokenList.addLast( lastAvceToken );
110         }
111         else if ( lastAvceToken.endsWith( "sources.jar" ) )
112         {
113             type = "java-source";
114
115             lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".jar".length() );
116
117             avceTokenList.addLast( lastAvceToken );
118         }
119         else if ( lastAvceToken.endsWith( ".zip" ) )
120         {
121             type = "distribution-zip";
122
123             lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".zip".length() );
124
125             avceTokenList.addLast( lastAvceToken );
126         }
127         else
128         {
129             int extPos = lastAvceToken.lastIndexOf( '.' );
130
131             if ( extPos > 0 )
132             {
133                 String ext = lastAvceToken.substring( extPos + 1 );
134                 if ( type.equals( ext ) )
135                 {
136                     lastAvceToken = lastAvceToken.substring( 0, extPos );
137
138                     avceTokenList.addLast( lastAvceToken );
139                 }
140                 else
141                 {
142                     addKickedOutPath( path );
143
144                     return null;
145                 }
146             }
147             else
148             {
149                 // no extension
150                 addKickedOutPath( path );
151
152                 return null;
153             }
154         }
155
156         // TODO: this is obscene - surely a better way?
157         String validVersionParts = "([Dd][Ee][Vv][_.0-9]*)|" + "([Ss][Nn][Aa][Pp][Ss][Hh][Oo][Tt])|" +
158             "([0-9][_.0-9a-zA-Z]*)|" + "([Gg]?[_.0-9ab]*([Pp][Rr][Ee]|[Rr][Cc]|[Gg]|[Mm])[_.0-9]*)|" +
159             "([Aa][Ll][Pp][Hh][Aa][_.0-9]*)|" + "([Bb][Ee][Tt][Aa][_.0-9]*)|" + "([Rr][Cc][_.0-9]*)|" +
160             "([Tt][Ee][Ss][Tt][_.0-9]*)|" + "([Dd][Ee][Bb][Uu][Gg][_.0-9]*)|" +
161             "([Uu][Nn][Oo][Ff][Ff][Ii][Cc][Ii][Aa][Ll][_.0-9]*)|" + "([Cc][Uu][Rr][Rr][Ee][Nn][Tt])|" +
162             "([Ll][Aa][Tt][Ee][Ss][Tt])|" + "([Ff][Cc][Ss])|" + "([Rr][Ee][Ll][Ee][Aa][Ss][Ee][_.0-9]*)|" +
163             "([Nn][Ii][Gg][Hh][Tt][Ll][Yy])|" + "([AaBb][_.0-9]*)";
164
165         // let's discover the version, and whatever's leftover will be either
166         // a classifier, or part of the artifactId, depending on position.
167         // Since version is at the end, we have to move in from the back.
168         Collections.reverse( avceTokenList );
169
170         StringBuffer classifierBuffer = new StringBuffer();
171         StringBuffer versionBuffer = new StringBuffer();
172
173         boolean firstVersionTokenEncountered = false;
174         boolean firstToken = true;
175
176         int tokensIterated = 0;
177         for ( Iterator it = avceTokenList.iterator(); it.hasNext(); )
178         {
179             String token = (String) it.next();
180
181             boolean tokenIsVersionPart = token.matches( validVersionParts );
182
183             StringBuffer bufferToUpdate;
184
185             // NOTE: logic in code is reversed, since we're peeling off the back
186             // Any token after the last versionPart will be in the classifier.
187             // Any token UP TO first non-versionPart is part of the version.
188             if ( !tokenIsVersionPart )
189             {
190                 if ( firstVersionTokenEncountered )
191                 {
192                     break;
193                 }
194                 else
195                 {
196                     bufferToUpdate = classifierBuffer;
197                 }
198             }
199             else
200             {
201                 firstVersionTokenEncountered = true;
202
203                 bufferToUpdate = versionBuffer;
204             }
205
206             if ( firstToken )
207             {
208                 firstToken = false;
209             }
210             else
211             {
212                 bufferToUpdate.insert( 0, '-' );
213             }
214
215             bufferToUpdate.insert( 0, token );
216
217             tokensIterated++;
218         }
219
220         getLogger().debug( "After parsing loop, state of buffers:\no  Version Buffer: \'" + versionBuffer +
221             "\'\no  Classifier Buffer: \'" + classifierBuffer + "\'\no Number of Tokens Iterated: " + tokensIterated );
222
223         // Now, restore the proper ordering so we can build the artifactId.
224         Collections.reverse( avceTokenList );
225
226         getLogger().debug(
227             "Before repairing bad version and/or cleaning up used tokens, avce token list is:\n" + avceTokenList );
228
229         // if we didn't find a version, then punt. Use the last token
230         // as the version, and set the classifier empty.
231         if ( versionBuffer.length() < 1 )
232         {
233             if ( avceTokenList.size() > 1 )
234             {
235                 int lastIdx = avceTokenList.size() - 1;
236
237                 versionBuffer.append( avceTokenList.get( lastIdx ) );
238                 avceTokenList.remove( lastIdx );
239             }
240             else
241             {
242                 getLogger().debug( "Cannot parse version from artifact path: \'" + path + "\'." );
243                 getLogger().debug(
244                     "artifact-version-classifier-extension remaining tokens is: \'" + avceTokenList + "\'" );
245             }
246
247             classifierBuffer.setLength( 0 );
248         }
249         else
250         {
251             getLogger().debug( "Removing " + tokensIterated + " tokens from avce token list." );
252
253             // if everything is kosher, then pop off all the classifier and
254             // version tokens, leaving the naked artifact id in the list.
255             avceTokenList = new LinkedList( avceTokenList.subList( 0, avceTokenList.size() - tokensIterated ) );
256         }
257
258         getLogger().debug( "Now, remainder of avce token list is:\n" + avceTokenList );
259
260         StringBuffer artifactIdBuffer = new StringBuffer();
261
262         firstToken = true;
263         for ( Iterator it = avceTokenList.iterator(); it.hasNext(); )
264         {
265             String token = (String) it.next();
266
267             if ( firstToken )
268             {
269                 firstToken = false;
270             }
271             else
272             {
273                 artifactIdBuffer.append( '-' );
274             }
275
276             artifactIdBuffer.append( token );
277         }
278
279         String artifactId = artifactIdBuffer.toString();
280
281         int lastVersionCharIdx = versionBuffer.length() - 1;
282         if ( lastVersionCharIdx > -1 && versionBuffer.charAt( lastVersionCharIdx ) == '-' )
283         {
284             versionBuffer.setLength( lastVersionCharIdx );
285         }
286
287         String version = versionBuffer.toString();
288
289         if ( version.length() < 1 )
290         {
291             addKickedOutPath( path );
292
293             return null;
294         }
295
296         getLogger().debug( "Extracted artifact information from path:\n" + "groupId: \'" + groupId + "\'\n" +
297             "artifactId: \'" + artifactId + "\'\n" + "type: \'" + type + "\'\n" + "version: \'" + version + "\'\n" +
298             "classifier: \'" + classifierBuffer + "\'" );
299
300         Artifact result = null;
301
302         if ( classifierBuffer.length() > 0 )
303         {
304             getLogger().debug( "Creating artifact with classifier." );
305
306             result = artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, type,
307                                                                    classifierBuffer.toString() );
308         }
309         else
310         {
311             result = artifactFactory.createArtifact( groupId, artifactId, version, Artifact.SCOPE_RUNTIME, type );
312         }
313
314         result.setFile( new File( path ) );
315
316         return result;
317     }
318
319 }