package org.apache.maven.plugins.surefire.report;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.apache.maven.shared.utils.PathTool;
import static java.util.Collections.addAll;
import static org.apache.maven.plugins.surefire.report.SurefireReportParser.hasReportFiles;
import static org.apache.maven.shared.utils.StringUtils.isEmpty;
/**
* Abstract base class for reporting test results using Surefire.
*
* @author Stephen Connolly
*/
public abstract class AbstractSurefireReportMojo
extends AbstractMavenReport
{
/**
* If set to false, only failures are shown.
*
* @noinspection UnusedDeclaration
*/
@Parameter( defaultValue = "true", required = true, property = "showSuccess" )
private boolean showSuccess;
/**
* Directories containing the XML Report files that will be parsed and rendered to HTML format.
*
* @noinspection UnusedDeclaration
*/
@Parameter
private File[] reportsDirectories;
/**
* (Deprecated, use reportsDirectories) This directory contains the XML Report files that will be parsed and
* rendered to HTML format.
*
* @noinspection UnusedDeclaration
*/
@Deprecated
@Parameter
private File reportsDirectory;
/**
* The projects in the reactor for aggregation report.
*
* @noinspection MismatchedQueryAndUpdateOfCollection, UnusedDeclaration
*/
@Parameter( defaultValue = "${reactorProjects}", readonly = true )
private List<MavenProject> reactorProjects;
/**
* Location of the Xrefs to link.
*
* @noinspection UnusedDeclaration
*/
@Parameter( defaultValue = "${project.reporting.outputDirectory}/xref-test" )
private File xrefLocation;
/**
* Whether to link the XRef if found.
*
* @noinspection UnusedDeclaration
*/
@Parameter( defaultValue = "true", property = "linkXRef" )
private boolean linkXRef;
/**
* Whether to build an aggregated report at the root, or build individual reports.
*
* @noinspection UnusedDeclaration
*/
@Parameter( defaultValue = "false", property = "aggregate" )
private boolean aggregate;
private List<File> resolvedReportsDirectories;
/**
* Whether the report should be generated or not.
*
* @return {@code true} if and only if the report should be generated.
* @since 2.11
*/
protected boolean isSkipped()
{
return false;
}
/**
* Whether the report should be generated when there are no test results.
*
* @return {@code true} if and only if the report should be generated when there are no result files at all.
* @since 2.11
*/
protected boolean isGeneratedWhenNoResults()
{
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void executeReport( Locale locale )
throws MavenReportException
{
if ( !hasReportDirectories() )
{
return;
}
new SurefireReportGenerator( getReportsDirectories(), locale, showSuccess, determineXrefLocation(),
getConsoleLogger() )
.doGenerateReport( getBundle( locale ), getSink() );
}
@Override
public boolean canGenerateReport()
{
return hasReportDirectories() && super.canGenerateReport();
}
private boolean hasReportDirectories()
{
if ( isSkipped() )
{
return false;
}
final List<File> reportsDirectories = getReportsDirectories();
if ( reportsDirectories == null )
{
return false;
}
if ( !isGeneratedWhenNoResults() )
{
boolean atLeastOneDirectoryExists = false;
for ( Iterator<File> i = reportsDirectories.iterator(); i.hasNext() && !atLeastOneDirectoryExists; )
{
atLeastOneDirectoryExists = hasReportFiles( i.next() );
}
if ( !atLeastOneDirectoryExists )
{
return false;
}
}
return true;
}
private List<File> getReportsDirectories()
{
if ( resolvedReportsDirectories != null )
{
return resolvedReportsDirectories;
}
resolvedReportsDirectories = new ArrayList<File>();
if ( this.reportsDirectories != null )
{
addAll( resolvedReportsDirectories, this.reportsDirectories );
}
//noinspection deprecation
if ( reportsDirectory != null )
{
//noinspection deprecation
resolvedReportsDirectories.add( reportsDirectory );
}
if ( aggregate )
{
if ( !project.isExecutionRoot() )
{
return null;
}
if ( this.reportsDirectories == null )
{
for ( MavenProject mavenProject : getProjectsWithoutRoot() )
{
resolvedReportsDirectories.add( getSurefireReportsDirectory( mavenProject ) );
}
}
else
{
// Multiple report directories are configured.
// Let's see if those directories exist in each sub-module to fix SUREFIRE-570
String parentBaseDir = getProject().getBasedir().getAbsolutePath();
for ( MavenProject subProject : getProjectsWithoutRoot() )
{
String moduleBaseDir = subProject.getBasedir().getAbsolutePath();
for ( File reportsDirectory1 : this.reportsDirectories )
{
String reportDir = reportsDirectory1.getPath();
if ( reportDir.startsWith( parentBaseDir ) )
{
reportDir = reportDir.substring( parentBaseDir.length() );
}
File reportsDirectory = new File( moduleBaseDir, reportDir );
if ( reportsDirectory.exists() && reportsDirectory.isDirectory() )
{
getConsoleLogger().debug( "Adding report dir : " + moduleBaseDir + reportDir );
resolvedReportsDirectories.add( reportsDirectory );
}
}
}
}
}
else
{
if ( resolvedReportsDirectories.isEmpty() )
{
resolvedReportsDirectories.add( getSurefireReportsDirectory( project ) );
}
}
return resolvedReportsDirectories;
}
/**
* Gets the default surefire reports directory for the specified project.
*
* @param subProject the project to query.
* @return the default surefire reports directory for the specified project.
*/
protected abstract File getSurefireReportsDirectory( MavenProject subProject );
private List<MavenProject> getProjectsWithoutRoot()
{
List<MavenProject> result = new ArrayList<MavenProject>();
for ( MavenProject subProject : reactorProjects )
{
if ( !project.equals( subProject ) )
{
result.add( subProject );
}
}
return result;
}
private String determineXrefLocation()
{
String location = null;
if ( linkXRef )
{
String relativePath = PathTool.getRelativePath( getOutputDirectory(), xrefLocation.getAbsolutePath() );
if ( isEmpty( relativePath ) )
{
relativePath = ".";
}
relativePath = relativePath + "/" + xrefLocation.getName();
if ( xrefLocation.exists() )
{
// XRef was already generated by manual execution of a lifecycle binding
location = relativePath;
}
else
{
// Not yet generated - check if the report is on its way
for ( Object o : project.getReportPlugins() )
{
ReportPlugin report = (ReportPlugin) o;
String artifactId = report.getArtifactId();
if ( "maven-jxr-plugin".equals( artifactId ) || "jxr-maven-plugin".equals( artifactId ) )
{
location = relativePath;
}
}
}
if ( location == null )
{
getConsoleLogger().warning( "Unable to locate Test Source XRef to link to - DISABLED" );
}
}
return location;
}
/**
* {@inheritDoc}
*/
@Override
public String getName( Locale locale )
{
return getBundle( locale ).getString( "report.surefire.name" );
}
/**
* {@inheritDoc}
*/
@Override
public String getDescription( Locale locale )
{
return getBundle( locale ).getString( "report.surefire.description" );
}
/**
* {@inheritDoc}
*/
@Override
public abstract String getOutputName();
private ResourceBundle getBundle( Locale locale )
{
return ResourceBundle.getBundle( "surefire-report", locale, getClass().getClassLoader() );
}
protected final ConsoleLogger getConsoleLogger()
{
return new PluginConsoleLogger( getLog() );
}
}