List currentArtifacts =
artifacts.subList( j, end > artifacts.size() ? artifacts.size() : end );
+ // TODO: proper queueing of this in case it was triggered externally (not harmful to do so at present, but not optimal)
+
// run the reports. Done intermittently to avoid losing track of what is indexed since
// that is what the filter is based on.
reportExecutor.runArtifactReports( currentArtifacts, repository );
*/
private Map metadataDiscoverers;
+ private static final int ARTIFACT_BUFFER_SIZE = 1000;
+
public void runMetadataReports( List metadata, ArtifactRepository repository )
throws ReportingStoreException
{
throws DiscovererException, ReportingStoreException
{
// Flush (as in toilet, not store) the report database
- reportingStore.removeReportDatabase( repository );
+ ReportingDatabase database = getReportDatabase( repository );
+ database.clear();
// Discovery process
String layoutProperty = getRepositoryLayout( repository.getLayout() );
{
getLogger().info( "Discovered " + artifacts.size() + " artifacts" );
- // run the reports
- runArtifactReports( artifacts, repository );
+ // Work through these in batches, then flush the project cache.
+ for ( int j = 0; j < artifacts.size(); j += ARTIFACT_BUFFER_SIZE )
+ {
+ int end = j + ARTIFACT_BUFFER_SIZE;
+ List currentArtifacts = artifacts.subList( j, end > artifacts.size() ? artifacts.size() : end );
+
+ // TODO: proper queueing of this in case it was triggered externally (not harmful to do so at present, but not optimal)
+
+ // run the reports.
+ runArtifactReports( currentArtifacts, repository );
+ }
+
+ // MNG-142 - the project builder retains a lot of objects in its inflexible cache. This is a hack
+ // around that. TODO: remove when it is configurable
+ flushProjectBuilderCacheHack();
}
MetadataDiscoverer metadataDiscoverer = (MetadataDiscoverer) metadataDiscoverers.get( layoutProperty );
report.processArtifact( artifact, model, reporter );
}
}
+
+ private void flushProjectBuilderCacheHack()
+ {
+ try
+ {
+ if ( projectBuilder != null )
+ {
+ java.lang.reflect.Field f = projectBuilder.getClass().getDeclaredField( "rawProjectCache" );
+ f.setAccessible( true );
+ Map cache = (Map) f.get( projectBuilder );
+ cache.clear();
+
+ f = projectBuilder.getClass().getDeclaredField( "processedProjectCache" );
+ f.setAccessible( true );
+ cache = (Map) f.get( projectBuilder );
+ cache.clear();
+ }
+ }
+ catch ( NoSuchFieldException e )
+ {
+ throw new RuntimeException( e );
+ }
+ catch ( IllegalAccessException e )
+ {
+ throw new RuntimeException( e );
+ }
+ }
}
}
}
- public void removeReportDatabase( ArtifactRepository repository )
- {
- reports.remove( repository );
- }
}
* @param repository the repository to run from
* @param blacklistedPatterns the patterns to exclude during discovery
* @param filter the filter to use during discovery to get a consistent list of artifacts
+ * @throws ReportingStoreException if there is a problem reading/writing the report database
+ * @throws org.apache.maven.archiva.discoverer.DiscovererException
+ * if there is a problem finding the artifacts and metadata to report on
*/
public void runReports( ArtifactRepository repository, List blacklistedPatterns, ArtifactFilter filter )
throws DiscovererException, ReportingStoreException;
private ArtifactRepository repository;
+ private boolean inProgress;
+
public ReportingDatabase()
{
this( new Reporting(), null );
return repository;
}
+ public boolean isInProgress()
+ {
+ return inProgress;
+ }
+
+ public void setInProgress( boolean inProgress )
+ {
+ this.inProgress = inProgress;
+ }
+
+ public void clear()
+ {
+ // clear the values rather than destroy the instance so that the "inProgress" indicator is in tact.
+ numWarnings = 0;
+ numFailures = 0;
+
+ artifactMap.clear();
+ metadataMap.clear();
+
+ reporting.getArtifacts().clear();
+ reporting.getMetadata().clear();
+ }
}
void storeReports( ReportingDatabase database, ArtifactRepository repository )
throws ReportingStoreException;
- /**
- * Remove the report database from the memory cache.
- *
- * @param repository the repository of the database to remove
- */
- void removeReportDatabase( ArtifactRepository repository );
}
RepositoryConfiguration repositoryConfiguration = configuration.getRepositoryById( repositoryId );
ArtifactRepository repository = factory.createRepository( repositoryConfiguration );
+ ReportingDatabase database = executor.getReportDatabase( repository );
+ if ( database.isInProgress() )
+ {
+ return SUCCESS;
+ }
+
+ database.setInProgress( true );
+
List blacklistedPatterns = new ArrayList();
if ( repositoryConfiguration.getBlackListPatterns() != null )
{
filter = new SnapshotArtifactFilter();
}
- executor.runReports( repository, blacklistedPatterns, filter );
+ try
+ {
+ executor.runReports( repository, blacklistedPatterns, filter );
+ }
+ finally
+ {
+ database.setInProgress( false );
+ }
- return execute();
+ return SUCCESS;
}
public String getRepositoryId()
<result>/WEB-INF/jsp/reports/reports.jsp</result>
</action>
+ <action name="runReport" class="reportsAction" method="runReport">
+ <interceptor-ref name="configuredStack"/>
+ <interceptor-ref name="execAndWait"/>
+ <result name="wait" type="redirect-action">reports</result>
+ <result name="success" type="redirect-action">reports</result>
+ </action>
+
<action name="showArtifactDependencies" class="showArtifactAction" method="dependencies">
<result>/WEB-INF/jsp/showArtifact.jsp</result>
</action>
<div id="contentArea">
+<ww:actionerror/>
+
<ww:set name="databases" value="databases"/>
<c:forEach items="${databases}" var="database">
<div>
<a href="#">Repair all</a>
|
--%>
- <c:set var="url">
- <ww:url action="reports" namespace="/" method="runReport">
- <ww:param name="repositoryId" value="%{'${database.repository.id}'}"/>
- </ww:url>
- </c:set>
- <a href="${url}">Regenerate Report</a>
+ <c:choose>
+ <c:when test="${!database.inProgress}">
+ <c:set var="url">
+ <ww:url action="runReport" namespace="/">
+ <ww:param name="repositoryId" value="%{'${database.repository.id}'}"/>
+ </ww:url>
+ </c:set>
+ <a href="${url}">Regenerate Report</a>
+ </c:when>
+ <c:otherwise>
+ <!-- TODO: would be good to have a generic task/job mechanism that tracked progress and ability to run
+ concurrently -->
+ <span style="color: gray;">Report in progress</span>
+ </c:otherwise>
+ </c:choose>
</div>
<h2>Repository: ${database.repository.name}</h2>
${database.numWarnings}
</p>
+ <%-- TODO need to protect iterations against concurrent modification exceptions by cloning the lists synchronously --%>
<%-- TODO! factor out common parts, especially artifact rendering tag --%>
- <%-- TODO! paginate --%>
+ <%-- TODO! paginate (displaytag?) --%>
<c:if test="${!empty(database.reporting.artifacts)}">
<h3>Artifacts</h3>
<c:forEach items="${database.reporting.artifacts}" var="artifact" begin="0" end="2">