1 package org.apache.maven.archiva.repository.content;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.maven.archiva.common.utils.VersionUtil;
24 import org.apache.maven.archiva.model.ArtifactReference;
25 import org.apache.maven.archiva.repository.layout.LayoutException;
28 * DefaultPathParser is a parser for maven 2 (default layout) paths to ArtifactReference.
30 * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
33 * @plexus.component role="org.apache.maven.archiva.repository.content.PathParser" role-hint="default"
35 public class DefaultPathParser implements PathParser
37 private static final String INVALID_ARTIFACT_PATH = "Invalid path to Artifact: ";
41 * @see org.apache.maven.archiva.repository.content.PathParser#toArtifactReference(java.lang.String)
43 public ArtifactReference toArtifactReference( String path )
44 throws LayoutException
46 if ( StringUtils.isBlank( path ) )
48 throw new LayoutException( "Unable to convert blank path." );
51 ArtifactReference artifact = new ArtifactReference();
53 String normalizedPath = StringUtils.replace( path, "\\", "/" );
54 String pathParts[] = StringUtils.split( normalizedPath, '/' );
58 * path = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar"
59 * path[0] = "commons-lang"; // The Group ID
60 * path[1] = "commons-lang"; // The Artifact ID
61 * path[2] = "2.1"; // The Version
62 * path[3] = "commons-lang-2.1.jar" // The filename.
65 if ( pathParts.length < 4 )
67 // Illegal Path Parts Length.
68 throw new LayoutException( "Not enough parts to the path [" + path
69 + "] to construct an ArchivaArtifact from. (Requires at least 4 parts)" );
73 int partCount = pathParts.length;
74 int filenamePos = partCount - 1;
75 int baseVersionPos = partCount - 2;
76 int artifactIdPos = partCount - 3;
77 int groupIdPos = partCount - 4;
79 // Second to last is the baseVersion (the directory version)
80 String baseVersion = pathParts[baseVersionPos];
82 // Third to last is the artifact Id.
83 artifact.setArtifactId( pathParts[artifactIdPos] );
85 // Remaining pieces are the groupId.
86 for ( int i = 0; i <= groupIdPos; i++ )
90 artifact.setGroupId( pathParts[i] );
94 artifact.setGroupId( artifact.getGroupId() + "." + pathParts[i] );
100 // Last part is the filename
101 String filename = pathParts[filenamePos];
103 // Now we need to parse the filename to get the artifact version Id.
104 if ( StringUtils.isBlank( filename ) )
106 throw new IllegalArgumentException( INVALID_ARTIFACT_PATH + "Unable to split blank filename." );
109 FilenameParser parser = new FilenameParser( filename );
111 // Expect the filename to start with the artifactId.
112 artifact.setArtifactId( parser.expect( artifact.getArtifactId() ) );
114 if ( artifact.getArtifactId() == null )
116 throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid, "
117 + "should start with artifactId as stated in path." );
120 // Process the version.
121 artifact.setVersion( parser.expect( baseVersion ) );
123 if ( artifact.getVersion() == null )
125 // We working with a snapshot?
126 if ( VersionUtil.isSnapshot( baseVersion ) )
128 artifact.setVersion( parser.nextVersion() );
129 if ( !VersionUtil.isUniqueSnapshot( artifact.getVersion() ) )
131 throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid,"
132 + "expected timestamp format in filename." );
137 throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid, "
138 + "expected version as stated in path." );
142 // Do we have a classifier?
143 switch(parser.seperator())
146 // Definately a classifier.
147 artifact.setClassifier( parser.remaining() );
150 artifact.setType( ArtifactExtensionMapping.mapExtensionAndClassifierToType( artifact.getClassifier(), parser.getExtension() ) );
153 // We have an dual extension possibility.
154 String extension = parser.remaining() + '.' + parser.getExtension();
155 artifact.setType( extension );
158 // End of the filename, only a simple extension left. - Set the type.
159 String type = ArtifactExtensionMapping.mapExtensionToType( parser.getExtension() );
162 throw new LayoutException( "Invalid artifact: no type was specified" );
164 artifact.setType( type );
168 // Special case for maven plugins
169 if ( StringUtils.equals( "jar", artifact.getType() ) &&
170 ArtifactExtensionMapping.isMavenPlugin( artifact.getArtifactId() ) )
172 artifact.setType( ArtifactExtensionMapping.MAVEN_PLUGIN );
175 catch ( LayoutException e )
182 // Do we have a snapshot version?
183 if ( VersionUtil.isSnapshot( artifact.getVersion() ) )
185 // Rules are different for SNAPSHOTS
186 if ( !VersionUtil.isGenericSnapshot( baseVersion ) )
188 String filenameBaseVersion = VersionUtil.getBaseVersion( artifact.getVersion() );
189 throw new LayoutException( "Invalid snapshot artifact location, version directory should be "
190 + filenameBaseVersion );
195 // Non SNAPSHOT rules.
196 // Do we pass the simple test?
197 if ( !StringUtils.equals( baseVersion, artifact.getVersion() ) )
199 throw new LayoutException( "Invalid artifact: version declared in directory path does"
200 + " not match what was found in the artifact filename." );