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