[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 ) catch ( FileNotFoundException e )
{ {
database = new ReportingDatabase(); database = new ReportingDatabase( repository );
} }
if ( database == null ) if ( database == null )
@ -75,7 +75,7 @@ public class DefaultReportingStore
getLogger().info( "Reading report database from " + file ); getLogger().info( "Reading report database from " + file );
try try
{ {
database = new ReportingDatabase( reader.read( fileReader, false ) ); database = new ReportingDatabase( reader.read( fileReader, false ), repository );
} }
catch ( IOException e ) 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.Reporting;
import org.apache.maven.archiva.reporting.model.Result; import org.apache.maven.archiva.reporting.model.Result;
import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.metadata.RepositoryMetadata; import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
import java.util.HashMap; import java.util.HashMap;
@ -38,37 +39,55 @@ public class ReportingDatabase
private Map metadataMap; private Map metadataMap;
private int totalFailures; private int numFailures;
private int totalWarnings; private int numWarnings;
private ArtifactRepository repository;
public ReportingDatabase() public ReportingDatabase()
{ {
reporting = new Reporting(); this( new Reporting(), null );
} }
public ReportingDatabase( Reporting reporting ) 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.reporting = reporting;
this.repository = repository;
initArtifactMap();
initMetadataMap();
} }
public void addFailure( Artifact artifact, String reason ) public void addFailure( Artifact artifact, String reason )
{ {
ArtifactResults results = getArtifactResults( artifact ); ArtifactResults results = getArtifactResults( artifact );
results.addFailure( createResults( reason ) ); results.addFailure( createResults( reason ) );
totalFailures++; numFailures++;
} }
public void addWarning( Artifact artifact, String reason ) public void addWarning( Artifact artifact, String reason )
{ {
ArtifactResults results = getArtifactResults( artifact ); ArtifactResults results = getArtifactResults( artifact );
results.addWarning( createResults( reason ) ); results.addWarning( createResults( reason ) );
totalWarnings++; numWarnings++;
} }
private ArtifactResults getArtifactResults( Artifact artifact ) private ArtifactResults getArtifactResults( Artifact artifact )
{ {
Map artifactMap = getArtifactMap(); Map artifactMap = this.artifactMap;
String key = getArtifactKey( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), String key = getArtifactKey( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(),
artifact.getType(), artifact.getClassifier() ); artifact.getType(), artifact.getClassifier() );
@ -89,25 +108,21 @@ public class ReportingDatabase
return results; 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(); ArtifactResults result = (ArtifactResults) i.next();
for ( Iterator i = reporting.getArtifacts().iterator(); i.hasNext(); )
{
ArtifactResults result = (ArtifactResults) i.next();
String key = getArtifactKey( result.getGroupId(), result.getArtifactId(), result.getVersion(), String key = getArtifactKey( result.getGroupId(), result.getArtifactId(), result.getVersion(),
result.getType(), result.getClassifier() ); result.getType(), result.getClassifier() );
map.put( key, result ); map.put( key, result );
totalFailures += result.getFailures().size(); numFailures += result.getFailures().size();
totalWarnings += result.getWarnings().size(); numWarnings += result.getWarnings().size();
}
artifactMap = map;
} }
return artifactMap; artifactMap = map;
} }
private static String getArtifactKey( String groupId, String artifactId, String version, String type, 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() ); MetadataResults results = getMetadataResults( metadata, System.currentTimeMillis() );
results.addFailure( createResults( reason ) ); results.addFailure( createResults( reason ) );
totalFailures++; numFailures++;
} }
public void addWarning( RepositoryMetadata metadata, String reason ) public void addWarning( RepositoryMetadata metadata, String reason )
{ {
MetadataResults results = getMetadataResults( metadata, System.currentTimeMillis() ); MetadataResults results = getMetadataResults( metadata, System.currentTimeMillis() );
results.addWarning( createResults( reason ) ); 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(); MetadataResults result = (MetadataResults) i.next();
for ( Iterator i = reporting.getMetadata().iterator(); i.hasNext(); )
{
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(); numFailures += result.getFailures().size();
totalWarnings += result.getWarnings().size(); numWarnings += result.getWarnings().size();
}
metadataMap = map;
} }
return metadataMap; metadataMap = map;
} }
private static String getMetadataKey( String groupId, String artifactId, String version ) private static String getMetadataKey( String groupId, String artifactId, String version )
@ -165,12 +176,12 @@ public class ReportingDatabase
public int getNumFailures() public int getNumFailures()
{ {
return totalFailures; return numFailures;
} }
public int getNumWarnings() public int getNumWarnings()
{ {
return totalWarnings; return numWarnings;
} }
public Reporting getReporting() public Reporting getReporting()
@ -191,7 +202,7 @@ public class ReportingDatabase
public boolean isMetadataUpToDate( RepositoryMetadata metadata, long timestamp ) public boolean isMetadataUpToDate( RepositoryMetadata metadata, long timestamp )
{ {
String key = getMetadataKey( metadata ); String key = getMetadataKey( metadata );
Map map = getMetadataMap(); Map map = metadataMap;
MetadataResults results = (MetadataResults) map.get( key ); MetadataResults results = (MetadataResults) map.get( key );
return results != null && results.getLastModified() >= timestamp; return results != null && results.getLastModified() >= timestamp;
} }
@ -207,14 +218,18 @@ public class ReportingDatabase
MetadataResults results = getMetadataResults( metadata, lastModified ); MetadataResults results = getMetadataResults( metadata, lastModified );
results.setLastModified( lastModified ); results.setLastModified( lastModified );
numFailures -= results.getFailures().size();
results.getFailures().clear(); results.getFailures().clear();
numWarnings -= results.getWarnings().size();
results.getWarnings().clear(); results.getWarnings().clear();
} }
private MetadataResults getMetadataResults( RepositoryMetadata metadata, long lastModified ) private MetadataResults getMetadataResults( RepositoryMetadata metadata, long lastModified )
{ {
String key = getMetadataKey( metadata ); String key = getMetadataKey( metadata );
Map metadataMap = getMetadataMap(); Map metadataMap = this.metadataMap;
MetadataResults results = (MetadataResults) metadataMap.get( key ); MetadataResults results = (MetadataResults) metadataMap.get( key );
if ( results == null ) if ( results == null )
{ {
@ -237,7 +252,7 @@ public class ReportingDatabase
public void removeArtifact( Artifact artifact ) public void removeArtifact( Artifact artifact )
{ {
Map map = getArtifactMap(); Map map = artifactMap;
String key = getArtifactKey( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), String key = getArtifactKey( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(),
artifact.getType(), artifact.getClassifier() ); artifact.getType(), artifact.getClassifier() );
@ -251,7 +266,16 @@ public class ReportingDatabase
i.remove(); i.remove();
} }
} }
numFailures -= results.getFailures().size();
numWarnings -= results.getWarnings().size();
map.remove( key ); 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> <result>/WEB-INF/jsp/showArtifact.jsp</result>
</action> </action>
<action name="reports" class="reportsAction">
<result>/WEB-INF/jsp/reports/reports.jsp</result>
</action>
<action name="showArtifactDependencies" class="showArtifactAction" method="dependencies"> <action name="showArtifactDependencies" class="showArtifactAction" method="dependencies">
<result>/WEB-INF/jsp/showArtifact.jsp</result> <result>/WEB-INF/jsp/showArtifact.jsp</result>
</action> </action>

View File

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

View File

@ -1,7 +1,7 @@
<%@ taglib prefix="ww" uri="/webwork" %> <%@ taglib prefix="ww" uri="/webwork" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- TODO: paginate --%> <%-- TODO: paginate! --%>
<c:forEach items="${dependencies}" var="dependency"> <c:forEach items="${dependencies}" var="dependency">
<h3> <h3>
<c:set var="url"> <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; text-align: right;
padding-right: 1em; padding-right: 1em;
font-size: x-small; font-size: x-small;
vertical-align: top;
} }
.infoTable th { .infoTable th {

View File

@ -96,3 +96,11 @@
.actionMessage { .actionMessage {
font-weight: bold; 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>
<div id="contentArea"> <div id="contentArea">
<h2>Status</h2> <h2>Repository 1</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>
<p> <p>
No errors found. Status:
</p> <img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
<h2>Warnings</h2> 2
<p> <img src="images/icon_warning_sml.gif" width="15" height="15" alt=""/>
3 warnings found. ( 0
(
<a href="#">Repair all</a> <a href="#">Repair all</a>
) )
</p> </p>
<h3>Artifacts</h3>
<table> <table>
<tr> <tr>
<th>Group ID</th> <td>
<th>Artifact ID</th> <img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
<th>Version</th> </td>
<th>Message</th> <td>
<th></th> File is missing SHA1 checksum
</tr> <p>
<tr> <span style="font-size: x-small">
<td>org.apache.maven</td> <strong>Group ID:</strong>
<td>maven-model</td> <a href="browse2.html">org</a>
<td>2.0.1</td> /
<td>File is missing SHA1 checksum</td> <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> <td>
<a href="#">Repair</a> <a href="#">Repair</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td>org.apache.maven</td>
<td>maven-model</td>
<td>2.0.2</td>
<td>File is missing SHA1 checksum</td>
<td> <td>
<span <img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
style="color: green; font-weight: bold">Fixed </td>
</span> <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> </td>
</tr> </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> <tr>
<td>org.apache.maven</td> <td>
<td>maven-model</td> <img src="images/icon_warning_sml.gif" width="15" height="15" alt=""/>
<td>2.0.2</td> </td>
<td>File is missing a digital signature</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> <td>
<span style="color: gray">No fix available</span> <span style="color: gray">No fix available</span>
</td> </td>
</tr> </tr>
</table> </table>
<table>
</table>
</div> </div>
</body> </body>
</document> </document>