1 package org.apache.maven.plugin.checkstyle;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import com.puppycrawl.tools.checkstyle.DefaultLogger;
23 import com.puppycrawl.tools.checkstyle.XMLLogger;
24 import com.puppycrawl.tools.checkstyle.api.AuditListener;
25 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
26 import org.apache.maven.doxia.siterenderer.Renderer;
27 import org.apache.maven.doxia.tools.SiteTool;
28 import org.apache.maven.model.ReportPlugin;
29 import org.apache.maven.model.Resource;
30 import org.apache.maven.plugin.checkstyle.rss.CheckstyleRssGenerator;
31 import org.apache.maven.plugin.checkstyle.rss.CheckstyleRssGeneratorRequest;
32 import org.apache.maven.plugins.annotations.Component;
33 import org.apache.maven.plugins.annotations.Parameter;
34 import org.apache.maven.project.MavenProject;
35 import org.apache.maven.reporting.AbstractMavenReport;
36 import org.apache.maven.reporting.MavenReportException;
37 import org.codehaus.plexus.resource.ResourceManager;
38 import org.codehaus.plexus.resource.loader.FileResourceLoader;
39 import org.codehaus.plexus.util.PathTool;
40 import org.codehaus.plexus.util.StringUtils;
41
42 import java.io.ByteArrayOutputStream;
43 import java.io.File;
44 import java.io.FileNotFoundException;
45 import java.io.FileOutputStream;
46 import java.io.IOException;
47 import java.io.OutputStream;
48 import java.util.Calendar;
49 import java.util.List;
50 import java.util.Locale;
51 import java.util.ResourceBundle;
52
53
54
55
56
57
58
59 public abstract class AbstractCheckstyleReport
60 extends AbstractMavenReport
61 {
62 public static final String PLUGIN_RESOURCES = "org/apache/maven/plugin/checkstyle";
63
64 protected static final String JAVA_FILES = "**\\/*.java";
65
66
67
68
69
70
71 @Parameter( property = "checkstyle.skip", defaultValue = "false" )
72 protected boolean skip;
73
74
75
76
77
78
79
80 @Parameter( defaultValue = "${project.reporting.outputDirectory}", required = true )
81 private File outputDirectory;
82
83
84
85
86
87
88 @Parameter( property = "checkstyle.output.file", defaultValue = "${project.build.directory}/checkstyle-result.xml" )
89 private File outputFile;
90
91
92
93
94
95
96 @Parameter( defaultValue = "${project.resources}", readonly = true )
97 protected List<Resource> resources;
98
99
100
101
102
103
104 @Parameter( defaultValue = "${project.testResources}", readonly = true )
105 protected List<Resource> testResources;
106
107
108
109
110
111 @Parameter
112 private File useFile;
113
114
115
116
117
118 @Parameter( property = "checkstyle.output.format", defaultValue = "xml" )
119 private String outputFileFormat;
120
121
122
123
124 @Parameter( property = "checkstyle.enable.rules.summary", defaultValue = "true" )
125 private boolean enableRulesSummary;
126
127
128
129
130 @Parameter( property = "checkstyle.enable.severity.summary", defaultValue = "true" )
131 private boolean enableSeveritySummary;
132
133
134
135
136 @Parameter( property = "checkstyle.enable.files.summary", defaultValue = "true" )
137 private boolean enableFilesSummary;
138
139
140
141
142 @Parameter( property = "checkstyle.enable.rss", defaultValue = "true" )
143 private boolean enableRSS;
144
145
146
147
148
149
150 @Component( role = SiteTool.class )
151 protected SiteTool siteTool;
152
153
154
155
156 @Component
157 protected MavenProject project;
158
159
160
161
162
163
164
165 @Parameter( property = "linkXRef", defaultValue = "true" )
166 private boolean linkXRef;
167
168
169
170
171 @Parameter( defaultValue = "${project.reporting.outputDirectory}/xref" )
172 private File xrefLocation;
173
174
175
176
177
178
179 @Parameter
180 private List<String> treeWalkerNames;
181
182
183
184 @Component
185 private Renderer siteRenderer;
186
187
188
189 @Component
190 protected ResourceManager locator;
191
192
193
194
195
196
197 @Component( role = CheckstyleRssGenerator.class, hint = "default" )
198 protected CheckstyleRssGenerator checkstyleRssGenerator;
199
200
201
202
203 @Component( role = CheckstyleExecutor.class, hint = "default" )
204 protected CheckstyleExecutor checkstyleExecutor;
205
206 protected ByteArrayOutputStream stringOutputStream;
207
208
209 public String getName( Locale locale )
210 {
211 return getBundle( locale ).getString( "report.checkstyle.name" );
212 }
213
214
215 public String getDescription( Locale locale )
216 {
217 return getBundle( locale ).getString( "report.checkstyle.description" );
218 }
219
220
221 protected String getOutputDirectory()
222 {
223 return outputDirectory.getAbsolutePath();
224 }
225
226
227 protected MavenProject getProject()
228 {
229 return project;
230 }
231
232
233 protected Renderer getSiteRenderer()
234 {
235 return siteRenderer;
236 }
237
238
239 public void executeReport( Locale locale )
240 throws MavenReportException
241 {
242 locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() );
243 locator.addSearchPath( "url", "" );
244
245 locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) );
246
247
248
249
250
251
252
253
254 ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
255
256 try
257 {
258 CheckstyleExecutorRequest request = createRequest();
259
260 CheckstyleResults results = checkstyleExecutor.executeCheckstyle( request );
261
262 ResourceBundle bundle = getBundle( locale );
263 generateReportStatics();
264 generateMainReport( results, bundle );
265 if ( enableRSS )
266 {
267 CheckstyleRssGeneratorRequest checkstyleRssGeneratorRequest =
268 new CheckstyleRssGeneratorRequest( this.project, this.getCopyright(), outputDirectory, getLog() );
269 checkstyleRssGenerator.generateRSS( results, checkstyleRssGeneratorRequest );
270 }
271
272 }
273 catch ( CheckstyleException e )
274 {
275 throw new MavenReportException( "Failed during checkstyle configuration", e );
276 }
277 catch ( CheckstyleExecutorException e )
278 {
279 throw new MavenReportException( "Failed during checkstyle execution", e );
280 }
281 finally
282 {
283
284 Thread.currentThread().setContextClassLoader( currentClassLoader );
285 }
286 }
287
288
289
290
291
292
293
294 protected abstract CheckstyleExecutorRequest createRequest()
295 throws MavenReportException;
296
297
298
299
300
301
302
303 protected AuditListener getListener()
304 throws MavenReportException
305 {
306 AuditListener listener = null;
307
308 if ( StringUtils.isNotEmpty( outputFileFormat ) )
309 {
310 File resultFile = outputFile;
311
312 OutputStream out = getOutputStream( resultFile );
313
314 if ( "xml".equals( outputFileFormat ) )
315 {
316 listener = new XMLLogger( out, true );
317 }
318 else if ( "plain".equals( outputFileFormat ) )
319 {
320 listener = new DefaultLogger( out, true );
321 }
322 else
323 {
324
325 throw new MavenReportException( "Invalid output file format: (" + outputFileFormat
326 + "). Must be 'plain' or 'xml'." );
327 }
328 }
329
330 return listener;
331 }
332
333 private OutputStream getOutputStream( File file )
334 throws MavenReportException
335 {
336 File parentFile = file.getAbsoluteFile().getParentFile();
337
338 if ( !parentFile.exists() )
339 {
340 parentFile.mkdirs();
341 }
342
343 FileOutputStream fileOutputStream;
344 try
345 {
346 fileOutputStream = new FileOutputStream( file );
347 }
348 catch ( FileNotFoundException e )
349 {
350 throw new MavenReportException( "Unable to create output stream: " + file, e );
351 }
352 return fileOutputStream;
353 }
354
355
356
357
358
359
360
361 protected DefaultLogger getConsoleListener()
362 throws MavenReportException
363 {
364 DefaultLogger consoleListener;
365
366 if ( useFile == null )
367 {
368 stringOutputStream = new ByteArrayOutputStream();
369 consoleListener = new DefaultLogger( stringOutputStream, false );
370 }
371 else
372 {
373 OutputStream out = getOutputStream( useFile );
374
375 consoleListener = new DefaultLogger( out, true );
376 }
377
378 return consoleListener;
379 }
380
381 private void generateReportStatics()
382 throws MavenReportException
383 {
384 ReportResource rresource = new ReportResource( PLUGIN_RESOURCES, outputDirectory );
385 try
386 {
387 rresource.copy( "images/rss.png" );
388 }
389 catch ( IOException e )
390 {
391 throw new MavenReportException( "Unable to copy static resources.", e );
392 }
393 }
394
395
396 private String getCopyright()
397 {
398 String copyright;
399 int currentYear = Calendar.getInstance().get( Calendar.YEAR );
400 if ( StringUtils.isNotEmpty( project.getInceptionYear() )
401 && !String.valueOf( currentYear ).equals( project.getInceptionYear() ) )
402 {
403 copyright = project.getInceptionYear() + " - " + currentYear;
404 }
405 else
406 {
407 copyright = String.valueOf( currentYear );
408 }
409
410 if ( ( project.getOrganization() != null ) && StringUtils.isNotEmpty( project.getOrganization().getName() ) )
411 {
412 copyright = copyright + " " + project.getOrganization().getName();
413 }
414 return copyright;
415 }
416
417 private void generateMainReport( CheckstyleResults results, ResourceBundle bundle )
418 {
419 CheckstyleReportGenerator generator =
420 new CheckstyleReportGenerator( getSink(), bundle, project.getBasedir(), siteTool );
421
422 generator.setLog( getLog() );
423 generator.setEnableRulesSummary( enableRulesSummary );
424 generator.setEnableSeveritySummary( enableSeveritySummary );
425 generator.setEnableFilesSummary( enableFilesSummary );
426 generator.setEnableRSS( enableRSS );
427 generator.setCheckstyleConfig( results.getConfiguration() );
428 if ( linkXRef )
429 {
430 String relativePath = PathTool.getRelativePath( getOutputDirectory(), xrefLocation.getAbsolutePath() );
431 if ( StringUtils.isEmpty( relativePath ) )
432 {
433 relativePath = ".";
434 }
435 relativePath = relativePath + "/" + xrefLocation.getName();
436 if ( xrefLocation.exists() )
437 {
438
439
440 generator.setXrefLocation( relativePath );
441 }
442 else
443 {
444
445 for (ReportPlugin report : (Iterable<ReportPlugin>) getProject().getReportPlugins()) {
446 String artifactId = report.getArtifactId();
447 if ("maven-jxr-plugin".equals(artifactId) || "jxr-maven-plugin".equals(artifactId)) {
448 generator.setXrefLocation(relativePath);
449 }
450 }
451 }
452
453 if ( generator.getXrefLocation() == null )
454 {
455 getLog().warn( "Unable to locate Source XRef to link to - DISABLED" );
456 }
457 }
458 if ( treeWalkerNames != null )
459 {
460 generator.setTreeWalkerNames( treeWalkerNames );
461 }
462 generator.generateReport( results );
463 }
464
465 private static ResourceBundle getBundle( Locale locale )
466 {
467 return ResourceBundle.getBundle( "checkstyle-report", locale, AbstractCheckstyleReport.class.getClassLoader() );
468 }
469
470
471 public void setReportOutputDirectory( File reportOutputDirectory )
472 {
473 super.setReportOutputDirectory( reportOutputDirectory );
474 this.outputDirectory = reportOutputDirectory;
475 }
476 }