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 List<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 = Collections.emptyList();
280 }
281
282 Collection<File> excludeRootFiles = new HashSet<File>( excludeRoots.size() );
283
284 for ( File file : excludeRoots )
285 {
286 if ( file.isDirectory() )
287 {
288 excludeRootFiles.add( file );
289 }
290 }
291
292 List<PmdFileInfo> directories = new ArrayList<PmdFileInfo>();
293
294 if ( compileSourceRoots != null )
295 {
296
297 for ( String root : compileSourceRoots )
298 {
299 File sroot = new File( root );
300 directories.add( new PmdFileInfo( project, sroot, sourceXref ) );
301 }
302
303 }
304 if ( includeTests )
305 {
306 if ( testSourceRoots != null )
307 {
308 for ( String root : testSourceRoots )
309 {
310 File sroot = new File( root );
311 directories.add( new PmdFileInfo( project, sroot, testXref ) );
312 }
313 }
314 }
315 if ( aggregate )
316 {
317 for ( MavenProject localProject : reactorProjects )
318 {
319 @SuppressWarnings( "unchecked" )
320 List<String> localCompileSourceRoots = localProject.getCompileSourceRoots();
321 for ( String root : localCompileSourceRoots )
322 {
323 File sroot = new File( root );
324 directories.add( new PmdFileInfo( localProject, sroot, sourceXref ) );
325 }
326 if ( includeTests )
327 {
328 @SuppressWarnings( "unchecked" )
329 List<String> localTestCompileSourceRoots = localProject.getTestCompileSourceRoots();
330 for ( String root : localTestCompileSourceRoots )
331 {
332 File sroot = new File( root );
333 directories.add( new PmdFileInfo( localProject, sroot, testXref ) );
334 }
335 }
336 }
337
338 }
339
340 String excluding = getExcludes();
341 getLog().debug( "Exclusions: " + excluding );
342 String including = getIncludes();
343 getLog().debug( "Inclusions: " + including );
344
345 Map<File, PmdFileInfo> files = new TreeMap<File, PmdFileInfo>();
346
347 for ( PmdFileInfo finfo : directories )
348 {
349 File sourceDirectory = finfo.getSourceDirectory();
350 if ( sourceDirectory.isDirectory() && !excludeRootFiles.contains( sourceDirectory ) )
351 {
352 @SuppressWarnings( "unchecked" )
353 List<File> newfiles = FileUtils.getFiles( sourceDirectory, including, excluding );
354 for ( Iterator<File> it2 = newfiles.iterator(); it2.hasNext(); )
355 {
356 files.put( it2.next(), finfo );
357 }
358 }
359 }
360
361 return files;
362 }
363
364
365
366
367
368
369 private String getIncludes()
370 {
371 Collection<String> patterns = new LinkedHashSet<String>();
372 if ( includes != null )
373 {
374 patterns.addAll( includes );
375 }
376 if ( patterns.isEmpty() )
377 {
378 patterns.add( "**/*.java" );
379 }
380 return StringUtils.join( patterns.iterator(), "," );
381 }
382
383
384
385
386
387
388 private String getExcludes()
389 {
390 @SuppressWarnings( "unchecked" )
391 Collection<String> patterns = new LinkedHashSet<String>( FileUtils.getDefaultExcludesAsList() );
392 if ( excludes != null )
393 {
394 patterns.addAll( excludes );
395 }
396 return StringUtils.join( patterns.iterator(), "," );
397 }
398
399 protected boolean isHtml()
400 {
401 return "html".equals( format );
402 }
403
404
405 public boolean canGenerateReport()
406 {
407 if ( aggregate && !project.isExecutionRoot() )
408 {
409 return false;
410 }
411
412 if ( "pom".equals( project.getPackaging() ) && !aggregate )
413 {
414 return false;
415 }
416
417
418
419 if ( "xml".equals( format ) )
420 {
421 return true;
422 }
423 try
424 {
425 Map<File, PmdFileInfo> filesToProcess = getFilesToProcess();
426 if ( filesToProcess.isEmpty() )
427 {
428 return false;
429 }
430 }
431 catch ( IOException e )
432 {
433 getLog().error( e );
434 }
435 return true;
436 }
437
438
439 protected String getOutputDirectory()
440 {
441 return outputDirectory.getAbsolutePath();
442 }
443
444 protected String getSourceEncoding()
445 {
446 return sourceEncoding;
447 }
448
449
450
451
452
453
454
455 protected String getOutputEncoding()
456 {
457 return ( outputEncoding != null ) ? outputEncoding : ReaderFactory.UTF_8;
458 }
459
460 static String getPmdVersion()
461 {
462 try
463 {
464 return (String) PMD.class.getField( "VERSION" ).get( null );
465 }
466 catch ( IllegalAccessException e )
467 {
468 throw new RuntimeException( "PMD VERSION field not accessible", e );
469 }
470 catch ( NoSuchFieldException e )
471 {
472 throw new RuntimeException( "PMD VERSION field not found", e );
473 }
474 }
475 }