]> source.dussan.org Git - archiva.git/blob
f254422dff010fad48eab8882d76f65dd3f8e30c
[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.webwork.interceptor.ServletRequestAware;
23 import com.opensymphony.xwork.Preparable;
24
25 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
26 import org.apache.maven.archiva.database.ArchivaDAO;
27 import org.apache.maven.archiva.database.ArchivaDatabaseException;
28 import org.apache.maven.archiva.database.Constraint;
29 import org.apache.maven.archiva.database.ObjectNotFoundException;
30 import org.apache.maven.archiva.database.RepositoryContentStatisticsDAO;
31 import org.apache.maven.archiva.database.constraints.RangeConstraint;
32 import org.apache.maven.archiva.database.constraints.RepositoryContentStatisticsByRepositoryConstraint;
33 import org.apache.maven.archiva.database.constraints.RepositoryProblemByGroupIdConstraint;
34 import org.apache.maven.archiva.database.constraints.RepositoryProblemByRepositoryIdConstraint;
35 import org.apache.maven.archiva.database.constraints.RepositoryProblemConstraint;
36 import org.apache.maven.archiva.database.constraints.UniqueFieldConstraint;
37 import org.apache.maven.archiva.model.RepositoryContentStatistics;
38 import org.apache.maven.archiva.model.RepositoryProblem;
39 import org.apache.maven.archiva.model.RepositoryProblemReport;
40 import org.apache.maven.archiva.reporting.ArchivaReportException;
41 import org.apache.maven.archiva.reporting.DataLimits;
42 import org.apache.maven.archiva.reporting.RepositoryStatistics;
43 import org.apache.maven.archiva.reporting.RepositoryStatisticsReportGenerator;
44 import org.apache.maven.archiva.security.ArchivaRoleConstants;
45 import org.codehaus.plexus.redback.rbac.Resource;
46 import org.codehaus.plexus.redback.xwork.interceptor.SecureAction;
47 import org.codehaus.plexus.redback.xwork.interceptor.SecureActionBundle;
48 import org.codehaus.plexus.redback.xwork.interceptor.SecureActionException;
49 import org.codehaus.plexus.xwork.action.PlexusActionSupport;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 import javax.servlet.http.HttpServletRequest;
54 import java.util.ArrayList;
55 import java.util.Calendar;
56 import java.util.Collection;
57 import java.util.Date;
58 import java.util.List;
59 import java.util.Map;
60 import java.util.TreeMap;
61
62 /**
63  * @plexus.component role="com.opensymphony.xwork.Action" role-hint="generateReport"
64  */
65 public class GenerateReportAction
66     extends PlexusActionSupport
67     implements SecureAction, ServletRequestAware, Preparable
68 {
69     private Logger log = LoggerFactory.getLogger( GenerateReportAction.class );
70     
71     /**
72      * @plexus.requirement role-hint="jdo"
73      */
74     protected ArchivaDAO dao;
75     
76     /**
77      * @plexus.requirement
78      */
79     private ArchivaConfiguration archivaConfiguration;
80
81     protected Constraint constraint;
82
83     protected HttpServletRequest request;
84
85     protected List<RepositoryProblemReport> reports = new ArrayList<RepositoryProblemReport>();
86
87     protected String groupId;
88
89     protected String repositoryId;
90
91     protected String prev;
92
93     protected String next;
94
95     protected int[] range = new int[2];
96
97     protected int page = 1;
98
99     protected int rowCount = 100;
100
101     protected boolean isLastPage;
102
103     public static final String BLANK = "blank";
104
105     public static final String BASIC = "basic";
106
107     private static Boolean jasperPresent;
108
109     private Collection<String> repositoryIds;
110
111     public static final String ALL_REPOSITORIES = "All Repositories";
112     
113     protected Map<String, List<RepositoryProblemReport>> repositoriesMap = 
114                 new TreeMap<String, List<RepositoryProblemReport>>();
115     
116     // for statistics report
117     /**
118      * @plexus.requirement role-hint="simple"
119      */
120     private RepositoryStatisticsReportGenerator generator;
121     
122     private List<String> selectedRepositories = new ArrayList<String>();
123     
124     private List<String> availableRepositories;  
125     
126     private Date startDate;
127     
128     private Date endDate;
129     
130     private int reposSize;
131     
132     private String selectedRepo;
133     
134     private List<RepositoryStatistics> repositoryStatistics = new ArrayList<RepositoryStatistics>();
135     
136     public void prepare()
137     {
138         repositoryIds = new ArrayList<String>();
139         repositoryIds.add( ALL_REPOSITORIES ); // comes first to be first in the list
140         repositoryIds.addAll(
141             dao.query( new UniqueFieldConstraint( RepositoryProblem.class.getName(), "repositoryId" ) ) );
142         
143         availableRepositories = new ArrayList<String>();
144      
145         // remove selected repositories in the option for the statistics report
146         availableRepositories.addAll( archivaConfiguration.getConfiguration().getManagedRepositoriesAsMap().keySet() );        
147         for( String repo : selectedRepositories )
148         {
149             if( availableRepositories.contains( repo ) )
150             {
151                 availableRepositories.remove( repo );
152             }
153         }
154     }
155
156     public Collection<String> getRepositoryIds()
157     {
158         return repositoryIds;
159     }
160
161     /**
162      * Generate the statistics report.
163      * 
164      * check whether single repo report or comparison report
165      * 1. if it is a single repository, get all the statistics for the repository on the specified date
166      *    - if no date is specified, get only the latest 
167      *          (total page = 1 --> no pagination since only the most recent stats will be displayed)
168      *    - otherwise, get everything within the date range (total pages = repo stats / rows per page)
169      *       - required params: repository, startDate, endDate
170      *       
171      * 2. if multiple repositories, get the latest statistics on each repository on the specified date
172      *    - if no date is specified, use the current date endDate
173      *       - required params: repositories, endDate
174      *    - total pages = repositories / rows per page
175      * 
176      * @return
177      */
178     public String generateStatistics()
179     {   
180         DataLimits limits = new DataLimits();        
181         setDefaults();
182         reposSize = selectedRepositories.size();
183         
184         try
185         {
186             RepositoryContentStatisticsDAO repoContentStatsDao = dao.getRepositoryContentStatisticsDAO();            
187             if( selectedRepositories.size() > 1 )
188             {
189                 limits.setTotalCount( selectedRepositories.size() );            
190                 limits.setCurrentPage( 1 );
191                 limits.setPerPageCount( 1 );
192                 limits.setCountOfPages( 1 );
193                 
194                 // multiple repos
195                 for( String repo : selectedRepositories )
196                 {  
197                     try
198                     {
199                         List contentStats = repoContentStatsDao.queryRepositoryContentStatistics( 
200                            new RepositoryContentStatisticsByRepositoryConstraint( repo, startDate, endDate ) );
201                         
202                         if( contentStats == null || contentStats.isEmpty() )
203                         {
204                             log.info( "No statistics available for repository '" + repo + "'." );
205                             // TODO set repo's stats to 0
206                             
207                             continue;
208                         }                        
209                         repositoryStatistics.addAll( generator.generateReport( contentStats, repo, startDate, endDate, limits ) );
210                     }
211                     catch ( ObjectNotFoundException oe )
212                     {
213                         log.error( "No statistics available for repository '" + repo + "'." );
214                         // TODO set repo's stats to 0
215                     }
216                     catch ( ArchivaDatabaseException ae )
217                     {
218                         log.error( "Error encountered while querying statistics of repository '" + repo + "'." );
219                         // TODO set repo's stats to 0
220                     }
221                 }
222             }
223             else if ( selectedRepositories.size() == 1 )
224             {   
225                 limits.setCurrentPage( getPage() );
226                 limits.setPerPageCount( getRowCount() );
227                 
228                 selectedRepo = selectedRepositories.get( 0 );
229                 try
230                 {
231                     List<RepositoryContentStatistics> contentStats = repoContentStatsDao.queryRepositoryContentStatistics( 
232                            new RepositoryContentStatisticsByRepositoryConstraint( selectedRepo, startDate, endDate ) );
233                     
234                     if( contentStats == null || contentStats.isEmpty() )
235                     {   
236                         addActionError( "No statistics available for repository. Repository might not have been scanned." );
237                         return ERROR;
238                     }   
239                     
240                     limits.setTotalCount( contentStats.size() );                    
241                     int extraPage = ( limits.getTotalCount() % limits.getPerPageCount() ) != 0 ? 1 : 0;
242                     int totalPages = ( limits.getTotalCount() / limits.getPerPageCount() ) + extraPage;                    
243                     limits.setCountOfPages( totalPages );
244                     
245                     repositoryStatistics = generator.generateReport( contentStats, selectedRepo, startDate, endDate, limits );
246                 }
247                 catch ( ObjectNotFoundException oe )
248                 {
249                     addActionError( oe.getMessage() );
250                     return ERROR;
251                 }
252                 catch ( ArchivaDatabaseException de )
253                 {
254                     addActionError( de.getMessage() );
255                     return ERROR;
256                 }
257             }
258             else
259             {
260                 addFieldError( "availableRepositories", "Please select a repository (or repositories) from the list." );
261                 return INPUT;
262             }            
263         }
264         catch ( ArchivaReportException e )
265         {
266             addActionError( "Error encountered while generating report :: " + e.getMessage() );
267             return ERROR;
268         }
269         
270         return SUCCESS;
271     }
272
273     private void setDefaults()
274     {
275         if( startDate == null )
276         {
277             Calendar cal = Calendar.getInstance();
278             cal.clear();
279             cal.set( 1900, 1, 1, 0, 0, 0 );
280             startDate = cal.getTime();
281         }
282         
283         if( endDate == null )
284         {
285             endDate = Calendar.getInstance().getTime();
286         }
287     }
288     
289     public String execute()
290         throws Exception
291     {   
292         if( repositoryId == null )
293         {
294             addFieldError( "repositoryId", "You must provide a repository id.");            
295             return INPUT;
296         }
297         
298         if( rowCount < 10 )
299         {
300             addFieldError( "rowCount", "Row count must be larger than 10." );
301             return INPUT;
302         }
303         
304         List<RepositoryProblem> problemArtifacts =
305             dao.getRepositoryProblemDAO().queryRepositoryProblems( configureConstraint() );
306
307         String contextPath =
308             request.getRequestURL().substring( 0, request.getRequestURL().indexOf( request.getRequestURI() ) );
309         RepositoryProblem problemArtifact;
310         RepositoryProblemReport problemArtifactReport;
311         for ( int i = 0; i < problemArtifacts.size(); i++ )
312         {
313             problemArtifact = (RepositoryProblem) problemArtifacts.get( i );
314             problemArtifactReport = new RepositoryProblemReport( problemArtifact );
315
316             problemArtifactReport.setGroupURL( contextPath + "/browse/" + problemArtifact.getGroupId() );
317             problemArtifactReport.setArtifactURL(
318                 contextPath + "/browse/" + problemArtifact.getGroupId() + "/" + problemArtifact.getArtifactId() );
319
320             addToList( problemArtifactReport );
321             
322             // retained the reports list because this is the datasource for the jasper report            
323             reports.add( problemArtifactReport );
324         }
325         
326         if ( reports.size() <= rowCount )
327         {
328             isLastPage = true;
329         }
330         else
331         {
332             reports.remove( rowCount );
333         }
334
335         prev = request.getRequestURL() + "?page=" + ( page - 1 ) + "&rowCount=" + rowCount + "&groupId=" + groupId +
336             "&repositoryId=" + repositoryId;
337         next = request.getRequestURL() + "?page=" + ( page + 1 ) + "&rowCount=" + rowCount + "&groupId=" + groupId +
338             "&repositoryId=" + repositoryId;
339
340         if ( reports.size() == 0 && page == 1 )
341         {
342             return BLANK;
343         }
344         else if ( isJasperPresent() )
345         {
346             return "jasper";
347         }
348         else
349         {
350             return SUCCESS;
351         }
352     }
353     
354     private static boolean isJasperPresent()
355     {
356         if ( jasperPresent == null )
357         {
358             try
359             {
360                 Class.forName( "net.sf.jasperreports.engine.JRExporterParameter" );
361                 jasperPresent = Boolean.TRUE;
362             }
363             catch ( NoClassDefFoundError e )
364             {
365                 jasperPresent = Boolean.FALSE;
366             }
367             catch ( ClassNotFoundException e )
368             {
369                 jasperPresent = Boolean.FALSE;
370             }
371         }
372         return jasperPresent.booleanValue();
373     }
374
375     private Constraint configureConstraint()
376     {
377         Constraint constraint;
378
379         range[0] = ( page - 1 ) * rowCount;
380         range[1] = ( page * rowCount ) + 1; // Add 1 to check if it's the last page or not.
381
382         if ( groupId != null && ( !groupId.equals( "" ) ) )
383         {
384             if ( repositoryId != null && ( !repositoryId.equals( "" ) && !repositoryId.equals( ALL_REPOSITORIES ) ) )
385             {
386                 constraint = new RepositoryProblemConstraint( range, groupId, repositoryId );
387             }
388             else
389             {
390                 constraint = new RepositoryProblemByGroupIdConstraint( range, groupId );
391             }
392         }
393         else if ( repositoryId != null && ( !repositoryId.equals( "" ) && !repositoryId.equals( ALL_REPOSITORIES ) ) )
394         {
395             constraint = new RepositoryProblemByRepositoryIdConstraint( range, repositoryId );
396         }
397         else
398         {
399             constraint = new RangeConstraint( range, "repositoryId" );
400         }
401
402         return constraint;
403     }
404     
405     public SecureActionBundle getSecureActionBundle()
406         throws SecureActionException
407     {
408         SecureActionBundle bundle = new SecureActionBundle();
409     
410         bundle.setRequiresAuthentication( true );
411         bundle.addRequiredAuthorization( ArchivaRoleConstants.OPERATION_ACCESS_REPORT, Resource.GLOBAL );
412     
413         return bundle;
414     }
415     
416     private void addToList( RepositoryProblemReport repoProblemReport )
417     {
418         List<RepositoryProblemReport> problemsList = null;
419         
420         if ( repositoriesMap.containsKey( repoProblemReport.getRepositoryId() ) )
421         {
422             problemsList = ( List<RepositoryProblemReport> ) repositoriesMap.get( repoProblemReport.getRepositoryId() );
423         }
424         else
425         {
426             problemsList = new ArrayList<RepositoryProblemReport>();
427             repositoriesMap.put( repoProblemReport.getRepositoryId(), problemsList );
428         }
429         
430         problemsList.add( repoProblemReport );
431     }
432
433     public void setServletRequest( HttpServletRequest request )
434     {
435         this.request = request;
436     }
437
438     public List<RepositoryProblemReport> getReports()
439     {
440         return reports;
441     }
442
443     public String getGroupId()
444     {
445         return groupId;
446     }
447
448     public void setGroupId( String groupId )
449     {
450         this.groupId = groupId;
451     }
452
453     public String getRepositoryId()
454     {
455         return repositoryId;
456     }
457
458     public void setRepositoryId( String repositoryId )
459     {
460         this.repositoryId = repositoryId;
461     }
462
463     public String getPrev()
464     {
465         return prev;
466     }
467
468     public String getNext()
469     {
470         return next;
471     }
472
473     public int getPage()
474     {
475         return page;
476     }
477
478     public void setPage( int page )
479     {
480         this.page = page;
481     }
482
483     public int getRowCount()
484     {
485         return rowCount;
486     }
487
488     public void setRowCount( int rowCount )
489     {
490         this.rowCount = rowCount;
491     }
492
493     public boolean getIsLastPage()
494     {
495         return isLastPage;
496     }
497
498     public void setRepositoriesMap( Map<String, List<RepositoryProblemReport>> repositoriesMap )
499     {
500         this.repositoriesMap = repositoriesMap;
501     }
502     
503     public Map<String, List<RepositoryProblemReport>> getRepositoriesMap()
504     {
505         return repositoriesMap;
506     }
507     
508     public List<String> getSelectedRepositories()
509     {
510         return selectedRepositories;
511     }
512
513     public void setSelectedRepositories( List<String> selectedRepositories )
514     {
515         this.selectedRepositories = selectedRepositories;
516     }
517
518     public List<String> getAvailableRepositories()
519     {
520         return availableRepositories;
521     }
522
523     public void setAvailableRepositories( List<String> availableRepositories )
524     {
525         this.availableRepositories = availableRepositories;
526     }
527
528     public Date getStartDate()
529     {
530         return startDate;
531     }
532
533     public void setStartDate( Date startDate )
534     {
535         this.startDate = startDate;
536     }
537
538     public Date getEndDate()
539     {
540         return endDate;
541     }
542
543     public void setEndDate( Date endDate )
544     {
545         this.endDate = endDate;
546     }
547
548     public List<RepositoryStatistics> getRepositoryStatistics()
549     {
550         return repositoryStatistics;
551     }
552
553     public void setRepositoryStatistics( List<RepositoryStatistics> repositoryStatistics )
554     {
555         this.repositoryStatistics = repositoryStatistics;
556     }
557     
558     public int getReposSize()
559     {
560         return reposSize;
561     }
562
563     public void setReposSize( int reposSize )
564     {
565         this.reposSize = reposSize;
566     }
567
568     public String getSelectedRepo()
569     {
570         return selectedRepo;
571     }
572
573     public void setSelectedRepo( String selectedRepo )
574     {
575         this.selectedRepo = selectedRepo;
576     }
577 }