blob: 7356d19ced9c0c4b14b2f9895cda24ede69a3d4c [file] [log] [blame]
package org.apache.maven.index.artifact;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import javax.inject.Named;
import javax.inject.Singleton;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* An M2 <code>GavCalculator</code>.
*
* @author Jason van Zyl
* @author Tamas Cservenak
*/
@Singleton
@Named( "maven2" )
public class M2GavCalculator
implements GavCalculator
{
public Gav pathToGav( String str )
{
try
{
String s = str.startsWith( "/" ) ? str.substring( 1 ) : str;
int vEndPos = s.lastIndexOf( '/' );
if ( vEndPos == -1 )
{
return null;
}
int aEndPos = s.lastIndexOf( '/', vEndPos - 1 );
if ( aEndPos == -1 )
{
return null;
}
int gEndPos = s.lastIndexOf( '/', aEndPos - 1 );
if ( gEndPos == -1 )
{
return null;
}
String groupId = s.substring( 0, gEndPos ).replace( '/', '.' );
String artifactId = s.substring( gEndPos + 1, aEndPos );
String version = s.substring( aEndPos + 1, vEndPos );
String fileName = s.substring( vEndPos + 1 );
boolean checksum = false;
boolean signature = false;
Gav.HashType checksumType = null;
Gav.SignatureType signatureType = null;
if ( s.endsWith( ".md5" ) )
{
checksum = true;
checksumType = Gav.HashType.md5;
s = s.substring( 0, s.length() - 4 );
}
else if ( s.endsWith( ".sha1" ) )
{
checksum = true;
checksumType = Gav.HashType.sha1;
s = s.substring( 0, s.length() - 5 );
}
if ( s.endsWith( ".asc" ) )
{
signature = true;
signatureType = Gav.SignatureType.gpg;
s = s.substring( 0, s.length() - 4 );
}
if ( s.endsWith( "maven-metadata.xml" ) )
{
return null;
}
boolean snapshot = version.endsWith( "SNAPSHOT" );
if ( snapshot )
{
return getSnapshotGav( s, vEndPos, groupId, artifactId, version, fileName, checksum, signature,
checksumType, signatureType );
}
else
{
return getReleaseGav( s, vEndPos, groupId, artifactId, version, fileName, checksum, signature,
checksumType, signatureType );
}
}
catch ( NumberFormatException e )
{
return null;
}
catch ( StringIndexOutOfBoundsException e )
{
return null;
}
}
private Gav getReleaseGav( String s, int vEndPos, String groupId, String artifactId, String version,
String fileName, boolean checksum, boolean signature, Gav.HashType checksumType,
Gav.SignatureType signatureType )
{
if ( !fileName.startsWith( artifactId + "-" + version + "." )
&& !fileName.startsWith( artifactId + "-" + version + "-" ) )
{
// The path does not represents an artifact (filename does not match artifactId-version)!
return null;
}
int nTailPos = vEndPos + artifactId.length() + version.length() + 2;
String tail = s.substring( nTailPos );
int nExtPos = tail.indexOf( '.' );
if ( nExtPos == -1 )
{
// NX-563: not allowing extensionless paths to be interpreted as artifact
return null;
}
String ext = tail.substring( nExtPos + 1 );
String classifier = tail.charAt( 0 ) == '-' ? tail.substring( 1, nExtPos ) : null;
return new Gav( groupId, artifactId, version, classifier, ext, null, null, fileName, checksum, checksumType,
signature, signatureType );
}
private Gav getSnapshotGav( String s, int vEndPos, String groupId, String artifactId, String version,
String fileName, boolean checksum, boolean signature, Gav.HashType checksumType,
Gav.SignatureType signatureType )
{
Integer snapshotBuildNo = null;
Long snapshotTimestamp = null;
int vSnapshotStart = vEndPos + artifactId.length() + version.length() - 9 + 3;
String vSnapshot = s.substring( vSnapshotStart, vSnapshotStart + 8 );
String classifier = null;
String ext = null;
if ( "SNAPSHOT".equals( vSnapshot ) )
{
int nTailPos = vEndPos + artifactId.length() + version.length() + 2;
String tail = s.substring( nTailPos );
int nExtPos = tail.indexOf( '.' );
if ( nExtPos == -1 )
{
// NX-563: not allowing extensionless paths to be interpreted as artifact
return null;
}
ext = tail.substring( nExtPos + 1 );
classifier = tail.charAt( 0 ) == '-' ? tail.substring( 1, nExtPos ) : null;
}
else
{
StringBuilder sb = new StringBuilder( vSnapshot );
sb.append( s.substring( vSnapshotStart + sb.length(), vSnapshotStart + sb.length() + 8 ) );
try
{
SimpleDateFormat df = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
snapshotTimestamp = Long.valueOf( df.parse( sb.toString() ).getTime() );
}
catch ( ParseException e )
{
}
int buildNumberPos = vSnapshotStart + sb.length();
StringBuilder bnr = new StringBuilder();
while ( s.charAt( buildNumberPos ) >= '0' && s.charAt( buildNumberPos ) <= '9' )
{
sb.append( s.charAt( buildNumberPos ) );
bnr.append( s.charAt( buildNumberPos ) );
buildNumberPos++;
}
String snapshotBuildNumber = sb.toString();
snapshotBuildNo = Integer.parseInt( bnr.toString() );
int n = version.length() > 9 ? version.length() - 9 + 1 : 0;
String tail = s.substring( vEndPos + artifactId.length() + n + snapshotBuildNumber.length() + 2 );
int nExtPos = tail.indexOf( '.' );
if ( nExtPos == -1 )
{
// NX-563: not allowing extensionless paths to be interpreted as artifact
return null;
}
ext = tail.substring( nExtPos + 1 );
classifier = tail.charAt( 0 ) == '-' ? tail.substring( 1, nExtPos ) : null;
version = version.substring( 0, version.length() - 8 ) + snapshotBuildNumber;
}
return new Gav( groupId, artifactId, version, classifier, ext, snapshotBuildNo, snapshotTimestamp, fileName,
checksum, checksumType, signature, signatureType );
}
public String gavToPath( Gav gav )
{
StringBuilder path = new StringBuilder( "/" );
path.append( gav.getGroupId().replaceAll( "(?m)(.)\\.", "$1/" ) ); // replace all '.' except the first char
path.append( "/" );
path.append( gav.getArtifactId() );
path.append( "/" );
path.append( gav.getBaseVersion() );
path.append( "/" );
path.append( calculateArtifactName( gav ) );
return path.toString();
}
public String calculateArtifactName( Gav gav )
{
if ( gav.getName() != null && gav.getName().trim().length() > 0 )
{
return gav.getName();
}
else
{
StringBuilder path = new StringBuilder( gav.getArtifactId() );
path.append( "-" );
path.append( gav.getVersion() );
if ( gav.getClassifier() != null && gav.getClassifier().trim().length() > 0 )
{
path.append( "-" );
path.append( gav.getClassifier() );
}
if ( gav.getExtension() != null )
{
path.append( "." );
path.append( gav.getExtension() );
}
if ( gav.isSignature() )
{
path.append( "." );
path.append( gav.getSignatureType().toString() );
}
if ( gav.isHash() )
{
path.append( "." );
path.append( gav.getHashType().toString() );
}
return path.toString();
}
}
}