Coverage Report - org.apache.maven.plugin.checkstyle.DefaultCheckstyleExecutor
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultCheckstyleExecutor
0%
0/164
0%
0/106
13.333
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.maven.plugin.checkstyle;
 20  
 
 21  
 import java.io.ByteArrayInputStream;
 22  
 import java.io.File;
 23  
 import java.io.FileInputStream;
 24  
 import java.io.IOException;
 25  
 import java.net.MalformedURLException;
 26  
 import java.net.URL;
 27  
 import java.net.URLClassLoader;
 28  
 import java.util.ArrayList;
 29  
 import java.util.Collections;
 30  
 import java.util.Iterator;
 31  
 import java.util.List;
 32  
 import java.util.Properties;
 33  
 
 34  
 import org.apache.maven.artifact.DependencyResolutionRequiredException;
 35  
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 36  
 import org.codehaus.plexus.resource.ResourceManager;
 37  
 import org.codehaus.plexus.resource.loader.FileResourceCreationException;
 38  
 import org.codehaus.plexus.resource.loader.ResourceNotFoundException;
 39  
 import org.codehaus.plexus.util.FileUtils;
 40  
 import org.codehaus.plexus.util.StringUtils;
 41  
 
 42  
 import com.puppycrawl.tools.checkstyle.Checker;
 43  
 import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
 44  
 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
 45  
 import com.puppycrawl.tools.checkstyle.PackageNamesLoader;
 46  
 import com.puppycrawl.tools.checkstyle.PropertiesExpander;
 47  
 import com.puppycrawl.tools.checkstyle.api.AuditListener;
 48  
 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
 49  
 import com.puppycrawl.tools.checkstyle.api.Configuration;
 50  
 import com.puppycrawl.tools.checkstyle.api.FilterSet;
 51  
 import com.puppycrawl.tools.checkstyle.filters.SuppressionsLoader;
 52  
 
 53  
 /**
 54  
  * @author <a href="mailto:olamy@apache.org">olamy</a>
 55  
  * @plexus.component role="org.apache.maven.plugin.checkstyle.CheckstyleExecutor" role-hint="default"
 56  
  * @since 2.5
 57  
  * @version $Id: org.apache.maven.plugin.checkstyle.DefaultCheckstyleExecutor.html 816658 2012-05-08 13:56:19Z hboutemy $
 58  
  */
 59  0
 public class DefaultCheckstyleExecutor
 60  
     extends AbstractLogEnabled
 61  
     implements CheckstyleExecutor
 62  
 {
 63  
     
 64  
     /**
 65  
      * @plexus.requirement role="org.codehaus.plexus.resource.ResourceManager" role-hint="default"
 66  
      */
 67  
     private ResourceManager locator;    
 68  
     
 69  0
     private static final File[] EMPTY_FILE_ARRAY = new File[0];
 70  
 
 71  
     public CheckstyleResults executeCheckstyle( CheckstyleExecutorRequest request )
 72  
         throws CheckstyleExecutorException, CheckstyleException
 73  
     {
 74  
         // checkstyle will always use the context classloader in order
 75  
         // to load resources (dtds),
 76  
         // so we have to fix it
 77  
         // olamy this hack is not anymore needed in maven 3.x
 78  0
         ClassLoader checkstyleClassLoader = PackageNamesLoader.class.getClassLoader();
 79  0
         Thread.currentThread().setContextClassLoader( checkstyleClassLoader );
 80  
 
 81  0
         if ( getLogger().isDebugEnabled() )
 82  
         {
 83  0
             getLogger().debug( "executeCheckstyle start headerLocation : " + request.getHeaderLocation() );
 84  
         }
 85  0
         locator.setOutputDirectory( new File( request.getProject().getBuild().getDirectory() ) );
 86  
         File[] files;
 87  
         try
 88  
         {
 89  0
             files = getFilesToProcess( request );
 90  
         }
 91  0
         catch ( IOException e )
 92  
         {
 93  0
             throw new CheckstyleExecutorException( "Error getting files to process", e );
 94  0
         }
 95  
 
 96  0
         FilterSet filterSet = getSuppressions( request );
 97  
 
 98  0
         Checker checker = new Checker();
 99  
 
 100  
         // setup classloader, needed to avoid "Unable to get class information
 101  
         // for ..." errors
 102  0
         List classPathStrings = new ArrayList();
 103  0
         List outputDirectories = new ArrayList();
 104  
         try
 105  
         {
 106  0
             classPathStrings = request.getProject().getCompileClasspathElements();
 107  0
             outputDirectories.add( request.getProject().getBuild().getOutputDirectory() );
 108  
 
 109  0
             if ( request.isIncludeTestSourceDirectory() && ( request.getSourceDirectory() != null )
 110  
                 && ( request.getTestSourceDirectory().exists() ) && ( request.getTestSourceDirectory().isDirectory() ) )
 111  
             {
 112  0
                 classPathStrings = request.getProject().getTestClasspathElements();
 113  0
                 outputDirectories.add( request.getProject().getBuild().getTestOutputDirectory() );
 114  
             }
 115  
         }
 116  0
         catch ( DependencyResolutionRequiredException e )
 117  
         {
 118  0
             throw new CheckstyleExecutorException( e.getMessage(), e );
 119  0
         }
 120  
 
 121  0
         if ( classPathStrings == null )
 122  
         {
 123  0
             classPathStrings = Collections.EMPTY_LIST;
 124  
         }
 125  
 
 126  0
         List urls = new ArrayList( classPathStrings.size() );
 127  
 
 128  0
         Iterator iter = classPathStrings.iterator();
 129  0
         while ( iter.hasNext() )
 130  
         {
 131  
             try
 132  
             {
 133  0
                 urls.add( new File( ( (String) iter.next() ) ).toURL() );
 134  
             }
 135  0
             catch ( MalformedURLException e )
 136  
             {
 137  0
                 throw new CheckstyleExecutorException( e.getMessage(), e );
 138  0
             }
 139  
         }
 140  
 
 141  0
         Iterator iterator = outputDirectories.iterator();
 142  0
         while ( iterator.hasNext() )
 143  
         {
 144  
             try
 145  
             {
 146  0
                 String outputDirectoryString = (String) iterator.next();
 147  0
                 if ( outputDirectoryString != null )
 148  
                 {
 149  0
                     File outputDirectoryFile = new File( outputDirectoryString );
 150  0
                     if ( outputDirectoryFile.exists() )
 151  
                     {
 152  0
                         URL outputDirectoryUrl = outputDirectoryFile.toURL();
 153  0
                         request.getLog().debug(
 154  
                                                 "Adding the outputDirectory " + outputDirectoryUrl.toString()
 155  
                                                     + " to the Checkstyle class path" );
 156  0
                         urls.add( outputDirectoryUrl );
 157  
                     }
 158  
                 }
 159  
             }
 160  0
             catch ( MalformedURLException e )
 161  
             {
 162  0
                 throw new CheckstyleExecutorException( e.getMessage(), e );
 163  0
             }
 164  
         }
 165  
 
 166  0
         URLClassLoader projectClassLoader = new URLClassLoader( (URL[]) urls.toArray( new URL[urls.size()] ), null );
 167  0
         checker.setClassloader( projectClassLoader );
 168  
 
 169  0
         checker.setModuleClassLoader( Thread.currentThread().getContextClassLoader() );
 170  
 
 171  0
         if ( filterSet != null )
 172  
         {
 173  0
             checker.addFilter( filterSet );
 174  
         }
 175  0
         Configuration configuration = getConfiguration( request ); 
 176  0
         checker.configure( configuration );
 177  
 
 178  0
         AuditListener listener = request.getListener();
 179  
 
 180  0
         if ( listener != null )
 181  
         {
 182  0
             checker.addListener( listener );
 183  
         }
 184  
 
 185  0
         if ( request.isConsoleOutput() )
 186  
         {
 187  0
             checker.addListener( request.getConsoleListener() );
 188  
         }
 189  
 
 190  0
         CheckstyleReportListener sinkListener = new CheckstyleReportListener( request.getSourceDirectory(), configuration );
 191  0
         if ( request.isIncludeTestSourceDirectory() && ( request.getTestSourceDirectory() != null )
 192  
             && ( request.getTestSourceDirectory().exists() ) && ( request.getTestSourceDirectory().isDirectory() ) )
 193  
         {
 194  0
             sinkListener.addSourceDirectory( request.getTestSourceDirectory() );
 195  
         }
 196  
 
 197  0
         checker.addListener( sinkListener );
 198  
 
 199  0
         ArrayList filesList = new ArrayList();
 200  0
         for ( int i = 0; i < files.length; i++ )
 201  
         {
 202  0
             filesList.add( files[i] );
 203  
         }
 204  0
         int nbErrors = checker.process( filesList );
 205  
 
 206  0
         checker.destroy();
 207  
 
 208  0
         if ( request.getStringOutputStream() != null )
 209  
         {
 210  0
             request.getLog().info( request.getStringOutputStream().toString() );
 211  
         }
 212  
 
 213  0
         if ( request.isFailsOnError() && nbErrors > 0 )
 214  
         {
 215  
             // TODO: should be a failure, not an error. Report is not meant to
 216  
             // throw an exception here (so site would
 217  
             // work regardless of config), but should record this information
 218  0
             throw new CheckstyleExecutorException( "There are " + nbErrors + " checkstyle errors." );
 219  
         }
 220  0
         else if ( nbErrors > 0 )
 221  
         {
 222  0
             request.getLog().info( "There are " + nbErrors + " checkstyle errors." );
 223  
         }
 224  
 
 225  0
         return sinkListener.getResults();
 226  
     }
 227  
 
 228  
     public Configuration getConfiguration( CheckstyleExecutorRequest request )
 229  
         throws CheckstyleExecutorException
 230  
     {
 231  
         try
 232  
         {
 233  
             // checkstyle will always use the context classloader in order
 234  
             // to load resources (dtds),
 235  
             // so we have to fix it
 236  0
             ClassLoader checkstyleClassLoader = PackageNamesLoader.class.getClassLoader();
 237  0
             Thread.currentThread().setContextClassLoader( checkstyleClassLoader );
 238  0
             String configFile = getConfigFile( request );
 239  0
             Properties overridingProperties = getOverridingProperties( request );
 240  0
             Configuration config = ConfigurationLoader
 241  
                 .loadConfiguration( configFile, new PropertiesExpander( overridingProperties ) );
 242  0
             String effectiveEncoding = StringUtils.isNotEmpty( request.getEncoding() ) ? request.getEncoding() : System
 243  
                 .getProperty( "file.encoding", "UTF-8" );
 244  0
             if ( StringUtils.isEmpty( request.getEncoding() ) )
 245  
             {
 246  0
                 request.getLog().warn(
 247  
                                        "File encoding has not been set, using platform encoding " + effectiveEncoding
 248  
                                            + ", i.e. build is platform dependent!" );
 249  
             }
 250  0
             Configuration[] modules = config.getChildren();
 251  0
             for ( int i = 0; i < modules.length; i++ )
 252  
             {
 253  0
                 Configuration module = modules[i];
 254  0
                 if ( "Checker".equals( module.getName() )
 255  
                     || "com.puppycrawl.tools.checkstyle.Checker".equals( module.getName() ) )
 256  
                 {
 257  0
                     if ( module instanceof DefaultConfiguration )
 258  
                     {
 259  0
                         ( (DefaultConfiguration) module ).addAttribute( "charset", effectiveEncoding );
 260  
                     }
 261  
                     else
 262  
                     {
 263  0
                         request.getLog().warn( "Failed to configure file encoding on module " + module );
 264  
                     }
 265  
                 }
 266  0
                 if ( "TreeWalker".equals( module.getName() )
 267  
                     || "com.puppycrawl.tools.checkstyle.TreeWalker".equals( module.getName() ) )
 268  
                 {
 269  0
                     if ( module instanceof DefaultConfiguration )
 270  
                     {
 271  0
                         ( (DefaultConfiguration) module ).addAttribute( "cacheFile", request.getCacheFile() );
 272  
                     }
 273  
                     else
 274  
                     {
 275  0
                         request.getLog().warn( "Failed to configure cache file on module " + module );
 276  
                     }
 277  
                 }
 278  
             }
 279  0
             return config;
 280  
         }
 281  0
         catch ( CheckstyleException e )
 282  
         {
 283  0
             throw new CheckstyleExecutorException( "Failed during checkstyle configuration", e );
 284  
         }
 285  
     }
 286  
 
 287  
     private Properties getOverridingProperties( CheckstyleExecutorRequest request )
 288  
         throws CheckstyleExecutorException
 289  
     {
 290  0
         Properties p = new Properties();
 291  
 
 292  
         try
 293  
         {
 294  0
             if ( request.getPropertiesLocation() != null )
 295  
             {
 296  0
                 if ( getLogger().isDebugEnabled() )
 297  
                 {
 298  0
                     getLogger().debug( "request.getPropertiesLocation() " + request.getPropertiesLocation() );
 299  
                 }                
 300  
                 
 301  0
                 File propertiesFile = locator.getResourceAsFile( request.getPropertiesLocation(),
 302  
                                                                  "checkstyle-checker.properties" );
 303  
 
 304  0
                 if ( propertiesFile != null )
 305  
                 {
 306  0
                     p.load( new FileInputStream( propertiesFile ) );
 307  
                 }
 308  
             }
 309  
 
 310  0
             if ( StringUtils.isNotEmpty( request.getPropertyExpansion() ) )
 311  
             {
 312  0
                 String propertyExpansion = request.getPropertyExpansion();
 313  
                 // Convert \ to \\, so that p.load will convert it back properly
 314  0
                 propertyExpansion = StringUtils.replace( propertyExpansion, "\\", "\\\\" );
 315  0
                 p.load( new ByteArrayInputStream( propertyExpansion.getBytes() ) );
 316  
             }
 317  
 
 318  
             // Workaround for MCHECKSTYLE-48
 319  
             // Make sure that "config/maven-header.txt" is the default value
 320  
             // for headerLocation, if configLocation="config/maven_checks.xml"
 321  0
             String headerLocation = request.getHeaderLocation();
 322  0
             if ( "config/maven_checks.xml".equals( request.getConfigLocation() ) )
 323  
             {
 324  
 
 325  0
                 if ( "LICENSE.txt".equals( request.getHeaderLocation() ) )
 326  
                 {
 327  0
                     headerLocation = "config/maven-header.txt";
 328  
                 }
 329  
             }
 330  0
             if ( getLogger().isDebugEnabled() )
 331  
             {
 332  0
                 getLogger().debug( "headerLocation " + headerLocation );
 333  
             } 
 334  
             
 335  0
             if ( StringUtils.isNotEmpty( headerLocation ) )
 336  
             {
 337  
                 try
 338  
                 {
 339  0
                     File headerFile = locator.getResourceAsFile( headerLocation, "checkstyle-header.txt" );
 340  
 
 341  0
                     if ( headerFile != null )
 342  
                     {
 343  0
                         p.setProperty( "checkstyle.header.file", headerFile.getAbsolutePath() );
 344  
                     }
 345  
                 }
 346  0
                 catch ( FileResourceCreationException e )
 347  
                 {
 348  0
                     throw new CheckstyleExecutorException( "Unable to process header location: " + headerLocation, e );
 349  
                 }
 350  0
                 catch ( ResourceNotFoundException e )
 351  
                 {
 352  0
                     throw new CheckstyleExecutorException( "Unable to process header location: " + headerLocation, e );
 353  0
                 }                
 354  
             }
 355  
 
 356  0
             if ( request.getCacheFile() != null )
 357  
             {
 358  0
                 p.setProperty( "checkstyle.cache.file", request.getCacheFile() );
 359  
             }
 360  
         }
 361  0
         catch ( IOException e )
 362  
         {
 363  0
             throw new CheckstyleExecutorException( "Failed to get overriding properties", e );
 364  
         }
 365  0
         catch ( FileResourceCreationException e )
 366  
         {
 367  0
             throw new CheckstyleExecutorException( "Failed to get overriding properties", e );
 368  
         }
 369  0
         catch ( ResourceNotFoundException e )
 370  
         {
 371  0
             throw new CheckstyleExecutorException( "Failed to get overriding properties", e );
 372  0
         } 
 373  0
         if ( request.getSuppressionsFileExpression() != null )
 374  
         {
 375  0
             String suppresionFile = request.getSuppressionsFileExpression();
 376  
 
 377  0
             if ( suppresionFile != null )
 378  
             {
 379  0
                 p.setProperty( request.getSuppressionsFileExpression(), suppresionFile );
 380  
             }
 381  
         }
 382  
 
 383  0
         return p;
 384  
     }
 385  
 
 386  
     private File[] getFilesToProcess( CheckstyleExecutorRequest request )
 387  
         throws IOException
 388  
     {
 389  0
         StringBuffer excludesStr = new StringBuffer();
 390  
 
 391  0
         if ( StringUtils.isNotEmpty( request.getExcludes() ) )
 392  
         {
 393  0
             excludesStr.append( request.getExcludes() );
 394  
         }
 395  
 
 396  0
         String[] defaultExcludes = FileUtils.getDefaultExcludes();
 397  0
         for ( int i = 0; i < defaultExcludes.length; i++ )
 398  
         {
 399  0
             if ( excludesStr.length() > 0 )
 400  
             {
 401  0
                 excludesStr.append( "," );
 402  
             }
 403  
 
 404  0
             excludesStr.append( defaultExcludes[i] );
 405  
         }
 406  
 
 407  0
         List files = FileUtils.getFiles( request.getSourceDirectory(), request.getIncludes(), excludesStr.toString() );
 408  0
         if ( request.isIncludeTestSourceDirectory() && ( request.getTestSourceDirectory() != null )
 409  
             && ( request.getTestSourceDirectory().exists() ) && ( request.getTestSourceDirectory().isDirectory() ) )
 410  
         {
 411  0
             files.addAll( FileUtils.getFiles( request.getTestSourceDirectory(), request.getIncludes(), excludesStr
 412  
                 .toString() ) );
 413  
         }
 414  
 
 415  0
         return (File[]) files.toArray( EMPTY_FILE_ARRAY );
 416  
     }
 417  
 
 418  
     private FilterSet getSuppressions( CheckstyleExecutorRequest request )
 419  
         throws CheckstyleExecutorException
 420  
     {
 421  
         try
 422  
         {
 423  0
             File suppressionsFile = locator.resolveLocation( request.getSuppressionsLocation(),
 424  
                                                              "checkstyle-suppressions.xml" );
 425  
 
 426  0
             if ( suppressionsFile == null )
 427  
             {
 428  0
                 return null;
 429  
             }
 430  
 
 431  0
             return SuppressionsLoader.loadSuppressions( suppressionsFile.getAbsolutePath() );
 432  
         }
 433  0
         catch ( CheckstyleException ce )
 434  
         {
 435  0
             throw new CheckstyleExecutorException( "failed to load suppressions location: "
 436  
                 + request.getSuppressionsLocation(), ce );
 437  
         }
 438  0
         catch ( IOException e )
 439  
         {
 440  0
             throw new CheckstyleExecutorException( "Failed to process supressions location: "
 441  
                 + request.getSuppressionsLocation(), e );
 442  
         }
 443  
     }
 444  
 
 445  
     private String getConfigFile( CheckstyleExecutorRequest request )
 446  
         throws CheckstyleExecutorException
 447  
     {
 448  
         try
 449  
         {
 450  0
             if ( getLogger().isDebugEnabled() )
 451  
             {
 452  0
                 getLogger().debug( "request.getConfigLocation() " + request.getConfigLocation() );
 453  
             }
 454  
            
 455  0
             File configFile = locator.getResourceAsFile( request.getConfigLocation(), "checkstyle-checker.xml" );
 456  
 
 457  0
             if ( configFile == null )
 458  
             {
 459  0
                 throw new CheckstyleExecutorException( "Unable to process config location: "
 460  
                     + request.getConfigLocation() );
 461  
             }
 462  0
             return configFile.getAbsolutePath();
 463  
         }
 464  0
         catch ( org.codehaus.plexus.resource.loader.ResourceNotFoundException e )
 465  
         {
 466  0
             throw new CheckstyleExecutorException( "Unable to find configuration file at location "
 467  
                 + request.getConfigLocation(), e );
 468  
         }
 469  0
         catch ( FileResourceCreationException e )
 470  
         {
 471  0
             throw new CheckstyleExecutorException( "Unable to process configuration file location "
 472  
                 + request.getConfigLocation(), e );
 473  
         }
 474  
 
 475  
     }
 476  
 }