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