1 package org.apache.maven.archiva.reporting;
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.discoverer.ArtifactDiscoverer;
20 import org.apache.maven.archiva.discoverer.DiscovererException;
21 import org.apache.maven.archiva.discoverer.MetadataDiscoverer;
22 import org.apache.maven.archiva.discoverer.filter.AcceptAllMetadataFilter;
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.layout.ArtifactRepositoryLayout;
27 import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
28 import org.apache.maven.artifact.repository.layout.LegacyRepositoryLayout;
29 import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
30 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
31 import org.apache.maven.model.Model;
32 import org.apache.maven.project.MavenProject;
33 import org.apache.maven.project.MavenProjectBuilder;
34 import org.apache.maven.project.ProjectBuildingException;
35 import org.codehaus.plexus.logging.AbstractLogEnabled;
38 import java.util.Collections;
39 import java.util.Iterator;
40 import java.util.List;
44 * Report executor implementation.
48 public class DefaultReportExecutor
49 extends AbstractLogEnabled
50 implements ReportExecutor
55 private MavenProjectBuilder projectBuilder;
60 private ReportingStore reportingStore;
65 private ArtifactFactory artifactFactory;
68 * @todo replace with a ReportGroup that is identified as "health" and has requirements on the specific health reports
69 * @plexus.requirement role="org.apache.maven.archiva.reporting.ArtifactReportProcessor"
71 private List artifactReports;
74 * @plexus.requirement role="org.apache.maven.archiva.reporting.MetadataReportProcessor"
76 private List metadataReports;
79 * @plexus.requirement role="org.apache.maven.archiva.discoverer.ArtifactDiscoverer"
81 private Map artifactDiscoverers;
84 * @plexus.requirement role="org.apache.maven.archiva.discoverer.MetadataDiscoverer"
86 private Map metadataDiscoverers;
88 private static final int ARTIFACT_BUFFER_SIZE = 1000;
90 public void runMetadataReports( List metadata, ArtifactRepository repository )
91 throws ReportingStoreException
93 ReportingDatabase reporter = getReportDatabase( repository );
95 for ( Iterator i = metadata.iterator(); i.hasNext(); )
97 RepositoryMetadata repositoryMetadata = (RepositoryMetadata) i.next();
100 new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( repositoryMetadata ) );
101 reporter.cleanMetadata( repositoryMetadata, file.lastModified() );
103 // TODO: should the report set be limitable by configuration?
104 runMetadataReports( repositoryMetadata, repository, reporter );
107 reportingStore.storeReports( reporter, repository );
110 private void runMetadataReports( RepositoryMetadata repositoryMetadata, ArtifactRepository repository,
111 ReportingDatabase reporter )
113 for ( Iterator i = metadataReports.iterator(); i.hasNext(); )
115 MetadataReportProcessor report = (MetadataReportProcessor) i.next();
117 report.processMetadata( repositoryMetadata, repository, reporter );
121 public void runArtifactReports( List artifacts, ArtifactRepository repository )
122 throws ReportingStoreException
124 ReportingDatabase reporter = getReportDatabase( repository );
126 for ( Iterator i = artifacts.iterator(); i.hasNext(); )
128 Artifact artifact = (Artifact) i.next();
133 Artifact pomArtifact = artifactFactory.createProjectArtifact( artifact.getGroupId(),
134 artifact.getArtifactId(),
135 artifact.getVersion() );
136 MavenProject project =
137 projectBuilder.buildFromRepository( pomArtifact, Collections.EMPTY_LIST, repository );
139 model = project.getModel();
141 catch ( ProjectBuildingException e )
143 reporter.addWarning( artifact, "Error reading project model: " + e );
146 reporter.removeArtifact( artifact );
148 runArtifactReports( artifact, model, reporter );
151 reportingStore.storeReports( reporter, repository );
154 public ReportingDatabase getReportDatabase( ArtifactRepository repository )
155 throws ReportingStoreException
157 getLogger().debug( "Reading previous report database from repository " + repository.getId() );
158 return reportingStore.getReportsFromStore( repository );
161 public void runReports( ArtifactRepository repository, List blacklistedPatterns, ArtifactFilter filter )
162 throws DiscovererException, ReportingStoreException
164 // Flush (as in toilet, not store) the report database
165 ReportingDatabase database = getReportDatabase( repository );
169 String layoutProperty = getRepositoryLayout( repository.getLayout() );
170 ArtifactDiscoverer discoverer = (ArtifactDiscoverer) artifactDiscoverers.get( layoutProperty );
172 // Save some memory by not tracking paths we won't use
173 // TODO: Plexus CDC should be able to inject this configuration
174 discoverer.setTrackOmittedPaths( false );
176 List artifacts = discoverer.discoverArtifacts( repository, blacklistedPatterns, filter );
178 if ( !artifacts.isEmpty() )
180 getLogger().info( "Discovered " + artifacts.size() + " artifacts" );
182 // Work through these in batches, then flush the project cache.
183 for ( int j = 0; j < artifacts.size(); j += ARTIFACT_BUFFER_SIZE )
185 int end = j + ARTIFACT_BUFFER_SIZE;
186 List currentArtifacts = artifacts.subList( j, end > artifacts.size() ? artifacts.size() : end );
188 // TODO: proper queueing of this in case it was triggered externally (not harmful to do so at present, but not optimal)
191 runArtifactReports( currentArtifacts, repository );
194 // MNG-142 - the project builder retains a lot of objects in its inflexible cache. This is a hack
195 // around that. TODO: remove when it is configurable
196 flushProjectBuilderCacheHack();
199 MetadataDiscoverer metadataDiscoverer = (MetadataDiscoverer) metadataDiscoverers.get( layoutProperty );
201 metadataDiscoverer.discoverMetadata( repository, blacklistedPatterns, new AcceptAllMetadataFilter() );
203 if ( !metadata.isEmpty() )
205 getLogger().info( "Discovered " + metadata.size() + " metadata files" );
208 runMetadataReports( metadata, repository );
212 private String getRepositoryLayout( ArtifactRepositoryLayout layout )
214 // gross limitation that there is no reverse lookup of the hint for the layout.
215 if ( layout.getClass().equals( DefaultRepositoryLayout.class ) )
219 else if ( layout.getClass().equals( LegacyRepositoryLayout.class ) )
225 throw new IllegalArgumentException( "Unknown layout: " + layout );
229 private void runArtifactReports( Artifact artifact, Model model, ReportingDatabase reporter )
231 // TODO: should the report set be limitable by configuration?
232 for ( Iterator i = artifactReports.iterator(); i.hasNext(); )
234 ArtifactReportProcessor report = (ArtifactReportProcessor) i.next();
236 report.processArtifact( artifact, model, reporter );
240 private void flushProjectBuilderCacheHack()
244 if ( projectBuilder != null )
246 java.lang.reflect.Field f = projectBuilder.getClass().getDeclaredField( "rawProjectCache" );
247 f.setAccessible( true );
248 Map cache = (Map) f.get( projectBuilder );
251 f = projectBuilder.getClass().getDeclaredField( "processedProjectCache" );
252 f.setAccessible( true );
253 cache = (Map) f.get( projectBuilder );
257 catch ( NoSuchFieldException e )
259 throw new RuntimeException( e );
261 catch ( IllegalAccessException e )
263 throw new RuntimeException( e );