Improving repository API

This commit is contained in:
Martin Stockhammer 2020-06-11 14:33:00 +02:00
parent b942314aa2
commit 46fd585f40
15 changed files with 477 additions and 185 deletions

View File

@ -194,4 +194,6 @@ public class VersionUtil
} }
return version; return version;
} }
} }

View File

@ -23,9 +23,9 @@ import org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.common.utils.VersionUtil; import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.metadata.audit.RepositoryListener; import org.apache.archiva.metadata.audit.RepositoryListener;
import org.apache.archiva.metadata.repository.RepositorySession; import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.LayoutException;
import org.apache.archiva.repository.BaseRepositoryContentLayout; import org.apache.archiva.repository.BaseRepositoryContentLayout;
import org.apache.archiva.repository.LayoutException;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.content.Artifact; import org.apache.archiva.repository.content.Artifact;
import org.apache.archiva.repository.content.ContentItem; import org.apache.archiva.repository.content.ContentItem;
import org.apache.archiva.repository.content.base.ArchivaItemSelector; import org.apache.archiva.repository.content.base.ArchivaItemSelector;
@ -74,9 +74,7 @@ public class DaysOldRepositoryPurge
{ {
ContentItem item = repository.toItem( path ); ContentItem item = repository.toItem( path );
if ( item instanceof Artifact ) Artifact artifactItem = repository.getLayout( BaseRepositoryContentLayout.class ).adaptItem( Artifact.class, item );
{
Artifact artifactItem = (Artifact) item;
if ( !artifactItem.exists( ) ) if ( !artifactItem.exists( ) )
{ {
@ -97,7 +95,8 @@ public class DaysOldRepositoryPurge
.build( ); .build( );
List<String> artifactVersions; List<String> artifactVersions;
try( Stream<? extends Artifact> stream = repository.getLayout( BaseRepositoryContentLayout.class ).newArtifactStream( selector )){ try ( Stream<? extends Artifact> stream = repository.getLayout( BaseRepositoryContentLayout.class ).newArtifactStream( selector ) )
{
artifactVersions = stream.map( a -> a.getArtifactVersion( ) ) artifactVersions = stream.map( a -> a.getArtifactVersion( ) )
.filter( StringUtils::isNotEmpty ) .filter( StringUtils::isNotEmpty )
.distinct( ) .distinct( )
@ -155,14 +154,15 @@ public class DaysOldRepositoryPurge
artifactsToDelete.addAll( repository.getLayout( BaseRepositoryContentLayout.class ).getArtifacts( artifactSelector ) ); artifactsToDelete.addAll( repository.getLayout( BaseRepositoryContentLayout.class ).getArtifacts( artifactSelector ) );
} }
} }
} catch ( IllegalArgumentException e ) { }
catch ( IllegalArgumentException e )
{
log.error( "Bad selector for artifact: {}", e.getMessage( ), e ); log.error( "Bad selector for artifact: {}", e.getMessage( ), e );
// continue // continue
} }
} }
purge( artifactsToDelete ); purge( artifactsToDelete );
} }
}
catch ( LayoutException e ) catch ( LayoutException e )
{ {
log.debug( "Not processing file that is not an artifact: {}", e.getMessage( ) ); log.debug( "Not processing file that is not an artifact: {}", e.getMessage( ) );

View File

@ -21,12 +21,12 @@ package org.apache.archiva.consumers.core.repository;
import org.apache.archiva.common.utils.VersionComparator; import org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.common.utils.VersionUtil; import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.metadata.audit.RepositoryListener;
import org.apache.archiva.metadata.repository.RepositorySession; import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.model.ArtifactReference; import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.LayoutException;
import org.apache.archiva.repository.BaseRepositoryContentLayout; import org.apache.archiva.repository.BaseRepositoryContentLayout;
import org.apache.archiva.metadata.audit.RepositoryListener; import org.apache.archiva.repository.LayoutException;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.content.Artifact; import org.apache.archiva.repository.content.Artifact;
import org.apache.archiva.repository.content.ContentItem; import org.apache.archiva.repository.content.ContentItem;
import org.apache.archiva.repository.content.base.ArchivaItemSelector; import org.apache.archiva.repository.content.base.ArchivaItemSelector;
@ -61,10 +61,10 @@ public class RetentionCountRepositoryPurge
try try
{ {
ContentItem item = repository.toItem( path ); ContentItem item = repository.toItem( path );
if (item instanceof Artifact ) BaseRepositoryContentLayout layout = repository.getLayout( BaseRepositoryContentLayout.class );
Artifact artifact = layout.adaptItem( Artifact.class, item );
if ( !artifact.exists( ) )
{ {
Artifact artifact = (Artifact) item;
if (!artifact.exists()) {
return; return;
} }
@ -81,7 +81,8 @@ public class RetentionCountRepositoryPurge
List<String> versions; List<String> versions;
try( Stream<? extends Artifact> stream = repository.getLayout( BaseRepositoryContentLayout.class ).newArtifactStream( selector) ){ try ( Stream<? extends Artifact> stream = repository.getLayout( BaseRepositoryContentLayout.class ).newArtifactStream( selector ) )
{
versions = stream.map( a -> a.getArtifactVersion( ) ) versions = stream.map( a -> a.getArtifactVersion( ) )
.filter( StringUtils::isNotEmpty ) .filter( StringUtils::isNotEmpty )
.distinct( ) .distinct( )
@ -120,9 +121,6 @@ public class RetentionCountRepositoryPurge
} }
purge( artifactsToDelete ); purge( artifactsToDelete );
} }
} else {
throw new RepositoryPurgeException( "Bad artifact path " + path );
}
} }
catch ( LayoutException le ) catch ( LayoutException le )
{ {

View File

@ -25,6 +25,7 @@ import org.apache.archiva.policies.ProxyDownloadException;
import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.RepositoryType; import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.content.Artifact; import org.apache.archiva.repository.content.Artifact;
import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.repository.storage.StorageAsset;
import java.util.List; import java.util.List;
@ -89,6 +90,21 @@ public interface RepositoryProxyHandler
StorageAsset fetchFromProxies( ManagedRepository repository, Artifact artifact ) StorageAsset fetchFromProxies( ManagedRepository repository, Artifact artifact )
throws ProxyDownloadException; throws ProxyDownloadException;
/**
* Performs the artifact fetch operation against the target repositories
* of the provided source repository.
* <p>
* If the artifact is found, it is downloaded and placed into the source repository
* filesystem.
*
* @param repository the source repository to use. (must be a managed repository)
* @param artifactSelector the artifact to fetch.
* @return the file that was obtained, or null if no content was obtained
* @throws ProxyDownloadException if there was a problem fetching the content from the target repositories.
*/
StorageAsset fetchFromProxies( ManagedRepository repository, ItemSelector artifactSelector )
throws ProxyDownloadException;
/** /**
* Performs the metadata fetch operation against the target repositories * Performs the metadata fetch operation against the target repositories
* of the provided source repository. * of the provided source repository.

View File

@ -50,6 +50,7 @@ import org.apache.archiva.repository.RemoteRepository;
import org.apache.archiva.repository.RemoteRepositoryContent; import org.apache.archiva.repository.RemoteRepositoryContent;
import org.apache.archiva.repository.RepositoryType; import org.apache.archiva.repository.RepositoryType;
import org.apache.archiva.repository.content.Artifact; import org.apache.archiva.repository.content.Artifact;
import org.apache.archiva.repository.content.ContentItem;
import org.apache.archiva.repository.content.ItemSelector; import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.repository.content.base.ArchivaItemSelector; import org.apache.archiva.repository.content.base.ArchivaItemSelector;
import org.apache.archiva.repository.metadata.base.MetadataTools; import org.apache.archiva.repository.metadata.base.MetadataTools;
@ -206,6 +207,73 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
return null; return null;
} }
@Override
public StorageAsset fetchFromProxies( ManagedRepository repository, ItemSelector artifactSelector )
throws ProxyDownloadException
{
Map<String, Exception> previousExceptions = new LinkedHashMap<>();
ContentItem item = repository.getContent( ).getItem( artifactSelector );
StorageAsset localFile = item.getAsset( );
Properties requestProperties = new Properties();
requestProperties.setProperty( "filetype", "artifact" );
requestProperties.setProperty( "version", artifactSelector.getVersion() );
requestProperties.setProperty( "managedRepositoryId", repository.getId() );
List<ProxyConnector> connectors = getProxyConnectors( repository );
for ( ProxyConnector connector : connectors )
{
if ( !connector.isEnabled() )
{
continue;
}
RemoteRepository targetRepository = connector.getTargetRepository();
requestProperties.setProperty( "remoteRepositoryId", targetRepository.getId() );
StorageAsset targetFile = targetRepository.getAsset( localFile.getPath( ) );
// Removing the leading '/' from the path
String targetPath = targetFile.getPath( ).substring( 1 );
try
{
StorageAsset downloadedFile =
transferFile( connector, targetRepository, targetPath, repository, localFile, requestProperties,
true );
if ( fileExists(downloadedFile) )
{
log.debug( "Successfully transferred: {}", downloadedFile.getPath() );
return downloadedFile;
}
}
catch ( NotFoundException e )
{
log.debug( "Artifact {} not found on repository \"{}\".", item,
targetRepository.getId() );
}
catch ( NotModifiedException e )
{
log.debug( "Artifact {} not updated on repository \"{}\".", item,
targetRepository.getId() );
}
catch ( ProxyException e )
{
validatePolicies( this.downloadErrorPolicies, connector.getPolicies(), requestProperties, item,
targetRepository.getContent(), localFile, e, previousExceptions );
}
}
if ( !previousExceptions.isEmpty() )
{
throw new ProxyDownloadException( "Failures occurred downloading from some remote repositories",
previousExceptions );
}
log.debug( "Exhausted all target repositories, artifact {} not found.", item );
return null;
}
@Override @Override
public StorageAsset fetchFromProxies( ManagedRepository repository, ArtifactReference artifact ) public StorageAsset fetchFromProxies( ManagedRepository repository, ArtifactReference artifact )
throws ProxyDownloadException throws ProxyDownloadException
@ -736,7 +804,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
} }
private void validatePolicies( Map<String, DownloadErrorPolicy> policies, Map<Policy, PolicyOption> settings, private void validatePolicies( Map<String, DownloadErrorPolicy> policies, Map<Policy, PolicyOption> settings,
Properties request, Artifact artifact, RemoteRepositoryContent content, Properties request, ContentItem artifact, RemoteRepositoryContent content,
StorageAsset localFile, Exception exception, Map<String, Exception> previousExceptions ) StorageAsset localFile, Exception exception, Map<String, Exception> previousExceptions )
throws ProxyDownloadException throws ProxyDownloadException
{ {
@ -784,7 +852,7 @@ public abstract class DefaultRepositoryProxyHandler implements RepositoryProxyHa
log.warn( log.warn(
"Transfer error from repository {} for artifact {} , continuing to next repository. Error message: {}", "Transfer error from repository {} for artifact {} , continuing to next repository. Error message: {}",
content.getRepository().getId(), artifact.getId(), exception.getMessage() ); content.getRepository().getId(), artifact, exception.getMessage() );
log.debug( "Full stack trace", exception ); log.debug( "Full stack trace", exception );
} }

View File

@ -20,6 +20,7 @@ package org.apache.archiva.repository;
*/ */
import org.apache.archiva.model.ArtifactReference; import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.repository.features.RepositoryFeature; import org.apache.archiva.repository.features.RepositoryFeature;
/** /**
@ -42,6 +43,15 @@ public interface RepositoryRequestInfo
*/ */
ArtifactReference toArtifactReference( String requestPath ) throws LayoutException; ArtifactReference toArtifactReference( String requestPath ) throws LayoutException;
/**
* Returns the item selector that matches the given path.
* @param requestPath the request path which may be different from the filesystem structure
* @return the item selector
* @throws LayoutException if the path is not valid for the given repository layout
*/
ItemSelector toItemSelector( String requestPath ) throws LayoutException;
/** /**
* <p> * <p>
* Tests the path to see if it conforms to the expectations of a metadata request. * Tests the path to see if it conforms to the expectations of a metadata request.

View File

@ -20,6 +20,7 @@ package org.apache.archiva.repository.maven.content;
import org.apache.archiva.common.filelock.FileLockManager; import org.apache.archiva.common.filelock.FileLockManager;
import org.apache.archiva.common.utils.FileUtils; import org.apache.archiva.common.utils.FileUtils;
import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.configuration.FileTypes; import org.apache.archiva.configuration.FileTypes;
import org.apache.archiva.metadata.maven.MavenMetadataReader; import org.apache.archiva.metadata.maven.MavenMetadataReader;
import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator; import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
@ -185,6 +186,8 @@ public class ManagedDefaultRepositoryContent
@Override @Override
public <T extends ContentItem> T adaptItem( Class<T> clazz, ContentItem item ) throws LayoutException public <T extends ContentItem> T adaptItem( Class<T> clazz, ContentItem item ) throws LayoutException
{
try
{ {
if ( clazz.isAssignableFrom( Version.class ) ) if ( clazz.isAssignableFrom( Version.class ) )
{ {
@ -193,24 +196,34 @@ public class ManagedDefaultRepositoryContent
item.setCharacteristic( Version.class, createVersionFromPath( item.getAsset( ) ) ); item.setCharacteristic( Version.class, createVersionFromPath( item.getAsset( ) ) );
} }
return (T) item.adapt( Version.class ); return (T) item.adapt( Version.class );
} else if ( clazz.isAssignableFrom( Project.class )) { }
else if ( clazz.isAssignableFrom( Project.class ) )
{
if ( !item.hasCharacteristic( Project.class ) ) if ( !item.hasCharacteristic( Project.class ) )
{ {
item.setCharacteristic( Project.class, createProjectFromPath( item.getAsset( ) ) ); item.setCharacteristic( Project.class, createProjectFromPath( item.getAsset( ) ) );
} }
return (T) item.adapt( Project.class ); return (T) item.adapt( Project.class );
} else if ( clazz.isAssignableFrom( Namespace.class )) { }
else if ( clazz.isAssignableFrom( Namespace.class ) )
{
if ( !item.hasCharacteristic( Namespace.class ) ) if ( !item.hasCharacteristic( Namespace.class ) )
{ {
item.setCharacteristic( Namespace.class, createNamespaceFromPath( item.getAsset( ) ) ); item.setCharacteristic( Namespace.class, createNamespaceFromPath( item.getAsset( ) ) );
} }
return (T) item.adapt( Namespace.class ); return (T) item.adapt( Namespace.class );
} else if ( clazz.isAssignableFrom( Artifact.class )) { }
if (!item.hasCharacteristic( Artifact.class )) { else if ( clazz.isAssignableFrom( Artifact.class ) )
{
if ( !item.hasCharacteristic( Artifact.class ) )
{
item.setCharacteristic( Artifact.class, createArtifactFromPath( item.getAsset( ) ) ); item.setCharacteristic( Artifact.class, createArtifactFromPath( item.getAsset( ) ) );
} }
return (T) item.adapt( Artifact.class ); return (T) item.adapt( Artifact.class );
} }
} catch (LayoutRuntimeException e) {
throw new LayoutException( e.getMessage( ), e );
}
throw new LayoutException( "Could not convert item to class " + clazz); throw new LayoutException( "Could not convert item to class " + clazz);
} }
@ -593,6 +606,7 @@ public class ManagedDefaultRepositoryContent
} }
} }
private DataItem getDataItemFromPath( final StorageAsset artifactPath ) private DataItem getDataItemFromPath( final StorageAsset artifactPath )
{ {
final String contentType = getContentType( artifactPath ); final String contentType = getContentType( artifactPath );
@ -644,13 +658,13 @@ public class ManagedDefaultRepositoryContent
private ArtifactType artifactType = BaseArtifactTypes.MAIN; private ArtifactType artifactType = BaseArtifactTypes.MAIN;
} }
private ArtifactInfo getArtifactInfoFromPath( String genericVersion, StorageAsset path ) private ArtifactInfo getArtifactInfoFromPath( final String genericVersion, final StorageAsset path )
{ {
final ArtifactInfo info = new ArtifactInfo( ); final ArtifactInfo info = new ArtifactInfo( );
info.asset = path; info.asset = path;
info.id = path.getParent( ).getParent( ).getName( ); info.id = path.getParent( ).getParent( ).getName( );
final String fileName = path.getName( ); final String fileName = path.getName( );
if ( genericVersion.endsWith( "-" + SNAPSHOT ) ) if ( VersionUtil.isGenericSnapshot( genericVersion ) )
{ {
String baseVersion = StringUtils.substringBeforeLast( genericVersion, "-" + SNAPSHOT ); String baseVersion = StringUtils.substringBeforeLast( genericVersion, "-" + SNAPSHOT );
String prefix = info.id + "-" + baseVersion + "-"; String prefix = info.id + "-" + baseVersion + "-";
@ -722,7 +736,7 @@ public class ManagedDefaultRepositoryContent
else else
{ {
String prefix = info.id + "-" + genericVersion; String prefix = info.id + "-" + genericVersion;
if ( fileName.startsWith( prefix ) ) if ( fileName.startsWith( prefix + "-") )
{ {
info.version = genericVersion; info.version = genericVersion;
String classPostfix = StringUtils.removeStart( fileName, prefix ); String classPostfix = StringUtils.removeStart( fileName, prefix );
@ -737,6 +751,24 @@ public class ManagedDefaultRepositoryContent
info.classifier = ""; info.classifier = "";
info.remainder = classPostfix; info.remainder = classPostfix;
} }
} else if (fileName.startsWith(prefix + ".")) {
info.version = genericVersion;
info.remainder = StringUtils.removeStart( fileName, prefix );
info.classifier = "";
} else if (fileName.startsWith(info.id+"-")) {
String postFix = StringUtils.removeStart( fileName, info.id + "-" );
String versionPart = StringUtils.substringBefore( postFix, "." );
if (VersionUtil.isVersion(versionPart)) {
info.version = versionPart;
info.remainder = StringUtils.removeStart( postFix, versionPart );
info.classifier = "";
} else {
info.version = "";
info.classifier = "";
int dotPos = fileName.indexOf( "." );
info.remainder = fileName.substring( dotPos );
}
} }
else else
{ {
@ -747,10 +779,10 @@ public class ManagedDefaultRepositoryContent
else else
{ {
info.id = fileName; info.id = fileName;
info.version = "";
} }
log.debug( "Artifact does not match the version pattern {}", path ); log.debug( "Artifact does not match the version pattern {}", path );
info.artifactType = BaseArtifactTypes.UNKNOWN; info.artifactType = BaseArtifactTypes.UNKNOWN;
info.version = "";
info.classifier = ""; info.classifier = "";
info.remainder = StringUtils.substringAfterLast( fileName, "." ); info.remainder = StringUtils.substringAfterLast( fileName, "." );
} }
@ -1454,16 +1486,40 @@ public class ManagedDefaultRepositoryContent
@Override @Override
public ContentItem toItem( String path ) throws LayoutException public ContentItem toItem( String path ) throws LayoutException
{ {
StorageAsset asset = getRepository( ).getAsset( path ); StorageAsset asset = getRepository( ).getAsset( path );
if ( asset.isLeaf( ) ) ContentItem item = getItemFromPath( asset );
{ if (item instanceof DataItem) {
ItemSelector selector = getPathParser( ).toItemSelector( path ); Artifact artifact = adaptItem( Artifact.class, item );
return getItem( selector ); if (asset.getParent()==null) {
throw new LayoutException( "Path too short for maven artifact "+path );
} }
else String version = asset.getParent( ).getName( );
{ if (asset.getParent().getParent()==null) {
return getItemFromPath( asset ); throw new LayoutException( "Path too short for maven artifact " + path );
} }
String project = item.getAsset( ).getParent( ).getParent( ).getName( );
DataItem dataItem = (DataItem) item;
if (StringUtils.isEmpty( dataItem.getExtension())) {
throw new LayoutException( "Missing type on maven artifact" );
}
if (!project.equals(artifact.getId())) {
throw new LayoutException( "The maven artifact id "+artifact.getId() +" does not match the project id: " + project);
}
boolean versionIsGenericSnapshot = VersionUtil.isGenericSnapshot( version );
boolean artifactVersionIsSnapshot = VersionUtil.isSnapshot( artifact.getArtifactVersion() );
if ( versionIsGenericSnapshot && !artifactVersionIsSnapshot ) {
throw new LayoutException( "The maven artifact has no snapshot version in snapshot directory " + dataItem );
}
if ( !versionIsGenericSnapshot && artifactVersionIsSnapshot) {
throw new LayoutException( "The maven artifact version " + artifact.getArtifactVersion() + " is a snapshot version but inside a non snapshot directory " + version );
}
if ( !versionIsGenericSnapshot && !version.equals( artifact.getArtifactVersion() ) )
{
throw new LayoutException( "The maven artifact version " + artifact.getArtifactVersion() + " does not match the version directory " + version );
}
}
return item;
} }
@Override @Override

View File

@ -20,6 +20,7 @@ package org.apache.archiva.repository.maven.content;
import org.apache.archiva.model.ArtifactReference; import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.repository.*; import org.apache.archiva.repository.*;
import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.repository.content.PathParser; import org.apache.archiva.repository.content.PathParser;
import org.apache.archiva.repository.features.RepositoryFeature; import org.apache.archiva.repository.features.RepositoryFeature;
import org.apache.archiva.repository.metadata.base.MetadataTools; import org.apache.archiva.repository.metadata.base.MetadataTools;
@ -82,6 +83,12 @@ public class MavenRepositoryRequestInfo implements RepositoryRequestInfo
} }
} }
@Override
public ItemSelector toItemSelector( String requestPath ) throws LayoutException
{
return repository.getContent( ).toItemSelector( requestPath );
}
/** /**
* <p> * <p>
* Tests the path to see if it conforms to the expectations of a metadata request. * Tests the path to see if it conforms to the expectations of a metadata request.
@ -275,12 +282,18 @@ public class MavenRepositoryRequestInfo implements RepositoryRequestInfo
* Default layout is the only layout that can contain maven-metadata.xml files, and * Default layout is the only layout that can contain maven-metadata.xml files, and
* if the managedRepository is layout legacy, this request would never occur. * if the managedRepository is layout legacy, this request would never occur.
*/ */
if (requestedPath.startsWith( "/" )) {
return requestedPath; return requestedPath;
} else
{
return "/"+requestedPath;
}
} }
// Treat as an artifact reference. // Treat as an artifact reference.
ArtifactReference ref = toArtifactReference( referencedResource ); String adjustedPath = repository.getContent( ).toPath( repository.getContent( ).toItem( requestedPath ) );
String adjustedPath = repository.getContent().toPath( ref );
return adjustedPath + supportfile; return adjustedPath + supportfile;
} }

View File

@ -644,6 +644,98 @@ public class Maven2RepositoryStorage
} }
} }
@Override
public ItemSelector applyServerSideRelocation(ManagedRepository managedRepository, ItemSelector artifactSelector)
throws ProxyDownloadException {
if ("pom".equals(artifactSelector.getType())) {
return artifactSelector;
}
// Build the artifact POM reference
BaseRepositoryContentLayout layout;
try
{
layout = managedRepository.getContent( ).getLayout( BaseRepositoryContentLayout.class );
}
catch ( LayoutException e )
{
throw new ProxyDownloadException( "Could not set layout " + e.getMessage( ), new HashMap<>( ) );
}
RepositoryType repositoryType = managedRepository.getType();
if (!proxyRegistry.hasHandler(repositoryType)) {
throw new ProxyDownloadException("No proxy handler found for repository type " + repositoryType, new HashMap<>());
}
ItemSelector selector = ArchivaItemSelector.builder( )
.withNamespace( artifactSelector.getNamespace( ) )
.withProjectId( artifactSelector.getArtifactId( ) )
.withArtifactId( artifactSelector.getArtifactId( ) )
.withVersion( artifactSelector.getVersion( ) )
.withArtifactVersion( artifactSelector.getVersion( ) )
.withType( "pom" ).build( );
Artifact pom = layout.getArtifact( selector );
RepositoryProxyHandler proxyHandler = proxyRegistry.getHandler(repositoryType).get(0);
// Get the artifact POM from proxied repositories if needed
proxyHandler.fetchFromProxies(managedRepository, pom);
// Open and read the POM from the managed repo
if (!pom.exists()) {
return artifactSelector;
}
try {
// MavenXpp3Reader leaves the file open, so we need to close it ourselves.
Model model;
try (Reader reader = Channels.newReader(pom.getAsset().getReadChannel(), Charset.defaultCharset().name())) {
model = MAVEN_XPP_3_READER.read(reader);
}
DistributionManagement dist = model.getDistributionManagement();
if (dist != null) {
Relocation relocation = dist.getRelocation();
if (relocation != null) {
ArchivaItemSelector.Builder relocatedBuilder = ArchivaItemSelector.builder( );
// artifact is relocated : update the repositoryPath
if (relocation.getGroupId() != null) {
relocatedBuilder.withNamespace( relocation.getGroupId( ) );
} else {
relocatedBuilder.withNamespace( artifactSelector.getNamespace( ) );
}
if (relocation.getArtifactId() != null) {
relocatedBuilder.withArtifactId( relocation.getArtifactId( ) );
} else {
relocatedBuilder.withArtifactId( artifactSelector.getArtifactId( ) );
}
if (relocation.getVersion() != null)
{
relocatedBuilder.withVersion( relocation.getVersion( ) );
} else {
relocatedBuilder.withVersion( artifactSelector.getVersion( ) );
}
return relocatedBuilder.withArtifactVersion( artifactSelector.getArtifactVersion( ) )
.withClassifier( artifactSelector.getClassifier( ) )
.withType( artifactSelector.getType( ) )
.withProjectId( artifactSelector.getProjectId( ) )
.withExtension( artifactSelector.getExtension( ) )
.build( );
}
}
} catch (IOException e) {
// Unable to read POM : ignore.
} catch (XmlPullParserException e) {
// Invalid POM : ignore
}
return artifactSelector;
}
@Override @Override
public String getFilePath(String requestPath, org.apache.archiva.repository.ManagedRepository managedRepository) { public String getFilePath(String requestPath, org.apache.archiva.repository.ManagedRepository managedRepository) {

View File

@ -1014,7 +1014,7 @@ public class ManagedDefaultRepositoryContentTest
path = "/org/apache/maven/shared/maven-downloader/1.1/maven-downloader-1.1.jar"; path = "/org/apache/maven/shared/maven-downloader/1.1/maven-downloader-1.1.jar";
item = repoContent.toItem( path ); item = repoContent.toItem( path );
assertNotNull( item ); assertNotNull( item );
assertTrue( item instanceof Artifact ); assertTrue( item instanceof DataItem );
} }

View File

@ -72,6 +72,9 @@ public class MavenRepositoryRequestInfoTest
@Inject @Inject
FileLockManager fileLockManager; FileLockManager fileLockManager;
@Inject
MavenContentHelper mavenContentHelper;
private MavenRepositoryRequestInfo repoRequest; private MavenRepositoryRequestInfo repoRequest;
@ -109,6 +112,8 @@ public class MavenRepositoryRequestInfoTest
ManagedDefaultRepositoryContent repoContent = new ManagedDefaultRepositoryContent(repository, artifactMappingProviders, fileTypes, fileLockManager); ManagedDefaultRepositoryContent repoContent = new ManagedDefaultRepositoryContent(repository, artifactMappingProviders, fileTypes, fileLockManager);
//repoContent = (ManagedRepositoryContent) lookup( ManagedRepositoryContent.class, "default" ); //repoContent = (ManagedRepositoryContent) lookup( ManagedRepositoryContent.class, "default" );
repository.setContent(repoContent); repository.setContent(repoContent);
repoContent.setMavenContentHelper( mavenContentHelper );
repoRequest = new MavenRepositoryRequestInfo(repository); repoRequest = new MavenRepositoryRequestInfo(repository);
} }
@ -430,7 +435,7 @@ public class MavenRepositoryRequestInfoTest
ManagedRepositoryContent repository = createManagedRepo( "default" ); ManagedRepositoryContent repository = createManagedRepo( "default" );
// Test (artifact) default to default - dual extension // Test (artifact) default to default - dual extension
assertEquals( "org/project/example-presentation/3.2/example-presentation-3.2.xml.zip", assertEquals( "/org/project/example-presentation/3.2/example-presentation-3.2.xml.zip",
repoRequest.toNativePath( "org/project/example-presentation/3.2/example-presentation-3.2.xml.zip") ); repoRequest.toNativePath( "org/project/example-presentation/3.2/example-presentation-3.2.xml.zip") );
} }
@ -442,7 +447,7 @@ public class MavenRepositoryRequestInfoTest
ManagedRepositoryContent repository = createManagedRepo( "default" ); ManagedRepositoryContent repository = createManagedRepo( "default" );
// Test (metadata) default to default // Test (metadata) default to default
assertEquals( "org/apache/derby/derby/10.2.2.0/maven-metadata.xml.sha1", assertEquals( "/org/apache/derby/derby/10.2.2.0/maven-metadata.xml.sha1",
repoRequest.toNativePath( "org/apache/derby/derby/10.2.2.0/maven-metadata.xml.sha1") ); repoRequest.toNativePath( "org/apache/derby/derby/10.2.2.0/maven-metadata.xml.sha1") );
} }

View File

@ -31,6 +31,7 @@ import org.apache.archiva.components.taskqueue.TaskQueueException;
import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.metadata.audit.RepositoryListener; import org.apache.archiva.metadata.audit.RepositoryListener;
import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.scheduler.repository.model.RepositoryArchivaTaskScheduler; import org.apache.archiva.scheduler.repository.model.RepositoryArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.model.RepositoryTask; import org.apache.archiva.scheduler.repository.model.RepositoryTask;
import org.apache.archiva.xml.XMLException; import org.apache.archiva.xml.XMLException;
@ -108,6 +109,12 @@ public class MockBeanServices
} }
@Override
public ItemSelector applyServerSideRelocation( ManagedRepository managedRepository, ItemSelector selector ) throws ProxyDownloadException
{
return null;
}
@Override @Override
public void deleteArtifact( MetadataRepository metadataRepository, String repositoryId, String namespace, public void deleteArtifact( MetadataRepository metadataRepository, String repositoryId, String namespace,

View File

@ -68,6 +68,7 @@ import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.RepositoryRequestInfo; import org.apache.archiva.repository.RepositoryRequestInfo;
import org.apache.archiva.repository.content.Artifact; import org.apache.archiva.repository.content.Artifact;
import org.apache.archiva.repository.content.ContentItem; import org.apache.archiva.repository.content.ContentItem;
import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.repository.storage.fs.FilesystemStorage; import org.apache.archiva.repository.storage.fs.FilesystemStorage;
import org.apache.archiva.repository.storage.StorageAsset; import org.apache.archiva.repository.storage.StorageAsset;
import org.apache.archiva.metadata.audit.AuditListener; import org.apache.archiva.metadata.audit.AuditListener;
@ -791,22 +792,23 @@ public class ArchivaDavResourceFactory
try try
{ {
// Get the artifact reference in a layout neutral way. // Get the artifact reference in a layout neutral way.
ArtifactReference artifact = repositoryRequestInfo.toArtifactReference( path ); // ArtifactReference artifact = repositoryRequestInfo.toArtifactReference( path );
ItemSelector selector = repositoryRequestInfo.toItemSelector( path );
if ( artifact != null ) if ( selector != null )
{ {
String repositoryLayout = managedRepository.getLayout(); String repositoryLayout = managedRepository.getLayout();
RepositoryStorage repositoryStorage = RepositoryStorage repositoryStorage =
this.applicationContext.getBean( "repositoryStorage#" + repositoryLayout, RepositoryStorage.class ); this.applicationContext.getBean( "repositoryStorage#" + repositoryLayout, RepositoryStorage.class );
repositoryStorage.applyServerSideRelocation( managedRepository, artifact ); selector = repositoryStorage.applyServerSideRelocation( managedRepository, selector );
StorageAsset proxiedFile = proxyHandler.fetchFromProxies( managedRepository, artifact ); StorageAsset proxiedFile = proxyHandler.fetchFromProxies( managedRepository, selector );
resource.setPath( managedRepository.getContent().toPath( artifact ) ); resource.setPath( managedRepository.getContent().toPath( selector ) );
log.debug( "Proxied artifact '{}:{}:{}'", artifact.getGroupId(), artifact.getArtifactId(), log.debug( "Proxied artifact '{}:{}:{}:{}'", selector.getNamespace(), selector.getArtifactId(),
artifact.getVersion() ); selector.getVersion(), selector.getArtifactVersion() );
return ( proxiedFile != null ); return ( proxiedFile != null );
} }

View File

@ -27,6 +27,7 @@ import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.policies.ProxyDownloadException; import org.apache.archiva.policies.ProxyDownloadException;
import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.xml.XMLException; import org.apache.archiva.xml.XMLException;
import java.io.IOException; import java.io.IOException;
@ -74,6 +75,21 @@ public interface RepositoryStorage
void applyServerSideRelocation( ManagedRepository managedRepository, ArtifactReference artifact ) void applyServerSideRelocation( ManagedRepository managedRepository, ArtifactReference artifact )
throws ProxyDownloadException; throws ProxyDownloadException;
/**
* A relocation capable client will request the POM prior to the artifact, and will then read meta-data and do
* client side relocation. A simplier client (like maven 1) will only request the artifact and not use the
* metadatas.
* <p>
* For such clients, archiva does server-side relocation by reading itself the &lt;relocation&gt; element in
* metadatas and serving the expected artifact.
* @param managedRepository the used managed repository
* @param artifact the artifact reference
* @throws org.apache.archiva.policies.ProxyDownloadException
*/
ItemSelector applyServerSideRelocation( ManagedRepository managedRepository, ItemSelector selector )
throws ProxyDownloadException;
/** /**
* add an other method to evaluate real path as when receiving -SNAPSHOT (for maven storage) * add an other method to evaluate real path as when receiving -SNAPSHOT (for maven storage)
* request redirect to the last build * request redirect to the last build

View File

@ -37,6 +37,7 @@ import org.apache.archiva.policies.ProxyDownloadException;
import org.apache.archiva.repository.ManagedRepositoryContent; import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.ManagedRepository;
import org.apache.archiva.metadata.audit.RepositoryListener; import org.apache.archiva.metadata.audit.RepositoryListener;
import org.apache.archiva.repository.content.ItemSelector;
import org.apache.archiva.xml.XMLException; import org.apache.archiva.xml.XMLException;
import java.io.IOException; import java.io.IOException;
@ -112,6 +113,12 @@ public class MockRepositoryStorage
} }
@Override
public ItemSelector applyServerSideRelocation( ManagedRepository managedRepository, ItemSelector selector ) throws ProxyDownloadException
{
return null;
}
@Override @Override
public String getFilePath( String requestPath, org.apache.archiva.repository.ManagedRepository managedRepository ) public String getFilePath( String requestPath, org.apache.archiva.repository.ManagedRepository managedRepository )
{ {