]> source.dussan.org Git - archiva.git/blob
94c9f5eead6e482fa9bda86f90130bd41c23beb8
[archiva.git] /
1 package org.apache.maven.archiva.web.action.reports;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import com.opensymphony.xwork2.Preparable;
23
24 import org.apache.commons.io.IOUtils;
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.commons.lang.time.DateUtils;
27 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
28 import org.apache.maven.archiva.database.ArchivaDAO;
29 import org.apache.maven.archiva.database.ArchivaDatabaseException;
30 import org.apache.maven.archiva.database.Constraint;
31 import org.apache.maven.archiva.database.ObjectNotFoundException;
32 import org.apache.maven.archiva.database.RepositoryContentStatisticsDAO;
33 import org.apache.maven.archiva.database.constraints.RangeConstraint;
34 import org.apache.maven.archiva.database.constraints.RepositoryContentStatisticsByRepositoryConstraint;
35 import org.apache.maven.archiva.database.constraints.RepositoryProblemByGroupIdConstraint;
36 import org.apache.maven.archiva.database.constraints.RepositoryProblemByRepositoryIdConstraint;
37 import org.apache.maven.archiva.database.constraints.RepositoryProblemConstraint;
38 import org.apache.maven.archiva.database.constraints.UniqueFieldConstraint;
39 import org.apache.maven.archiva.model.RepositoryContentStatistics;
40 import org.apache.maven.archiva.model.RepositoryProblem;
41 import org.apache.maven.archiva.model.RepositoryProblemReport;
42 import org.apache.maven.archiva.reporting.ArchivaReportException;
43 import org.apache.maven.archiva.reporting.DataLimits;
44 import org.apache.maven.archiva.reporting.RepositoryStatistics;
45 import org.apache.maven.archiva.reporting.RepositoryStatisticsReportGenerator;
46 import org.apache.maven.archiva.security.ArchivaRoleConstants;
47 import org.codehaus.plexus.redback.rbac.Resource;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import javax.servlet.http.HttpServletRequest;
52
53 import java.io.ByteArrayInputStream;
54 import java.io.IOException;
55 import java.io.InputStream;
56 import java.io.StringReader;
57 import java.text.ParseException;
58 import java.util.ArrayList;
59 import java.util.Calendar;
60 import java.util.Collection;
61 import java.util.Date;
62 import java.util.List;
63 import java.util.Map;
64 import java.util.TreeMap;
65 import org.apache.maven.archiva.web.action.PlexusActionSupport;
66 import org.apache.struts2.interceptor.ServletRequestAware;
67 import org.codehaus.redback.integration.interceptor.SecureAction;
68 import org.codehaus.redback.integration.interceptor.SecureActionBundle;
69 import org.codehaus.redback.integration.interceptor.SecureActionException;
70
71 /**
72  * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="generateReport" instantiation-strategy="per-lookup"
73  */
74 public class GenerateReportAction
75     extends PlexusActionSupport
76     implements SecureAction, ServletRequestAware, Preparable
77 {
78     private Logger log = LoggerFactory.getLogger( GenerateReportAction.class );
79     
80     /**
81      * @plexus.requirement role-hint="jdo"
82      */
83     protected ArchivaDAO dao;
84     
85     /**
86      * @plexus.requirement
87      */
88     private ArchivaConfiguration archivaConfiguration;
89
90     protected Constraint constraint;
91
92     protected HttpServletRequest request;
93
94     protected List<RepositoryProblemReport> reports = new ArrayList<RepositoryProblemReport>();
95
96     protected String groupId;
97
98     protected String repositoryId;
99
100     protected String prev;
101
102     protected String next;
103
104     protected int[] range = new int[2];
105
106     protected int page = 1;
107
108     protected int rowCount = 100;
109
110     protected boolean isLastPage;
111
112     public static final String BLANK = "blank";
113
114     public static final String BASIC = "basic";
115
116     private static Boolean jasperPresent;
117
118     private Collection<String> repositoryIds;
119
120     public static final String ALL_REPOSITORIES = "All Repositories";
121     
122     protected Map<String, List<RepositoryProblemReport>> repositoriesMap = 
123                 new TreeMap<String, List<RepositoryProblemReport>>();
124     
125     // for statistics report
126     /**
127      * @plexus.requirement role-hint="simple"
128      */
129     private RepositoryStatisticsReportGenerator generator;
130     
131     private List<String> selectedRepositories = new ArrayList<String>();
132     
133     private List<String> availableRepositories;  
134     
135     private String startDate;
136     
137     private String endDate;
138     
139     private int reposSize;
140     
141     private String selectedRepo;
142     
143     private List<RepositoryStatistics> repositoryStatistics = new ArrayList<RepositoryStatistics>();
144     
145     private DataLimits limits = new DataLimits();
146     
147     private String[] datePatterns = new String[] { "MM/dd/yy", "MM/dd/yyyy", "MMMMM/dd/yyyy", "MMMMM/dd/yy", 
148         "dd MMMMM yyyy", "dd/MM/yy", "dd/MM/yyyy", "yyyy/MM/dd", "yyyy-MM-dd", "yyyy-dd-MM", "MM-dd-yyyy",
149         "MM-dd-yy" };
150     
151     public static final String SEND_FILE = "send-file";
152     
153     private InputStream inputStream;
154     
155     public void prepare()
156     {
157         repositoryIds = new ArrayList<String>();
158         repositoryIds.add( ALL_REPOSITORIES ); // comes first to be first in the list
159         repositoryIds.addAll(
160             dao.query( new UniqueFieldConstraint( RepositoryProblem.class.getName(), "repositoryId" ) ) );
161         
162         availableRepositories = new ArrayList<String>();
163      
164         // remove selected repositories in the option for the statistics report
165         availableRepositories.addAll( archivaConfiguration.getConfiguration().getManagedRepositoriesAsMap().keySet() );        
166         for( String repo : selectedRepositories )
167         {
168             if( availableRepositories.contains( repo ) )
169             {
170                 availableRepositories.remove( repo );
171             }
172         }
173     }
174
175     public Collection<String> getRepositoryIds()
176     {
177         return repositoryIds;
178     }
179
180     /**
181      * Generate the statistics report.
182      * 
183      * check whether single repo report or comparison report
184      * 1. if it is a single repository, get all the statistics for the repository on the specified date
185      *    - if no date is specified, get only the latest 
186      *          (total page = 1 --> no pagination since only the most recent stats will be displayed)
187      *    - otherwise, get everything within the date range (total pages = repo stats / rows per page)
188      *       - required params: repository, startDate, endDate
189      *       
190      * 2. if multiple repositories, get the latest statistics on each repository on the specified date
191      *    - if no date is specified, use the current date endDate
192      *       - required params: repositories, endDate
193      *    - total pages = repositories / rows per page
194      * 
195      * @return
196      */
197     public String generateStatistics()
198     {   
199         if( rowCount < 10 )
200         {
201             addFieldError( "rowCount", "Row count must be larger than 10." );
202             return INPUT;
203         }
204         reposSize = selectedRepositories.size();                
205         
206         try
207         {
208             RepositoryContentStatisticsDAO repoContentStatsDao = dao.getRepositoryContentStatisticsDAO();
209             Date startDateInDF = null;
210             Date endDateInDF = null;
211             
212             if( selectedRepositories.size() > 1 )
213             {
214                 limits.setTotalCount( selectedRepositories.size() );            
215                 limits.setCurrentPage( 1 );
216                 limits.setPerPageCount( 1 );
217                 limits.setCountOfPages( 1 );
218                 
219                 try
220                 {
221                         startDateInDF = getStartDateInDateFormat();                     
222                         endDateInDF = getEndDateInDateFormat();
223                 }
224                 catch ( ParseException e )
225                 {
226                         addActionError( "Error parsing date(s)." );
227                         return ERROR;
228                 }
229                 
230                 if( startDateInDF.after( endDateInDF ) )
231                 {
232                     addFieldError( "startDate", "Start Date must be earlier than the End Date" );
233                     return INPUT;
234                 }
235                 
236                 // multiple repos
237                 generateReportForMultipleRepos(repoContentStatsDao, startDateInDF, endDateInDF, true);                
238             }
239             else if ( selectedRepositories.size() == 1 )
240             {   
241                 limits.setCurrentPage( getPage() );
242                 limits.setPerPageCount( getRowCount() );
243                 
244                 selectedRepo = selectedRepositories.get( 0 );
245                 try
246                 {        
247                         startDateInDF = getStartDateInDateFormat();                     
248                         endDateInDF = getEndDateInDateFormat();
249                          
250                         if( startDateInDF.after( endDateInDF ) )
251                     {
252                             addFieldError( "startDate", "Start Date must be earlier than the End Date" );
253                             return INPUT;
254                     }
255                         
256                     List<RepositoryContentStatistics> contentStats = repoContentStatsDao.queryRepositoryContentStatistics( 
257                            new RepositoryContentStatisticsByRepositoryConstraint( selectedRepo, startDateInDF, endDateInDF ) );
258                     
259                     if( contentStats == null || contentStats.isEmpty() )
260                     {   
261                         addActionError( "No statistics available for repository. Repository might not have been scanned." );
262                         return ERROR;
263                     }   
264                     
265                     limits.setTotalCount( contentStats.size() );                    
266                     int extraPage = ( limits.getTotalCount() % limits.getPerPageCount() ) != 0 ? 1 : 0;
267                     int totalPages = ( limits.getTotalCount() / limits.getPerPageCount() ) + extraPage;                    
268                     limits.setCountOfPages( totalPages );
269                     
270                     repositoryStatistics = generator.generateReport( contentStats, selectedRepo, startDateInDF, endDateInDF, limits );
271                 }
272                 catch ( ObjectNotFoundException oe )
273                 {
274                     addActionError( oe.getMessage() );
275                     return ERROR;
276                 }
277                 catch ( ArchivaDatabaseException de )
278                 {
279                     addActionError( de.getMessage() );
280                     return ERROR;
281                 }
282                 catch ( ParseException pe )
283                 {
284                         addActionError( pe.getMessage() );
285                         return ERROR;
286                 }
287             }
288             else
289             {
290                 addFieldError( "availableRepositories", "Please select a repository (or repositories) from the list." );
291                 return INPUT;
292             } 
293             
294             if( repositoryStatistics.isEmpty() )
295             {
296                 return BLANK;
297             }            
298         }
299         catch ( ArchivaReportException e )
300         {
301             addActionError( "Error encountered while generating report :: " + e.getMessage() );
302             return ERROR;
303         }
304         
305         return SUCCESS;
306     }
307         
308     /**
309      * Export report to CSV.
310      * 
311      * @return
312      */
313     public String downloadStatisticsReport()
314     {   
315         try
316         {
317                 Date startDateInDF = null;
318             Date endDateInDF = null;
319             
320             selectedRepositories = parseSelectedRepositories();
321             repositoryStatistics = new ArrayList<RepositoryStatistics>();
322             
323             RepositoryContentStatisticsDAO repoContentStatsDao = dao.getRepositoryContentStatisticsDAO();            
324             if( selectedRepositories.size() > 1 )
325             {   
326                 try
327                 {        
328                         startDateInDF = getStartDateInDateFormat();                     
329                         endDateInDF = getEndDateInDateFormat();
330                 }
331                 catch ( ParseException e )
332                 {
333                         addActionError( "Error parsing date(s)." );
334                         return ERROR;
335                 }
336                 
337                 if( startDateInDF.after( endDateInDF ) )
338                 {
339                     addFieldError( "startDate", "Start Date must be earlier than the End Date" );
340                     return INPUT;
341                 }
342                 
343              // multiple repos
344                 generateReportForMultipleRepos( repoContentStatsDao, startDateInDF, endDateInDF, false );
345             }
346             else if ( selectedRepositories.size() == 1 )
347             {   
348                 selectedRepo = selectedRepositories.get( 0 );
349                 try
350                 {                 
351                         startDateInDF = getStartDateInDateFormat();
352                         endDateInDF = getEndDateInDateFormat();
353                         
354                         if( startDateInDF.after( endDateInDF ) )
355                     {
356                             addFieldError( "startDate", "Start Date must be earlier than the End Date" );
357                             return INPUT;
358                     }
359                         
360                     List<RepositoryContentStatistics> contentStats = repoContentStatsDao.queryRepositoryContentStatistics( 
361                            new RepositoryContentStatisticsByRepositoryConstraint( selectedRepo, startDateInDF, endDateInDF ) );
362                                         
363                     if( contentStats == null || contentStats.isEmpty() )
364                     {   
365                         addActionError( "No statistics available for repository. Repository might not have been scanned." );
366                         return ERROR;
367                     }   
368                     
369                     repositoryStatistics = generator.generateReport( contentStats, selectedRepo, startDateInDF, endDateInDF, false );                    
370                 }
371                 catch ( ObjectNotFoundException oe )
372                 {
373                     addActionError( oe.getMessage() );
374                     return ERROR;
375                 }
376                 catch ( ArchivaDatabaseException de )
377                 {
378                     addActionError( de.getMessage() );
379                     return ERROR;
380                 }
381                 catch ( ParseException pe )
382                 {
383                         addActionError( pe.getMessage() );
384                         return ERROR;
385                 }
386             }
387             else
388             {
389                 addFieldError( "availableRepositories", "Please select a repository (or repositories) from the list." );
390                 return INPUT;
391             } 
392             
393             if( repositoryStatistics.isEmpty() )
394             {
395                 return BLANK;
396             }            
397         }
398         catch ( ArchivaReportException e )
399         {
400             addActionError( "Error encountered while generating report :: " + e.getMessage() );
401             return ERROR;
402         }    
403         
404         // write output stream depending on single or comparison report              
405         StringBuffer input = getInput();        
406         StringReader reader = new StringReader( input.toString() );
407         
408         try
409         {
410                 inputStream = new ByteArrayInputStream( IOUtils.toByteArray( reader ) );
411         }
412         catch ( IOException i )
413         {       
414                 addActionError( "Error occurred while generating CSV file." );
415                 return ERROR;
416         }
417         
418         return SEND_FILE;
419     }
420     
421     // hack for parsing the struts list passed as param in <s:url ../>
422     private List<String> parseSelectedRepositories()
423     {           
424         List<String> pasedSelectedRepos = new ArrayList<String>();
425      
426         for( String repo : selectedRepositories )
427         {   
428             String[] tokens = StringUtils.split( repo, ',' );
429             if( tokens.length > 1 )
430             {
431                 for( int i = 0; i < tokens.length; i++ )
432                 {   
433                     pasedSelectedRepos.add( StringUtils.remove( StringUtils.remove( tokens[i], '[' ), ']' ).trim() );
434                 }
435             }
436             else
437             {
438                 pasedSelectedRepos.add( StringUtils.remove( StringUtils.remove( repo, '[' ), ']' ).trim() );
439             }
440         }
441         return pasedSelectedRepos;
442     }
443
444     private void generateReportForMultipleRepos( RepositoryContentStatisticsDAO repoContentStatsDao,
445                                                  Date startDateInDF, Date endDateInDF, boolean useLimits )
446         throws ArchivaReportException
447     {   
448         for ( String repo : selectedRepositories )
449         {   
450             try
451             {                
452                 List contentStats = repoContentStatsDao.queryRepositoryContentStatistics( 
453                          new RepositoryContentStatisticsByRepositoryConstraint( repo, startDateInDF, endDateInDF ) );
454
455                 if ( contentStats == null || contentStats.isEmpty() )
456                 {
457                     log.info( "No statistics available for repository '" + repo + "'." );
458                     // TODO set repo's stats to 0
459                     continue;
460                 }
461                 
462                 if( useLimits )
463                 {
464                     repositoryStatistics.addAll( generator.generateReport( contentStats, repo, startDateInDF, endDateInDF,
465                                                                        limits ) );
466                 }
467                 else
468                 {
469                     repositoryStatistics.addAll( generator.generateReport( contentStats, repo, startDateInDF, endDateInDF, true ) );
470                 }
471             }
472             catch ( ObjectNotFoundException oe )
473             {
474                 log.error( "No statistics available for repository '" + repo + "'." );
475                 // TODO set repo's stats to 0
476             }
477             catch ( ArchivaDatabaseException ae )
478             {
479                 log.error( "Error encountered while querying statistics of repository '" + repo + "'." );
480                 // TODO set repo's stats to 0
481             }
482         }
483     }
484
485     private Date getStartDateInDateFormat()
486         throws ParseException
487     {
488         Date startDateInDF;
489         if ( startDate == null || "".equals( startDate ) )
490         {
491             startDateInDF = getDefaultStartDate();
492         }
493         else
494         {
495             startDateInDF = DateUtils.parseDate( startDate, datePatterns );
496         }
497         return startDateInDF;
498     }
499
500     private Date getEndDateInDateFormat()
501         throws ParseException
502     {
503         Date endDateInDF;
504         if ( endDate == null || "".equals( endDate ) )
505         {
506             endDateInDF = getDefaultEndDate();
507         }
508         else
509         {
510             endDateInDF = DateUtils.parseDate( endDate, datePatterns );
511         }
512         
513         return endDateInDF;
514     }
515     
516     private StringBuffer getInput()
517     {
518         StringBuffer input = null;
519         
520         if( selectedRepositories.size() == 1 )
521         {               
522                 input = new StringBuffer( "Date of Scan,Total File Count,Total Size,Artifact Count,Group Count,Project Count," +
523                                 "Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" );
524                 
525                 for( RepositoryStatistics stats : repositoryStatistics )
526                 {
527                         input.append( stats.getDateOfScan() ).append( "," );
528                         input.append( stats.getFileCount() ).append( "," );
529                         input.append( stats.getTotalSize() ).append( "," );
530                         input.append( stats.getArtifactCount() ).append( "," );
531                         input.append( stats.getGroupCount() ).append( "," );
532                         input.append( stats.getProjectCount() ).append( "," );
533                         input.append( stats.getPluginCount() ).append( "," );
534                         input.append( stats.getArchetypeCount() ).append( "," );
535                         input.append( stats.getJarCount() ).append( "," );
536                         input.append( stats.getWarCount() ).append( "," );
537                         input.append( stats.getDeploymentCount() ).append( "," );
538                         input.append( stats.getDownloadCount() ).append( "\n" );
539                 }               
540         }            
541         else if( selectedRepositories.size() > 1 )
542         {
543                 input = new StringBuffer( "Repository,Total File Count,Total Size,Artifact Count,Group Count,Project Count," +
544                                         "Plugins,Archetypes,Jars,Wars,Deployments,Downloads\n" );
545                         
546                         for( RepositoryStatistics stats : repositoryStatistics )
547                         {
548                                 input.append( stats.getRepositoryId() ).append( "," );
549                                 input.append( stats.getFileCount() ).append( "," );
550                                 input.append( stats.getTotalSize() ).append( "," );
551                                 input.append( stats.getArtifactCount() ).append( "," );
552                                 input.append( stats.getGroupCount() ).append( "," );
553                                 input.append( stats.getProjectCount() ).append( "," );
554                                 input.append( stats.getPluginCount() ).append( "," );
555                                 input.append( stats.getArchetypeCount() ).append( "," );
556                                 input.append( stats.getJarCount() ).append( "," );
557                                 input.append( stats.getWarCount() ).append( "," );
558                                 input.append( stats.getDeploymentCount() ).append( "," );
559                                 input.append( stats.getDownloadCount() ).append( "\n" );
560                         }
561         }
562         
563         return input;
564     }
565     
566     private Date getDefaultStartDate()
567     {
568         Calendar cal = Calendar.getInstance();
569         cal.clear();
570         cal.set( 1900, 1, 1, 0, 0, 0 );
571         
572         return cal.getTime();
573     }
574     
575     private Date getDefaultEndDate()
576     {
577         return Calendar.getInstance().getTime();
578     }
579     
580     public String execute()
581         throws Exception
582     {   
583         if( repositoryId == null )
584         {
585             addFieldError( "repositoryId", "You must provide a repository id.");            
586             return INPUT;
587         }
588         
589         if( rowCount < 10 )
590         {
591             addFieldError( "rowCount", "Row count must be larger than 10." );
592             return INPUT;
593         }
594         
595         List<RepositoryProblem> problemArtifacts =
596             dao.getRepositoryProblemDAO().queryRepositoryProblems( configureConstraint() );
597
598         String contextPath =
599             request.getRequestURL().substring( 0, request.getRequestURL().indexOf( request.getRequestURI() ) );
600         RepositoryProblem problemArtifact;
601         RepositoryProblemReport problemArtifactReport;
602         for ( int i = 0; i < problemArtifacts.size(); i++ )
603         {
604             problemArtifact = (RepositoryProblem) problemArtifacts.get( i );
605             problemArtifactReport = new RepositoryProblemReport( problemArtifact );
606
607             problemArtifactReport.setGroupURL( contextPath + "/browse/" + problemArtifact.getGroupId() );
608             problemArtifactReport.setArtifactURL(
609                 contextPath + "/browse/" + problemArtifact.getGroupId() + "/" + problemArtifact.getArtifactId() );
610
611             addToList( problemArtifactReport );
612             
613             // retained the reports list because this is the datasource for the jasper report            
614             reports.add( problemArtifactReport );
615         }
616         
617         if ( reports.size() <= rowCount )
618         {
619             isLastPage = true;
620         }
621         else
622         {
623             reports.remove( rowCount );
624         }
625
626         prev = request.getRequestURL() + "?page=" + ( page - 1 ) + "&rowCount=" + rowCount + "&groupId=" + groupId +
627             "&repositoryId=" + repositoryId;
628         next = request.getRequestURL() + "?page=" + ( page + 1 ) + "&rowCount=" + rowCount + "&groupId=" + groupId +
629             "&repositoryId=" + repositoryId;
630
631         if ( reports.size() == 0 && page == 1 )
632         {
633             return BLANK;
634         }
635         else if ( isJasperPresent() )
636         {
637             return "jasper";
638         }
639         else
640         {
641             return SUCCESS;
642         }
643     }
644     
645     private static boolean isJasperPresent()
646     {
647         if ( jasperPresent == null )
648         {
649             try
650             {
651                 Class.forName( "net.sf.jasperreports.engine.JRExporterParameter" );
652                 jasperPresent = Boolean.TRUE;
653             }
654             catch ( NoClassDefFoundError e )
655             {
656                 jasperPresent = Boolean.FALSE;
657             }
658             catch ( ClassNotFoundException e )
659             {
660                 jasperPresent = Boolean.FALSE;
661             }
662         }
663         return jasperPresent.booleanValue();
664     }
665
666     private Constraint configureConstraint()
667     {
668         Constraint constraint;
669
670         range[0] = ( page - 1 ) * rowCount;
671         range[1] = ( page * rowCount ) + 1; // Add 1 to check if it's the last page or not.
672
673         if ( groupId != null && ( !groupId.equals( "" ) ) )
674         {
675             if ( repositoryId != null && ( !repositoryId.equals( "" ) && !repositoryId.equals( ALL_REPOSITORIES ) ) )
676             {
677                 constraint = new RepositoryProblemConstraint( range, groupId, repositoryId );
678             }
679             else
680             {
681                 constraint = new RepositoryProblemByGroupIdConstraint( range, groupId );
682             }
683         }
684         else if ( repositoryId != null && ( !repositoryId.equals( "" ) && !repositoryId.equals( ALL_REPOSITORIES ) ) )
685         {
686             constraint = new RepositoryProblemByRepositoryIdConstraint( range, repositoryId );
687         }
688         else
689         {
690             constraint = new RangeConstraint( range, "repositoryId" );
691         }
692
693         return constraint;
694     }
695     
696     public SecureActionBundle getSecureActionBundle()
697         throws SecureActionException
698     {
699         SecureActionBundle bundle = new SecureActionBundle();
700     
701         bundle.setRequiresAuthentication( true );
702         bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL );
703     
704         return bundle;
705     }
706     
707     private void addToList( RepositoryProblemReport repoProblemReport )
708     {
709         List<RepositoryProblemReport> problemsList = null;
710         
711         if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) )
712         {
713             problemsList = ( List<RepositoryProblemReport> ) repositoriesMap.get( repoProblemReport.getRepositoryId() );
714         }
715         else
716         {
717             problemsList = new ArrayList<RepositoryProblemReport>();
718             repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList );
719         }
720         
721         problemsList.add( repoProblemReport );
722     }
723
724     public void setServletRequest( HttpServletRequest request )
725     {
726         this.request = request;
727     }
728
729     public List<RepositoryProblemReport> getReports()
730     {
731         return reports;
732     }
733
734     public String getGroupId()
735     {
736         return groupId;
737     }
738
739     public void setGroupId( String groupId )
740     {
741         this.groupId = groupId;
742     }
743
744     public String getRepositoryId()
745     {
746         return repositoryId;
747     }
748
749     public void setRepositoryId( String repositoryId )
750     {
751         this.repositoryId = repositoryId;
752     }
753
754     public String getPrev()
755     {
756         return prev;
757     }
758
759     public String getNext()
760     {
761         return next;
762     }
763
764     public int getPage()
765     {
766         return page;
767     }
768
769     public void setPage( int page )
770     {
771         this.page = page;
772     }
773
774     public int getRowCount()
775     {
776         return rowCount;
777     }
778
779     public void setRowCount( int rowCount )
780     {
781         this.rowCount = rowCount;
782     }
783
784     public boolean getIsLastPage()
785     {
786         return isLastPage;
787     }
788
789     public void setRepositoriesMap( Map<String, List<RepositoryProblemReport>> repositoriesMap )
790     {
791         this.repositoriesMap = repositoriesMap;
792     }
793     
794     public Map<String, List<RepositoryProblemReport>> getRepositoriesMap()
795     {
796         return repositoriesMap;
797     }
798     
799     public List<String> getSelectedRepositories()
800     {
801         return selectedRepositories;
802     }
803
804     public void setSelectedRepositories( List<String> selectedRepositories )
805     {
806         this.selectedRepositories = selectedRepositories;
807     }
808
809     public List<String> getAvailableRepositories()
810     {
811         return availableRepositories;
812     }
813
814     public void setAvailableRepositories( List<String> availableRepositories )
815     {
816         this.availableRepositories = availableRepositories;
817     }
818
819     public String getStartDate()
820     {
821         return startDate;
822     }
823
824     public void setStartDate( String startDate )
825     {
826         this.startDate = startDate;
827     }
828
829     public String getEndDate()
830     {
831         return endDate;
832     }
833
834     public void setEndDate( String endDate )
835     {
836         this.endDate = endDate;
837     }
838
839     public List<RepositoryStatistics> getRepositoryStatistics()
840     {
841         return repositoryStatistics;
842     }
843
844     public void setRepositoryStatistics( List<RepositoryStatistics> repositoryStatistics )
845     {
846         this.repositoryStatistics = repositoryStatistics;
847     }
848     
849     public int getReposSize()
850     {
851         return reposSize;
852     }
853
854     public void setReposSize( int reposSize )
855     {
856         this.reposSize = reposSize;
857     }
858
859     public String getSelectedRepo()
860     {
861         return selectedRepo;
862     }
863
864     public void setSelectedRepo( String selectedRepo )
865     {
866         this.selectedRepo = selectedRepo;
867     }
868
869     public DataLimits getLimits()
870     {
871         return limits;
872     }
873
874     public void setLimits( DataLimits limits )
875     {
876         this.limits = limits;
877     }
878     
879     public InputStream getInputStream()
880     {
881         return inputStream;
882     }
883 }