This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.repository.content.maven2;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.archiva.model.ArtifactReference;
023import org.apache.archiva.repository.ManagedRepositoryContent;
024import org.apache.archiva.repository.content.PathParser;
025import org.apache.archiva.repository.layout.LayoutException;
026import org.apache.archiva.repository.metadata.MetadataTools;
027import org.apache.commons.lang.StringUtils;
028
029/**
030 * RepositoryRequest is used to determine the type of request that is incoming, and convert it to an appropriate
031 * ArtifactReference.
032 */
033public class RepositoryRequest
034{
035    private PathParser defaultPathParser = new DefaultPathParser();
036
037    public RepositoryRequest()
038    {
039        // no op
040    }
041
042    /**
043     * Takes an incoming requested path (in "/" format) and gleans the layout
044     * and ArtifactReference appropriate for that content.
045     *
046     * @param requestedPath the relative path to the content.
047     * @return the ArtifactReference for the requestedPath.
048     * @throws org.apache.archiva.repository.layout.LayoutException if the request path is not layout valid.
049     */
050    public ArtifactReference toArtifactReference( String requestedPath )
051        throws LayoutException
052    {
053        if ( StringUtils.isBlank( requestedPath ) )
054        {
055            throw new LayoutException( "Blank request path is not a valid." );
056        }
057
058        String path = requestedPath;
059        while ( path.startsWith( "/" ) )
060        {
061            path = path.substring( 1 );
062
063            // Only slash? that's bad, mmm-kay?
064            if ( "/".equals( path ) )
065            {
066                throw new LayoutException( "Invalid request path: Slash only." );
067            }
068        }
069
070        if ( isDefault( path ) )
071        {
072            return defaultPathParser.toArtifactReference( path );
073        }
074        else if ( isLegacy( path ) )
075        {
076            throw new LayoutException( "Legacy Maven1 repository not supported anymore." );
077        }
078        else
079        {
080            throw new LayoutException( "Not a valid request path layout, too short." );
081        }
082    }
083
084    /**
085     * <p>
086     * Tests the path to see if it conforms to the expectations of a metadata request.
087     * </p>
088     * <p>
089     * NOTE: This does a cursory check on the path's last element.  A result of true
090     * from this method is not a guarantee that the metadata is in a valid format, or
091     * that it even contains data.
092     * </p>
093     *
094     * @param requestedPath the path to test.
095     * @return true if the requestedPath is likely a metadata request.
096     */
097    public boolean isMetadata( String requestedPath )
098    {
099        return requestedPath.endsWith( "/" + MetadataTools.MAVEN_METADATA );
100    }
101
102    /**
103     * @param requestedPath
104     * @return true if the requestedPath is likely an archetype catalog request.
105     */
106    public boolean isArchetypeCatalog( String requestedPath )
107    {
108        return requestedPath.endsWith( "/" + MetadataTools.MAVEN_ARCHETYPE_CATALOG );
109    }
110
111    /**
112     * <p>
113     * Tests the path to see if it conforms to the expectations of a support file request.
114     * </p>
115     * <p>
116     * Tests for <code>.sha1</code>, <code>.md5</code>, <code>.asc</code>, and <code>.php</code>.
117     * </p>
118     * <p>
119     * NOTE: This does a cursory check on the path's extension only.  A result of true
120     * from this method is not a guarantee that the support resource is in a valid format, or
121     * that it even contains data.
122     * </p>
123     *
124     * @param requestedPath the path to test.
125     * @return true if the requestedPath is likely that of a support file request.
126     */
127    public boolean isSupportFile( String requestedPath )
128    {
129        int idx = requestedPath.lastIndexOf( '.' );
130        if ( idx <= 0 )
131        {
132            return false;
133        }
134
135        String ext = requestedPath.substring( idx );
136        return ( ".sha1".equals( ext ) || ".md5".equals( ext ) || ".asc".equals( ext ) || ".pgp".equals( ext ) );
137    }
138
139    public boolean isMetadataSupportFile( String requestedPath )
140    {
141        if ( isSupportFile( requestedPath ) )
142        {
143            String basefilePath = StringUtils.substring( requestedPath, 0, requestedPath.lastIndexOf( '.' ) );
144            if ( isMetadata( basefilePath ) )
145            {
146                return true;
147            }
148        }
149
150        return false;
151    }
152
153    /**
154     * <p>
155     * Tests the path to see if it conforms to the expectations of a default layout request.
156     * </p>
157     * <p>
158     * NOTE: This does a cursory check on the count of path elements only.  A result of
159     * true from this method is not a guarantee that the path sections are valid and
160     * can be resolved to an artifact reference.  use {@link #toArtifactReference(String)}
161     * if you want a more complete analysis of the validity of the path.
162     * </p>
163     *
164     * @param requestedPath the path to test.
165     * @return true if the requestedPath is likely that of a default layout request.
166     */
167    public boolean isDefault( String requestedPath )
168    {
169        if ( StringUtils.isBlank( requestedPath ) )
170        {
171            return false;
172        }
173
174        String pathParts[] = StringUtils.splitPreserveAllTokens( requestedPath, '/' );
175        if ( pathParts.length > 3 )
176        {
177            return true;
178        }
179        else if ( pathParts.length == 3 )
180        {
181            // check if artifact-level metadata (ex. eclipse/jdtcore/maven-metadata.xml)
182            if ( isMetadata( requestedPath ) )
183            {
184                return true;
185            }
186            else
187            {
188                // check if checksum of artifact-level metadata (ex. eclipse/jdtcore/maven-metadata.xml.sha1)
189                int idx = requestedPath.lastIndexOf( '.' );
190                if ( idx > 0 )
191                {
192                    String base = requestedPath.substring( 0, idx );
193                    if ( isMetadata( base ) && isSupportFile( requestedPath ) )
194                    {
195                        return true;
196                    }
197                }
198
199                return false;
200            }
201        }
202        else
203        {
204            return false;
205        }
206    }
207
208    /**
209     * <p>
210     * Tests the path to see if it conforms to the expectations of a legacy layout request.
211     * </p>
212     * <p>
213     * NOTE: This does a cursory check on the count of path elements only.  A result of
214     * true from this method is not a guarantee that the path sections are valid and
215     * can be resolved to an artifact reference.  use {@link #toArtifactReference(String)}
216     * if you want a more complete analysis of the validity of the path.
217     * </p>
218     *
219     * @param requestedPath the path to test.
220     * @return true if the requestedPath is likely that of a legacy layout request.
221     */
222    public boolean isLegacy( String requestedPath )
223    {
224        if ( StringUtils.isBlank( requestedPath ) )
225        {
226            return false;
227        }
228
229        String pathParts[] = StringUtils.splitPreserveAllTokens( requestedPath, '/' );
230        return pathParts.length == 3;
231    }
232
233    /**
234     * Adjust the requestedPath to conform to the native layout of the provided {@link org.apache.archiva.repository.ManagedRepositoryContent}.
235     *
236     * @param requestedPath the incoming requested path.
237     * @param repository    the repository to adjust to.
238     * @return the adjusted (to native) path.
239     * @throws org.apache.archiva.repository.layout.LayoutException if the path cannot be parsed.
240     */
241    public String toNativePath( String requestedPath, ManagedRepositoryContent repository )
242        throws LayoutException
243    {
244        if ( StringUtils.isBlank( requestedPath ) )
245        {
246            throw new LayoutException( "Request Path is blank." );
247        }
248
249        String referencedResource = requestedPath;
250        // No checksum by default.
251        String supportfile = "";
252
253        // Figure out support file, and actual referencedResource.
254        if ( isSupportFile( requestedPath ) )
255        {
256            int idx = requestedPath.lastIndexOf( '.' );
257            referencedResource = requestedPath.substring( 0, idx );
258            supportfile = requestedPath.substring( idx );
259        }
260
261        if ( isMetadata( referencedResource ) )
262        {
263            /* Nothing to translate.
264             * Default layout is the only layout that can contain maven-metadata.xml files, and
265             * if the managedRepository is layout legacy, this request would never occur.
266             */
267            return requestedPath;
268        }
269
270        // Treat as an artifact reference.
271        ArtifactReference ref = toArtifactReference( referencedResource );
272        String adjustedPath = repository.toPath( ref );
273        return adjustedPath + supportfile;
274    }
275}