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 org.apache.commons.collections.CollectionUtils;
23 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
24 import org.apache.maven.archiva.configuration.ConfigurationNames;
25 import org.apache.maven.archiva.configuration.FileTypes;
26 import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
27 import org.apache.maven.archiva.consumers.ArchivaArtifactConsumer;
28 import org.apache.maven.archiva.consumers.ConsumerException;
29 import org.apache.maven.archiva.database.ArchivaDAO;
30 import org.apache.maven.archiva.database.ArchivaDatabaseException;
31 import org.apache.maven.archiva.database.ObjectNotFoundException;
32 import org.apache.maven.archiva.database.constraints.ArtifactsByChecksumConstraint;
33 import org.apache.maven.archiva.model.ArchivaArtifact;
34 import org.apache.maven.archiva.model.RepositoryProblem;
35 import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayout;
36 import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayoutFactory;
37 import org.apache.maven.archiva.repository.layout.LayoutException;
38 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
39 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
40 import org.codehaus.plexus.registry.Registry;
41 import org.codehaus.plexus.registry.RegistryListener;
43 import java.util.ArrayList;
44 import java.util.Iterator;
45 import java.util.List;
48 * Search the database of known SHA1 Checksums for potential duplicate artifacts.
50 * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
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
61 * @plexus.configuration default-value="duplicate-artifacts"
66 * @plexus.configuration default-value="Check for Duplicate Artifacts via SHA1 Checksums"
68 private String description;
73 private ArchivaConfiguration configuration;
78 private FileTypes filetypes;
81 * @plexus.requirement role-hint="jdo"
83 private ArchivaDAO dao;
88 private BidirectionalRepositoryLayoutFactory layoutFactory;
90 private List includes = new ArrayList();
97 public String getDescription()
102 public boolean isPermanent()
107 public void beginScan()
112 public void completeScan()
117 public List getIncludedTypes()
122 public void processArchivaArtifact( ArchivaArtifact artifact )
123 throws ConsumerException
125 String checksumSha1 = artifact.getModel().getChecksumSHA1();
130 results = dao.getArtifactDAO().queryArtifacts( new ArtifactsByChecksumConstraint(
131 checksumSha1, ArtifactsByChecksumConstraint.SHA1 ) );
133 catch ( ObjectNotFoundException e )
135 getLogger().debug( "No duplicates for artifact: " + artifact );
138 catch ( ArchivaDatabaseException e )
140 getLogger().warn( "Unable to query DB for potential duplicates with : " + artifact );
144 if ( CollectionUtils.isNotEmpty( results ) )
146 if ( results.size() <= 1 )
148 // No duplicates detected.
149 getLogger().debug( "Found no duplicate artifact results on: " + artifact );
153 Iterator it = results.iterator();
154 while ( it.hasNext() )
156 ArchivaArtifact dupArtifact = (ArchivaArtifact) it.next();
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 getLogger().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();
182 getLogger().warn( emsg, e );
183 throw new ConsumerException( emsg, e );
189 private String toPath( ArchivaArtifact artifact )
193 BidirectionalRepositoryLayout layout = layoutFactory.getLayout( artifact );
194 return layout.toPath( artifact );
196 catch ( LayoutException e )
198 getLogger().warn( "Unable to calculate path for artifact: " + artifact );
203 public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
205 if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
211 public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
216 private void initIncludes()
220 includes.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
223 public void initialize()
224 throws InitializationException
227 configuration.addChangeListener( this );