Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java?rev=700729&r1=700728&r2=700729&view=diff ============================================================================== --- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java (original) +++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java Wed Oct 1 03:27:16 2008 @@ -21,25 +21,40 @@ import com.opensymphony.webwork.interceptor.ServletRequestAware; import com.opensymphony.xwork.Preparable; + +import org.apache.maven.archiva.configuration.ArchivaConfiguration; import org.apache.maven.archiva.database.ArchivaDAO; +import org.apache.maven.archiva.database.ArchivaDatabaseException; import org.apache.maven.archiva.database.Constraint; +import org.apache.maven.archiva.database.ObjectNotFoundException; +import org.apache.maven.archiva.database.RepositoryContentStatisticsDAO; import org.apache.maven.archiva.database.constraints.RangeConstraint; +import org.apache.maven.archiva.database.constraints.RepositoryContentStatisticsByRepositoryConstraint; import org.apache.maven.archiva.database.constraints.RepositoryProblemByGroupIdConstraint; import org.apache.maven.archiva.database.constraints.RepositoryProblemByRepositoryIdConstraint; import org.apache.maven.archiva.database.constraints.RepositoryProblemConstraint; import org.apache.maven.archiva.database.constraints.UniqueFieldConstraint; +import org.apache.maven.archiva.model.RepositoryContentStatistics; import org.apache.maven.archiva.model.RepositoryProblem; import org.apache.maven.archiva.model.RepositoryProblemReport; +import org.apache.maven.archiva.reporting.ArchivaReportException; +import org.apache.maven.archiva.reporting.DataLimits; +import org.apache.maven.archiva.reporting.RepositoryStatistics; +import org.apache.maven.archiva.reporting.RepositoryStatisticsReportGenerator; import org.apache.maven.archiva.security.ArchivaRoleConstants; import org.codehaus.plexus.redback.rbac.Resource; import org.codehaus.plexus.redback.xwork.interceptor.SecureAction; import org.codehaus.plexus.redback.xwork.interceptor.SecureActionBundle; import org.codehaus.plexus.redback.xwork.interceptor.SecureActionException; import org.codehaus.plexus.xwork.action.PlexusActionSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collection; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -51,10 +66,17 @@ extends PlexusActionSupport implements SecureAction, ServletRequestAware, Preparable { + private Logger log = LoggerFactory.getLogger( GenerateReportAction.class ); + /** * @plexus.requirement role-hint="jdo" */ protected ArchivaDAO dao; + + /** + * @plexus.requirement + */ + private ArchivaConfiguration archivaConfiguration; protected Constraint constraint; @@ -90,13 +112,45 @@ protected Map<String, List<RepositoryProblemReport>> repositoriesMap = new TreeMap<String, List<RepositoryProblemReport>>(); - + + // for statistics report + /** + * @plexus.requirement role-hint="simple" + */ + private RepositoryStatisticsReportGenerator generator; + + private List<String> selectedRepositories = new ArrayList<String>(); + + private List<String> availableRepositories; + + private Date startDate; + + private Date endDate; + + private int reposSize; + + private String selectedRepo; + + private List<RepositoryStatistics> repositoryStatistics = new ArrayList<RepositoryStatistics>(); + public void prepare() { repositoryIds = new ArrayList<String>(); repositoryIds.add( ALL_REPOSITORIES ); // comes first to be first in the list repositoryIds.addAll( dao.query( new UniqueFieldConstraint( RepositoryProblem.class.getName(), "repositoryId" ) ) ); + + availableRepositories = new ArrayList<String>(); + + // remove selected repositories in the option for the statistics report + availableRepositories.addAll( archivaConfiguration.getConfiguration().getManagedRepositoriesAsMap().keySet() ); + for( String repo : selectedRepositories ) + { + if( availableRepositories.contains( repo ) ) + { + availableRepositories.remove( repo ); + } + } } public Collection<String> getRepositoryIds() @@ -104,9 +158,149 @@ return repositoryIds; } + /** + * Generate the statistics report. + * + * check whether single repo report or comparison report + * 1. if it is a single repository, get all the statistics for the repository on the specified date + * - if no date is specified, get only the latest + * (total page = 1 --> no pagination since only the most recent stats will be displayed) + * - otherwise, get everything within the date range (total pages = repo stats / rows per page) + * - required params: repository, startDate, endDate + * + * 2. if multiple repositories, get the latest statistics on each repository on the specified date + * - if no date is specified, use the current date endDate + * - required params: repositories, endDate + * - total pages = repositories / rows per page + * + * @return + */ + public String generateStatistics() + { + DataLimits limits = new DataLimits(); + setDefaults(); + reposSize = selectedRepositories.size(); + + try + { + RepositoryContentStatisticsDAO repoContentStatsDao = dao.getRepositoryContentStatisticsDAO(); + if( selectedRepositories.size() > 1 ) + { + limits.setTotalCount( selectedRepositories.size() ); + limits.setCurrentPage( 1 ); + limits.setPerPageCount( 1 ); + limits.setCountOfPages( 1 ); + + // multiple repos + for( String repo : selectedRepositories ) + { + try + { + List contentStats = repoContentStatsDao.queryRepositoryContentStatistics( + new RepositoryContentStatisticsByRepositoryConstraint( repo, startDate, endDate ) ); + + if( contentStats == null || contentStats.isEmpty() ) + { + log.info( "No statistics available for repository '" + repo + "'." ); + // TODO set repo's stats to 0 + + continue; + } + repositoryStatistics.addAll( generator.generateReport( contentStats, repo, startDate, endDate, limits ) ); + } + catch ( ObjectNotFoundException oe ) + { + log.error( "No statistics available for repository '" + repo + "'." ); + // TODO set repo's stats to 0 + } + catch ( ArchivaDatabaseException ae ) + { + log.error( "Error encountered while querying statistics of repository '" + repo + "'." ); + // TODO set repo's stats to 0 + } + } + } + else if ( selectedRepositories.size() == 1 ) + { + limits.setCurrentPage( getPage() ); + limits.setPerPageCount( getRowCount() ); + + selectedRepo = selectedRepositories.get( 0 ); + try + { + List<RepositoryContentStatistics> contentStats = repoContentStatsDao.queryRepositoryContentStatistics( + new RepositoryContentStatisticsByRepositoryConstraint( selectedRepo, startDate, endDate ) ); + + if( contentStats == null || contentStats.isEmpty() ) + { + addActionError( "No statistics available for repository. Repository might not have been scanned." ); + return ERROR; + } + + limits.setTotalCount( contentStats.size() ); + int extraPage = ( limits.getTotalCount() % limits.getPerPageCount() ) != 0 ? 1 : 0; + int totalPages = ( limits.getTotalCount() / limits.getPerPageCount() ) + extraPage; + limits.setCountOfPages( totalPages ); + + repositoryStatistics = generator.generateReport( contentStats, selectedRepo, startDate, endDate, limits ); + } + catch ( ObjectNotFoundException oe ) + { + addActionError( oe.getMessage() ); + return ERROR; + } + catch ( ArchivaDatabaseException de ) + { + addActionError( de.getMessage() ); + return ERROR; + } + } + else + { + addFieldError( "availableRepositories", "Please select a repository (or repositories) from the list." ); + return INPUT; + } + } + catch ( ArchivaReportException e ) + { + addActionError( "Error encountered while generating report :: " + e.getMessage() ); + return ERROR; + } + + return SUCCESS; + } + + private void setDefaults() + { + if( startDate == null ) + { + Calendar cal = Calendar.getInstance(); + cal.clear(); + cal.set( 1900, 1, 1, 0, 0, 0 ); + startDate = cal.getTime(); + } + + if( endDate == null ) + { + endDate = Calendar.getInstance().getTime(); + } + } + public String execute() throws Exception - { + { + if( repositoryId == null ) + { + addFieldError( "repositoryId", "You must provide a repository id."); + return INPUT; + } + + if( rowCount < 10 ) + { + addFieldError( "rowCount", "Row count must be larger than 10." ); + return INPUT; + } + List<RepositoryProblem> problemArtifacts = dao.getRepositoryProblemDAO().queryRepositoryProblems( configureConstraint() ); @@ -156,7 +350,7 @@ return SUCCESS; } } - + private static boolean isJasperPresent() { if ( jasperPresent == null ) @@ -207,6 +401,34 @@ return constraint; } + + public SecureActionBundle getSecureActionBundle() + throws SecureActionException + { + SecureActionBundle bundle = new SecureActionBundle(); + + bundle.setRequiresAuthentication( true ); + bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL ); + + return bundle; + } + + private void addToList( RepositoryProblemReport repoProblemReport ) + { + List<RepositoryProblemReport> problemsList = null; + + if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) ) + { + problemsList = ( List<RepositoryProblemReport> ) repositoriesMap.get( repoProblemReport.getRepositoryId() ); + } + else + { + problemsList = new ArrayList<RepositoryProblemReport>(); + repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList ); + } + + problemsList.add( repoProblemReport ); + } public void setServletRequest( HttpServletRequest request ) { @@ -283,31 +505,73 @@ return repositoriesMap; } - public SecureActionBundle getSecureActionBundle() - throws SecureActionException + public List<String> getSelectedRepositories() { - SecureActionBundle bundle = new SecureActionBundle(); + return selectedRepositories; + } - bundle.setRequiresAuthentication( true ); - bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL ); + public void setSelectedRepositories( List<String> selectedRepositories ) + { + this.selectedRepositories = selectedRepositories; + } - return bundle; + public List<String> getAvailableRepositories() + { + return availableRepositories; + } + + public void setAvailableRepositories( List<String> availableRepositories ) + { + this.availableRepositories = availableRepositories; + } + + public Date getStartDate() + { + return startDate; + } + + public void setStartDate( Date startDate ) + { + this.startDate = startDate; + } + + public Date getEndDate() + { + return endDate; + } + + public void setEndDate( Date endDate ) + { + this.endDate = endDate; + } + + public List<RepositoryStatistics> getRepositoryStatistics() + { + return repositoryStatistics; + } + + public void setRepositoryStatistics( List<RepositoryStatistics> repositoryStatistics ) + { + this.repositoryStatistics = repositoryStatistics; } - private void addToList( RepositoryProblemReport repoProblemReport ) + public int getReposSize() + { + return reposSize; + } + + public void setReposSize( int reposSize ) + { + this.reposSize = reposSize; + } + + public String getSelectedRepo() + { + return selectedRepo; + } + + public void setSelectedRepo( String selectedRepo ) { - List<RepositoryProblemReport> problemsList = null; - - if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) ) - { - problemsList = ( List<RepositoryProblemReport> ) repositoriesMap.get( repoProblemReport.getRepositoryId() ); - } - else - { - problemsList = new ArrayList<RepositoryProblemReport>(); - repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList ); - } - - problemsList.add( repoProblemReport ); + this.selectedRepo = selectedRepo; } }
Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/resources/xwork.xml URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/resources/xwork.xml?rev=700729&r1=700728&r2=700729&view=diff ============================================================================== --- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/resources/xwork.xml (original) +++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/resources/xwork.xml Wed Oct 1 03:27:16 2008 @@ -511,6 +511,13 @@ <result name="blank">/WEB-INF/jsp/reports/blankReport.jsp</result> <result>/WEB-INF/jsp/reports/basicReport.jsp</result> </action> + + <action name="generateStatisticsReport" class="generateReport" method="generateStatistics"> + <result name="input">/WEB-INF/jsp/reports/pickReport.jsp</result> + <result name="blank">/WEB-INF/jsp/reports/blankReport.jsp</result> + <result>/WEB-INF/jsp/reports/statisticsReport.jsp</result> + </action> + </package> </xwork> Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp?rev=700729&r1=700728&r2=700729&view=diff ============================================================================== --- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp (original) +++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/pickReport.jsp Wed Oct 1 03:27:16 2008 @@ -27,13 +27,28 @@ <body> <h1>Reports</h1> - + <div id="contentArea"> - <ww:form action="generateReport" namespace="/report" validate="true"> + <h2>Repository Statistics</h2> + <ww:form action="generateStatisticsReport" namespace="/report" validate="true"> + + <ww:optiontransferselect label="Repositories To Be Compared" name="availableRepositories" + list="availableRepositories" doubleName="selectedRepositories" + doubleList="selectedRepositories" size="8" doubleSize="8"/> + + <ww:datepicker label="Start Date" name="startDate" id="startDate"/> + <ww:datepicker label="End Date" name="endDate" id="endDate"/> + + <ww:submit value="View Statistics"/> + </ww:form> + + <h2>Repository Health</h2> + <ww:form namespace="/report" action="generateReport" validate="true"> <ww:textfield label="Row Count" name="rowCount" /> <ww:textfield label="Group ID" name="groupId"/> - <ww:select label="Repository ID" name="repositoryId" list="repositoryIds"/> + <ww:select label="Repository ID" name="repositoryId" list="repositoryIds"/> + <ww:submit value="Show Report"/> </ww:form> Added: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp?rev=700729&view=auto ============================================================================== --- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp (added) +++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/statisticsReport.jsp Wed Oct 1 03:27:16 2008 @@ -0,0 +1,115 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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="archiva" uri="http://archiva.apache.org" %> + +<html> +<head> + <title>Reports</title> + <ww:head/> +</head> + +<body> +<h1>Statistics Report</h1> + +<div id="contentArea"> + <c:choose> + <c:when test="${reposSize > 1}"> + + <h1>Latest Statistics Comparison Report</h1> + <table class="infoTable" border="1"> + <tr> + <th>Repository</th> + <th>Total File Count</th> + <th>Total Size</th> + <th>Artifact Count</th> + <th>Group Count</th> + <th>Project Count</th> + <th>Plugins</th> + <th>Archetypes</th> + <th>Jars</th> + <th>Wars</th> + <th>Deployments</th> + <th>Downloads</th> + </tr> + + <c:forEach var="stats" items="${repositoryStatistics}"> + <tr> + <td>${stats.repositoryId}</td> + <td align="right">${stats.fileCount}</td> + <td align="right">${stats.totalSize}</td> + <td align="right">${stats.artifactCount}</td> + <td align="right">${stats.groupCount}</td> + <td align="right">${stats.projectCount}</td> + <td align="right">${stats.pluginCount}</td> + <td align="right">${stats.archetypeCount}</td> + <td align="right">${stats.jarCount}</td> + <td align="right">${stats.warCount}</td> + <td align="right">${stats.deploymentCount}</td> + <td align="right">${stats.downloadCount}</td> + </tr> + </c:forEach> + </table> + + </c:when> + <c:otherwise> + + <h1>Statistics for Repository '${selectedRepo}'</h1> + <table class="infoTable" border="1"> + <tr> + <th>Date of Scan</th> + <th>Total File Count</th> + <th>Total Size</th> + <th>Artifact Count</th> + <th>Group Count</th> + <th>Project Count</th> + <th>Plugins</th> + <th>Archetypes</th> + <th>Jars</th> + <th>Wars</th> + <th>Deployments</th> + <th>Downloads</th> + </tr> + + <c:forEach var="stats" items="${repositoryStatistics}"> + <tr> + <td align="right">${stats.dateOfScan}</td> + <td align="right">${stats.fileCount}</td> + <td align="right">${stats.totalSize}</td> + <td align="right">${stats.artifactCount}</td> + <td align="right">${stats.groupCount}</td> + <td align="right">${stats.projectCount}</td> + <td align="right">${stats.pluginCount}</td> + <td align="right">${stats.archetypeCount}</td> + <td align="right">${stats.jarCount}</td> + <td align="right">${stats.warCount}</td> + <td align="right">${stats.deploymentCount}</td> + <td align="right">${stats.downloadCount}</td> + </tr> + </c:forEach> + </table> + + </c:otherwise> + </c:choose> + +</div> +</body> +</html> Modified: archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css URL: http://svn.apache.org/viewvc/archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css?rev=700729&r1=700728&r2=700729&view=diff ============================================================================== --- archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css (original) +++ archiva/trunk/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/css/maven-theme.css Wed Oct 1 03:27:16 2008 @@ -33,7 +33,8 @@ select { padding-left: 3px; - height: 1.4em; + height: auto; + width: auto; } input {
