1 package org.apache.maven.archiva.reporting.artifact;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import java.util.ArrayList;
23 import java.util.List;
25 import org.apache.commons.collections.CollectionUtils;
26 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
27 import org.apache.maven.archiva.configuration.ConfigurationNames;
28 import org.apache.maven.archiva.configuration.FileTypes;
29 import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
30 import org.apache.maven.archiva.consumers.ConsumerException;
31 import org.apache.maven.archiva.database.ArchivaDAO;
32 import org.apache.maven.archiva.database.ArchivaDatabaseException;
33 import org.apache.maven.archiva.database.ObjectNotFoundException;
34 import org.apache.maven.archiva.database.constraints.ArtifactsByChecksumConstraint;
35 import org.apache.maven.archiva.database.updater.ArchivaArtifactConsumer;
36 import org.apache.maven.archiva.model.ArchivaArtifact;
37 import org.apache.maven.archiva.model.RepositoryProblem;
38 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
39 import org.apache.maven.archiva.repository.RepositoryContentFactory;
40 import org.apache.maven.archiva.repository.RepositoryException;
41 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
42 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
43 import org.codehaus.plexus.registry.Registry;
44 import org.codehaus.plexus.registry.RegistryListener;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
49 * Search the database of known SHA1 Checksums for potential duplicate artifacts.
53 * @plexus.component role="org.apache.maven.archiva.consumers.ArchivaArtifactConsumer"
54 * role-hint="duplicate-artifacts"
56 public class DuplicateArtifactsConsumer
57 extends AbstractMonitoredConsumer
58 implements ArchivaArtifactConsumer, RegistryListener, Initializable
60 private Logger log = LoggerFactory.getLogger( DuplicateArtifactsConsumer.class );
63 * @plexus.configuration default-value="duplicate-artifacts"
68 * @plexus.configuration default-value="Check for Duplicate Artifacts via SHA1 Checksums"
70 private String description;
75 private ArchivaConfiguration configuration;
80 private FileTypes filetypes;
83 * @plexus.requirement role-hint="jdo"
85 private ArchivaDAO dao;
90 private RepositoryContentFactory repositoryFactory;
92 // TODO: why is this not used? If it should be, what about excludes?
93 private List<String> includes = new ArrayList<String>();
100 public String getDescription()
105 public boolean isPermanent()
110 public void beginScan()
115 public void completeScan()
120 public List<String> getIncludedTypes()
125 public void processArchivaArtifact( ArchivaArtifact artifact )
126 throws ConsumerException
128 String checksumSha1 = artifact.getModel().getChecksumSHA1();
130 List<ArchivaArtifact> results = null;
133 results = dao.getArtifactDAO().queryArtifacts( new ArtifactsByChecksumConstraint(
134 checksumSha1, ArtifactsByChecksumConstraint.SHA1 ) );
136 catch ( ObjectNotFoundException e )
138 log.debug( "No duplicates for artifact: " + artifact );
141 catch ( ArchivaDatabaseException e )
143 log.warn( "Unable to query DB for potential duplicates with : " + artifact );
147 if ( CollectionUtils.isNotEmpty( results ) )
149 if ( results.size() <= 1 )
151 // No duplicates detected.
152 log.debug( "Found no duplicate artifact results on: " + artifact );
156 for ( ArchivaArtifact dupArtifact : results )
158 if ( dupArtifact.equals( artifact ) )
160 // Skip reference to itself.
164 RepositoryProblem problem = new RepositoryProblem();
165 problem.setRepositoryId( dupArtifact.getModel().getRepositoryId() );
166 problem.setPath( toPath( dupArtifact ) );
167 problem.setGroupId( artifact.getGroupId() );
168 problem.setArtifactId( artifact.getArtifactId() );
169 problem.setVersion( artifact.getVersion() );
170 problem.setType( DuplicateArtifactReport.PROBLEM_TYPE_DUPLICATE_ARTIFACTS );
171 problem.setOrigin( getId() );
172 problem.setMessage( "Duplicate Artifact Detected: " + artifact + " <--> " + dupArtifact );
176 log.debug( "Found duplicate artifact: " + problem );
177 dao.getRepositoryProblemDAO().saveRepositoryProblem( problem );
179 catch ( ArchivaDatabaseException e )
181 String emsg = "Unable to save problem with duplicate artifact to DB: " + e.getMessage();
183 throw new ConsumerException( emsg, e );
189 private String toPath( ArchivaArtifact artifact )
193 String repoId = artifact.getModel().getRepositoryId();
194 ManagedRepositoryContent repo = repositoryFactory.getManagedRepositoryContent( repoId );
195 return repo.toPath( artifact );
197 catch ( RepositoryException e )
199 log.warn( "Unable to calculate path for artifact: " + artifact );
204 public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
206 if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
212 public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
217 private void initIncludes()
221 includes.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
224 public void initialize()
225 throws InitializationException
228 configuration.addChangeListener( this );