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