View Javadoc

1   package org.apache.maven.plugin.jxr;
2   
3   /*
4    * Copyright 2004-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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 &copy; ${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      * Tells whether Javadoc is part of the reports being generated during the build
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         // init some attributes
144         init();
145 
146         // and start the report 
147         Sink sink = getSink();
148 
149         startSink( sink, locale );
150 
151         // check if there are sources in the sourceDir and generate Xref
152         generateXrefForSources( locale, sink );
153 
154         // check if there are test sources in the testSourceDir and generate Xref
155         generateXrefForTests( locale, sink );
156 
157         endSink( sink );
158     }
159 
160     /*
161      * Generates the Xref for the application sources if they exist
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                 // create the XRef for the source dir
176                 createXref( locale, destDir, sourceDirs );
177 
178                 // put the link to the sources
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      * Generates the Xref for the test sources if they exist
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                 // create the XRef for the source dir
232                 createXref( locale, testDestDir, testSourceDirs );
233 
234                 // put the link to the sources
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      * Initialize some attributes required during the report generation
258      */
259     private void init()
260     {
261         // wanna know if Javadoc is being generated
262         // TODO: what if it is not part of the site though, and just on the command line?
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         // and finally copy the stylesheet
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 }