]> source.dussan.org Git - archiva.git/blob
7eab35512d022bbec622cbce6e93e993febb474c
[archiva.git] /
1 package org.apache.maven.archiva.reporting;
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.artifact.Artifact;
22 import org.apache.maven.artifact.factory.ArtifactFactory;
23 import org.apache.maven.artifact.repository.ArtifactRepository;
24 import org.apache.maven.artifact.repository.metadata.Plugin;
25 import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
26 import org.apache.maven.artifact.repository.metadata.Snapshot;
27 import org.apache.maven.artifact.repository.metadata.Versioning;
28 import org.codehaus.plexus.util.FileUtils;
29 import org.codehaus.plexus.util.StringUtils;
30
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39
40 /**
41  * This class will report on bad metadata files.  These include invalid version declarations and incomplete version
42  * information inside the metadata file.  Plugin metadata will be checked for validity of the latest plugin artifacts.
43  *
44  * @plexus.component role="org.apache.maven.archiva.reporting.MetadataReportProcessor" role-hint="bad-metadata"
45  */
46 public class BadMetadataReportProcessor
47     implements MetadataReportProcessor
48 {
49     /**
50      * @plexus.requirement
51      */
52     private ArtifactFactory artifactFactory;
53
54     /**
55      * @plexus.requirement
56      */
57     private RepositoryQueryLayerFactory repositoryQueryLayerFactory;
58
59     /**
60      * Process the metadata encountered in the repository and report all errors found, if any.
61      *
62      * @param metadata   the metadata to be processed.
63      * @param repository the repository where the metadata was encountered
64      * @param reporter   the ArtifactReporter to receive processing results
65      * @throws ReportProcessorException if an error was occurred while processing the metadata
66      */
67     public void processMetadata( RepositoryMetadata metadata, ArtifactRepository repository, ArtifactReporter reporter )
68         throws ReportProcessorException
69     {
70         boolean hasFailures = false;
71
72         if ( metadata.storedInGroupDirectory() )
73         {
74             try
75             {
76                 hasFailures = checkPluginMetadata( metadata, repository, reporter );
77             }
78             catch ( IOException e )
79             {
80                 throw new ReportProcessorException( "Error getting plugin artifact directories versions", e );
81             }
82         }
83         else
84         {
85             String lastUpdated = metadata.getMetadata().getVersioning().getLastUpdated();
86             if ( lastUpdated == null || lastUpdated.length() == 0 )
87             {
88                 reporter.addFailure( metadata, "Missing lastUpdated element inside the metadata." );
89                 hasFailures = true;
90             }
91
92             if ( metadata.storedInArtifactVersionDirectory() )
93             {
94                 hasFailures |= checkSnapshotMetadata( metadata, repository, reporter );
95             }
96             else
97             {
98                 if ( !checkMetadataVersions( metadata, repository, reporter ) )
99                 {
100                     hasFailures = true;
101                 }
102
103                 try
104                 {
105                     if ( checkRepositoryVersions( metadata, repository, reporter ) )
106                     {
107                         hasFailures = true;
108                     }
109                 }
110                 catch ( IOException e )
111                 {
112                     throw new ReportProcessorException( "Error getting versions", e );
113                 }
114             }
115         }
116
117         if ( !hasFailures )
118         {
119             reporter.addSuccess( metadata );
120         }
121     }
122
123     /**
124      * Method for processing a GroupRepositoryMetadata
125      *
126      * @param metadata   the metadata to be processed.
127      * @param repository the repository where the metadata was encountered
128      * @param reporter   the ArtifactReporter to receive processing results
129      */
130     private boolean checkPluginMetadata( RepositoryMetadata metadata, ArtifactRepository repository,
131                                          ArtifactReporter reporter )
132         throws IOException
133     {
134         boolean hasFailures = false;
135
136         File metadataDir =
137             new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( metadata ) ).getParentFile();
138         List pluginDirs = getArtifactIdFiles( metadataDir );
139
140         Map prefixes = new HashMap();
141         for ( Iterator plugins = metadata.getMetadata().getPlugins().iterator(); plugins.hasNext(); )
142         {
143             Plugin plugin = (Plugin) plugins.next();
144
145             String artifactId = plugin.getArtifactId();
146             if ( artifactId == null || artifactId.length() == 0 )
147             {
148                 reporter.addFailure( metadata, "Missing or empty artifactId in group metadata." );
149                 hasFailures = true;
150             }
151
152             String prefix = plugin.getPrefix();
153             if ( prefix == null || prefix.length() == 0 )
154             {
155                 reporter.addFailure( metadata, "Missing or empty plugin prefix for artifactId " + artifactId + "." );
156                 hasFailures = true;
157             }
158             else
159             {
160                 if ( prefixes.containsKey( prefix ) )
161                 {
162                     reporter.addFailure( metadata, "Duplicate plugin prefix found: " + prefix + "." );
163                     hasFailures = true;
164                 }
165                 else
166                 {
167                     prefixes.put( prefix, plugin );
168                 }
169             }
170
171             if ( artifactId != null && artifactId.length() > 0 )
172             {
173                 File pluginDir = new File( metadataDir, artifactId );
174                 if ( !pluginDirs.contains( pluginDir ) )
175                 {
176                     reporter.addFailure( metadata, "Metadata plugin " + artifactId + " not found in the repository" );
177                     hasFailures = true;
178                 }
179                 else
180                 {
181                     pluginDirs.remove( pluginDir );
182                 }
183             }
184         }
185
186         if ( pluginDirs.size() > 0 )
187         {
188             for ( Iterator plugins = pluginDirs.iterator(); plugins.hasNext(); )
189             {
190                 File plugin = (File) plugins.next();
191                 reporter.addFailure( metadata, "Plugin " + plugin.getName() + " is present in the repository but " +
192                     "missing in the metadata." );
193             }
194             hasFailures = true;
195         }
196
197         return hasFailures;
198     }
199
200     /**
201      * Method for processing a SnapshotArtifactRepository
202      *
203      * @param metadata   the metadata to be processed.
204      * @param repository the repository where the metadata was encountered
205      * @param reporter   the ArtifactReporter to receive processing results
206      */
207     private boolean checkSnapshotMetadata( RepositoryMetadata metadata, ArtifactRepository repository,
208                                            ArtifactReporter reporter )
209     {
210         RepositoryQueryLayer repositoryQueryLayer =
211             repositoryQueryLayerFactory.createRepositoryQueryLayer( repository );
212
213         boolean hasFailures = false;
214
215         Snapshot snapshot = metadata.getMetadata().getVersioning().getSnapshot();
216
217         String version = StringUtils.replace( metadata.getBaseVersion(), Artifact.SNAPSHOT_VERSION,
218                                               snapshot.getTimestamp() + "-" + snapshot.getBuildNumber() );
219         Artifact artifact =
220             artifactFactory.createProjectArtifact( metadata.getGroupId(), metadata.getArtifactId(), version );
221         artifact.isSnapshot(); // trigger baseVersion correction
222
223         if ( !repositoryQueryLayer.containsArtifact( artifact ) )
224         {
225             reporter.addFailure( metadata, "Snapshot artifact " + version + " does not exist." );
226             hasFailures = true;
227         }
228
229         return hasFailures;
230     }
231
232     /**
233      * Method for validating the versions declared inside an ArtifactRepositoryMetadata
234      *
235      * @param metadata   the metadata to be processed.
236      * @param repository the repository where the metadata was encountered
237      * @param reporter   the ArtifactReporter to receive processing results
238      */
239     private boolean checkMetadataVersions( RepositoryMetadata metadata, ArtifactRepository repository,
240                                            ArtifactReporter reporter )
241     {
242         RepositoryQueryLayer repositoryQueryLayer =
243             repositoryQueryLayerFactory.createRepositoryQueryLayer( repository );
244
245         boolean hasFailures = false;
246         Versioning versioning = metadata.getMetadata().getVersioning();
247         for ( Iterator versions = versioning.getVersions().iterator(); versions.hasNext(); )
248         {
249             String version = (String) versions.next();
250
251             Artifact artifact =
252                 artifactFactory.createProjectArtifact( metadata.getGroupId(), metadata.getArtifactId(), version );
253
254             if ( !repositoryQueryLayer.containsArtifact( artifact ) )
255             {
256                 reporter.addFailure( metadata, "Artifact version " + version + " is present in metadata but " +
257                     "missing in the repository." );
258                 hasFailures = true;
259             }
260         }
261         return hasFailures;
262     }
263
264     /**
265      * Searches the artifact repository directory for all versions and verifies that all of them are listed in the
266      * ArtifactRepositoryMetadata
267      *
268      * @param metadata   the metadata to be processed.
269      * @param repository the repository where the metadata was encountered
270      * @param reporter   the ArtifactReporter to receive processing results
271      */
272     private boolean checkRepositoryVersions( RepositoryMetadata metadata, ArtifactRepository repository,
273                                              ArtifactReporter reporter )
274         throws IOException
275     {
276         boolean hasFailures = false;
277         Versioning versioning = metadata.getMetadata().getVersioning();
278         File versionsDir =
279             new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( metadata ) ).getParentFile();
280         List versions = FileUtils.getFileNames( versionsDir, "*/*.pom", null, false );
281         for ( Iterator i = versions.iterator(); i.hasNext(); )
282         {
283             File path = new File( (String) i.next() );
284             String version = path.getParentFile().getName();
285             if ( !versioning.getVersions().contains( version ) )
286             {
287                 reporter.addFailure( metadata, "Artifact version " + version + " found in the repository but " +
288                     "missing in the metadata." );
289                 hasFailures = true;
290             }
291         }
292         return hasFailures;
293     }
294
295     /**
296      * Used to gather artifactIds from a groupId directory.
297      *
298      * @param groupIdDir the directory of the group
299      * @return the list of artifact ID File objects for each directory
300      * @throws IOException if there was a failure to read the directories
301      */
302     private List getArtifactIdFiles( File groupIdDir )
303         throws IOException
304     {
305         List artifactIdFiles = new ArrayList();
306
307         List fileArray = new ArrayList( Arrays.asList( groupIdDir.listFiles() ) );
308         for ( Iterator files = fileArray.iterator(); files.hasNext(); )
309         {
310             File artifactDir = (File) files.next();
311
312             if ( artifactDir.isDirectory() )
313             {
314                 List versions = FileUtils.getFileNames( artifactDir, "*/*.pom", null, false );
315                 if ( versions.size() > 0 )
316                 {
317                     artifactIdFiles.add( artifactDir );
318                 }
319             }
320         }
321
322         return artifactIdFiles;
323     }
324 }