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 org.apache.maven.archiver.MavenArchiveConfiguration;
23  import org.apache.maven.archiver.MavenArchiver;
24  import org.apache.maven.artifact.DependencyResolutionRequiredException;
25  import org.apache.maven.artifact.handler.ArtifactHandler;
26  import org.apache.maven.model.Resource;
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugins.annotations.Component;
29  import org.apache.maven.plugins.annotations.LifecyclePhase;
30  import org.apache.maven.plugins.annotations.Mojo;
31  import org.apache.maven.plugins.annotations.Parameter;
32  import org.apache.maven.plugins.annotations.ResolutionScope;
33  import org.apache.maven.project.MavenProjectHelper;
34  import org.apache.maven.reporting.MavenReportException;
35  import org.codehaus.plexus.archiver.Archiver;
36  import org.codehaus.plexus.archiver.ArchiverException;
37  import org.codehaus.plexus.archiver.jar.JarArchiver;
38  import org.codehaus.plexus.archiver.jar.ManifestException;
39  
40  import java.io.File;
41  import java.io.IOException;
42  import java.util.List;
43  import java.util.Locale;
44  
45  /**
46   * Bundles the Javadoc documentation for <code>main Java code</code> in an <b>NON aggregator</b> project into
47   * a jar using the standard <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/">Javadoc Tool</a>.
48   *
49   * @version $Id: JavadocJar.java 1752018 2016-07-09 16:35:25Z rfscholte $
50   * @since 2.0
51   */
52  @Mojo( name = "jar", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE,
53                  threadSafe = true )
54  public class JavadocJar
55      extends AbstractJavadocMojo
56  {
57      /**
58       * Includes all generated Javadoc files
59       */
60      private static final String[] DEFAULT_INCLUDES = new String[]{ "**/**" };
61  
62      /**
63       * Excludes all processing files.
64       *
65       * @see AbstractJavadocMojo#DEBUG_JAVADOC_SCRIPT_NAME
66       * @see AbstractJavadocMojo#OPTIONS_FILE_NAME
67       * @see AbstractJavadocMojo#PACKAGES_FILE_NAME
68       * @see AbstractJavadocMojo#ARGFILE_FILE_NAME
69       * @see AbstractJavadocMojo#FILES_FILE_NAME
70       */
71      private static final String[] DEFAULT_EXCLUDES =
72          new String[]{ DEBUG_JAVADOC_SCRIPT_NAME, OPTIONS_FILE_NAME, PACKAGES_FILE_NAME, ARGFILE_FILE_NAME,
73              FILES_FILE_NAME };
74  
75      // ----------------------------------------------------------------------
76      // Mojo components
77      // ----------------------------------------------------------------------
78  
79      /**
80       * Used for attaching the artifact in the project.
81       */
82      @Component
83      private MavenProjectHelper projectHelper;
84  
85      /**
86       * The Jar archiver.
87       *
88       * @since 2.5
89       */
90      @Component( role = Archiver.class, hint = "jar" )
91      private JarArchiver jarArchiver;
92  
93      // ----------------------------------------------------------------------
94      // Mojo Parameters
95      // ----------------------------------------------------------------------
96  
97      /**
98       * Specifies the destination directory where javadoc saves the generated HTML files.
99       * See <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javadoc.html#d">d</a>.
100      *
101      * @deprecated
102      */
103     @Deprecated
104     @Parameter( property = "destDir" )
105     private File destDir;
106 
107     /**
108      * Specifies the directory where the generated jar file will be put.
109      */
110     @Parameter( property = "project.build.directory" )
111     private String jarOutputDirectory;
112 
113     /**
114      * Specifies the filename that will be used for the generated jar file. Please note that <code>-javadoc</code>
115      * or <code>-test-javadoc</code> will be appended to the file name.
116      */
117     @Parameter( property = "project.build.finalName" )
118     private String finalName;
119 
120     /**
121      * Specifies whether to attach the generated artifact to the project helper.
122      * <br/>
123      */
124     @Parameter( property = "attach", defaultValue = "true" )
125     private boolean attach;
126 
127     /**
128      * The archive configuration to use.
129      * See <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver Reference</a>.
130      *
131      * @since 2.5
132      */
133     @Parameter
134     private MavenArchiveConfiguration archive = new JavadocArchiveConfiguration();
135 
136     /**
137      * Path to the default MANIFEST file to use. It will be used if
138      * <code>useDefaultManifestFile</code> is set to <code>true</code>.
139      *
140      * @since 2.5
141      */
142     @Parameter( defaultValue = "${project.build.outputDirectory}/META-INF/MANIFEST.MF", required = true,
143                 readonly = true )
144     private File defaultManifestFile;
145 
146     /**
147      * Set this to <code>true</code> to enable the use of the <code>defaultManifestFile</code>.
148      * <br/>
149      *
150      * @since 2.5
151      */
152     @Parameter( defaultValue = "false" )
153     private boolean useDefaultManifestFile;
154 
155     /**
156      * @since 2.10
157      */
158     @Parameter( property = "maven.javadoc.classifier", defaultValue = "javadoc", required = true )
159     private String classifier;
160 
161     /** {@inheritDoc} */
162     @Override
163     public void doExecute()
164         throws MojoExecutionException
165     {
166         if ( skip )
167         {
168             getLog().info( "Skipping javadoc generation" );
169             return;
170         }
171 
172         File innerDestDir = this.destDir;
173         if ( innerDestDir == null )
174         {
175             innerDestDir = new File( getOutputDirectory() );
176         }
177 
178         if ( !( "pom".equalsIgnoreCase( project.getPackaging() ) && isAggregator() ) )
179         {
180             ArtifactHandler artifactHandler = project.getArtifact().getArtifactHandler();
181             if ( !"java".equals( artifactHandler.getLanguage() ) )
182             {
183                 getLog().info( "Not executing Javadoc as the project is not a Java classpath-capable package" );
184                 return;
185             }
186         }
187 
188         try
189         {
190             executeReport( Locale.getDefault() );
191         }
192         catch ( MavenReportException e )
193         {
194             failOnError( "MavenReportException: Error while generating Javadoc", e );
195         }
196         catch ( RuntimeException e )
197         {
198             failOnError( "RuntimeException: Error while generating Javadoc", e );
199         }
200 
201         if ( innerDestDir.exists() )
202         {
203             try
204             {
205                 File outputFile = generateArchive( innerDestDir, finalName + "-" + getClassifier() + ".jar" );
206 
207                 if ( !attach )
208                 {
209                     getLog().info( "NOT adding javadoc to attached artifacts list." );
210                 }
211                 else
212                 {
213                     // TODO: these introduced dependencies on the project are going to become problematic - can we export it
214                     //  through metadata instead?
215                     projectHelper.attachArtifact( project, "javadoc", getClassifier(), outputFile );
216                 }
217             }
218             catch ( ArchiverException e )
219             {
220                 failOnError( "ArchiverException: Error while creating archive", e );
221             }
222             catch ( IOException e )
223             {
224                 failOnError( "IOException: Error while creating archive", e );
225             }
226             catch ( RuntimeException e )
227             {
228                 failOnError( "RuntimeException: Error while creating archive", e );
229             }
230         }
231     }
232 
233     // ----------------------------------------------------------------------
234     // Protected methods
235     // ----------------------------------------------------------------------
236 
237     /**
238      * @return the wanted classifier, i.e. <code>javadoc</code> or <code>test-javadoc</code>
239      */
240     protected String getClassifier()
241     {
242         return classifier;
243     }
244 
245     // ----------------------------------------------------------------------
246     // private methods
247     // ----------------------------------------------------------------------
248 
249     /**
250      * Method that creates the jar file
251      *
252      * @param javadocFiles the directory where the generated jar file will be put
253      * @param jarFileName the filename of the generated jar file
254      * @return a File object that contains the generated jar file
255      * @throws ArchiverException {@link ArchiverException}
256      * @throws IOException {@link IOException}
257      */
258     private File generateArchive( File javadocFiles, String jarFileName )
259         throws ArchiverException, IOException
260     {
261         File javadocJar = new File( jarOutputDirectory, jarFileName );
262 
263         if ( javadocJar.exists() )
264         {
265             javadocJar.delete();
266         }
267 
268         MavenArchiver archiver = new MavenArchiver();
269         archiver.setArchiver( jarArchiver );
270         archiver.setOutputFile( javadocJar );
271 
272         File contentDirectory = javadocFiles;
273         if ( !contentDirectory.exists() )
274         {
275             getLog().warn( "JAR will be empty - no content was marked for inclusion!" );
276         }
277         else
278         {
279             archiver.getArchiver().addDirectory( contentDirectory, DEFAULT_INCLUDES, DEFAULT_EXCLUDES );
280         }
281 
282         List<Resource> resources = project.getBuild().getResources();
283 
284         for ( Resource r : resources )
285         {
286             if ( r.getDirectory().endsWith( "maven-shared-archive-resources" ) )
287             {
288                 archiver.getArchiver().addDirectory( new File( r.getDirectory() ) );
289             }
290         }
291 
292         if ( useDefaultManifestFile && defaultManifestFile.exists() && archive.getManifestFile() == null )
293         {
294             getLog().info( "Adding existing MANIFEST to archive. Found under: " + defaultManifestFile.getPath() );
295             archive.setManifestFile( defaultManifestFile );
296         }
297 
298         try
299         {
300             archiver.createArchive( session, project, archive );
301         }
302         catch ( ManifestException e )
303         {
304             throw new ArchiverException( "ManifestException: " + e.getMessage(), e );
305         }
306         catch ( DependencyResolutionRequiredException e )
307         {
308             throw new ArchiverException( "DependencyResolutionRequiredException: " + e.getMessage(), e );
309         }
310 
311         return javadocJar;
312     }
313 }