]> source.dussan.org Git - archiva.git/blob
d473c16d0347508f42f64d7770af4dd019227b8a
[archiva.git] /
1 package org.apache.maven.archiva.repository.content;
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.configuration.ArchivaConfiguration;
24 import org.apache.maven.archiva.configuration.FileTypes;
25 import org.apache.maven.archiva.model.ArtifactReference;
26 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
27 import org.apache.maven.archiva.repository.layout.LayoutException;
28 import org.apache.maven.archiva.repository.metadata.MetadataTools;
29 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
30 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
31 import org.codehaus.plexus.registry.Registry;
32 import org.codehaus.plexus.registry.RegistryListener;
33 import org.codehaus.plexus.util.SelectorUtils;
34
35 import java.util.ArrayList;
36 import java.util.Iterator;
37 import java.util.List;
38
39 /**
40  * RepositoryRequest is used to determine the type of request that is incoming, and convert it to an appropriate
41  * ArtifactReference.
42  *
43  * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
44  * @version $Id$
45  *
46  * @plexus.component
47  *      role="org.apache.maven.archiva.repository.content.RepositoryRequest"
48  */
49 public class RepositoryRequest
50     implements RegistryListener, Initializable
51 {
52     /**
53      * @plexus.requirement
54      */
55     private FileTypes filetypes;
56
57     /**
58      * @plexus.requirement
59      */
60     private ArchivaConfiguration archivaConfiguration;
61
62     /**
63      * @plexus.requirement role-hint="default"
64      */
65     private PathParser defaultPathParser;
66
67     /**
68      * @plexus.requirement role-hint="legacy"
69      */
70     private PathParser legacyPathParser;
71
72     private List<String> artifactPatterns;
73
74     /**
75      * Test path to see if it is an artifact being requested (or not).
76      *
77      * @param requestedPath the path to test.
78      * @return true if it is an artifact being requested.
79      */
80     public boolean isArtifact( String requestedPath )
81     {
82         // Correct the slash pattern.
83         String relativePath = requestedPath.replace( '\\', '/' );
84
85         Iterator<String> it = this.artifactPatterns.iterator();
86         while ( it.hasNext() )
87         {
88             String pattern = it.next();
89
90             if ( SelectorUtils.matchPath( pattern, relativePath, false ) )
91             {
92                 // Found match
93                 return true;
94             }
95         }
96
97         // No match.
98         return false;
99     }
100
101     /**
102      * Takes an incoming requested path (in "/" format) and gleans the layout
103      * and ArtifactReference appropriate for that content.
104      *
105      * @param requestedPath the relative path to the content.
106      * @return the ArtifactReference for the requestedPath.
107      * @throws LayoutException if the request path is not layout valid.
108      */
109     public ArtifactReference toArtifactReference( String requestedPath )
110         throws LayoutException
111     {
112         if ( StringUtils.isBlank( requestedPath ) )
113         {
114             throw new LayoutException( "Blank request path is not a valid." );
115         }
116
117         String path = requestedPath;
118         while ( path.startsWith( "/" ) )
119         {
120             path = path.substring( 1 );
121
122             // Only slash? that's bad, mmm-kay?
123             if ( "/".equals( path ) )
124             {
125                 throw new LayoutException( "Invalid request path: Slash only." );
126             }
127         }
128
129         if ( isDefault( path ) )
130         {
131             return defaultPathParser.toArtifactReference( path );
132         }
133         else if ( isLegacy( path ) )
134         {
135             return legacyPathParser.toArtifactReference( path );
136         }
137         else
138         {
139             throw new LayoutException( "Not a valid request path layout, too short." );
140         }
141     }
142
143     /**
144      * <p>
145      * Tests the path to see if it conforms to the expectations of a metadata request.
146      * </p>
147      * <p>
148      * NOTE: This does a cursory check on the path's last element.  A result of true
149      * from this method is not a guarantee that the metadata is in a valid format, or
150      * that it even contains data.
151      * </p>
152      *
153      * @param requestedPath the path to test.
154      * @return true if the requestedPath is likely a metadata request.
155      */
156     public boolean isMetadata( String requestedPath )
157     {
158         return requestedPath.endsWith( "/" + MetadataTools.MAVEN_METADATA );
159     }
160
161     /**
162      * <p>
163      * Tests the path to see if it conforms to the expectations of a support file request.
164      * </p>
165      * <p>
166      * Tests for <code>.sha1</code>, <code>.md5</code>, <code>.asc</code>, and <code>.php</code>.
167      * </p>
168      * <p>
169      * NOTE: This does a cursory check on the path's extension only.  A result of true
170      * from this method is not a guarantee that the support resource is in a valid format, or
171      * that it even contains data.
172      * </p>
173      *
174      * @param requestedPath the path to test.
175      * @return true if the requestedPath is likely that of a support file request.
176      */
177     public boolean isSupportFile( String requestedPath )
178     {
179         int idx = requestedPath.lastIndexOf( '.' );
180         if ( idx <= 0 )
181         {
182             return false;
183         }
184
185         String ext = requestedPath.substring( idx );
186         return ( ".sha1".equals( ext ) || ".md5".equals( ext ) || ".asc".equals( ext ) || ".pgp".equals( ext ) );
187     }
188
189     /**
190      * <p>
191      * Tests the path to see if it conforms to the expectations of a default layout request.
192      * </p>
193      * <p>
194      * NOTE: This does a cursory check on the count of path elements only.  A result of
195      * true from this method is not a guarantee that the path sections are valid and
196      * can be resolved to an artifact reference.  use {@link #toArtifactReference(String)}
197      * if you want a more complete analysis of the validity of the path.
198      * </p>
199      *
200      * @param requestedPath the path to test.
201      * @return true if the requestedPath is likely that of a default layout request.
202      */
203     public boolean isDefault( String requestedPath )
204     {
205         if ( StringUtils.isBlank( requestedPath ) )
206         {
207             return false;
208         }
209
210         String pathParts[] = StringUtils.splitPreserveAllTokens( requestedPath, '/' );
211         return pathParts.length > 3;
212     }
213
214     /**
215      * <p>
216      * Tests the path to see if it conforms to the expectations of a legacy layout request.
217      * </p>
218      * <p>
219      * NOTE: This does a cursory check on the count of path elements only.  A result of
220      * true from this method is not a guarantee that the path sections are valid and
221      * can be resolved to an artifact reference.  use {@link #toArtifactReference(String)}
222      * if you want a more complete analysis of the validity of the path.
223      * </p>
224      *
225      * @param requestedPath the path to test.
226      * @return true if the requestedPath is likely that of a legacy layout request.
227      */
228     public boolean isLegacy( String requestedPath )
229     {
230         if ( StringUtils.isBlank( requestedPath ) )
231         {
232             return false;
233         }
234
235         String pathParts[] = StringUtils.splitPreserveAllTokens( requestedPath, '/' );
236         return pathParts.length == 3;
237     }
238
239     /**
240      * Adjust the requestedPath to conform to the native layout of the provided {@link ManagedRepositoryContent}.
241      *
242      * @param requestedPath the incoming requested path.
243      * @param repository the repository to adjust to.
244      * @return the adjusted (to native) path.
245      * @throws LayoutException if the path cannot be parsed.
246      */
247     public String toNativePath( String requestedPath, ManagedRepositoryContent repository ) throws LayoutException
248     {
249         if ( StringUtils.isBlank( requestedPath ) )
250         {
251             throw new LayoutException( "Request Path is blank." );
252         }
253
254         String referencedResource = requestedPath;
255         // No checksum by default.
256         String supportfile = "";
257
258         // Figure out support file, and actual referencedResource.
259         if( isSupportFile( requestedPath ) )
260         {
261             int idx = requestedPath.lastIndexOf( '.' );
262             referencedResource = requestedPath.substring( 0, idx );
263             supportfile = requestedPath.substring( idx );
264         }
265
266         if ( isMetadata( referencedResource ) )
267         {
268             if ( repository instanceof ManagedLegacyRepositoryContent )
269             {
270                 throw new LayoutException( "Cannot translate metadata request to legacy layout." );
271             }
272
273             /* Nothing to translate.
274              * Default layout is the only layout that can contain maven-metadata.xml files, and
275              * if the managedRepository is layout legacy, this request would never occur.
276              */
277             return requestedPath;
278         }
279
280         // Treat as an artifact reference.
281         ArtifactReference ref = toArtifactReference( referencedResource );
282         String adjustedPath = repository.toPath( ref );
283         return adjustedPath + supportfile;
284     }
285
286     public void initialize()
287         throws InitializationException
288     {
289         this.artifactPatterns = new ArrayList<String>();
290         initVariables();
291         this.archivaConfiguration.addChangeListener( this );
292     }
293
294     private void initVariables()
295     {
296         synchronized ( this.artifactPatterns )
297         {
298             this.artifactPatterns.clear();
299             this.artifactPatterns.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
300         }
301     }
302
303     public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
304     {
305         if ( propertyName.contains( "fileType" ) )
306         {
307             initVariables();
308         }
309     }
310
311     public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
312     {
313         /* nothing to do */
314
315     }
316 }