Coverage Report - org.apache.maven.plugin.checkstyle.AbstractCheckstyleReport
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractCheckstyleReport
83%
75/90
58%
20/34
2,733
 
 1  
 package org.apache.maven.plugin.checkstyle;
 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.ByteArrayOutputStream;
 23  
 import java.io.File;
 24  
 import java.io.FileNotFoundException;
 25  
 import java.io.FileOutputStream;
 26  
 import java.io.IOException;
 27  
 import java.io.OutputStream;
 28  
 import java.util.Calendar;
 29  
 import java.util.Iterator;
 30  
 import java.util.Locale;
 31  
 import java.util.ResourceBundle;
 32  
 
 33  
 import org.apache.maven.doxia.siterenderer.Renderer;
 34  
 import org.apache.maven.doxia.tools.SiteTool;
 35  
 import org.apache.maven.model.ReportPlugin;
 36  
 import org.apache.maven.plugin.checkstyle.rss.CheckstyleRssGenerator;
 37  
 import org.apache.maven.plugin.checkstyle.rss.CheckstyleRssGeneratorRequest;
 38  
 import org.apache.maven.project.MavenProject;
 39  
 import org.apache.maven.reporting.AbstractMavenReport;
 40  
 import org.apache.maven.reporting.MavenReportException;
 41  
 import org.codehaus.plexus.resource.ResourceManager;
 42  
 import org.codehaus.plexus.resource.loader.FileResourceLoader;
 43  
 import org.codehaus.plexus.util.PathTool;
 44  
 import org.codehaus.plexus.util.StringUtils;
 45  
 
 46  
 import com.puppycrawl.tools.checkstyle.DefaultLogger;
 47  
 import com.puppycrawl.tools.checkstyle.XMLLogger;
 48  
 import com.puppycrawl.tools.checkstyle.api.AuditListener;
 49  
 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
 50  
 
 51  
 /**
 52  
  * Base abstract class for Checkstyle reports.
 53  
  *
 54  
  * @version $Id$
 55  
  * @since 2.8
 56  
  */
 57  11
 public abstract class AbstractCheckstyleReport
 58  
     extends AbstractMavenReport
 59  
 {
 60  
     public static final String PLUGIN_RESOURCES = "org/apache/maven/plugin/checkstyle";
 61  
 
 62  
     /**
 63  
      * Skip entire check.
 64  
      *
 65  
      * @parameter expression="${checkstyle.skip}" default-value="false"
 66  
      * @since 2.2
 67  
      */
 68  
     protected boolean skip;
 69  
 
 70  
     /**
 71  
      * The output directory for the report. Note that this parameter is only
 72  
      * evaluated if the goal is run directly from the command line. If the goal
 73  
      * is run indirectly as part of a site generation, the output directory
 74  
      * configured in Maven Site Plugin is used instead.
 75  
      *
 76  
      * @parameter default-value="${project.reporting.outputDirectory}"
 77  
      * @required
 78  
      */
 79  
     private File outputDirectory;
 80  
 
 81  
     /**
 82  
      * Specifies the path and filename to save the checkstyle output. The format
 83  
      * of the output file is determined by the <code>outputFileFormat</code>
 84  
      * parameter.
 85  
      *
 86  
      * @parameter expression="${checkstyle.output.file}"
 87  
      *            default-value="${project.build.directory}/checkstyle-result.xml"
 88  
      */
 89  
     private File outputFile;
 90  
 
 91  
     /**
 92  
      * If <code>null</code>, the Checkstyle plugin will display violations on stdout.
 93  
      * Otherwise, a text file will be created with the violations.
 94  
      *
 95  
      * @parameter
 96  
      */
 97  
     private File useFile;
 98  
 
 99  
     /**
 100  
      * Specifies the format of the output to be used when writing to the output
 101  
      * file. Valid values are "plain" and "xml".
 102  
      *
 103  
      * @parameter expression="${checkstyle.output.format}" default-value="xml"
 104  
      */
 105  
     private String outputFileFormat;
 106  
 
 107  
     /**
 108  
      * Specifies if the Rules summary should be enabled or not.
 109  
      *
 110  
      * @parameter expression="${checkstyle.enable.rules.summary}"
 111  
      *            default-value="true"
 112  
      */
 113  
     private boolean enableRulesSummary;
 114  
 
 115  
     /**
 116  
      * Specifies if the Severity summary should be enabled or not.
 117  
      *
 118  
      * @parameter expression="${checkstyle.enable.severity.summary}"
 119  
      *            default-value="true"
 120  
      */
 121  
     private boolean enableSeveritySummary;
 122  
 
 123  
     /**
 124  
      * Specifies if the Files summary should be enabled or not.
 125  
      *
 126  
      * @parameter expression="${checkstyle.enable.files.summary}"
 127  
      *            default-value="true"
 128  
      */
 129  
     private boolean enableFilesSummary;
 130  
 
 131  
     /**
 132  
      * Specifies if the RSS should be enabled or not.
 133  
      *
 134  
      * @parameter expression="${checkstyle.enable.rss}" default-value="true"
 135  
      */
 136  
     private boolean enableRSS;
 137  
 
 138  
     /**
 139  
      * SiteTool.
 140  
      *
 141  
      * @since 2.2
 142  
      * @component role="org.apache.maven.doxia.tools.SiteTool"
 143  
      * @required
 144  
      * @readonly
 145  
      */
 146  
     protected SiteTool siteTool;
 147  
 
 148  
     /**
 149  
      * The Maven Project Object.
 150  
      *
 151  
      * @parameter default-value="${project}"
 152  
      * @required
 153  
      * @readonly
 154  
      */
 155  
     protected MavenProject project;
 156  
 
 157  
     /**
 158  
      * Link the violation line numbers to the source xref. Will link
 159  
      * automatically if Maven JXR plugin is being used.
 160  
      *
 161  
      * @parameter expression="${linkXRef}" default-value="true"
 162  
      * @since 2.1
 163  
      */
 164  
     private boolean linkXRef;
 165  
 
 166  
     /**
 167  
      * Location of the Xrefs to link to.
 168  
      *
 169  
      * @parameter default-value="${project.reporting.outputDirectory}/xref"
 170  
      */
 171  
     private File xrefLocation;
 172  
 
 173  
     /**
 174  
      * @component
 175  
      * @required
 176  
      * @readonly
 177  
      */
 178  
     private Renderer siteRenderer;
 179  
 
 180  
     /**
 181  
      * @component
 182  
      * @required
 183  
      * @readonly
 184  
      */
 185  
     protected ResourceManager locator;
 186  
 
 187  
     /**
 188  
      * CheckstyleRssGenerator.
 189  
      *
 190  
      * @since 2.4
 191  
      * @component role="org.apache.maven.plugin.checkstyle.rss.CheckstyleRssGenerator" role-hint="default"
 192  
      * @required
 193  
      * @readonly
 194  
      */
 195  
     protected CheckstyleRssGenerator checkstyleRssGenerator;
 196  
 
 197  
     /**
 198  
      * @since 2.5
 199  
      * @component role="org.apache.maven.plugin.checkstyle.CheckstyleExecutor" role-hint="default"
 200  
      * @required
 201  
      * @readonly
 202  
      */
 203  
     protected CheckstyleExecutor checkstyleExecutor;
 204  
 
 205  
     protected ByteArrayOutputStream stringOutputStream;
 206  
 
 207  
     /** {@inheritDoc} */
 208  
     public String getName( Locale locale )
 209  
     {
 210  2
         return getBundle( locale ).getString( "report.checkstyle.name" );
 211  
     }
 212  
 
 213  
     /** {@inheritDoc} */
 214  
     public String getDescription( Locale locale )
 215  
     {
 216  0
         return getBundle( locale ).getString( "report.checkstyle.description" );
 217  
     }
 218  
 
 219  
     /** {@inheritDoc} */
 220  
     protected String getOutputDirectory()
 221  
     {
 222  42
         return outputDirectory.getAbsolutePath();
 223  
     }
 224  
 
 225  
     /** {@inheritDoc} */
 226  
     protected MavenProject getProject()
 227  
     {
 228  0
         return project;
 229  
     }
 230  
 
 231  
     /** {@inheritDoc} */
 232  
     protected Renderer getSiteRenderer()
 233  
     {
 234  16
         return siteRenderer;
 235  
     }
 236  
 
 237  
     /** {@inheritDoc} */
 238  
     public void executeReport( Locale locale )
 239  
         throws MavenReportException
 240  
     {
 241  18
         locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() );
 242  18
         locator.addSearchPath( "url", "" );
 243  
 
 244  18
         locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) );
 245  
 
 246  
         // for when we start using maven-shared-io and
 247  
         // maven-shared-monitor...
 248  
         // locator = new Locator( new MojoLogMonitorAdaptor( getLog() ) );
 249  
 
 250  
         // locator = new Locator( getLog(), new File(
 251  
         // project.getBuild().getDirectory() ) );
 252  
 
 253  18
         ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
 254  
 
 255  
         try
 256  
         {
 257  18
             CheckstyleExecutorRequest request = createRequest();
 258  
 
 259  18
             CheckstyleResults results = checkstyleExecutor.executeCheckstyle( request );
 260  
 
 261  16
             ResourceBundle bundle = getBundle( locale );
 262  16
             generateReportStatics();
 263  16
             generateMainReport( results, bundle );
 264  16
             if ( enableRSS )
 265  
             {
 266  16
                 CheckstyleRssGeneratorRequest checkstyleRssGeneratorRequest =
 267  
                     new CheckstyleRssGeneratorRequest( this.project, this.getCopyright(), outputDirectory, getLog() );
 268  16
                 checkstyleRssGenerator.generateRSS( results, checkstyleRssGeneratorRequest );
 269  
             }
 270  
 
 271  
         }
 272  0
         catch ( CheckstyleException e )
 273  
         {
 274  0
             throw new MavenReportException( "Failed during checkstyle configuration", e );
 275  
         }
 276  2
         catch ( CheckstyleExecutorException e )
 277  
         {
 278  2
             throw new MavenReportException( "Failed during checkstyle execution", e );
 279  
         }
 280  
         finally
 281  
         {
 282  
             //be sure to restore original context classloader
 283  18
             Thread.currentThread().setContextClassLoader( currentClassLoader );
 284  16
         }
 285  16
     }
 286  
 
 287  
     /**
 288  
      * Create the Checkstyle executor request.
 289  
      *
 290  
      * @return The executor request.
 291  
      * @throws MavenReportException If something goes wrong during creation.
 292  
      */
 293  
     protected abstract CheckstyleExecutorRequest createRequest()
 294  
             throws MavenReportException;
 295  
 
 296  
     /**
 297  
      * Creates and returns the report generation listener.
 298  
      *
 299  
      * @return The audit listener.
 300  
      * @throws MavenReportException If something goes wrong.
 301  
      */
 302  
     protected AuditListener getListener()
 303  
         throws MavenReportException
 304  
     {
 305  18
         AuditListener listener = null;
 306  
 
 307  18
         if ( StringUtils.isNotEmpty( outputFileFormat ) )
 308  
         {
 309  18
             File resultFile = outputFile;
 310  
 
 311  18
             OutputStream out = getOutputStream( resultFile );
 312  
 
 313  18
             if ( "xml".equals( outputFileFormat ) )
 314  
             {
 315  16
                 listener = new XMLLogger( out, true );
 316  
             }
 317  2
             else if ( "plain".equals( outputFileFormat ) )
 318  
             {
 319  2
                 listener = new DefaultLogger( out, true );
 320  
             }
 321  
             else
 322  
             {
 323  
                 // TODO: failure if not a report
 324  0
                 throw new MavenReportException( "Invalid output file format: (" + outputFileFormat
 325  
                     + "). Must be 'plain' or 'xml'." );
 326  
             }
 327  
         }
 328  
 
 329  18
         return listener;
 330  
     }
 331  
 
 332  
     private OutputStream getOutputStream( File file )
 333  
         throws MavenReportException
 334  
     {
 335  20
         File parentFile = file.getAbsoluteFile().getParentFile();
 336  
 
 337  20
         if ( !parentFile.exists() )
 338  
         {
 339  0
             parentFile.mkdirs();
 340  
         }
 341  
 
 342  
         FileOutputStream fileOutputStream;
 343  
         try
 344  
         {
 345  20
             fileOutputStream = new FileOutputStream( file );
 346  
         }
 347  0
         catch ( FileNotFoundException e )
 348  
         {
 349  0
             throw new MavenReportException( "Unable to create output stream: " + file, e );
 350  20
         }
 351  20
         return fileOutputStream;
 352  
     }
 353  
 
 354  
     /**
 355  
      * Creates and returns the console listener.
 356  
      *
 357  
      * @return The console listener.
 358  
      * @throws MavenReportException If something goes wrong.
 359  
      */
 360  
     protected DefaultLogger getConsoleListener()
 361  
         throws MavenReportException
 362  
     {
 363  
         DefaultLogger consoleListener;
 364  
 
 365  18
         if ( useFile == null )
 366  
         {
 367  16
             stringOutputStream = new ByteArrayOutputStream();
 368  16
             consoleListener = new DefaultLogger( stringOutputStream, false );
 369  
         }
 370  
         else
 371  
         {
 372  2
             OutputStream out = getOutputStream( useFile );
 373  
 
 374  2
             consoleListener = new DefaultLogger( out, true );
 375  
         }
 376  
 
 377  18
         return consoleListener;
 378  
     }
 379  
 
 380  
     private void generateReportStatics()
 381  
         throws MavenReportException
 382  
     {
 383  16
         ReportResource rresource = new ReportResource( PLUGIN_RESOURCES, outputDirectory );
 384  
         try
 385  
         {
 386  16
             rresource.copy( "images/rss.png" );
 387  
         }
 388  0
         catch ( IOException e )
 389  
         {
 390  0
             throw new MavenReportException( "Unable to copy static resources.", e );
 391  16
         }
 392  16
     }
 393  
 
 394  
 
 395  
     private String getCopyright()
 396  
     {
 397  
         String copyright;
 398  16
         int currentYear = Calendar.getInstance().get( Calendar.YEAR );
 399  16
         if ( StringUtils.isNotEmpty( project.getInceptionYear() )
 400  
             && !String.valueOf( currentYear ).equals( project.getInceptionYear() ) )
 401  
         {
 402  16
             copyright = project.getInceptionYear() + " - " + currentYear;
 403  
         }
 404  
         else
 405  
         {
 406  0
             copyright = String.valueOf( currentYear );
 407  
         }
 408  
 
 409  16
         if ( ( project.getOrganization() != null ) && StringUtils.isNotEmpty( project.getOrganization().getName() ) )
 410  
         {
 411  16
             copyright = copyright + " " + project.getOrganization().getName();
 412  
         }
 413  16
         return copyright;
 414  
     }
 415  
 
 416  
     private void generateMainReport( CheckstyleResults results, ResourceBundle bundle )
 417  
     {
 418  16
         CheckstyleReportGenerator generator =
 419  
             new CheckstyleReportGenerator( getSink(), bundle, project.getBasedir(), siteTool );
 420  
 
 421  16
         generator.setLog( getLog() );
 422  16
         generator.setEnableRulesSummary( enableRulesSummary );
 423  16
         generator.setEnableSeveritySummary( enableSeveritySummary );
 424  16
         generator.setEnableFilesSummary( enableFilesSummary );
 425  16
         generator.setEnableRSS( enableRSS );
 426  16
         generator.setCheckstyleConfig( results.getConfiguration() );
 427  16
         if ( linkXRef )
 428  
         {
 429  16
             String relativePath = PathTool.getRelativePath( getOutputDirectory(), xrefLocation.getAbsolutePath() );
 430  16
             if ( StringUtils.isEmpty( relativePath ) )
 431  
             {
 432  16
                 relativePath = ".";
 433  
             }
 434  16
             relativePath = relativePath + "/" + xrefLocation.getName();
 435  16
             if ( xrefLocation.exists() )
 436  
             {
 437  
                 // XRef was already generated by manual execution of a lifecycle
 438  
                 // binding
 439  2
                 generator.setXrefLocation( relativePath );
 440  
             }
 441  
             else
 442  
             {
 443  
                 // Not yet generated - check if the report is on its way
 444  14
                 for ( Iterator<ReportPlugin> reports = getProject().getReportPlugins().iterator(); reports.hasNext(); )
 445  
                 {
 446  14
                     ReportPlugin report = reports.next();
 447  
 
 448  14
                     String artifactId = report.getArtifactId();
 449  14
                     if ( "maven-jxr-plugin".equals( artifactId ) || "jxr-maven-plugin".equals( artifactId ) )
 450  
                     {
 451  14
                         generator.setXrefLocation( relativePath );
 452  
                     }
 453  14
                 }
 454  
             }
 455  
 
 456  16
             if ( generator.getXrefLocation() == null )
 457  
             {
 458  0
                 getLog().warn( "Unable to locate Source XRef to link to - DISABLED" );
 459  
             }
 460  
         }
 461  16
         generator.generateReport( results );
 462  16
     }
 463  
 
 464  
     private static ResourceBundle getBundle( Locale locale )
 465  
     {
 466  18
         return ResourceBundle.getBundle( "checkstyle-report", locale, AbstractCheckstyleReport.class.getClassLoader() );
 467  
     }
 468  
 
 469  
     /** {@inheritDoc} */
 470  
     public void setReportOutputDirectory( File reportOutputDirectory )
 471  
     {
 472  0
         super.setReportOutputDirectory( reportOutputDirectory );
 473  0
         this.outputDirectory = reportOutputDirectory;
 474  0
     }
 475  
 }