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.*;
024import org.apache.archiva.repository.content.PathParser;
025import org.apache.archiva.repository.features.RepositoryFeature;
026import org.apache.archiva.repository.metadata.base.MetadataTools;
027import org.apache.commons.lang3.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 MavenRepositoryRequestInfo implements RepositoryRequestInfo
034{
035    private PathParser defaultPathParser = new DefaultPathParser();
036
037    ManagedRepository repository;
038
039    public MavenRepositoryRequestInfo(ManagedRepository repository)
040    {
041        this.repository = repository;
042    }
043
044    /**
045     * Takes an incoming requested path (in "/" format) and gleans the layout
046     * and ArtifactReference appropriate for that content.
047     *
048     * @param requestedPath the relative path to the content.
049     * @return the ArtifactReference for the requestedPath.
050     * @throws LayoutException if the request path is not layout valid.
051     */
052    public ArtifactReference toArtifactReference( String requestedPath )
053        throws LayoutException
054    {
055        if ( StringUtils.isBlank( requestedPath ) )
056        {
057            throw new LayoutException( "Blank request path is not a valid." );
058        }
059
060        String path = requestedPath;
061        while ( path.startsWith( "/" ) )
062        {
063            path = path.substring( 1 );
064
065            // Only slash? that's bad, mmm-kay?
066            if ( "/".equals( path ) )
067            {
068                throw new LayoutException( "Invalid request path: Slash only." );
069            }
070        }
071
072        if ( isDefault( path ) )
073        {
074            return defaultPathParser.toArtifactReference( path );
075        }
076        else if ( isLegacy( path ) )
077        {
078            throw new LayoutException( "Legacy Maven1 repository not supported anymore." );
079        }
080        else
081        {
082            throw new LayoutException( "Not a valid request path layout, too short." );
083        }
084    }
085
086    /**
087     * <p>
088     * Tests the path to see if it conforms to the expectations of a metadata request.
089     * </p>
090     * <p>
091     * NOTE: This does a cursory check on the path's last element.  A result of true
092     * from this method is not a guarantee that the metadata is in a valid format, or
093     * that it even contains data.
094     * </p>
095     *
096     * @param requestedPath the path to test.
097     * @return true if the requestedPath is likely a metadata request.
098     */
099    public boolean isMetadata( String requestedPath )
100    {
101        return requestedPath.endsWith( "/" + MetadataTools.MAVEN_METADATA );
102    }
103
104    /**
105     * @param requestedPath
106     * @return true if the requestedPath is likely an archetype catalog request.
107     */
108    public boolean isArchetypeCatalog( String requestedPath )
109    {
110        return requestedPath.endsWith( "/" + MetadataTools.MAVEN_ARCHETYPE_CATALOG );
111    }
112
113    /**
114     * <p>
115     * Tests the path to see if it conforms to the expectations of a support file request.
116     * </p>
117     * <p>
118     * Tests for <code>.sha1</code>, <code>.md5</code>, <code>.asc</code>, and <code>.php</code>.
119     * </p>
120     * <p>
121     * NOTE: This does a cursory check on the path's extension only.  A result of true
122     * from this method is not a guarantee that the support resource is in a valid format, or
123     * that it even contains data.
124     * </p>
125     *
126     * @param requestedPath the path to test.
127     * @return true if the requestedPath is likely that of a support file request.
128     */
129    public boolean isSupportFile( String requestedPath )
130    {
131        int idx = requestedPath.lastIndexOf( '.' );
132        if ( idx <= 0 )
133        {
134            return false;
135        }
136
137        String ext = requestedPath.substring( idx );
138        return ( ".sha1".equals( ext ) || ".md5".equals( ext ) || ".asc".equals( ext ) || ".pgp".equals( ext ) );
139    }
140
141    public boolean isMetadataSupportFile( String requestedPath )
142    {
143        if ( isSupportFile( requestedPath ) )
144        {
145            String basefilePath = StringUtils.substring( requestedPath, 0, requestedPath.lastIndexOf( '.' ) );
146            if ( isMetadata( basefilePath ) )
147            {
148                return true;
149            }
150        }
151
152        return false;
153    }
154
155    @Override
156    public String getLayout(String requestPath) {
157        if (isDefault(requestPath)) {
158            return "default";
159        } else if (isLegacy(requestPath)) {
160            return "legacy";
161        } else {
162            return "unknown";
163        }
164    }
165
166    /**
167     * <p>
168     * Tests the path to see if it conforms to the expectations of a default layout request.
169     * </p>
170     * <p>
171     * NOTE: This does a cursory check on the count of path elements only.  A result of
172     * true from this method is not a guarantee that the path sections are valid and
173     * can be resolved to an artifact reference.  use {@link #toArtifactReference(String)}
174     * if you want a more complete analysis of the validity of the path.
175     * </p>
176     *
177     * @param requestedPath the path to test.
178     * @return true if the requestedPath is likely that of a default layout request.
179     */
180    private boolean isDefault( String requestedPath )
181    {
182        if ( StringUtils.isBlank( requestedPath ) )
183        {
184            return false;
185        }
186
187        String pathParts[] = StringUtils.splitPreserveAllTokens( requestedPath, '/' );
188        if ( pathParts.length > 3 )
189        {
190            return true;
191        }
192        else if ( pathParts.length == 3 )
193        {
194            // check if artifact-level metadata (ex. eclipse/jdtcore/maven-metadata.xml)
195            if ( isMetadata( requestedPath ) )
196            {
197                return true;
198            }
199            else
200            {
201                // check if checksum of artifact-level metadata (ex. eclipse/jdtcore/maven-metadata.xml.sha1)
202                int idx = requestedPath.lastIndexOf( '.' );
203                if ( idx > 0 )
204                {
205                    String base = requestedPath.substring( 0, idx );
206                    if ( isMetadata( base ) && isSupportFile( requestedPath ) )
207                    {
208                        return true;
209                    }
210                }
211
212                return false;
213            }
214        }
215        else
216        {
217            return false;
218        }
219    }
220
221    /**
222     * <p>
223     * Tests the path to see if it conforms to the expectations of a legacy layout request.
224     * </p>
225     * <p>
226     * NOTE: This does a cursory check on the count of path elements only.  A result of
227     * true from this method is not a guarantee that the path sections are valid and
228     * can be resolved to an artifact reference.  use {@link #toArtifactReference(String)}
229     * if you want a more complete analysis of the validity of the path.
230     * </p>
231     *
232     * @param requestedPath the path to test.
233     * @return true if the requestedPath is likely that of a legacy layout request.
234     */
235    private boolean isLegacy( String requestedPath )
236    {
237        if ( StringUtils.isBlank( requestedPath ) )
238        {
239            return false;
240        }
241
242        String pathParts[] = StringUtils.splitPreserveAllTokens( requestedPath, '/' );
243        return pathParts.length == 3;
244    }
245
246    /**
247     * Adjust the requestedPath to conform to the native layout of the provided {@link org.apache.archiva.repository.ManagedRepositoryContent}.
248     *
249     * @param requestedPath the incoming requested path.
250     * @return the adjusted (to native) path.
251     * @throws LayoutException if the path cannot be parsed.
252     */
253    public String toNativePath( String requestedPath)
254        throws LayoutException
255    {
256        if ( StringUtils.isBlank( requestedPath ) )
257        {
258            throw new LayoutException( "Request Path is blank." );
259        }
260
261        String referencedResource = requestedPath;
262        // No checksum by default.
263        String supportfile = "";
264
265        // Figure out support file, and actual referencedResource.
266        if ( isSupportFile( requestedPath ) )
267        {
268            int idx = requestedPath.lastIndexOf( '.' );
269            referencedResource = requestedPath.substring( 0, idx );
270            supportfile = requestedPath.substring( idx );
271        }
272
273        if ( isMetadata( referencedResource ) )
274        {
275            /* Nothing to translate.
276             * Default layout is the only layout that can contain maven-metadata.xml files, and
277             * if the managedRepository is layout legacy, this request would never occur.
278             */
279            return requestedPath;
280        }
281
282        // Treat as an artifact reference.
283        ArtifactReference ref = toArtifactReference( referencedResource );
284        String adjustedPath = repository.getContent().toPath( ref );
285        return adjustedPath + supportfile;
286    }
287
288    @Override
289    public <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature(Class<T> clazz) throws UnsupportedFeatureException {
290        return null;
291    }
292
293    @Override
294    public <T extends RepositoryFeature<T>> boolean supportsFeature(Class<T> clazz) {
295        return false;
296    }
297}