View Javadoc

1   package org.apache.maven.plugins.surefire.report;
2   
3   import org.apache.maven.doxia.siterenderer.Renderer;
4   import org.apache.maven.model.ReportPlugin;
5   import org.apache.maven.project.MavenProject;
6   import org.apache.maven.reporting.AbstractMavenReport;
7   import org.apache.maven.reporting.MavenReportException;
8   import org.codehaus.plexus.util.PathTool;
9   import org.codehaus.plexus.util.StringUtils;
10  
11  import java.io.File;
12  import java.util.ArrayList;
13  import java.util.Arrays;
14  import java.util.Iterator;
15  import java.util.List;
16  import java.util.Locale;
17  import java.util.ResourceBundle;
18  
19  /**
20   * Abstract base class for reporting test results using Surefire.
21   *
22   * @author Stephen Connolly
23   * @version $Id$
24   */
25  public abstract class AbstractSurefireReportMojo
26      extends AbstractMavenReport
27  {
28      /**
29       * Location where generated html will be created.
30       *
31       * @parameter expression="${project.reporting.outputDirectory}"
32       * @noinspection UnusedDeclaration
33       */
34      private File outputDirectory;
35  
36      /**
37       * Doxia Site Renderer
38       *
39       * @component
40       * @noinspection UnusedDeclaration
41       */
42      private Renderer siteRenderer;
43  
44      /**
45       * Maven Project
46       *
47       * @parameter expression="${project}"
48       * @required @readonly
49       * @noinspection UnusedDeclaration
50       */
51      private MavenProject project;
52  
53      /**
54       * If set to false, only failures are shown.
55       *
56       * @parameter expression="${showSuccess}" default-value="true"
57       * @required
58       * @noinspection UnusedDeclaration
59       */
60      private boolean showSuccess;
61  
62      /**
63       * Directories containing the XML Report files that will be parsed and rendered to HTML format.
64       *
65       * @parameter
66       * @noinspection UnusedDeclaration
67       */
68      private File[] reportsDirectories;
69  
70      /**
71       * (Deprecated, use reportsDirectories) This directory contains the XML Report files that will be parsed and rendered to HTML format.
72       *
73       * @parameter
74       * @deprecated
75       * @noinspection UnusedDeclaration
76       */
77      private File reportsDirectory;
78  
79      /**
80       * The projects in the reactor for aggregation report.
81       *
82       * @parameter expression="${reactorProjects}"
83       * @readonly
84       * @noinspection MismatchedQueryAndUpdateOfCollection, UnusedDeclaration
85       */
86      private List reactorProjects;
87  
88      /**
89       * Location of the Xrefs to link.
90       *
91       * @parameter default-value="${project.reporting.outputDirectory}/xref-test"
92       * @noinspection UnusedDeclaration
93       */
94      private File xrefLocation;
95  
96      /**
97       * Whether to link the XRef if found.
98       *
99       * @parameter expression="${linkXRef}" default-value="true"
100      * @noinspection UnusedDeclaration
101      */
102     private boolean linkXRef;
103 
104     /**
105      * Whether to build an aggregated report at the root, or build individual reports.
106      *
107      * @parameter expression="${aggregate}" default-value="false"
108      * @noinspection UnusedDeclaration
109      */
110     private boolean aggregate;
111 
112     /**
113      * Whether the report should be generated or not.
114      *
115      * @return {@code true} if and only if the report should be generated.
116      * @since 2.11
117      */
118     protected boolean isSkipped()
119     {
120         return false;
121     }
122 
123     /**
124      * Whether the report should be generated when there are no test results.
125      *
126      * @return {@code true} if and only if the report should be generated when there are no result files at all.
127      * @since 2.11
128      */
129     protected boolean isGeneratedWhenNoResults()
130     {
131         return false;
132     }
133 
134     /**
135      * {@inheritDoc}
136      */
137     public void executeReport( Locale locale )
138         throws MavenReportException
139     {
140         if ( isSkipped() )
141         {
142             return;
143         }
144 
145         final List reportsDirectoryList = getReportsDirectories();
146 
147         if ( reportsDirectoryList == null )
148         {
149             return;
150         }
151 
152         if ( !isGeneratedWhenNoResults() )
153         {
154             boolean atLeastOneDirectoryExists = false;
155             for ( Iterator i = reportsDirectoryList.iterator(); i.hasNext() && !atLeastOneDirectoryExists; )
156             {
157                 atLeastOneDirectoryExists = SurefireReportParser.hasReportFiles( (File) i.next() );
158             }
159             if ( !atLeastOneDirectoryExists )
160             {
161                 return;
162             }
163         }
164 
165         SurefireReportGenerator report =
166             new SurefireReportGenerator( reportsDirectoryList, locale, showSuccess, determineXrefLocation() );
167 
168         report.doGenerateReport( getBundle( locale ), getSink() );
169     }
170 
171     public boolean canGenerateReport()
172     {
173         if ( isSkipped() )
174         {
175             return false;
176         }
177 
178         final List reportsDirectoryList = getReportsDirectories();
179 
180         if ( reportsDirectoryList == null )
181         {
182             return false;
183         }
184 
185         if ( !isGeneratedWhenNoResults() )
186         {
187             boolean atLeastOneDirectoryExists = false;
188             for ( Iterator i = reportsDirectoryList.iterator(); i.hasNext() && !atLeastOneDirectoryExists; )
189             {
190                 atLeastOneDirectoryExists = SurefireReportParser.hasReportFiles( (File) i.next() );
191             }
192             if ( !atLeastOneDirectoryExists )
193             {
194                 return false;
195             }
196         }
197 
198         return super.canGenerateReport();
199     }
200 
201     private List getReportsDirectories()
202     {
203         final List reportsDirectoryList = new ArrayList();
204 
205         if ( reportsDirectories != null )
206         {
207             reportsDirectoryList.addAll( Arrays.asList( reportsDirectories ) );
208         }
209         //noinspection deprecation
210         if ( reportsDirectory != null )
211         {
212             //noinspection deprecation
213             reportsDirectoryList.add( reportsDirectory );
214         }
215         if ( aggregate )
216         {
217             if ( !project.isExecutionRoot() )
218             {
219                 return null;
220             }
221             if ( reportsDirectories == null )
222             {
223                 for ( Iterator i = getProjectsWithoutRoot().iterator(); i.hasNext(); )
224                 {
225                     reportsDirectoryList.add( getSurefireReportsDirectory( (MavenProject) i.next() ) );
226                 }
227             }
228             else
229             {
230                 // Multiple report directories are configured.
231                 // Let's see if those directories exist in each sub-module to fix SUREFIRE-570
232                 String parentBaseDir = getProject().getBasedir().getAbsolutePath();
233                 for ( Iterator i = getProjectsWithoutRoot().iterator(); i.hasNext(); )
234                 {
235                     MavenProject subProject = (MavenProject) i.next();
236                     String moduleBaseDir = subProject.getBasedir().getAbsolutePath();
237                     for ( int d = 0; d < reportsDirectories.length; d++ )
238                     {
239                         String reportDir = reportsDirectories[d].getPath();
240                         if ( reportDir.startsWith( parentBaseDir ) )
241                         {
242                             reportDir = reportDir.substring( parentBaseDir.length() );
243                         }
244                         File reportsDirectory = new File( moduleBaseDir, reportDir );
245                         if ( reportsDirectory.exists() && reportsDirectory.isDirectory() )
246                         {
247                             getLog().debug( "Adding report dir : " + moduleBaseDir + reportDir );
248                             reportsDirectoryList.add( reportsDirectory );
249                         }
250                     }
251                 }
252             }
253         }
254         else
255         {
256             if ( reportsDirectoryList.size() == 0 )
257             {
258 
259                 reportsDirectoryList.add( getSurefireReportsDirectory( project ) );
260             }
261         }
262         return reportsDirectoryList;
263     }
264 
265     /**
266      * Gets the default surefire reports directory for the specified project.
267      * @param subProject the project to query.
268      * @return the default surefire reports directory for the specified project.
269      */
270     protected abstract File getSurefireReportsDirectory( MavenProject subProject );
271 
272     private List getProjectsWithoutRoot()
273     {
274         List result = new ArrayList();
275         for ( Iterator i = reactorProjects.iterator(); i.hasNext(); )
276         {
277             MavenProject subProject = (MavenProject) i.next();
278             if ( !project.equals( subProject ) )
279             {
280                 result.add( subProject );
281             }
282         }
283         return result;
284 
285     }
286 
287     private String determineXrefLocation()
288     {
289         String location = null;
290 
291         if ( linkXRef )
292         {
293             String relativePath = PathTool.getRelativePath( getOutputDirectory(), xrefLocation.getAbsolutePath() );
294             if ( StringUtils.isEmpty( relativePath ) )
295             {
296                 relativePath = ".";
297             }
298             relativePath = relativePath + "/" + xrefLocation.getName();
299             if ( xrefLocation.exists() )
300             {
301                 // XRef was already generated by manual execution of a lifecycle binding
302                 location = relativePath;
303             }
304             else
305             {
306                 // Not yet generated - check if the report is on its way
307                 for ( Iterator reports = project.getReportPlugins().iterator(); reports.hasNext(); )
308                 {
309                     ReportPlugin report = (ReportPlugin) reports.next();
310 
311                     String artifactId = report.getArtifactId();
312                     if ( "maven-jxr-plugin".equals( artifactId ) || "jxr-maven-plugin".equals( artifactId ) )
313                     {
314                         location = relativePath;
315                     }
316                 }
317             }
318 
319             if ( location == null )
320             {
321                 getLog().warn( "Unable to locate Test Source XRef to link to - DISABLED" );
322             }
323         }
324         return location;
325     }
326 
327     /**
328      * {@inheritDoc}
329      */
330     public String getName( Locale locale )
331     {
332         return getBundle( locale ).getString( "report.surefire.name" );
333     }
334 
335     /**
336      * {@inheritDoc}
337      */
338     public String getDescription( Locale locale )
339     {
340         return getBundle( locale ).getString( "report.surefire.description" );
341     }
342 
343     /**
344      * {@inheritDoc}
345      */
346     protected Renderer getSiteRenderer()
347     {
348         return siteRenderer;
349     }
350 
351     /**
352      * {@inheritDoc}
353      */
354     protected MavenProject getProject()
355     {
356         return project;
357     }
358 
359     /**
360      * {@inheritDoc}
361      */
362     public abstract String getOutputName();
363 
364     /**
365      * {@inheritDoc}
366      */
367     protected String getOutputDirectory()
368     {
369         return outputDirectory.getAbsolutePath();
370     }
371 
372     private ResourceBundle getBundle( Locale locale )
373     {
374         return ResourceBundle.getBundle( "surefire-report", locale, this.getClass().getClassLoader() );
375     }
376 }