package org.codehaus.mojo.emma; /* * The MIT License * * Copyright (c) 2007-8, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import java.io.File; import java.io.IOException; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import java.util.WeakHashMap; import org.apache.maven.doxia.siterenderer.Renderer; import org.apache.maven.project.MavenProject; import org.apache.maven.reporting.AbstractMavenReport; import org.apache.maven.reporting.MavenReportException; import org.codehaus.mojo.emma.task.ReportTask; import org.codehaus.plexus.util.ReaderFactory; /** * Instruments, tests, and generates an EMMA report. * * @author <a href="mailto:alexandre.roman@gmail.com">Alexandre ROMAN</a> * @goal emma * @execute phase="test" lifecycle="emma" * @requiresDependencyResolution test */ public class EmmaReportMojo extends AbstractMavenReport { /** * The bundle base name for i18n and l10n. */ private static final String BUNDLE_BASENAME = EmmaReportMojo.class.getPackage().getName() + ".Resources"; /** * Output directory for the report. * * @parameter default-value="${project.reporting.outputDirectory}/emma" * @required */ protected File outputDirectory; /** * Source locations. * * @parameter */ protected File[] sourcePaths; /** * Location to store class coverage metadata. * * @parameter expression="${emma.metadataFile}" default-value="${project.build.directory}/coverage.em" */ protected File metadataFile; /** * Class coverage data files. * * @parameter */ protected File[] dataFiles; /** * Report encoding. * * @parameter expression="${emma.report.encoding}" default-value="${project.reporting.outputEncoding}" */ protected String outputEncoding; /** * Specifies the amount of detail to be included in the generated coverage reports. Valid values are: * <code>all</code>, <code>package</code>, <code>source</code>, <code>class</code>, <code>method</code>. * * @parameter expression="${emma.report.depth}" default-value="method" */ protected String depth; /** * Specifies which report columns and in which order to use for report generation, as a comma-separated list of * column ids. * * @parameter expression="${emma.report.columns}" default-value="name,class,method,block,line" */ protected String columns; /** * Specifies report column sorting order, as a comma-separated list of columns ids prefixed with "+" for ascending * or "-" for descending directions. * * @parameter expression="${emma.report.sort}" default-value="+block,+name,+method,+class" */ protected String sort; /** * Specifies the threshold coverage metrics values for a given set of columns. * * @parameter expression="${emma.report.metrics}" default-value="method:70,block:70,line:80,class:100" */ protected String metrics; /** * Sets EMMA verbosity level to <code>verbose</code>. * * @parameter expression="${emma.verbose}" default-value="false" */ protected boolean verbose; /** * Maven project. * * @parameter expression="${project}" * @required * @readonly */ protected MavenProject project; /** * Plugin classpath. * * @parameter expression="${plugin.artifacts}" * @required * @readonly */ protected List pluginClasspath; /** * Site renderer. * * @component */ protected Renderer siteRenderer; /** * The bundles. */ private final Map bundles = new WeakHashMap(); /** * Check parameters. * * @throws MavenReportException if any parameters are wrong */ protected void checkParameters() throws MavenReportException { if ( getLog().isDebugEnabled() ) { verbose = true; } if ( dataFiles == null ) { dataFiles = new File[] { new File( project.getBasedir(), "coverage.ec" ) }; } if ( sourcePaths == null ) { sourcePaths = new File[] { new File( project.getBuild().getSourceDirectory() ) }; } } /** * Executes the report for a specific locale. * * @param locale the locale. * @throws MavenReportException if something goes wrong. */ protected void executeReport( Locale locale ) throws MavenReportException { checkParameters(); if ( !canGenerateReport() ) { return; } if ( getLog().isDebugEnabled() ) { getLog().debug( "Output directory: " + outputDirectory.getAbsolutePath() ); getLog().debug( "Source paths:" ); for ( int i = 0; i < sourcePaths.length; ++i ) { getLog().debug( " o " + sourcePaths[i] ); } } // aggregate several EMMA coverage data files final File[] newDataFiles = EmmaUtils.fixDataFileLocations( project, dataFiles ); final ReportTask task = new ReportTask(); task.setVerbose( verbose ); task.setMetadataFile( metadataFile ); task.setDataFiles( newDataFiles ); task.setSourcePaths( sourcePaths ); task.setOutputDirectory( outputDirectory ); task.setColumns( columns ); task.setDepth( depth ); task.setEncoding( ( outputEncoding != null ) ? outputEncoding : ReaderFactory.UTF_8 ); task.setMetrics( metrics ); task.setSort( sort ); try { task.execute(); } catch ( IOException e ) { throw new MavenReportException( "Failed to generate EMMA report", e ); } } /** * Gets the output directory. * * @return the output directory. */ protected String getOutputDirectory() { return outputDirectory.getAbsolutePath(); } /** * Gets the maven project. * * @return the maven project. */ protected MavenProject getProject() { return project; } /** * Gets the site renderer. * * @return the site renderer. */ protected Renderer getSiteRenderer() { return siteRenderer; } /** * Gets the description in the specified locale. * * @param locale the locale. * @return the description in the specified locale. */ public String getDescription( Locale locale ) { return getResourceBundle( locale ).getString( "emma.plugin.description" ); } /** * Gets the name in the specified locale. * * @param locale the locale. * @return the name in the specified locale. */ public String getName( Locale locale ) { return getResourceBundle( locale ).getString( "emma.plugin.name" ); } /** * Gets the output name. * * @return the output name. */ public String getOutputName() { return "emma/index"; } /** * Returns <code>true</code> as this is an external report. * * @return <code>true</code> as this is an external report. */ public boolean isExternalReport() { return true; } /** * Checks if the report can be generated. * * @return <code>true</code> if the report can be generated. */ public boolean canGenerateReport() { final boolean ready = metadataFile.exists(); if ( !ready ) { getLog().info( "Not generating EMMA report as the metadata file (" + metadataFile.getName() + ") could not be found" ); } return ready; } /** * Gets the resource bundle for the specified locale. * * @param locale the locale. * @return the resource bundle for the specified locale. */ protected ResourceBundle getResourceBundle( Locale locale ) { ResourceBundle bundle = (ResourceBundle) bundles.get( locale ); if ( bundle == null ) { bundle = ResourceBundle.getBundle( BUNDLE_BASENAME, locale ); bundles.put( locale, bundle ); } return bundle; } }