1 package org.apache.maven.plugin.jxr;
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.net.URL;
25 import java.util.ArrayList;
26 import java.util.Calendar;
27 import java.util.Collection;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.ResourceBundle;
32
33 import org.apache.maven.doxia.siterenderer.Renderer;
34 import org.apache.maven.jxr.JXR;
35 import org.apache.maven.jxr.JxrException;
36 import org.apache.maven.model.ReportPlugin;
37 import org.apache.maven.plugin.MojoExecutionException;
38 import org.apache.maven.project.MavenProject;
39 import org.apache.maven.reporting.AbstractMavenReport;
40 import org.apache.maven.reporting.MavenReportException;
41 import org.codehaus.plexus.util.FileUtils;
42 import org.codehaus.plexus.util.ReaderFactory;
43 import org.codehaus.plexus.util.StringUtils;
44
45
46
47
48
49
50
51
52
53 public abstract class AbstractJxrReport
54 extends AbstractMavenReport
55 {
56
57
58
59
60
61 private MavenProject project;
62
63
64
65
66 private Renderer siteRenderer;
67
68
69
70
71
72
73
74
75
76 private File outputDirectory;
77
78
79
80
81
82
83 private String inputEncoding;
84
85
86
87
88
89
90 private String outputEncoding;
91
92
93
94
95
96
97 private String windowTitle;
98
99
100
101
102
103
104 private String docTitle;
105
106
107
108
109
110
111 private String bottom;
112
113
114
115
116
117
118
119
120 private String templateDir;
121
122
123
124
125
126
127
128 private String stylesheet;
129
130
131
132
133
134
135
136 private ArrayList excludes;
137
138
139
140
141
142
143
144 private ArrayList includes;
145
146
147
148
149
150
151
152 protected List reactorProjects;
153
154
155
156
157
158
159
160 protected boolean aggregate;
161
162
163
164
165
166
167
168 protected boolean skip;
169
170
171
172
173
174
175
176 private boolean linkJavadoc;
177
178
179
180
181
182
183
184 protected String getOutputEncoding()
185 {
186 return ( outputEncoding == null ) ? ReaderFactory.UTF_8 : outputEncoding;
187 }
188
189
190
191
192
193
194
195 protected List pruneSourceDirs( List sourceDirs )
196 {
197 List pruned = new ArrayList( sourceDirs.size() );
198 for ( Iterator i = sourceDirs.iterator(); i.hasNext(); )
199 {
200 String dir = (String) i.next();
201 if ( !pruned.contains( dir ) && hasSources( new File( dir ) ) )
202 {
203 pruned.add( dir );
204 }
205 }
206 return pruned;
207 }
208
209
210
211
212 protected void init()
213 {
214
215
216 Collection plugin = project.getReportPlugins();
217 if ( plugin != null )
218 {
219 for ( Iterator iter = plugin.iterator(); iter.hasNext(); )
220 {
221 ReportPlugin reportPlugin = (ReportPlugin) iter.next();
222 if ( "maven-javadoc-plugin".equals( reportPlugin.getArtifactId() ) )
223 {
224 break;
225 }
226 }
227 }
228 }
229
230
231
232
233
234
235
236 private boolean hasSources( File dir )
237 {
238 if ( dir.exists() && dir.isDirectory() )
239 {
240 File[] files = dir.listFiles();
241 for ( int i = 0; i < files.length; i++ )
242 {
243 File currentFile = files[i];
244 if ( currentFile.isFile() )
245 {
246 if ( currentFile.getName().endsWith( ".java" ) )
247 {
248 return true;
249 }
250 }
251 else
252 {
253 if ( Character.isJavaIdentifierStart( currentFile.getName().charAt( 0 ) )
254 && hasSources( currentFile ) )
255 {
256 return true;
257 }
258 }
259 }
260 }
261 return false;
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275 private void createXref( Locale locale, String destinationDirectory, List sourceDirs )
276 throws IOException, JxrException
277 {
278 JXR jxr = new JXR();
279 jxr.setDest( destinationDirectory );
280 if ( StringUtils.isEmpty( inputEncoding ) )
281 {
282 String platformEncoding = System.getProperty( "file.encoding" );
283 getLog().warn( "File encoding has not been set, using platform encoding " + platformEncoding
284 + ", i.e. build is platform dependent!" );
285 }
286 jxr.setInputEncoding( inputEncoding );
287 jxr.setLocale( locale );
288 jxr.setLog( new PluginLogAdapter( getLog() ) );
289 jxr.setOutputEncoding( getOutputEncoding() );
290 jxr.setRevision( "HEAD" );
291 jxr.setJavadocLinkDir( getJavadocLocation() );
292
293 if ( excludes != null && !excludes.isEmpty() )
294 {
295 jxr.setExcludes( (String[]) excludes.toArray( new String[0] ) );
296 }
297 if ( includes != null && !includes.isEmpty() )
298 {
299 jxr.setIncludes( (String[]) includes.toArray( new String[0] ) );
300 }
301
302
303 ClassLoader savedTccl = Thread.currentThread().getContextClassLoader();
304 try
305 {
306 Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
307 jxr.xref( sourceDirs, templateDir, windowTitle, docTitle, getBottomText() );
308 }
309 finally
310 {
311 Thread.currentThread().setContextClassLoader( savedTccl );
312 }
313
314
315 copyRequiredResources( destinationDirectory );
316 }
317
318
319
320
321 private String getBottomText()
322 {
323 int currentYear = Calendar.getInstance().get( Calendar.YEAR );
324 String year = String.valueOf( currentYear );
325
326 String inceptionYear = project.getInceptionYear();
327
328 String theBottom = StringUtils.replace( this.bottom, "{currentYear}", year );
329
330 if ( inceptionYear != null )
331 {
332 if ( inceptionYear.equals( year ) )
333 {
334 theBottom = StringUtils.replace( theBottom, "{inceptionYear}–", "" );
335 }
336 else
337 {
338 theBottom = StringUtils.replace( theBottom, "{inceptionYear}", inceptionYear );
339 }
340 }
341 else
342 {
343 theBottom = StringUtils.replace( theBottom, "{inceptionYear}–", "" );
344 }
345
346 if ( project.getOrganization() == null )
347 {
348 theBottom = StringUtils.replace( theBottom, " {organizationName}", "" );
349 }
350 else
351 {
352 if ( StringUtils.isNotEmpty( project.getOrganization().getName() ) )
353 {
354 if ( StringUtils.isNotEmpty( project.getOrganization().getUrl() ) )
355 {
356 theBottom = StringUtils.replace( theBottom, "{organizationName}",
357 "<a href=\"" + project.getOrganization().getUrl() + "\">"
358 + project.getOrganization().getName() + "</a>" );
359 }
360 else
361 {
362 theBottom =
363 StringUtils.replace( theBottom, "{organizationName}", project.getOrganization().getName() );
364 }
365 }
366 else
367 {
368 theBottom = StringUtils.replace( theBottom, " {organizationName}", "" );
369 }
370 }
371
372 return theBottom;
373 }
374
375
376
377
378
379
380
381 private void copyRequiredResources( String dir )
382 {
383 File stylesheetFile = new File( stylesheet );
384 File destStylesheetFile = new File( dir, "stylesheet.css" );
385
386 try
387 {
388 if ( stylesheetFile.isAbsolute() )
389 {
390 FileUtils.copyFile( stylesheetFile, destStylesheetFile );
391 }
392 else
393 {
394 URL stylesheetUrl = this.getClass().getClassLoader().getResource( stylesheet );
395 FileUtils.copyURLToFile( stylesheetUrl, destStylesheetFile );
396 }
397 }
398 catch ( IOException e )
399 {
400 getLog().warn( "An error occured while copying the stylesheet to the target directory", e );
401 }
402
403 }
404
405
406
407
408 protected Renderer getSiteRenderer()
409 {
410 return siteRenderer;
411 }
412
413
414
415
416 protected String getOutputDirectory()
417 {
418 return outputDirectory.getAbsolutePath();
419 }
420
421
422
423
424 public MavenProject getProject()
425 {
426 return project;
427 }
428
429
430
431
432
433
434
435 protected ResourceBundle getBundle( Locale locale )
436 {
437 return ResourceBundle.getBundle( "jxr-report", locale, this.getClass().getClassLoader() );
438 }
439
440
441
442
443
444 protected boolean canGenerateReport( List sourceDirs )
445 {
446 boolean canGenerate = !sourceDirs.isEmpty();
447
448 if ( isAggregate() && !project.isExecutionRoot() )
449 {
450 canGenerate = false;
451 }
452 return canGenerate;
453 }
454
455
456
457
458
459
460 public void execute()
461 throws MojoExecutionException
462 {
463
464 if ( skip )
465 {
466 getLog().info( "Skipping JXR." );
467 return;
468 }
469
470 Locale locale = Locale.getDefault();
471 try
472 {
473 executeReport( locale );
474 }
475 catch ( MavenReportException e )
476 {
477 throw new MojoExecutionException( "Error generating JXR report", e );
478 }
479 }
480
481
482
483
484 protected void executeReport( Locale locale )
485 throws MavenReportException
486 {
487 if ( skip )
488 {
489 getLog().info( "Skipping JXR." );
490 return;
491 }
492 List sourceDirs = constructSourceDirs();
493 if ( canGenerateReport( sourceDirs ) )
494 {
495
496 init();
497
498 try
499 {
500 createXref( locale, getDestinationDirectory(), sourceDirs );
501 }
502 catch ( JxrException e )
503 {
504 throw new MavenReportException( "Error while generating the HTML source code of the projet.", e );
505 }
506 catch ( IOException e )
507 {
508 throw new MavenReportException( "Error while generating the HTML source code of the projet.", e );
509 }
510 }
511 }
512
513
514
515
516
517
518 protected List constructSourceDirs()
519 {
520 List sourceDirs = new ArrayList( getSourceRoots() );
521 if ( isAggregate() )
522 {
523 for ( Iterator i = reactorProjects.iterator(); i.hasNext(); )
524 {
525 MavenProject project = (MavenProject) i.next();
526
527 if ( "java".equals( project.getArtifact().getArtifactHandler().getLanguage() ) )
528 {
529 sourceDirs.addAll( getSourceRoots( project ) );
530 }
531 }
532 }
533
534 sourceDirs = pruneSourceDirs( sourceDirs );
535 return sourceDirs;
536 }
537
538
539
540
541 public boolean canGenerateReport()
542 {
543 return canGenerateReport( constructSourceDirs() );
544 }
545
546
547
548
549 public boolean isExternalReport()
550 {
551 return true;
552 }
553
554
555
556
557 private String getJavadocLocation()
558 throws IOException
559 {
560 String location = null;
561 if ( linkJavadoc )
562 {
563
564
565 if ( getJavadocDir().exists() )
566 {
567
568 location = getJavadocDir().getAbsolutePath();
569 }
570 else
571 {
572
573
574
575 String stagingDirectory = System.getProperty( "stagingDirectory" );
576
577 if ( StringUtils.isNotEmpty( stagingDirectory ) )
578 {
579 String javadocDestDir = getJavadocDir().getName();
580 boolean javadocAggregate = JxrReportUtil.isJavadocAggregated( project );
581 String structureProject = JxrReportUtil.getStructure( project, false );
582
583 if ( isAggregate() && javadocAggregate )
584 {
585 File outputDirectory = new File( stagingDirectory, structureProject );
586 location = outputDirectory + "/" + javadocDestDir;
587 }
588 if ( !isAggregate() && javadocAggregate )
589 {
590 location = stagingDirectory + "/" + javadocDestDir;
591
592 String hierarchy = project.getName();
593
594 MavenProject parent = project.getParent();
595 while ( parent != null )
596 {
597 hierarchy = parent.getName();
598 parent = parent.getParent();
599 }
600 File outputDirectory = new File( stagingDirectory, hierarchy );
601 location = outputDirectory + "/" + javadocDestDir;
602 }
603 if ( isAggregate() && !javadocAggregate )
604 {
605 getLog().warn( "The JXR plugin is configured to build an aggregated report at the root, "
606 + "not the Javadoc plugin." );
607 }
608 if ( !isAggregate() && !javadocAggregate )
609 {
610 location = stagingDirectory + "/" + structureProject + "/" + javadocDestDir;
611 }
612 }
613 else
614 {
615 location = getJavadocDir().getAbsolutePath();
616 }
617 }
618
619 if ( location == null )
620 {
621 getLog().warn( "Unable to locate Javadoc to link to - DISABLED" );
622 }
623 }
624
625 return location;
626 }
627
628
629
630
631
632
633 protected abstract String getDestinationDirectory();
634
635
636
637
638
639
640 protected abstract List getSourceRoots();
641
642
643
644
645
646
647
648
649 protected abstract List getSourceRoots( MavenProject project );
650
651
652
653
654
655
656 protected abstract File getJavadocDir();
657
658
659
660
661
662
663 protected boolean isAggregate()
664 {
665 return aggregate;
666 }
667 }