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