1 package org.apache.maven.plugin.pmd;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.plugin.MojoExecutionException;
23 import org.apache.maven.plugin.MojoFailureException;
24 import org.apache.maven.plugin.pmd.model.PmdErrorDetail;
25 import org.apache.maven.plugin.pmd.model.PmdFile;
26 import org.apache.maven.plugin.pmd.model.Violation;
27 import org.apache.maven.plugin.pmd.model.io.xpp3.PmdXpp3Reader;
28 import org.apache.maven.plugins.annotations.Execute;
29 import org.apache.maven.plugins.annotations.LifecyclePhase;
30 import org.apache.maven.plugins.annotations.Mojo;
31 import org.apache.maven.plugins.annotations.Parameter;
32 import org.codehaus.plexus.util.IOUtil;
33 import org.codehaus.plexus.util.StringUtils;
34 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
35
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.FileReader;
39 import java.io.IOException;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.HashSet;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Map.Entry;
46 import java.util.Properties;
47 import java.util.Set;
48
49
50
51
52
53
54
55 @Mojo( name = "check", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true )
56 @Execute( goal = "pmd" )
57 public class PmdViolationCheckMojo
58 extends AbstractPmdViolationCheckMojo<Violation>
59 {
60
61
62
63
64
65 @Parameter( property = "pmd.failurePriority", defaultValue = "5", required = true )
66 private int failurePriority;
67
68
69
70
71 @Parameter( property = "pmd.skip", defaultValue = "false" )
72 private boolean skip;
73
74 private final Map<String, Set<String>> excludeFromFailureClasses = new HashMap<String, Set<String>>();
75
76
77
78
79 public void execute()
80 throws MojoExecutionException, MojoFailureException
81 {
82 if ( !skip )
83 {
84 executeCheck( "pmd.xml", "violation", "PMD violation", failurePriority );
85 }
86 }
87
88 @Override
89 protected void loadExcludeFromFailuresData( final String excludeFromFailureFile )
90 throws MojoExecutionException
91 {
92 File file = new File( excludeFromFailureFile );
93 if ( !file.exists() )
94 {
95 return;
96 }
97 final Properties props = new Properties();
98 FileInputStream fileInputStream = null;
99 try
100 {
101 fileInputStream = new FileInputStream( new File( excludeFromFailureFile ) );
102 props.load( fileInputStream );
103 }
104 catch ( final IOException e )
105 {
106 throw new MojoExecutionException( "Cannot load properties file " + excludeFromFailureFile, e );
107 }
108 finally
109 {
110 IOUtil.close( fileInputStream );
111 }
112 for ( final Entry<Object, Object> propEntry : props.entrySet() )
113 {
114 final Set<String> excludedRuleSet = new HashSet<String>();
115 final String className = propEntry.getKey().toString();
116 final String[] excludedRules = propEntry.getValue().toString().split( "," );
117 for ( final String excludedRule : excludedRules )
118 {
119 excludedRuleSet.add( excludedRule.trim() );
120 }
121 excludeFromFailureClasses.put( className, excludedRuleSet );
122 }
123 }
124
125 @Override
126 protected boolean isExcludedFromFailure( final Violation errorDetail )
127 {
128 final String className = extractClassName( errorDetail );
129 final Set<String> excludedRuleSet = excludeFromFailureClasses.get( className );
130 return excludedRuleSet != null && excludedRuleSet.contains( errorDetail.getRule() );
131 }
132
133 private String extractClassName( final Violation errorDetail )
134 {
135
136 if ( errorDetail.getViolationPackage() != null && errorDetail.getViolationClass() != null )
137 {
138 return errorDetail.getViolationPackage() + "." + errorDetail.getViolationClass();
139 }
140 else
141 {
142 final String fileName = errorDetail.getFileName();
143 final int javaIdx = fileName.indexOf( File.separator + "java" + File.separator );
144 return fileName.substring( javaIdx >= 0 ? javaIdx + 6 : 0, fileName.length() - 5 ).replace(
145 File.separatorChar, '.' );
146 }
147 }
148
149
150
151
152 protected void printError( Violation item, String severity )
153 {
154
155 StringBuilder buff = new StringBuilder( 100 );
156 buff.append( "PMD " ).append( severity ).append( ": " );
157 if ( item.getViolationClass() != null )
158 {
159 if ( item.getViolationPackage() != null )
160 {
161 buff.append( item.getViolationPackage() );
162 buff.append( "." );
163 }
164 buff.append( item.getViolationClass() );
165 }
166 else
167 {
168 buff.append( item.getFileName() );
169 }
170 buff.append( ":" );
171 buff.append( item.getBeginline() );
172 buff.append( " Rule:" ).append( item.getRule() );
173 buff.append( " Priority:" ).append( item.getPriority() );
174 buff.append( " " ).append( item.getText() ).append( "." );
175
176 this.getLog().info( buff.toString() );
177 }
178
179 @Override
180 protected List<Violation> getErrorDetails( File pmdFile )
181 throws XmlPullParserException, IOException
182 {
183 final FileReader reader1 = new FileReader( pmdFile );
184 try
185 {
186 PmdXpp3Reader reader = new PmdXpp3Reader();
187 PmdErrorDetail details = reader.read( reader1, false );
188
189 List<Violation> violations = new ArrayList<Violation>();
190 for ( PmdFile file : details.getFiles() )
191 {
192 String fullPath = file.getName();
193
194 for ( Violation violation : file.getViolations() )
195 {
196 violation.setFileName( getFilename( fullPath, violation.getViolationPackage() ) );
197 violations.add( violation );
198 }
199 }
200 return violations;
201 }
202 finally
203 {
204 reader1.close();
205 }
206 }
207
208 @Override
209 protected int getPriority( Violation errorDetail )
210 {
211 return errorDetail.getPriority();
212 }
213
214 @Override
215 protected ViolationDetails<Violation> newViolationDetailsInstance()
216 {
217 return new ViolationDetails<Violation>();
218 }
219
220 private String getFilename( String fullpath, String pkg )
221 {
222 int index = fullpath.lastIndexOf( File.separatorChar );
223
224 while ( StringUtils.isNotEmpty( pkg ) )
225 {
226 index = fullpath.substring( 0, index ).lastIndexOf( File.separatorChar );
227
228 int dot = pkg.indexOf( '.' );
229
230 if ( dot < 0 )
231 {
232 break;
233 }
234 pkg = pkg.substring( dot + 1 );
235 }
236
237 return fullpath.substring( index + 1 );
238 }
239 }