1 package org.apache.maven.archiva.reporting.processor;
4 * Copyright 2005-2006 The Apache Software Foundation.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
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;
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;
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.
47 * @plexus.component role="org.apache.maven.archiva.reporting.processor.MetadataReportProcessor" role-hint="bad-metadata"
49 public class BadMetadataReportProcessor
50 implements MetadataReportProcessor
55 private ArtifactFactory artifactFactory;
60 private RepositoryQueryLayerFactory repositoryQueryLayerFactory;
62 private static final String ROLE_HINT = "bad-metadata";
65 * Process the metadata encountered in the repository and report all errors found, if any.
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
71 public void processMetadata( RepositoryMetadata metadata, ArtifactRepository repository,
72 ReportingDatabase reporter )
74 if ( metadata.storedInGroupDirectory() )
78 checkPluginMetadata( metadata, repository, reporter );
80 catch ( IOException e )
82 addWarning( reporter, metadata, null, "Error getting plugin artifact directories versions: " + e );
87 Versioning versioning = metadata.getMetadata().getVersioning();
88 boolean found = false;
89 if ( versioning != null )
91 String lastUpdated = versioning.getLastUpdated();
92 if ( lastUpdated != null && lastUpdated.length() != 0 )
99 addFailure( reporter, metadata, "missing-last-updated",
100 "Missing lastUpdated element inside the metadata." );
103 if ( metadata.storedInArtifactVersionDirectory() )
105 checkSnapshotMetadata( metadata, repository, reporter );
109 checkMetadataVersions( metadata, repository, reporter );
113 checkRepositoryVersions( metadata, repository, reporter );
115 catch ( IOException e )
117 String reason = "Error getting plugin artifact directories versions: " + e;
118 addWarning( reporter, metadata, null, reason );
124 private static void addWarning( ReportingDatabase reporter, RepositoryMetadata metadata, String problem,
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 );
132 * Method for processing a GroupRepositoryMetadata
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
138 private void checkPluginMetadata( RepositoryMetadata metadata, ArtifactRepository repository,
139 ReportingDatabase reporter )
143 new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( metadata ) ).getParentFile();
144 List pluginDirs = getArtifactIdFiles( metadataDir );
146 Map prefixes = new HashMap();
147 for ( Iterator plugins = metadata.getMetadata().getPlugins().iterator(); plugins.hasNext(); )
149 Plugin plugin = (Plugin) plugins.next();
151 String artifactId = plugin.getArtifactId();
152 if ( artifactId == null || artifactId.length() == 0 )
154 addFailure( reporter, metadata, "missing-artifact-id:" + plugin.getPrefix(),
155 "Missing or empty artifactId in group metadata for plugin " + plugin.getPrefix() );
158 String prefix = plugin.getPrefix();
159 if ( prefix == null || prefix.length() == 0 )
161 addFailure( reporter, metadata, "missing-plugin-prefix:" + artifactId,
162 "Missing or empty plugin prefix for artifactId " + artifactId + "." );
166 if ( prefixes.containsKey( prefix ) )
168 addFailure( reporter, metadata, "duplicate-plugin-prefix:" + prefix,
169 "Duplicate plugin prefix found: " + prefix + "." );
173 prefixes.put( prefix, plugin );
177 if ( artifactId != null && artifactId.length() > 0 )
179 File pluginDir = new File( metadataDir, artifactId );
180 if ( !pluginDirs.contains( pluginDir ) )
182 addFailure( reporter, metadata, "missing-plugin-from-repository:" + artifactId,
183 "Metadata plugin " + artifactId + " not found in the repository" );
187 pluginDirs.remove( pluginDir );
192 if ( pluginDirs.size() > 0 )
194 for ( Iterator plugins = pluginDirs.iterator(); plugins.hasNext(); )
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." );
204 * Method for processing a SnapshotArtifactRepository
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
210 private void checkSnapshotMetadata( RepositoryMetadata metadata, ArtifactRepository repository,
211 ReportingDatabase reporter )
213 RepositoryQueryLayer repositoryQueryLayer =
214 repositoryQueryLayerFactory.createRepositoryQueryLayer( repository );
216 Versioning versioning = metadata.getMetadata().getVersioning();
217 if ( versioning != null )
219 Snapshot snapshot = versioning.getSnapshot();
221 String version = StringUtils.replace( metadata.getBaseVersion(), Artifact.SNAPSHOT_VERSION,
222 snapshot.getTimestamp() + "-" + snapshot.getBuildNumber() );
224 artifactFactory.createProjectArtifact( metadata.getGroupId(), metadata.getArtifactId(), version );
225 artifact.isSnapshot(); // trigger baseVersion correction
227 if ( !repositoryQueryLayer.containsArtifact( artifact ) )
229 addFailure( reporter, metadata, "missing-snapshot-artifact-from-repository:" + version,
230 "Snapshot artifact " + version + " does not exist." );
236 * Method for validating the versions declared inside an ArtifactRepositoryMetadata
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
242 private void checkMetadataVersions( RepositoryMetadata metadata, ArtifactRepository repository,
243 ReportingDatabase reporter )
245 RepositoryQueryLayer repositoryQueryLayer =
246 repositoryQueryLayerFactory.createRepositoryQueryLayer( repository );
248 Versioning versioning = metadata.getMetadata().getVersioning();
249 if ( versioning != null )
251 for ( Iterator versions = versioning.getVersions().iterator(); versions.hasNext(); )
253 String version = (String) versions.next();
256 artifactFactory.createProjectArtifact( metadata.getGroupId(), metadata.getArtifactId(), version );
258 if ( !repositoryQueryLayer.containsArtifact( artifact ) )
260 addFailure( reporter, metadata, "missing-artifact-from-repository:" + version, "Artifact version " +
261 version + " is present in metadata but " + "missing in the repository." );
268 * Searches the artifact repository directory for all versions and verifies that all of them are listed in the
269 * ArtifactRepositoryMetadata
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
276 private void checkRepositoryVersions( RepositoryMetadata metadata, ArtifactRepository repository,
277 ReportingDatabase reporter )
280 Versioning versioning = metadata.getMetadata().getVersioning();
281 List metadataVersions = versioning != null ? versioning.getVersions() : Collections.EMPTY_LIST;
283 new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( metadata ) ).getParentFile();
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() )
289 List versions = FileUtils.getFileNames( versionsDir, "*/*.pom", null, false );
290 for ( Iterator i = versions.iterator(); i.hasNext(); )
292 File path = new File( (String) i.next() );
293 String version = path.getParentFile().getName();
294 if ( !metadataVersions.contains( version ) )
296 addFailure( reporter, metadata, "missing-artifact-from-metadata:" + version, "Artifact version " +
297 version + " found in the repository but " + "missing in the metadata." );
303 addFailure( reporter, metadata, null, "Metadata's directory did not exist: " + versionsDir );
308 * Used to gather artifactIds from a groupId directory.
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
314 private List getArtifactIdFiles( File groupIdDir )
317 List artifactIdFiles = new ArrayList();
319 File[] files = groupIdDir.listFiles();
322 for ( Iterator i = Arrays.asList( files ).iterator(); i.hasNext(); )
324 File artifactDir = (File) i.next();
326 if ( artifactDir.isDirectory() )
328 List versions = FileUtils.getFileNames( artifactDir, "*/*.pom", null, false );
329 if ( versions.size() > 0 )
331 artifactIdFiles.add( artifactDir );
337 return artifactIdFiles;
340 private static void addFailure( ReportingDatabase reporter, RepositoryMetadata metadata, String problem,
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 );