All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.maven.plugin.checkstyle.CheckstyleReport Maven / Gradle / Ivy

Go to download

Publishing a Kuali version of this plugin in order to upgrade the dependency on checkstyle to 5.4 (was 5.0)

The newest version!
package org.apache.maven.plugin.checkstyle;

/*
 * 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.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.doxia.tools.SiteTool;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.plugin.checkstyle.rss.CheckstyleRssGenerator;
import org.apache.maven.plugin.checkstyle.rss.CheckstyleRssGeneratorRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.plexus.resource.ResourceManager;
import org.codehaus.plexus.resource.loader.FileResourceLoader;
import org.codehaus.plexus.util.PathTool;
import org.codehaus.plexus.util.StringUtils;

import com.puppycrawl.tools.checkstyle.DefaultLogger;
import com.puppycrawl.tools.checkstyle.XMLLogger;
import com.puppycrawl.tools.checkstyle.api.AuditListener;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;

/**
 * Perform a Checkstyle analysis, and generate a report on violations.
 *
 * @author Emmanuel Venisse
 * @author Vincent Siveton
 * @author Joakim Erdfelt
 * @version $Id: CheckstyleReport.java 952476 2010-06-07 23:00:42Z olamy $
 * @goal checkstyle
 * @requiresDependencyResolution compile
 * @threadSafe
 */
public class CheckstyleReport
    extends AbstractMavenReport
{
    public static final String PLUGIN_RESOURCES = "org/apache/maven/plugin/checkstyle";

    /**
     * @deprecated Remove with format parameter.
     */
    private static final Map FORMAT_TO_CONFIG_LOCATION;

    static
    {
        Map fmt2Cfg = new HashMap();

        fmt2Cfg.put( "sun", "config/sun_checks.xml" );
        fmt2Cfg.put( "turbine", "config/turbine_checks.xml" );
        fmt2Cfg.put( "avalon", "config/avalon_checks.xml" );
        fmt2Cfg.put( "maven", "config/maven_checks.xml" );

        FORMAT_TO_CONFIG_LOCATION = Collections.unmodifiableMap( fmt2Cfg );
    }

    /**
     * Skip entire check.
     *
     * @parameter expression="${checkstyle.skip}" default-value="false"
     * @since 2.2
     */
    private boolean skip;

    /**
     * The output directory for the report. Note that this parameter is only
     * evaluated if the goal is run directly from the command line. If the goal
     * is run indirectly as part of a site generation, the output directory
     * configured in Maven Site Plugin is used instead.
     *
     * @parameter default-value="${project.reporting.outputDirectory}"
     * @required
     */
    private File outputDirectory;

    /**
     * Specifies if the Rules summary should be enabled or not.
     *
     * @parameter expression="${checkstyle.enable.rules.summary}"
     *            default-value="true"
     */
    private boolean enableRulesSummary;

    /**
     * Specifies if the Severity summary should be enabled or not.
     *
     * @parameter expression="${checkstyle.enable.severity.summary}"
     *            default-value="true"
     */
    private boolean enableSeveritySummary;

    /**
     * Specifies if the Files summary should be enabled or not.
     *
     * @parameter expression="${checkstyle.enable.files.summary}"
     *            default-value="true"
     */
    private boolean enableFilesSummary;

    /**
     * Specifies if the RSS should be enabled or not.
     *
     * @parameter expression="${checkstyle.enable.rss}" default-value="true"
     */
    private boolean enableRSS;

    /**
     * Specifies the names filter of the source files to be used for Checkstyle.
     *
     * @parameter expression="${checkstyle.includes}" default-value="**\/*.java"
     * @required
     */
    private String includes;

    /**
     * Specifies the names filter of the source files to be excluded for
     * Checkstyle.
     *
     * @parameter expression="${checkstyle.excludes}"
     */
    private String excludes;

    /**
     * 

* Specifies the location of the XML configuration to use. *

* *

* Potential values are a filesystem path, a URL, or a classpath resource. * This parameter expects that the contents of the location conform to the * xml format (Checkstyle Checker * module) configuration of rulesets. *

* *

* This parameter is resolved as resource, URL, then file. If successfully * resolved, the contents of the configuration is copied into the * ${project.build.directory}/checkstyle-configuration.xml * file before being passed to Checkstyle as a configuration. *

* *

* There are 4 predefined rulesets. *

* *
    *
  • config/sun_checks.xml: Sun Checks.
  • *
  • config/turbine_checks.xml: Turbine Checks.
  • *
  • config/avalon_checks.xml: Avalon Checks.
  • *
  • config/maven_checks.xml: Maven Source Checks.
  • *
* * @parameter expression="${checkstyle.config.location}" * default-value="config/sun_checks.xml" */ private String configLocation; /** * Specifies what predefined check set to use. Available sets are "sun" (for * the Sun coding conventions), "turbine", and "avalon". * * @parameter default-value="sun" * @deprecated Use configLocation instead. */ private String format; /** *

* Specifies the location of the properties file. *

* *

* This parameter is resolved as URL, File then resource. If successfully * resolved, the contents of the properties location is copied into the * ${project.build.directory}/checkstyle-checker.properties * file before being passed to Checkstyle for loading. *

* *

* The contents of the propertiesLocation will be made * available to Checkstyle for specifying values for parameters within the * xml configuration (specified in the configLocation * parameter). *

* * @parameter expression="${checkstyle.properties.location}" * @since 2.0-beta-2 */ private String propertiesLocation; /** * Specifies the location of the Checkstyle properties file that will be used to * check the source. * * @parameter * @deprecated Use propertiesLocation instead. */ private File propertiesFile; /** * Specifies the URL of the Checkstyle properties that will be used to check * the source. * * @parameter * @deprecated Use propertiesLocation instead. */ private URL propertiesURL; /** * Allows for specifying raw property expansion information. * * @parameter */ private String propertyExpansion; /** *

* Specifies the location of the License file (a.k.a. the header file) that * can be used by Checkstyle to verify that source code has the correct * license header. *

*

* You need to use ${checkstyle.header.file} in your Checkstyle xml * configuration to reference the name of this header file. *

*

* For instance: *

*

* * <module name="RegexpHeader"> * <property name="headerFile" value="${checkstyle.header.file}"/> * </module> * *

* * @parameter expression="${checkstyle.header.file}" default-value="LICENSE.txt" * @since 2.0-beta-2 */ private String headerLocation; /** * Specifies the location of the License file (a.k.a. the header file) that * is used by Checkstyle to verify that source code has the correct * license header. * * @parameter expression="${basedir}/LICENSE.txt" * @deprecated Use headerLocation instead. */ private File headerFile; /** * Specifies the cache file used to speed up Checkstyle on successive runs. * * @parameter default-value="${project.build.directory}/checkstyle-cachefile" */ private String cacheFile; /** * If null, the Checkstyle plugin will display violations on stdout. * Otherwise, a text file will be created with the violations. * * @parameter */ private File useFile; /** * SiteTool. * * @since 2.2 * @component role="org.apache.maven.doxia.tools.SiteTool" * @required * @readonly */ protected SiteTool siteTool; /** *

* Specifies the location of the suppressions XML file to use. *

* *

* This parameter is resolved as resource, URL, then file. If successfully * resolved, the contents of the suppressions XML is copied into the * ${project.build.directory}/checkstyle-supressions.xml file * before being passed to Checkstyle for loading. *

* *

* See suppressionsFileExpression for the property that will * be made available to your checkstyle configuration. *

* * @parameter expression="${checkstyle.suppressions.location}" * @since 2.0-beta-2 */ private String suppressionsLocation; /** * The key to be used in the properties for the suppressions file. * * @parameter expression="${checkstyle.suppression.expression}" * default-value="checkstyle.suppressions.file" * @since 2.1 */ private String suppressionsFileExpression; /** * Specifies the location of the suppressions XML file to use. The plugin * defines a Checkstyle property named * checkstyle.suppressions.file with the value of this * property. This allows using the Checkstyle property in your own custom * checkstyle configuration file when specifying a suppressions file. * * @parameter * @deprecated Use suppressionsLocation instead. */ private String suppressionsFile; /** * Specifies the path and filename to save the checkstyle output. The format * of the output file is determined by the outputFileFormat * parameter. * * @parameter expression="${checkstyle.output.file}" * default-value="${project.build.directory}/checkstyle-result.xml" */ private File outputFile; /** * Specifies the format of the output to be used when writing to the output * file. Valid values are "plain" and "xml". * * @parameter expression="${checkstyle.output.format}" default-value="xml" */ private String outputFileFormat; /** *

* Specifies the location of the package names XML to be used to configure * the Checkstyle Packages. *

* *

* This parameter is resolved as resource, URL, then file. If resolved to a * resource, or a URL, the contents of the package names XML is copied into * the ${project.build.directory}/checkstyle-packagenames.xml * file before being passed to Checkstyle for loading. *

* * @parameter * @since 2.0-beta-2 */ private String packageNamesLocation; /** * Specifies the location of the package names XML to be used to configure * Checkstyle. * * @parameter * @deprecated Use packageNamesLocation instead. */ private String packageNamesFile; /** * Specifies if the build should fail upon a violation. * * @parameter default-value="false" */ private boolean failsOnError; /** * Specifies the location of the source directory to be used for Checkstyle. * * @parameter default-value="${project.build.sourceDirectory}" * @required */ private File sourceDirectory; /** * Specifies the location of the test source directory to be used for * Checkstyle. * * @parameter default-value="${project.build.testSourceDirectory}" * @since 2.2 */ private File testSourceDirectory; /** * Include or not the test source directory to be used for Checkstyle. * * @parameter default-value="${false}" * @since 2.2 */ private boolean includeTestSourceDirectory; /** * The Maven Project Object. * * @parameter default-value="${project}" * @required * @readonly */ private MavenProject project; /** * Output errors to console. * * @parameter default-value="false" */ private boolean consoleOutput; /** * Link the violation line numbers to the source xref. Will link * automatically if Maven JXR plugin is being used. * * @parameter expression="${linkXRef}" default-value="true" * @since 2.1 */ private boolean linkXRef; /** * Location of the Xrefs to link to. * * @parameter default-value="${project.reporting.outputDirectory}/xref" */ private File xrefLocation; /** * The file encoding to use when reading the source files. If the property project.build.sourceEncoding * is not set, the platform default encoding is used. Note: This parameter always overrides the * property charset from Checkstyle's TreeWalker module. * * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}" * @since 2.2 */ private String encoding; /** * @component * @required * @readonly */ private Renderer siteRenderer; private ByteArrayOutputStream stringOutputStream; /** * @component * @required * @readonly */ private ResourceManager locator; /** * CheckstyleRssGenerator. * * @since 2.4 * @component role="org.apache.maven.plugin.checkstyle.rss.CheckstyleRssGenerator" role-hint="default" * @required * @readonly */ protected CheckstyleRssGenerator checkstyleRssGenerator; /** * @since 2.5 * @component role="org.apache.maven.plugin.checkstyle.CheckstyleExecutor" role-hint="default" * @required * @readonly */ protected CheckstyleExecutor checkstyleExecutor; /** {@inheritDoc} */ public String getName( Locale locale ) { return getBundle( locale ).getString( "report.checkstyle.name" ); } /** {@inheritDoc} */ public String getDescription( Locale locale ) { return getBundle( locale ).getString( "report.checkstyle.description" ); } /** {@inheritDoc} */ protected String getOutputDirectory() { return outputDirectory.getAbsolutePath(); } /** {@inheritDoc} */ protected MavenProject getProject() { return project; } /** {@inheritDoc} */ protected Renderer getSiteRenderer() { return siteRenderer; } /** {@inheritDoc} */ public void executeReport( Locale locale ) throws MavenReportException { if ( !skip ) { mergeDeprecatedInfo(); locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() ); locator.addSearchPath( "url", "" ); locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) ); if ( !canGenerateReport() ) { getLog().info( "Source directory does not exist - skipping report." ); return; } // for when we start using maven-shared-io and // maven-shared-monitor... // locator = new Locator( new MojoLogMonitorAdaptor( getLog() ) ); // locator = new Locator( getLog(), new File( // project.getBuild().getDirectory() ) ); ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); try { CheckstyleExecutorRequest request = new CheckstyleExecutorRequest(); request.setConsoleListener( getConsoleListener() ).setConsoleOutput( consoleOutput ) .setExcludes( excludes ).setFailsOnError( failsOnError ).setIncludes( includes ) .setIncludeTestSourceDirectory( includeTestSourceDirectory ).setListener( getListener() ) .setLog( getLog() ).setProject( project ).setSourceDirectory( sourceDirectory ) .setStringOutputStream( stringOutputStream ).setSuppressionsLocation( suppressionsLocation ) .setTestSourceDirectory( testSourceDirectory ).setConfigLocation( configLocation ) .setPropertyExpansion( propertyExpansion ).setHeaderLocation( headerLocation ) .setCacheFile( cacheFile ).setSuppressionsFileExpression( suppressionsFileExpression ) .setEncoding( encoding ).setPropertiesLocation( propertiesLocation ); CheckstyleResults results = checkstyleExecutor.executeCheckstyle( request ); ResourceBundle bundle = getBundle( locale ); generateReportStatics(); generateMainReport( results, bundle ); if ( enableRSS ) { CheckstyleRssGeneratorRequest checkstyleRssGeneratorRequest = new CheckstyleRssGeneratorRequest( this.project, this.getCopyright(), outputDirectory, getLog() ); checkstyleRssGenerator.generateRSS( results, checkstyleRssGeneratorRequest ); } } catch ( CheckstyleException e ) { throw new MavenReportException( "Failed during checkstyle configuration", e ); } catch (CheckstyleExecutorException e) { throw new MavenReportException( "Failed during checkstyle execution", e ); } finally { //be sure to restore original context classloader Thread.currentThread().setContextClassLoader( currentClassLoader ); } } } private void generateReportStatics() throws MavenReportException { ReportResource rresource = new ReportResource( PLUGIN_RESOURCES, outputDirectory ); try { rresource.copy( "images/rss.png" ); } catch ( IOException e ) { throw new MavenReportException( "Unable to copy static resources.", e ); } } private String getCopyright() { String copyright; int currentYear = Calendar.getInstance().get( Calendar.YEAR ); if ( StringUtils.isNotEmpty( project.getInceptionYear() ) && !String.valueOf( currentYear ).equals( project.getInceptionYear() ) ) { copyright = project.getInceptionYear() + " - " + currentYear; } else { copyright = String.valueOf( currentYear ); } if ( ( project.getOrganization() != null ) && StringUtils.isNotEmpty( project.getOrganization().getName() ) ) { copyright = copyright + " " + project.getOrganization().getName(); } return copyright; } private void generateMainReport( CheckstyleResults results, ResourceBundle bundle ) { CheckstyleReportGenerator generator = new CheckstyleReportGenerator( getSink(), bundle, project.getBasedir(), siteTool ); generator.setLog( getLog() ); generator.setEnableRulesSummary( enableRulesSummary ); generator.setEnableSeveritySummary( enableSeveritySummary ); generator.setEnableFilesSummary( enableFilesSummary ); generator.setEnableRSS( enableRSS ); generator.setCheckstyleConfig( results.getConfiguration() ); if ( linkXRef ) { String relativePath = PathTool.getRelativePath( getOutputDirectory(), xrefLocation.getAbsolutePath() ); if ( StringUtils.isEmpty( relativePath ) ) { relativePath = "."; } relativePath = relativePath + "/" + xrefLocation.getName(); if ( xrefLocation.exists() ) { // XRef was already generated by manual execution of a lifecycle // binding generator.setXrefLocation( relativePath ); } else { // Not yet generated - check if the report is on its way for ( Iterator reports = getProject().getReportPlugins().iterator(); reports.hasNext(); ) { ReportPlugin report = reports.next(); String artifactId = report.getArtifactId(); if ( "maven-jxr-plugin".equals( artifactId ) || "jxr-maven-plugin".equals( artifactId ) ) { generator.setXrefLocation( relativePath ); } } } if ( generator.getXrefLocation() == null ) { getLog().warn( "Unable to locate Source XRef to link to - DISABLED" ); } } generator.generateReport( results ); } /** * Merge in the deprecated parameters to the new ones, unless the new * parameters have values. * * @deprecated Remove when deprecated params are removed. */ private void mergeDeprecatedInfo() { if ( "config/sun_checks.xml".equals( configLocation ) && !"sun".equals( format ) ) { configLocation = (String) FORMAT_TO_CONFIG_LOCATION.get( format ); } if ( StringUtils.isEmpty( propertiesLocation ) ) { if ( propertiesFile != null ) { propertiesLocation = propertiesFile.getPath(); } else if ( propertiesURL != null ) { propertiesLocation = propertiesURL.toExternalForm(); } } if ( "LICENSE.txt".equals( headerLocation ) ) { File defaultHeaderFile = new File( project.getBasedir(), "LICENSE.txt" ); if ( !defaultHeaderFile.equals( headerFile ) ) { headerLocation = headerFile.getPath(); } } if ( StringUtils.isEmpty( suppressionsLocation ) ) { suppressionsLocation = suppressionsFile; } if ( StringUtils.isEmpty( packageNamesLocation ) ) { packageNamesLocation = packageNamesFile; } } /** {@inheritDoc} */ public String getOutputName() { return "checkstyle"; } private AuditListener getListener() throws MavenReportException { AuditListener listener = null; if ( StringUtils.isNotEmpty( outputFileFormat ) ) { File resultFile = outputFile; OutputStream out = getOutputStream( resultFile ); if ( "xml".equals( outputFileFormat ) ) { listener = new XMLLogger( out, true ); } else if ( "plain".equals( outputFileFormat ) ) { listener = new DefaultLogger( out, true ); } else { // TODO: failure if not a report throw new MavenReportException( "Invalid output file format: (" + outputFileFormat + "). Must be 'plain' or 'xml'." ); } } return listener; } private OutputStream getOutputStream( File file ) throws MavenReportException { File parentFile = file.getAbsoluteFile().getParentFile(); if ( !parentFile.exists() ) { parentFile.mkdirs(); } FileOutputStream fileOutputStream; try { fileOutputStream = new FileOutputStream( file ); } catch ( FileNotFoundException e ) { throw new MavenReportException( "Unable to create output stream: " + file, e ); } return fileOutputStream; } private DefaultLogger getConsoleListener() throws MavenReportException { DefaultLogger consoleListener; if ( useFile == null ) { stringOutputStream = new ByteArrayOutputStream(); consoleListener = new DefaultLogger( stringOutputStream, false ); } else { OutputStream out = getOutputStream( useFile ); consoleListener = new DefaultLogger( out, true ); } return consoleListener; } private static ResourceBundle getBundle( Locale locale ) { return ResourceBundle.getBundle( "checkstyle-report", locale, CheckstyleReport.class.getClassLoader() ); } /** {@inheritDoc} */ public boolean canGenerateReport() { // TODO: would be good to scan the files here return sourceDirectory.exists(); } /** {@inheritDoc} */ public void setReportOutputDirectory( File reportOutputDirectory ) { super.setReportOutputDirectory( reportOutputDirectory ); this.outputDirectory = reportOutputDirectory; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy