View Javadoc

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