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