--- /dev/null
+package org.apache.maven.repository.reporting;
+
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.model.Model;
+import org.apache.maven.repository.digest.DefaultDigester;
+import org.apache.maven.repository.digest.Digester;
+import org.apache.maven.repository.indexing.DefaultRepositoryIndexingFactory;
+import org.apache.maven.repository.indexing.RepositoryIndex;
+import org.apache.maven.repository.indexing.RepositoryIndexException;
+import org.apache.maven.repository.indexing.RepositoryIndexSearchException;
+import org.apache.maven.repository.indexing.RepositoryIndexSearchLayer;
+import org.apache.maven.repository.indexing.RepositoryIndexingFactory;
+import org.apache.maven.repository.indexing.SearchResult;
+import org.apache.maven.repository.indexing.query.Query;
+import org.apache.maven.repository.indexing.query.SinglePhraseQuery;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Validates an artifact file for duplicates within the same groupId based from what's available in a RepositoryIndex
+ *
+ * @author Edwin Punzalan
+ */
+public class DuplicateArtifactFileReportProcessor
+ implements ArtifactReportProcessor
+{
+ private Digester digester;
+
+ private RepositoryIndexingFactory indexFactory;
+
+ //@todo configurable?
+ private String algorithm = RepositoryIndex.FLD_MD5;
+
+ private RepositoryIndexSearchLayer searchLayer;
+
+ //@todo must be injected
+ private ArtifactFactory artifactFactory;
+
+ public void processArtifact( Model model, Artifact artifact, ArtifactReporter reporter,
+ ArtifactRepository repository )
+ throws ReportProcessorException
+ {
+ if ( artifact.getFile() != null )
+ {
+ //@todo remove hard-coded value; current value enables tests to pass
+ String indexPath = new File( "target/.index" ).getAbsolutePath();
+
+ //@todo may be injected?
+ if ( digester == null )
+ {
+ digester = new DefaultDigester();
+ }
+
+ //@todo may be injected?
+ if ( indexFactory == null )
+ {
+ indexFactory = new DefaultRepositoryIndexingFactory();
+ }
+
+ RepositoryIndex index;
+ try
+ {
+ index = indexFactory.createArtifactRepositoryIndex( indexPath, repository );
+ }
+ catch ( RepositoryIndexException e )
+ {
+ throw new ReportProcessorException( "Unable to create RepositoryIndex instance", e );
+ }
+
+ if ( searchLayer == null )
+ {
+ searchLayer = new RepositoryIndexSearchLayer( index, artifactFactory );
+ }
+
+ String checksum;
+ try
+ {
+ checksum = digester.createChecksum( artifact.getFile(), algorithm );
+ }
+ catch ( IOException e )
+ {
+ throw new ReportProcessorException( "Failed to generate checksum", e );
+ }
+ catch ( NoSuchAlgorithmException e )
+ {
+ throw new ReportProcessorException( "Failed to generate checksum", e );
+ }
+
+ Query query = new SinglePhraseQuery( algorithm, checksum.trim() );
+
+ try
+ {
+ List results = searchLayer.searchAdvanced( query );
+
+ if ( results.isEmpty() )
+ {
+ reporter.addSuccess( artifact );
+ }
+ else
+ {
+ String id = artifact.getId();
+
+ boolean hasDuplicates = false;
+ for ( Iterator hits = results.iterator(); hits.hasNext(); )
+ {
+ SearchResult result = (SearchResult) hits.next();
+ Artifact artifactMatch = result.getArtifact();
+
+ //make sure it is not the same artifact
+ if ( !id.equals( artifactMatch.getId() ) )
+ {
+ //report only duplicates from the same groupId
+ String groupId = artifact.getGroupId();
+ if ( groupId.equals( artifactMatch.getGroupId() ) )
+ {
+ hasDuplicates = true;
+ reporter.addFailure( artifact, "Found duplicate for " + artifactMatch.getId() );
+ }
+ }
+ }
+
+ if ( !hasDuplicates )
+ {
+ reporter.addSuccess( artifact );
+ }
+ }
+ }
+ catch ( RepositoryIndexSearchException e )
+ {
+ throw new ReportProcessorException( "Failed to search in index", e );
+ }
+ }
+ else
+ {
+ reporter.addWarning( artifact, "Artifact file is null" );
+ }
+ }
+
+ public ArtifactFactory getArtifactFactory()
+ {
+ return artifactFactory;
+ }
+
+ public void setArtifactFactory( ArtifactFactory artifactFactory )
+ {
+ this.artifactFactory = artifactFactory;
+ }
+}
--- /dev/null
+package org.apache.maven.repository.reporting;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.model.Model;
+import org.apache.maven.repository.digest.DefaultDigester;
+import org.apache.maven.repository.indexing.ArtifactRepositoryIndex;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.File;
+
+/**
+ * @author Edwin Punzalan
+ */
+public class DuplicateArtifactFileReportProcessorTest
+ extends AbstractRepositoryReportsTestCase
+{
+ private MockArtifactReporter reporter;
+
+ private Artifact artifact;
+
+ private Model model;
+
+ private DuplicateArtifactFileReportProcessor processor;
+
+ private ArtifactFactory artifactFactory;
+
+ private String indexPath = new File( "target/.index" ).getAbsolutePath();
+
+ protected void setUp()
+ throws Exception
+ {
+ super.setUp();
+ artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.class.getName() );
+ reporter = new MockArtifactReporter();
+ artifact = createArtifact( "groupId", "artifactId", "1.0-alpha-1", "1.0-alpha-1", "jar" );
+ model = new Model();
+ processor = new DuplicateArtifactFileReportProcessor();
+ processor.setArtifactFactory( artifactFactory );
+
+ ArtifactRepositoryIndex index = new ArtifactRepositoryIndex( indexPath, repository, new DefaultDigester() );
+ index.indexArtifact( artifact );
+ index.optimize();
+ index.close();
+ }
+
+ protected void tearDown()
+ throws Exception
+ {
+ FileUtils.deleteDirectory( indexPath );
+
+ processor = null;
+ model = null;
+ artifact = null;
+ reporter = null;
+ super.tearDown();
+ }
+
+ public void testNullArtifactFile()
+ throws Exception
+ {
+ artifact.setFile( null );
+
+ processor.processArtifact( model, artifact, reporter, repository );
+
+ assertEquals( "Check no successes", 0, reporter.getSuccesses() );
+ assertEquals( "Check warnings", 1, reporter.getWarnings() );
+ assertEquals( "Check no failures", 0, reporter.getFailures() );
+ }
+
+ public void testSuccessOnAlreadyIndexedArtifact()
+ throws Exception
+ {
+ processor.processArtifact( model, artifact, reporter, repository );
+
+ assertEquals( "Check no successes", 1, reporter.getSuccesses() );
+ assertEquals( "Check warnings", 0, reporter.getWarnings() );
+ assertEquals( "Check no failures", 0, reporter.getFailures() );
+ }
+
+ public void testSuccessOnDifferentGroupId()
+ throws Exception
+ {
+ artifact.setGroupId( "different.groupId" );
+ processor.processArtifact( model, artifact, reporter, repository );
+
+ assertEquals( "Check no successes", 1, reporter.getSuccesses() );
+ assertEquals( "Check warnings", 0, reporter.getWarnings() );
+ assertEquals( "Check no failures", 0, reporter.getFailures() );
+ }
+
+ public void testSuccessOnNewArtifact()
+ throws Exception
+ {
+ Artifact newArtifact = createArtifact( "groupId", "artifactId", "1.0-alpha-1", "1.0-alpha-1", "pom" );
+
+ processor.processArtifact( model, newArtifact, reporter, repository );
+
+ assertEquals( "Check no successes", 1, reporter.getSuccesses() );
+ assertEquals( "Check warnings", 0, reporter.getWarnings() );
+ assertEquals( "Check no failures", 0, reporter.getFailures() );
+ }
+
+ public void testFailure()
+ throws Exception
+ {
+ Artifact duplicate = createArtifact( artifact.getGroupId(), "snapshot-artifact", "1.0-alpha-1-SNAPSHOT",
+ artifact.getVersion(), artifact.getType() );
+ duplicate.setFile( artifact.getFile() );
+
+ processor.processArtifact( model, duplicate, reporter, repository );
+
+ assertEquals( "Check no successes", 0, reporter.getSuccesses() );
+ assertEquals( "Check warnings", 0, reporter.getWarnings() );
+ assertEquals( "Check no failures", 1, reporter.getFailures() );
+ }
+
+ private Artifact createArtifact( String groupId, String artifactId, String baseVersion, String version,
+ String type )
+ {
+ Artifact artifact = artifactFactory.createArtifact( groupId, artifactId, version, null, type );
+ artifact.setBaseVersion( baseVersion );
+ artifact.setRepository( repository );
+ artifact.setFile( new File( repository.getBasedir(), repository.pathOf( artifact ) ) );
+ return artifact;
+ }
+}