1 package org.codehaus.mojo.javancss;
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.List;
26 import java.util.Locale;
27 import java.util.ResourceBundle;
28
29 import org.apache.maven.model.ReportPlugin;
30 import org.apache.maven.plugins.annotations.Mojo;
31 import org.apache.maven.plugins.annotations.Parameter;
32 import org.apache.maven.project.MavenProject;
33 import org.apache.maven.reporting.AbstractMavenReport;
34 import org.apache.maven.reporting.MavenReportException;
35 import org.codehaus.plexus.util.DirectoryScanner;
36 import org.codehaus.plexus.util.PathTool;
37 import org.codehaus.plexus.util.ReaderFactory;
38 import org.codehaus.plexus.util.StringUtils;
39 import org.dom4j.Document;
40 import org.dom4j.DocumentException;
41 import org.dom4j.io.SAXReader;
42
43
44
45
46
47
48
49 @Mojo( name = "report" )
50 public class NcssReportMojo
51 extends AbstractMavenReport
52 {
53 private static final String OUTPUT_NAME = "javancss";
54
55
56
57
58 @Parameter( defaultValue = "${project.build.directory}", readonly = true, required = true )
59 private File xmlOutputDirectory;
60
61
62
63
64 @Parameter( defaultValue = "${project.build.sourceDirectory}", readonly = true, required = true )
65 private File sourceDirectory;
66
67
68
69
70 @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
71 private String sourceEncoding;
72
73
74
75
76 @Parameter( defaultValue = "30" )
77 private int lineThreshold;
78
79
80
81
82 @Parameter( defaultValue = "javancss-raw-report.xml" )
83 private String tempFileName;
84
85
86
87
88 @Parameter( defaultValue = "${reactorProjects}", readonly = true, required = true )
89 private List<MavenProject> reactorProjects;
90
91
92
93
94
95 @Parameter( property = "linkXRef", defaultValue = "true" )
96 private boolean linkXRef;
97
98
99
100
101 @Parameter( defaultValue = "${project.build.directory}/site/xref" )
102 private File xrefLocation;
103
104
105
106
107
108 @Parameter
109 private String[] includes;
110
111
112
113
114
115 @Parameter
116 private String[] excludes;
117
118
119
120
121
122
123 @Parameter( property = "ncss.skip", defaultValue = "false" )
124 private boolean skip;
125
126
127
128
129
130
131 protected String getSourceEncoding()
132 {
133 return sourceEncoding;
134 }
135
136
137
138
139 public void executeReport( Locale locale )
140 throws MavenReportException
141 {
142 if ( !canGenerateReport() )
143 {
144 return;
145 }
146
147 if ( canGenerateSingleReport() )
148 {
149 generateSingleReport( locale );
150 }
151 if ( canGenerateAggregateReport() )
152 {
153 generateAggregateReport( locale );
154 }
155 }
156
157 private void generateAggregateReport( Locale locale )
158 throws MavenReportException
159 {
160
161
162 String basedir = project.getBasedir().toString();
163 String output = xmlOutputDirectory.toString();
164 if ( getLog().isDebugEnabled() )
165 {
166 getLog().debug( "basedir: " + basedir );
167 getLog().debug( "output: " + output );
168 }
169 String relative = null;
170 if ( output.startsWith( basedir ) )
171 {
172 relative = output.substring( basedir.length() + 1 );
173 }
174 else
175 {
176 getLog().error(
177 "Unable to aggregate report because I can't "
178 + "determine the relative location of the XML report" );
179 return;
180 }
181 getLog().debug( "relative: " + relative );
182 List<ModuleReport> reports = new ArrayList<ModuleReport>();
183 for ( MavenProject child : reactorProjects )
184 {
185 File xmlReport = new File( child.getBasedir() + File.separator + relative, tempFileName );
186 if ( xmlReport.exists() )
187 {
188 reports.add( new ModuleReport( child, loadDocument( xmlReport ) ) );
189 }
190 else
191 {
192 getLog().debug( "xml file not found: " + xmlReport );
193 }
194 }
195 getLog().debug( "Aggregating " + reports.size() + " JavaNCSS reports" );
196
197
198 NcssAggregateReportGenerator reportGenerator =
199 new NcssAggregateReportGenerator( getSink(), getBundle( locale ), getLog() );
200 reportGenerator.doReport( locale, reports, lineThreshold );
201 }
202
203 private boolean isIncludeExcludeUsed()
204 {
205 return ( ( excludes != null ) || ( includes != null ) );
206 }
207
208 private void generateSingleReport( Locale locale )
209 throws MavenReportException
210 {
211 getLog().info( "Running JavaNCSS " + NcssExecuter.getJavaNCSSVersion() );
212 if ( getLog().isDebugEnabled() )
213 {
214 getLog().debug( "Calling NcssExecuter with src: " + sourceDirectory );
215 getLog().debug( " output: " + buildOutputFileName() );
216 getLog().debug( " includes: " + includes );
217 getLog().debug( " excludes: " + excludes );
218 getLog().debug( " encoding: " + getSourceEncoding() );
219 }
220
221
222 NcssExecuter ncssExecuter;
223 if ( isIncludeExcludeUsed() )
224 {
225 ncssExecuter = new NcssExecuter( scanForSources(), buildOutputFileName() );
226 }
227 else
228 {
229 ncssExecuter = new NcssExecuter( sourceDirectory, buildOutputFileName() );
230 }
231 ncssExecuter.setEncoding( getSourceEncoding() );
232
233
234 ncssExecuter.execute();
235 if ( !isTempReportGenerated() )
236 {
237 throw new MavenReportException( "Can't process temp ncss xml file." );
238 }
239
240 NcssReportGenerator reportGenerator =
241 new NcssReportGenerator( getSink(), getBundle( locale ), getLog(), constructXRefLocation() );
242 reportGenerator.doReport( loadDocument(), lineThreshold );
243 }
244
245
246
247
248 private Document loadDocument( File file )
249 throws MavenReportException
250 {
251 try
252 {
253 SAXReader saxReader = new SAXReader();
254 return saxReader.read( ReaderFactory.newXmlReader( file ) );
255 }
256 catch ( DocumentException de )
257 {
258 throw new MavenReportException( de.getMessage(), de );
259 }
260 catch ( IOException ioe )
261 {
262 throw new MavenReportException( ioe.getMessage(), ioe );
263 }
264 }
265
266 private Document loadDocument()
267 throws MavenReportException
268 {
269 return loadDocument( new File( buildOutputFileName() ) );
270 }
271
272
273
274
275
276
277 private boolean isTempReportGenerated()
278 {
279 return new File( buildOutputFileName() ).exists();
280 }
281
282
283
284
285 public boolean canGenerateReport()
286 {
287 return !skip && ( canGenerateSingleReport() || canGenerateAggregateReport() );
288 }
289
290 private boolean canGenerateAggregateReport()
291 {
292 if ( project.getModules().size() == 0 )
293 {
294
295 return false;
296 }
297 if ( sourceDirectory != null && sourceDirectory.exists() )
298 {
299
300 String[] sources = scanForSources();
301 return !( ( sources != null ) && ( sources.length > 0 ) );
302 }
303 return true;
304 }
305
306 private boolean canGenerateSingleReport()
307 {
308 if ( sourceDirectory == null || !sourceDirectory.exists() )
309 {
310 return false;
311 }
312
313
314 String[] sources = scanForSources();
315 return ( sources != null ) && ( sources.length > 0 );
316 }
317
318
319
320
321
322
323 private String[] scanForSources()
324 {
325 String[] defaultIncludes = { "**\\*.java" };
326 DirectoryScanner ds = new DirectoryScanner();
327 if ( includes == null )
328 {
329 ds.setIncludes( defaultIncludes );
330 }
331 else
332 {
333 ds.setIncludes( includes );
334 }
335 if ( excludes != null )
336 {
337 ds.setExcludes( excludes );
338 }
339 ds.setBasedir( sourceDirectory );
340 getLog().debug( "Scanning base directory " + sourceDirectory );
341 ds.scan();
342 int maxFiles = ds.getIncludedFiles().length;
343 String[] result = new String[maxFiles];
344 for ( int i = 0; i < maxFiles; i++ )
345 {
346 result[i] = sourceDirectory + File.separator + ds.getIncludedFiles()[i];
347 }
348 return result;
349 }
350
351
352
353
354
355
356 String buildOutputFileName()
357 {
358 return getXmlOutputDirectory() + File.separator + tempFileName;
359 }
360
361
362
363
364 public String getName( Locale locale )
365 {
366 return getBundle( locale ).getString( "report.javancss.name" );
367 }
368
369
370
371
372 public String getDescription( Locale locale )
373 {
374 return getBundle( locale ).getString( "report.javancss.description" );
375 }
376
377 protected String getXmlOutputDirectory()
378 {
379 return xmlOutputDirectory.getAbsolutePath();
380 }
381
382
383
384
385 public String getOutputName()
386 {
387 return OUTPUT_NAME;
388 }
389
390
391
392
393
394
395 protected File getSourceDirectory()
396 {
397 return sourceDirectory;
398 }
399
400
401 private static ResourceBundle getBundle( Locale locale )
402 {
403 return ResourceBundle.getBundle( "javancss-report", locale, NcssReportMojo.class.getClassLoader() );
404 }
405
406
407 protected String constructXRefLocation()
408 {
409 String location = null;
410 if ( linkXRef )
411 {
412 String relativePath =
413 PathTool.getRelativePath( outputDirectory.getAbsolutePath(), xrefLocation.getAbsolutePath() );
414 if ( StringUtils.isEmpty( relativePath ) )
415 {
416 relativePath = ".";
417 }
418 relativePath = relativePath + "/" + xrefLocation.getName();
419 if ( xrefLocation.exists() )
420 {
421
422 location = relativePath;
423 }
424 else
425 {
426
427 for ( ReportPlugin plugin : (List<ReportPlugin>) project.getReportPlugins() )
428 {
429 String artifactId = plugin.getArtifactId();
430 if ( "maven-jxr-plugin".equals( artifactId ) || "jxr-maven-plugin".equals( artifactId ) )
431 {
432 location = relativePath;
433 }
434 }
435 }
436
437 if ( location == null )
438 {
439 getLog().warn( "Unable to locate Source XRef to link to - DISABLED" );
440 }
441 }
442 return location;
443 }
444 }