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 java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.URI;
27 import java.net.URISyntaxException;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Calendar;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Locale;
38 import java.util.Map;
39 import java.util.Properties;
40 import java.util.Set;
41 import java.util.StringTokenizer;
42
43 import org.apache.commons.lang.ClassUtils;
44 import org.apache.commons.lang.SystemUtils;
45 import org.apache.maven.artifact.Artifact;
46 import org.apache.maven.artifact.factory.ArtifactFactory;
47 import org.apache.maven.artifact.handler.ArtifactHandler;
48 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
49 import org.apache.maven.artifact.repository.ArtifactRepository;
50 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
51 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
52 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
53 import org.apache.maven.artifact.resolver.ArtifactResolver;
54 import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException;
55 import org.apache.maven.artifact.versioning.ArtifactVersion;
56 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
57 import org.apache.maven.execution.MavenSession;
58 import org.apache.maven.plugin.AbstractMojo;
59 import org.apache.maven.plugin.javadoc.options.BootclasspathArtifact;
60 import org.apache.maven.plugin.javadoc.options.DocletArtifact;
61 import org.apache.maven.plugin.javadoc.options.Group;
62 import org.apache.maven.plugin.javadoc.options.JavadocPathArtifact;
63 import org.apache.maven.plugin.javadoc.options.OfflineLink;
64 import org.apache.maven.plugin.javadoc.options.ResourcesArtifact;
65 import org.apache.maven.plugin.javadoc.options.Tag;
66 import org.apache.maven.plugin.javadoc.options.Taglet;
67 import org.apache.maven.plugin.javadoc.options.TagletArtifact;
68 import org.apache.maven.project.MavenProject;
69 import org.apache.maven.project.MavenProjectBuilder;
70 import org.apache.maven.project.ProjectBuildingException;
71 import org.apache.maven.project.artifact.InvalidDependencyVersionException;
72 import org.apache.maven.reporting.MavenReportException;
73 import org.apache.maven.settings.Proxy;
74 import org.apache.maven.settings.Settings;
75 import org.apache.maven.toolchain.Toolchain;
76 import org.apache.maven.toolchain.ToolchainManager;
77 import org.apache.maven.wagon.PathUtils;
78 import org.codehaus.plexus.archiver.ArchiverException;
79 import org.codehaus.plexus.archiver.UnArchiver;
80 import org.codehaus.plexus.archiver.manager.ArchiverManager;
81 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
82 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
83 import org.codehaus.plexus.util.FileUtils;
84 import org.codehaus.plexus.util.IOUtil;
85 import org.codehaus.plexus.util.ReaderFactory;
86 import org.codehaus.plexus.util.StringUtils;
87 import org.codehaus.plexus.util.cli.CommandLineException;
88 import org.codehaus.plexus.util.cli.CommandLineUtils;
89 import org.codehaus.plexus.util.cli.Commandline;
90 import org.codehaus.plexus.util.cli.DefaultConsumer;
91
92 /**
93 * Base class with majority of Javadoc functionalities.
94 *
95 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
96 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
97 * @version $Id: AbstractJavadocMojo.html 829389 2012-08-19 17:23:07Z hboutemy $
98 * @since 2.0
99 * @requiresDependencyResolution compile
100 */
101 public abstract class AbstractJavadocMojo
102 extends AbstractMojo
103 {
104 /** The Javadoc script file name when <code>debug</code> parameter is on, i.e. javadoc.bat or javadoc.sh */
105 protected static final String DEBUG_JAVADOC_SCRIPT_NAME =
106 "javadoc." + ( SystemUtils.IS_OS_WINDOWS ? "bat" : "sh" );
107
108 /** The <code>options</code> file name in the output directory when calling:
109 * <code>javadoc.exe(or .sh) @options @packages | @argfile | @files</code> */
110 protected static final String OPTIONS_FILE_NAME = "options";
111
112 /** The <code>packages</code> file name in the output directory when calling:
113 * <code>javadoc.exe(or .sh) @options @packages | @argfile | @files</code> */
114 protected static final String PACKAGES_FILE_NAME = "packages";
115
116 /** The <code>argfile</code> file name in the output directory when calling:
117 * <code>javadoc.exe(or .sh) @options @packages | @argfile | @files</code> */
118 protected static final String ARGFILE_FILE_NAME = "argfile";
119
120 /** The <code>files</code> file name in the output directory when calling:
121 * <code>javadoc.exe(or .sh) @options @packages | @argfile | @files</code> */
122 protected static final String FILES_FILE_NAME = "files";
123
124 /** The current class directory */
125 private static final String RESOURCE_DIR = ClassUtils.getPackageName( JavadocReport.class ).replace( '.', '/' );
126
127 /** Default css file name */
128 private static final String DEFAULT_CSS_NAME = "stylesheet.css";
129
130 /** Default location for css */
131 private static final String RESOURCE_CSS_DIR = RESOURCE_DIR + "/css";
132
133 /**
134 * For Javadoc options appears since Java 1.4.
135 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">
136 * What's New in Javadoc 1.4</a>
137 * @since 2.1
138 */
139 private static final float SINCE_JAVADOC_1_4 = 1.4f;
140
141 /**
142 * For Javadoc options appears since Java 1.4.2.
143 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.2.html#commandlineoptions">
144 * What's New in Javadoc 1.4.2</a>
145 * @since 2.1
146 */
147 private static final float SINCE_JAVADOC_1_4_2 = 1.42f;
148
149 /**
150 * For Javadoc options appears since Java 5.0.
151 * See <a href="http://java.sun.com/j2se/1.5.0/docs/guide/javadoc/whatsnew-1.5.0.html#commandlineoptions">
152 * What's New in Javadoc 5.0</a>
153 * @since 2.1
154 */
155 private static final float SINCE_JAVADOC_1_5 = 1.5f;
156
157 /**
158 * For Javadoc options appears since Java 6.0.
159 * See <a href="http://java.sun.com/javase/6/docs/technotes/guides/javadoc/index.html">
160 * Javadoc Technology</a>
161 * @since 2.4
162 */
163 private static final float SINCE_JAVADOC_1_6 = 1.6f;
164
165 // ----------------------------------------------------------------------
166 // Mojo components
167 // ----------------------------------------------------------------------
168
169 /**
170 * Archiver manager
171 *
172 * @since 2.5
173 * @component
174 */
175 private ArchiverManager archiverManager;
176
177 /**
178 * Factory for creating artifact objects
179 *
180 * @component
181 */
182 private ArtifactFactory factory;
183
184 /**
185 * Used to resolve artifacts of aggregated modules
186 *
187 * @since 2.1
188 * @component
189 */
190 private ArtifactMetadataSource artifactMetadataSource;
191
192 /**
193 * Used for resolving artifacts
194 *
195 * @component
196 */
197 private ArtifactResolver resolver;
198
199 /**
200 * Project builder
201 *
202 * @since 2.5
203 * @component
204 */
205 private MavenProjectBuilder mavenProjectBuilder;
206
207 // ----------------------------------------------------------------------
208 // Mojo parameters
209 // ----------------------------------------------------------------------
210
211 /**
212 * The current build session instance. This is used for
213 * toolchain manager API calls.
214 *
215 * @parameter expression="${session}"
216 * @required
217 * @readonly
218 */
219 private MavenSession session;
220
221 /**
222 * The Maven Settings.
223 *
224 * @since 2.3
225 * @parameter default-value="${settings}"
226 * @required
227 * @readonly
228 */
229 private Settings settings;
230
231 /**
232 * The Maven Project Object
233 *
234 * @parameter expression="${project}"
235 * @required
236 * @readonly
237 */
238 protected MavenProject project;
239
240 /**
241 * Specify if the Javadoc should operate in offline mode.
242 *
243 * @parameter default-value="${settings.offline}"
244 * @required
245 * @readonly
246 */
247 private boolean isOffline;
248
249 /**
250 * Specifies the Javadoc resources directory to be included in the Javadoc (i.e. package.html, images...).
251 * <br/>
252 * Could be used in addition of <code>docfilessubdirs</code> parameter.
253 * <br/>
254 * See <a href="#docfilessubdirs">docfilessubdirs</a>.
255 *
256 * @since 2.1
257 * @parameter expression="${basedir}/src/main/javadoc"
258 * @see #docfilessubdirs
259 */
260 private File javadocDirectory;
261
262 /**
263 * Set an additional parameter(s) on the command line. This value should include quotes as necessary for
264 * parameters that include spaces. Useful for a custom doclet.
265 *
266 * @parameter expression="${additionalparam}"
267 */
268 private String additionalparam;
269
270 /**
271 * Set an additional Javadoc option(s) (i.e. JVM options) on the command line.
272 * Example:
273 * <pre>
274 * <additionalJOption>-J-Xss128m</additionalJOption>
275 * </pre>
276 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#J">Jflag</a>.
277 * <br/>
278 * See <a href="http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp">vmoptions</a>.
279 *
280 * @since 2.3
281 * @parameter expression="${additionalJOption}"
282 */
283 private String additionalJOption;
284
285 /**
286 * A list of artifacts containing resources which should be copied into the
287 * Javadoc output directory (like stylesheets, icons, etc.).
288 * <br/>
289 * Example:
290 * <pre>
291 * <resourcesArtifacts>
292 * <resourcesArtifact>
293 * <groupId>external.group.id</groupId>
294 * <artifactId>external-resources</artifactId>
295 * <version>1.0</version>
296 * </resourcesArtifact>
297 * </resourcesArtifacts>
298 * </pre>
299 * <br/>
300 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/ResourcesArtifact.html">Javadoc</a>.
301 * <br/>
302 *
303 * @since 2.5
304 * @parameter expression="${resourcesArtifacts}"
305 */
306 private ResourcesArtifact[] resourcesArtifacts;
307
308 /**
309 * The local repository where the artifacts are located.
310 *
311 * @parameter expression="${localRepository}"
312 */
313 private ArtifactRepository localRepository;
314
315 /**
316 * The remote repositories where artifacts are located.
317 *
318 * @parameter expression="${project.remoteArtifactRepositories}"
319 */
320 private List remoteRepositories;
321
322 /**
323 * The projects in the reactor for aggregation report.
324 *
325 * @parameter expression="${reactorProjects}"
326 * @readonly
327 */
328 private List reactorProjects;
329
330 /**
331 * Whether to build an aggregated report at the root, or build individual reports.
332 *
333 * @parameter expression="${aggregate}" default-value="false"
334 * @deprecated As of version 2.5, use the goals <code>javadoc:aggregate</code> and
335 * <code>javadoc:test-aggregate</code> instead.
336 */
337 protected boolean aggregate;
338
339 /**
340 * Set this to 'true' to debug Javadoc plugin. With this, 'options' and 'files' files are provided.
341 * <br/>
342 *
343 * @since 2.1
344 * @parameter expression="${debug}" default-value="false"
345 */
346 private boolean debug;
347
348 /**
349 * Sets the absolute path of the Javadoc Tool executable to use. Since version 2.5, a mere directory specification
350 * is sufficient to have the plugin use "javadoc" or "javadoc.exe" respectively from this directory.
351 *
352 * @since 2.3
353 * @parameter expression="${javadocExecutable}"
354 */
355 private String javadocExecutable;
356
357 /**
358 * Version of the Javadoc Tool executable to use, ex. "1.3", "1.5".
359 *
360 * @since 2.3
361 * @parameter expression="${javadocVersion}"
362 */
363 private String javadocVersion;
364
365 /**
366 * Version of the Javadoc Tool executable to use as float.
367 */
368 private float fJavadocVersion = 0.0f;
369
370 /**
371 * Specifies whether the Javadoc generation should be skipped.
372 *
373 * @since 2.5
374 * @parameter expression="${maven.javadoc.skip}" default-value="false"
375 */
376 protected boolean skip;
377
378 /**
379 * Specifies whether the build will continue even if there are errors.
380 *
381 * @parameter expression="${maven.javadoc.failOnError}" default-value="true"
382 * @since 2.5
383 */
384 protected boolean failOnError;
385
386 /**
387 * Specifies to use the <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#standard">
388 * options provided by the Standard Doclet</a> for a custom doclet.
389 * <br/>
390 * Example:
391 * <pre>
392 * <docletArtifacts>
393 * <docletArtifact>
394 * <groupId>com.sun.tools.doclets</groupId>
395 * <artifactId>doccheck</artifactId>
396 * <version>1.2b2</version>
397 * </docletArtifact>
398 * </docletArtifacts>
399 * <useStandardDocletOptions>true</useStandardDocletOptions>
400 * </pre>
401 *
402 * @parameter expression="${useStandardDocletOptions}" default-value="true"
403 * @since 2.5
404 */
405 protected boolean useStandardDocletOptions;
406
407 // ----------------------------------------------------------------------
408 // Javadoc Options - all alphabetical
409 // ----------------------------------------------------------------------
410
411 /**
412 * Specifies the paths where the boot classes reside.
413 * <br/>
414 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#bootclasspath">bootclasspath</a>.
415 * <br/>
416 *
417 * @parameter expression="${bootclasspath}"
418 * @since 2.5
419 */
420 private String bootclasspath;
421
422 /**
423 * Specifies the artifacts where the boot classes reside.
424 * <br/>
425 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#bootclasspath">bootclasspath</a>.
426 * <br/>
427 * Example:
428 * <pre>
429 * <bootclasspathArtifacts>
430 * <bootclasspathArtifact>
431 * <groupId>my-groupId</groupId>
432 * <artifactId>my-artifactId</artifactId>
433 * <version>my-version</version>
434 * </bootclasspathArtifact>
435 * </bootclasspathArtifacts>
436 * </pre>
437 * <br/>
438 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/BootclasspathArtifact.html">Javadoc</a>.
439 * <br/>
440 *
441 * @parameter expression="${bootclasspathArtifacts}"
442 * @since 2.5
443 */
444 private BootclasspathArtifact[] bootclasspathArtifacts;
445
446 /**
447 * Uses the sentence break iterator to determine the end of the first sentence.
448 * <br/>
449 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#breakiterator">breakiterator</a>.
450 * <br/>
451 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
452 * <br/>
453 *
454 * @parameter expression="${breakiterator}" default-value="false"
455 */
456 private boolean breakiterator;
457
458 /**
459 * Specifies the class file that starts the doclet used in generating the documentation.
460 * <br/>
461 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#doclet">doclet</a>.
462 *
463 * @parameter expression="${doclet}"
464 */
465 private String doclet;
466
467 /**
468 * Specifies the artifact containing the doclet starting class file (specified with the -doclet option).
469 * <br/>
470 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#docletpath">docletpath</a>.
471 * <br/>
472 * Example:
473 * <pre>
474 * <docletArtifact>
475 * <groupId>com.sun.tools.doclets</groupId>
476 * <artifactId>doccheck</artifactId>
477 * <version>1.2b2</version>
478 * </docletArtifact>
479 * </pre>
480 * <br/>
481 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/DocletArtifact.html">Javadoc</a>.
482 * <br/>
483 *
484 * @parameter expression="${docletArtifact}"
485 */
486 private DocletArtifact docletArtifact;
487
488 /**
489 * Specifies multiple artifacts containing the path for the doclet starting class file (specified with the
490 * -doclet option).
491 * <br/>
492 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#docletpath">docletpath</a>.
493 * <br/>
494 * Example:
495 * <pre>
496 * <docletArtifacts>
497 * <docletArtifact>
498 * <groupId>com.sun.tools.doclets</groupId>
499 * <artifactId>doccheck</artifactId>
500 * <version>1.2b2</version>
501 * </docletArtifact>
502 * </docletArtifacts>
503 * </pre>
504 * <br/>
505 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/DocletArtifact.html">Javadoc</a>.
506 * <br/>
507 *
508 * @since 2.1
509 * @parameter expression="${docletArtifacts}"
510 */
511 private DocletArtifact[] docletArtifacts;
512
513 /**
514 * Specifies the path to the doclet starting class file (specified with the -doclet option) and any jar files
515 * it depends on. The docletPath can contain multiple paths by separating them with a colon (<code>:</code>)
516 * on Solaris and a semi-colon (<code>;</code>) on Windows.
517 * <br/>
518 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#docletpath">docletpath</a>.
519 *
520 * @parameter expression="${docletPath}"
521 */
522 private String docletPath;
523
524 /**
525 * Specifies the encoding name of the source files. If not specificed, the encoding value will be the value of the
526 * <code>file.encoding</code> system property.
527 * <br/>
528 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#encoding">encoding</a>.
529 * <br/>
530 * <b>Note</b>: In 2.4, the default value was locked to <code>ISO-8859-1</code> to ensure reproducing build, but
531 * this was reverted in 2.5.
532 * <br/>
533 *
534 * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
535 */
536 private String encoding;
537
538 /**
539 * Unconditionally excludes the specified packages and their subpackages from the list formed by -subpackages.
540 * Multiple packages can be separated by colons (<code>:</code>).
541 * <br/>
542 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#exclude">exclude</a>.
543 * <br/>
544 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
545 *
546 * @parameter expression="${excludePackageNames}"
547 */
548 private String excludePackageNames;
549
550 /**
551 * Specifies the directories where extension classes reside. Separate directories in dirlist with a colon
552 * (<code>:</code>) on Solaris and a semi-colon (<code>;</code>) on Windows.
553 * <br/>
554 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#extdirs">extdirs</a>.
555 *
556 * @parameter expression="${extdirs}"
557 */
558 private String extdirs;
559
560 /**
561 * Specifies the locale that javadoc uses when generating documentation.
562 * <br/>
563 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#locale">locale</a>.
564 *
565 * @parameter expression="${locale}"
566 */
567 private String locale;
568
569 /**
570 * Specifies the maximum Java heap size to be used when launching the Javadoc tool.
571 * JVMs refer to this property as the <code>-Xmx</code> parameter. Example: '512' or '512m'.
572 * The memory unit depends on the JVM used. The units supported could be: <code>k</code>, <code>kb</code>,
573 * <code>m</code>, <code>mb</code>, <code>g</code>, <code>gb</code>, <code>t</code>, <code>tb</code>.
574 * If no unit specified, the default unit is <code>m</code>.
575 *
576 * @parameter expression="${maxmemory}"
577 */
578 private String maxmemory;
579
580 /**
581 * Specifies the minimum Java heap size to be used when launching the Javadoc tool.
582 * JVMs refer to this property as the <code>-Xms</code> parameter. Example: '512' or '512m'.
583 * The memory unit depends on the JVM used. The units supported could be: <code>k</code>, <code>kb</code>,
584 * <code>m</code>, <code>mb</code>, <code>g</code>, <code>gb</code>, <code>t</code>, <code>tb</code>.
585 * If no unit specified, the default unit is <code>m</code>.
586 *
587 * @parameter expression="${minmemory}"
588 */
589 private String minmemory;
590
591 /**
592 * This option creates documentation with the appearance and functionality of documentation generated by
593 * Javadoc 1.1.
594 * <br/>
595 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#1.1">1.1</a>.
596 * <br/>
597 *
598 * @parameter expression="${old}" default-value="false"
599 */
600 private boolean old;
601
602 /**
603 * Specifies that javadoc should retrieve the text for the overview documentation from the "source" file
604 * specified by path/filename and place it on the Overview page (overview-summary.html).
605 * <br/>
606 * <b>Note</b>: could be in conflict with <nooverview/>.
607 * <br/>
608 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#overview">overview</a>.
609 * <br/>
610 *
611 * @parameter expression="${overview}" default-value="${basedir}/src/main/javadoc/overview.html"
612 */
613 private File overview;
614
615 /**
616 * Specifies the proxy host where the javadoc web access in <code>-link</code> would pass through.
617 * It defaults to the proxy host of the active proxy set in the <code>settings.xml</code>, otherwise it gets the
618 * proxy configuration set in the pom.
619 * <br/>
620 *
621 * @parameter expression="${proxyHost}" default-value="${settings.activeProxy.host}"
622 * @deprecated since 2.4. Instead of, configure an active proxy host in <code>settings.xml</code>.
623 */
624 private String proxyHost;
625
626 /**
627 * Specifies the proxy port where the javadoc web access in <code>-link</code> would pass through.
628 * It defaults to the proxy port of the active proxy set in the <code>settings.xml</code>, otherwise it gets the
629 * proxy configuration set in the pom.
630 * <br/>
631 *
632 * @parameter expression="${proxyPort}" default-value="${settings.activeProxy.port}"
633 * @deprecated since 2.4. Instead of, configure an active proxy port in <code>settings.xml</code>.
634 */
635 private int proxyPort;
636
637 /**
638 * Shuts off non-error and non-warning messages, leaving only the warnings and errors appear, making them
639 * easier to view.
640 * <br/>
641 * Note: was a standard doclet in Java 1.4.2 (refer to bug ID
642 * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4714350">4714350</a>).
643 * <br/>
644 * See <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#quiet">quiet</a>.
645 * <br/>
646 * Since Java 5.0.
647 * <br/>
648 *
649 * @parameter expression="${quiet}" default-value="false"
650 */
651 private boolean quiet;
652
653 /**
654 * Specifies the access level for classes and members to show in the Javadocs.
655 * Possible values are:
656 * <ul>
657 * <li><a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#public">public</a>
658 * (shows only public classes and members)</li>
659 * <li><a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#protected">protected</a>
660 * (shows only public and protected classes and members)</li>
661 * <li><a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#package">package</a>
662 * (shows all classes and members not marked private)</li>
663 * <li><a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#private">private</a>
664 * (shows all classes and members)</li>
665 * </ul>
666 * <br/>
667 *
668 * @parameter expression="${show}" default-value="protected"
669 */
670 private String show;
671
672 /**
673 * Necessary to enable javadoc to handle assertions present in J2SE v 1.4 source code.
674 * <br/>
675 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#source">source</a>.
676 * <br/>
677 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
678 *
679 * @parameter expression="${source}"
680 */
681 private String source;
682
683 /**
684 * Specifies the source paths where the subpackages are located. The paths are separated with a colon
685 * (<code>:</code>) on Solaris and a semi-colon (<code>;</code>) on Windows.
686 * <br/>
687 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#sourcepath">sourcepath</a>.
688 *
689 * @parameter expression="${sourcepath}"
690 */
691 private String sourcepath;
692
693 /**
694 * Specifies the package directory where javadoc will be executed. Multiple packages can be separated by
695 * colons (<code>:</code>).
696 * <br/>
697 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#subpackages">subpackages</a>.
698 * <br/>
699 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
700 *
701 * @parameter expression="${subpackages}"
702 */
703 private String subpackages;
704
705 /**
706 * Provides more detailed messages while javadoc is running.
707 * <br/>
708 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#verbose">verbose</a>.
709 * <br/>
710 *
711 * @parameter expression="${verbose}" default-value="false"
712 */
713 private boolean verbose;
714
715 // ----------------------------------------------------------------------
716 // Standard Doclet Options - all alphabetical
717 // ----------------------------------------------------------------------
718
719 /**
720 * Specifies whether or not the author text is included in the generated Javadocs.
721 * <br/>
722 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#author">author</a>.
723 * <br/>
724 *
725 * @parameter expression="${author}" default-value="true"
726 */
727 private boolean author;
728
729 /**
730 * Specifies the text to be placed at the bottom of each output file.<br/>
731 * If you want to use html you have to put it in a CDATA section, <br/>
732 * eg. <code><![CDATA[Copyright 2005, <a href="http://www.mycompany.com">MyCompany, Inc.<a>]]></code>
733 * <br/>
734 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#bottom">bottom</a>.
735 * <br/>
736 *
737 * @parameter expression="${bottom}"
738 * default-value="Copyright © {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved."
739 */
740 private String bottom;
741
742 /**
743 * Specifies the HTML character set for this document. If not specificed, the charset value will be the value of
744 * the <code>docencoding</code> parameter.
745 * <br/>
746 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#charset">charset</a>.
747 * <br/>
748 *
749 * @parameter expression="${charset}"
750 */
751 private String charset;
752
753 /**
754 * Specifies the encoding of the generated HTML files. If not specificed, the docencoding value will be
755 * <code>UTF-8</code>.
756 * <br/>
757 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#docencoding">docencoding</a>.
758 *
759 * @parameter expression="${docencoding}" default-value="${project.reporting.outputEncoding}"
760 */
761 private String docencoding;
762
763 /**
764 * Enables deep copying of "doc-files" directories.
765 * <br/>
766 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#docfilessubdirs">
767 * docfilessubdirs</a>.
768 * <br/>
769 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
770 * <br/>
771 * See <a href="#javadocDirectory">javadocDirectory</a>.
772 * <br/>
773 *
774 * @parameter expression="${docfilessubdirs}" default-value="false"
775 * @see #excludedocfilessubdir
776 * @see #javadocDirectory
777 */
778 private boolean docfilessubdirs;
779
780 /**
781 * Specifies the title to be placed near the top of the overview summary file.
782 * <br/>
783 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#doctitle">doctitle</a>.
784 * <br/>
785 *
786 * @parameter expression="${doctitle}" default-value="${project.name} ${project.version} API"
787 */
788 private String doctitle;
789
790 /**
791 * Excludes any "doc-files" subdirectories with the given names. Multiple patterns can be excluded
792 * by separating them with colons (<code>:</code>).
793 * <br/>
794 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#excludedocfilessubdir">
795 * excludedocfilessubdir</a>.
796 * <br/>
797 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
798 *
799 * @parameter expression="${excludedocfilessubdir}"
800 * @see #docfilessubdirs
801 */
802 private String excludedocfilessubdir;
803
804 /**
805 * Specifies the footer text to be placed at the bottom of each output file.
806 * <br/>
807 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#footer">footer</a>.
808 *
809 * @parameter expression="${footer}"
810 */
811 private String footer;
812
813 /**
814 * Separates packages on the overview page into whatever groups you specify, one group per table. The
815 * packages pattern can be any package name, or can be the start of any package name followed by an asterisk
816 * (<code>*</code>) meaning "match any characters". Multiple patterns can be included in a group
817 * by separating them with colons (<code>:</code>).
818 * <br/>
819 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#group">group</a>.
820 * <br/>
821 * Example:
822 * <pre>
823 * <groups>
824 * <group>
825 * <title>Core Packages</title>
826 * <packages>org.apache.core</packages>
827 * </group>
828 * </groups>
829 * </pre>
830 * <br/>
831 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/Group.html">Javadoc</a>.
832 * <br/>
833 *
834 * @parameter expression="${groups}"
835 */
836 private Group[] groups;
837
838 /**
839 * Specifies the header text to be placed at the top of each output file.
840 * <br/>
841 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#header">header</a>.
842 *
843 * @parameter expression="${header}"
844 */
845 private String header;
846
847 /**
848 * Specifies the path of an alternate help file path\filename that the HELP link in the top and bottom
849 * navigation bars link to.
850 * <br/>
851 * <b>Note</b>: could be in conflict with <nohelp/>.
852 * <br/>
853 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#helpfile">helpfile</a>.
854 *
855 * @parameter expression="${helpfile}"
856 */
857 private String helpfile;
858
859 /**
860 * Adds HTML meta keyword tags to the generated file for each class.
861 * <br/>
862 * See <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#keywords">keywords</a>.
863 * <br/>
864 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.2.html#commandlineoptions">
865 * Java 1.4.2</a>.
866 * <br/>
867 * Since <a href="http://java.sun.com/j2se/1.5.0/docs/guide/javadoc/whatsnew-1.5.0.html#commandlineoptions">
868 * Java 5.0</a>.
869 * <br/>
870 *
871 * @since 2.1
872 * @parameter expression="${keywords}" default-value="false"
873 */
874 private boolean keywords;
875
876 /**
877 * Creates links to existing javadoc-generated documentation of external referenced classes.
878 * <br/>
879 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#link">link</a>.
880 *
881 * @parameter expression="${links}"
882 */
883 protected ArrayList links;
884
885 /**
886 * Creates an HTML version of each source file (with line numbers) and adds links to them from the standard
887 * HTML documentation.
888 * <br/>
889 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#linksource">linksource</a>.
890 * <br/>
891 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
892 * <br/>
893 *
894 * @parameter expression="${linksource}" default-value="false"
895 */
896 private boolean linksource;
897
898 /**
899 * Suppress the entire comment body, including the main description and all tags, generating only declarations.
900 * <br/>
901 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#nocomment">nocomment</a>.
902 * <br/>
903 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
904 * <br/>
905 *
906 * @parameter expression="${nocomment}" default-value="false"
907 */
908 private boolean nocomment;
909
910 /**
911 * Prevents the generation of any deprecated API at all in the documentation.
912 * <br/>
913 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#nodeprecated">nodeprecated</a>.
914 * <br/>
915 *
916 * @parameter expression="${nodeprecated}" default-value="false"
917 */
918 private boolean nodeprecated;
919
920 /**
921 * Prevents the generation of the file containing the list of deprecated APIs (deprecated-list.html) and the
922 * link in the navigation bar to that page.
923 * <br/>
924 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#nodeprecatedlist">
925 * nodeprecatedlist</a>.
926 * <br/>
927 *
928 * @parameter expression="${nodeprecatedlist}" default-value="false"
929 */
930 private boolean nodeprecatedlist;
931
932 /**
933 * Omits the HELP link in the navigation bars at the top and bottom of each page of output.
934 * <br/>
935 * <b>Note</b>: could be in conflict with <helpfile/>.
936 * <br/>
937 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#nohelp">nohelp</a>.
938 * <br/>
939 *
940 * @parameter expression="${nohelp}" default-value="false"
941 */
942 private boolean nohelp;
943
944 /**
945 * Omits the index from the generated docs.
946 * <br/>
947 * <b>Note</b>: could be in conflict with <splitindex/>.
948 * <br/>
949 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#noindex">noindex</a>.
950 * <br/>
951 *
952 * @parameter expression="${noindex}" default-value="false"
953 */
954 private boolean noindex;
955
956 /**
957 * Omits the navigation bar from the generated docs.
958 * <br/>
959 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#nonavbar">nonavbar</a>.
960 * <br/>
961 *
962 * @parameter expression="${nonavbar}" default-value="false"
963 */
964 private boolean nonavbar;
965
966 /**
967 * Omits the entire overview page from the generated docs.
968 * <br/>
969 * <b>Note</b>: could be in conflict with <overview/>.
970 * <br/>
971 * Standard Doclet undocumented option.
972 * <br/>
973 *
974 * @since 2.4
975 * @parameter expression="${nooverview}" default-value="false"
976 */
977 private boolean nooverview;
978
979 /**
980 * Omits qualifying package name from ahead of class names in output.
981 * <br/>
982 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#noqualifier">noqualifier</a>.
983 * <br/>
984 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
985 *
986 * @parameter expression="${noqualifier}"
987 */
988 private String noqualifier;
989
990 /**
991 * Omits from the generated docs the "Since" sections associated with the since tags.
992 * <br/>
993 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#nosince">nosince</a>.
994 * <br/>
995 *
996 * @parameter expression="${nosince}" default-value="false"
997 */
998 private boolean nosince;
999
1000 /**
1001 * Suppresses the timestamp, which is hidden in an HTML comment in the generated HTML near the top of each page.
1002 * <br/>
1003 * See <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#notimestamp">notimestamp</a>.
1004 * <br/>
1005 * Since <a href="http://java.sun.com/j2se/1.5.0/docs/guide/javadoc/whatsnew-1.5.0.html#commandlineoptions">
1006 * Java 5.0</a>.
1007 * <br/>
1008 *
1009 * @since 2.1
1010 * @parameter expression="${notimestamp}" default-value="false"
1011 */
1012 private boolean notimestamp;
1013
1014 /**
1015 * Omits the class/interface hierarchy pages from the generated docs.
1016 * <br/>
1017 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#notree">notree</a>.
1018 * <br/>
1019 *
1020 * @parameter expression="${notree}" default-value="false"
1021 */
1022 private boolean notree;
1023
1024 /**
1025 * This option is a variation of -link; they both create links to javadoc-generated documentation for external
1026 * referenced classes.
1027 * <br/>
1028 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#linkoffline">linkoffline</a>.
1029 * <br/>
1030 * Example:
1031 * <pre>
1032 * <offlineLinks>
1033 * <offlineLink>
1034 * <url>http://java.sun.com/j2se/1.5.0/docs/api/</url>
1035 * <location>../javadoc/jdk-5.0/</location>
1036 * </offlineLink>
1037 * </offlineLinks>
1038 * </pre>
1039 * <br/>
1040 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/OfflineLink.html">Javadoc</a>.
1041 * <br/>
1042 *
1043 * @parameter expression="${offlineLinks}"
1044 */
1045 private OfflineLink[] offlineLinks;
1046
1047 /**
1048 * Specifies the destination directory where javadoc saves the generated HTML files.
1049 * <br/>
1050 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#d">d</a>.
1051 * <br/>
1052 *
1053 * @parameter expression="${destDir}" alias="destDir" default-value="${project.build.directory}/apidocs"
1054 * @required
1055 */
1056 protected File outputDirectory;
1057
1058 /**
1059 * Specify the text for upper left frame.
1060 * <br/>
1061 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.2.html#commandlineoptions">
1062 * Java 1.4.2</a>.
1063 *
1064 * @since 2.1
1065 * @parameter expression="${packagesheader}"
1066 */
1067 private String packagesheader;
1068
1069 /**
1070 * Generates compile-time warnings for missing serial tags.
1071 * <br/>
1072 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#serialwarn">serialwarn</a>
1073 * <br/>
1074 *
1075 * @parameter expression="${serialwarn}" default-value="false"
1076 */
1077 private boolean serialwarn;
1078
1079 /**
1080 * Specify the number of spaces each tab takes up in the source. If no tab is used in source, the default
1081 * space is used.
1082 * <br/>
1083 * Note: was <code>linksourcetab</code> in Java 1.4.2 (refer to bug ID
1084 * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4788919">4788919</a>).
1085 * <br/>
1086 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.2.html#commandlineoptions">
1087 * 1.4.2</a>.
1088 * <br/>
1089 * Since Java 5.0.
1090 *
1091 * @since 2.1
1092 * @parameter expression="${sourcetab}" alias="linksourcetab"
1093 */
1094 private int sourcetab;
1095
1096 /**
1097 * Splits the index file into multiple files, alphabetically, one file per letter, plus a file for any index
1098 * entries that start with non-alphabetical characters.
1099 * <br/>
1100 * <b>Note</b>: could be in conflict with <noindex/>.
1101 * <br/>
1102 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#splitindex">splitindex</a>.
1103 * <br/>
1104 *
1105 * @parameter expression="${splitindex}" default-value="false"
1106 */
1107 private boolean splitindex;
1108
1109 /**
1110 * Specifies whether the stylesheet to be used is the maven javadoc stylesheet or java's default stylesheet
1111 * when a <i>stylesheetfile</i> parameter is not specified. Possible values: "maven" or "java".
1112 * <br/>
1113 *
1114 * @parameter expression="${stylesheet}" default-value="java"
1115 */
1116 private String stylesheet;
1117
1118 /**
1119 * Specifies the path of an alternate HTML stylesheet file.
1120 * <br/>
1121 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#stylesheetfile">
1122 * stylesheetfile</a>.
1123 *
1124 * @parameter expression="${stylesheetfile}"
1125 */
1126 private String stylesheetfile;
1127
1128 /**
1129 * Specifies the class file that starts the taglet used in generating the documentation for that tag.
1130 * <br/>
1131 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#taglet">taglet</a>.
1132 * <br/>
1133 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
1134 *
1135 * @parameter expression="${taglet}"
1136 */
1137 private String taglet;
1138
1139 /**
1140 * Specifies the Taglet artifact containing the taglet class files (.class).
1141 * <br/>
1142 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#tagletpath">tagletpath</a>.
1143 * <br/>
1144 * Example:
1145 * <pre>
1146 * <taglets>
1147 * <taglet>
1148 * <tagletClass>com.sun.tools.doclets.ToDoTaglet</tagletClass>
1149 * </taglet>
1150 * <taglet>
1151 * <tagletClass>package.to.AnotherTagletClass</tagletClass>
1152 * </taglet>
1153 * ...
1154 * </taglets>
1155 * <tagletArtifact>
1156 * <groupId>group-Taglet</groupId>
1157 * <artifactId>artifact-Taglet</artifactId>
1158 * <version>version-Taglet</version>
1159 * </tagletArtifact>
1160 * </pre>
1161 * <br/>
1162 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/TagletArtifact.html">Javadoc</a>.
1163 * <br/>
1164 *
1165 * @since 2.1
1166 * @parameter expression="${tagletArtifact}"
1167 */
1168 private TagletArtifact tagletArtifact;
1169
1170 /**
1171 * Specifies several Taglet artifacts containing the taglet class files (.class). These taglets class names will be
1172 * auto-detect and so no need to specify them.
1173 * <br/>
1174 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#taglet">taglet</a>.
1175 * <br/>
1176 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#tagletpath">tagletpath</a>.
1177 * <br/>
1178 * Example:
1179 * <pre>
1180 * <tagletArtifacts>
1181 * <tagletArtifact>
1182 * <groupId>group-Taglet</groupId>
1183 * <artifactId>artifact-Taglet</artifactId>
1184 * <version>version-Taglet</version>
1185 * </tagletArtifact>
1186 * ...
1187 * </tagletArtifacts>
1188 * </pre>
1189 * <br/>
1190 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/TagletArtifact.html">Javadoc</a>.
1191 * <br/>
1192 *
1193 * @since 2.5
1194 * @parameter expression="${tagletArtifacts}"
1195 */
1196 private TagletArtifact[] tagletArtifacts;
1197
1198 /**
1199 * Specifies the search paths for finding taglet class files (.class). The tagletPath can contain
1200 * multiple paths by separating them with a colon (<code>:</code>) on Solaris and a semi-colon (<code>;</code>)
1201 * on Windows.
1202 * <br/>
1203 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#tagletpath">tagletpath</a>.
1204 * <br/>
1205 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
1206 *
1207 * @parameter expression="${tagletpath}"
1208 */
1209 private String tagletpath;
1210
1211 /**
1212 * Enables the Javadoc tool to interpret multiple taglets.
1213 * <br/>
1214 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#taglet">taglet</a>.
1215 * <br/>
1216 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#tagletpath">tagletpath</a>.
1217 * <br/>
1218 * Example:
1219 * <pre>
1220 * <taglets>
1221 * <taglet>
1222 * <tagletClass>com.sun.tools.doclets.ToDoTaglet</tagletClass>
1223 * <!--<tagletpath>/home/taglets</tagletpath>-->
1224 * <tagletArtifact>
1225 * <groupId>group-Taglet</groupId>
1226 * <artifactId>artifact-Taglet</artifactId>
1227 * <version>version-Taglet</version>
1228 * </tagletArtifact>
1229 * </taglet>
1230 * </taglets>
1231 * </pre>
1232 * <br/>
1233 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/Taglet.html">Javadoc</a>.
1234 * <br/>
1235 *
1236 * @since 2.1
1237 * @parameter expression="${taglets}"
1238 */
1239 private Taglet[] taglets;
1240
1241 /**
1242 * Enables the Javadoc tool to interpret a simple, one-argument custom block tag tagname in doc comments.
1243 * <br/>
1244 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#tag">tag</a>.
1245 * <br/>
1246 * Since <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#summary">Java 1.4</a>.
1247 * <br/>
1248 * Example:
1249 * <pre>
1250 * <tags>
1251 * <tag>
1252 * <name>todo</name>
1253 * <placement>a</placement>
1254 * <head>To Do:</head>
1255 * </tag>
1256 * </tags>
1257 * </pre>
1258 * <br/>
1259 * See <a href="./apidocs/org/apache/maven/plugin/javadoc/options/Tag.html">Javadoc</a>.
1260 * <br/>
1261 *
1262 * @parameter expression="${tags}"
1263 */
1264 private Tag[] tags;
1265
1266 /**
1267 * Specifies the top text to be placed at the top of each output file.
1268 * <br/>
1269 * See <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6227616">6227616</a>.
1270 * <br/>
1271 * Since Java 6.0
1272 *
1273 * @since 2.4
1274 * @parameter expression="${top}"
1275 */
1276 private String top;
1277
1278 /**
1279 * Includes one "Use" page for each documented class and package.
1280 * <br/>
1281 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#use">use</a>.
1282 * <br/>
1283 *
1284 * @parameter expression="${use}" default-value="true"
1285 */
1286 private boolean use;
1287
1288 /**
1289 * Includes the version text in the generated docs.
1290 * <br/>
1291 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#version">version</a>.
1292 * <br/>
1293 *
1294 * @parameter expression="${version}" default-value="true"
1295 */
1296 private boolean version;
1297
1298 /**
1299 * Specifies the title to be placed in the HTML title tag.
1300 * <br/>
1301 * See <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#windowtitle">windowtitle</a>.
1302 * <br/>
1303 *
1304 * @parameter expression="${windowtitle}" default-value="${project.name} ${project.version} API"
1305 */
1306 private String windowtitle;
1307
1308 // ----------------------------------------------------------------------
1309 // protected methods
1310 // ----------------------------------------------------------------------
1311
1312 /**
1313 * Indicates whether this goal is flagged with <code>@aggregator</code>.
1314 *
1315 * @return <code>true</code> if the goal is designed as an aggregator, <code>false</code> otherwise.
1316 * @see AggregatorJavadocReport
1317 * @see AggregatorTestJavadocReport
1318 */
1319 protected boolean isAggregator()
1320 {
1321 return false;
1322 }
1323
1324 /**
1325 * @return the output directory
1326 */
1327 protected String getOutputDirectory()
1328 {
1329 return outputDirectory.getAbsoluteFile().toString();
1330 }
1331
1332 /**
1333 * @param p not null maven project
1334 * @return the list of directories where compiled classes are placed for the given project. These dirs are
1335 * added in the javadoc classpath.
1336 */
1337 protected List getProjectBuildOutputDirs( MavenProject p )
1338 {
1339 if ( StringUtils.isEmpty( p.getBuild().getOutputDirectory() ) )
1340 {
1341 return Collections.EMPTY_LIST;
1342 }
1343
1344 return Collections.singletonList( p.getBuild().getOutputDirectory() );
1345 }
1346
1347 /**
1348 * @param p not null maven project
1349 * @return the list of source paths for the given project
1350 */
1351 protected List getProjectSourceRoots( MavenProject p )
1352 {
1353 if ( "pom".equals( p.getPackaging().toLowerCase() ) )
1354 {
1355 return Collections.EMPTY_LIST;
1356 }
1357
1358 return p.getCompileSourceRoots();
1359 }
1360
1361 /**
1362 * @param p not null maven project
1363 * @return the list of source paths for the execution project of the given project
1364 */
1365 protected List getExecutionProjectSourceRoots( MavenProject p )
1366 {
1367 if ( "pom".equals( p.getExecutionProject().getPackaging().toLowerCase() ) )
1368 {
1369 return Collections.EMPTY_LIST;
1370 }
1371
1372 return p.getExecutionProject().getCompileSourceRoots();
1373 }
1374
1375 /**
1376 * @param p not null maven project
1377 * @return the list of artifacts for the given project
1378 */
1379 protected List getProjectArtifacts( MavenProject p )
1380 {
1381 return p.getCompileArtifacts();
1382 }
1383
1384 /**
1385 * @return the current javadoc directory
1386 */
1387 protected File getJavadocDirectory()
1388 {
1389 return javadocDirectory;
1390 }
1391
1392 /**
1393 * @return the title to be placed near the top of the overview summary file
1394 */
1395 protected String getDoctitle()
1396 {
1397 return doctitle;
1398 }
1399
1400 /**
1401 * @return the overview documentation file from the user parameter or from the <code>javadocdirectory</code>
1402 */
1403 protected File getOverview()
1404 {
1405 return overview;
1406 }
1407
1408 /**
1409 * @return the title to be placed in the HTML title tag
1410 */
1411 protected String getWindowtitle()
1412 {
1413 return windowtitle;
1414 }
1415
1416 /**
1417 * @return the charset attribute or the value of {@link #getDocencoding()} if <code>null</code>.
1418 */
1419 private String getCharset()
1420 {
1421 return ( StringUtils.isEmpty( charset ) ) ? getDocencoding() : charset;
1422 }
1423
1424 /**
1425 * @return the docencoding attribute or <code>UTF-8</code> if <code>null</code>.
1426 */
1427 private String getDocencoding()
1428 {
1429 return ( StringUtils.isEmpty( docencoding ) ) ? ReaderFactory.UTF_8 : docencoding;
1430 }
1431
1432 /**
1433 * @return the encoding attribute or the value of <code>file.encoding</code> system property if <code>null</code>.
1434 */
1435 private String getEncoding()
1436 {
1437 return ( StringUtils.isEmpty( encoding ) ) ? ReaderFactory.FILE_ENCODING : encoding;
1438 }
1439
1440 /**
1441 * The <a href="package-summary.html">package documentation</a> details the
1442 * Javadoc Options used by this Plugin.
1443 *
1444 * @param unusedLocale the wanted locale (actually unused).
1445 * @throws MavenReportException if any
1446 */
1447 protected void executeReport( Locale unusedLocale )
1448 throws MavenReportException
1449 {
1450 if ( skip )
1451 {
1452 getLog().info( "Skipping javadoc generation" );
1453 return;
1454 }
1455
1456 if ( isAggregator() && !project.isExecutionRoot() )
1457 {
1458 return;
1459 }
1460
1461 if ( getLog().isDebugEnabled() )
1462 {
1463 this.debug = true;
1464 }
1465
1466 List sourcePaths = getSourcePaths();
1467 List files = getFiles( sourcePaths );
1468 if ( !canGenerateReport( files ) )
1469 {
1470 return;
1471 }
1472
1473 List packageNames = getPackageNames( sourcePaths, files );
1474 List filesWithUnnamedPackages = getFilesWithUnnamedPackages( sourcePaths, files );
1475
1476 // ----------------------------------------------------------------------
1477 // Find the javadoc executable and version
1478 // ----------------------------------------------------------------------
1479
1480 String jExecutable;
1481 try
1482 {
1483 jExecutable = getJavadocExecutable();
1484 }
1485 catch ( IOException e )
1486 {
1487 throw new MavenReportException( "Unable to find javadoc command: " + e.getMessage(), e );
1488 }
1489 setFJavadocVersion( new File( jExecutable ) );
1490
1491 // ----------------------------------------------------------------------
1492 // Javadoc output directory as File
1493 // ----------------------------------------------------------------------
1494
1495 File javadocOutputDirectory = new File( getOutputDirectory() );
1496 if ( javadocOutputDirectory.exists() && !javadocOutputDirectory.isDirectory() )
1497 {
1498 throw new MavenReportException( "IOException: " + getOutputDirectory() + " is not a directory." );
1499 }
1500 if ( javadocOutputDirectory.exists() && !javadocOutputDirectory.canWrite() )
1501 {
1502 throw new MavenReportException( "IOException: " + getOutputDirectory() + " is not writable." );
1503 }
1504 javadocOutputDirectory.mkdirs();
1505
1506 // ----------------------------------------------------------------------
1507 // Copy all resources
1508 // ----------------------------------------------------------------------
1509
1510 copyAllResources( javadocOutputDirectory );
1511
1512 // ----------------------------------------------------------------------
1513 // Create command line for Javadoc
1514 // ----------------------------------------------------------------------
1515
1516 Commandline cmd = new Commandline();
1517 cmd.getShell().setQuotedArgumentsEnabled( false ); // for Javadoc JVM args
1518 cmd.setWorkingDirectory( javadocOutputDirectory.getAbsolutePath() );
1519 cmd.setExecutable( jExecutable );
1520
1521 // ----------------------------------------------------------------------
1522 // Wrap Javadoc JVM args
1523 // ----------------------------------------------------------------------
1524
1525 addMemoryArg( cmd, "-Xmx", this.maxmemory );
1526 addMemoryArg( cmd, "-Xms", this.minmemory );
1527 addProxyArg( cmd );
1528
1529 if ( StringUtils.isNotEmpty( additionalJOption ) )
1530 {
1531 cmd.createArg().setValue( additionalJOption );
1532 }
1533
1534 List arguments = new ArrayList();
1535
1536 // ----------------------------------------------------------------------
1537 // Wrap Javadoc options
1538 // ----------------------------------------------------------------------
1539
1540 addJavadocOptions( arguments, sourcePaths );
1541
1542 // ----------------------------------------------------------------------
1543 // Wrap Standard doclet Options
1544 // ----------------------------------------------------------------------
1545
1546 if ( StringUtils.isEmpty( doclet ) || useStandardDocletOptions )
1547 {
1548 addStandardDocletOptions( javadocOutputDirectory, arguments );
1549 }
1550
1551 // ----------------------------------------------------------------------
1552 // Write options file and include it in the command line
1553 // ----------------------------------------------------------------------
1554
1555 if ( arguments.size() > 0 )
1556 {
1557 addCommandLineOptions( cmd, arguments, javadocOutputDirectory );
1558 }
1559
1560 // ----------------------------------------------------------------------
1561 // Write packages file and include it in the command line
1562 // ----------------------------------------------------------------------
1563
1564 if ( !packageNames.isEmpty() )
1565 {
1566 addCommandLinePackages( cmd, javadocOutputDirectory, packageNames );
1567
1568 // ----------------------------------------------------------------------
1569 // Write argfile file and include it in the command line
1570 // ----------------------------------------------------------------------
1571
1572 if ( !filesWithUnnamedPackages.isEmpty() )
1573 {
1574 addCommandLineArgFile( cmd, javadocOutputDirectory, filesWithUnnamedPackages );
1575 }
1576 }
1577 else
1578 {
1579 // ----------------------------------------------------------------------
1580 // Write argfile file and include it in the command line
1581 // ----------------------------------------------------------------------
1582
1583 if ( !files.isEmpty() )
1584 {
1585 addCommandLineArgFile( cmd, javadocOutputDirectory, files );
1586 }
1587 }
1588
1589 // ----------------------------------------------------------------------
1590 // Execute command line
1591 // ----------------------------------------------------------------------
1592
1593 executeJavadocCommandLine( cmd, javadocOutputDirectory );
1594 }
1595
1596 /**
1597 * Method to get the files on the specified source paths
1598 *
1599 * @param sourcePaths a List that contains the paths to the source files
1600 * @return a List that contains the specific path for every source file
1601 */
1602 protected List getFiles( List sourcePaths )
1603 {
1604 List files = new ArrayList();
1605 if ( StringUtils.isEmpty( subpackages ) )
1606 {
1607 String[] excludedPackages = getExcludedPackages();
1608
1609 for ( Iterator i = sourcePaths.iterator(); i.hasNext(); )
1610 {
1611 File sourceDirectory = new File( (String) i.next() );
1612 JavadocUtil.addFilesFromSource( files, sourceDirectory, excludedPackages );
1613 }
1614 }
1615
1616 return files;
1617 }
1618
1619 /**
1620 * Method to get the source paths. If no source path is specified in the parameter, the compile source roots
1621 * of the project will be used.
1622 *
1623 * @return a List of the project absolute source paths as <code>String</code>
1624 * @see JavadocUtil#pruneDirs(MavenProject, List)
1625 */
1626 protected List getSourcePaths()
1627 {
1628 List sourcePaths;
1629
1630 if ( StringUtils.isEmpty( sourcepath ) )
1631 {
1632 sourcePaths = new ArrayList( JavadocUtil.pruneDirs( project, getProjectSourceRoots( project ) ) );
1633
1634 if ( project.getExecutionProject() != null )
1635 {
1636 sourcePaths.addAll( JavadocUtil.pruneDirs( project, getExecutionProjectSourceRoots( project ) ) );
1637 }
1638
1639 /*
1640 * Should be after the source path (i.e. -sourcepath '.../src/main/java;.../src/main/javadoc') and
1641 * *not* the opposite. If not, the javadoc tool always copies doc files, even if -docfilessubdirs is
1642 * not setted.
1643 */
1644 if ( getJavadocDirectory() != null )
1645 {
1646 File javadocDir = getJavadocDirectory();
1647 if ( javadocDir.exists() && javadocDir.isDirectory() )
1648 {
1649 List l =
1650 JavadocUtil.pruneDirs( project,
1651 Collections.singletonList( getJavadocDirectory().getAbsolutePath() ) );
1652 sourcePaths.addAll( l );
1653 }
1654 }
1655
1656 if ( isAggregator() && project.isExecutionRoot() )
1657 {
1658 for ( Iterator i = reactorProjects.iterator(); i.hasNext(); )
1659 {
1660 MavenProject subProject = (MavenProject) i.next();
1661
1662 if ( subProject != project )
1663 {
1664 List sourceRoots = getProjectSourceRoots( subProject );
1665
1666 if ( subProject.getExecutionProject() != null )
1667 {
1668 sourceRoots.addAll( getExecutionProjectSourceRoots( subProject ) );
1669 }
1670
1671 ArtifactHandler artifactHandler = subProject.getArtifact().getArtifactHandler();
1672 if ( "java".equals( artifactHandler.getLanguage() ) )
1673 {
1674 sourcePaths.addAll( JavadocUtil.pruneDirs( subProject, sourceRoots ) );
1675 }
1676
1677 String javadocDirRelative =
1678 PathUtils.toRelative( project.getBasedir(), getJavadocDirectory().getAbsolutePath() );
1679 File javadocDir = new File( subProject.getBasedir(), javadocDirRelative );
1680 if ( javadocDir.exists() && javadocDir.isDirectory() )
1681 {
1682 List l =
1683 JavadocUtil.pruneDirs( subProject,
1684 Collections.singletonList( javadocDir.getAbsolutePath() ) );
1685 sourcePaths.addAll( l );
1686 }
1687 }
1688 }
1689 }
1690 }
1691 else
1692 {
1693 sourcePaths = new ArrayList( Arrays.asList( sourcepath.split( "[;]" ) ) );
1694 sourcePaths = JavadocUtil.pruneDirs( project, sourcePaths );
1695 if ( getJavadocDirectory() != null )
1696 {
1697 List l =
1698 JavadocUtil.pruneDirs( project,
1699 Collections.singletonList( getJavadocDirectory().getAbsolutePath() ) );
1700 sourcePaths.addAll( l );
1701 }
1702 }
1703
1704 sourcePaths = JavadocUtil.pruneDirs( project, sourcePaths );
1705
1706 return sourcePaths;
1707 }
1708
1709 /**
1710 * Method that indicates whether the javadoc can be generated or not. If the project does not contain any source
1711 * files and no subpackages are specified, the plugin will terminate.
1712 *
1713 * @param files the project files
1714 * @return a boolean that indicates whether javadoc report can be generated or not
1715 */
1716 protected boolean canGenerateReport( List files )
1717 {
1718 boolean canGenerate = true;
1719
1720 if ( files.isEmpty() && StringUtils.isEmpty( subpackages ) )
1721 {
1722 canGenerate = false;
1723 }
1724
1725 return canGenerate;
1726 }
1727
1728 /**
1729 * @param result not null
1730 * @return the compile artifacts from the result
1731 * @see JavadocUtil#getCompileArtifacts(Set, boolean)
1732 */
1733 protected List getCompileArtifacts( ArtifactResolutionResult result )
1734 {
1735 return JavadocUtil.getCompileArtifacts( result.getArtifacts(), false );
1736 }
1737
1738 // ----------------------------------------------------------------------
1739 // private methods
1740 // ----------------------------------------------------------------------
1741
1742 /**
1743 * Method to get the excluded source files from the javadoc and create the argument string
1744 * that will be included in the javadoc commandline execution.
1745 *
1746 * @param sourcePaths the list of paths to the source files
1747 * @return a String that contains the exclude argument that will be used by javadoc
1748 */
1749 private String getExcludedPackages( List sourcePaths )
1750 {
1751 List excludedNames = null;
1752
1753 if ( StringUtils.isNotEmpty( sourcepath ) && StringUtils.isNotEmpty( subpackages ) )
1754 {
1755 String[] excludedPackages = getExcludedPackages();
1756 String[] subpackagesList = subpackages.split( "[:]" );
1757
1758 excludedNames = JavadocUtil.getExcludedNames( sourcePaths, subpackagesList, excludedPackages );
1759 }
1760
1761 String excludeArg = "";
1762 if ( StringUtils.isNotEmpty( subpackages ) && excludedNames != null )
1763 {
1764 // add the excludedpackage names
1765 for ( Iterator it = excludedNames.iterator(); it.hasNext(); )
1766 {
1767 String str = (String) it.next();
1768 excludeArg = excludeArg + str;
1769
1770 if ( it.hasNext() )
1771 {
1772 excludeArg = excludeArg + ":";
1773 }
1774 }
1775 }
1776
1777 return excludeArg;
1778 }
1779
1780 /**
1781 * Method to format the specified source paths that will be accepted by the javadoc tool.
1782 *
1783 * @param sourcePaths the list of paths to the source files that will be included in the javadoc
1784 * @return a String that contains the formatted source path argument
1785 */
1786 private String getSourcePath( List sourcePaths )
1787 {
1788 String sourcePath = null;
1789
1790 if ( StringUtils.isEmpty( subpackages ) || StringUtils.isNotEmpty( sourcepath ) )
1791 {
1792 sourcePath = StringUtils.join( sourcePaths.iterator(), File.pathSeparator );
1793 }
1794
1795 return sourcePath;
1796 }
1797
1798 /**
1799 * Method to get the packages specified in the excludePackageNames parameter. The packages are split
1800 * with ',', ':', or ';' and then formatted.
1801 *
1802 * @return an array of String objects that contain the package names
1803 */
1804 private String[] getExcludedPackages()
1805 {
1806 String[] excludePackages = {};
1807
1808 // for the specified excludePackageNames
1809 if ( excludePackageNames != null )
1810 {
1811 excludePackages = excludePackageNames.split( "[ ,:;]" );
1812 }
1813 for ( int i = 0; i < excludePackages.length; i++ )
1814 {
1815 excludePackages[i] = excludePackages[i].replace( '.', File.separatorChar );
1816 }
1817
1818 return excludePackages;
1819 }
1820
1821 /**
1822 * Method that sets the classpath elements that will be specified in the javadoc -classpath parameter.
1823 *
1824 * @return a String that contains the concatenated classpath elements
1825 * @throws MavenReportException if any
1826 */
1827 private String getClasspath()
1828 throws MavenReportException
1829 {
1830 List classpathElements = new ArrayList();
1831 Map compileArtifactMap = new HashMap();
1832
1833 classpathElements.addAll( getProjectBuildOutputDirs( project ) );
1834
1835 populateCompileArtifactMap( compileArtifactMap, getProjectArtifacts( project ) );
1836
1837 if ( isAggregator() && project.isExecutionRoot() )
1838 {
1839 try
1840 {
1841 for ( Iterator i = reactorProjects.iterator(); i.hasNext(); )
1842 {
1843 MavenProject subProject = (MavenProject) i.next();
1844
1845 if ( subProject != project )
1846 {
1847 classpathElements.addAll( getProjectBuildOutputDirs( subProject ) );
1848
1849 Set dependencyArtifacts = subProject.createArtifacts( factory, null, null );
1850 if ( !dependencyArtifacts.isEmpty() )
1851 {
1852 ArtifactResolutionResult result = null;
1853 try
1854 {
1855 result =
1856 resolver.resolveTransitively( dependencyArtifacts, subProject.getArtifact(),
1857 subProject.getManagedVersionMap(),
1858 localRepository,
1859 subProject.getRemoteArtifactRepositories(),
1860 artifactMetadataSource );
1861 }
1862 catch ( MultipleArtifactsNotFoundException e )
1863 {
1864 if ( checkMissingArtifactsInReactor( dependencyArtifacts, e.getMissingArtifacts() ) )
1865 {
1866 getLog().warn( "IGNORED to add some artifacts in the classpath. See above." );
1867 }
1868 else
1869 {
1870 // we can't find all the artifacts in the reactor so bubble the exception up.
1871 throw new MavenReportException( e.getMessage(), e );
1872 }
1873 }
1874 catch ( ArtifactNotFoundException e )
1875 {
1876 throw new MavenReportException( e.getMessage(), e );
1877 }
1878 catch ( ArtifactResolutionException e )
1879 {
1880 throw new MavenReportException( e.getMessage(), e );
1881 }
1882
1883 if ( result == null )
1884 {
1885 continue;
1886 }
1887
1888 populateCompileArtifactMap( compileArtifactMap, getCompileArtifacts( result ) );
1889
1890 if ( getLog().isDebugEnabled() )
1891 {
1892 StringBuffer sb = new StringBuffer();
1893
1894 sb.append( "Compiled artifacts for " );
1895 sb.append( subProject.getGroupId() ).append( ":" );
1896 sb.append( subProject.getArtifactId() ).append( ":" );
1897 sb.append( subProject.getVersion() ).append( '\n' );
1898 for ( Iterator it = compileArtifactMap.keySet().iterator(); it.hasNext(); )
1899 {
1900 String key = it.next().toString();
1901
1902 Artifact a = (Artifact) compileArtifactMap.get( key );
1903 sb.append( a.getFile() ).append( '\n' );
1904 }
1905
1906 getLog().debug( sb.toString() );
1907 }
1908 }
1909 }
1910 }
1911 }
1912 catch ( InvalidDependencyVersionException e )
1913 {
1914 throw new MavenReportException( e.getMessage(), e );
1915 }
1916 }
1917
1918 for ( Iterator it = compileArtifactMap.keySet().iterator(); it.hasNext(); )
1919 {
1920 String key = it.next().toString();
1921
1922 Artifact a = (Artifact) compileArtifactMap.get( key );
1923 classpathElements.add( a.getFile() );
1924 }
1925
1926 return StringUtils.join( classpathElements.iterator(), File.pathSeparator );
1927 }
1928
1929 /**
1930 * TODO remove the part with ToolchainManager lookup once we depend on
1931 * 3.0.9 (have it as prerequisite). Define as regular component field then.
1932 *
1933 * @return Toolchain instance
1934 */
1935 private Toolchain getToolchain()
1936 {
1937 Toolchain tc = null;
1938 try
1939 {
1940 if ( session != null ) // session is null in tests..
1941 {
1942 ToolchainManager toolchainManager =
1943 (ToolchainManager) session.getContainer().lookup( ToolchainManager.ROLE );
1944 if ( toolchainManager != null )
1945 {
1946 tc = toolchainManager.getToolchainFromBuildContext( "jdk", session );
1947 }
1948 }
1949 }
1950 catch ( ComponentLookupException componentLookupException )
1951 {
1952 // just ignore, could happen in pre-3.0.9 builds..
1953 }
1954
1955 return tc;
1956 }
1957
1958 /**
1959 * Method to put the artifacts in the hashmap.
1960 *
1961 * @param compileArtifactMap the hashmap that will contain the artifacts
1962 * @param artifactList the list of artifacts that will be put in the map
1963 * @throws MavenReportException if any
1964 */
1965 private void populateCompileArtifactMap( Map compileArtifactMap, Collection artifactList )
1966 throws MavenReportException
1967 {
1968 if ( artifactList != null )
1969 {
1970 for ( Iterator i = artifactList.iterator(); i.hasNext(); )
1971 {
1972 Artifact newArtifact = (Artifact) i.next();
1973
1974 File file = newArtifact.getFile();
1975
1976 if ( file == null )
1977 {
1978 throw new MavenReportException( "Error in plugin descriptor - "
1979 + "dependency was not resolved for artifact: " + newArtifact.getGroupId() + ":"
1980 + newArtifact.getArtifactId() + ":" + newArtifact.getVersion() );
1981 }
1982
1983 if ( compileArtifactMap.get( newArtifact.getDependencyConflictId() ) != null )
1984 {
1985 Artifact oldArtifact =
1986 (Artifact) compileArtifactMap.get( newArtifact.getDependencyConflictId() );
1987
1988 ArtifactVersion oldVersion = new DefaultArtifactVersion( oldArtifact.getVersion() );
1989 ArtifactVersion newVersion = new DefaultArtifactVersion( newArtifact.getVersion() );
1990 if ( newVersion.compareTo( oldVersion ) > 0 )
1991 {
1992 compileArtifactMap.put( newArtifact.getDependencyConflictId(), newArtifact );
1993 }
1994 }
1995 else
1996 {
1997 compileArtifactMap.put( newArtifact.getDependencyConflictId(), newArtifact );
1998 }
1999 }
2000 }
2001 }
2002
2003 /**
2004 * Method that sets the bottom text that will be displayed on the bottom of the
2005 * javadocs.
2006 *
2007 * @return a String that contains the text that will be displayed at the bottom of the javadoc
2008 */
2009 private String getBottomText()
2010 {
2011 int actualYear = Calendar.getInstance().get( Calendar.YEAR );
2012 String year = String.valueOf( actualYear );
2013
2014 String inceptionYear = project.getInceptionYear();
2015
2016 String theBottom = StringUtils.replace( this.bottom, "{currentYear}", year );
2017
2018 if ( inceptionYear != null )
2019 {
2020 if ( inceptionYear.equals( year ) )
2021 {
2022 theBottom = StringUtils.replace( theBottom, "{inceptionYear}-", "" );
2023 }
2024 else
2025 {
2026 theBottom = StringUtils.replace( theBottom, "{inceptionYear}", inceptionYear );
2027 }
2028 }
2029 else
2030 {
2031 theBottom = StringUtils.replace( theBottom, "{inceptionYear}-", "" );
2032 }
2033
2034 if ( project.getOrganization() == null )
2035 {
2036 theBottom = StringUtils.replace( theBottom, " {organizationName}", "" );
2037 }
2038 else
2039 {
2040 if ( StringUtils.isNotEmpty( project.getOrganization().getName() ) )
2041 {
2042 if ( StringUtils.isNotEmpty( project.getOrganization().getUrl() ) )
2043 {
2044 theBottom =
2045 StringUtils.replace( theBottom, "{organizationName}", "<a href=\""
2046 + project.getOrganization().getUrl() + "\">" + project.getOrganization().getName()
2047 + "</a>" );
2048 }
2049 else
2050 {
2051 theBottom =
2052 StringUtils.replace( theBottom, "{organizationName}", project.getOrganization().getName() );
2053 }
2054 }
2055 else
2056 {
2057 theBottom = StringUtils.replace( theBottom, " {organizationName}", "" );
2058 }
2059 }
2060
2061 return theBottom;
2062 }
2063
2064 /**
2065 * Method to get the stylesheet path file to be used in the javadocs. If a custom stylesheet file is not specified,
2066 * either the stylesheet included in the plugin or the stylesheet file used by the javadoc tool will be used.
2067 *
2068 * @param javadocOutputDirectory the base directory of the plugin
2069 * @return a String that contains the path to the stylesheet file
2070 */
2071 private String getStylesheetFile( File javadocOutputDirectory )
2072 {
2073 String stylesheetfilePath = this.stylesheetfile;
2074 if ( StringUtils.isEmpty( stylesheetfilePath ) && "maven".equals( stylesheet ) )
2075 {
2076 stylesheetfilePath = javadocOutputDirectory + File.separator + DEFAULT_CSS_NAME;
2077 }
2078
2079 return stylesheetfilePath;
2080 }
2081
2082 /**
2083 * Method to get the access level for the classes and members to be shown in the generated javadoc.
2084 * If the specified access level is not public, protected, package or private, the access level
2085 * is set to protected.
2086 *
2087 * @return the access level
2088 */
2089 private String getAccessLevel()
2090 {
2091 String accessLevel;
2092 if ( "public".equalsIgnoreCase( show ) || "protected".equalsIgnoreCase( show )
2093 || "package".equalsIgnoreCase( show ) || "private".equalsIgnoreCase( show ) )
2094 {
2095 accessLevel = "-" + show;
2096 }
2097 else
2098 {
2099 if ( getLog().isErrorEnabled() )
2100 {
2101 getLog().error( "Unrecognized access level to show '" + show + "'. Defaulting to protected." );
2102 }
2103 accessLevel = "-protected";
2104 }
2105
2106 return accessLevel;
2107 }
2108
2109 /**
2110 * Method to get the path of the bootclass artifacts used in the -bootclasspath option.
2111 *
2112 * @return the path to jar file that contains taglet class file separated with a colon (<code>:</code>)
2113 * on Solaris and a semi-colon (<code>;</code>) on Windows
2114 * @throws MavenReportException if any
2115 */
2116 private String getBootclassPath()
2117 throws MavenReportException
2118 {
2119 StringBuffer path = new StringBuffer();
2120
2121 if ( bootclasspathArtifacts != null )
2122 {
2123 List bootclassPath = new ArrayList();
2124 for ( int i = 0; i < bootclasspathArtifacts.length; i++ )
2125 {
2126 BootclasspathArtifact aBootclasspathArtifact = bootclasspathArtifacts[i];
2127
2128 if ( ( StringUtils.isNotEmpty( aBootclasspathArtifact.getGroupId() ) )
2129 && ( StringUtils.isNotEmpty( aBootclasspathArtifact.getArtifactId() ) )
2130 && ( StringUtils.isNotEmpty( aBootclasspathArtifact.getVersion() ) ) )
2131 {
2132 bootclassPath.addAll( getArtifactsAbsolutePath( aBootclasspathArtifact ) );
2133 }
2134 }
2135
2136 bootclassPath = JavadocUtil.pruneFiles( bootclassPath );
2137
2138 path.append( StringUtils.join( bootclassPath.iterator(), File.pathSeparator ) );
2139 }
2140
2141 if ( StringUtils.isNotEmpty( bootclasspath ) )
2142 {
2143 path.append( bootclasspath );
2144 }
2145
2146 return path.toString();
2147 }
2148
2149 /**
2150 * Method to get the path of the doclet artifacts used in the -docletpath option.
2151 *
2152 * Either docletArtifact or doclectArtifacts can be defined and used, not both, docletArtifact
2153 * takes precedence over doclectArtifacts. docletPath is always appended to any result path
2154 * definition.
2155 *
2156 * @return the path to jar file that contains doclet class file separated with a colon (<code>:</code>)
2157 * on Solaris and a semi-colon (<code>;</code>) on Windows
2158 * @throws MavenReportException if any
2159 */
2160 private String getDocletPath()
2161 throws MavenReportException
2162 {
2163 StringBuffer path = new StringBuffer();
2164 if ( !isDocletArtifactEmpty( docletArtifact ) )
2165 {
2166 path.append( StringUtils.join( getArtifactsAbsolutePath( docletArtifact ).iterator(),
2167 File.pathSeparator ) );
2168 }
2169 else if ( docletArtifacts != null )
2170 {
2171 for ( int i = 0; i < docletArtifacts.length; i++ )
2172 {
2173 if ( !isDocletArtifactEmpty( docletArtifacts[i] ) )
2174 {
2175 path.append( StringUtils.join( getArtifactsAbsolutePath( docletArtifacts[i] ).iterator(),
2176 File.pathSeparator ) );
2177
2178 if ( i < docletArtifacts.length - 1 )
2179 {
2180 path.append( File.pathSeparator );
2181 }
2182 }
2183 }
2184 }
2185
2186 if ( !StringUtils.isEmpty( docletPath ) )
2187 {
2188 path.append( docletPath );
2189 }
2190
2191 if ( StringUtils.isEmpty( path.toString() ) && getLog().isWarnEnabled() )
2192 {
2193 getLog().warn(
2194 "No docletpath option was found. Please review <docletpath/> or <docletArtifact/>"
2195 + " or <doclets/>." );
2196 }
2197
2198 return path.toString();
2199 }
2200
2201 /**
2202 * Verify if a doclet artifact is empty or not
2203 *
2204 * @param aDocletArtifact could be null
2205 * @return <code>true</code> if aDocletArtifact or the groupId/artifactId/version of the doclet artifact is null,
2206 * <code>false</code> otherwise.
2207 */
2208 private boolean isDocletArtifactEmpty( DocletArtifact aDocletArtifact )
2209 {
2210 if ( aDocletArtifact == null )
2211 {
2212 return true;
2213 }
2214
2215 return StringUtils.isEmpty( aDocletArtifact.getGroupId() )
2216 && StringUtils.isEmpty( aDocletArtifact.getArtifactId() )
2217 && StringUtils.isEmpty( aDocletArtifact.getVersion() );
2218 }
2219
2220 /**
2221 * Method to get the path of the taglet artifacts used in the -tagletpath option.
2222 *
2223 * @return the path to jar file that contains taglet class file separated with a colon (<code>:</code>)
2224 * on Solaris and a semi-colon (<code>;</code>) on Windows
2225 * @throws MavenReportException if any
2226 */
2227 private String getTagletPath()
2228 throws MavenReportException
2229 {
2230 StringBuffer path = new StringBuffer();
2231
2232 if ( ( tagletArtifact != null ) && ( StringUtils.isNotEmpty( tagletArtifact.getGroupId() ) )
2233 && ( StringUtils.isNotEmpty( tagletArtifact.getArtifactId() ) )
2234 && ( StringUtils.isNotEmpty( tagletArtifact.getVersion() ) ) )
2235 {
2236 path.append( StringUtils.join( getArtifactsAbsolutePath( tagletArtifact ).iterator(),
2237 File.pathSeparator ) );
2238 }
2239
2240 if ( tagletArtifacts != null )
2241 {
2242 List tagletsPath = new ArrayList();
2243 for ( int i = 0; i < tagletArtifacts.length; i++ )
2244 {
2245 TagletArtifact aTagletArtifact = tagletArtifacts[i];
2246
2247 if ( ( StringUtils.isNotEmpty( aTagletArtifact.getGroupId() ) )
2248 && ( StringUtils.isNotEmpty( aTagletArtifact.getArtifactId() ) )
2249 && ( StringUtils.isNotEmpty( aTagletArtifact.getVersion() ) ) )
2250 {
2251 tagletsPath.addAll( getArtifactsAbsolutePath( aTagletArtifact ) );
2252 }
2253 }
2254
2255 tagletsPath = JavadocUtil.pruneFiles( tagletsPath );
2256
2257 path.append( StringUtils.join( tagletsPath.iterator(), File.pathSeparator ) );
2258 }
2259
2260 if ( taglets != null )
2261 {
2262 List tagletsPath = new ArrayList();
2263 for ( int i = 0; i < taglets.length; i++ )
2264 {
2265 Taglet current = taglets[i];
2266
2267 if ( current == null )
2268 {
2269 continue;
2270 }
2271
2272 if ( ( current.getTagletArtifact() != null )
2273 && ( StringUtils.isNotEmpty( current.getTagletArtifact().getGroupId() ) )
2274 && ( StringUtils.isNotEmpty( current.getTagletArtifact().getArtifactId() ) )
2275 && ( StringUtils.isNotEmpty( current.getTagletArtifact().getVersion() ) ) )
2276 {
2277 tagletsPath.addAll( getArtifactsAbsolutePath( current.getTagletArtifact() ) );
2278 }
2279 else if ( StringUtils.isNotEmpty( current.getTagletpath() ) )
2280 {
2281 tagletsPath.add( current.getTagletpath() );
2282 }
2283 }
2284
2285 tagletsPath = JavadocUtil.pruneFiles( tagletsPath );
2286
2287 path.append( StringUtils.join( tagletsPath.iterator(), File.pathSeparator ) );
2288 }
2289
2290 if ( StringUtils.isNotEmpty( tagletpath ) )
2291 {
2292 path.append( tagletpath );
2293 }
2294
2295 return path.toString();
2296 }
2297
2298 /**
2299 * Return the Javadoc artifact path and its transitive dependencies path from the local repository
2300 *
2301 * @param javadocArtifact not null
2302 * @return a list of locale artifacts absolute path
2303 * @throws MavenReportException if any
2304 */
2305 private List getArtifactsAbsolutePath( JavadocPathArtifact javadocArtifact )
2306 throws MavenReportException
2307 {
2308 if ( ( StringUtils.isEmpty( javadocArtifact.getGroupId() ) )
2309 && ( StringUtils.isEmpty( javadocArtifact.getArtifactId() ) )
2310 && ( StringUtils.isEmpty( javadocArtifact.getVersion() ) ) )
2311 {
2312 return Collections.EMPTY_LIST;
2313 }
2314
2315 List path = new ArrayList();
2316
2317 try
2318 {
2319 Artifact artifact = createAndResolveArtifact( javadocArtifact );
2320 path.add( artifact.getFile().getAbsolutePath() );
2321
2322 // Find its transitive dependencies in the local repo
2323 MavenProject artifactProject =
2324 mavenProjectBuilder.buildFromRepository( artifact, remoteRepositories, localRepository );
2325 Set dependencyArtifacts = artifactProject.createArtifacts( factory, null, null );
2326 if ( !dependencyArtifacts.isEmpty() )
2327 {
2328 ArtifactResolutionResult result =
2329 resolver.resolveTransitively( dependencyArtifacts, artifactProject.getArtifact(),
2330 artifactProject.getRemoteArtifactRepositories(),
2331 localRepository, artifactMetadataSource );
2332 Set artifacts = result.getArtifacts();
2333
2334 Map compileArtifactMap = new HashMap();
2335 populateCompileArtifactMap( compileArtifactMap, artifacts );
2336
2337 for ( Iterator it = compileArtifactMap.keySet().iterator(); it.hasNext(); )
2338 {
2339 String key = it.next().toString();
2340
2341 Artifact a = (Artifact) compileArtifactMap.get( key );
2342 path.add( a.getFile().getAbsolutePath() );
2343 }
2344 }
2345
2346 return path;
2347 }
2348 catch ( ArtifactResolutionException e )
2349 {
2350 throw new MavenReportException( "Unable to resolve artifact:" + javadocArtifact, e );
2351 }
2352 catch ( ArtifactNotFoundException e )
2353 {
2354 throw new MavenReportException( "Unable to find artifact:" + javadocArtifact, e );
2355 }
2356 catch ( ProjectBuildingException e )
2357 {
2358 throw new MavenReportException( "Unable to build the Maven project for the artifact:"
2359 + javadocArtifact, e );
2360 }
2361 catch ( InvalidDependencyVersionException e )
2362 {
2363 throw new MavenReportException( "Unable to resolve artifact:" + javadocArtifact, e );
2364 }
2365 }
2366
2367 /**
2368 * creates an {@link Artifact} representing the configured {@link JavadocPathArtifact} and resolves it.
2369 *
2370 * @param javadocArtifact the {@link JavadocPathArtifact} to resolve
2371 * @return a resolved {@link Artifact}
2372 * @throws ArtifactResolutionException if the resolution of the artifact failed.
2373 * @throws ArtifactNotFoundException if the artifact hasn't been found.
2374 * @throws ProjectBuildingException if the artifact POM could not be build.
2375 */
2376 private Artifact createAndResolveArtifact( JavadocPathArtifact javadocArtifact )
2377 throws ArtifactResolutionException, ArtifactNotFoundException, ProjectBuildingException
2378 {
2379 Artifact artifact =
2380 factory.createProjectArtifact( javadocArtifact.getGroupId(), javadocArtifact.getArtifactId(),
2381 javadocArtifact.getVersion(), Artifact.SCOPE_COMPILE );
2382
2383 if ( artifact.getFile() == null )
2384 {
2385 MavenProject pluginProject =
2386 mavenProjectBuilder.buildFromRepository( artifact, remoteRepositories, localRepository );
2387 artifact = pluginProject.getArtifact();
2388
2389 resolver.resolve( artifact, remoteRepositories, localRepository );
2390 }
2391
2392 return artifact;
2393 }
2394
2395 /**
2396 * Method that adds/sets the java memory parameters in the command line execution.
2397 *
2398 * @param cmd the command line execution object where the argument will be added
2399 * @param arg the argument parameter name
2400 * @param memory the JVM memory value to be set
2401 * @see JavadocUtil#parseJavadocMemory(String)
2402 */
2403 private void addMemoryArg( Commandline cmd, String arg, String memory )
2404 {
2405 if ( StringUtils.isNotEmpty( memory ) )
2406 {
2407 try
2408 {
2409 cmd.createArg().setValue( "-J" + arg + JavadocUtil.parseJavadocMemory( memory ) );
2410 }
2411 catch ( IllegalArgumentException e )
2412 {
2413 if ( getLog().isErrorEnabled() )
2414 {
2415 getLog().error( "Malformed memory pattern for '" + arg + memory + "'. Ignore this option." );
2416 }
2417 }
2418 }
2419 }
2420
2421 /**
2422 * Method that adds/sets the javadoc proxy parameters in the command line execution.
2423 *
2424 * @param cmd the command line execution object where the argument will be added
2425 */
2426 private void addProxyArg( Commandline cmd )
2427 {
2428 // backward compatible
2429 if ( StringUtils.isNotEmpty( proxyHost ) )
2430 {
2431 if ( getLog().isWarnEnabled() )
2432 {
2433 getLog().warn(
2434 "The Javadoc plugin parameter 'proxyHost' is deprecated since 2.4. "
2435 + "Please configure an active proxy in your settings.xml." );
2436 }
2437 cmd.createArg().setValue( "-J-DproxyHost=" + proxyHost );
2438
2439 if ( proxyPort > 0 )
2440 {
2441 if ( getLog().isWarnEnabled() )
2442 {
2443 getLog().warn(
2444 "The Javadoc plugin parameter 'proxyPort' is deprecated since 2.4. "
2445 + "Please configure an active proxy in your settings.xml." );
2446 }
2447 cmd.createArg().setValue( "-J-DproxyPort=" + proxyPort );
2448 }
2449 }
2450
2451 if ( settings == null )
2452 {
2453 return;
2454 }
2455
2456 Proxy activeProxy = settings.getActiveProxy();
2457 if ( activeProxy != null )
2458 {
2459 String protocol =
2460 StringUtils.isNotEmpty( activeProxy.getProtocol() ) ? activeProxy.getProtocol() + "." : "";
2461
2462 if ( StringUtils.isNotEmpty( activeProxy.getHost() ) )
2463 {
2464 cmd.createArg().setValue( "-J-D" + protocol + "proxySet=true" );
2465 cmd.createArg().setValue( "-J-D" + protocol + "proxyHost=" + activeProxy.getHost() );
2466
2467 if ( activeProxy.getPort() > 0 )
2468 {
2469 cmd.createArg().setValue( "-J-D" + protocol + "proxyPort=" + activeProxy.getPort() );
2470 }
2471
2472 if ( StringUtils.isNotEmpty( activeProxy.getNonProxyHosts() ) )
2473 {
2474 cmd.createArg().setValue(
2475 "-J-D" + protocol + "nonProxyHosts=\""
2476 + activeProxy.getNonProxyHosts() + "\"" );
2477 }
2478
2479 if ( StringUtils.isNotEmpty( activeProxy.getUsername() ) )
2480 {
2481 cmd.createArg().setValue( "-J-Dhttp.proxyUser=\"" + activeProxy.getUsername() + "\"" );
2482
2483 if ( StringUtils.isNotEmpty( activeProxy.getPassword() ) )
2484 {
2485 cmd.createArg().setValue( "-J-Dhttp.proxyPassword=\"" + activeProxy.getPassword() + "\"" );
2486 }
2487 }
2488 }
2489 }
2490 }
2491
2492 /**
2493 * Get the path of the Javadoc tool executable depending the user entry or try to find it depending the OS
2494 * or the <code>java.home</code> system property or the <code>JAVA_HOME</code> environment variable.
2495 *
2496 * @return the path of the Javadoc tool
2497 * @throws IOException if not found
2498 */
2499 private String getJavadocExecutable()
2500 throws IOException
2501 {
2502 Toolchain tc = getToolchain();
2503
2504 if ( tc != null )
2505 {
2506 getLog().info( "Toolchain in javadoc-plugin: " + tc );
2507 if ( javadocExecutable != null )
2508 {
2509 getLog().warn(
2510 "Toolchains are ignored, 'javadocExecutable' parameter is set to "
2511 + javadocExecutable );
2512 }
2513 else
2514 {
2515 javadocExecutable = tc.findTool( "javadoc" );
2516 }
2517 }
2518
2519 String javadocCommand = "javadoc" + ( SystemUtils.IS_OS_WINDOWS ? ".exe" : "" );
2520
2521 File javadocExe;
2522
2523 // ----------------------------------------------------------------------
2524 // The javadoc executable is defined by the user
2525 // ----------------------------------------------------------------------
2526 if ( StringUtils.isNotEmpty( javadocExecutable ) )
2527 {
2528 javadocExe = new File( javadocExecutable );
2529
2530 if ( javadocExe.isDirectory() )
2531 {
2532 javadocExe = new File( javadocExe, javadocCommand );
2533 }
2534
2535 if ( SystemUtils.IS_OS_WINDOWS && javadocExe.getName().indexOf( '.' ) < 0 )
2536 {
2537 javadocExe = new File( javadocExe.getPath() + ".exe" );
2538 }
2539
2540 if ( !javadocExe.isFile() )
2541 {
2542 throw new IOException( "The javadoc executable '" + javadocExe
2543 + "' doesn't exist or is not a file. Verify the <javadocExecutable/> parameter." );
2544 }
2545
2546 return javadocExe.getAbsolutePath();
2547 }
2548
2549 // ----------------------------------------------------------------------
2550 // Try to find javadocExe from System.getProperty( "java.home" )
2551 // By default, System.getProperty( "java.home" ) = JRE_HOME and JRE_HOME
2552 // should be in the JDK_HOME
2553 // ----------------------------------------------------------------------
2554 // For IBM's JDK 1.2
2555 if ( SystemUtils.IS_OS_AIX )
2556 {
2557 javadocExe =
2558 new File( SystemUtils.getJavaHome() + File.separator + ".." + File.separator + "sh",
2559 javadocCommand );
2560 }
2561 else if ( SystemUtils.IS_OS_MAC_OSX )
2562 {
2563 javadocExe = new File( SystemUtils.getJavaHome() + File.separator + "bin", javadocCommand );
2564 }
2565 else
2566 {
2567 javadocExe =
2568 new File( SystemUtils.getJavaHome() + File.separator + ".." + File.separator + "bin",
2569 javadocCommand );
2570 }
2571
2572 // ----------------------------------------------------------------------
2573 // Try to find javadocExe from JAVA_HOME environment variable
2574 // ----------------------------------------------------------------------
2575 if ( !javadocExe.exists() || !javadocExe.isFile() )
2576 {
2577 Properties env = CommandLineUtils.getSystemEnvVars();
2578 String javaHome = env.getProperty( "JAVA_HOME" );
2579 if ( StringUtils.isEmpty( javaHome ) )
2580 {
2581 throw new IOException( "The environment variable JAVA_HOME is not correctly set." );
2582 }
2583 if ( ( !new File( javaHome ).exists() ) || ( !new File( javaHome ).isDirectory() ) )
2584 {
2585 throw new IOException( "The environment variable JAVA_HOME=" + javaHome
2586 + " doesn't exist or is not a valid directory." );
2587 }
2588
2589 javadocExe = new File( env.getProperty( "JAVA_HOME" ) + File.separator + "bin", javadocCommand );
2590 }
2591
2592 if ( !javadocExe.exists() || !javadocExe.isFile() )
2593 {
2594 throw new IOException( "The javadoc executable '" + javadocExe
2595 + "' doesn't exist or is not a file. Verify the JAVA_HOME environment variable." );
2596 }
2597
2598 return javadocExe.getAbsolutePath();
2599 }
2600
2601 /**
2602 * Set a new value for <code>fJavadocVersion</code>
2603 *
2604 * @param jExecutable not null
2605 * @throws MavenReportException if not found
2606 * @see JavadocUtil#getJavadocVersion(File)
2607 */
2608 private void setFJavadocVersion( File jExecutable )
2609 throws MavenReportException
2610 {
2611 float jVersion;
2612 try
2613 {
2614 jVersion = JavadocUtil.getJavadocVersion( jExecutable );
2615 }
2616 catch ( IOException e )
2617 {
2618 if ( getLog().isWarnEnabled() )
2619 {
2620 getLog().warn( "Unable to find the javadoc version: " + e.getMessage() );
2621 getLog().warn( "Using the Java version instead of, i.e. " + SystemUtils.JAVA_VERSION_FLOAT );
2622 }
2623 jVersion = SystemUtils.JAVA_VERSION_FLOAT;
2624 }
2625 catch ( CommandLineException e )
2626 {
2627 if ( getLog().isWarnEnabled() )
2628 {
2629 getLog().warn( "Unable to find the javadoc version: " + e.getMessage() );
2630 getLog().warn( "Using the Java the version instead of, i.e. " + SystemUtils.JAVA_VERSION_FLOAT );
2631 }
2632 jVersion = SystemUtils.JAVA_VERSION_FLOAT;
2633 }
2634 catch ( IllegalArgumentException e )
2635 {
2636 if ( getLog().isWarnEnabled() )
2637 {
2638 getLog().warn( "Unable to find the javadoc version: " + e.getMessage() );
2639 getLog().warn( "Using the Java the version instead of, i.e. " + SystemUtils.JAVA_VERSION_FLOAT );
2640 }
2641 jVersion = SystemUtils.JAVA_VERSION_FLOAT;
2642 }
2643
2644 if ( StringUtils.isNotEmpty( javadocVersion ) )
2645 {
2646 try
2647 {
2648 fJavadocVersion = Float.parseFloat( javadocVersion );
2649 }
2650 catch ( NumberFormatException e )
2651 {
2652 throw new MavenReportException( "Unable to parse javadoc version: " + e.getMessage(), e );
2653 }
2654
2655 if ( fJavadocVersion != jVersion && getLog().isWarnEnabled() )
2656 {
2657 getLog().warn( "Are you sure about the <javadocVersion/> parameter? It seems to be " + jVersion );
2658 }
2659 }
2660 else
2661 {
2662 fJavadocVersion = jVersion;
2663 }
2664 }
2665
2666 /**
2667 * Is the Javadoc version at least the requested version.
2668 *
2669 * @param requiredVersion the required version, for example 1.5f
2670 * @return <code>true</code> if the javadoc version is equal or greater than the
2671 * required version
2672 */
2673 private boolean isJavaDocVersionAtLeast( float requiredVersion )
2674 {
2675 return fJavadocVersion >= requiredVersion;
2676 }
2677
2678 /**
2679 * Convenience method to add an argument to the <code>command line</code>
2680 * conditionally based on the given flag.
2681 *
2682 * @param arguments a list of arguments, not null
2683 * @param b the flag which controls if the argument is added or not.
2684 * @param value the argument value to be added.
2685 */
2686 private void addArgIf( List arguments, boolean b, String value )
2687 {
2688 if ( b )
2689 {
2690 arguments.add( value );
2691 }
2692 }
2693
2694 /**
2695 * Convenience method to add an argument to the <code>command line</code>
2696 * regarding the requested Java version.
2697 *
2698 * @param arguments a list of arguments, not null
2699 * @param b the flag which controls if the argument is added or not.
2700 * @param value the argument value to be added.
2701 * @param requiredJavaVersion the required Java version, for example 1.31f or 1.4f
2702 * @see #addArgIf(java.util.List,boolean,String)
2703 * @see #isJavaDocVersionAtLeast(float)
2704 */
2705 private void addArgIf( List arguments, boolean b, String value, float requiredJavaVersion )
2706 {
2707 if ( b )
2708 {
2709 if ( isJavaDocVersionAtLeast( requiredJavaVersion ) )
2710 {
2711 addArgIf( arguments, b, value );
2712 }
2713 else
2714 {
2715 if ( getLog().isWarnEnabled() )
2716 {
2717 getLog().warn(
2718 value + " option is not supported on Java version < " + requiredJavaVersion
2719 + ". Ignore this option." );
2720 }
2721 }
2722 }
2723 }
2724
2725 /**
2726 * Convenience method to add an argument to the <code>command line</code>
2727 * if the the value is not null or empty.
2728 * <p/>
2729 * Moreover, the value could be comma separated.
2730 *
2731 * @param arguments a list of arguments, not null
2732 * @param key the argument name.
2733 * @param value the argument value to be added.
2734 * @see #addArgIfNotEmpty(java.util.List,String,String,boolean)
2735 */
2736 private void addArgIfNotEmpty( List arguments, String key, String value )
2737 {
2738 addArgIfNotEmpty( arguments, key, value, false );
2739 }
2740
2741 /**
2742 * Convenience method to add an argument to the <code>command line</code>
2743 * if the the value is not null or empty.
2744 * <p/>
2745 * Moreover, the value could be comma separated.
2746 *
2747 * @param arguments a list of arguments, not null
2748 * @param key the argument name.
2749 * @param value the argument value to be added.
2750 * @param repeatKey repeat or not the key in the command line
2751 * @param splitValue if <code>true</code> given value will be tokenized by comma
2752 * @param requiredJavaVersion the required Java version, for example 1.31f or 1.4f
2753 * @see #addArgIfNotEmpty(List, String, String, boolean, boolean)
2754 * @see #isJavaDocVersionAtLeast(float)
2755 */
2756 private void addArgIfNotEmpty( List arguments, String key, String value, boolean repeatKey,
2757 boolean splitValue, float requiredJavaVersion )
2758 {
2759 if ( StringUtils.isNotEmpty( value ) )
2760 {
2761 if ( isJavaDocVersionAtLeast( requiredJavaVersion ) )
2762 {
2763 addArgIfNotEmpty( arguments, key, value, repeatKey, splitValue );
2764 }
2765 else
2766 {
2767 if ( getLog().isWarnEnabled() )
2768 {
2769 getLog().warn(
2770 key + " option is not supported on Java version < " + requiredJavaVersion
2771 + ". Ignore this option." );
2772 }
2773 }
2774 }
2775 }
2776
2777 /**
2778 * Convenience method to add an argument to the <code>command line</code>
2779 * if the the value is not null or empty.
2780 * <p/>
2781 * Moreover, the value could be comma separated.
2782 *
2783 * @param arguments a list of arguments, not null
2784 * @param key the argument name.
2785 * @param value the argument value to be added.
2786 * @param repeatKey repeat or not the key in the command line
2787 * @param splitValue if <code>true</code> given value will be tokenized by comma
2788 */
2789 private void addArgIfNotEmpty( List arguments, String key, String value, boolean repeatKey, boolean splitValue )
2790 {
2791 if ( StringUtils.isNotEmpty( value ) )
2792 {
2793 if ( StringUtils.isNotEmpty( key ) )
2794 {
2795 arguments.add( key );
2796 }
2797
2798 if ( splitValue )
2799 {
2800 StringTokenizer token = new StringTokenizer( value, "," );
2801 while ( token.hasMoreTokens() )
2802 {
2803 String current = token.nextToken().trim();
2804
2805 if ( StringUtils.isNotEmpty( current ) )
2806 {
2807 arguments.add( current );
2808
2809 if ( token.hasMoreTokens() && repeatKey )
2810 {
2811 arguments.add( key );
2812 }
2813 }
2814 }
2815 }
2816 else
2817 {
2818 arguments.add( value );
2819 }
2820 }
2821 }
2822
2823 /**
2824 * Convenience method to add an argument to the <code>command line</code>
2825 * if the the value is not null or empty.
2826 * <p/>
2827 * Moreover, the value could be comma separated.
2828 *
2829 * @param arguments a list of arguments, not null
2830 * @param key the argument name.
2831 * @param value the argument value to be added.
2832 * @param repeatKey repeat or not the key in the command line
2833 */
2834 private void addArgIfNotEmpty( List arguments, String key, String value, boolean repeatKey )
2835 {
2836 addArgIfNotEmpty( arguments, key, value, repeatKey, true );
2837 }
2838
2839 /**
2840 * Convenience method to add an argument to the <code>command line</code>
2841 * regarding the requested Java version.
2842 *
2843 * @param arguments a list of arguments, not null
2844 * @param key the argument name.
2845 * @param value the argument value to be added.
2846 * @param requiredJavaVersion the required Java version, for example 1.31f or 1.4f
2847 * @see #addArgIfNotEmpty(java.util.List, String, String, float, boolean)
2848 */
2849 private void addArgIfNotEmpty( List arguments, String key, String value, float requiredJavaVersion )
2850 {
2851 addArgIfNotEmpty( arguments, key, value, requiredJavaVersion, false );
2852 }
2853
2854 /**
2855 * Convenience method to add an argument to the <code>command line</code>
2856 * regarding the requested Java version.
2857 *
2858 * @param arguments a list of arguments, not null
2859 * @param key the argument name.
2860 * @param value the argument value to be added.
2861 * @param requiredJavaVersion the required Java version, for example 1.31f or 1.4f
2862 * @param repeatKey repeat or not the key in the command line
2863 * @see #addArgIfNotEmpty(java.util.List,String,String)
2864 * @see #isJavaDocVersionAtLeast(float)
2865 */
2866 private void addArgIfNotEmpty( List arguments, String key, String value, float requiredJavaVersion,
2867 boolean repeatKey )
2868 {
2869 if ( StringUtils.isNotEmpty( value ) )
2870 {
2871 if ( isJavaDocVersionAtLeast( requiredJavaVersion ) )
2872 {
2873 addArgIfNotEmpty( arguments, key, value, repeatKey );
2874 }
2875 else
2876 {
2877 if ( getLog().isWarnEnabled() )
2878 {
2879 getLog().warn( key + " option is not supported on Java version < " + requiredJavaVersion );
2880 }
2881 }
2882 }
2883 }
2884
2885 /**
2886 * Convenience method to process offlineLink values as individual -linkoffline javadoc options
2887 *
2888 * @param arguments a list of arguments, not null
2889 */
2890 private void addLinkofflineArguments( List arguments )
2891 {
2892 List offlineLinksList =
2893 ( offlineLinks != null ? new ArrayList( Arrays.asList( offlineLinks ) ) : new ArrayList() );
2894
2895 if ( !isAggregator() && reactorProjects != null )
2896 {
2897 String javadocDirRelative = PathUtils.toRelative( project.getBasedir(), getOutputDirectory() );
2898
2899 for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
2900 {
2901 MavenProject p = (MavenProject) it.next();
2902
2903 // don't add projects that have not built yet.
2904 if ( p.getId().equals( project.getId() ) )
2905 {
2906 break;
2907 }
2908
2909 if ( p.getUrl() != null )
2910 {
2911 String url = p.getUrl() + "/apidocs";
2912 File location = new File( p.getBasedir(), javadocDirRelative );
2913
2914 if ( location.exists() )
2915 {
2916 OfflineLink ol = new OfflineLink();
2917 ol.setUrl( url );
2918 ol.setLocation( location.getAbsolutePath() );
2919
2920 offlineLinksList.add( ol );
2921 }
2922 }
2923 }
2924 }
2925
2926 if ( offlineLinksList != null )
2927 {
2928 for ( int i = 0; i < offlineLinksList.size(); i++ )
2929 {
2930 OfflineLink offlineLink = (OfflineLink) offlineLinksList.get( i );
2931 addArgIfNotEmpty( arguments, "-linkoffline", JavadocUtil.quotedPathArgument( offlineLink.getUrl() )
2932 + " " + JavadocUtil.quotedPathArgument( offlineLink.getLocation() ), true );
2933 }
2934 }
2935 }
2936
2937 /**
2938 * Convenience method to process link values as individual -link javadoc options.
2939 * If a <code>package-list</code> in a configured link is not available, remove the link.
2940 * <br/>
2941 * <b>Note</b>: if a link is not fetchable:
2942 * <ul>
2943 * <li>Javadoc 1.4 and less throw an exception</li>
2944 * <li>Javadoc 1.5 and more display a warning</li>
2945 * </ul>
2946 *
2947 * @param arguments a list of arguments, not null
2948 */
2949 private void addLinkArguments( List arguments )
2950 {
2951 if ( links != null )
2952 {
2953 for ( int i = 0; i < links.size(); i++ )
2954 {
2955 String link = (String) links.get( i );
2956
2957 if ( StringUtils.isEmpty( link ) )
2958 {
2959 continue;
2960 }
2961
2962 if ( link.endsWith( "/" ) )
2963 {
2964 link = link.substring( 0, link.length() - 1 );
2965 }
2966
2967 try
2968 {
2969 URI linkUri;
2970 if ( link.trim().toLowerCase( Locale.ENGLISH ).startsWith( "http" )
2971 || link.trim().toLowerCase( Locale.ENGLISH ).startsWith( "https" )
2972 || link.trim().toLowerCase( Locale.ENGLISH ).startsWith( "ftp" )
2973 || link.trim().toLowerCase( Locale.ENGLISH ).startsWith( "file" ) )
2974 {
2975 linkUri = new URI( link + "/package-list" );
2976 }
2977 else
2978 {
2979 // links can be relative paths or files
2980 linkUri = new File( getOutputDirectory(), link + "/package-list" ).toURI();
2981 }
2982 JavadocUtil.fetchURL( settings, linkUri.toURL() );
2983 addArgIfNotEmpty( arguments, "-link", JavadocUtil.quotedPathArgument( link ), true );
2984 }
2985 catch ( URISyntaxException e )
2986 {
2987 if ( getLog().isErrorEnabled() )
2988 {
2989 getLog().error( "Malformed link: " + link + "/package-list. Ignored it." );
2990 }
2991 }
2992 catch ( IOException e )
2993 {
2994 if ( getLog().isErrorEnabled() )
2995 {
2996 getLog().error( "Error fetching link: " + link + "/package-list. Ignored it." );
2997 }
2998 }
2999 }
3000 }
3001 }
3002
3003 /**
3004 * Returns an input stream for reading the specified resource from the
3005 * current class loader.
3006 *
3007 * @param resource the resource
3008 * @return InputStream An input stream for reading the resource, or <tt>null</tt>
3009 * if the resource could not be found
3010 */
3011 private InputStream getStream( String resource )
3012 {
3013 return getClass().getClassLoader().getResourceAsStream( resource );
3014 }
3015
3016 /**
3017 * Coppy all resources to the output directory
3018 *
3019 * @param javadocOutputDirectory not null
3020 * @throws MavenReportException if any
3021 * @see #copyDefaultStylesheet(File)
3022 * @see #copyJavadocResources(File)
3023 * @see #copyAdditionalJavadocResources(File)
3024 */
3025 private void copyAllResources( File javadocOutputDirectory )
3026 throws MavenReportException
3027 {
3028 // ----------------------------------------------------------------------
3029 // Copy default resources
3030 // ----------------------------------------------------------------------
3031
3032 try
3033 {
3034 copyDefaultStylesheet( javadocOutputDirectory );
3035 }
3036 catch ( IOException e )
3037 {
3038 throw new MavenReportException( "Unable to copy default stylesheet: " + e.getMessage(), e );
3039 }
3040
3041 // ----------------------------------------------------------------------
3042 // Copy javadoc resources
3043 // ----------------------------------------------------------------------
3044
3045 if ( docfilessubdirs )
3046 {
3047 /*
3048 * Workaround since -docfilessubdirs doesn't seem to be used correctly by the javadoc tool
3049 * (see other note about -sourcepath). Take care of the -excludedocfilessubdir option.
3050 */
3051 try
3052 {
3053 copyJavadocResources( javadocOutputDirectory );
3054 }
3055 catch ( IOException e )
3056 {
3057 throw new MavenReportException( "Unable to copy javadoc resources: " + e.getMessage(), e );
3058 }
3059 }
3060
3061 // ----------------------------------------------------------------------
3062 // Copy additional javadoc resources in artifacts
3063 // ----------------------------------------------------------------------
3064
3065 copyAdditionalJavadocResources( javadocOutputDirectory );
3066 }
3067
3068 /**
3069 * Method that copy the <code>DEFAULT_STYLESHEET_NAME</code> file from the current class
3070 * loader to the <code>outputDirectory</code>.
3071 *
3072 * @param anOutputDirectory the output directory
3073 * @throws java.io.IOException if any
3074 * @see #DEFAULT_CSS_NAME
3075 */
3076 private void copyDefaultStylesheet( File anOutputDirectory )
3077 throws IOException
3078 {
3079 if ( anOutputDirectory == null || !anOutputDirectory.exists() )
3080 {
3081 throw new IOException( "The outputDirectory " + anOutputDirectory + " doesn't exists." );
3082 }
3083
3084 InputStream is = getStream( RESOURCE_CSS_DIR + "/" + DEFAULT_CSS_NAME );
3085
3086 if ( is == null )
3087 {
3088 throw new IOException( "The resource " + DEFAULT_CSS_NAME + " doesn't exists." );
3089 }
3090
3091 File outputFile = new File( anOutputDirectory, DEFAULT_CSS_NAME );
3092
3093 if ( !outputFile.getParentFile().exists() )
3094 {
3095 outputFile.getParentFile().mkdirs();
3096 }
3097
3098 FileOutputStream w = new FileOutputStream( outputFile );
3099
3100 IOUtil.copy( is, w );
3101
3102 IOUtil.close( is );
3103
3104 IOUtil.close( w );
3105 }
3106
3107 /**
3108 * Method that copy all <code>doc-files</code> directories from <code>javadocDirectory</code> of
3109 * the current projet or of the projects in the reactor to the <code>outputDirectory</code>.
3110 *
3111 * @see <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.2.html#docfiles">Reference
3112 * Guide, Copies new "doc-files" directory for holding images and examples</a>
3113 * @see #docfilessubdirs
3114 *
3115 * @param anOutputDirectory the output directory
3116 * @throws java.io.IOException if any
3117 */
3118 private void copyJavadocResources( File anOutputDirectory )
3119 throws IOException
3120 {
3121 if ( anOutputDirectory == null || !anOutputDirectory.exists() )
3122 {
3123 throw new IOException( "The outputDirectory " + anOutputDirectory + " doesn't exists." );
3124 }
3125
3126 if ( getJavadocDirectory() != null )
3127 {
3128 JavadocUtil.copyJavadocResources( anOutputDirectory, getJavadocDirectory(), excludedocfilessubdir );
3129 }
3130
3131 if ( isAggregator() && project.isExecutionRoot() )
3132 {
3133 for ( Iterator i = reactorProjects.iterator(); i.hasNext(); )
3134 {
3135 MavenProject subProject = (MavenProject) i.next();
3136
3137 if ( subProject != project )
3138 {
3139 String javadocDirRelative =
3140 PathUtils.toRelative( project.getBasedir(), getJavadocDirectory().getAbsolutePath() );
3141 File javadocDir = new File( subProject.getBasedir(), javadocDirRelative );
3142 JavadocUtil.copyJavadocResources( anOutputDirectory, javadocDir, excludedocfilessubdir );
3143 }
3144 }
3145 }
3146 }
3147
3148 /**
3149 * Method that copy additional Javadoc resources from given artifacts.
3150 *
3151 * @see #resourcesArtifacts
3152 * @param anOutputDirectory the output directory
3153 * @throws MavenReportException if any
3154 */
3155 private void copyAdditionalJavadocResources( File anOutputDirectory )
3156 throws MavenReportException
3157 {
3158 if ( resourcesArtifacts != null && resourcesArtifacts.length > 0 )
3159 {
3160 UnArchiver unArchiver;
3161 try
3162 {
3163 unArchiver = archiverManager.getUnArchiver( "jar" );
3164 }
3165 catch ( NoSuchArchiverException e )
3166 {
3167 throw new MavenReportException( "Unable to extract resources artifact. "
3168 + "No archiver for 'jar' available.", e );
3169 }
3170
3171 for ( int i = 0; i < resourcesArtifacts.length; i++ )
3172 {
3173 ResourcesArtifact item = resourcesArtifacts[i];
3174
3175 Artifact artifact;
3176 try
3177 {
3178 artifact = createAndResolveArtifact( item );
3179 }
3180 catch ( ArtifactResolutionException e )
3181 {
3182 throw new MavenReportException( "Unable to resolve artifact:" + item, e );
3183 }
3184 catch ( ArtifactNotFoundException e )
3185 {
3186 throw new MavenReportException( "Unable to find artifact:" + item, e );
3187 }
3188 catch ( ProjectBuildingException e )
3189 {
3190 throw new MavenReportException( "Unable to build the Maven project for the artifact:" + item,
3191 e );
3192 }
3193
3194 unArchiver.setSourceFile( artifact.getFile() );
3195 unArchiver.setDestDirectory( anOutputDirectory );
3196
3197 getLog().info( "Extracting contents of resources artifact: " + artifact.getArtifactId() );
3198 try
3199 {
3200 unArchiver.extract();
3201 }
3202 catch ( ArchiverException e )
3203 {
3204 throw new MavenReportException( "Extraction of resources failed. Artifact that failed was: "
3205 + artifact.getArtifactId(), e );
3206 }
3207 }
3208 }
3209 }
3210
3211 /**
3212 * @param sourcePaths could be null
3213 * @param files not null
3214 * @return the list of package names for files in the sourcePaths
3215 */
3216 private List getPackageNames( List sourcePaths, List files )
3217 {
3218 return getPackageNamesOrFilesWithUnnamedPackages( sourcePaths, files, true );
3219 }
3220
3221 /**
3222 * @param sourcePaths could be null
3223 * @param files not null
3224 * @return a list files with unnamed package names for files in the sourecPaths
3225 */
3226 private List getFilesWithUnnamedPackages( List sourcePaths, List files )
3227 {
3228 return getPackageNamesOrFilesWithUnnamedPackages( sourcePaths, files, false );
3229 }
3230
3231 /**
3232 * @param sourcePaths not null, containing absolute and relative paths
3233 * @param files not null, containing list of quoted files
3234 * @param onlyPackageName boolean for only package name
3235 * @return a list of package names or files with unnamed package names, depending the value of the unnamed flag
3236 * @see #getFiles(List)
3237 * @see #getSourcePaths()
3238 */
3239 private List getPackageNamesOrFilesWithUnnamedPackages( List sourcePaths, List files, boolean onlyPackageName )
3240 {
3241 List returnList = new ArrayList();
3242
3243 if ( !StringUtils.isEmpty( sourcepath ) )
3244 {
3245 return returnList;
3246 }
3247
3248 for ( Iterator it = files.iterator(); it.hasNext(); )
3249 {
3250 String currentFile = (String) it.next();
3251 currentFile = currentFile.replace( '\\', '/' );
3252
3253 for ( Iterator it2 = sourcePaths.iterator(); it2.hasNext(); )
3254 {
3255 String currentSourcePath = (String) it2.next();
3256 currentSourcePath = currentSourcePath.replace( '\\', '/' );
3257
3258 if ( !currentSourcePath.endsWith( "/" ) )
3259 {
3260 currentSourcePath += "/";
3261 }
3262
3263 if ( currentFile.indexOf( currentSourcePath ) != -1 )
3264 {
3265 String packagename = currentFile.substring( currentSourcePath.length() + 1 );
3266 if ( onlyPackageName && packagename.lastIndexOf( "/" ) != -1 )
3267 {
3268 packagename = packagename.substring( 0, packagename.lastIndexOf( "/" ) );
3269 packagename = packagename.replace( '/', '.' );
3270
3271 if ( !returnList.contains( packagename ) )
3272 {
3273 returnList.add( packagename );
3274 }
3275 }
3276 if ( !onlyPackageName && packagename.lastIndexOf( "/" ) == -1 )
3277 {
3278 returnList.add( currentFile );
3279 }
3280 }
3281 }
3282 }
3283
3284 return returnList;
3285 }
3286
3287 /**
3288 * Generate an <code>options</code> file for all options and arguments and add the <code>@options</code> in the
3289 * command line.
3290 *
3291 * @see <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#argumentfiles">
3292 * Reference Guide, Command line argument files</a>
3293 *
3294 * @param cmd not null
3295 * @param arguments not null
3296 * @param javadocOutputDirectory not null
3297 * @throws MavenReportException if any
3298 * @see #OPTIONS_FILE_NAME
3299 */
3300 private void addCommandLineOptions( Commandline cmd, List arguments, File javadocOutputDirectory )
3301 throws MavenReportException
3302 {
3303 File optionsFile = new File( javadocOutputDirectory, OPTIONS_FILE_NAME );
3304
3305 StringBuffer options = new StringBuffer();
3306 options.append( StringUtils.join( arguments.toArray( new String[0] ), SystemUtils.LINE_SEPARATOR ) );
3307
3308 try
3309 {
3310 FileUtils.fileWrite( optionsFile.getAbsolutePath(), options.toString() );
3311 }
3312 catch ( IOException e )
3313 {
3314 throw new MavenReportException( "Unable to write '" + optionsFile.getName()
3315 + "' temporary file for command execution", e );
3316 }
3317
3318 cmd.createArg().setValue( "@" + OPTIONS_FILE_NAME );
3319
3320 if ( !debug )
3321 {
3322 optionsFile.deleteOnExit();
3323 }
3324 }
3325
3326 /**
3327 * Generate a file called <code>argfile</code> (or <code>files</code>, depending the JDK) to hold files and add
3328 * the <code>@argfile</code> (or <code>@file</code>, depending the JDK) in the command line.
3329 *
3330 * @see <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#argumentfiles">
3331 * Reference Guide, Command line argument files
3332 * </a>
3333 * @see <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/javadoc/whatsnew-1.4.html#runningjavadoc">
3334 * What s New in Javadoc 1.4
3335 * </a>
3336 *
3337 * @param cmd not null
3338 * @param javadocOutputDirectory not null
3339 * @param files not null
3340 * @throws MavenReportException if any
3341 * @see #isJavaDocVersionAtLeast(float)
3342 * @see #ARGFILE_FILE_NAME
3343 * @see #FILES_FILE_NAME
3344 */
3345 private void addCommandLineArgFile( Commandline cmd, File javadocOutputDirectory, List files )
3346 throws MavenReportException
3347 {
3348 File argfileFile;
3349 if ( isJavaDocVersionAtLeast( SINCE_JAVADOC_1_4 ) )
3350 {
3351 argfileFile = new File( javadocOutputDirectory, ARGFILE_FILE_NAME );
3352 }
3353 else
3354 {
3355 argfileFile = new File( javadocOutputDirectory, FILES_FILE_NAME );
3356 }
3357
3358 try
3359 {
3360 FileUtils.fileWrite( argfileFile.getAbsolutePath(), StringUtils.join( files.iterator(),
3361 SystemUtils.LINE_SEPARATOR ) );
3362 }
3363 catch ( IOException e )
3364 {
3365 throw new MavenReportException( "Unable to write '" + argfileFile.getName()
3366 + "' temporary file for command execution", e );
3367 }
3368
3369 if ( isJavaDocVersionAtLeast( SINCE_JAVADOC_1_4 ) )
3370 {
3371 cmd.createArg().setValue( "@" + ARGFILE_FILE_NAME );
3372 }
3373 else
3374 {
3375 cmd.createArg().setValue( "@" + FILES_FILE_NAME );
3376 }
3377
3378 if ( !debug )
3379 {
3380 argfileFile.deleteOnExit();
3381 }
3382 }
3383
3384 /**
3385 * Generate a file called <code>packages</code> to hold all package names and add the <code>@packages</code> in
3386 * the command line.
3387 *
3388 * @see <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#argumentfiles">
3389 * Reference Guide, Command line argument files</a>
3390 *
3391 * @param cmd not null
3392 * @param javadocOutputDirectory not null
3393 * @param packageNames not null
3394 * @throws MavenReportException if any
3395 * @see #PACKAGES_FILE_NAME
3396 */
3397 private void addCommandLinePackages( Commandline cmd, File javadocOutputDirectory, List packageNames )
3398 throws MavenReportException
3399 {
3400 File packagesFile = new File( javadocOutputDirectory, PACKAGES_FILE_NAME );
3401
3402 try
3403 {
3404 FileUtils.fileWrite( packagesFile.getAbsolutePath(),
3405 StringUtils.join( packageNames.toArray( new String[0] ),
3406 SystemUtils.LINE_SEPARATOR ) );
3407 }
3408 catch ( IOException e )
3409 {
3410 throw new MavenReportException( "Unable to write '" + packagesFile.getName()
3411 + "' temporary file for command execution", e );
3412 }
3413
3414 cmd.createArg().setValue( "@" + PACKAGES_FILE_NAME );
3415
3416 if ( !debug )
3417 {
3418 packagesFile.deleteOnExit();
3419 }
3420 }
3421
3422 /**
3423 * Checks for the validity of the Javadoc options used by the user.
3424 *
3425 * @throws MavenReportException if error
3426 */
3427 private void validateJavadocOptions()
3428 throws MavenReportException
3429 {
3430 // encoding
3431 if ( StringUtils.isNotEmpty( getEncoding() ) && !JavadocUtil.validateEncoding( getEncoding() ) )
3432 {
3433 throw new MavenReportException( "Encoding not supported: " + getEncoding() );
3434 }
3435 }
3436
3437 /**
3438 * Checks for the validity of the Standard Doclet options.
3439 * <br/>
3440 * For example, throw an exception if <nohelp/> and <helpfile/> options are used together.
3441 *
3442 * @throws MavenReportException if error or conflict found
3443 */
3444 private void validateStandardDocletOptions()
3445 throws MavenReportException
3446 {
3447 // docencoding
3448 if ( StringUtils.isNotEmpty( getDocencoding() ) && !JavadocUtil.validateEncoding( getDocencoding() ) )
3449 {
3450 throw new MavenReportException( "Encoding not supported: " + getDocencoding() );
3451 }
3452
3453 // helpfile
3454 if ( StringUtils.isNotEmpty( helpfile ) && nohelp )
3455 {
3456 throw new MavenReportException( "Option <nohelp/> conflicts with <helpfile/>" );
3457 }
3458 if ( ( StringUtils.isNotEmpty( helpfile ) ) && ( !new File( helpfile ).exists() ) )
3459 {
3460 throw new MavenReportException( "File not found: " + helpfile );
3461 }
3462
3463 // overview
3464 if ( ( getOverview() != null ) && nooverview )
3465 {
3466 throw new MavenReportException( "Option <nooverview/> conflicts with <overview/>" );
3467 }
3468
3469 // index
3470 if ( splitindex && noindex )
3471 {
3472 throw new MavenReportException( "Option <noindex/> conflicts with <splitindex/>" );
3473 }
3474 }
3475
3476 /**
3477 * This method is checking to see if the artifacts that can't be resolved are all
3478 * part of this reactor. This is done to prevent a chicken or egg scenario with
3479 * fresh projects. See MJAVADOC-116 for more info.
3480 *
3481 * @param dependencyArtifacts the sibling projects in the reactor
3482 * @param missing the artifacts that can't be found
3483 * @return true if ALL missing artifacts are found in the reactor.
3484 * @see DefaultPluginManager#checkRequiredMavenVersion( plugin, localRepository, remoteRepositories )
3485 */
3486 private boolean checkMissingArtifactsInReactor( Collection dependencyArtifacts, Collection missing )
3487 {
3488 Set foundInReactor = new HashSet();
3489 Iterator iter = missing.iterator();
3490 while ( iter.hasNext() )
3491 {
3492 Artifact mArtifact = (Artifact) iter.next();
3493 Iterator pIter = reactorProjects.iterator();
3494 while ( pIter.hasNext() )
3495 {
3496 MavenProject p = (MavenProject) pIter.next();
3497 if ( p.getArtifactId().equals( mArtifact.getArtifactId() )
3498 && p.getGroupId().equals( mArtifact.getGroupId() )
3499 && p.getVersion().equals( mArtifact.getVersion() ) )
3500 {
3501 getLog().warn(
3502 "The dependency: ["
3503 + p.getId()
3504 + "] can't be resolved but has been found in the reactor (probably snapshots).\n"
3505 + "This dependency has been excluded from the Javadoc classpath. "
3506 + "You should rerun javadoc after executing mvn install." );
3507
3508 // found it, move on.
3509 foundInReactor.add( p );
3510 break;
3511 }
3512 }
3513 }
3514
3515 // if all of them have been found, we can continue.
3516 return foundInReactor.size() == missing.size();
3517 }
3518
3519 /**
3520 * Add Standard Javadoc Options.
3521 * <br/>
3522 * The <a href="package-summary.html#Standard_Javadoc_Options">package documentation</a> details the
3523 * Standard Javadoc Options wrapped by this Plugin.
3524 *
3525 * @param arguments not null
3526 * @param sourcePaths not null
3527 * @throws MavenReportException if any
3528 * @see <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#javadocoptions">
3529 * http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#javadocoptions</a>
3530 */
3531 private void addJavadocOptions( List arguments, List sourcePaths )
3532 throws MavenReportException
3533 {
3534 validateJavadocOptions();
3535
3536 // see com.sun.tools.javadoc.Start#parseAndExecute(String argv[])
3537 addArgIfNotEmpty( arguments, "-locale", JavadocUtil.quotedArgument( this.locale ) );
3538
3539 // all options in alphabetical order
3540
3541 if ( old && isJavaDocVersionAtLeast( SINCE_JAVADOC_1_4 ) )
3542 {
3543 if ( getLog().isWarnEnabled() )
3544 {
3545 getLog().warn( "Javadoc 1.4+ doesn't support the -1.1 switch anymore. Ignore this option." );
3546 }
3547 }
3548 else
3549 {
3550 addArgIf( arguments, old, "-1.1" );
3551 }
3552
3553 addArgIfNotEmpty( arguments, "-bootclasspath", JavadocUtil.quotedPathArgument( getBootclassPath() ) );
3554
3555 if ( isJavaDocVersionAtLeast( SINCE_JAVADOC_1_5 ) )
3556 {
3557 addArgIf( arguments, breakiterator, "-breakiterator", SINCE_JAVADOC_1_5 );
3558 }
3559
3560 addArgIfNotEmpty( arguments, "-classpath", JavadocUtil.quotedPathArgument( getClasspath() ) );
3561
3562 if ( StringUtils.isNotEmpty( doclet ) )
3563 {
3564 addArgIfNotEmpty( arguments, "-doclet", JavadocUtil.quotedArgument( doclet ) );
3565 addArgIfNotEmpty( arguments, "-docletpath", JavadocUtil.quotedPathArgument( getDocletPath() ) );
3566 }
3567
3568 if ( StringUtils.isEmpty( encoding ) )
3569 {
3570 getLog().warn(
3571 "Source files encoding has not been set, using platform encoding "
3572 + ReaderFactory.FILE_ENCODING + ", i.e. build is platform dependent!" );
3573 }
3574 addArgIfNotEmpty( arguments, "-encoding", JavadocUtil.quotedArgument( getEncoding() ) );
3575
3576 addArgIfNotEmpty( arguments, "-exclude", getExcludedPackages( sourcePaths ), SINCE_JAVADOC_1_4 );
3577
3578 addArgIfNotEmpty( arguments, "-extdirs", JavadocUtil.quotedPathArgument( extdirs ) );
3579
3580 if ( ( getOverview() != null ) && ( getOverview().exists() ) )
3581 {
3582 addArgIfNotEmpty( arguments, "-overview",
3583 JavadocUtil.quotedPathArgument( getOverview().getAbsolutePath() ) );
3584 }
3585
3586 arguments.add( getAccessLevel() );
3587
3588 if ( isJavaDocVersionAtLeast( SINCE_JAVADOC_1_5 ) )
3589 {
3590 addArgIf( arguments, quiet, "-quiet", SINCE_JAVADOC_1_5 );
3591 }
3592
3593 addArgIfNotEmpty( arguments, "-source", JavadocUtil.quotedArgument( source ), SINCE_JAVADOC_1_4 );
3594
3595 if ( ( StringUtils.isEmpty( sourcepath ) ) && ( StringUtils.isNotEmpty( subpackages ) ) )
3596 {
3597 sourcepath = StringUtils.join( sourcePaths.iterator(), File.pathSeparator );
3598 }
3599 addArgIfNotEmpty( arguments, "-sourcepath", JavadocUtil.quotedPathArgument( getSourcePath( sourcePaths ) ) );
3600
3601 if ( StringUtils.isNotEmpty( sourcepath ) && isJavaDocVersionAtLeast( SINCE_JAVADOC_1_5 ) )
3602 {
3603 addArgIfNotEmpty( arguments, "-subpackages", subpackages, SINCE_JAVADOC_1_5 );
3604 }
3605
3606 addArgIf( arguments, verbose, "-verbose" );
3607
3608 addArgIfNotEmpty( arguments, null, additionalparam );
3609 }
3610
3611 /**
3612 * Add Standard Doclet Options.
3613 * <br/>
3614 * The <a href="package-summary.html#Standard_Doclet_Options">package documentation</a> details the
3615 * Standard Doclet Options wrapped by this Plugin.
3616 *
3617 * @param javadocOutputDirectory not null
3618 * @param arguments not null
3619 * @throws MavenReportException if any
3620 * @see <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#standard">
3621 * http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#standard</a>
3622 */
3623 private void addStandardDocletOptions( File javadocOutputDirectory, List arguments )
3624 throws MavenReportException
3625 {
3626 validateStandardDocletOptions();
3627
3628 // all options in alphabetical order
3629
3630 addArgIf( arguments, author, "-author" );
3631
3632 addArgIfNotEmpty( arguments, "-bottom", JavadocUtil.quotedArgument( getBottomText() ), false, false );
3633
3634 if ( !isJavaDocVersionAtLeast( SINCE_JAVADOC_1_5 ) )
3635 {
3636 addArgIf( arguments, breakiterator, "-breakiterator", SINCE_JAVADOC_1_4 );
3637 }
3638
3639 addArgIfNotEmpty( arguments, "-charset", JavadocUtil.quotedArgument( getCharset() ) );
3640
3641 addArgIfNotEmpty( arguments, "-d", JavadocUtil.quotedPathArgument( javadocOutputDirectory.toString() ) );
3642
3643 addArgIfNotEmpty( arguments, "-docencoding", JavadocUtil.quotedArgument( getDocencoding() ) );
3644
3645 addArgIf( arguments, docfilessubdirs, "-docfilessubdirs", SINCE_JAVADOC_1_4 );
3646
3647 addArgIfNotEmpty( arguments, "-doctitle", JavadocUtil.quotedArgument( getDoctitle() ), false, false );
3648
3649 if ( docfilessubdirs )
3650 {
3651 addArgIfNotEmpty( arguments, "-excludedocfilessubdir",
3652 JavadocUtil.quotedPathArgument( excludedocfilessubdir ), SINCE_JAVADOC_1_4 );
3653 }
3654
3655 addArgIfNotEmpty( arguments, "-footer", JavadocUtil.quotedArgument( footer ), false, false );
3656
3657 addGroups( arguments );
3658
3659 addArgIfNotEmpty( arguments, "-header", JavadocUtil.quotedArgument( header ), false, false );
3660
3661 addArgIfNotEmpty( arguments, "-helpfile", JavadocUtil.quotedPathArgument( helpfile ) );
3662
3663 addArgIf( arguments, keywords, "-keywords", SINCE_JAVADOC_1_4_2 );
3664
3665 if ( !isOffline )
3666 {
3667 addLinkArguments( arguments );
3668 }
3669
3670 addLinkofflineArguments( arguments );
3671
3672 addArgIf( arguments, linksource, "-linksource", SINCE_JAVADOC_1_4 );
3673
3674 if ( sourcetab > 0 )
3675 {
3676 if ( fJavadocVersion == SINCE_JAVADOC_1_4_2 )
3677 {
3678 addArgIfNotEmpty( arguments, "-linksourcetab", String.valueOf( sourcetab ) );
3679 }
3680 addArgIfNotEmpty( arguments, "-sourcetab", String.valueOf( sourcetab ), SINCE_JAVADOC_1_5 );
3681 }
3682
3683 addArgIf( arguments, nocomment, "-nocomment", SINCE_JAVADOC_1_4 );
3684
3685 addArgIf( arguments, nodeprecated, "-nodeprecated" );
3686
3687 addArgIf( arguments, nodeprecatedlist, "-nodeprecatedlist" );
3688
3689 addArgIf( arguments, nohelp, "-nohelp" );
3690
3691 addArgIf( arguments, noindex, "-noindex" );
3692
3693 addArgIf( arguments, nonavbar, "-nonavbar" );
3694
3695 addArgIf( arguments, nooverview, "-nooverview" );
3696
3697 addArgIfNotEmpty( arguments, "-noqualifier", JavadocUtil.quotedArgument( noqualifier ), SINCE_JAVADOC_1_4 );
3698
3699 addArgIf( arguments, nosince, "-nosince" );
3700
3701 addArgIf( arguments, notimestamp, "-notimestamp", SINCE_JAVADOC_1_5 );
3702
3703 addArgIf( arguments, notree, "-notree" );
3704
3705 addArgIfNotEmpty( arguments, "-packagesheader", JavadocUtil.quotedArgument( packagesheader ),
3706 SINCE_JAVADOC_1_4_2 );
3707
3708 if ( !isJavaDocVersionAtLeast( SINCE_JAVADOC_1_5 ) ) // Sun bug: 4714350
3709 {
3710 addArgIf( arguments, quiet, "-quiet", SINCE_JAVADOC_1_4 );
3711 }
3712
3713 addArgIf( arguments, serialwarn, "-serialwarn" );
3714
3715 addArgIf( arguments, splitindex, "-splitindex" );
3716
3717 addArgIfNotEmpty( arguments, "-stylesheetfile",
3718 JavadocUtil.quotedPathArgument( getStylesheetFile( javadocOutputDirectory ) ) );
3719
3720 if ( StringUtils.isNotEmpty( sourcepath ) && !isJavaDocVersionAtLeast( SINCE_JAVADOC_1_5 ) )
3721 {
3722 addArgIfNotEmpty( arguments, "-subpackages", subpackages, SINCE_JAVADOC_1_4 );
3723 }
3724
3725 addArgIfNotEmpty( arguments, "-taglet", JavadocUtil.quotedArgument( taglet ), SINCE_JAVADOC_1_4 );
3726 addTaglets( arguments );
3727 addTagletsFromTagletArtifacts( arguments );
3728 addArgIfNotEmpty( arguments, "-tagletpath", JavadocUtil.quotedPathArgument( getTagletPath() ),
3729 SINCE_JAVADOC_1_4 );
3730
3731 addTags( arguments );
3732
3733 addArgIfNotEmpty( arguments, "-top", JavadocUtil.quotedArgument( top ), false, false, SINCE_JAVADOC_1_6 );
3734
3735 addArgIf( arguments, use, "-use" );
3736
3737 addArgIf( arguments, version, "-version" );
3738
3739 addArgIfNotEmpty( arguments, "-windowtitle", JavadocUtil.quotedArgument( getWindowtitle() ), false, false );
3740 }
3741
3742 /**
3743 * Add <code>groups</code> parameter to arguments.
3744 *
3745 * @param arguments not null
3746 */
3747 private void addGroups( List arguments )
3748 {
3749 if ( groups == null )
3750 {
3751 return;
3752
3753 }
3754
3755 for ( int i = 0; i < groups.length; i++ )
3756 {
3757 if ( groups[i] == null || StringUtils.isEmpty( groups[i].getTitle() )
3758 || StringUtils.isEmpty( groups[i].getPackages() ) )
3759 {
3760 if ( getLog().isWarnEnabled() )
3761 {
3762 getLog().warn( "A group option is empty. Ignore this option." );
3763 }
3764 }
3765 else
3766 {
3767 String groupTitle = StringUtils.replace( groups[i].getTitle(), ",", "," );
3768 addArgIfNotEmpty( arguments, "-group", JavadocUtil.quotedArgument( groupTitle ) + " "
3769 + JavadocUtil.quotedArgument( groups[i].getPackages() ), true );
3770 }
3771 }
3772 }
3773
3774 /**
3775 * Add <code>tags</code> parameter to arguments.
3776 *
3777 * @param arguments not null
3778 */
3779 private void addTags( List arguments )
3780 {
3781 if ( tags == null )
3782 {
3783 return;
3784 }
3785
3786 for ( int i = 0; i < tags.length; i++ )
3787 {
3788 if ( StringUtils.isEmpty( tags[i].getName() ) )
3789 {
3790 if ( getLog().isWarnEnabled() )
3791 {
3792 getLog().warn( "A tag name is empty. Ignore this option." );
3793 }
3794 }
3795 else
3796 {
3797 String value = "\"" + tags[i].getName();
3798 if ( StringUtils.isNotEmpty( tags[i].getPlacement() ) )
3799 {
3800 value += ":" + tags[i].getPlacement();
3801 if ( StringUtils.isNotEmpty( tags[i].getHead() ) )
3802 {
3803 value += ":" + tags[i].getHead();
3804 }
3805 }
3806 value += "\"";
3807 addArgIfNotEmpty( arguments, "-tag", value, SINCE_JAVADOC_1_4 );
3808 }
3809 }
3810 }
3811
3812 /**
3813 * Add <code>taglets</code> parameter to arguments.
3814 *
3815 * @param arguments not null
3816 */
3817 private void addTaglets( List arguments )
3818 {
3819 if ( taglets == null )
3820 {
3821 return;
3822 }
3823
3824 for ( int i = 0; i < taglets.length; i++ )
3825 {
3826 if ( ( taglets[i] == null ) || ( StringUtils.isEmpty( taglets[i].getTagletClass() ) ) )
3827 {
3828 if ( getLog().isWarnEnabled() )
3829 {
3830 getLog().warn( "A taglet option is empty. Ignore this option." );
3831 }
3832 }
3833 else
3834 {
3835 addArgIfNotEmpty( arguments, "-taglet", JavadocUtil.quotedArgument( taglets[i].getTagletClass() ),
3836 SINCE_JAVADOC_1_4 );
3837 }
3838 }
3839 }
3840
3841 /**
3842 * Auto-detect taglets class name from <code>tagletArtifacts</code> and add them to arguments.
3843 *
3844 * @param arguments not null
3845 * @throws MavenReportException if any
3846 * @see JavadocUtil#getTagletClassNames(File)
3847 */
3848 private void addTagletsFromTagletArtifacts( List arguments )
3849 throws MavenReportException
3850 {
3851 if ( tagletArtifacts == null )
3852 {
3853 return;
3854 }
3855
3856 List tagletsPath = new ArrayList();
3857 for ( int i = 0; i < tagletArtifacts.length; i++ )
3858 {
3859 TagletArtifact aTagletArtifact = tagletArtifacts[i];
3860
3861 if ( ( StringUtils.isNotEmpty( aTagletArtifact.getGroupId() ) )
3862 && ( StringUtils.isNotEmpty( aTagletArtifact.getArtifactId() ) )
3863 && ( StringUtils.isNotEmpty( aTagletArtifact.getVersion() ) ) )
3864 {
3865 Artifact artifact;
3866 try
3867 {
3868 artifact = createAndResolveArtifact( aTagletArtifact );
3869 }
3870 catch ( ArtifactResolutionException e )
3871 {
3872 throw new MavenReportException( "Unable to resolve artifact:" + aTagletArtifact, e );
3873 }
3874 catch ( ArtifactNotFoundException e )
3875 {
3876 throw new MavenReportException( "Unable to find artifact:" + aTagletArtifact, e );
3877 }
3878 catch ( ProjectBuildingException e )
3879 {
3880 throw new MavenReportException( "Unable to build the Maven project for the artifact:"
3881 + aTagletArtifact, e );
3882 }
3883
3884 tagletsPath.add( artifact.getFile().getAbsolutePath() );
3885 }
3886 }
3887
3888 tagletsPath = JavadocUtil.pruneFiles( tagletsPath );
3889
3890 for ( Iterator it = tagletsPath.iterator(); it.hasNext(); )
3891 {
3892 String tagletJar = (String) it.next();
3893
3894 if ( !tagletJar.toLowerCase( Locale.ENGLISH ).endsWith( ".jar" ) )
3895 {
3896 continue;
3897 }
3898
3899 List tagletClasses;
3900 try
3901 {
3902 tagletClasses = JavadocUtil.getTagletClassNames( new File( tagletJar ) );
3903 }
3904 catch ( IOException e )
3905 {
3906 if ( getLog().isWarnEnabled() )
3907 {
3908 getLog().warn(
3909 "Unable to auto-detect Taglet class names from '" + tagletJar
3910 + "'. Try to specify them with <taglets/>." );
3911 }
3912 if ( getLog().isDebugEnabled() )
3913 {
3914 getLog().debug( "IOException: " + e.getMessage(), e );
3915 }
3916 continue;
3917 }
3918 catch ( ClassNotFoundException e )
3919 {
3920 if ( getLog().isWarnEnabled() )
3921 {
3922 getLog().warn(
3923 "Unable to auto-detect Taglet class names from '" + tagletJar
3924 + "'. Try to specify them with <taglets/>." );
3925 }
3926 if ( getLog().isDebugEnabled() )
3927 {
3928 getLog().debug( "ClassNotFoundException: " + e.getMessage(), e );
3929 }
3930 continue;
3931 }
3932 catch ( NoClassDefFoundError e )
3933 {
3934 if ( getLog().isWarnEnabled() )
3935 {
3936 getLog().warn(
3937 "Unable to auto-detect Taglet class names from '" + tagletJar
3938 + "'. Try to specify them with <taglets/>." );
3939 }
3940 if ( getLog().isDebugEnabled() )
3941 {
3942 getLog().debug( "NoClassDefFoundError: " + e.getMessage(), e );
3943 }
3944 continue;
3945 }
3946
3947 if ( tagletClasses != null && !tagletClasses.isEmpty() )
3948 {
3949 for ( Iterator it2 = tagletClasses.iterator(); it2.hasNext(); )
3950 {
3951 String tagletClass = (String) it2.next();
3952
3953 addArgIfNotEmpty( arguments, "-taglet", JavadocUtil.quotedArgument( tagletClass ),
3954 SINCE_JAVADOC_1_4 );
3955 }
3956 }
3957 }
3958 }
3959
3960 /**
3961 * Execute the Javadoc command line
3962 *
3963 * @param cmd not null
3964 * @param javadocOutputDirectory not null
3965 * @throws MavenReportException if any errors occur
3966 */
3967 private void executeJavadocCommandLine( Commandline cmd, File javadocOutputDirectory )
3968 throws MavenReportException
3969 {
3970 if ( getLog().isDebugEnabled() )
3971 {
3972 // no quoted arguments
3973 getLog().debug( CommandLineUtils.toString( cmd.getCommandline() ).replaceAll( "'", "" ) );
3974 }
3975
3976 if ( debug )
3977 {
3978 File commandLineFile =
3979 new File( javadocOutputDirectory, DEBUG_JAVADOC_SCRIPT_NAME );
3980
3981 try
3982 {
3983 FileUtils.fileWrite( commandLineFile.getAbsolutePath(),
3984 CommandLineUtils.toString( cmd.getCommandline() ).replaceAll( "'", "" ) );
3985
3986 if ( !SystemUtils.IS_OS_WINDOWS )
3987 {
3988 Runtime.getRuntime().exec( new String[] { "chmod", "a+x", commandLineFile.getAbsolutePath() } );
3989 }
3990 }
3991 catch ( IOException e )
3992 {
3993 if ( getLog().isWarnEnabled() )
3994 {
3995 getLog().warn( "Unable to write '" + commandLineFile.getName() + "' debug script file", e );
3996 }
3997 }
3998 }
3999
4000 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
4001 try
4002 {
4003 int exitCode = CommandLineUtils.executeCommandLine( cmd, new DefaultConsumer(), err );
4004
4005 if ( exitCode != 0 )
4006 {
4007 String cmdLine = CommandLineUtils.toString( cmd.getCommandline() ).replaceAll( "'", "" );
4008 cmdLine = JavadocUtil.hideProxyPassword( cmdLine, settings );
4009
4010 StringBuffer msg = new StringBuffer( "Exit code: " + exitCode + " - " + err.getOutput() );
4011 msg.append( '\n' );
4012 msg.append( "Command line was:" + cmdLine );
4013 throw new MavenReportException( msg.toString() );
4014 }
4015 }
4016 catch ( CommandLineException e )
4017 {
4018 throw new MavenReportException( "Unable to execute javadoc command: " + e.getMessage(), e );
4019 }
4020
4021 // ----------------------------------------------------------------------
4022 // Handle Javadoc warnings
4023 // ----------------------------------------------------------------------
4024
4025 if ( StringUtils.isNotEmpty( err.getOutput() ) && getLog().isWarnEnabled() )
4026 {
4027 getLog().warn( "Javadoc Warnings" );
4028
4029 StringTokenizer token = new StringTokenizer( err.getOutput(), "\n" );
4030 while ( token.hasMoreTokens() )
4031 {
4032 String current = token.nextToken().trim();
4033
4034 getLog().warn( current );
4035 }
4036 }
4037 }
4038 }