]> source.dussan.org Git - archiva.git/blob
58e1dd9cce52df003d212f223406ca07ddd0240f
[archiva.git] /
1 package org.apache.maven.archiva.consumers.database;
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 java.io.File;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.maven.archiva.common.utils.VersionUtil;
28 import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
29 import org.apache.maven.archiva.consumers.ConsumerException;
30 import org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer;
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.model.ArchivaArtifact;
35 import org.apache.maven.archiva.model.ArchivaProjectModel;
36 import org.apache.maven.archiva.model.Keys;
37 import org.apache.maven.archiva.model.RepositoryProblem;
38 import org.apache.maven.archiva.reporting.artifact.CorruptArtifactReport;
39 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
40 import org.apache.maven.archiva.repository.RepositoryContentFactory;
41 import org.apache.maven.archiva.repository.RepositoryException;
42 import org.apache.maven.archiva.repository.content.ManagedLegacyRepositoryContent;
43 import org.apache.maven.archiva.repository.project.ProjectModelException;
44 import org.apache.maven.archiva.repository.project.ProjectModelFilter;
45 import org.apache.maven.archiva.repository.project.ProjectModelReader;
46 import org.apache.maven.archiva.repository.project.filters.EffectiveProjectModelFilter;
47 import org.apache.maven.archiva.repository.project.readers.ProjectModel300Reader;
48 import org.apache.maven.archiva.repository.project.readers.ProjectModel400Reader;
49 import org.codehaus.plexus.cache.Cache;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 /**
54  * ProjectModelToDatabaseConsumer
55  *
56  * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
57  * @version $Id$
58  * @plexus.component role="org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer"
59  * role-hint="update-db-project"
60  * instantiation-strategy="per-lookup"
61  */
62 public class ProjectModelToDatabaseConsumer
63     extends AbstractMonitoredConsumer
64     implements DatabaseUnprocessedArtifactConsumer
65 {
66     private Logger log = LoggerFactory.getLogger( ProjectModelToDatabaseConsumer.class );
67
68     /**
69      * @plexus.configuration default-value="update-db-project"
70      */
71     private String id;
72
73     /**
74      * @plexus.configuration default-value="Update database with project model information."
75      */
76     private String description;
77
78     /**
79      * @plexus.requirement role-hint="jdo"
80      */
81     private ArchivaDAO dao;
82
83     /**
84      * @plexus.requirement
85      */
86     private RepositoryContentFactory repositoryFactory;
87
88     /**
89      * @plexus.requirement role-hint="expression"
90      */
91     private ProjectModelFilter expressionModelFilter;
92
93     /**
94      * @plexus.requirement role="org.apache.maven.archiva.repository.project.ProjectModelFilter"
95      * role-hint="effective"
96      */
97     private EffectiveProjectModelFilter effectiveModelFilter;
98
99     private List<String> includes;
100
101     /**
102      * @plexus.requirement role-hint="effective-project-cache"
103      */
104     private Cache effectiveProjectCache;
105
106     public ProjectModelToDatabaseConsumer()
107     {
108         includes = new ArrayList<String>();
109         includes.add( "pom" );
110     }
111
112     public void beginScan()
113     {
114         /* nothing to do here */
115     }
116
117     public void completeScan()
118     {
119         /* nothing to do here */
120     }
121
122     public List<String> getIncludedTypes()
123     {
124         return includes;
125     }
126
127     public void processArchivaArtifact( ArchivaArtifact artifact )
128         throws ConsumerException
129     {
130         if ( !StringUtils.equals( "pom", artifact.getType() ) )
131         {
132             // Not a pom.  Skip it.
133             return;
134         }
135         
136         ArchivaProjectModel model = null;
137         
138         // remove old project model if it already exists in the database
139         if ( ( model =
140             getProjectModelFromDatabase( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() ) ) != null )
141         {
142             removeOldProjectModel( model );
143             model = null;
144         }
145
146         ManagedRepositoryContent repo = getRepository( artifact );
147         File artifactFile = repo.toFile( artifact );
148         
149         ProjectModelReader reader;
150         if ( repo instanceof ManagedLegacyRepositoryContent )
151         {
152             reader = new ProjectModel300Reader();
153         }
154         else
155         {
156             reader = new ProjectModel400Reader();
157         }
158
159         try
160         {
161             model = reader.read( artifactFile );
162
163             model.setOrigin( "filesystem" );
164
165             // The version should be updated to the artifact/filename version if it is a unique snapshot
166             if ( VersionUtil.isUniqueSnapshot( artifact.getVersion() ) )
167             {
168                 model.setVersion( artifact.getVersion() );
169             }
170
171             // Filter the model
172             model = expressionModelFilter.filter( model );
173
174             // Resolve the project model
175             model = effectiveModelFilter.filter( model );
176
177             if ( isValidModel( model, repo, artifact ) )
178             {
179                 log.debug( "Adding project model to database - " + Keys.toKey( model ) );
180                 dao.getProjectModelDAO().saveProjectModel( model );
181             }
182             else
183             {
184                 log.warn( "Invalid or corrupt pom. Project model not added to database - " + Keys.toKey( model ) );
185             }
186
187         }
188         catch ( ProjectModelException e )
189         {
190             log.warn( "Unable to read project model " + artifactFile + " : " + e.getMessage(), e );
191
192             addProblem( artifact, "Unable to read project model " + artifactFile + " : " + e.getMessage() );
193         }
194         catch ( ArchivaDatabaseException e )
195         {
196             log.warn( "Unable to save project model " + artifactFile + " to the database : " + e.getMessage(), e );
197         }
198         catch ( Throwable t )
199         {
200             // Catch the other errors in the process to allow the rest of the process to complete.
201             log.error( "Unable to process model " + artifactFile + " due to : " + t.getClass().getName() + " : " +
202                 t.getMessage(), t );
203         }
204     }
205
206     private ArchivaProjectModel getProjectModelFromDatabase( String groupId, String artifactId, String version )
207     {
208         try
209         {
210             ArchivaProjectModel model = dao.getProjectModelDAO().getProjectModel( groupId, artifactId, version );
211             return model;
212         }
213         catch ( ObjectNotFoundException e )
214         {
215             return null;
216         }
217         catch ( ArchivaDatabaseException e )
218         {
219             return null;
220         }
221     }
222
223     private ManagedRepositoryContent getRepository( ArchivaArtifact artifact )
224         throws ConsumerException
225     {
226         String repoId = artifact.getModel().getRepositoryId();
227         try
228         {
229             return repositoryFactory.getManagedRepositoryContent( repoId );
230         }
231         catch ( RepositoryException e )
232         {
233             throw new ConsumerException( "Unable to process project model: " + e.getMessage(), e );
234         }
235     }
236
237     public String getDescription()
238     {
239         return description;
240     }
241
242     public String getId()
243     {
244         return id;
245     }
246
247     public boolean isPermanent()
248     {
249         // Tells the configuration that this consumer cannot be disabled.
250         return true;
251     }
252
253     private boolean isValidModel( ArchivaProjectModel model, ManagedRepositoryContent repo, ArchivaArtifact artifact )
254         throws ConsumerException
255     {
256         File artifactFile = repo.toFile( artifact );
257
258         if ( !artifact.getArtifactId().equalsIgnoreCase( model.getArtifactId() ) )
259         {
260             StringBuffer emsg = new StringBuffer();
261             emsg.append( "File " ).append( artifactFile.getName() );
262             emsg.append( " has an invalid project model [" );
263             appendModel( emsg, model );
264             emsg.append( "]: The model artifactId [" ).append( model.getArtifactId() );
265             emsg.append( "] does not match the artifactId portion of the filename: " ).append( artifact.getArtifactId() );
266
267             log.warn( emsg.toString() );
268             addProblem( artifact, emsg.toString() );
269
270             return false;
271         }
272
273         if ( !artifact.getVersion().equalsIgnoreCase( model.getVersion() ) &&
274             !VersionUtil.getBaseVersion( artifact.getVersion() ).equalsIgnoreCase( model.getVersion() ) )
275         {
276             StringBuffer emsg = new StringBuffer();
277             emsg.append( "File " ).append( artifactFile.getName() );
278             emsg.append( " has an invalid project model [" );
279             appendModel( emsg, model );
280             emsg.append( "]; The model version [" ).append( model.getVersion() );
281             emsg.append( "] does not match the version portion of the filename: " ).append( artifact.getVersion() );
282
283             log.warn( emsg.toString() );
284             addProblem( artifact, emsg.toString() );
285
286             return false;
287         }
288
289         return true;
290     }
291
292     private void appendModel( StringBuffer buf, ArchivaProjectModel model )
293     {
294         buf.append( "groupId:" ).append( model.getGroupId() );
295         buf.append( "|artifactId:" ).append( model.getArtifactId() );
296         buf.append( "|version:" ).append( model.getVersion() );
297         buf.append( "|packaging:" ).append( model.getPackaging() );
298     }
299
300     private void addProblem( ArchivaArtifact artifact, String msg )
301         throws ConsumerException
302     {
303         ManagedRepositoryContent repo = getRepository( artifact );
304
305         RepositoryProblem problem = new RepositoryProblem();
306         problem.setRepositoryId( artifact.getModel().getRepositoryId() );
307         problem.setPath( repo.toPath( artifact ) );
308         problem.setGroupId( artifact.getGroupId() );
309         problem.setArtifactId( artifact.getArtifactId() );
310         problem.setVersion( artifact.getVersion() );
311         problem.setType( CorruptArtifactReport.PROBLEM_TYPE_CORRUPT_ARTIFACT );
312         problem.setOrigin( getId() );
313         problem.setMessage( msg );
314
315         try
316         {
317             dao.getRepositoryProblemDAO().saveRepositoryProblem( problem );
318         }
319         catch ( ArchivaDatabaseException e )
320         {
321             String emsg = "Unable to save problem with artifact location to DB: " + e.getMessage();
322             log.warn( emsg, e );
323             throw new ConsumerException( emsg, e );
324         }
325     }
326
327     private String toProjectKey( ArchivaProjectModel project )
328     {
329         StringBuilder key = new StringBuilder();
330
331         key.append( project.getGroupId() ).append( ":" );
332         key.append( project.getArtifactId() ).append( ":" );
333         key.append( project.getVersion() );
334
335         return key.toString();
336     }
337
338     private void removeOldProjectModel( ArchivaProjectModel model )
339     {
340         try
341         {
342             dao.getProjectModelDAO().deleteProjectModel( model );
343         }
344         catch ( ArchivaDatabaseException ae )
345         {
346             log.error( "Unable to delete existing project model." );
347         }
348
349         // Force removal of project model from effective cache
350         String projectKey = toProjectKey( model );
351         synchronized ( effectiveProjectCache )
352         {
353             if ( effectiveProjectCache.hasKey( projectKey ) )
354             {
355                 effectiveProjectCache.remove( projectKey );
356             }
357         }
358     }
359     
360 }