]> source.dussan.org Git - archiva.git/blob
360af29d115bad038863b809294476d0c51ed4b6
[archiva.git] /
1 package org.apache.maven.archiva.reporting.artifact;
2
3 /*
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
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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.ManagedRepositoryContent;
36 import org.apache.maven.archiva.repository.RepositoryContentFactory;
37 import org.apache.maven.archiva.repository.RepositoryException;
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;
42
43 import java.util.ArrayList;
44 import java.util.List;
45
46 /**
47  * Search the database of known SHA1 Checksums for potential duplicate artifacts.
48  *
49  * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
50  * @version $Id$
51  * 
52  * @plexus.component role="org.apache.maven.archiva.consumers.ArchivaArtifactConsumer"
53  *                   role-hint="duplicate-artifacts"
54  */
55 public class DuplicateArtifactsConsumer
56     extends AbstractMonitoredConsumer
57     implements ArchivaArtifactConsumer, RegistryListener, Initializable
58 {
59     /**
60      * @plexus.configuration default-value="duplicate-artifacts"
61      */
62     private String id;
63
64     /**
65      * @plexus.configuration default-value="Check for Duplicate Artifacts via SHA1 Checksums"
66      */
67     private String description;
68
69     /**
70      * @plexus.requirement
71      */
72     private ArchivaConfiguration configuration;
73
74     /**
75      * @plexus.requirement
76      */
77     private FileTypes filetypes;
78
79     /**
80      * @plexus.requirement role-hint="jdo"
81      */
82     private ArchivaDAO dao;
83
84     /**
85      * @plexus.requirement
86      */
87     private RepositoryContentFactory repositoryFactory;
88
89     private List<String> includes = new ArrayList<String>();
90
91     public String getId()
92     {
93         return id;
94     }
95
96     public String getDescription()
97     {
98         return description;
99     }
100
101     public boolean isPermanent()
102     {
103         return false;
104     }
105
106     public void beginScan()
107     {
108         /* do nothing */
109     }
110
111     public void completeScan()
112     {
113         /* do nothing */
114     }
115
116     public List<String> getIncludedTypes()
117     {
118         return null;
119     }
120
121     public void processArchivaArtifact( ArchivaArtifact artifact )
122         throws ConsumerException
123     {
124         String checksumSha1 = artifact.getModel().getChecksumSHA1();
125
126         List<ArchivaArtifact> results = null;
127         try
128         {
129             results = dao.getArtifactDAO().queryArtifacts( new ArtifactsByChecksumConstraint(
130                 checksumSha1, ArtifactsByChecksumConstraint.SHA1 ) );
131         }
132         catch ( ObjectNotFoundException e )
133         {
134             getLogger().debug( "No duplicates for artifact: " + artifact );
135             return;
136         }
137         catch ( ArchivaDatabaseException e )
138         {
139             getLogger().warn( "Unable to query DB for potential duplicates with : " + artifact );
140             return;
141         }
142
143         if ( CollectionUtils.isNotEmpty( results ) )
144         {
145             if ( results.size() <= 1 )
146             {
147                 // No duplicates detected.
148                 getLogger().debug( "Found no duplicate artifact results on: " + artifact );
149                 return;
150             }
151
152             for ( ArchivaArtifact dupArtifact : results )
153             {
154                 if ( dupArtifact.equals( artifact ) )
155                 {
156                     // Skip reference to itself.
157                     continue;
158                 }
159
160                 RepositoryProblem problem = new RepositoryProblem();
161                 problem.setRepositoryId( dupArtifact.getModel().getRepositoryId() );
162                 problem.setPath( toPath( dupArtifact ) );
163                 problem.setGroupId( artifact.getGroupId() );
164                 problem.setArtifactId( artifact.getArtifactId() );
165                 problem.setVersion( artifact.getVersion() );
166                 problem.setType( DuplicateArtifactReport.PROBLEM_TYPE_DUPLICATE_ARTIFACTS );
167                 problem.setOrigin( getId() );
168                 problem.setMessage( "Duplicate Artifact Detected: " + artifact + " <--> " + dupArtifact );
169
170                 try
171                 {
172                     getLogger().debug( "Found duplicate artifact: " + problem );
173                     dao.getRepositoryProblemDAO().saveRepositoryProblem( problem );
174                 }
175                 catch ( ArchivaDatabaseException e )
176                 {
177                     String emsg = "Unable to save problem with duplicate artifact to DB: " + e.getMessage();
178                     getLogger().warn( emsg, e );
179                     throw new ConsumerException( emsg, e );
180                 }
181             }
182         }
183     }
184
185     private String toPath( ArchivaArtifact artifact )
186     {
187         try
188         {
189             String repoId = artifact.getModel().getRepositoryId();
190             ManagedRepositoryContent repo = repositoryFactory.getManagedRepositoryContent( repoId );
191             return repo.toPath( artifact );
192         }
193         catch ( RepositoryException e )
194         {
195             getLogger().warn( "Unable to calculate path for artifact: " + artifact );
196             return "";
197         }
198     }
199
200     public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
201     {
202         if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
203         {
204             initIncludes();
205         }
206     }
207
208     public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
209     {
210         /* do nothing */
211     }
212
213     private void initIncludes()
214     {
215         includes.clear();
216
217         includes.addAll( filetypes.getFileTypePatterns( FileTypes.ARTIFACTS ) );
218     }
219
220     public void initialize()
221         throws InitializationException
222     {
223         initIncludes();
224         configuration.addChangeListener( this );
225     }
226 }