[MNG-1301] remove the problem reports dependency on the repository layer, start to migrate path parsing into metadata API

git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@920649 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Brett Porter 2010-03-09 04:24:32 +00:00
parent 49eab5d3da
commit af2a929978
43 changed files with 829 additions and 332 deletions

View File

@ -18,7 +18,8 @@
~ under the License. ~ under the License.
--> -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.apache.archiva</groupId> <groupId>org.apache.archiva</groupId>
@ -42,17 +43,21 @@
<groupId>org.apache.archiva</groupId> <groupId>org.apache.archiva</groupId>
<artifactId>archiva-repository-layer</artifactId> <artifactId>archiva-repository-layer</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>metadata-repository-api</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-digest</artifactId> <artifactId>plexus-digest</artifactId>
</dependency> </dependency>
<!-- test dependencies -->
<dependency> <dependency>
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-spring</artifactId> <artifactId>plexus-spring</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- test dependencies -->
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId> <artifactId>slf4j-simple</artifactId>

View File

@ -19,18 +19,18 @@ package org.apache.maven.archiva.consumers.core.repository;
* under the License. * under the License.
*/ */
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.audit.AuditEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.audit.AuditEvent;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Base class for all repository purge tasks. * Base class for all repository purge tasks.
* *
@ -67,6 +67,7 @@ public abstract class AbstractRepositoryPurge
{ {
File artifactFile = repository.toFile( reference ); File artifactFile = repository.toFile( reference );
// TODO: looks incomplete, might not delete related metadata?
for ( RepositoryListener listener : listeners ) for ( RepositoryListener listener : listeners )
{ {
listener.deleteArtifact( repository.getId(), reference.getGroupId(), reference.getArtifactId(), listener.deleteArtifact( repository.getId(), reference.getGroupId(), reference.getArtifactId(),

View File

@ -19,12 +19,7 @@ package org.apache.maven.archiva.consumers.core.repository;
* under the License. * under the License.
*/ */
import java.io.File; import org.apache.archiva.repository.events.RepositoryListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.maven.archiva.common.utils.VersionComparator; import org.apache.maven.archiva.common.utils.VersionComparator;
import org.apache.maven.archiva.common.utils.VersionUtil; import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ArchivaConfiguration;
@ -38,11 +33,16 @@ import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.RepositoryContentFactory; import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException; import org.apache.maven.archiva.repository.RepositoryException;
import org.apache.maven.archiva.repository.RepositoryNotFoundException; import org.apache.maven.archiva.repository.RepositoryNotFoundException;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.repository.layout.LayoutException; import org.apache.maven.archiva.repository.layout.LayoutException;
import org.apache.maven.archiva.repository.metadata.MetadataTools; import org.apache.maven.archiva.repository.metadata.MetadataTools;
import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException; import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** /**
* <p> * <p>
* This will look in a single managed repository, and purge any snapshots that are present * This will look in a single managed repository, and purge any snapshots that are present
@ -174,7 +174,7 @@ public class CleanupReleasedSnapshotsRepositoryPurge
versionRef.setVersion( version ); versionRef.setVersion( version );
repository.deleteVersion( versionRef ); repository.deleteVersion( versionRef );
// TODO: looks incomplete, might not delete related artifacts? // TODO: looks incomplete, might not delete related metadata?
for ( RepositoryListener listener : listeners ) for ( RepositoryListener listener : listeners )
{ {
listener.deleteArtifact( repository.getId(), artifact.getGroupId(), artifact.getArtifactId(), listener.deleteArtifact( repository.getId(), artifact.getGroupId(), artifact.getArtifactId(),

View File

@ -19,6 +19,16 @@ package org.apache.maven.archiva.consumers.core.repository;
* under the License. * under the License.
*/ */
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.commons.lang.time.DateUtils;
import org.apache.maven.archiva.common.utils.VersionComparator;
import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.VersionedReference;
import org.apache.maven.archiva.repository.ContentNotFoundException;
import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.layout.LayoutException;
import java.io.File; import java.io.File;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -30,16 +40,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import org.apache.commons.lang.time.DateUtils;
import org.apache.maven.archiva.common.utils.VersionComparator;
import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.VersionedReference;
import org.apache.maven.archiva.repository.ContentNotFoundException;
import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.repository.layout.LayoutException;
/** /**
* Purge from repository all snapshots older than the specified days in the repository configuration. * Purge from repository all snapshots older than the specified days in the repository configuration.
* *

View File

@ -19,11 +19,7 @@ package org.apache.maven.archiva.consumers.core.repository;
* under the License. * under the License.
*/ */
import java.util.ArrayList; import org.apache.archiva.repository.events.RepositoryListener;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.ConfigurationNames; import org.apache.maven.archiva.configuration.ConfigurationNames;
import org.apache.maven.archiva.configuration.FileTypes; import org.apache.maven.archiva.configuration.FileTypes;
@ -35,13 +31,17 @@ import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.RepositoryContentFactory; import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException; import org.apache.maven.archiva.repository.RepositoryException;
import org.apache.maven.archiva.repository.RepositoryNotFoundException; import org.apache.maven.archiva.repository.RepositoryNotFoundException;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.repository.metadata.MetadataTools; import org.apache.maven.archiva.repository.metadata.MetadataTools;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.registry.Registry; import org.codehaus.plexus.registry.Registry;
import org.codehaus.plexus.registry.RegistryListener; import org.codehaus.plexus.registry.RegistryListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/** /**
* Consumer for removing old snapshots in the repository based on the criteria * Consumer for removing old snapshots in the repository based on the criteria
* specified by the user. * specified by the user.
@ -94,7 +94,7 @@ public class RepositoryPurgeConsumer
private boolean deleteReleasedSnapshots; private boolean deleteReleasedSnapshots;
/** @plexus.requirement role="org.apache.maven.archiva.repository.events.RepositoryListener" */ /** @plexus.requirement role="org.apache.archiva.repository.events.RepositoryListener" */
private List<RepositoryListener> listeners = Collections.emptyList(); private List<RepositoryListener> listeners = Collections.emptyList();
public String getId() public String getId()

View File

@ -19,21 +19,21 @@ package org.apache.maven.archiva.consumers.core.repository;
* under the License. * under the License.
*/ */
import java.io.File; import org.apache.archiva.repository.events.RepositoryListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.apache.maven.archiva.common.utils.VersionComparator; import org.apache.maven.archiva.common.utils.VersionComparator;
import org.apache.maven.archiva.common.utils.VersionUtil; import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.VersionedReference; import org.apache.maven.archiva.model.VersionedReference;
import org.apache.maven.archiva.repository.ContentNotFoundException; import org.apache.maven.archiva.repository.ContentNotFoundException;
import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.repository.layout.LayoutException; import org.apache.maven.archiva.repository.layout.LayoutException;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/** /**
* Purge the repository by retention count. Retain only the specified number of snapshots. * Purge the repository by retention count. Retain only the specified number of snapshots.
* *

View File

@ -19,17 +19,17 @@ package org.apache.maven.archiva.consumers.core.repository;
* under the License. * under the License.
*/ */
import java.io.File; import org.apache.archiva.repository.events.RepositoryListener;
import java.io.IOException;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
import org.apache.maven.archiva.model.ArchivaArtifact; import org.apache.maven.archiva.model.ArchivaArtifact;
import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.codehaus.plexus.spring.PlexusInSpringTestCase; import org.codehaus.plexus.spring.PlexusInSpringTestCase;
import org.easymock.MockControl; import org.easymock.MockControl;
import java.io.File;
import java.io.IOException;
/** /**
*/ */
public abstract class AbstractRepositoryPurgeTest public abstract class AbstractRepositoryPurgeTest

View File

@ -19,18 +19,18 @@ package org.apache.maven.archiva.consumers.core.repository;
* under the License. * under the License.
*/ */
import java.io.File; import org.apache.archiva.repository.events.RepositoryListener;
import java.util.Collections;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.Configuration; import org.apache.maven.archiva.configuration.Configuration;
import org.apache.maven.archiva.repository.RepositoryContentFactory; import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.repository.metadata.MetadataTools; import org.apache.maven.archiva.repository.metadata.MetadataTools;
import org.custommonkey.xmlunit.XMLAssert; import org.custommonkey.xmlunit.XMLAssert;
import org.easymock.MockControl; import org.easymock.MockControl;
import java.io.File;
import java.util.Collections;
/** /**
*/ */

View File

@ -71,6 +71,16 @@
<groupId>org.apache.archiva</groupId> <groupId>org.apache.archiva</groupId>
<artifactId>metadata-model</artifactId> <artifactId>metadata-model</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>maven2-repository</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.archiva</groupId>
<artifactId>problem-reports</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>

View File

@ -19,6 +19,9 @@ package org.apache.maven.archiva.repository.content;
* under the License. * under the License.
*/ */
import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
import org.apache.archiva.metadata.repository.storage.maven2.Maven2RepositoryPathTranslator;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.common.utils.VersionUtil; import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.ArtifactReference;
@ -27,12 +30,16 @@ import org.apache.maven.archiva.repository.layout.LayoutException;
/** /**
* DefaultPathParser is a parser for maven 2 (default layout) paths to ArtifactReference. * DefaultPathParser is a parser for maven 2 (default layout) paths to ArtifactReference.
* *
* TODO: remove in favour of path translator, this is just delegating for the most part
*
* @version $Id$ * @version $Id$
*/ */
public class DefaultPathParser implements PathParser public class DefaultPathParser implements PathParser
{ {
private static final String INVALID_ARTIFACT_PATH = "Invalid path to Artifact: "; private static final String INVALID_ARTIFACT_PATH = "Invalid path to Artifact: ";
private RepositoryPathTranslator pathTranslator = new Maven2RepositoryPathTranslator();
/** /**
* {@inheritDoc} * {@inheritDoc}
* @see org.apache.maven.archiva.repository.content.PathParser#toArtifactReference(java.lang.String) * @see org.apache.maven.archiva.repository.content.PathParser#toArtifactReference(java.lang.String)
@ -45,78 +52,32 @@ public class DefaultPathParser implements PathParser
throw new LayoutException( "Unable to convert blank path." ); throw new LayoutException( "Unable to convert blank path." );
} }
ArtifactReference artifact = new ArtifactReference(); ArtifactMetadata metadata;
String normalizedPath = StringUtils.replace( path, "\\", "/" );
String pathParts[] = StringUtils.split( normalizedPath, '/' );
/* Minimum parts.
*
* path = "commons-lang/commons-lang/2.1/commons-lang-2.1.jar"
* path[0] = "commons-lang"; // The Group ID
* path[1] = "commons-lang"; // The Artifact ID
* path[2] = "2.1"; // The Version
* path[3] = "commons-lang-2.1.jar" // The filename.
*/
if ( pathParts.length < 4 )
{
// Illegal Path Parts Length.
throw new LayoutException( "Not enough parts to the path [" + path
+ "] to construct an ArchivaArtifact from. (Requires at least 4 parts)" );
}
// Maven 2.x path.
int partCount = pathParts.length;
int filenamePos = partCount - 1;
int baseVersionPos = partCount - 2;
int artifactIdPos = partCount - 3;
int groupIdPos = partCount - 4;
// Second to last is the baseVersion (the directory version)
String baseVersion = pathParts[baseVersionPos];
// Third to last is the artifact Id.
artifact.setArtifactId( pathParts[artifactIdPos] );
// Remaining pieces are the groupId.
for ( int i = 0; i <= groupIdPos; i++ )
{
if ( i == 0 )
{
artifact.setGroupId( pathParts[i] );
}
else
{
artifact.setGroupId( artifact.getGroupId() + "." + pathParts[i] );
}
}
try try
{ {
// Last part is the filename metadata = pathTranslator.getArtifactForPath( null, path );
String filename = pathParts[filenamePos]; }
catch ( IllegalArgumentException e )
// Now we need to parse the filename to get the artifact version Id.
if ( StringUtils.isBlank( filename ) )
{ {
throw new IllegalArgumentException( INVALID_ARTIFACT_PATH + "Unable to split blank filename." ); throw new LayoutException( e.getMessage(), e );
} }
ArtifactReference artifact = new ArtifactReference();
artifact.setGroupId( metadata.getNamespace() );
artifact.setArtifactId( metadata.getProject() );
artifact.setVersion( metadata.getVersion() );
// TODO: use Maven facet instead
String filename = metadata.getId();
FilenameParser parser = new FilenameParser( filename ); FilenameParser parser = new FilenameParser( filename );
// Expect the filename to start with the artifactId.
artifact.setArtifactId( parser.expect( artifact.getArtifactId() ) ); artifact.setArtifactId( parser.expect( artifact.getArtifactId() ) );
if ( artifact.getArtifactId() == null ) if ( artifact.getArtifactId() == null )
{ {
throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid, " throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid, "
+ "should start with artifactId as stated in path." ); + "should start with artifactId as stated in path." );
} }
String baseVersion = VersionUtil.getBaseVersion( metadata.getVersion() );
// Process the version.
artifact.setVersion( parser.expect( baseVersion ) ); artifact.setVersion( parser.expect( baseVersion ) );
if ( artifact.getVersion() == null ) if ( artifact.getVersion() == null )
{ {
// We working with a snapshot? // We working with a snapshot?
@ -135,8 +96,6 @@ public class DefaultPathParser implements PathParser
+ "expected version as stated in path." ); + "expected version as stated in path." );
} }
} }
// Do we have a classifier?
switch(parser.seperator()) switch(parser.seperator())
{ {
case '-': case '-':
@ -161,18 +120,11 @@ public class DefaultPathParser implements PathParser
artifact.setType( type ); artifact.setType( type );
break; break;
} }
// Special case for maven plugins
if ( StringUtils.equals( "jar", artifact.getType() ) && if ( StringUtils.equals( "jar", artifact.getType() ) &&
ArtifactExtensionMapping.isMavenPlugin( artifact.getArtifactId() ) ) ArtifactExtensionMapping.isMavenPlugin( artifact.getArtifactId() ) )
{ {
artifact.setType( ArtifactExtensionMapping.MAVEN_PLUGIN ); artifact.setType( ArtifactExtensionMapping.MAVEN_PLUGIN );
} }
}
catch ( LayoutException e )
{
throw e;
}
// Sanity Checks. // Sanity Checks.
@ -187,16 +139,6 @@ public class DefaultPathParser implements PathParser
+ filenameBaseVersion ); + filenameBaseVersion );
} }
} }
else
{
// Non SNAPSHOT rules.
// Do we pass the simple test?
if ( !StringUtils.equals( baseVersion, artifact.getVersion() ) )
{
throw new LayoutException( "Invalid artifact: version declared in directory path does"
+ " not match what was found in the artifact filename." );
}
}
return artifact; return artifact;
} }

View File

@ -19,11 +19,6 @@ package org.apache.maven.archiva.repository.content;
* under the License. * under the License.
*/ */
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.maven.archiva.common.utils.PathUtil; import org.apache.maven.archiva.common.utils.PathUtil;
import org.apache.maven.archiva.configuration.FileTypes; import org.apache.maven.archiva.configuration.FileTypes;
@ -36,6 +31,11 @@ import org.apache.maven.archiva.repository.ContentNotFoundException;
import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.layout.LayoutException; import org.apache.maven.archiva.repository.layout.LayoutException;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/** /**
* ManagedDefaultRepositoryContent * ManagedDefaultRepositoryContent
* *
@ -332,9 +332,9 @@ public class ManagedDefaultRepositoryContent
public ArtifactReference toArtifactReference( String path ) public ArtifactReference toArtifactReference( String path )
throws LayoutException throws LayoutException
{ {
if ( ( path != null ) && path.startsWith( repository.getLocation() ) ) if ( ( path != null ) && path.startsWith( repository.getLocation() ) && repository.getLocation().length() > 0 )
{ {
return super.toArtifactReference( path.substring( repository.getLocation().length() ) ); return super.toArtifactReference( path.substring( repository.getLocation().length() + 1 ) );
} }
return super.toArtifactReference( path ); return super.toArtifactReference( path );

View File

@ -195,6 +195,19 @@ public class DefaultPathParserTest
assertLayout( path, groupId, artifactId, version, classifier, type ); assertLayout( path, groupId, artifactId, version, classifier, type );
} }
public void testWindowsPathSeparator()
throws LayoutException
{
String groupId = "commons-lang";
String artifactId = "commons-lang";
String version = "2.1";
String classifier = null;
String type = "jar";
String path = "commons-lang\\commons-lang/2.1\\commons-lang-2.1.jar";
assertLayout( path, groupId, artifactId, version, classifier, type );
}
/** /**
* [MRM-486] Can not deploy artifact test.maven-arch:test-arch due to "No ArtifactID Detected" * [MRM-486] Can not deploy artifact test.maven-arch:test-arch due to "No ArtifactID Detected"
*/ */

View File

@ -1,4 +1,4 @@
package org.apache.maven.archiva.repository.events; package org.apache.archiva.web.spring;
/* /*
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -19,13 +19,14 @@ package org.apache.maven.archiva.repository.events;
* under the License. * under the License.
*/ */
import java.util.List; import org.apache.archiva.repository.events.RepositoryListener;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import java.util.List;
/** /**
* @todo though we will eventually remove this altogether, an interim cleanup would be to genericise this * @todo though we will eventually remove this altogether, an interim cleanup would be to genericise this
* and replace the calls in RepositoryContentConsumers with calls to the same thing * and replace the calls in RepositoryContentConsumers with calls to the same thing

View File

@ -19,23 +19,13 @@ package org.apache.maven.archiva.web.action;
* under the License. * under the License.
*/ */
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import com.opensymphony.xwork2.Preparable; import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.Validateable; import com.opensymphony.xwork2.Validateable;
import org.apache.archiva.checksum.ChecksumAlgorithm; import org.apache.archiva.checksum.ChecksumAlgorithm;
import org.apache.archiva.checksum.ChecksummedFile; import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.metadata.model.ArtifactMetadata; import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository; import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.common.utils.VersionComparator; import org.apache.maven.archiva.common.utils.VersionComparator;
import org.apache.maven.archiva.common.utils.VersionUtil; import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ArchivaConfiguration;
@ -49,7 +39,6 @@ import org.apache.maven.archiva.repository.RepositoryException;
import org.apache.maven.archiva.repository.RepositoryNotFoundException; import org.apache.maven.archiva.repository.RepositoryNotFoundException;
import org.apache.maven.archiva.repository.audit.AuditEvent; import org.apache.maven.archiva.repository.audit.AuditEvent;
import org.apache.maven.archiva.repository.audit.Auditable; import org.apache.maven.archiva.repository.audit.Auditable;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.repository.metadata.MetadataTools; import org.apache.maven.archiva.repository.metadata.MetadataTools;
import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException; import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader; import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
@ -59,6 +48,17 @@ import org.apache.maven.archiva.security.ArchivaSecurityException;
import org.apache.maven.archiva.security.PrincipalNotFoundException; import org.apache.maven.archiva.security.PrincipalNotFoundException;
import org.apache.maven.archiva.security.UserRepositories; import org.apache.maven.archiva.security.UserRepositories;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
/** /**
* Delete an artifact. Metadata will be updated if one exists, otherwise it would be created. * Delete an artifact. Metadata will be updated if one exists, otherwise it would be created.
* *
@ -109,7 +109,7 @@ public class DeleteArtifactAction
private RepositoryContentFactory repositoryFactory; private RepositoryContentFactory repositoryFactory;
/** /**
* @plexus.requirement role="org.apache.maven.archiva.repository.events.RepositoryListener" * @plexus.requirement role="org.apache.archiva.repository.events.RepositoryListener"
*/ */
private List<RepositoryListener> listeners; private List<RepositoryListener> listeners;

View File

@ -55,7 +55,7 @@
<constructor-arg ref="metadataRepository"/> <constructor-arg ref="metadataRepository"/>
<constructor-arg ref="archivaTaskScheduler#repository"/> <constructor-arg ref="archivaTaskScheduler#repository"/>
<constructor-arg> <constructor-arg>
<bean class="org.apache.maven.archiva.repository.events.RepositoryListenerFactoryBean" /> <bean class="org.apache.archiva.web.spring.RepositoryListenerFactoryBean" />
</constructor-arg> </constructor-arg>
</bean> </bean>

View File

@ -19,12 +19,9 @@ package org.apache.archiva.web.xmlrpc.services;
* under the License. * under the License.
*/ */
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.archiva.metadata.model.ArtifactMetadata; import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository; import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.repository.scanner.RepositoryContentConsumers; import org.apache.archiva.repository.scanner.RepositoryContentConsumers;
import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler; import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.RepositoryTask; import org.apache.archiva.scheduler.repository.RepositoryTask;
@ -45,11 +42,14 @@ import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.RepositoryContentFactory; import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException; import org.apache.maven.archiva.repository.RepositoryException;
import org.apache.maven.archiva.repository.RepositoryNotFoundException; import org.apache.maven.archiva.repository.RepositoryNotFoundException;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.codehaus.plexus.registry.RegistryException; import org.codehaus.plexus.registry.RegistryException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/** /**
* AdministrationServiceImpl * AdministrationServiceImpl
* *

View File

@ -19,14 +19,9 @@ package org.apache.archiva.web.xmlrpc.services;
* under the License. * under the License.
*/ */
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.archiva.metadata.model.ArtifactMetadata; import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository; import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.repository.scanner.RepositoryContentConsumers; import org.apache.archiva.repository.scanner.RepositoryContentConsumers;
import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler; import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.RepositoryTask; import org.apache.archiva.scheduler.repository.RepositoryTask;
@ -47,12 +42,17 @@ import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.content.ManagedDefaultRepositoryContent; import org.apache.maven.archiva.repository.content.ManagedDefaultRepositoryContent;
import org.apache.maven.archiva.repository.content.ManagedLegacyRepositoryContent; import org.apache.maven.archiva.repository.content.ManagedLegacyRepositoryContent;
import org.apache.maven.archiva.repository.content.PathParser; import org.apache.maven.archiva.repository.content.PathParser;
import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.repository.layout.LayoutException; import org.apache.maven.archiva.repository.layout.LayoutException;
import org.codehaus.plexus.spring.PlexusInSpringTestCase; import org.codehaus.plexus.spring.PlexusInSpringTestCase;
import org.easymock.MockControl; import org.easymock.MockControl;
import org.easymock.classextension.MockClassControl; import org.easymock.classextension.MockClassControl;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** /**
* AdministrationServiceImplTest * AdministrationServiceImplTest
* *

View File

@ -19,6 +19,8 @@ package org.apache.archiva.metadata.repository.storage;
* under the License. * under the License.
*/ */
import org.apache.archiva.metadata.model.ArtifactMetadata;
import java.io.File; import java.io.File;
public interface RepositoryPathTranslator public interface RepositoryPathTranslator
@ -32,4 +34,9 @@ public interface RepositoryPathTranslator
File toFile( File basedir, String namespace ); File toFile( File basedir, String namespace );
File toFile( File basedir, String namespace, String projectId, String projectVersion ); File toFile( File basedir, String namespace, String projectId, String projectVersion );
ArtifactMetadata getArtifactForPath( String repoId, String relativePath );
ArtifactMetadata getArtifactFromId( String repoId, String namespace, String projectId, String projectVersion,
String id );
} }

View File

@ -1,4 +1,4 @@
package org.apache.maven.archiva.repository.events; package org.apache.archiva.repository.events;
/* /*
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -29,5 +29,6 @@
<modules> <modules>
<module>metadata-model</module> <module>metadata-model</module>
<module>metadata-repository-api</module> <module>metadata-repository-api</module>
<module>test-repository</module>
</modules> </modules>
</project> </project>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>metadata</artifactId>
<groupId>org.apache.archiva</groupId>
<version>1.4-SNAPSHOT</version>
</parent>
<artifactId>test-repository</artifactId>
<name>Archiva Repository for Testing</name>
</project>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.example.test</groupId>
<artifactId>test-artifact</artifactId>
<version>1.0-SNAPSHOT</version>
<versioning>
<snapshot>
<timestamp>20100308.230825</timestamp>
<buildNumber>1</buildNumber>
</snapshot>
<lastUpdated>20100308230825</lastUpdated>
</versioning>
</metadata>

View File

@ -0,0 +1,24 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.test</groupId>
<artifactId>test-artifact</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>test-artifact</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>test-repo</id>
<url>file:${basedir}/repository</url>
</repository>
</distributionManagement>
</project>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.example.test</groupId>
<artifactId>test-artifact</artifactId>
<version>1.0-SNAPSHOT</version>
<versioning>
<versions>
<version>1.0-SNAPSHOT</version>
</versions>
<lastUpdated>20100308230825</lastUpdated>
</versioning>
</metadata>

View File

@ -0,0 +1 @@
d59d588343d61fd7d838984a0daa4aaa2546bf9d

View File

@ -60,8 +60,6 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* @plexus.component role="org.apache.archiva.metadata.repository.storage.StorageMetadataResolver" role-hint="maven2" * @plexus.component role="org.apache.archiva.metadata.repository.storage.StorageMetadataResolver" role-hint="maven2"
@ -114,6 +112,7 @@ public class Maven2RepositoryMetadataResolver
String projectVersion ) String projectVersion )
throws MetadataResolutionException throws MetadataResolutionException
{ {
// Remove problems associated with this version, since we'll be re-adding any that still exist
// TODO: an event mechanism would remove coupling to the problem reporting plugin // TODO: an event mechanism would remove coupling to the problem reporting plugin
// TODO: this removes all problems - do we need something that just removes the problems created by this resolver? // TODO: this removes all problems - do we need something that just removes the problems created by this resolver?
String name = RepositoryProblemFacet.createName( namespace, projectId, projectVersion, null ); String name = RepositoryProblemFacet.createName( namespace, projectId, projectVersion, null );
@ -490,11 +489,18 @@ public class Maven2RepositoryMetadataResolver
{ {
for ( File file : files ) for ( File file : files )
{ {
ArtifactMetadata metadata = new ArtifactMetadata(); ArtifactMetadata metadata = getArtifactFromFile( repoId, namespace, projectId, projectVersion, file );
metadata.setId( file.getName() ); artifacts.add( metadata );
metadata.setProject( projectId ); }
metadata.setNamespace( namespace ); }
metadata.setRepositoryId( repoId ); return artifacts;
}
private ArtifactMetadata getArtifactFromFile( String repoId, String namespace, String projectId,
String projectVersion, File file )
{
ArtifactMetadata metadata = pathTranslator.getArtifactFromId( repoId, namespace, projectId, projectVersion, file.getName() );
metadata.setWhenGathered( new Date() ); metadata.setWhenGathered( new Date() );
metadata.setFileLastModified( file.lastModified() ); metadata.setFileLastModified( file.lastModified() );
ChecksummedFile checksummedFile = new ChecksummedFile( file ); ChecksummedFile checksummedFile = new ChecksummedFile( file );
@ -516,26 +522,7 @@ public class Maven2RepositoryMetadataResolver
} }
metadata.setSize( file.length() ); metadata.setSize( file.length() );
// TODO: very crude, migrate the functionality from the repository-layer here return metadata;
if ( VersionUtil.isGenericSnapshot( projectVersion ) )
{
String mainVersion = projectVersion.substring( 0, projectVersion.length() -
8 ); // 8 is length of "SNAPSHOT"
Matcher m = Pattern.compile(
projectId + "-" + mainVersion + "([0-9]{8}.[0-9]{6}-[0-9]+).*" ).matcher( file.getName() );
m.matches();
String version = mainVersion + m.group( 1 );
metadata.setVersion( version );
}
else
{
metadata.setVersion( projectVersion );
}
artifacts.add( metadata );
}
}
return artifacts;
} }
private boolean isProject( File dir, Filter<String> filter ) private boolean isProject( File dir, Filter<String> filter )

View File

@ -1,8 +1,14 @@
package org.apache.archiva.metadata.repository.storage.maven2; package org.apache.archiva.metadata.repository.storage.maven2;
import java.io.File; import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator; import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.common.utils.VersionUtil;
import java.io.File;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/* /*
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -113,4 +119,141 @@ public class Maven2RepositoryPathTranslator
{ {
return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR ); return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );
} }
private static String parseTimestampedVersionFromId( String projectId, String projectVersion, String id )
{
String mainVersion = projectVersion.substring( 0, projectVersion.length() - 8 ); // 8 is length of "SNAPSHOT"
if ( mainVersion.length() == 0 )
{
throw new IllegalArgumentException(
"Timestamped snapshots must contain the main version, filename was '" + id + "'" );
}
Matcher m = Pattern.compile( projectId + "-" + mainVersion + "([0-9]{8}.[0-9]{6}-[0-9]+).*" ).matcher( id );
m.matches();
return mainVersion + m.group( 1 );
}
public ArtifactMetadata getArtifactFromId( String repoId, String namespace, String projectId, String projectVersion,
String id )
{
ArtifactMetadata metadata = new ArtifactMetadata();
metadata.setId( id );
metadata.setProject( projectId );
metadata.setNamespace( namespace );
metadata.setRepositoryId( repoId );
if ( VersionUtil.isGenericSnapshot( projectVersion ) )
{
String version = parseTimestampedVersionFromId( projectId, projectVersion, id );
metadata.setVersion( version );
}
else
{
metadata.setVersion( projectVersion );
}
return metadata;
}
public ArtifactMetadata getArtifactForPath( String repoId, String relativePath )
{
String[] parts = relativePath.replace( '\\', '/' ).split( "/" );
int len = parts.length;
if ( len < 4 )
{
throw new IllegalArgumentException(
"Not a valid artifact path in a Maven 2 repository, not enough directories: " + relativePath );
}
String id = parts[--len];
String baseVersion = parts[--len];
String artifactId = parts[--len];
String groupId = StringUtils.join( Arrays.copyOfRange( parts, 0, len ), '.' );
if ( !id.startsWith( artifactId + "-" ) )
{
throw new IllegalArgumentException( "Not a valid artifact path in a Maven 2 repository, filename '" + id +
"' doesn't start with artifact ID '" + artifactId + "'" );
}
int index = artifactId.length() + 1;
String version;
if ( id.substring( index ).startsWith( baseVersion ) && !VersionUtil.isUniqueSnapshot( baseVersion ) )
{
// non-snapshot versions, or non-timestamped snapshot versions
version = baseVersion;
}
else if ( VersionUtil.isGenericSnapshot( baseVersion ) )
{
// timestamped snapshots
try
{
version = parseTimestampedVersionFromId( artifactId, baseVersion, id );
}
catch ( IllegalStateException e )
{
throw new IllegalArgumentException(
"Not a valid artifact path in a Maven 2 repository, filename '" + id +
"' doesn't contain a timestamped version matching snapshot '" + baseVersion + "'" );
}
}
else
{
// invalid
throw new IllegalArgumentException(
"Not a valid artifact path in a Maven 2 repository, filename '" + id + "' doesn't contain version '" +
baseVersion + "'" );
}
String classifier;
String ext;
index += version.length();
if ( index == id.length() )
{
// no classifier or extension
classifier = null;
ext = null;
}
else
{
char c = id.charAt( index );
if ( c == '-' )
{
// classifier up until last '.'
int extIndex = id.lastIndexOf( '.' );
if ( extIndex > index )
{
classifier = id.substring( index + 1, extIndex );
ext = id.substring( extIndex + 1 );
}
else
{
classifier = id.substring( index + 1 );
ext = null;
}
}
else if ( c == '.' )
{
// rest is the extension
classifier = null;
ext = id.substring( index + 1 );
}
else
{
throw new IllegalArgumentException(
"Not a valid artifact path in a Maven 2 repository, filename '" + id +
"' expected classifier or extension but got '" + id.substring( index ) + "'" );
}
}
ArtifactMetadata metadata = new ArtifactMetadata();
metadata.setId( id );
metadata.setNamespace( groupId );
metadata.setProject( artifactId );
metadata.setRepositoryId( repoId );
metadata.setVersion( version );
// TODO: set classifier and extension on Maven facet
return metadata;
}
} }

View File

@ -32,14 +32,59 @@
<groupId>org.apache.archiva</groupId> <groupId>org.apache.archiva</groupId>
<artifactId>metadata-repository-api</artifactId> <artifactId>metadata-repository-api</artifactId>
</dependency> </dependency>
<!-- TODO: we want to move the event handling, or perhaps centralise under deleteArtifact() in the metadata repository itself -->
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-repository-layer</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.archiva</groupId> <groupId>org.apache.archiva</groupId>
<artifactId>archiva-checksum</artifactId> <artifactId>archiva-checksum</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-model</artifactId>
</dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-consumer-api</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-spring</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>test-repository</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>test-repository</id>
<phase>generate-test-resources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeArtifactIds>test-repository</includeArtifactIds>
<outputDirectory>target/test-repository</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -20,12 +20,12 @@ package org.apache.archiva.reports;
*/ */
import org.apache.archiva.metadata.repository.MetadataRepository; import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.maven.archiva.repository.events.RepositoryListener; import org.apache.archiva.repository.events.RepositoryListener;
/** /**
* Process repository management events and respond appropriately. * Process repository management events and respond appropriately.
* *
* @plexus.component role="org.apache.maven.archiva.repository.events.RepositoryListener" role-hint="problem-reports" * @plexus.component role="org.apache.archiva.repository.events.RepositoryListener" role-hint="problem-reports"
*/ */
public class RepositoryProblemEventListener public class RepositoryProblemEventListener
implements RepositoryListener implements RepositoryListener

View File

@ -19,17 +19,11 @@ package org.apache.archiva.reports.consumers;
* under the License. * under the License.
*/ */
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.archiva.checksum.ChecksumAlgorithm; import org.apache.archiva.checksum.ChecksumAlgorithm;
import org.apache.archiva.checksum.ChecksummedFile; import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.metadata.model.ArtifactMetadata; import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository; import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
import org.apache.archiva.reports.RepositoryProblemFacet; import org.apache.archiva.reports.RepositoryProblemFacet;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.configuration.ArchivaConfiguration;
@ -39,11 +33,6 @@ import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer; import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
import org.apache.maven.archiva.consumers.ConsumerException; import org.apache.maven.archiva.consumers.ConsumerException;
import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer; import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException;
import org.apache.maven.archiva.repository.layout.LayoutException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.registry.Registry; import org.codehaus.plexus.registry.Registry;
@ -51,6 +40,13 @@ import org.codehaus.plexus.registry.RegistryListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/** /**
* Search the database of known SHA1 Checksums for potential duplicate artifacts. * Search the database of known SHA1 Checksums for potential duplicate artifacts.
* *
@ -87,24 +83,23 @@ public class DuplicateArtifactsConsumer
*/ */
private FileTypes filetypes; private FileTypes filetypes;
/**
* @plexus.requirement
*/
private RepositoryContentFactory repositoryFactory;
private List<String> includes = new ArrayList<String>(); private List<String> includes = new ArrayList<String>();
private File repositoryDir; private File repositoryDir;
private String repoId; private String repoId;
private ManagedRepositoryContent repository;
/** /**
* @plexus.requirement * @plexus.requirement
*/ */
private MetadataRepository metadataRepository; private MetadataRepository metadataRepository;
/**
* FIXME: needs to be selected based on the repository in question
* @plexus.requirement role-hint="maven2"
*/
private RepositoryPathTranslator pathTranslator;
public String getId() public String getId()
{ {
return id; return id;
@ -132,17 +127,9 @@ public class DuplicateArtifactsConsumer
public void beginScan( ManagedRepositoryConfiguration repo, Date whenGathered ) public void beginScan( ManagedRepositoryConfiguration repo, Date whenGathered )
throws ConsumerException throws ConsumerException
{
try
{ {
repoId = repo.getId(); repoId = repo.getId();
repository = repositoryFactory.getManagedRepositoryContent( repoId ); this.repositoryDir = new File( repo.getLocation() );
this.repositoryDir = new File( repository.getRepoRoot() );
}
catch ( RepositoryException e )
{
throw new ConsumerException( e.getMessage(), e );
}
} }
public void processFile( String path ) public void processFile( String path )
@ -152,6 +139,8 @@ public class DuplicateArtifactsConsumer
// TODO: would be quicker to somehow make sure it ran after the update database consumer, or as a part of that // TODO: would be quicker to somehow make sure it ran after the update database consumer, or as a part of that
// perhaps could use an artifact context that is retained for all consumers? First in can set the SHA-1 // perhaps could use an artifact context that is retained for all consumers? First in can set the SHA-1
// alternatively this could come straight from the storage resolver, which could populate the artifact metadata
// in the later parse call with the desired checksum and use that
String checksumSha1; String checksumSha1;
ChecksummedFile checksummedFile = new ChecksummedFile( artifactFile ); ChecksummedFile checksummedFile = new ChecksummedFile( artifactFile );
try try
@ -167,46 +156,45 @@ public class DuplicateArtifactsConsumer
if ( CollectionUtils.isNotEmpty( results ) ) if ( CollectionUtils.isNotEmpty( results ) )
{ {
if ( results.size() <= 1 ) ArtifactMetadata originalArtifact;
{
// No duplicates detected.
log.debug( "Found no duplicate artifact results on: " + path + " (repository " + repoId + ")" );
return;
}
ArtifactReference artifactReference;
try try
{ {
artifactReference = repository.toArtifactReference( path ); originalArtifact = pathTranslator.getArtifactForPath( repoId, path );
} }
catch ( LayoutException e ) catch ( Exception e )
{ {
log.warn( "Unable to report problem for path: " + path ); log.warn( "Not reporting problem for invalid artifact in checksum check: " + e.getMessage() );
return; return;
} }
for ( ArtifactMetadata dupArtifact : results ) for ( ArtifactMetadata dupArtifact : results )
{ {
String id = path.substring( path.lastIndexOf( "/" ) + 1 ); String id = path.substring( path.lastIndexOf( "/" ) + 1 );
if ( dupArtifact.getId().equals( id ) && if ( dupArtifact.getId().equals( id ) && dupArtifact.getNamespace().equals(
dupArtifact.getNamespace().equals( artifactReference.getGroupId() ) && originalArtifact.getNamespace() ) && dupArtifact.getProject().equals(
dupArtifact.getProject().equals( artifactReference.getArtifactId() ) && originalArtifact.getProject() ) && dupArtifact.getVersion().equals(
dupArtifact.getVersion().equals( artifactReference.getVersion() ) ) originalArtifact.getVersion() ) )
{ {
// Skip reference to itself. // Skip reference to itself.
if ( log.isDebugEnabled() )
{
log.debug( "Not counting duplicate for artifact " + dupArtifact + " for path " + path );
}
continue; continue;
} }
RepositoryProblemFacet problem = new RepositoryProblemFacet(); RepositoryProblemFacet problem = new RepositoryProblemFacet();
problem.setRepositoryId( repoId ); problem.setRepositoryId( repoId );
problem.setNamespace( artifactReference.getGroupId() ); problem.setNamespace( originalArtifact.getNamespace() );
problem.setProject( artifactReference.getArtifactId() ); problem.setProject( originalArtifact.getProject() );
problem.setVersion( artifactReference.getVersion() ); problem.setVersion( originalArtifact.getVersion() );
problem.setId( id ); problem.setId( id );
// TODO: proper path conversion for new metadata // TODO: need to get the right storage resolver for the repository the dupe artifact is in, it might be
problem.setMessage( // a different type
"Duplicate Artifact Detected: " + path + " <--> " + dupArtifact.getNamespace().replace( '.', '/' ) + // TODO: we need the project version here, not the artifact version
"/" + dupArtifact.getProject() + "/" + dupArtifact.getVersion() + "/" + dupArtifact.getId() ); problem.setMessage( "Duplicate Artifact Detected: " + path + " <--> " + pathTranslator.toPath(
dupArtifact.getNamespace(), dupArtifact.getProject(), dupArtifact.getVersion(),
dupArtifact.getId() ) );
problem.setProblem( "duplicate-artifact" ); problem.setProblem( "duplicate-artifact" );
metadataRepository.addMetadataFacet( repoId, problem ); metadataRepository.addMetadataFacet( repoId, problem );

View File

@ -0,0 +1,215 @@
package org.apache.archiva.reports.consumers;
/*
* 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 org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.model.MetadataFacet;
import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
import org.apache.archiva.reports.RepositoryProblemFacet;
import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
import org.apache.maven.archiva.consumers.ConsumerException;
import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer;
import org.codehaus.plexus.spring.PlexusInSpringTestCase;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Date;
import static org.mockito.Mockito.*;
@SuppressWarnings( {"ThrowableInstanceNeverThrown"} )
public class DuplicateArtifactsConsumerTest
extends PlexusInSpringTestCase
{
private DuplicateArtifactsConsumer consumer;
private ManagedRepositoryConfiguration config;
private MetadataRepository metadataRepository;
private static final String TEST_REPO = "test-repo";
private static final String TEST_CHECKSUM = "edf5938e646956f445c6ecb719d44579cdeed974";
private static final String TEST_PROJECT = "test-artifact";
private static final String TEST_NAMESPACE = "com.example.test";
private static final String TEST_FILE =
"com/example/test/test-artifact/1.0-SNAPSHOT/test-artifact-1.0-20100308.230825-1.jar";
private static final String TEST_VERSION = "1.0-20100308.230825-1";
private static final ArtifactMetadata TEST_METADATA = createMetadata( TEST_VERSION );
private RepositoryPathTranslator pathTranslator;
public void setUp()
throws Exception
{
super.setUp();
consumer = (DuplicateArtifactsConsumer) lookup( KnownRepositoryContentConsumer.class, "duplicate-artifacts" );
assertNotNull( consumer );
config = new ManagedRepositoryConfiguration();
config.setId( TEST_REPO );
config.setLocation( getTestFile( "target/test-repository" ).getAbsolutePath() );
metadataRepository = (MetadataRepository) lookup( MetadataRepository.class );
pathTranslator = (RepositoryPathTranslator) lookup( RepositoryPathTranslator.class, "maven2" );
when( pathTranslator.getArtifactForPath( TEST_REPO, TEST_FILE ) ).thenReturn( TEST_METADATA );
}
public void testConsumerArtifactNotDuplicated()
throws ConsumerException
{
when( metadataRepository.getArtifactsByChecksum( TEST_REPO, TEST_CHECKSUM ) ).thenReturn( Arrays.asList(
TEST_METADATA ) );
consumer.beginScan( config, new Date() );
consumer.processFile( TEST_FILE );
consumer.completeScan();
verify( metadataRepository, never() ).addMetadataFacet( eq( TEST_REPO ), Matchers.<MetadataFacet>anyObject() );
}
// TODO: Doesn't currently work
// public void testConsumerArtifactNotDuplicatedForOtherSnapshots()
// throws ConsumerException
// {
// when( metadataRepository.getArtifactsByChecksum( TEST_REPO, TEST_CHECKSUM ) ).thenReturn( Arrays.asList(
// TEST_METADATA, createMetadata( "1.0-20100309.002023-2" ) ) );
//
// consumer.beginScan( config, new Date() );
// consumer.processFile( TEST_FILE );
// consumer.completeScan();
//
// verify( metadataRepository, never() ).addMetadataFacet( eq( TEST_REPO ), Matchers.<MetadataFacet>anyObject() );
// }
public void testConsumerArtifactDuplicated()
throws ConsumerException
{
when( metadataRepository.getArtifactsByChecksum( TEST_REPO, TEST_CHECKSUM ) ).thenReturn( Arrays.asList(
TEST_METADATA, createMetadata( "1.0" ) ) );
consumer.beginScan( config, new Date() );
consumer.processFile( TEST_FILE );
consumer.completeScan();
ArgumentCaptor<RepositoryProblemFacet> argument = ArgumentCaptor.forClass( RepositoryProblemFacet.class );
verify( metadataRepository ).addMetadataFacet( eq( TEST_REPO ), argument.capture() );
RepositoryProblemFacet problem = argument.getValue();
assertProblem( problem );
}
public void testConsumerArtifactDuplicatedButSelfNotInMetadataRepository()
throws ConsumerException
{
when( metadataRepository.getArtifactsByChecksum( TEST_REPO, TEST_CHECKSUM ) ).thenReturn( Arrays.asList(
createMetadata( "1.0" ) ) );
consumer.beginScan( config, new Date() );
consumer.processFile( TEST_FILE );
consumer.completeScan();
ArgumentCaptor<RepositoryProblemFacet> argument = ArgumentCaptor.forClass( RepositoryProblemFacet.class );
verify( metadataRepository ).addMetadataFacet( eq( TEST_REPO ), argument.capture() );
RepositoryProblemFacet problem = argument.getValue();
assertProblem( problem );
}
public void testConsumerArtifactFileNotExist()
throws ConsumerException
{
consumer.beginScan( config, new Date() );
try
{
consumer.processFile( "com/example/test/test-artifact/2.0/test-artifact-2.0.jar" );
fail( "Should have failed to find file" );
}
catch ( ConsumerException e )
{
assertTrue( e.getCause() instanceof FileNotFoundException );
}
finally
{
consumer.completeScan();
}
verify( metadataRepository, never() ).addMetadataFacet( eq( TEST_REPO ), Matchers.<MetadataFacet>anyObject() );
}
public void testConsumerArtifactNotAnArtifactPathNoResults()
throws ConsumerException
{
consumer.beginScan( config, new Date() );
// No exception unnecessarily for something we can't report on
consumer.processFile( "com/example/invalid-artifact.txt" );
consumer.completeScan();
verify( metadataRepository, never() ).addMetadataFacet( eq( TEST_REPO ), Matchers.<MetadataFacet>anyObject() );
}
public void testConsumerArtifactNotAnArtifactPathResults()
throws ConsumerException
{
when( metadataRepository.getArtifactsByChecksum( eq( TEST_REPO ), anyString() ) ).thenReturn( Arrays.asList(
TEST_METADATA, createMetadata( "1.0" ) ) );
// override, this feels a little overspecified though
when( pathTranslator.getArtifactForPath( TEST_REPO, "com/example/invalid-artifact.txt" ) ).thenThrow(
new IllegalArgumentException() );
consumer.beginScan( config, new Date() );
// No exception unnecessarily for something we can't report on
consumer.processFile( "com/example/invalid-artifact.txt" );
consumer.completeScan();
verify( metadataRepository, never() ).addMetadataFacet( eq( TEST_REPO ), Matchers.<MetadataFacet>anyObject() );
}
private static void assertProblem( RepositoryProblemFacet problem )
{
assertEquals( TEST_REPO, problem.getRepositoryId() );
assertEquals( TEST_NAMESPACE, problem.getNamespace() );
assertEquals( TEST_PROJECT, problem.getProject() );
assertEquals( TEST_VERSION, problem.getVersion() );
assertEquals( TEST_PROJECT + "-" + TEST_VERSION + ".jar", problem.getId() );
assertNotNull( problem.getMessage() );
assertEquals( "duplicate-artifact", problem.getProblem() );
}
private static ArtifactMetadata createMetadata( String version )
{
ArtifactMetadata artifact = new ArtifactMetadata();
artifact.setId( TEST_PROJECT + "-" + version + ".jar" );
artifact.setNamespace( TEST_NAMESPACE );
artifact.setProject( TEST_PROJECT );
artifact.setVersion( version );
artifact.setRepositoryId( TEST_REPO );
return artifact;
}
}

View File

@ -0,0 +1,51 @@
package org.apache.archiva.reports.consumers;
/*
* 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 org.springframework.beans.factory.FactoryBean;
import static org.mockito.Mockito.mock;
public class MockitoFactory
implements FactoryBean
{
private final Class<Object> type;
public MockitoFactory( Class<Object> type )
{
this.type = type;
}
public Object getObject()
throws Exception
{
return mock( type );
}
public Class getObjectType()
{
return type;
}
public boolean isSingleton()
{
return true;
}
}

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="metadataRepositoryFactory" class="org.apache.archiva.reports.consumers.MockitoFactory"
name="metadataRepository">
<constructor-arg value="org.apache.archiva.metadata.repository.MetadataRepository"/>
</bean>
<bean id="repositoryPathTranslatorFactory" class="org.apache.archiva.reports.consumers.MockitoFactory"
name="repositoryPathTranslator#maven2">
<constructor-arg value="org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator"/>
</bean>
</beans>

17
pom.xml
View File

@ -329,11 +329,6 @@
<artifactId>archiva-artifact-converter</artifactId> <artifactId>archiva-artifact-converter</artifactId>
<version>1.4-SNAPSHOT</version> <version>1.4-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-artifact-reports</artifactId>
<version>1.4-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.archiva</groupId> <groupId>org.apache.archiva</groupId>
<artifactId>archiva-checksum</artifactId> <artifactId>archiva-checksum</artifactId>
@ -359,11 +354,6 @@
<artifactId>archiva-converter</artifactId> <artifactId>archiva-converter</artifactId>
<version>1.4-SNAPSHOT</version> <version>1.4-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-dependency-graph</artifactId>
<version>1.4-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.archiva</groupId> <groupId>org.apache.archiva</groupId>
<artifactId>archiva-core-consumers</artifactId> <artifactId>archiva-core-consumers</artifactId>
@ -376,12 +366,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.archiva</groupId> <groupId>org.apache.archiva</groupId>
<artifactId>archiva-database</artifactId> <artifactId>test-repository</artifactId>
<version>1.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-database-consumers</artifactId>
<version>1.4-SNAPSHOT</version> <version>1.4-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>