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