[MRM-77] preliminary reporting web interface

git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@441516 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Brett Porter 2006-09-08 14:33:45 +00:00
parent 3e5e310c64
commit 44dce10087
10 changed files with 441 additions and 102 deletions

View File

@ -67,7 +67,7 @@ public class DefaultReportingStore
}
catch ( FileNotFoundException e )
{
database = new ReportingDatabase();
database = new ReportingDatabase( repository );
}
if ( database == null )
@ -75,7 +75,7 @@ public class DefaultReportingStore
getLogger().info( "Reading report database from " + file );
try
{
database = new ReportingDatabase( reader.read( fileReader, false ) );
database = new ReportingDatabase( reader.read( fileReader, false ), repository );
}
catch ( IOException e )
{

View File

@ -21,6 +21,7 @@ import org.apache.maven.archiva.reporting.model.MetadataResults;
import org.apache.maven.archiva.reporting.model.Reporting;
import org.apache.maven.archiva.reporting.model.Result;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
import java.util.HashMap;
@ -38,37 +39,55 @@ public class ReportingDatabase
private Map metadataMap;
private int totalFailures;
private int numFailures;
private int totalWarnings;
private int numWarnings;
private ArtifactRepository repository;
public ReportingDatabase()
{
reporting = new Reporting();
this( new Reporting(), null );
}
public ReportingDatabase( Reporting reporting )
{
this( reporting, null );
}
public ReportingDatabase( ArtifactRepository repository )
{
this( new Reporting(), repository );
}
public ReportingDatabase( Reporting reporting, ArtifactRepository repository )
{
this.reporting = reporting;
this.repository = repository;
initArtifactMap();
initMetadataMap();
}
public void addFailure( Artifact artifact, String reason )
{
ArtifactResults results = getArtifactResults( artifact );
results.addFailure( createResults( reason ) );
totalFailures++;
numFailures++;
}
public void addWarning( Artifact artifact, String reason )
{
ArtifactResults results = getArtifactResults( artifact );
results.addWarning( createResults( reason ) );
totalWarnings++;
numWarnings++;
}
private ArtifactResults getArtifactResults( Artifact artifact )
{
Map artifactMap = getArtifactMap();
Map artifactMap = this.artifactMap;
String key = getArtifactKey( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(),
artifact.getType(), artifact.getClassifier() );
@ -89,25 +108,21 @@ public class ReportingDatabase
return results;
}
private Map getArtifactMap()
private void initArtifactMap()
{
if ( artifactMap == null )
Map map = new HashMap();
for ( Iterator i = reporting.getArtifacts().iterator(); i.hasNext(); )
{
Map map = new HashMap();
for ( Iterator i = reporting.getArtifacts().iterator(); i.hasNext(); )
{
ArtifactResults result = (ArtifactResults) i.next();
ArtifactResults result = (ArtifactResults) i.next();
String key = getArtifactKey( result.getGroupId(), result.getArtifactId(), result.getVersion(),
result.getType(), result.getClassifier() );
map.put( key, result );
String key = getArtifactKey( result.getGroupId(), result.getArtifactId(), result.getVersion(),
result.getType(), result.getClassifier() );
map.put( key, result );
totalFailures += result.getFailures().size();
totalWarnings += result.getWarnings().size();
}
artifactMap = map;
numFailures += result.getFailures().size();
numWarnings += result.getWarnings().size();
}
return artifactMap;
artifactMap = map;
}
private static String getArtifactKey( String groupId, String artifactId, String version, String type,
@ -127,35 +142,31 @@ public class ReportingDatabase
{
MetadataResults results = getMetadataResults( metadata, System.currentTimeMillis() );
results.addFailure( createResults( reason ) );
totalFailures++;
numFailures++;
}
public void addWarning( RepositoryMetadata metadata, String reason )
{
MetadataResults results = getMetadataResults( metadata, System.currentTimeMillis() );
results.addWarning( createResults( reason ) );
totalWarnings++;
numWarnings++;
}
private Map getMetadataMap()
private void initMetadataMap()
{
if ( metadataMap == null )
Map map = new HashMap();
for ( Iterator i = reporting.getMetadata().iterator(); i.hasNext(); )
{
Map map = new HashMap();
for ( Iterator i = reporting.getMetadata().iterator(); i.hasNext(); )
{
MetadataResults result = (MetadataResults) i.next();
MetadataResults result = (MetadataResults) i.next();
String key = getMetadataKey( result.getGroupId(), result.getArtifactId(), result.getVersion() );
String key = getMetadataKey( result.getGroupId(), result.getArtifactId(), result.getVersion() );
map.put( key, result );
map.put( key, result );
totalFailures += result.getFailures().size();
totalWarnings += result.getWarnings().size();
}
metadataMap = map;
numFailures += result.getFailures().size();
numWarnings += result.getWarnings().size();
}
return metadataMap;
metadataMap = map;
}
private static String getMetadataKey( String groupId, String artifactId, String version )
@ -165,12 +176,12 @@ public class ReportingDatabase
public int getNumFailures()
{
return totalFailures;
return numFailures;
}
public int getNumWarnings()
{
return totalWarnings;
return numWarnings;
}
public Reporting getReporting()
@ -191,7 +202,7 @@ public class ReportingDatabase
public boolean isMetadataUpToDate( RepositoryMetadata metadata, long timestamp )
{
String key = getMetadataKey( metadata );
Map map = getMetadataMap();
Map map = metadataMap;
MetadataResults results = (MetadataResults) map.get( key );
return results != null && results.getLastModified() >= timestamp;
}
@ -207,14 +218,18 @@ public class ReportingDatabase
MetadataResults results = getMetadataResults( metadata, lastModified );
results.setLastModified( lastModified );
numFailures -= results.getFailures().size();
results.getFailures().clear();
numWarnings -= results.getWarnings().size();
results.getWarnings().clear();
}
private MetadataResults getMetadataResults( RepositoryMetadata metadata, long lastModified )
{
String key = getMetadataKey( metadata );
Map metadataMap = getMetadataMap();
Map metadataMap = this.metadataMap;
MetadataResults results = (MetadataResults) metadataMap.get( key );
if ( results == null )
{
@ -237,7 +252,7 @@ public class ReportingDatabase
public void removeArtifact( Artifact artifact )
{
Map map = getArtifactMap();
Map map = artifactMap;
String key = getArtifactKey( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(),
artifact.getType(), artifact.getClassifier() );
@ -251,7 +266,16 @@ public class ReportingDatabase
i.remove();
}
}
numFailures -= results.getFailures().size();
numWarnings -= results.getWarnings().size();
map.remove( key );
}
}
public ArtifactRepository getRepository()
{
return repository;
}
}

View File

@ -0,0 +1,81 @@
package org.apache.maven.archiva.web.action;
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.opensymphony.xwork.ActionSupport;
import org.apache.maven.archiva.configuration.Configuration;
import org.apache.maven.archiva.configuration.ConfigurationStore;
import org.apache.maven.archiva.configuration.ConfiguredRepositoryFactory;
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
import org.apache.maven.archiva.reporting.ReportingDatabase;
import org.apache.maven.archiva.reporting.ReportingStore;
import org.apache.maven.artifact.repository.ArtifactRepository;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Repository reporting.
*
* @plexus.component role="com.opensymphony.xwork.Action" role-hint="reportsAction"
*/
public class ReportsAction
extends ActionSupport
{
/**
* @plexus.requirement
*/
private ReportingStore reportingStore;
/**
* @plexus.requirement
*/
private ConfigurationStore configurationStore;
/**
* @plexus.requirement
*/
private ConfiguredRepositoryFactory factory;
private List databases;
public String execute()
throws Exception
{
databases = new ArrayList();
Configuration configuration = configurationStore.getConfigurationFromStore();
for ( Iterator i = configuration.getRepositories().iterator(); i.hasNext(); )
{
RepositoryConfiguration repositoryConfiguration = (RepositoryConfiguration) i.next();
ArtifactRepository repository = factory.createRepository( repositoryConfiguration );
ReportingDatabase database = reportingStore.getReportsFromStore( repository );
databases.add( database );
}
return SUCCESS;
}
public List getDatabases()
{
return databases;
}
}

View File

@ -107,6 +107,10 @@
<result>/WEB-INF/jsp/showArtifact.jsp</result>
</action>
<action name="reports" class="reportsAction">
<result>/WEB-INF/jsp/reports/reports.jsp</result>
</action>
<action name="showArtifactDependencies" class="showArtifactAction" method="dependencies">
<result>/WEB-INF/jsp/showArtifact.jsp</result>
</action>

View File

@ -25,11 +25,11 @@
</title>
<style type="text/css" media="all">
@import url( "<%= request.getContextPath() %>/css/maven-base.css" );
@import url( "<%= request.getContextPath() %>/css/maven-theme.css" );
@import url( "<%= request.getContextPath() %>/css/site.css" );
@import url( "<c:url value="/css/maven-base.css" />" );
@import url( "<c:url value="/css/maven-theme.css" />" );
@import url( "<c:url value="/css/site.css" />" );
</style>
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/print.css" type="text/css" media="print"/>
<link rel="stylesheet" href="<c:url value="/css/print.css"/>" type="text/css" media="print"/>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
</head>
@ -62,10 +62,13 @@
<ww:url id="logoutUrl" action="logout" namespace="/"/>
<ww:url id="registerUrl" action="register" namespace="/"/>
<ww:if test="${sessionScope.authStatus != true}">
<ww:a href="%{loginUrl}">Login</ww:a> or <ww:a href="%{registerUrl}">Register</ww:a>
<ww:a href="%{loginUrl}">Login</ww:a>
or
<ww:a href="%{registerUrl}">Register</ww:a>
</ww:if>
<ww:else>
Welcome, <b>${sessionScope.user.username}</b> - <ww:a href="%{logoutUrl}">Logout</ww:a>
Welcome, <b>${sessionScope.user.username}</b> -
<ww:a href="%{logoutUrl}">Logout</ww:a>
</ww:else>
</div>
@ -101,12 +104,11 @@
</ul>
<h5>Manage</h5>
<ul>
<li class="none">
<my:currentWWUrl action="reports" namespace="/">Reports</my:currentWWUrl>
</li>
<%-- TODO
<li class="none">
<a href="#">Reports</a>
</li>
<li class="none">
<a href="#">Synchronisation</a>
</li>

View File

@ -1,7 +1,7 @@
<%@ taglib prefix="ww" uri="/webwork" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- TODO: paginate --%>
<%-- TODO: paginate! --%>
<c:forEach items="${dependencies}" var="dependency">
<h3>
<c:set var="url">

View File

@ -0,0 +1,181 @@
<%--
~ Copyright 2005-2006 The Apache Software Foundation.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
--%>
<%@ taglib prefix="ww" uri="/webwork" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
<head>
<title>Repository Health</title>
<ww:head/>
</head>
<body>
<h1>Reports</h1>
<div id="contentArea">
<ww:set name="databases" value="databases"/>
<c:forEach items="${databases}" var="database">
<h2>Repository: ${database.repository.name}</h2>
<p>
Status:
<img src="<c:url value="/images/icon_error_sml.gif"/>" width="15" height="15" alt=""/>
${database.numFailures}
<img src="<c:url value="/images/icon_warning_sml.gif"/>" width="15" height="15" alt=""/>
${database.numWarnings}
<%-- TODO!
(<a href="#">Repair all</a>)
--%>
</p>
<%-- TODO! factor out common parts, especially artifact rendering tag --%>
<%-- TODO! paginate --%>
<c:if test="${!empty(database.reporting.artifacts)}">
<h3>Artifacts</h3>
<c:forEach items="${database.reporting.artifacts}" var="artifact" begin="0" end="2">
<ul>
<c:forEach items="${artifact.failures}" var="result">
<li class="errorBullet">${result.reason}</li>
</c:forEach>
<c:forEach items="${artifact.warnings}" var="result">
<li class="warningBullet">${result.reason}</li>
</c:forEach>
</ul>
<p style="text-indent: 3em;">
<span style="font-size: x-small">
<%-- TODO! share with browse as a tag --%>
<c:set var="cumulativeGroup" value=""/>
<c:forTokens items="${artifact.groupId}" delims="." var="part">
<c:choose>
<c:when test="${empty(cumulativeGroup)}">
<c:set var="cumulativeGroup" value="${part}"/>
</c:when>
<c:otherwise>
<c:set var="cumulativeGroup" value="${cumulativeGroup}.${part}"/>
</c:otherwise>
</c:choose>
<c:set var="url">
<ww:url action="browseGroup" namespace="/">
<ww:param name="groupId" value="%{'${cumulativeGroup}'}"/>
</ww:url>
</c:set>
<a href="${url}">${part}</a> /
</c:forTokens>
<strong>${artifact.artifactId}</strong>
| <strong>Version:</strong>
<c:set var="url">
<ww:url action="showArtifact" namespace="/">
<ww:param name="groupId" value="%{'${artifact.groupId}'}"/>
<ww:param name="artifactId" value="%{'${artifact.artifactId}'}"/>
<c:if test="${!empty(artifact.version)}">
<ww:param name="version" value="%{'${artifact.version}'}"/>
</c:if>
</ww:url>
</c:set>
<a href="${url}">${artifact.version}</a>
<c:if test="${!empty(artifact.classifier)}">
| <strong>Classifier:</strong> ${artifact.classifier}
</c:if>
</span>
</p>
<%-- TODO!
<td>
<a href="#">Repair</a>
</td>
--%>
</c:forEach>
<c:if test="${fn:length(database.reporting.artifacts) gt 3}">
<p>
<b>... more ...</b>
</p>
</c:if>
</c:if>
<c:if test="${!empty(database.reporting.metadata)}">
<h3>Metadata</h3>
<c:forEach items="${database.reporting.metadata}" var="metadata" begin="0" end="2">
<ul>
<c:forEach items="${metadata.failures}" var="result">
<li class="errorBullet">${result.reason}</li>
</c:forEach>
<c:forEach items="${metadata.warnings}" var="result">
<li class="warningBullet">${result.reason}</li>
</c:forEach>
</ul>
<p style="text-indent: 3em;">
<span style="font-size: x-small">
<%-- TODO! share with browse as a tag --%>
<c:set var="cumulativeGroup" value=""/>
<c:forTokens items="${metadata.groupId}" delims="." var="part" varStatus="i">
<c:choose>
<c:when test="${empty(cumulativeGroup)}">
<c:set var="cumulativeGroup" value="${part}"/>
</c:when>
<c:otherwise>
<c:set var="cumulativeGroup" value="${cumulativeGroup}.${part}"/>
</c:otherwise>
</c:choose>
<c:set var="url">
<ww:url action="browseGroup" namespace="/">
<ww:param name="groupId" value="%{'${cumulativeGroup}'}"/>
</ww:url>
</c:set>
<a href="${url}">${part}</a>
<c:if test="${!i.last}">
/
</c:if>
</c:forTokens>
<c:if test="${!empty(metadata.artifactId)}">
<c:set var="url">
<ww:url action="browseArtifact" namespace="/">
<ww:param name="groupId" value="%{'${metadata.groupId}'}"/>
<ww:param name="artifactId" value="%{'${metadata.artifactId}'}"/>
</ww:url>
</c:set>
/ <a href="${url}">${metadata.artifactId}</a>
</c:if>
<c:if test="${!empty(metadata.version)}"> | <strong>Version:</strong>
<c:set var="url">
<ww:url action="showArtifact" namespace="/">
<ww:param name="groupId" value="%{'${metadata.groupId}'}"/>
<ww:param name="artifactId" value="%{'${metadata.artifactId}'}"/>
<ww:param name="version" value="%{'${metadata.version}'}"/>
</ww:url>
</c:set>
<a href="${url}">${metadata.version}</a>
</c:if>
</span>
</p>
<%-- TODO!
<td>
<a href="#">Repair</a>
</td>
--%>
</c:forEach>
<c:if test="${fn:length(database.reporting.metadata) gt 3}">
<p>
<b>... more ...</b>
</p>
</c:if>
</c:if>
</c:forEach>
</div>
</body>
</html>

View File

@ -31,6 +31,7 @@ th {
text-align: right;
padding-right: 1em;
font-size: x-small;
vertical-align: top;
}
.infoTable th {

View File

@ -96,3 +96,11 @@
.actionMessage {
font-weight: bold;
}
.errorBullet {
list-style-image: url( "../images/icon_error_sml.gif" );
}
.warningBullet {
list-style-image: url( "../images/icon_warning_sml.gif" );
}

View File

@ -10,75 +10,113 @@
</div>
<div id="contentArea">
<h2>Status</h2>
<table>
<tr>
<th>Last run</th>
<td>1 February 13:01:04</td>
</tr>
<tr>
<th>Next run</th>
<td>1 February 17:00:00</td>
</tr>
<tr>
<th>Status</th>
<td>
<span class="statusWarn">WARNING</span>
: some warnings were found.
</td>
</tr>
</table>
<h2>Errors</h2>
<h2>Repository 1</h2>
<p>
No errors found.
</p>
<h2>Warnings</h2>
<p>
3 warnings found. (
Status:
<img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
2
<img src="images/icon_warning_sml.gif" width="15" height="15" alt=""/>
0
(
<a href="#">Repair all</a>
)
</p>
<h3>Artifacts</h3>
<table>
<tr>
<th>Group ID</th>
<th>Artifact ID</th>
<th>Version</th>
<th>Message</th>
<th></th>
</tr>
<tr>
<td>org.apache.maven</td>
<td>maven-model</td>
<td>2.0.1</td>
<td>File is missing SHA1 checksum</td>
<td>
<img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
</td>
<td>
File is missing SHA1 checksum
<p>
<span style="font-size: x-small">
<strong>Group ID:</strong>
<a href="browse2.html">org</a>
/
<a href="browse2.html">apache</a>
/
<a href="browse2.html">maven</a>
<strong>Artifact ID:</strong>
<a href="browse3.html">maven-artifact</a>
<strong>Version(s):</strong>
<a href="artifact.html">2.0</a>
</span>
</p>
</td>
<td>
<a href="#">Repair</a>
</td>
</tr>
<tr>
<td>org.apache.maven</td>
<td>maven-model</td>
<td>2.0.2</td>
<td>File is missing SHA1 checksum</td>
<td>
<span
style="color: green; font-weight: bold">Fixed
</span>
<img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
</td>
<td>File is missing SHA1 checksum
<p>
<span style="font-size: x-small">
<strong>Group ID:</strong>
<a href="browse2.html">org</a>
/
<a href="browse2.html">apache</a>
/
<a href="browse2.html">maven</a>
<strong>Artifact ID:</strong>
<a href="browse3.html">maven-artifact</a>
<strong>Version(s):</strong>
<a href="artifact.html">2.0.1</a>
</span>
</p>
</td>
<td>
<a href="#">Repair</a>
</td>
</tr>
</table>
<h2>Repository 2</h2>
<p>
Status:
<img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
0
<img src="images/icon_warning_sml.gif" width="15" height="15" alt=""/>
1
(
<a href="#">Repair all</a>
)
</p>
<h3>Artifacts</h3>
<table>
<tr>
<td>org.apache.maven</td>
<td>maven-model</td>
<td>2.0.2</td>
<td>File is missing a digital signature</td>
<td>
<img src="images/icon_warning_sml.gif" width="15" height="15" alt=""/>
</td>
<td>
File is missing a digital signature
<p>
<span style="font-size: x-small">
<strong>Group ID:</strong>
<a href="browse2.html">org</a>
/
<a href="browse2.html">apache</a>
/
<a href="browse2.html">maven</a>
<strong>Artifact ID:</strong>
<a href="browse3.html">maven-artifact</a>
<strong>Version(s):</strong>
<a href="artifact.html">2.0.1</a>
</span>
</p>
</td>
<td>
<span style="color: gray">No fix available</span>
</td>
</tr>
</table>
<table>
</table>
</div>
</body>
</document>