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.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.TreeMap;
33
34 import net.sourceforge.pmd.PMD;
35
36 import org.apache.maven.doxia.siterenderer.Renderer;
37 import org.apache.maven.model.ReportPlugin;
38 import org.apache.maven.project.MavenProject;
39 import org.apache.maven.reporting.AbstractMavenReport;
40 import org.codehaus.plexus.util.FileUtils;
41 import org.codehaus.plexus.util.PathTool;
42 import org.codehaus.plexus.util.ReaderFactory;
43 import org.codehaus.plexus.util.StringUtils;
44
45
46
47
48
49
50
51 public abstract class AbstractPmdReport
52 extends AbstractMavenReport
53 {
54
55
56
57
58
59
60 protected File targetDirectory;
61
62
63
64
65
66
67
68
69
70 protected File outputDirectory;
71
72
73
74
75
76
77 private Renderer siteRenderer;
78
79
80
81
82
83
84
85
86 protected MavenProject project;
87
88
89
90
91
92
93
94
95
96 protected String format = "xml";
97
98
99
100
101
102
103
104 private boolean linkXRef;
105
106
107
108
109
110
111 private File xrefLocation;
112
113
114
115
116
117
118 private File xrefTestLocation;
119
120
121
122
123
124
125
126
127
128
129 private List<String> excludes;
130
131
132
133
134
135
136
137
138 private List<String> includes;
139
140
141
142
143
144
145
146
147 private List<String> compileSourceRoots;
148
149
150
151
152
153
154
155
156 private List<String> testSourceRoots;
157
158
159
160
161
162
163
164 private File[] excludeRoots;
165
166
167
168
169
170
171
172 protected boolean includeTests;
173
174
175
176
177
178
179
180 protected boolean aggregate;
181
182
183
184
185
186
187
188 private String sourceEncoding;
189
190
191
192
193
194
195
196 private String outputEncoding;
197
198
199
200
201
202
203
204 protected List<MavenProject> reactorProjects;
205
206
207 protected MavenProject getProject()
208 {
209 return project;
210 }
211
212
213 protected Renderer getSiteRenderer()
214 {
215 return siteRenderer;
216 }
217
218 protected String constructXRefLocation( boolean test )
219 {
220 String location = null;
221 if ( linkXRef )
222 {
223 File xrefLoc = test ? xrefTestLocation : xrefLocation;
224
225 String relativePath = PathTool.getRelativePath( outputDirectory.getAbsolutePath(),
226 xrefLoc.getAbsolutePath() );
227 if ( StringUtils.isEmpty( relativePath ) )
228 {
229 relativePath = ".";
230 }
231 relativePath = relativePath + "/" + xrefLoc.getName();
232 if ( xrefLoc.exists() )
233 {
234
235 location = relativePath;
236 }
237 else
238 {
239
240 @SuppressWarnings( "unchecked" )
241 List<ReportPlugin> reportPlugins = project.getReportPlugins();
242 for ( ReportPlugin plugin : reportPlugins )
243 {
244 String artifactId = plugin.getArtifactId();
245 if ( "maven-jxr-plugin".equals( artifactId ) || "jxr-maven-plugin".equals( artifactId ) )
246 {
247 location = relativePath;
248 }
249 }
250 }
251
252 if ( location == null )
253 {
254 getLog().warn( "Unable to locate Source XRef to link to - DISABLED" );
255 }
256 }
257 return location;
258 }
259
260
261
262
263
264
265
266 protected Map<File, PmdFileInfo> getFilesToProcess()
267 throws IOException
268 {
269 String sourceXref = constructXRefLocation( false );
270 String testXref = includeTests ? constructXRefLocation( true ) : "";
271
272 if ( aggregate && !project.isExecutionRoot() )
273 {
274 return Collections.emptyMap();
275 }
276
277 if ( excludeRoots == null )
278 {
279 excludeRoots = new File[0];
280 }
281
282 Collection<File> excludeRootFiles = new HashSet<File>( excludeRoots.length );
283
284 for ( int i = 0; i < excludeRoots.length; i++ )
285 {
286 File file = excludeRoots[i];
287 if ( file.isDirectory() )
288 {
289 excludeRootFiles.add( file );
290 }
291 }
292
293 List<PmdFileInfo> directories = new ArrayList<PmdFileInfo>();
294
295 if ( compileSourceRoots != null )
296 {
297
298 for ( String root : compileSourceRoots )
299 {
300 File sroot = new File( root );
301 directories.add( new PmdFileInfo( project, sroot, sourceXref ) );
302 }
303
304 }
305 if ( includeTests )
306 {
307 if ( testSourceRoots != null )
308 {
309 for ( String root : testSourceRoots )
310 {
311 File sroot = new File( root );
312 directories.add( new PmdFileInfo( project, sroot, testXref ) );
313 }
314 }
315 }
316 if ( aggregate )
317 {
318 for ( MavenProject localProject : reactorProjects )
319 {
320 @SuppressWarnings( "unchecked" )
321 List<String> localCompileSourceRoots = localProject.getCompileSourceRoots();
322 for ( String root : localCompileSourceRoots )
323 {
324 File sroot = new File( root );
325 directories.add( new PmdFileInfo( localProject, sroot, sourceXref ) );
326 }
327 if ( includeTests )
328 {
329 @SuppressWarnings( "unchecked" )
330 List<String> localTestCompileSourceRoots = localProject.getTestCompileSourceRoots();
331 for ( String root : localTestCompileSourceRoots )
332 {
333 File sroot = new File( root );
334 directories.add( new PmdFileInfo( localProject, sroot, testXref ) );
335 }
336 }
337 }
338
339 }
340
341 String excluding = getExcludes();
342 getLog().debug( "Exclusions: " + excluding );
343 String including = getIncludes();
344 getLog().debug( "Inclusions: " + including );
345
346 Map<File, PmdFileInfo> files = new TreeMap<File, PmdFileInfo>();
347
348 for ( PmdFileInfo finfo : directories )
349 {
350 File sourceDirectory = finfo.getSourceDirectory();
351 if ( sourceDirectory.isDirectory() && !excludeRootFiles.contains( sourceDirectory ) )
352 {
353 @SuppressWarnings( "unchecked" )
354 List<File> newfiles = FileUtils.getFiles( sourceDirectory, including, excluding );
355 for ( Iterator<File> it2 = newfiles.iterator(); it2.hasNext(); )
356 {
357 files.put( it2.next(), finfo );
358 }
359 }
360 }
361
362 return files;
363 }
364
365
366
367
368
369
370 private String getIncludes()
371 {
372 Collection<String> patterns = new LinkedHashSet<String>();
373 if ( includes != null )
374 {
375 patterns.addAll( includes );
376 }
377 if ( patterns.isEmpty() )
378 {
379 patterns.add( "**/*.java" );
380 }
381 return StringUtils.join( patterns.iterator(), "," );
382 }
383
384
385
386
387
388
389 private String getExcludes()
390 {
391 @SuppressWarnings( "unchecked" )
392 Collection<String> patterns = new LinkedHashSet<String>( FileUtils.getDefaultExcludesAsList() );
393 if ( excludes != null )
394 {
395 patterns.addAll( excludes );
396 }
397 return StringUtils.join( patterns.iterator(), "," );
398 }
399
400 protected boolean isHtml()
401 {
402 return "html".equals( format );
403 }
404
405
406 public boolean canGenerateReport()
407 {
408 if ( aggregate && !project.isExecutionRoot() )
409 {
410 return false;
411 }
412
413 if ( "pom".equals( project.getPackaging() ) && !aggregate )
414 {
415 return false;
416 }
417
418
419
420 if ( "xml".equals( format ) )
421 {
422 return true;
423 }
424 try
425 {
426 Map<File, PmdFileInfo> filesToProcess = getFilesToProcess();
427 if ( filesToProcess.isEmpty() )
428 {
429 return false;
430 }
431 }
432 catch ( IOException e )
433 {
434 getLog().error( e );
435 }
436 return true;
437 }
438
439
440 protected String getOutputDirectory()
441 {
442 return outputDirectory.getAbsolutePath();
443 }
444
445 protected String getSourceEncoding()
446 {
447 return sourceEncoding;
448 }
449
450
451
452
453
454
455
456 protected String getOutputEncoding()
457 {
458 return ( outputEncoding != null ) ? outputEncoding : ReaderFactory.UTF_8;
459 }
460
461 static String getPmdVersion()
462 {
463 try
464 {
465 return (String) PMD.class.getField( "VERSION" ).get( null );
466 }
467 catch ( IllegalAccessException e )
468 {
469 throw new RuntimeException( "PMD VERSION field not accessible", e );
470 }
471 catch ( NoSuchFieldException e )
472 {
473 throw new RuntimeException( "PMD VERSION field not found", e );
474 }
475 }
476 }