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 import org.apache.maven.jxr.JXR;
20 import org.apache.maven.model.ReportPlugin;
21 import org.apache.maven.project.MavenProject;
22 import org.apache.maven.reporting.AbstractMavenReport;
23 import org.apache.maven.reporting.MavenReportException;
24 import org.codehaus.doxia.sink.Sink;
25 import org.codehaus.doxia.site.renderer.SiteRenderer;
26 import org.codehaus.plexus.util.FileUtils;
27
28 import java.io.File;
29 import java.io.IOException;
30 import java.net.URL;
31 import java.util.Collection;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Locale;
35 import java.util.ResourceBundle;
36
37 /***
38 * MOJO for the JXR report.<br>
39 * Creates an html-based, cross referenced version of Java source code
40 * for a project.
41 *
42 * @author <a href="mailto:bellingard.NO-SPAM@gmail.com">Fabrice Bellingard</a>
43 * @goal jxr
44 */
45 public class JxrReport
46 extends AbstractMavenReport
47 {
48
49 /***
50 * @parameter expression="${project}"
51 * @required @readonly
52 */
53 private MavenProject project;
54
55 /***
56 * @parameter expression="${component.org.codehaus.doxia.site.renderer.SiteRenderer}"
57 * @required @readonly
58 */
59 private SiteRenderer siteRenderer;
60
61 /***
62 * @parameter expression="${project.compileSourceRoots}"
63 * @required
64 * @readonly
65 */
66 private List sourceDirs;
67
68 /***
69 * @parameter expression="${project.testCompileSourceRoots}"
70 * @required
71 * @readonly
72 */
73 private List testSourceDirs;
74
75 /***
76 * @parameter expression="${project.build.directory}/site"
77 * @required
78 */
79 private String outputDirectory;
80
81 /***
82 * @parameter expression="${project.build.directory}/site/xref"
83 */
84 private String destDir;
85
86 /***
87 * @parameter default-value="ISO-8859-1"
88 */
89 private String inputEncoding;
90
91 /***
92 * @parameter default-value="ISO-8859-1"
93 */
94 private String outputEncoding;
95
96 /***
97 * @parameter expression="${project.build.directory}/site/apidocs"
98 */
99 private String javadocDir;
100
101 /***
102 * @parameter expression="${project.name} ${project.version} Reference"
103 */
104 private String windowTitle;
105
106 /***
107 * @parameter expression="${project.name} ${project.version} Reference"
108 */
109 private String docTitle;
110
111 /***
112 * @parameter expression="Copyright © ${project.inceptionYear} ${project.organization.name}. All Rights Reserved."
113 */
114 private String bottom;
115
116 /***
117 * Directory where Velocity templates can be found to generate overviews,
118 * frames and summaries.<br>
119 * Should not be used. If used, should be an absolute path, like "${basedir}/myTemplates".
120 *
121 * @parameter default-value="templates"
122 */
123 private String templateDir;
124
125 /***
126 * @parameter default-value="stylesheet.css"
127 */
128 private String stylesheet;
129
130
131
132
133 private boolean javadocReportGenerated;
134
135 /***
136 * Cf. overriden method documentation.
137 *
138 * @see org.apache.maven.reporting.AbstractMavenReport#executeReport(java.util.Locale)
139 */
140 protected void executeReport( Locale locale )
141 throws MavenReportException
142 {
143
144 init();
145
146
147 Sink sink = getSink();
148
149 startSink( sink, locale );
150
151
152 generateXrefForSources( locale, sink );
153
154
155 generateXrefForTests( locale, sink );
156
157 endSink( sink );
158 }
159
160
161
162
163 private void generateXrefForSources( Locale locale, Sink sink )
164 throws MavenReportException
165 {
166 sink.section2();
167 sink.sectionTitle2();
168 sink.text( getBundle( locale ).getString( "report.xref.projectSources.title" ) );
169 sink.sectionTitle2_();
170 sink.paragraph();
171 if ( hasSources( sourceDirs ) )
172 {
173 try
174 {
175
176 createXref( locale, destDir, sourceDirs );
177
178
179 sink.text( getBundle( locale ).getString( "report.xref.projectSources.link" ) );
180 File out = new File( outputDirectory );
181 File des = new File( destDir );
182 String relativPath = des.getAbsolutePath().substring( out.getAbsolutePath().length() + 1 );
183 sink.link( relativPath + "/index.html" );
184 sink.text( relativPath + "/index.html" );
185 sink.link_();
186 }
187 catch ( Exception e )
188 {
189 throw new MavenReportException( "Error while generating the HTML source code of the projet.", e );
190 }
191 }
192 else
193 {
194 sink.text( getBundle( locale ).getString( "report.xref.projectSources.noSources" ) );
195 }
196 sink.paragraph_();
197 sink.section2_();
198 }
199
200 private boolean hasSources( List sourceDirs )
201 {
202 boolean found = false;
203 for ( Iterator i = sourceDirs.iterator(); i.hasNext() && !found; )
204 {
205 String dir = (String) i.next();
206 if ( hasSources( new File( dir ) ) )
207 {
208 found = true;
209 }
210 }
211 return found;
212 }
213
214
215
216
217 private void generateXrefForTests( Locale locale, Sink sink )
218 throws MavenReportException
219 {
220 sink.section2();
221 sink.sectionTitle2();
222 sink.text( getBundle( locale ).getString( "report.xref.testSources.title" ) );
223 sink.sectionTitle2_();
224 sink.paragraph();
225 if ( hasSources( testSourceDirs ) )
226 {
227 try
228 {
229 String testDestDir = destDir + "-test";
230
231
232 createXref( locale, testDestDir, testSourceDirs );
233
234
235 sink.text( getBundle( locale ).getString( "report.xref.testSources.link" ) );
236 File out = new File( outputDirectory );
237 File des = new File( testDestDir );
238 String relativPath = des.getAbsolutePath().substring( out.getAbsolutePath().length() + 1 );
239 sink.link( relativPath + "/index.html" );
240 sink.text( relativPath + "/index.html" );
241 sink.link_();
242 }
243 catch ( Exception e )
244 {
245 throw new MavenReportException( "Error while generating the HTML source code of the projet.", e );
246 }
247 }
248 else
249 {
250 sink.text( getBundle( locale ).getString( "report.xref.testSources.noSources" ) );
251 }
252 sink.paragraph_();
253 sink.section2_();
254 }
255
256
257
258
259 private void init()
260 {
261
262
263 Collection plugin = getProject().getReportPlugins();
264 if ( plugin != null )
265 {
266 for ( Iterator iter = plugin.iterator(); iter.hasNext(); )
267 {
268 ReportPlugin reportPlugin = (ReportPlugin) iter.next();
269 if ( "maven-javadoc-plugin".equals( reportPlugin.getArtifactId() ) )
270 {
271 javadocReportGenerated = true;
272 break;
273 }
274 }
275 }
276 }
277
278 /***
279 * Writes the beginning of the sink.
280 *
281 * @param sink
282 * @param locale
283 */
284 private void startSink( Sink sink, Locale locale )
285 {
286 sink.head();
287 sink.title();
288 sink.text( getBundle( locale ).getString( "report.xref.header" ) );
289 sink.title_();
290 sink.head_();
291
292 sink.body();
293 sink.section1();
294
295 sink.sectionTitle1();
296 sink.text( getBundle( locale ).getString( "report.xref.mainTitle" ) );
297 sink.sectionTitle1_();
298
299 sink.paragraph();
300 sink.text( getBundle( locale ).getString( "report.xref.summary" ) );
301 sink.paragraph_();
302 }
303
304 /***
305 * Writes the end of the sink.
306 *
307 * @param sink
308 */
309 private void endSink( Sink sink )
310 {
311 sink.section1_();
312 sink.body_();
313 sink.flush();
314 sink.close();
315 }
316
317 /***
318 * Checks whether the given directory contains Java files.
319 *
320 * @param dir the source directory
321 * @return true if the folder or one of its subfolders coantins at least 1 Java file
322 */
323 private boolean hasSources( File dir )
324 {
325 if ( !dir.exists() || !dir.isDirectory() )
326 {
327 return false;
328 }
329 File[] files = dir.listFiles();
330 for ( int i = 0; i < files.length; i++ )
331 {
332 File currentFile = files[i];
333 if ( currentFile.isFile() && currentFile.getName().endsWith( ".java" ) )
334 {
335 return true;
336 }
337 else if ( currentFile.isDirectory() )
338 {
339 boolean hasSources = hasSources( currentFile );
340 if ( hasSources )
341 {
342 return true;
343 }
344 }
345 }
346 return false;
347 }
348
349 /***
350 * Creates the Xref for the Java files found in the given source directory and puts
351 * them in the given destination directory.
352 *
353 * @param locale The user locale to use for the Xref generation
354 * @param destinationDirectory The output folder
355 * @param sourceDirs The source directories
356 * @throws IOException
357 * @throws Exception
358 */
359 private void createXref( Locale locale, String destinationDirectory, List sourceDirs )
360 throws IOException, Exception
361 {
362 JXR jxr = new JXR();
363 jxr.setDest( destinationDirectory );
364 jxr.setInputEncoding( inputEncoding );
365 jxr.setJavadocLinkDir( javadocDir );
366 jxr.setLocale( locale );
367 jxr.setLog( new PluginLogAdapter( getLog() ) );
368 jxr.setOutputEncoding( outputEncoding );
369 jxr.setRevision( "HEAD" );
370
371 jxr.xref( sourceDirs, templateDir, windowTitle, docTitle, bottom );
372
373
374 copyRequiredResources( destinationDirectory );
375 }
376
377 /***
378 * Copy some required resources (like the stylesheet) to the
379 * given directory
380 *
381 * @param dir the directory to copy the resources to
382 */
383 private void copyRequiredResources( String dir )
384 {
385 File stylesheetFile = new File( stylesheet );
386 File destStylesheetFile = new File( dir, "stylesheet.css" );
387
388 try
389 {
390 if ( stylesheetFile.isAbsolute() )
391 {
392 FileUtils.copyFile( stylesheetFile, destStylesheetFile );
393 }
394 else
395 {
396 URL stylesheetUrl = this.getClass().getClassLoader().getResource( stylesheet );
397 FileUtils.copyURLToFile( stylesheetUrl, destStylesheetFile );
398 }
399 }
400 catch ( IOException e )
401 {
402 getLog().warn( "An error occured while copying the stylesheet to the target directory", e );
403 }
404
405 }
406
407 /***
408 * Cf. overriden method documentation.
409 *
410 * @see org.apache.maven.reporting.AbstractMavenReport#getSiteRenderer()
411 */
412 protected SiteRenderer getSiteRenderer()
413 {
414 return siteRenderer;
415 }
416
417 /***
418 * Cf. overriden method documentation.
419 *
420 * @see org.apache.maven.reporting.AbstractMavenReport#getOutputDirectory()
421 */
422 protected String getOutputDirectory()
423 {
424 return outputDirectory;
425 }
426
427 /***
428 * Cf. overriden method documentation.
429 *
430 * @see org.apache.maven.reporting.AbstractMavenReport#getProject()
431 */
432 public MavenProject getProject()
433 {
434 return project;
435 }
436
437 /***
438 * Cf. overriden method documentation.
439 *
440 * @see org.apache.maven.reporting.MavenReport#getDescription(java.util.Locale)
441 */
442 public String getDescription( Locale locale )
443 {
444 return getBundle( locale ).getString( "report.xref.description" );
445 }
446
447 /***
448 * Cf. overriden method documentation.
449 *
450 * @see org.apache.maven.reporting.MavenReport#getName(java.util.Locale)
451 */
452 public String getName( Locale locale )
453 {
454 return getBundle( locale ).getString( "report.xref.name" );
455 }
456
457 /***
458 * Cf. overriden method documentation.
459 *
460 * @see org.apache.maven.reporting.MavenReport#getOutputName()
461 */
462 public String getOutputName()
463 {
464 return "jxr";
465 }
466
467 /***
468 * Returns the correct resource bundle according to the locale
469 *
470 * @param locale :
471 * the locale of the user
472 * @return the bundle correponding to the locale
473 */
474 private ResourceBundle getBundle( Locale locale )
475 {
476 return ResourceBundle.getBundle( "jxr-report", locale, this.getClass().getClassLoader() );
477 }
478
479 }