View Javadoc
1   package org.apache.maven.plugin.javadoc;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.doxia.module.xhtml.decoration.render.RenderingContext;
23  import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.plugin.MojoFailureException;
26  import org.apache.maven.plugins.annotations.Execute;
27  import org.apache.maven.plugins.annotations.LifecyclePhase;
28  import org.apache.maven.plugins.annotations.Mojo;
29  import org.apache.maven.plugins.annotations.Parameter;
30  import org.apache.maven.plugins.annotations.ResolutionScope;
31  import org.apache.maven.reporting.MavenReport;
32  import org.apache.maven.reporting.MavenReportException;
33  import org.codehaus.doxia.sink.Sink;
34  import org.codehaus.plexus.util.StringUtils;
35  
36  import java.io.File;
37  import java.util.List;
38  import java.util.Locale;
39  import java.util.ResourceBundle;
40  
41  /**
42   * Generates documentation for the <code>Java code</code> in an <b>NON aggregator</b> project using the standard
43   * <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/">Javadoc Tool</a>.
44   *
45   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
46   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
47   * @version $Id: JavadocReport.html 922314 2014-09-15 20:18:14Z dennisl $
48   * @since 2.0
49   * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/">Javadoc Tool</a>
50   * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#options">Javadoc Options</a>
51   */
52  @Mojo( name = "javadoc", requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true )
53  @Execute( phase = LifecyclePhase.GENERATE_SOURCES )
54  public class JavadocReport
55      extends AbstractJavadocMojo
56      implements MavenReport
57  {
58      // ----------------------------------------------------------------------
59      // Report Mojo Parameters
60      // ----------------------------------------------------------------------
61  
62      /**
63       * Specifies the destination directory where javadoc saves the generated HTML files.
64       */
65      @Parameter( property = "reportOutputDirectory", defaultValue = "${project.reporting.outputDirectory}/apidocs",
66                  required = true )
67      private File reportOutputDirectory;
68  
69      /**
70       * The name of the destination directory.
71       * <br/>
72       *
73       * @since 2.1
74       */
75      @Parameter( property = "destDir", defaultValue = "apidocs" )
76      private String destDir;
77  
78      /**
79       * The name of the Javadoc report to be displayed in the Maven Generated Reports page
80       * (i.e. <code>project-reports.html</code>).
81       *
82       * @since 2.1
83       */
84      @Parameter( property = "name" )
85      private String name;
86  
87      /**
88       * The description of the Javadoc report to be displayed in the Maven Generated Reports page
89       * (i.e. <code>project-reports.html</code>).
90       *
91       * @since 2.1
92       */
93      @Parameter( property = "description" )
94      private String description;
95  
96      // ----------------------------------------------------------------------
97      // Report public methods
98      // ----------------------------------------------------------------------
99  
100     /** {@inheritDoc} */
101     public String getName( Locale locale )
102     {
103         if ( StringUtils.isEmpty( name ) )
104         {
105             return getBundle( locale ).getString( "report.javadoc.name" );
106         }
107 
108         return name;
109     }
110 
111     /** {@inheritDoc} */
112     public String getDescription( Locale locale )
113     {
114         if ( StringUtils.isEmpty( description ) )
115         {
116             return getBundle( locale ).getString( "report.javadoc.description" );
117         }
118 
119         return description;
120     }
121 
122     /** {@inheritDoc} */
123     public void generate( Sink sink, Locale locale )
124         throws MavenReportException
125     {
126         outputDirectory = getReportOutputDirectory();
127 
128         try
129         {
130             executeReport( locale );
131         }
132         catch ( MavenReportException e )
133         {
134             if ( failOnError )
135             {
136                 throw e;
137             }
138             getLog().error( "Error while creating javadoc report: " + e.getMessage(), e );
139         }
140         catch ( RuntimeException e )
141         {
142             if ( failOnError )
143             {
144                 throw e;
145             }
146             getLog().error( "Error while creating javadoc report: " + e.getMessage(), e );
147         }
148     }
149 
150     /** {@inheritDoc} */
151     public String getOutputName()
152     {
153         return destDir + "/index";
154     }
155 
156     /** {@inheritDoc} */
157     public boolean isExternalReport()
158     {
159         return true;
160     }
161 
162     /**
163      * {@inheritDoc}
164      *
165      * <br/>
166      * The logic is the following:
167      * <table>
168      *   <tbody>
169      *     <tr>
170      *       <th> isAggregator </th>
171      *       <th> hasSourceFiles </th>
172      *       <th> isRootProject </th>
173      *       <th> Generate Report </th>
174      *     </tr>
175      *     <tr>
176      *       <td>True</td>
177      *       <td>True</td>
178      *       <td>True</td>
179      *       <td>True</td>
180      *     </tr>
181      *     <tr>
182      *       <td>True</td>
183      *       <td>True</td>
184      *       <td>False</td>
185      *       <td>False</td>
186      *     </tr>
187      *     <tr>
188      *       <td>True</td>
189      *       <td>False</td>
190      *       <td>True</td>
191      *       <td>False</td>
192      *     </tr>
193      *     <tr>
194      *       <td>True</td>
195      *       <td>False</td>
196      *       <td>False</td>
197      *       <td>False</td>
198      *     </tr>
199      *     <tr>
200      *       <td>False</td>
201      *       <td>True</td>
202      *       <td>True</td>
203      *       <td>True</td>
204      *     </tr>
205      *     <tr>
206      *       <td>False</td>
207      *       <td>True</td>
208      *       <td>False</td>
209      *       <td>True</td>
210      *     </tr>
211      *     <tr>
212      *        <td>False</td>
213      *        <td>False</td>
214      *        <td>True</td>
215      *        <td>False</td>
216      *      </tr>
217      *      <tr>
218      *        <td>False</td>
219      *        <td>False</td>
220      *        <td>False</td>
221      *        <td>False</td>
222      *      </tr>
223      *    </tbody>
224      *  </table>
225      */
226     public boolean canGenerateReport()
227     {
228         boolean canGenerate = false;
229 
230         if ( !this.isAggregator() || ( this.isAggregator() && this.project.isExecutionRoot() ) )
231         {
232             List<String> sourcePaths;
233             List<String> files;
234             try
235             {
236                 sourcePaths = getSourcePaths();
237                 files = getFiles( sourcePaths );
238             }
239             catch ( MavenReportException e )
240             {
241                 getLog().error( e.getMessage(), e );
242                 return false;
243             }
244 
245             canGenerate = canGenerateReport( files );
246         }
247         if ( getLog().isDebugEnabled() )
248         {
249             getLog().debug( " canGenerateReport = " + canGenerate + " for project " + this.project );
250         }
251         return canGenerate;
252     }
253 
254     /** {@inheritDoc} */
255     public String getCategoryName()
256     {
257         return CATEGORY_PROJECT_REPORTS;
258     }
259 
260     /** {@inheritDoc} */
261     public File getReportOutputDirectory()
262     {
263         if ( reportOutputDirectory == null )
264         {
265             return outputDirectory;
266         }
267 
268         return reportOutputDirectory;
269     }
270 
271     /**
272      * Method to set the directory where the generated reports will be put
273      *
274      * @param reportOutputDirectory the directory file to be set
275      */
276     public void setReportOutputDirectory( File reportOutputDirectory )
277     {
278         updateReportOutputDirectory( reportOutputDirectory, destDir );
279     }
280 
281     public void setDestDir( String destDir )
282     {
283         this.destDir = destDir;
284         updateReportOutputDirectory( reportOutputDirectory, destDir );
285     }
286 
287     private void updateReportOutputDirectory( File reportOutputDirectory, String destDir )
288     {
289         if ( reportOutputDirectory != null && destDir != null
290              && !reportOutputDirectory.getAbsolutePath().endsWith( destDir ) )
291         {
292             this.reportOutputDirectory = new File( reportOutputDirectory, destDir );
293         }
294         else
295         {
296             this.reportOutputDirectory = reportOutputDirectory;
297         }
298     }
299 
300     /** {@inheritDoc} */
301     public void execute()
302         throws MojoExecutionException, MojoFailureException
303     {
304         if ( skip )
305         {
306             getLog().info( "Skipping javadoc generation" );
307             return;
308         }
309 
310         try
311         {
312             RenderingContext context = new RenderingContext( outputDirectory, getOutputName() + ".html" );
313             SiteRendererSink sink = new SiteRendererSink( context );
314             Locale locale = Locale.getDefault();
315             generate( sink, locale );
316         }
317         catch ( MavenReportException e )
318         {
319             failOnError( "An error has occurred in " + getName( Locale.ENGLISH ) + " report generation", e );
320         }
321         catch ( RuntimeException e )
322         {
323             failOnError( "An error has occurred in " + getName( Locale.ENGLISH ) + " report generation", e );
324         }
325     }
326 
327     @Override
328     protected boolean isAggregator()
329     {
330         // only here for backward compatibility, this flag does not work reliably
331         return aggregate;
332     }
333 
334     /**
335      * Gets the resource bundle for the specified locale.
336      *
337      * @param locale The locale of the currently generated report.
338      * @return The resource bundle for the requested locale.
339      */
340     private ResourceBundle getBundle( Locale locale )
341     {
342         return ResourceBundle.getBundle( "javadoc-report", locale, getClass().getClassLoader() );
343     }
344 }