]> source.dussan.org Git - archiva.git/blob
1d4e18c64e48df60c5dda5b6178aa89898d2e3a2
[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.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;
36
37 import java.io.File;
38 import java.util.Collections;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.Map;
42
43 /**
44  * Report executor implementation.
45  *
46  * @plexus.component
47  */
48 public class DefaultReportExecutor
49     extends AbstractLogEnabled
50     implements ReportExecutor
51 {
52     /**
53      * @plexus.requirement
54      */
55     private MavenProjectBuilder projectBuilder;
56
57     /**
58      * @plexus.requirement
59      */
60     private ReportingStore reportingStore;
61
62     /**
63      * @plexus.requirement
64      */
65     private ArtifactFactory artifactFactory;
66
67     /**
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"
70      */
71     private List artifactReports;
72
73     /**
74      * @plexus.requirement role="org.apache.maven.archiva.reporting.MetadataReportProcessor"
75      */
76     private List metadataReports;
77
78     /**
79      * @plexus.requirement role="org.apache.maven.archiva.discoverer.ArtifactDiscoverer"
80      */
81     private Map artifactDiscoverers;
82
83     /**
84      * @plexus.requirement role="org.apache.maven.archiva.discoverer.MetadataDiscoverer"
85      */
86     private Map metadataDiscoverers;
87
88     private static final int ARTIFACT_BUFFER_SIZE = 1000;
89
90     public void runMetadataReports( List metadata, ArtifactRepository repository )
91         throws ReportingStoreException
92     {
93         ReportingDatabase reporter = getReportDatabase( repository );
94
95         for ( Iterator i = metadata.iterator(); i.hasNext(); )
96         {
97             RepositoryMetadata repositoryMetadata = (RepositoryMetadata) i.next();
98
99             File file =
100                 new File( repository.getBasedir(), repository.pathOfRemoteRepositoryMetadata( repositoryMetadata ) );
101             reporter.cleanMetadata( repositoryMetadata, file.lastModified() );
102
103             // TODO: should the report set be limitable by configuration?
104             runMetadataReports( repositoryMetadata, repository, reporter );
105         }
106
107         reportingStore.storeReports( reporter, repository );
108     }
109
110     private void runMetadataReports( RepositoryMetadata repositoryMetadata, ArtifactRepository repository,
111                                      ReportingDatabase reporter )
112     {
113         for ( Iterator i = metadataReports.iterator(); i.hasNext(); )
114         {
115             MetadataReportProcessor report = (MetadataReportProcessor) i.next();
116
117             report.processMetadata( repositoryMetadata, repository, reporter );
118         }
119     }
120
121     public void runArtifactReports( List artifacts, ArtifactRepository repository )
122         throws ReportingStoreException
123     {
124         ReportingDatabase reporter = getReportDatabase( repository );
125
126         for ( Iterator i = artifacts.iterator(); i.hasNext(); )
127         {
128             Artifact artifact = (Artifact) i.next();
129
130             Model model = null;
131             try
132             {
133                 Artifact pomArtifact = artifactFactory.createProjectArtifact( artifact.getGroupId(),
134                                                                               artifact.getArtifactId(),
135                                                                               artifact.getVersion() );
136                 MavenProject project =
137                     projectBuilder.buildFromRepository( pomArtifact, Collections.EMPTY_LIST, repository );
138
139                 model = project.getModel();
140             }
141             catch ( ProjectBuildingException e )
142             {
143                 reporter.addWarning( artifact, "Error reading project model: " + e );
144             }
145
146             reporter.removeArtifact( artifact );
147
148             runArtifactReports( artifact, model, reporter );
149         }
150
151         reportingStore.storeReports( reporter, repository );
152     }
153
154     public ReportingDatabase getReportDatabase( ArtifactRepository repository )
155         throws ReportingStoreException
156     {
157         getLogger().debug( "Reading previous report database from repository " + repository.getId() );
158         return reportingStore.getReportsFromStore( repository );
159     }
160
161     public void runReports( ArtifactRepository repository, List blacklistedPatterns, ArtifactFilter filter )
162         throws DiscovererException, ReportingStoreException
163     {
164         // Flush (as in toilet, not store) the report database
165         ReportingDatabase database = getReportDatabase( repository );
166         database.clear();
167
168         // Discovery process
169         String layoutProperty = getRepositoryLayout( repository.getLayout() );
170         ArtifactDiscoverer discoverer = (ArtifactDiscoverer) artifactDiscoverers.get( layoutProperty );
171
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 );
175
176         List artifacts = discoverer.discoverArtifacts( repository, blacklistedPatterns, filter );
177
178         if ( !artifacts.isEmpty() )
179         {
180             getLogger().info( "Discovered " + artifacts.size() + " artifacts" );
181
182             // Work through these in batches, then flush the project cache.
183             for ( int j = 0; j < artifacts.size(); j += ARTIFACT_BUFFER_SIZE )
184             {
185                 int end = j + ARTIFACT_BUFFER_SIZE;
186                 List currentArtifacts = artifacts.subList( j, end > artifacts.size() ? artifacts.size() : end );
187
188                 // TODO: proper queueing of this in case it was triggered externally (not harmful to do so at present, but not optimal)
189
190                 // run the reports.
191                 runArtifactReports( currentArtifacts, repository );
192
193                 // MNG-142 - the project builder retains a lot of objects in its inflexible cache. This is a hack
194                 // around that. TODO: remove when it is configurable
195                 flushProjectBuilderCacheHack();
196             }
197         }
198
199         MetadataDiscoverer metadataDiscoverer = (MetadataDiscoverer) metadataDiscoverers.get( layoutProperty );
200         List metadata =
201             metadataDiscoverer.discoverMetadata( repository, blacklistedPatterns, new AcceptAllMetadataFilter() );
202
203         if ( !metadata.isEmpty() )
204         {
205             getLogger().info( "Discovered " + metadata.size() + " metadata files" );
206
207             // run the reports
208             runMetadataReports( metadata, repository );
209         }
210     }
211
212     private String getRepositoryLayout( ArtifactRepositoryLayout layout )
213     {
214         // gross limitation that there is no reverse lookup of the hint for the layout.
215         if ( layout.getClass().equals( DefaultRepositoryLayout.class ) )
216         {
217             return "default";
218         }
219         else if ( layout.getClass().equals( LegacyRepositoryLayout.class ) )
220         {
221             return "legacy";
222         }
223         else
224         {
225             throw new IllegalArgumentException( "Unknown layout: " + layout );
226         }
227     }
228
229     private void runArtifactReports( Artifact artifact, Model model, ReportingDatabase reporter )
230     {
231         // TODO: should the report set be limitable by configuration?
232         for ( Iterator i = artifactReports.iterator(); i.hasNext(); )
233         {
234             ArtifactReportProcessor report = (ArtifactReportProcessor) i.next();
235
236             report.processArtifact( artifact, model, reporter );
237         }
238     }
239
240     private void flushProjectBuilderCacheHack()
241     {
242         try
243         {
244             if ( projectBuilder != null )
245             {
246                 java.lang.reflect.Field f = projectBuilder.getClass().getDeclaredField( "rawProjectCache" );
247                 f.setAccessible( true );
248                 Map cache = (Map) f.get( projectBuilder );
249                 cache.clear();
250
251                 f = projectBuilder.getClass().getDeclaredField( "processedProjectCache" );
252                 f.setAccessible( true );
253                 cache = (Map) f.get( projectBuilder );
254                 cache.clear();
255             }
256         }
257         catch ( NoSuchFieldException e )
258         {
259             throw new RuntimeException( e );
260         }
261         catch ( IllegalAccessException e )
262         {
263             throw new RuntimeException( e );
264         }
265     }
266 }