~ 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>
<parent>
<groupId>org.apache.archiva</groupId>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-repository-layer</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.archiva</groupId>
+ <artifactId>metadata-repository-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-digest</artifactId>
</dependency>
+
+ <!-- test dependencies -->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-spring</artifactId>
<scope>test</scope>
</dependency>
-
- <!-- test dependencies -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
* under the License.
*/
-import java.io.File;
-import java.io.FilenameFilter;
-import java.util.List;
-import java.util.Set;
-
+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.apache.maven.archiva.repository.events.RepositoryListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.List;
+import java.util.Set;
+
/**
* Base class for all repository purge tasks.
*
{
File artifactFile = repository.toFile( reference );
+ // TODO: looks incomplete, might not delete related metadata?
for ( RepositoryListener listener : listeners )
{
listener.deleteArtifact( repository.getId(), reference.getGroupId(), reference.getArtifactId(),
* 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.repository.events.RepositoryListener;
import org.apache.maven.archiva.common.utils.VersionComparator;
import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException;
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.metadata.MetadataTools;
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>
* This will look in a single managed repository, and purge any snapshots that are present
versionRef.setVersion( version );
repository.deleteVersion( versionRef );
- // TODO: looks incomplete, might not delete related artifacts?
+ // TODO: looks incomplete, might not delete related metadata?
for ( RepositoryListener listener : listeners )
{
listener.deleteArtifact( repository.getId(), artifact.getGroupId(), artifact.getArtifactId(),
* 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.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Set;
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.
*
* under the License.
*/
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-
+import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.ConfigurationNames;
import org.apache.maven.archiva.configuration.FileTypes;
import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException;
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.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.registry.Registry;
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
* specified by the user.
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();
public String getId()
* under the License.
*/
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
+import org.apache.archiva.repository.events.RepositoryListener;
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;
+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.
*
* under the License.
*/
-import java.io.File;
-import java.io.IOException;
-
+import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.commons.io.FileUtils;
import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
import org.apache.maven.archiva.model.ArchivaArtifact;
import org.apache.maven.archiva.repository.ManagedRepositoryContent;
-import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.codehaus.plexus.spring.PlexusInSpringTestCase;
import org.easymock.MockControl;
+import java.io.File;
+import java.io.IOException;
+
/**
*/
public abstract class AbstractRepositoryPurgeTest
* under the License.
*/
-import java.io.File;
-import java.util.Collections;
-
+import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.commons.io.FileUtils;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.Configuration;
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.custommonkey.xmlunit.XMLAssert;
import org.easymock.MockControl;
+import java.io.File;
+import java.util.Collections;
+
/**
*/
<groupId>org.apache.archiva</groupId>
<artifactId>metadata-model</artifactId>
</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>
<build>
<plugins>
* 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.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.model.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$
*/
public class DefaultPathParser implements PathParser
{
private static final String INVALID_ARTIFACT_PATH = "Invalid path to Artifact: ";
+ private RepositoryPathTranslator pathTranslator = new Maven2RepositoryPathTranslator();
+
/**
* {@inheritDoc}
* @see org.apache.maven.archiva.repository.content.PathParser#toArtifactReference(java.lang.String)
throw new LayoutException( "Unable to convert blank path." );
}
- ArtifactReference artifact = new ArtifactReference();
-
- 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 )
+ ArtifactMetadata metadata;
+ try
{
- // Illegal Path Parts Length.
- throw new LayoutException( "Not enough parts to the path [" + path
- + "] to construct an ArchivaArtifact from. (Requires at least 4 parts)" );
+ metadata = pathTranslator.getArtifactForPath( null, path );
}
-
- // 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++ )
+ catch ( IllegalArgumentException e )
{
- if ( i == 0 )
- {
- artifact.setGroupId( pathParts[i] );
- }
- else
- {
- artifact.setGroupId( artifact.getGroupId() + "." + pathParts[i] );
- }
+ throw new LayoutException( e.getMessage(), e );
}
- try
+ 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 );
+ artifact.setArtifactId( parser.expect( artifact.getArtifactId() ) );
+ if ( artifact.getArtifactId() == null )
{
- // Last part is the filename
- String filename = pathParts[filenamePos];
-
- // Now we need to parse the filename to get the artifact version Id.
- if ( StringUtils.isBlank( filename ) )
+ throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid, "
+ + "should start with artifactId as stated in path." );
+ }
+ String baseVersion = VersionUtil.getBaseVersion( metadata.getVersion() );
+ artifact.setVersion( parser.expect( baseVersion ) );
+ if ( artifact.getVersion() == null )
+ {
+ // We working with a snapshot?
+ if ( VersionUtil.isSnapshot( baseVersion ) )
{
- throw new IllegalArgumentException( INVALID_ARTIFACT_PATH + "Unable to split blank filename." );
+ artifact.setVersion( parser.nextVersion() );
+ if ( !VersionUtil.isUniqueSnapshot( artifact.getVersion() ) )
+ {
+ throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid,"
+ + "expected timestamp format in filename." );
+ }
}
-
- FilenameParser parser = new FilenameParser( filename );
-
- // Expect the filename to start with the artifactId.
- artifact.setArtifactId( parser.expect( artifact.getArtifactId() ) );
-
- if ( artifact.getArtifactId() == null )
+ else
{
throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid, "
- + "should start with artifactId as stated in path." );
+ + "expected version as stated in path." );
}
-
- // Process the version.
- artifact.setVersion( parser.expect( baseVersion ) );
-
- if ( artifact.getVersion() == null )
- {
- // We working with a snapshot?
- if ( VersionUtil.isSnapshot( baseVersion ) )
- {
- artifact.setVersion( parser.nextVersion() );
- if ( !VersionUtil.isUniqueSnapshot( artifact.getVersion() ) )
- {
- throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid,"
- + "expected timestamp format in filename." );
- }
- }
- else
+ }
+ switch(parser.seperator())
+ {
+ case '-':
+ // Definately a classifier.
+ artifact.setClassifier( parser.remaining() );
+
+ // Set the type.
+ artifact.setType( ArtifactExtensionMapping.mapExtensionAndClassifierToType( artifact.getClassifier(), parser.getExtension() ) );
+ break;
+ case '.':
+ // We have an dual extension possibility.
+ String extension = parser.remaining() + '.' + parser.getExtension();
+ artifact.setType( extension );
+ break;
+ case 0:
+ // End of the filename, only a simple extension left. - Set the type.
+ String type = ArtifactExtensionMapping.mapExtensionToType( parser.getExtension() );
+ if ( type == null )
{
- throw new LayoutException( INVALID_ARTIFACT_PATH + "filename format is invalid, "
- + "expected version as stated in path." );
+ throw new LayoutException( "Invalid artifact: no type was specified" );
}
- }
-
- // Do we have a classifier?
- switch(parser.seperator())
- {
- case '-':
- // Definately a classifier.
- artifact.setClassifier( parser.remaining() );
-
- // Set the type.
- artifact.setType( ArtifactExtensionMapping.mapExtensionAndClassifierToType( artifact.getClassifier(), parser.getExtension() ) );
- break;
- case '.':
- // We have an dual extension possibility.
- String extension = parser.remaining() + '.' + parser.getExtension();
- artifact.setType( extension );
- break;
- case 0:
- // End of the filename, only a simple extension left. - Set the type.
- String type = ArtifactExtensionMapping.mapExtensionToType( parser.getExtension() );
- if ( type == null )
- {
- throw new LayoutException( "Invalid artifact: no type was specified" );
- }
- artifact.setType( type );
- break;
- }
-
- // Special case for maven plugins
- if ( StringUtils.equals( "jar", artifact.getType() ) &&
- ArtifactExtensionMapping.isMavenPlugin( artifact.getArtifactId() ) )
- {
- artifact.setType( ArtifactExtensionMapping.MAVEN_PLUGIN );
- }
+ artifact.setType( type );
+ break;
}
- catch ( LayoutException e )
+ if ( StringUtils.equals( "jar", artifact.getType() ) &&
+ ArtifactExtensionMapping.isMavenPlugin( artifact.getArtifactId() ) )
{
- throw e;
+ artifact.setType( ArtifactExtensionMapping.MAVEN_PLUGIN );
}
// Sanity Checks.
+ 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;
}
* 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.maven.archiva.common.utils.PathUtil;
import org.apache.maven.archiva.configuration.FileTypes;
import org.apache.maven.archiva.repository.ManagedRepositoryContent;
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
*
public ArtifactReference toArtifactReference( String path )
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 );
+++ /dev/null
-package org.apache.maven.archiva.repository.events;
-
-/*
- * 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.
- */
-
-/**
- * Listen to events on the repository. This class is a stopgap
- * refactoring measure until an event bus is in place to handle
- * generic events such as these.
- */
-public interface RepositoryListener
-{
- /**
- * Event for the deletion of a given artifact.
- */
- void deleteArtifact( String repositoryId, String namespace, String project, String version, String id );
-}
+++ /dev/null
-package org.apache.maven.archiva.repository.events;
-
-/*
- * 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 java.util.List;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-/**
- * @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
- */
-public class RepositoryListenerFactoryBean
- implements FactoryBean, ApplicationContextAware
-{
-
- private ApplicationContext applicationContext;
-
- public void setApplicationContext( ApplicationContext applicationContext )
- throws BeansException
- {
- this.applicationContext = applicationContext;
- }
-
- public Object getObject()
- throws Exception
- {
- return applicationContext.getBeansOfType( RepositoryListener.class ).values();
- }
-
- @SuppressWarnings("unchecked")
- public Class<List> getObjectType()
- {
- return List.class;
- }
-
- public boolean isSingleton()
- {
- return true;
- }
-
-
-}
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"
*/
--- /dev/null
+package org.apache.archiva.web.spring;
+
+/*
+ * 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.repository.events.RepositoryListener;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.context.ApplicationContext;
+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
+ * and replace the calls in RepositoryContentConsumers with calls to the same thing
+ */
+public class RepositoryListenerFactoryBean
+ implements FactoryBean, ApplicationContextAware
+{
+
+ private ApplicationContext applicationContext;
+
+ public void setApplicationContext( ApplicationContext applicationContext )
+ throws BeansException
+ {
+ this.applicationContext = applicationContext;
+ }
+
+ public Object getObject()
+ throws Exception
+ {
+ return applicationContext.getBeansOfType( RepositoryListener.class ).values();
+ }
+
+ @SuppressWarnings("unchecked")
+ public Class<List> getObjectType()
+ {
+ return List.class;
+ }
+
+ public boolean isSingleton()
+ {
+ return true;
+ }
+
+
+}
* 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.Validateable;
import org.apache.archiva.checksum.ChecksumAlgorithm;
import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.metadata.model.ArtifactMetadata;
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.VersionUtil;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.repository.RepositoryNotFoundException;
import org.apache.maven.archiva.repository.audit.AuditEvent;
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.RepositoryMetadataException;
import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
import org.apache.maven.archiva.security.PrincipalNotFoundException;
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.
*
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;
<constructor-arg ref="metadataRepository"/>
<constructor-arg ref="archivaTaskScheduler#repository"/>
<constructor-arg>
- <bean class="org.apache.maven.archiva.repository.events.RepositoryListenerFactoryBean" />
+ <bean class="org.apache.archiva.web.spring.RepositoryListenerFactoryBean" />
</constructor-arg>
</bean>
* 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.repository.MetadataRepository;
+import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.repository.scanner.RepositoryContentConsumers;
import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.RepositoryTask;
import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException;
import org.apache.maven.archiva.repository.RepositoryNotFoundException;
-import org.apache.maven.archiva.repository.events.RepositoryListener;
import org.codehaus.plexus.registry.RegistryException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
/**
* AdministrationServiceImpl
*
* 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.repository.MetadataRepository;
+import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.repository.scanner.RepositoryContentConsumers;
import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler;
import org.apache.archiva.scheduler.repository.RepositoryTask;
import org.apache.maven.archiva.repository.content.ManagedDefaultRepositoryContent;
import org.apache.maven.archiva.repository.content.ManagedLegacyRepositoryContent;
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.codehaus.plexus.spring.PlexusInSpringTestCase;
import org.easymock.MockControl;
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
*
* under the License.
*/
+import org.apache.archiva.metadata.model.ArtifactMetadata;
+
import java.io.File;
public interface RepositoryPathTranslator
File toFile( File basedir, String namespace );
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 );
}
--- /dev/null
+package org.apache.archiva.repository.events;
+
+/*
+ * 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.
+ */
+
+/**
+ * Listen to events on the repository. This class is a stopgap
+ * refactoring measure until an event bus is in place to handle
+ * generic events such as these.
+ */
+public interface RepositoryListener
+{
+ /**
+ * Event for the deletion of a given artifact.
+ */
+ void deleteArtifact( String repositoryId, String namespace, String project, String version, String id );
+}
<modules>
<module>metadata-model</module>
<module>metadata-repository-api</module>
+ <module>test-repository</module>
</modules>
-</project>
+</project>
\ No newline at end of file
--- /dev/null
+<?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>
--- /dev/null
+invalid path
--- /dev/null
+<?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>
--- /dev/null
+7210867ac16cd955db89cfca699e7c96
\ No newline at end of file
--- /dev/null
+271faeb2039d026ee6a3c937375b5ff7d4b1d605
\ No newline at end of file
--- /dev/null
+cc2236dd70af3667080a786c7dcb4a9b
\ No newline at end of file
--- /dev/null
+edf5938e646956f445c6ecb719d44579cdeed974
\ No newline at end of file
--- /dev/null
+<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>
--- /dev/null
+ce7eeb9586dc4992dc961d9f3a28006b
\ No newline at end of file
--- /dev/null
+be040c8462fd31d4e03749e3586afbb21f43594e
\ No newline at end of file
--- /dev/null
+<?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>
--- /dev/null
+93afaac7340faadc7efd097952d79fa4
\ No newline at end of file
--- /dev/null
+d59d588343d61fd7d838984a0daa4aaa2546bf9d
\ No newline at end of file
import java.util.Collections;
import java.util.Date;
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"
String projectVersion )
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: 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 );
{
for ( File file : files )
{
- ArtifactMetadata metadata = new ArtifactMetadata();
- metadata.setId( file.getName() );
- metadata.setProject( projectId );
- metadata.setNamespace( namespace );
- metadata.setRepositoryId( repoId );
- metadata.setWhenGathered( new Date() );
- metadata.setFileLastModified( file.lastModified() );
- ChecksummedFile checksummedFile = new ChecksummedFile( file );
- try
- {
- metadata.setMd5( checksummedFile.calculateChecksum( ChecksumAlgorithm.MD5 ) );
- }
- catch ( IOException e )
- {
- log.error( "Unable to checksum file " + file + ": " + e.getMessage() );
- }
- try
- {
- metadata.setSha1( checksummedFile.calculateChecksum( ChecksumAlgorithm.SHA1 ) );
- }
- catch ( IOException e )
- {
- log.error( "Unable to checksum file " + file + ": " + e.getMessage() );
- }
- metadata.setSize( file.length() );
-
- // TODO: very crude, migrate the functionality from the repository-layer here
- 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 );
- }
+ ArtifactMetadata metadata = getArtifactFromFile( repoId, namespace, projectId, projectVersion, file );
artifacts.add( metadata );
}
}
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.setFileLastModified( file.lastModified() );
+ ChecksummedFile checksummedFile = new ChecksummedFile( file );
+ try
+ {
+ metadata.setMd5( checksummedFile.calculateChecksum( ChecksumAlgorithm.MD5 ) );
+ }
+ catch ( IOException e )
+ {
+ log.error( "Unable to checksum file " + file + ": " + e.getMessage() );
+ }
+ try
+ {
+ metadata.setSha1( checksummedFile.calculateChecksum( ChecksumAlgorithm.SHA1 ) );
+ }
+ catch ( IOException e )
+ {
+ log.error( "Unable to checksum file " + file + ": " + e.getMessage() );
+ }
+ metadata.setSize( file.length() );
+
+ return metadata;
+ }
+
private boolean isProject( File dir, Filter<String> filter )
{
// scan directories for a valid project version subdirectory, meaning this must be a project directory
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.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
{
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;
+ }
}
<groupId>org.apache.archiva</groupId>
<artifactId>metadata-repository-api</artifactId>
</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>
+ <artifactId>archiva-checksum</artifactId>
</dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
- <artifactId>archiva-checksum</artifactId>
+ <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>
+ <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>
*/
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.
*
- * @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
implements RepositoryListener
* 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.ChecksummedFile;
import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository;
+import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
import org.apache.archiva.reports.RepositoryProblemFacet;
import org.apache.commons.collections.CollectionUtils;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
import org.apache.maven.archiva.consumers.ConsumerException;
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.InitializationException;
import org.codehaus.plexus.registry.Registry;
import org.slf4j.Logger;
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.
*
*/
private FileTypes filetypes;
- /**
- * @plexus.requirement
- */
- private RepositoryContentFactory repositoryFactory;
-
private List<String> includes = new ArrayList<String>();
private File repositoryDir;
private String repoId;
- private ManagedRepositoryContent repository;
-
/**
* @plexus.requirement
*/
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()
{
return id;
public void beginScan( ManagedRepositoryConfiguration repo, Date whenGathered )
throws ConsumerException
{
- try
- {
- repoId = repo.getId();
- repository = repositoryFactory.getManagedRepositoryContent( repoId );
- this.repositoryDir = new File( repository.getRepoRoot() );
- }
- catch ( RepositoryException e )
- {
- throw new ConsumerException( e.getMessage(), e );
- }
+ repoId = repo.getId();
+ this.repositoryDir = new File( repo.getLocation() );
}
public void processFile( String path )
// 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
+ // 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;
ChecksummedFile checksummedFile = new ChecksummedFile( artifactFile );
try
if ( CollectionUtils.isNotEmpty( results ) )
{
- if ( results.size() <= 1 )
- {
- // No duplicates detected.
- log.debug( "Found no duplicate artifact results on: " + path + " (repository " + repoId + ")" );
- return;
- }
-
- ArtifactReference artifactReference;
+ ArtifactMetadata originalArtifact;
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;
}
for ( ArtifactMetadata dupArtifact : results )
{
String id = path.substring( path.lastIndexOf( "/" ) + 1 );
- if ( dupArtifact.getId().equals( id ) &&
- dupArtifact.getNamespace().equals( artifactReference.getGroupId() ) &&
- dupArtifact.getProject().equals( artifactReference.getArtifactId() ) &&
- dupArtifact.getVersion().equals( artifactReference.getVersion() ) )
+ if ( dupArtifact.getId().equals( id ) && dupArtifact.getNamespace().equals(
+ originalArtifact.getNamespace() ) && dupArtifact.getProject().equals(
+ originalArtifact.getProject() ) && dupArtifact.getVersion().equals(
+ originalArtifact.getVersion() ) )
{
// Skip reference to itself.
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "Not counting duplicate for artifact " + dupArtifact + " for path " + path );
+ }
continue;
}
RepositoryProblemFacet problem = new RepositoryProblemFacet();
problem.setRepositoryId( repoId );
- problem.setNamespace( artifactReference.getGroupId() );
- problem.setProject( artifactReference.getArtifactId() );
- problem.setVersion( artifactReference.getVersion() );
+ problem.setNamespace( originalArtifact.getNamespace() );
+ problem.setProject( originalArtifact.getProject() );
+ problem.setVersion( originalArtifact.getVersion() );
problem.setId( id );
- // TODO: proper path conversion for new metadata
- problem.setMessage(
- "Duplicate Artifact Detected: " + path + " <--> " + dupArtifact.getNamespace().replace( '.', '/' ) +
- "/" + dupArtifact.getProject() + "/" + dupArtifact.getVersion() + "/" + dupArtifact.getId() );
+ // TODO: need to get the right storage resolver for the repository the dupe artifact is in, it might be
+ // a different type
+ // TODO: we need the project version here, not the artifact version
+ problem.setMessage( "Duplicate Artifact Detected: " + path + " <--> " + pathTranslator.toPath(
+ dupArtifact.getNamespace(), dupArtifact.getProject(), dupArtifact.getVersion(),
+ dupArtifact.getId() ) );
problem.setProblem( "duplicate-artifact" );
metadataRepository.addMetadataFacet( repoId, problem );
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+<?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>
\ No newline at end of file
<artifactId>archiva-artifact-converter</artifactId>
<version>1.4-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.apache.archiva</groupId>
- <artifactId>archiva-artifact-reports</artifactId>
- <version>1.4-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-checksum</artifactId>
<artifactId>archiva-converter</artifactId>
<version>1.4-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.apache.archiva</groupId>
- <artifactId>archiva-dependency-graph</artifactId>
- <version>1.4-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
<artifactId>archiva-core-consumers</artifactId>
</dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
- <artifactId>archiva-database</artifactId>
- <version>1.4-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.archiva</groupId>
- <artifactId>archiva-database-consumers</artifactId>
+ <artifactId>test-repository</artifactId>
<version>1.4-SNAPSHOT</version>
</dependency>
<dependency>