From: Brett Porter Date: Tue, 8 Dec 2009 15:09:13 +0000 (+0000) Subject: Merged /archiva/trunk:r887040-888396 X-Git-Tag: archiva-1.4-M1~1017^2~91 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ebaee33d1ef27a2aefb989533fdbfb0ffd9f161b;p=archiva.git Merged /archiva/trunk:r887040-888396 git-svn-id: https://svn.apache.org/repos/asf/archiva/branches/MRM-1025@888427 13f79535-47bb-0310-9956-ffa450edef68 --- ebaee33d1ef27a2aefb989533fdbfb0ffd9f161b diff --cc archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java index a0484fe28,f38012909..49724c86d --- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/reports/GenerateReportAction.java @@@ -187,75 -224,61 +187,75 @@@ public class GenerateReportActio } catch ( ParseException e ) { - addActionError( "Error parsing date(s)." ); - return ERROR; + addActionError( "Error parsing date(s)." ); + return ERROR; } - - if( startDateInDF.after( endDateInDF ) ) + - if ( startDateInDF.after( endDateInDF ) ) ++ if ( startDateInDF != null && endDateInDF != null && startDateInDF.after( endDateInDF ) ) { addFieldError( "startDate", "Start Date must be earlier than the End Date" ); return INPUT; } - + // multiple repos - generateReportForMultipleRepos(repoContentStatsDao, startDateInDF, endDateInDF, true); + for ( String repo : selectedRepositories ) + { + List stats = + repositoryStatisticsManager.getStatisticsInRange( repo, startDateInDF, endDateInDF ); + if ( stats.isEmpty() ) + { + log.info( "No statistics available for repository '" + repo + "'." ); + // TODO set repo's stats to 0 + continue; + } + + repositoryStatistics.add( stats.get( 0 ) ); + } } else if ( selectedRepositories.size() == 1 ) - { - limits.setCurrentPage( getPage() ); - limits.setPerPageCount( getRowCount() ); - - selectedRepo = selectedRepositories.get( 0 ); + { + repositoryId = selectedRepositories.get( 0 ); try - { - startDateInDF = getStartDateInDateFormat(); - endDateInDF = getEndDateInDateFormat(); - - if( startDateInDF.after( endDateInDF ) ) + { + startDateInDF = getStartDateInDateFormat(); + endDateInDF = getEndDateInDateFormat(); + - if ( startDateInDF.after( endDateInDF ) ) ++ if ( startDateInDF != null && endDateInDF != null && startDateInDF.after( endDateInDF ) ) { - addFieldError( "startDate", "Start Date must be earlier than the End Date" ); - return INPUT; + addFieldError( "startDate", "Start Date must be earlier than the End Date" ); + return INPUT; } - - List contentStats = repoContentStatsDao.queryRepositoryContentStatistics( - new RepositoryContentStatisticsByRepositoryConstraint( selectedRepo, startDateInDF, endDateInDF ) ); - - if( contentStats == null || contentStats.isEmpty() ) - { - addActionError( "No statistics available for repository. Repository might not have been scanned." ); + + List stats = + repositoryStatisticsManager.getStatisticsInRange( repositoryId, startDateInDF, endDateInDF ); + + if ( stats.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, startDateInDF, endDateInDF, limits ); - } - catch ( ObjectNotFoundException oe ) - { - addActionError( oe.getMessage() ); - return ERROR; - } - catch ( ArchivaDatabaseException de ) - { - addActionError( de.getMessage() ); - return ERROR; + } + + int rowCount = getRowCount(); + int extraPage = ( stats.size() % rowCount ) != 0 ? 1 : 0; + int totalPages = ( stats.size() / rowCount ) + extraPage; + numPages = totalPages; + + int currentPage = getPage(); + if ( currentPage > totalPages ) + { + throw new ArchivaReportException( "The requested page exceeds the total number of pages." ); + } + + int start = rowCount * ( currentPage - 1 ); + int end = ( start + rowCount ) - 1; + + if ( end > stats.size() ) + { + end = stats.size() - 1; + } + + repositoryStatistics = stats.subList( start, end + 1 ); } catch ( ParseException pe ) { @@@ -279,171 -302,136 +279,171 @@@ addActionError( "Error encountered while generating report :: " + e.getMessage() ); return ERROR; } - + return SUCCESS; } - + /** * Export report to CSV. - * - * @return + * + * @return action result */ public String downloadStatisticsReport() - { - try + { + Date startDateInDF; + Date endDateInDF; + + selectedRepositories = parseSelectedRepositories(); + List repositoryStatistics = new ArrayList(); + + StringBuffer input = null; + if ( selectedRepositories.size() > 1 ) { - Date startDateInDF = null; - Date endDateInDF = null; - - selectedRepositories = parseSelectedRepositories(); - repositoryStatistics = new ArrayList(); - - RepositoryContentStatisticsDAO repoContentStatsDao = dao.getRepositoryContentStatisticsDAO(); - if( selectedRepositories.size() > 1 ) - { - try - { - startDateInDF = getStartDateInDateFormat(); - endDateInDF = getEndDateInDateFormat(); - } - catch ( ParseException e ) + try + { + startDateInDF = getStartDateInDateFormat(); + endDateInDF = getEndDateInDateFormat(); + } + catch ( ParseException e ) + { + addActionError( "Error parsing date(s)." ); + return ERROR; + } + - if ( startDateInDF.after( endDateInDF ) ) ++ if ( startDateInDF != null && endDateInDF != null && startDateInDF.after( endDateInDF ) ) + { + addFieldError( "startDate", "Start Date must be earlier than the End Date" ); + return INPUT; + } + ++ input = new StringBuffer( ++ "Repository,Total File Count,Total Size,Artifact Count,Group Count,Project Count," + ++ "Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" ); ++ + // multiple repos + for ( String repo : selectedRepositories ) + { + List stats = + repositoryStatisticsManager.getStatisticsInRange( repo, startDateInDF, endDateInDF ); + if ( stats.isEmpty() ) { - addActionError( "Error parsing date(s)." ); - return ERROR; + log.info( "No statistics available for repository '" + repo + "'." ); + // TODO set repo's stats to 0 + continue; } - - if( startDateInDF.after( endDateInDF ) ) + + // only the first one + RepositoryStatistics repositoryStats = stats.get( 0 ); + repositoryStatistics.add( repositoryStats ); + - input = new StringBuffer( - "Repository,Total File Count,Total Size,Artifact Count,Group Count,Project Count," + - "Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" ); - + input.append( repo ).append( "," ); + input.append( repositoryStats.getTotalFileCount() ).append( "," ); + input.append( repositoryStats.getTotalArtifactFileSize() ).append( "," ); + input.append( repositoryStats.getTotalArtifactCount() ).append( "," ); + input.append( repositoryStats.getTotalGroupCount() ).append( "," ); - input.append( repositoryStats.getTotalProjectCount() ).append( "," ); ++ input.append( repositoryStats.getTotalProjectCount() );//.append( "," ); + // TODO +// input.append( repositoryStats.getPluginCount() ).append( "," ); +// input.append( repositoryStats.getArchetypeCount() ).append( "," ); +// input.append( repositoryStats.getJarCount() ).append( "," ); +// input.append( repositoryStats.getWarCount() ).append( "," ); +// input.append( repositoryStats.getDeploymentCount() ).append( "," ); +// input.append( repositoryStats.getDownloadCount() ).append( "\n" ); + input.append( "\n" ); + } + } + else if ( selectedRepositories.size() == 1 ) + { + repositoryId = selectedRepositories.get( 0 ); + try + { + startDateInDF = getStartDateInDateFormat(); + endDateInDF = getEndDateInDateFormat(); + - if ( startDateInDF.after( endDateInDF ) ) ++ if ( startDateInDF != null && endDateInDF != null && startDateInDF.after( endDateInDF ) ) { addFieldError( "startDate", "Start Date must be earlier than the End Date" ); return INPUT; } - - // multiple repos - generateReportForMultipleRepos( repoContentStatsDao, startDateInDF, endDateInDF, false ); - } - else if ( selectedRepositories.size() == 1 ) - { - selectedRepo = selectedRepositories.get( 0 ); - try - { - startDateInDF = getStartDateInDateFormat(); - endDateInDF = getEndDateInDateFormat(); - - if( startDateInDF.after( endDateInDF ) ) - { - addFieldError( "startDate", "Start Date must be earlier than the End Date" ); - return INPUT; - } - - List contentStats = repoContentStatsDao.queryRepositoryContentStatistics( - new RepositoryContentStatisticsByRepositoryConstraint( selectedRepo, startDateInDF, endDateInDF ) ); - - if( contentStats == null || contentStats.isEmpty() ) - { - addActionError( "No statistics available for repository. Repository might not have been scanned." ); - return ERROR; - } - - repositoryStatistics = generator.generateReport( contentStats, selectedRepo, startDateInDF, endDateInDF, false ); - } - catch ( ObjectNotFoundException oe ) - { - addActionError( oe.getMessage() ); - return ERROR; - } - catch ( ArchivaDatabaseException de ) + + List stats = + repositoryStatisticsManager.getStatisticsInRange( repositoryId, startDateInDF, endDateInDF ); + if ( stats.isEmpty() ) { - addActionError( de.getMessage() ); + addActionError( "No statistics available for repository. Repository might not have been scanned." ); return ERROR; } - catch ( ParseException pe ) + + input = new StringBuffer( + "Date of Scan,Total File Count,Total Size,Artifact Count,Group Count,Project Count," + + "Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" ); + + for ( RepositoryStatistics repositoryStats : stats ) { - addActionError( pe.getMessage() ); - return ERROR; + input.append( repositoryStats.getScanStartTime() ).append( "," ); + input.append( repositoryStats.getTotalFileCount() ).append( "," ); + input.append( repositoryStats.getTotalArtifactFileSize() ).append( "," ); + input.append( repositoryStats.getTotalArtifactCount() ).append( "," ); + input.append( repositoryStats.getTotalGroupCount() ).append( "," ); - input.append( repositoryStats.getTotalProjectCount() ).append( "," ); ++ input.append( repositoryStats.getTotalProjectCount() );//.append( "," ); + // TODO +// input.append( repositoryStats.getPluginCount() ).append( "," ); +// input.append( repositoryStats.getArchetypeCount() ).append( "," ); +// input.append( repositoryStats.getJarCount() ).append( "," ); +// input.append( repositoryStats.getWarCount() ).append( "," ); +// input.append( repositoryStats.getDeploymentCount() ).append( "," ); +// input.append( repositoryStats.getDownloadCount() ); + input.append( "\n" ); } + + repositoryStatistics = stats; } - else + catch ( ParseException pe ) { - addFieldError( "availableRepositories", "Please select a repository (or repositories) from the list." ); - return INPUT; - } - - if( repositoryStatistics.isEmpty() ) - { - return BLANK; - } + addActionError( pe.getMessage() ); + return ERROR; + } } - catch ( ArchivaReportException e ) + else { - addActionError( "Error encountered while generating report :: " + e.getMessage() ); - return ERROR; - } - - // write output stream depending on single or comparison report - StringBuffer input = getInput(); + addFieldError( "availableRepositories", "Please select a repository (or repositories) from the list." ); + return INPUT; + } + + if ( repositoryStatistics.isEmpty() ) + { + return BLANK; + } + + // write output stream depending on single or comparison report StringReader reader = new StringReader( input.toString() ); - + try { - inputStream = new ByteArrayInputStream( IOUtils.toByteArray( reader ) ); + inputStream = new ByteArrayInputStream( IOUtils.toByteArray( reader ) ); } catch ( IOException i ) - { - addActionError( "Error occurred while generating CSV file." ); - return ERROR; + { + addActionError( "Error occurred while generating CSV file." ); + return ERROR; } - - return SEND_FILE; + + return SEND_FILE; } - + // hack for parsing the struts list passed as param in private List parseSelectedRepositories() - { + { List pasedSelectedRepos = new ArrayList(); - - for( String repo : selectedRepositories ) - { + + for ( String repo : selectedRepositories ) + { String[] tokens = StringUtils.split( repo, ',' ); - if( tokens.length > 1 ) + if ( tokens.length > 1 ) { - for( int i = 0; i < tokens.length; i++ ) - { - pasedSelectedRepos.add( StringUtils.remove( StringUtils.remove( tokens[i], '[' ), ']' ).trim() ); + for ( String token : tokens ) + { + pasedSelectedRepos.add( StringUtils.remove( StringUtils.remove( token, '[' ), ']' ).trim() ); } } else @@@ -460,7 -489,7 +460,7 @@@ Date startDateInDF; if ( startDate == null || "".equals( startDate ) ) { -- startDateInDF = getDefaultStartDate(); ++ startDateInDF = null; } else { @@@ -475,46 -504,90 +475,32 @@@ Date endDateInDF; if ( endDate == null || "".equals( endDate ) ) { -- endDateInDF = getDefaultEndDate(); ++ endDateInDF = null; } else { endDateInDF = DateUtils.parseDate( endDate, datePatterns ); + + // add a day, since we don't inclue time and want the date to be inclusive + Calendar cal = Calendar.getInstance(); + cal.setTime( endDateInDF ); + cal.add( Calendar.DAY_OF_MONTH, 1 ); + endDateInDF = cal.getTime(); } - + return endDateInDF; } - - private StringBuffer getInput() - { - StringBuffer input = null; - - if( selectedRepositories.size() == 1 ) - { - input = new StringBuffer( "Date of Scan,Total File Count,Total Size,Artifact Count,Group Count,Project Count," + - "Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" ); - - for( RepositoryStatistics stats : repositoryStatistics ) - { - input.append( stats.getDateOfScan() ).append( "," ); - input.append( stats.getFileCount() ).append( "," ); - input.append( stats.getTotalSize() ).append( "," ); - input.append( stats.getArtifactCount() ).append( "," ); - input.append( stats.getGroupCount() ).append( "," ); - input.append( stats.getProjectCount() ).append( "," ); - input.append( stats.getPluginCount() ).append( "," ); - input.append( stats.getArchetypeCount() ).append( "," ); - input.append( stats.getJarCount() ).append( "," ); - input.append( stats.getWarCount() ).append( "," ); - input.append( stats.getDeploymentCount() ).append( "," ); - input.append( stats.getDownloadCount() ).append( "\n" ); - } - } - else if( selectedRepositories.size() > 1 ) - { - input = new StringBuffer( "Repository,Total File Count,Total Size,Artifact Count,Group Count,Project Count," + - "Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" ); - - for( RepositoryStatistics stats : repositoryStatistics ) - { - input.append( stats.getRepositoryId() ).append( "," ); - input.append( stats.getFileCount() ).append( "," ); - input.append( stats.getTotalSize() ).append( "," ); - input.append( stats.getArtifactCount() ).append( "," ); - input.append( stats.getGroupCount() ).append( "," ); - input.append( stats.getProjectCount() ).append( "," ); - input.append( stats.getPluginCount() ).append( "," ); - input.append( stats.getArchetypeCount() ).append( "," ); - input.append( stats.getJarCount() ).append( "," ); - input.append( stats.getWarCount() ).append( "," ); - input.append( stats.getDeploymentCount() ).append( "," ); - input.append( stats.getDownloadCount() ).append( "\n" ); - } - } - - return input; - } - - private Date getDefaultStartDate() - { - Calendar cal = Calendar.getInstance(); - cal.clear(); - cal.set( 1900, 1, 1, 0, 0, 0 ); - - return cal.getTime(); - } - - private Date getDefaultEndDate() - { - return Calendar.getInstance().getTime(); - } - + - private Date getDefaultStartDate() - { - Calendar cal = Calendar.getInstance(); - cal.clear(); - cal.set( 1900, 1, 1, 0, 0, 0 ); - - return cal.getTime(); - } - - private Date getDefaultEndDate() - { - return Calendar.getInstance().getTime(); - } - public String execute() throws Exception - { - if( repositoryId == null ) + { + if ( repositoryId == null ) { - addFieldError( "repositoryId", "You must provide a repository id."); + addFieldError( "repositoryId", "You must provide a repository id." ); return INPUT; } - - if( rowCount < 10 ) + + if ( rowCount < 10 ) { addFieldError( "rowCount", "Row count must be larger than 10." ); return INPUT; @@@ -597,33 -698,28 +583,16 @@@ throws SecureActionException { SecureActionBundle bundle = new SecureActionBundle(); - + bundle.setRequiresAuthentication( true ); bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL ); - + return bundle; } - - private void addToList( RepositoryProblemReport repoProblemReport ) + - private void addToList( RepositoryProblemReport repoProblemReport ) - { - List problemsList = null; - - if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) ) - { - problemsList = (List) repositoriesMap.get( repoProblemReport.getRepositoryId() ); - } - else - { - problemsList = new ArrayList(); - repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList ); - } - - problemsList.add( repoProblemReport ); - } - + public Collection getRepositoryIds() { - List problemsList = null; - - if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) ) - { - problemsList = ( List ) repositoriesMap.get( repoProblemReport.getRepositoryId() ); - } - else - { - problemsList = new ArrayList(); - repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList ); - } - - problemsList.add( repoProblemReport ); + return repositoryIds; } public void setServletRequest( HttpServletRequest request ) @@@ -730,24 -846,39 +699,29 @@@ { this.repositoryStatistics = repositoryStatistics; } - - public int getReposSize() - { - return reposSize; - } - public void setReposSize( int reposSize ) + public boolean isLastPage() { - this.reposSize = reposSize; + return lastPage; } - public String getSelectedRepo() + public void setLastPage( boolean lastPage ) { - return selectedRepo; + this.lastPage = lastPage; } - public void setSelectedRepo( String selectedRepo ) + public InputStream getInputStream() { - this.selectedRepo = selectedRepo; + return inputStream; } - public DataLimits getLimits() + public int getNumPages() { - return limits; + return numPages; } + - public void setLimits( DataLimits limits ) - { - this.limits = limits; - } - - public InputStream getInputStream() ++ public void setRepositoryStatisticsManager( RepositoryStatisticsManager repositoryStatisticsManager ) + { - return inputStream; ++ this.repositoryStatisticsManager = repositoryStatisticsManager; + } } diff --cc archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/repositories/ArchivaDAOStub.java index 3466be16d,2e9b97e58..973da10bb --- a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/repositories/ArchivaDAOStub.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/repositories/ArchivaDAOStub.java @@@ -1,17 -1,23 +1,5 @@@ package org.apache.maven.archiva.web.action.admin.repositories; --import java.io.Serializable; -import java.util.ArrayList; --import java.util.List; -- -import junit.framework.Assert; --import org.apache.maven.archiva.configuration.ArchivaConfiguration; --import org.apache.maven.archiva.database.ArchivaDAO; --import org.apache.maven.archiva.database.ArtifactDAO; -import org.apache.maven.archiva.database.ProjectModelDAO; -import org.apache.maven.archiva.database.RepositoryContentStatisticsDAO; --import org.apache.maven.archiva.database.RepositoryProblemDAO; --import org.apache.maven.archiva.database.SimpleConstraint; --import org.apache.maven.archiva.database.constraints.UniqueArtifactIdConstraint; -import org.apache.maven.archiva.database.constraints.UniqueFieldConstraint; --import org.apache.maven.archiva.database.constraints.UniqueGroupIdConstraint; --import org.apache.maven.archiva.database.constraints.UniqueVersionConstraint; -import org.apache.maven.archiva.model.RepositoryContentStatistics; -- /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@@ -31,6 -37,6 +19,19 @@@ * under the License. */ ++import java.io.Serializable; ++import java.util.List; ++ ++import org.apache.maven.archiva.configuration.ArchivaConfiguration; ++import org.apache.maven.archiva.database.ArchivaDAO; ++import org.apache.maven.archiva.database.ArtifactDAO; ++import org.apache.maven.archiva.database.RepositoryProblemDAO; ++import org.apache.maven.archiva.database.SimpleConstraint; ++import org.apache.maven.archiva.database.constraints.UniqueArtifactIdConstraint; ++import org.apache.maven.archiva.database.constraints.UniqueFieldConstraint; ++import org.apache.maven.archiva.database.constraints.UniqueGroupIdConstraint; ++import org.apache.maven.archiva.database.constraints.UniqueVersionConstraint; ++ /** * Stub class for Archiva DAO to avoid having to set up a database for tests. * @@@ -49,6 -57,12 +50,10 @@@ public class ArchivaDAOStu private List artifacts; + private List repositoryIds; + - private RepositoryContentStatisticsDAO repositoryContentStatisticsDAO; - + private RepositoryProblemDAO repositoryProblemDAO; + public List query( SimpleConstraint constraint ) { if ( constraint instanceof UniqueVersionConstraint ) @@@ -63,7 -77,23 +68,11 @@@ { return artifacts; } + else if ( constraint instanceof UniqueFieldConstraint ) + { + return repositoryIds; + } - else - { - Assert.assertEquals( RepositoryContentStatistics.class, constraint.getResultClass() ); - - List stats = new ArrayList(); - for ( String repo : configuration.getConfiguration().getManagedRepositoriesAsMap().keySet() ) - { - RepositoryContentStatistics statistics = new RepositoryContentStatistics(); - statistics.setRepositoryId( repo ); - stats.add( statistics ); - } - return stats; - } + throw new UnsupportedOperationException(); } public Object save( Serializable obj ) @@@ -76,11 -106,21 +85,11 @@@ return artifactDao; } - public ProjectModelDAO getProjectModelDAO() - { - return projectDao; - } - public RepositoryProblemDAO getRepositoryProblemDAO() { - throw new UnsupportedOperationException( "method not implemented for stub" ); + return repositoryProblemDAO; } - public RepositoryContentStatisticsDAO getRepositoryContentStatisticsDAO() - { - return repositoryContentStatisticsDAO; - } - public void setArtifactDao( ArtifactDAO artifactDao ) { this.artifactDao = artifactDao; diff --cc archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/reports/GenerateReportActionTest.java index 000000000,82103db48..46c258f2f mode 000000,100644..100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/reports/GenerateReportActionTest.java +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/reports/GenerateReportActionTest.java @@@ -1,0 -1,535 +1,643 @@@ + package org.apache.maven.archiva.web.action.reports; + + /* + * 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. + */ + + import java.io.IOException; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collections; ++import java.util.Date; + import java.util.List; + + import com.meterware.servletunit.ServletRunner; + import com.meterware.servletunit.ServletUnitClient; + import com.opensymphony.xwork2.Action; ++import org.apache.archiva.metadata.repository.stats.RepositoryStatistics; ++import org.apache.archiva.metadata.repository.stats.RepositoryStatisticsManager; + import org.apache.commons.io.IOUtils; + import org.apache.maven.archiva.database.ArchivaDAO; + import org.apache.maven.archiva.database.ArchivaDatabaseException; -import org.apache.maven.archiva.database.RepositoryContentStatisticsDAO; + import org.apache.maven.archiva.database.RepositoryProblemDAO; + 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.model.RepositoryContentStatistics; + import org.apache.maven.archiva.model.RepositoryProblem; + import org.apache.maven.archiva.model.RepositoryProblemReport; + import org.apache.maven.archiva.web.action.admin.repositories.ArchivaDAOStub; -import org.apache.maven.archiva.web.action.admin.repositories.RepositoryContentStatisticsDAOStub; + import org.codehaus.plexus.spring.PlexusInSpringTestCase; + import org.easymock.MockControl; + + /** + * Test the GenerationReportAction. Note that we are testing for current behaviour, however there are several + * instances below where other behaviour may actually be more appropriate (eg the error handling, download stats should + * never forward to HTML page, etc). This is also missing tests for various combinations of paging at this point. + */ + public class GenerateReportActionTest + extends PlexusInSpringTestCase + { + private GenerateReportAction action; + + private static final String SNAPSHOTS = "snapshots"; + + private static final String INTERNAL = "internal"; + + private RepositoryProblemDAO repositoryProblemDAO; + + private MockControl repositoryProblemDAOControl; + + private static final String GROUP_ID = "groupId"; + + private static final String URL = "http://localhost/reports/generateReport.action"; + ++ private RepositoryStatisticsManager repositoryStatisticsManager; ++ ++ private MockControl repositoryStatisticsManagerControl; ++ + @Override + protected void setUp() + throws Exception + { + super.setUp(); + + ArchivaDAOStub archivaDAOStub = (ArchivaDAOStub) lookup( ArchivaDAO.class, "jdo" ); + archivaDAOStub.setRepositoryIds( Arrays.asList( "repo1", "repo2" ) ); + + repositoryProblemDAOControl = MockControl.createControl( RepositoryProblemDAO.class ); + repositoryProblemDAO = (RepositoryProblemDAO) repositoryProblemDAOControl.getMock(); + archivaDAOStub.setRepositoryProblemDAO( repositoryProblemDAO ); + + action = (GenerateReportAction) lookup( Action.class, "generateReport" ); ++ ++ repositoryStatisticsManagerControl = MockControl.createControl( RepositoryStatisticsManager.class ); ++ repositoryStatisticsManager = (RepositoryStatisticsManager) repositoryStatisticsManagerControl.getMock(); ++ action.setRepositoryStatisticsManager( repositoryStatisticsManager ); + } + + private void prepareAction( List selectedRepositories, List availableRepositories ) + { + action.setSelectedRepositories( selectedRepositories ); + action.prepare(); + + assertEquals( Arrays.asList( GenerateReportAction.ALL_REPOSITORIES, "repo1", "repo2" ), + action.getRepositoryIds() ); + assertEquals( availableRepositories, action.getAvailableRepositories() ); + } + + public void testGenerateStatisticsInvalidRowCount() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Collections.singletonList( INTERNAL ), Collections.singletonList( SNAPSHOTS ) ); + + action.setRowCount( 0 ); + String result = action.generateStatistics(); + assertEquals( Action.INPUT, result ); + assertTrue( action.hasFieldErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsInvalidEndDate() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Collections.singletonList( INTERNAL ), Collections.singletonList( SNAPSHOTS ) ); + + action.setStartDate( "2009/12/12" ); + action.setEndDate( "2008/11/11" ); + String result = action.generateStatistics(); + assertEquals( Action.INPUT, result ); + assertTrue( action.hasFieldErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsMalformedEndDate() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Collections.singletonList( INTERNAL ), Collections.singletonList( SNAPSHOTS ) ); + + action.setEndDate( "This is not a date" ); + String result = action.generateStatistics(); + + // TODO: should be an input error + assertEquals( Action.ERROR, result ); + assertTrue( action.hasActionErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsInvalidEndDateMultiRepo() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); + + action.setStartDate( "2009/12/12" ); + action.setEndDate( "2008/11/11" ); + String result = action.generateStatistics(); + assertEquals( Action.INPUT, result ); + assertTrue( action.hasFieldErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsMalformedEndDateMultiRepo() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); + + action.setEndDate( "This is not a date" ); + String result = action.generateStatistics(); + + // TODO: should be an input error + assertEquals( Action.ERROR, result ); + assertTrue( action.hasActionErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsNoRepos() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.generateStatistics(); + assertEquals( Action.INPUT, result ); + assertTrue( action.hasFieldErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsSingleRepo() + { ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), ++ Collections.singletonList( createDefaultStats() ) ); ++ ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Collections.singletonList( INTERNAL ), Collections.singletonList( SNAPSHOTS ) ); + + String result = action.generateStatistics(); + assertSuccessResult( result ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsSingleRepoNoStats() + { - RepositoryContentStatisticsDAOStub dao = - (RepositoryContentStatisticsDAOStub) lookup( RepositoryContentStatisticsDAO.class, "jdo" ); - dao.setStats( Collections.emptyList() ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), Collections.emptyList() ); ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Collections.singletonList( INTERNAL ), Collections.singletonList( SNAPSHOTS ) ); + + String result = action.generateStatistics(); + assertEquals( Action.ERROR, result ); + assertTrue( action.hasActionErrors() ); ++ ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsOvershotPages() + { ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), ++ Collections.singletonList( createDefaultStats() ) ); ++ repositoryStatisticsManagerControl.replay(); + action.setPage( 2 ); + prepareAction( Collections.singletonList( INTERNAL ), Collections.singletonList( SNAPSHOTS ) ); + + String result = action.generateStatistics(); + assertEquals( Action.ERROR, result ); + assertTrue( action.hasActionErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsMultipleRepoNoResults() + { - RepositoryContentStatisticsDAOStub dao = - (RepositoryContentStatisticsDAOStub) lookup( RepositoryContentStatisticsDAO.class, "jdo" ); - dao.setStats( Collections.emptyList() ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( SNAPSHOTS, null, null ), ++ Collections.emptyList() ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), Collections.emptyList() ); ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); + + String result = action.generateStatistics(); + assertEquals( GenerateReportAction.BLANK, result ); + assertFalse( action.hasActionErrors() ); + assertFalse( action.hasActionMessages() ); + assertFalse( action.hasFieldErrors() ); ++ ++ repositoryStatisticsManagerControl.verify(); + } + + public void testGenerateStatisticsMultipleRepo() + { ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( SNAPSHOTS, null, null ), ++ Collections.singletonList( createDefaultStats() ) ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), ++ Collections.singletonList( createDefaultStats() ) ); ++ ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); + + String result = action.generateStatistics(); + assertSuccessResult( result ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testDownloadStatisticsSingleRepo() + throws IOException, ArchivaDatabaseException + { ++ Date date = new Date(); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( SNAPSHOTS, null, null ), ++ Collections.singletonList( createStats( date ) ) ); ++ repositoryStatisticsManagerControl.replay(); ++ + prepareAction( Arrays.asList( SNAPSHOTS ), Arrays.asList( INTERNAL ) ); + + String result = action.downloadStatisticsReport(); + assertEquals( GenerateReportAction.SEND_FILE, result ); + assertFalse( action.hasActionErrors() ); + assertFalse( action.hasFieldErrors() ); + - RepositoryContentStatisticsDAOStub dao = - (RepositoryContentStatisticsDAOStub) lookup( RepositoryContentStatisticsDAO.class, "jdo" ); - RepositoryContentStatistics stats = dao.queryRepositoryContentStatistics( - new RepositoryContentStatisticsByRepositoryConstraint( SNAPSHOTS ) ).get( 0 ); - ++// assertEquals( ++// "Date of Scan,Total File Count,Total Size,Artifact Count,Group Count,Project Count,Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" + ++// date + ",0,0,0,0,0,1,0,1,1,0,0\n", IOUtils.toString( action.getInputStream() ) ); + assertEquals( + "Date of Scan,Total File Count,Total Size,Artifact Count,Group Count,Project Count,Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" + - stats.getWhenGathered() + ",0,0,0,0,0,1,0,1,1,0,0\n", IOUtils.toString( action.getInputStream() ) ); ++ date + ",0,0,0,0,0\n", IOUtils.toString( action.getInputStream() ) ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testDownloadStatisticsMultipleRepos() + throws IOException, ArchivaDatabaseException + { ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( SNAPSHOTS, null, null ), ++ Collections.singletonList( createDefaultStats() ) ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), ++ Collections.singletonList( createDefaultStats() ) ); ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); + + String result = action.downloadStatisticsReport(); + assertEquals( GenerateReportAction.SEND_FILE, result ); + assertFalse( action.hasActionErrors() ); + assertFalse( action.hasFieldErrors() ); + + assertMultiRepoCsvResult(); ++ repositoryStatisticsManagerControl.verify(); + } + - private void assertMultiRepoCsvResult() - throws IOException ++ public void testDownloadStatisticsMalformedEndDateMultiRepo() + { - assertEquals( - "Repository,Total File Count,Total Size,Artifact Count,Group Count,Project Count,Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" + - "snapshots,0,0,0,0,0,1,0,1,1,0,0\n" + "internal,0,0,0,0,0,1,0,1,1,0,0\n", - IOUtils.toString( action.getInputStream() ) ); ++ repositoryStatisticsManagerControl.replay(); ++ prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); ++ ++ action.setEndDate( "This is not a date" ); ++ String result = action.downloadStatisticsReport(); ++ ++ // TODO: should be an input error ++ assertEquals( Action.ERROR, result ); ++ assertTrue( action.hasActionErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + - public void testDownloadStatisticsMalformedEndDateMultiRepo() ++ public void testDownloadStatisticsMalformedEndDateSingleRepo() + { - prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); ++ repositoryStatisticsManagerControl.replay(); ++ prepareAction( Arrays.asList( SNAPSHOTS ), Arrays.asList( INTERNAL ) ); + + action.setEndDate( "This is not a date" ); + String result = action.downloadStatisticsReport(); + + // TODO: should be an input error + assertEquals( Action.ERROR, result ); + assertTrue( action.hasActionErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testDownloadStatisticsInvalidEndDateMultiRepo() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); + + action.setStartDate( "2009/12/12" ); + action.setEndDate( "2008/11/11" ); + String result = action.downloadStatisticsReport(); + assertEquals( Action.INPUT, result ); + assertTrue( action.hasFieldErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testDownloadStatisticsInvalidEndDateSingleRepo() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS ), Arrays.asList( INTERNAL ) ); + + action.setStartDate( "2009/12/12" ); + action.setEndDate( "2008/11/11" ); + String result = action.downloadStatisticsReport(); + assertEquals( Action.INPUT, result ); + assertTrue( action.hasFieldErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testDownloadStatisticsSingleRepoNoStats() + { - RepositoryContentStatisticsDAOStub dao = - (RepositoryContentStatisticsDAOStub) lookup( RepositoryContentStatisticsDAO.class, "jdo" ); - dao.setStats( Collections.emptyList() ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), Collections.emptyList() ); ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Collections.singletonList( INTERNAL ), Collections.singletonList( SNAPSHOTS ) ); + + String result = action.downloadStatisticsReport(); + assertEquals( Action.ERROR, result ); + assertTrue( action.hasActionErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testDownloadStatisticsNoRepos() + { ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.downloadStatisticsReport(); + assertEquals( Action.INPUT, result ); + assertTrue( action.hasFieldErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testDownloadStatisticsMultipleRepoNoResults() + { - RepositoryContentStatisticsDAOStub dao = - (RepositoryContentStatisticsDAOStub) lookup( RepositoryContentStatisticsDAO.class, "jdo" ); - dao.setStats( Collections.emptyList() ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( SNAPSHOTS, null, null ), ++ Collections.emptyList() ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), Collections.emptyList() ); ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); + + String result = action.downloadStatisticsReport(); + assertEquals( GenerateReportAction.BLANK, result ); + assertFalse( action.hasActionErrors() ); + assertFalse( action.hasActionMessages() ); + assertFalse( action.hasFieldErrors() ); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testDownloadStatisticsMultipleRepoInStrutsFormat() + throws IOException + { ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( SNAPSHOTS, null, null ), ++ Collections.singletonList( createDefaultStats() ) ); ++ repositoryStatisticsManagerControl.expectAndReturn( ++ repositoryStatisticsManager.getStatisticsInRange( INTERNAL, null, null ), ++ Collections.singletonList( createDefaultStats() ) ); ++ repositoryStatisticsManagerControl.replay(); + prepareAction( Arrays.asList( SNAPSHOTS, INTERNAL ), Collections.emptyList() ); + + action.setSelectedRepositories( Collections.singletonList( "[" + SNAPSHOTS + "],[" + INTERNAL + "]" ) ); + String result = action.downloadStatisticsReport(); + assertEquals( GenerateReportAction.SEND_FILE, result ); + assertFalse( action.hasActionErrors() ); + assertFalse( action.hasFieldErrors() ); + + assertMultiRepoCsvResult(); ++ repositoryStatisticsManagerControl.verify(); + } + + public void testHealthReportSingleRepo() + throws Exception + { + RepositoryProblem problem1 = createProblem( GROUP_ID, "artifactId", INTERNAL ); + RepositoryProblem problem2 = createProblem( GROUP_ID, "artifactId-2", INTERNAL ); + repositoryProblemDAOControl.expectAndReturn( repositoryProblemDAO.queryRepositoryProblems( + new RepositoryProblemByRepositoryIdConstraint( new int[]{0, 101}, INTERNAL ) ), + Arrays.asList( problem1, problem2 ) ); + repositoryProblemDAOControl.replay(); + + action.setRepositoryId( INTERNAL ); + ServletRunner sr = new ServletRunner(); + ServletUnitClient sc = sr.newClient(); + + action.setServletRequest( sc.newInvocation( URL ).getRequest() ); + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.execute(); + assertSuccessResult( result ); + + RepositoryProblemReport problemReport1 = createProblemReport( problem1 ); + RepositoryProblemReport problemReport2 = createProblemReport( problem2 ); + assertEquals( Collections.singleton( INTERNAL ), action.getRepositoriesMap().keySet() ); + assertEquals( Arrays.asList( problemReport1, problemReport2 ), action.getRepositoriesMap().get( INTERNAL ) ); + + repositoryProblemDAOControl.verify(); + } + + public void testHealthReportInvalidRowCount() + throws Exception + { + repositoryProblemDAOControl.replay(); + + action.setRowCount( 0 ); + action.setRepositoryId( INTERNAL ); + ServletRunner sr = new ServletRunner(); + ServletUnitClient sc = sr.newClient(); + + action.setServletRequest( sc.newInvocation( URL ).getRequest() ); + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.execute(); + assertEquals( Action.INPUT, result ); + assertFalse( action.hasActionErrors() ); + assertTrue( action.hasFieldErrors() ); + + repositoryProblemDAOControl.verify(); + } + + public void testHealthReportAllRepos() + throws Exception + { + RepositoryProblem problem1 = createProblem( GROUP_ID, "artifactId", INTERNAL ); + RepositoryProblem problem2 = createProblem( GROUP_ID, "artifactId-2", SNAPSHOTS ); + repositoryProblemDAOControl.expectAndReturn( + repositoryProblemDAO.queryRepositoryProblems( new RangeConstraint( new int[]{0, 101} ) ), + Arrays.asList( problem1, problem2 ) ); + repositoryProblemDAOControl.replay(); + + action.setRepositoryId( GenerateReportAction.ALL_REPOSITORIES ); + ServletRunner sr = new ServletRunner(); + ServletUnitClient sc = sr.newClient(); + + action.setServletRequest( sc.newInvocation( URL ).getRequest() ); + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.execute(); + assertSuccessResult( result ); + + RepositoryProblemReport problemReport1 = createProblemReport( problem1 ); + RepositoryProblemReport problemReport2 = createProblemReport( problem2 ); + assertEquals( Arrays.asList( INTERNAL, SNAPSHOTS ), + new ArrayList( action.getRepositoriesMap().keySet() ) ); + assertEquals( Arrays.asList( problemReport1 ), action.getRepositoriesMap().get( INTERNAL ) ); + assertEquals( Arrays.asList( problemReport2 ), action.getRepositoriesMap().get( SNAPSHOTS ) ); + + repositoryProblemDAOControl.verify(); + } + + public void testHealthReportSingleRepoByCorrectGroupId() + throws Exception + { + RepositoryProblem problem1 = createProblem( GROUP_ID, "artifactId", INTERNAL ); + RepositoryProblem problem2 = createProblem( GROUP_ID, "artifactId-2", INTERNAL ); + repositoryProblemDAOControl.expectAndReturn( repositoryProblemDAO.queryRepositoryProblems( + new RepositoryProblemConstraint( new int[]{0, 101}, GROUP_ID, INTERNAL ) ), + Arrays.asList( problem1, problem2 ) ); + repositoryProblemDAOControl.replay(); + + action.setGroupId( GROUP_ID ); + action.setRepositoryId( INTERNAL ); + ServletRunner sr = new ServletRunner(); + ServletUnitClient sc = sr.newClient(); + + action.setServletRequest( sc.newInvocation( URL ).getRequest() ); + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.execute(); + assertSuccessResult( result ); + + RepositoryProblemReport problemReport1 = createProblemReport( problem1 ); + RepositoryProblemReport problemReport2 = createProblemReport( problem2 ); + assertEquals( Collections.singleton( INTERNAL ), action.getRepositoriesMap().keySet() ); + assertEquals( Arrays.asList( problemReport1, problemReport2 ), action.getRepositoriesMap().get( INTERNAL ) ); + + repositoryProblemDAOControl.verify(); + } + + public void testHealthReportSingleRepoByCorrectGroupIdAllRepositories() + throws Exception + { + RepositoryProblem problem1 = createProblem( GROUP_ID, "artifactId", INTERNAL ); + RepositoryProblem problem2 = createProblem( GROUP_ID, "artifactId-2", SNAPSHOTS ); + repositoryProblemDAOControl.expectAndReturn( repositoryProblemDAO.queryRepositoryProblems( + new RepositoryProblemByGroupIdConstraint( new int[]{0, 101}, GROUP_ID ) ), + Arrays.asList( problem1, problem2 ) ); + repositoryProblemDAOControl.replay(); + + action.setGroupId( GROUP_ID ); + action.setRepositoryId( GenerateReportAction.ALL_REPOSITORIES ); + ServletRunner sr = new ServletRunner(); + ServletUnitClient sc = sr.newClient(); + + action.setServletRequest( sc.newInvocation( URL ).getRequest() ); + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.execute(); + assertSuccessResult( result ); + + RepositoryProblemReport problemReport1 = createProblemReport( problem1 ); + RepositoryProblemReport problemReport2 = createProblemReport( problem2 ); + assertEquals( Arrays.asList( INTERNAL, SNAPSHOTS ), + new ArrayList( action.getRepositoriesMap().keySet() ) ); + assertEquals( Arrays.asList( problemReport1 ), action.getRepositoriesMap().get( INTERNAL ) ); + assertEquals( Arrays.asList( problemReport2 ), action.getRepositoriesMap().get( SNAPSHOTS ) ); + + repositoryProblemDAOControl.verify(); + } + + public void testHealthReportSingleRepoByIncorrectGroupId() + throws Exception + { + repositoryProblemDAOControl.expectAndReturn( repositoryProblemDAO.queryRepositoryProblems( + new RepositoryProblemConstraint( new int[]{0, 101}, "not.it", INTERNAL ) ), + Collections.emptyList() ); + repositoryProblemDAOControl.replay(); + + action.setGroupId( "not.it" ); + action.setRepositoryId( INTERNAL ); + ServletRunner sr = new ServletRunner(); + ServletUnitClient sc = sr.newClient(); + + action.setServletRequest( sc.newInvocation( URL ).getRequest() ); + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.execute(); + assertEquals( GenerateReportAction.BLANK, result ); + assertFalse( action.hasActionErrors() ); + assertFalse( action.hasFieldErrors() ); + + repositoryProblemDAOControl.verify(); + } + ++ private void assertMultiRepoCsvResult() ++ throws IOException ++ { ++// assertEquals( ++// "Repository,Total File Count,Total Size,Artifact Count,Group Count,Project Count,Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" + ++// "snapshots,0,0,0,0,0,1,0,1,1,0,0\n" + "internal,0,0,0,0,0,1,0,1,1,0,0\n", ++ assertEquals( ++ "Repository,Total File Count,Total Size,Artifact Count,Group Count,Project Count,Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" + ++ "snapshots,0,0,0,0,0\n" + "internal,0,0,0,0,0\n", IOUtils.toString( action.getInputStream() ) ); ++ } ++ + private RepositoryProblemReport createProblemReport( RepositoryProblem problem ) + { + RepositoryProblemReport problemReport = new RepositoryProblemReport( problem ); + problemReport.setGroupURL( "http://localhost/browse/" + problem.getGroupId() ); + problemReport.setArtifactURL( problemReport.getGroupURL() + "/" + problem.getArtifactId() ); + return problemReport; + } + + private RepositoryProblem createProblem( String groupId, String artifactId, String repoId ) + { + RepositoryProblem problem = new RepositoryProblem(); + problem.setRepositoryId( repoId ); + problem.setGroupId( groupId ); + problem.setArtifactId( artifactId ); + return problem; + } + + public void testHealthReportNoRepositoryId() + throws Exception + { + prepareAction( Collections.emptyList(), Arrays.asList( SNAPSHOTS, INTERNAL ) ); + + String result = action.execute(); + assertEquals( Action.INPUT, result ); + assertTrue( action.hasFieldErrors() ); + } + + private void assertSuccessResult( String result ) + { + assertEquals( Action.SUCCESS, result ); + assertFalse( action.hasActionErrors() ); + assertFalse( action.hasFieldErrors() ); + } ++ ++ private RepositoryStatistics createDefaultStats() ++ { ++ return createStats( new Date() ); ++ } ++ ++ private RepositoryStatistics createStats( Date date ) ++ { ++ RepositoryStatistics stats = new RepositoryStatistics(); ++ stats.setScanStartTime( date ); ++ return stats; ++ } + } diff --cc archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/action/reports/GenerateReportActionTest.xml index 000000000,dc68e12af..44882614c mode 000000,100644..100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/action/reports/GenerateReportActionTest.xml +++ b/archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/action/reports/GenerateReportActionTest.xml @@@ -1,0 -1,49 +1,39 @@@ + + + + + + org.apache.maven.archiva.database.ArchivaDAO + jdo + org.apache.maven.archiva.web.action.admin.repositories.ArchivaDAOStub + + + org.apache.maven.archiva.database.ArtifactDAO + jdo + - - org.apache.maven.archiva.database.RepositoryContentStatisticsDAO - jdo - + + + + org.apache.maven.archiva.database.ArtifactDAO + jdo + org.apache.maven.archiva.web.action.admin.repositories.ArtifactDAOStub + - - org.apache.maven.archiva.database.RepositoryContentStatisticsDAO - jdo - org.apache.maven.archiva.web.action.admin.repositories.RepositoryContentStatisticsDAOStub - - + + diff --cc archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/DefaultRepositoryStatisticsManager.java index 9fc14104f,000000000..b47e1166f mode 100644,000000..100644 --- a/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/DefaultRepositoryStatisticsManager.java +++ b/archiva-modules/plugins/repository-statistics/src/main/java/org/apache/archiva/metadata/repository/stats/DefaultRepositoryStatisticsManager.java @@@ -1,126 -1,0 +1,127 @@@ +package org.apache.archiva.metadata.repository.stats; + +/* + * 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. + */ + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.apache.archiva.metadata.repository.MetadataRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @plexus.component role="org.apache.archiva.metadata.repository.stats.RepositoryStatisticsManager" role-hint="default" + */ +public class DefaultRepositoryStatisticsManager + implements RepositoryStatisticsManager +{ + private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryStatisticsManager.class ); + + /** + * @plexus.requirement + */ + private MetadataRepository metadataRepository; + + static final DateFormat SCAN_TIMESTAMP = new SimpleDateFormat( "yyyyMMdd.HHmmss.SSS" ); + + public RepositoryStatistics getLastStatistics( String repositoryId ) + { + // TODO: consider a more efficient implementation that directly gets the last one from the content repository + List scans = metadataRepository.getMetadataFacets( repositoryId, RepositoryStatistics.FACET_ID ); + Collections.sort( scans ); + if ( !scans.isEmpty() ) + { + String name = scans.get( scans.size() - 1 ); + return (RepositoryStatistics) metadataRepository.getMetadataFacet( repositoryId, + RepositoryStatistics.FACET_ID, name ); + } + else + { + return null; + } + } + + public void addStatisticsAfterScan( String repositoryId, RepositoryStatistics repositoryStatistics ) + { + // In the future, instead of being tied to a scan we might want to record information in the fly based on + // events that are occurring. Even without these totals we could query much of the information on demand based + // on information from the metadata content repository. In the mean time, we lock information in at scan time. + // Note that if new types are later discoverable due to a code change or new plugin, historical stats will not + // be updated and the repository will need to be rescanned. + + // TODO, populate these and also a count per artifact type + // populate total artifact count from content repository +// repositoryStatistics.setTotalArtifactCount( ); + // populate total size from content repository +// repositoryStatistics.setTotalArtifactFileSize( ); + // populate total group count from content repository +// repositoryStatistics.setTotalGroupCount( ); + // populate total project count from content repository +// repositoryStatistics.setTotalProjectCount( ); + + metadataRepository.addMetadataFacet( repositoryId, RepositoryStatistics.FACET_ID, + SCAN_TIMESTAMP.format( repositoryStatistics.getScanStartTime() ), + repositoryStatistics ); + } + + public void deleteStatistics( String repositoryId ) + { + metadataRepository.removeMetadataFacets( repositoryId, RepositoryStatistics.FACET_ID ); + } + + public List getStatisticsInRange( String repositoryId, Date startTime, Date endTime ) + { + List results = new ArrayList(); + List list = metadataRepository.getMetadataFacets( repositoryId, RepositoryStatistics.FACET_ID ); + Collections.sort( list, Collections.reverseOrder() ); + for ( String name : list ) + { + try + { + Date date = SCAN_TIMESTAMP.parse( name ); - if ( !date.before( startTime ) && !date.after( endTime ) ) ++ if ( ( startTime == null || !date.before( startTime ) ) && ++ ( endTime == null || !date.after( endTime ) ) ) + { + RepositoryStatistics stats = + (RepositoryStatistics) metadataRepository.getMetadataFacet( repositoryId, + RepositoryStatistics.FACET_ID, + name ); + results.add( stats ); + } + } + catch ( ParseException e ) + { + log.error( "Invalid scan result found in the metadata repository: " + e.getMessage() ); + // continue and ignore this one + } + } + return results; + } + + public void setMetadataRepository( MetadataRepository metadataRepository ) + { + this.metadataRepository = metadataRepository; + } +}