]> source.dussan.org Git - archiva.git/blob
a9fe1fc5f29b5a325db9bf54635de9db326ba0b9
[archiva.git] /
1 package org.apache.maven.archiva.reporting.processor;
2
3 /*
4  * Copyright 2005-2006 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 import org.apache.maven.archiva.layer.RepositoryQueryLayer;
20 import org.apache.maven.archiva.layer.RepositoryQueryLayerFactory;
21 import org.apache.maven.archiva.reporting.processor.MetadataReportProcessor;
22 import org.apache.maven.archiva.reporting.database.ReportingDatabase;
23 import org.apache.maven.artifact.Artifact;
24 import org.apache.maven.artifact.factory.ArtifactFactory;
25 import org.apache.maven.artifact.repository.ArtifactRepository;
26 import org.apache.maven.artifact.repository.metadata.Plugin;
27 import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
28 import org.apache.maven.artifact.repository.metadata.Snapshot;
29 import org.apache.maven.artifact.repository.metadata.Versioning;
30 import org.codehaus.plexus.util.FileUtils;
31 import org.apache.commons.lang.StringUtils;
32
33 import java.io.File;
34 import java.io.IOException;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.HashMap;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.Map;
42
43 /**
44  * This class will report on bad metadata files.  These include invalid version declarations and incomplete version
45  * information inside the metadata file.  Plugin metadata will be checked for validity of the latest plugin artifacts.
46  *
47  * @plexus.component role="org.apache.maven.archiva.reporting.processor.MetadataReportProcessor" role-hint="bad-metadata"
48  */
49 public class BadMetadataReportProcessor
50     implements MetadataReportProcessor
51 {
52     /**
53      * @plexus.requirement
54      */
55     private ArtifactFactory artifactFactory;
56
57     /**
58      * @plexus.requirement
59      */
60     private RepositoryQueryLayerFactory repositoryQueryLayerFactory;
61
62     private static final String ROLE_HINT = "bad-metadata";
63
64     /**
65      * Process the metadata encountered in the repository and report all errors found, if any.
66      *
67      * @param metadata   the metadata to be processed.
68      * @param repository the repository where the metadata was encountered
69      * @param reporter   the ReportingDatabase to receive processing results
70      */
71     public void processMetadata( RepositoryMetadata metadata, ArtifactRepository repository,
72                                  ReportingDatabase reporter )
73     {
74         if ( metadata.storedInGroupDirectory() )
75         {
76             try
77             {
78                 checkPluginMetadata( metadata, repository, reporter );
79             }
80             catch ( IOException e )
81             {
82                 addWarning( reporter, metadata, null, "Error getting plugin artifact directories versions: " + e );
83             }
84         }
85         else
86         {
87             Versioning versioning = metadata.getMetadata().getVersioning();
88             boolean found = false;
89             if ( versioning != null )
90             {
91                 String lastUpdated = versioning.getLastUpdated();
92                 if ( lastUpdated != null && lastUpdated.length() != 0 )
93                 {
94                     found = true;
95                 }
96             }
97             if ( !found )
98             {
99                 addFailure( reporter, metadata, "missing-last-updated",
100                             "Missing lastUpdated element inside the metadata." );
101             }
102
103             if ( metadata.storedInArtifactVersionDirectory() )
104             {
105                 checkSnapshotMetadata( metadata, repository, reporter );
106             }
107             else
108             {
109                 checkMetadataVersions( metadata, repository, reporter );
110
111                 try
112                 {
113                     checkRepositoryVersions( metadata, repository, reporter );
114                 }
115                 catch ( IOException e )
116                 {
117                     String reason = "Error getting plugin artifact directories versions: " + e;
118                     addWarning( reporter, metadata, null, reason );
119                 }
120             }
121         }
122     }
123
124     private static void addWarning( ReportingDatabase reporter, RepositoryMetadata metadata, String problem,
125                                     String reason )
126     {
127         // TODO: reason could be an i18n key derived from the processor and the problem ID and the
128         reporter.addWarning( metadata, ROLE_HINT, problem, reason );
129     }
130
131     /**
132      * Method for processing a GroupRepositoryMetadata
133      *
134      * @param metadata   the metadata to be processed.
135      * @param repository the repository where the metadata was encountered
136      * @param reporter   the ReportingDatabase to receive processing results
137      */
138     private void checkPluginMetadata( RepositoryMetadata metadata, ArtifactRepository repository,
139                                       ReportingDatabase reporter )
140         throws IOException
141     {
142         File metadataDir =
143             new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( metadata ) ).getParentFile();
144         List pluginDirs = getArtifactIdFiles( metadataDir );
145
146         Map prefixes = new HashMap();
147         for ( Iterator plugins = metadata.getMetadata().getPlugins().iterator(); plugins.hasNext(); )
148         {
149             Plugin plugin = (Plugin) plugins.next();
150
151             String artifactId = plugin.getArtifactId();
152             if ( artifactId == null || artifactId.length() == 0 )
153             {
154                 addFailure( reporter, metadata, "missing-artifact-id:" + plugin.getPrefix(),
155                             "Missing or empty artifactId in group metadata for plugin " + plugin.getPrefix() );
156             }
157
158             String prefix = plugin.getPrefix();
159             if ( prefix == null || prefix.length() == 0 )
160             {
161                 addFailure( reporter, metadata, "missing-plugin-prefix:" + artifactId,
162                             "Missing or empty plugin prefix for artifactId " + artifactId + "." );
163             }
164             else
165             {
166                 if ( prefixes.containsKey( prefix ) )
167                 {
168                     addFailure( reporter, metadata, "duplicate-plugin-prefix:" + prefix,
169                                 "Duplicate plugin prefix found: " + prefix + "." );
170                 }
171                 else
172                 {
173                     prefixes.put( prefix, plugin );
174                 }
175             }
176
177             if ( artifactId != null && artifactId.length() > 0 )
178             {
179                 File pluginDir = new File( metadataDir, artifactId );
180                 if ( !pluginDirs.contains( pluginDir ) )
181                 {
182                     addFailure( reporter, metadata, "missing-plugin-from-repository:" + artifactId,
183                                 "Metadata plugin " + artifactId + " not found in the repository" );
184                 }
185                 else
186                 {
187                     pluginDirs.remove( pluginDir );
188                 }
189             }
190         }
191
192         if ( pluginDirs.size() > 0 )
193         {
194             for ( Iterator plugins = pluginDirs.iterator(); plugins.hasNext(); )
195             {
196                 File plugin = (File) plugins.next();
197                 addFailure( reporter, metadata, "missing-plugin-from-metadata:" + plugin.getName(), "Plugin " +
198                     plugin.getName() + " is present in the repository but " + "missing in the metadata." );
199             }
200         }
201     }
202
203     /**
204      * Method for processing a SnapshotArtifactRepository
205      *
206      * @param metadata   the metadata to be processed.
207      * @param repository the repository where the metadata was encountered
208      * @param reporter   the ReportingDatabase to receive processing results
209      */
210     private void checkSnapshotMetadata( RepositoryMetadata metadata, ArtifactRepository repository,
211                                         ReportingDatabase reporter )
212     {
213         RepositoryQueryLayer repositoryQueryLayer =
214             repositoryQueryLayerFactory.createRepositoryQueryLayer( repository );
215
216         Versioning versioning = metadata.getMetadata().getVersioning();
217         if ( versioning != null )
218         {
219             Snapshot snapshot = versioning.getSnapshot();
220
221             String version = StringUtils.replace( metadata.getBaseVersion(), Artifact.SNAPSHOT_VERSION,
222                                                   snapshot.getTimestamp() + "-" + snapshot.getBuildNumber() );
223             Artifact artifact =
224                 artifactFactory.createProjectArtifact( metadata.getGroupId(), metadata.getArtifactId(), version );
225             artifact.isSnapshot(); // trigger baseVersion correction
226
227             if ( !repositoryQueryLayer.containsArtifact( artifact ) )
228             {
229                 addFailure( reporter, metadata, "missing-snapshot-artifact-from-repository:" + version,
230                             "Snapshot artifact " + version + " does not exist." );
231             }
232         }
233     }
234
235     /**
236      * Method for validating the versions declared inside an ArtifactRepositoryMetadata
237      *
238      * @param metadata   the metadata to be processed.
239      * @param repository the repository where the metadata was encountered
240      * @param reporter   the ReportingDatabase to receive processing results
241      */
242     private void checkMetadataVersions( RepositoryMetadata metadata, ArtifactRepository repository,
243                                         ReportingDatabase reporter )
244     {
245         RepositoryQueryLayer repositoryQueryLayer =
246             repositoryQueryLayerFactory.createRepositoryQueryLayer( repository );
247
248         Versioning versioning = metadata.getMetadata().getVersioning();
249         if ( versioning != null )
250         {
251             for ( Iterator versions = versioning.getVersions().iterator(); versions.hasNext(); )
252             {
253                 String version = (String) versions.next();
254
255                 Artifact artifact =
256                     artifactFactory.createProjectArtifact( metadata.getGroupId(), metadata.getArtifactId(), version );
257
258                 if ( !repositoryQueryLayer.containsArtifact( artifact ) )
259                 {
260                     addFailure( reporter, metadata, "missing-artifact-from-repository:" + version, "Artifact version " +
261                         version + " is present in metadata but " + "missing in the repository." );
262                 }
263             }
264         }
265     }
266
267     /**
268      * Searches the artifact repository directory for all versions and verifies that all of them are listed in the
269      * ArtifactRepositoryMetadata
270      *
271      * @param metadata   the metadata to be processed.
272      * @param repository the repository where the metadata was encountered
273      * @param reporter   the ReportingDatabase to receive processing results
274      * @throws java.io.IOException if there is a problem reading from the file system
275      */
276     private void checkRepositoryVersions( RepositoryMetadata metadata, ArtifactRepository repository,
277                                           ReportingDatabase reporter )
278         throws IOException
279     {
280         Versioning versioning = metadata.getMetadata().getVersioning();
281         List metadataVersions = versioning != null ? versioning.getVersions() : Collections.EMPTY_LIST;
282         File versionsDir =
283             new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( metadata ) ).getParentFile();
284
285         // TODO: I don't know how this condition can happen, but it was seen on the main repository.
286         // Avoid hard failure
287         if ( versionsDir.exists() )
288         {
289             List versions = FileUtils.getFileNames( versionsDir, "*/*.pom", null, false );
290             for ( Iterator i = versions.iterator(); i.hasNext(); )
291             {
292                 File path = new File( (String) i.next() );
293                 String version = path.getParentFile().getName();
294                 if ( !metadataVersions.contains( version ) )
295                 {
296                     addFailure( reporter, metadata, "missing-artifact-from-metadata:" + version, "Artifact version " +
297                         version + " found in the repository but " + "missing in the metadata." );
298                 }
299             }
300         }
301         else
302         {
303             addFailure( reporter, metadata, null, "Metadata's directory did not exist: " + versionsDir );
304         }
305     }
306
307     /**
308      * Used to gather artifactIds from a groupId directory.
309      *
310      * @param groupIdDir the directory of the group
311      * @return the list of artifact ID File objects for each directory
312      * @throws IOException if there was a failure to read the directories
313      */
314     private List getArtifactIdFiles( File groupIdDir )
315         throws IOException
316     {
317         List artifactIdFiles = new ArrayList();
318
319         File[] files = groupIdDir.listFiles();
320         if ( files != null )
321         {
322             for ( Iterator i = Arrays.asList( files ).iterator(); i.hasNext(); )
323             {
324                 File artifactDir = (File) i.next();
325
326                 if ( artifactDir.isDirectory() )
327                 {
328                     List versions = FileUtils.getFileNames( artifactDir, "*/*.pom", null, false );
329                     if ( versions.size() > 0 )
330                     {
331                         artifactIdFiles.add( artifactDir );
332                     }
333                 }
334             }
335         }
336
337         return artifactIdFiles;
338     }
339
340     private static void addFailure( ReportingDatabase reporter, RepositoryMetadata metadata, String problem,
341                                     String reason )
342     {
343         // TODO: reason could be an i18n key derived from the processor and the problem ID and the
344         reporter.addFailure( metadata, ROLE_HINT, problem, reason );
345     }
346 }