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 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
44
45
46
47
48 public abstract class AbstractPmdViolationCheckMojo
49 extends AbstractMojo
50 {
51 private static final Boolean FAILURES_KEY = Boolean.TRUE;
52
53 private static final Boolean WARNINGS_KEY = Boolean.FALSE;
54
55
56
57
58
59
60
61 private File targetDirectory;
62
63
64
65
66
67
68
69 private boolean failOnViolation;
70
71
72
73
74
75
76
77
78 private String language;
79
80
81
82
83
84
85
86 protected boolean aggregate;
87
88
89
90
91
92
93 private boolean verbose;
94
95
96
97
98
99
100
101
102 protected MavenProject project;
103
104 protected void executeCheck( String filename, String tagName, String key, int failurePriority )
105 throws MojoFailureException, MojoExecutionException
106 {
107 if ( aggregate && !project.isExecutionRoot() )
108 {
109 return;
110 }
111
112 if ( "java".equals( language ) || aggregate )
113 {
114 File outputFile = new File( targetDirectory, filename );
115
116 if ( outputFile.exists() )
117 {
118 Reader reader = null;
119 try
120 {
121 XmlPullParser xpp = new MXParser();
122 reader = ReaderFactory.newXmlReader( outputFile );
123 xpp.setInput( reader );
124
125 Map violations = getViolations( xpp, tagName, failurePriority );
126
127 List failures = (List) violations.get( FAILURES_KEY );
128 List warnings = (List) violations.get( WARNINGS_KEY );
129
130 if ( verbose )
131 {
132 printErrors( failures, warnings );
133 }
134
135 int failureCount = failures.size();
136 int warningCount = warnings.size();
137
138 String message = getMessage( failureCount, warningCount, key, outputFile );
139
140 if ( failureCount > 0 && failOnViolation )
141 {
142 throw new MojoFailureException( message );
143 }
144
145 this.getLog().info( message );
146 }
147 catch ( IOException e )
148 {
149 throw new MojoExecutionException(
150 "Unable to read PMD results xml: " + outputFile.getAbsolutePath(),
151 e );
152 }
153 catch ( XmlPullParserException e )
154 {
155 throw new MojoExecutionException(
156 "Unable to read PMD results xml: " + outputFile.getAbsolutePath(),
157 e );
158 }
159 finally
160 {
161 IOUtil.close( reader );
162 }
163 }
164 else
165 {
166 throw new MojoFailureException( "Unable to perform check, " + "unable to find " + outputFile );
167 }
168 }
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182 private Map getViolations( XmlPullParser xpp, String tagName, int failurePriority )
183 throws XmlPullParserException, IOException
184 {
185 int eventType = xpp.getEventType();
186
187 List failures = new ArrayList();
188 List warnings = new ArrayList();
189
190 String fullpath = null;
191
192 while ( eventType != XmlPullParser.END_DOCUMENT )
193 {
194 if ( eventType == XmlPullParser.START_TAG && "file".equals( xpp.getName() ) )
195 {
196 fullpath = xpp.getAttributeValue( "", "name" );
197 }
198 if ( eventType == XmlPullParser.START_TAG && tagName.equals( xpp.getName() ) )
199 {
200 Map details = getErrorDetails( xpp );
201
202 if ( fullpath != null )
203 {
204 details.put( "filename", getFilename( fullpath, (String) details.get( "package" ) ) );
205 }
206
207 try
208 {
209 int priority = Integer.parseInt( (String) details.get( "priority" ) );
210 if ( priority <= failurePriority )
211 {
212 failures.add( details );
213 }
214 else
215 {
216 warnings.add( details );
217 }
218 }
219 catch ( NumberFormatException e )
220 {
221
222
223 failures.add( details );
224 }
225 catch ( NullPointerException e )
226 {
227
228
229 failures.add( details );
230 }
231
232 }
233
234 eventType = xpp.next();
235 }
236
237 HashMap map = new HashMap( 2 );
238 map.put( FAILURES_KEY, failures );
239 map.put( WARNINGS_KEY, warnings );
240 return map;
241 }
242
243 private String getFilename( String fullpath, String pkg )
244 {
245 int index = fullpath.lastIndexOf( File.separatorChar );
246
247 while ( StringUtils.isNotEmpty( pkg ) )
248 {
249 index = fullpath.substring( 0, index ).lastIndexOf( File.separatorChar );
250
251 int dot = pkg.indexOf( '.' );
252
253 if ( dot < 0 )
254 {
255 break;
256 }
257 pkg = pkg.substring( dot + 1 );
258 }
259
260 return fullpath.substring( index + 1 );
261 }
262
263
264
265
266
267
268
269
270
271 protected void printErrors( List failures, List warnings )
272 {
273 Iterator iter = warnings.iterator();
274 while ( iter.hasNext() )
275 {
276 printError( (Map) iter.next(), "Warning" );
277 }
278
279 iter = failures.iterator();
280 while ( iter.hasNext() )
281 {
282 printError( (Map) iter.next(), "Failure" );
283 }
284 }
285
286
287
288
289
290
291
292
293
294
295 private String getMessage( int failureCount, int warningCount, String key, File outputFile )
296 {
297 StringBuffer message = new StringBuffer();
298 if ( failureCount > 0 || warningCount > 0 )
299 {
300 if ( failureCount > 0 )
301 {
302 message.append( "You have " + failureCount + " " + key + ( failureCount > 1 ? "s" : "" ) );
303 }
304
305 if ( warningCount > 0 )
306 {
307 if ( failureCount > 0 )
308 {
309 message.append( " and " );
310 }
311 else
312 {
313 message.append( "You have " );
314 }
315 message.append( warningCount + " warning" + ( warningCount > 1 ? "s" : "" ) );
316 }
317
318 message.append( ". For more details see:" ).append( outputFile.getAbsolutePath() );
319 }
320 return message.toString();
321 }
322
323
324
325
326
327
328 protected abstract void printError( Map item, String severity );
329
330
331
332
333
334
335
336
337
338 protected abstract Map getErrorDetails( XmlPullParser xpp )
339 throws XmlPullParserException, IOException;
340 }