View Javadoc
1   package org.apache.maven.plugins.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.FileReader;
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.plugin.MojoFailureException;
30  import org.apache.maven.plugins.pmd.model.PmdErrorDetail;
31  import org.apache.maven.plugins.pmd.model.PmdFile;
32  import org.apache.maven.plugins.pmd.model.Violation;
33  import org.apache.maven.plugins.pmd.model.io.xpp3.PmdXpp3Reader;
34  import org.apache.maven.plugins.annotations.Execute;
35  import org.apache.maven.plugins.annotations.LifecyclePhase;
36  import org.apache.maven.plugins.annotations.Mojo;
37  import org.apache.maven.plugins.annotations.Parameter;
38  import org.codehaus.plexus.util.StringUtils;
39  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
40  
41  /**
42   * Fails the build if there were any PMD violations in the source code.
43   *
44   * @version $Id$
45   * @since 2.0
46   */
47  @Mojo( name = "check", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true )
48  @Execute( goal = "pmd" )
49  public class PmdViolationCheckMojo
50      extends AbstractPmdViolationCheckMojo<Violation>
51  {
52      /**
53       * Default constructor. Initializes with the correct {@link ExcludeViolationsFromFile}.
54       */
55      public PmdViolationCheckMojo()
56      {
57          super( new ExcludeViolationsFromFile() );
58      }
59  
60      /**
61       * What priority level to fail the build on.
62       * PMD violations are assigned a priority from 1 (most severe) to 5 (least severe) according the
63       * the rule's priority.
64       * Violations at or less than this priority level are considered failures and will fail
65       * the build if {@code failOnViolation=true} and the count exceeds {@code maxAllowedViolations}.
66       * The other violations will be regarded as warnings and will be displayed in the build output
67       * if {@code verbose=true}.
68       * Setting a value of 5 will treat all violations as failures, which may cause the build to fail.
69       * Setting a value of 1 will treat all violations as warnings.
70       * Only values from 1 to 5 are valid.
71       */
72      @Parameter( property = "pmd.failurePriority", defaultValue = "5", required = true )
73      private int failurePriority = 5;
74  
75      /**
76       * Skip the PMD checks. Most useful on the command line via "-Dpmd.skip=true".
77       */
78      @Parameter( property = "pmd.skip", defaultValue = "false" )
79      private boolean skip;
80  
81      /**
82       * {@inheritDoc}
83       */
84      public void execute()
85          throws MojoExecutionException, MojoFailureException
86      {
87          if ( skip )
88          {
89              getLog().info( "Skipping PMD execution" );
90              return;
91          }
92  
93          executeCheck( "pmd.xml", "violation", "PMD violation", failurePriority );
94      }
95  
96      /**
97       * {@inheritDoc}
98       */
99      protected void printError( Violation item, String severity )
100     {
101 
102         StringBuilder buff = new StringBuilder( 100 );
103         buff.append( "PMD " ).append( severity ).append( ": " );
104         if ( item.getViolationClass() != null )
105         {
106             if ( item.getViolationPackage() != null )
107             {
108                 buff.append( item.getViolationPackage() );
109                 buff.append( "." );
110             }
111             buff.append( item.getViolationClass() );
112         }
113         else
114         {
115             buff.append( item.getFileName() );
116         }
117         buff.append( ":" );
118         buff.append( item.getBeginline() );
119         buff.append( " Rule:" ).append( item.getRule() );
120         buff.append( " Priority:" ).append( item.getPriority() );
121         buff.append( " " ).append( item.getText() ).append( "." );
122 
123         this.getLog().info( buff.toString() );
124     }
125 
126     @Override
127     protected List<Violation> getErrorDetails( File pmdFile )
128         throws XmlPullParserException, IOException
129     {
130         try ( FileReader reader1 = new FileReader( pmdFile ) )
131         {
132             PmdXpp3Reader reader = new PmdXpp3Reader();
133             PmdErrorDetail details = reader.read( reader1, false );
134 
135             List<Violation> violations = new ArrayList<>();
136             for ( PmdFile file : details.getFiles() )
137             {
138                 String fullPath = file.getName();
139 
140                 for ( Violation violation : file.getViolations() )
141                 {
142                     violation.setFileName( getFilename( fullPath, violation.getViolationPackage() ) );
143                     violations.add( violation );
144                 }
145             }
146             return violations;
147         }
148     }
149 
150     @Override
151     protected int getPriority( Violation errorDetail )
152     {
153         return errorDetail.getPriority();
154     }
155 
156     @Override
157     protected ViolationDetails<Violation> newViolationDetailsInstance()
158     {
159         return new ViolationDetails<>();
160     }
161 
162     private String getFilename( String fullpath, String pkg )
163     {
164         int index = fullpath.lastIndexOf( File.separatorChar );
165 
166         while ( StringUtils.isNotEmpty( pkg ) )
167         {
168             index = fullpath.substring( 0, index ).lastIndexOf( File.separatorChar );
169 
170             int dot = pkg.indexOf( '.' );
171 
172             if ( dot < 0 )
173             {
174                 break;
175             }
176             pkg = pkg.substring( dot + 1 );
177         }
178 
179         return fullpath.substring( index + 1 );
180     }
181 }