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