Coverage Report - org.apache.maven.plugin.pmd.AbstractPmdViolationCheckMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractPmdViolationCheckMojo
90 %
76/84
83 %
43/52
4,857
 
 1  
 package org.apache.maven.plugin.pmd;
 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.File;
 23  
 import java.io.IOException;
 24  
 import java.io.Reader;
 25  
 import java.util.ArrayList;
 26  
 import java.util.HashMap;
 27  
 import java.util.Iterator;
 28  
 import java.util.List;
 29  
 import java.util.Map;
 30  
 
 31  
 import org.apache.maven.plugin.AbstractMojo;
 32  
 import org.apache.maven.plugin.MojoExecutionException;
 33  
 import org.apache.maven.plugin.MojoFailureException;
 34  
 import org.apache.maven.project.MavenProject;
 35  
 import org.codehaus.plexus.util.IOUtil;
 36  
 import org.codehaus.plexus.util.ReaderFactory;
 37  
 import org.codehaus.plexus.util.StringUtils;
 38  
 import org.codehaus.plexus.util.xml.pull.MXParser;
 39  
 import org.codehaus.plexus.util.xml.pull.XmlPullParser;
 40  
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 41  
 
 42  
 /**
 43  
  * Base class for mojos that check if there were any PMD violations.
 44  
  *
 45  
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 46  
  * @version $Id: org.apache.maven.plugin.pmd.AbstractPmdViolationCheckMojo.html 816688 2012-05-08 15:14:44Z hboutemy $
 47  
  */
 48  16
 public abstract class AbstractPmdViolationCheckMojo
 49  
     extends AbstractMojo
 50  
 {
 51  2
     private static final Boolean FAILURES_KEY = Boolean.TRUE;
 52  
 
 53  2
     private static final Boolean WARNINGS_KEY = Boolean.FALSE;
 54  
 
 55  
     /**
 56  
      * The location of the XML report to check, as generated by the PMD report.
 57  
      *
 58  
      * @parameter expression="${project.build.directory}"
 59  
      * @required
 60  
      */
 61  
     private File targetDirectory;
 62  
 
 63  
     /**
 64  
      * Whether to fail the build if the validation check fails.
 65  
      *
 66  
      * @parameter expression="${pmd.failOnViolation}" default-value="true"
 67  
      * @required
 68  
      */
 69  
     private boolean failOnViolation;
 70  
 
 71  
     /**
 72  
      * The project language, for determining whether to run the report.
 73  
      *
 74  
      * @parameter expression="${project.artifact.artifactHandler.language}"
 75  
      * @required
 76  
      * @readonly
 77  
      */
 78  
     private String language;
 79  
 
 80  
     /**
 81  
      * Whether to build an aggregated report at the root, or build individual reports.
 82  
      *
 83  
      * @parameter expression="${aggregate}" default-value="false"
 84  
      * @since 2.2
 85  
      */
 86  
     protected boolean aggregate;
 87  
 
 88  
     /**
 89  
      * Print details of check failures to build output.
 90  
      *
 91  
      * @parameter expression="${pmd.verbose}" default-value="false"
 92  
      */
 93  
     private boolean verbose;
 94  
 
 95  
     /**
 96  
      * The project to analyze.
 97  
      *
 98  
      * @parameter expression="${project}"
 99  
      * @required
 100  
      * @readonly
 101  
      */
 102  
     protected MavenProject project;
 103  
 
 104  
     protected void executeCheck( String filename, String tagName, String key, int failurePriority )
 105  
         throws MojoFailureException, MojoExecutionException
 106  
     {
 107  8
         if ( aggregate && !project.isExecutionRoot() )
 108  
         {
 109  0
             return;
 110  
         }
 111  
 
 112  8
         if ( "java".equals( language ) || aggregate )
 113  
         {
 114  8
             File outputFile = new File( targetDirectory, filename );
 115  
 
 116  8
             if ( outputFile.exists() )
 117  
             {
 118  8
                 Reader reader = null;
 119  
                 try
 120  
                 {
 121  8
                     XmlPullParser xpp = new MXParser();
 122  8
                     reader = ReaderFactory.newXmlReader( outputFile );
 123  8
                     xpp.setInput( reader );
 124  
 
 125  8
                     Map violations = getViolations( xpp, tagName, failurePriority );
 126  
 
 127  8
                     List failures = (List) violations.get( FAILURES_KEY );
 128  8
                     List warnings = (List) violations.get( WARNINGS_KEY );
 129  
 
 130  8
                     if ( verbose )
 131  
                     {
 132  2
                         printErrors( failures, warnings );
 133  
                     }
 134  
 
 135  8
                     int failureCount = failures.size();
 136  8
                     int warningCount = warnings.size();
 137  
 
 138  8
                     String message = getMessage( failureCount, warningCount, key, outputFile );
 139  
 
 140  8
                     if ( failureCount > 0 && failOnViolation )
 141  
                     {
 142  2
                         throw new MojoFailureException( message );
 143  
                     }
 144  
 
 145  6
                     this.getLog().info( message );
 146  
                 }
 147  0
                 catch ( IOException e )
 148  
                 {
 149  0
                     throw new MojoExecutionException(
 150  
                                                       "Unable to read PMD results xml: " + outputFile.getAbsolutePath(),
 151  
                                                       e );
 152  
                 }
 153  0
                 catch ( XmlPullParserException e )
 154  
                 {
 155  0
                     throw new MojoExecutionException(
 156  
                                                       "Unable to read PMD results xml: " + outputFile.getAbsolutePath(),
 157  
                                                       e );
 158  
                 }
 159  
                 finally
 160  
                 {
 161  8
                     IOUtil.close( reader );
 162  6
                 }
 163  6
             }
 164  
             else
 165  
             {
 166  0
                 throw new MojoFailureException( "Unable to perform check, " + "unable to find " + outputFile );
 167  
             }
 168  
         }
 169  6
     }
 170  
 
 171  
     /**
 172  
      * Method for collecting the violations found by the PMD tool
 173  
      *
 174  
      * @param xpp
 175  
      *            the xml parser object
 176  
      * @param tagName
 177  
      *            the element that will be checked
 178  
      * @return an int that specifies the number of violations found
 179  
      * @throws XmlPullParserException
 180  
      * @throws IOException
 181  
      */
 182  
     private Map getViolations( XmlPullParser xpp, String tagName, int failurePriority )
 183  
         throws XmlPullParserException, IOException
 184  
     {
 185  8
         int eventType = xpp.getEventType();
 186  
 
 187  8
         List failures = new ArrayList();
 188  8
         List warnings = new ArrayList();
 189  
 
 190  8
         String fullpath = null;
 191  
 
 192  224
         while ( eventType != XmlPullParser.END_DOCUMENT )
 193  
         {
 194  216
             if ( eventType == XmlPullParser.START_TAG && "file".equals( xpp.getName() ) )
 195  
             {
 196  18
                 fullpath = xpp.getAttributeValue( "", "name" );
 197  
             }
 198  216
             if ( eventType == XmlPullParser.START_TAG && tagName.equals( xpp.getName() ) )
 199  
             {
 200  38
                 Map details = getErrorDetails( xpp );
 201  
 
 202  38
                 if ( fullpath != null )
 203  
                 {
 204  36
                     details.put( "filename", getFilename( fullpath, (String) details.get( "package" ) ) );
 205  
                 }
 206  
 
 207  
                 try
 208  
                 {
 209  38
                     int priority = Integer.parseInt( (String) details.get( "priority" ) );
 210  36
                     if ( priority <= failurePriority )
 211  
                     {
 212  10
                         failures.add( details );
 213  
                     }
 214  
                     else
 215  
                     {
 216  26
                         warnings.add( details );
 217  
                     }
 218  
                 }
 219  2
                 catch ( NumberFormatException e )
 220  
                 {
 221  
                     // I don't know what priority this is. Treat it like a
 222  
                     // failure
 223  2
                     failures.add( details );
 224  
                 }
 225  0
                 catch ( NullPointerException e )
 226  
                 {
 227  
                     // I don't know what priority this is. Treat it like a
 228  
                     // failure
 229  0
                     failures.add( details );
 230  38
                 }
 231  
 
 232  
             }
 233  
 
 234  216
             eventType = xpp.next();
 235  
         }
 236  
 
 237  8
         HashMap map = new HashMap( 2 );
 238  8
         map.put( FAILURES_KEY, failures );
 239  8
         map.put( WARNINGS_KEY, warnings );
 240  8
         return map;
 241  
     }
 242  
 
 243  
     private String getFilename( String fullpath, String pkg )
 244  
     {
 245  36
         int index = fullpath.lastIndexOf( File.separatorChar );
 246  
 
 247  72
         while ( StringUtils.isNotEmpty( pkg ) )
 248  
         {
 249  72
             index = fullpath.substring( 0, index ).lastIndexOf( File.separatorChar );
 250  
 
 251  72
             int dot = pkg.indexOf( '.' );
 252  
 
 253  72
             if ( dot < 0 )
 254  
             {
 255  36
                 break;
 256  
             }
 257  36
             pkg = pkg.substring( dot + 1 );
 258  36
         }
 259  
 
 260  36
         return fullpath.substring( index + 1 );
 261  
     }
 262  
 
 263  
     /**
 264  
      * Prints the warnings and failures
 265  
      *
 266  
      * @param failures
 267  
      *            list of failures
 268  
      * @param warnings
 269  
      *            list of warnings
 270  
      */
 271  
     protected void printErrors( List failures, List warnings )
 272  
     {
 273  2
         Iterator iter = warnings.iterator();
 274  4
         while ( iter.hasNext() )
 275  
         {
 276  2
             printError( (Map) iter.next(), "Warning" );
 277  
         }
 278  
 
 279  2
         iter = failures.iterator();
 280  12
         while ( iter.hasNext() )
 281  
         {
 282  10
             printError( (Map) iter.next(), "Failure" );
 283  
         }
 284  2
     }
 285  
 
 286  
     /**
 287  
      * Gets the output message
 288  
      *
 289  
      * @param failureCount
 290  
      * @param warningCount
 291  
      * @param key
 292  
      * @param outputFile
 293  
      * @return
 294  
      */
 295  
     private String getMessage( int failureCount, int warningCount, String key, File outputFile )
 296  
     {
 297  8
         StringBuffer message = new StringBuffer();
 298  8
         if ( failureCount > 0 || warningCount > 0 )
 299  
         {
 300  8
             if ( failureCount > 0 )
 301  
             {
 302  4
                 message.append( "You have " + failureCount + " " + key + ( failureCount > 1 ? "s" : "" ) );
 303  
             }
 304  
 
 305  8
             if ( warningCount > 0 )
 306  
             {
 307  6
                 if ( failureCount > 0 )
 308  
                 {
 309  2
                     message.append( " and " );
 310  
                 }
 311  
                 else
 312  
                 {
 313  4
                     message.append( "You have " );
 314  
                 }
 315  6
                 message.append( warningCount + " warning" + ( warningCount > 1 ? "s" : "" ) );
 316  
             }
 317  
 
 318  8
             message.append( ". For more details see:" + outputFile.getAbsolutePath() );
 319  
         }
 320  8
         return message.toString();
 321  
     }
 322  
 
 323  
     /**
 324  
      * Formats the failure details and prints them as an INFO message
 325  
      *
 326  
      * @param item
 327  
      */
 328  
     protected abstract void printError( Map item, String severity );
 329  
 
 330  
     /**
 331  
      * Gets the attributes and text for the violation tag and puts them in a
 332  
      * HashMap
 333  
      *
 334  
      * @param xpp
 335  
      * @throws XmlPullParserException
 336  
      * @throws IOException
 337  
      */
 338  
     protected abstract Map getErrorDetails( XmlPullParser xpp )
 339  
         throws XmlPullParserException, IOException;
 340  
 }