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