source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/Javadoc.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 69.5 KB
Line 
1/*
2 * Copyright 2000-2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17package org.apache.tools.ant.taskdefs;
18
19import java.io.File;
20import java.io.FileWriter;
21import java.io.FilenameFilter;
22import java.io.IOException;
23import java.io.PrintWriter;
24import java.io.BufferedReader;
25import java.io.FileReader;
26import java.net.MalformedURLException;
27import java.net.URL;
28import java.util.Enumeration;
29import java.util.Locale;
30import java.util.StringTokenizer;
31import java.util.Vector;
32import org.apache.tools.ant.BuildException;
33import org.apache.tools.ant.DirectoryScanner;
34import org.apache.tools.ant.Project;
35import org.apache.tools.ant.ProjectComponent;
36import org.apache.tools.ant.Task;
37import org.apache.tools.ant.types.Commandline;
38import org.apache.tools.ant.types.DirSet;
39import org.apache.tools.ant.types.EnumeratedAttribute;
40import org.apache.tools.ant.types.FileSet;
41import org.apache.tools.ant.types.Path;
42import org.apache.tools.ant.types.PatternSet;
43import org.apache.tools.ant.types.Reference;
44import org.apache.tools.ant.util.FileUtils;
45import org.apache.tools.ant.util.JavaEnvUtils;
46
47/**
48 * Generates Javadoc documentation for a collection
49 * of source code.
50 *
51 * <P>Current known limitations are:
52 *
53 * <P><UL>
54 * <LI>patterns must be of the form "xxx.*", every other pattern doesn't
55 * work.
56 * <LI>there is no control on arguments sanity since they are left
57 * to the javadoc implementation.
58 * </UL>
59 *
60 * <P>If no <CODE>doclet</CODE> is set, then the <CODE>version</CODE> and
61 * <CODE>author</CODE> are by default <CODE>"yes"</CODE>.
62 *
63 * <P>Note: This task is run on another VM because the Javadoc code calls
64 * <CODE>System.exit()</CODE> which would break Ant functionality.
65 *
66 *
67 * @since Ant 1.1
68 *
69 * @ant.task category="java"
70 */
71public class Javadoc extends Task {
72 /**
73 * Inner class used to manage doclet parameters.
74 */
75 public class DocletParam {
76 /** The parameter name */
77 private String name;
78
79 /** The parameter value */
80 private String value;
81
82 /**
83 * Set the name of the parameter.
84 *
85 * @param name the name of the doclet parameter
86 */
87 public void setName(String name) {
88 this.name = name;
89 }
90
91 /**
92 * Get the parameter name.
93 *
94 * @return the parameter's name.
95 */
96 public String getName() {
97 return name;
98 }
99
100 /**
101 * Set the parameter value.
102 *
103 * Note that only string values are supported. No resolution of file
104 * paths is performed.
105 *
106 * @param value the parameter value.
107 */
108 public void setValue(String value) {
109 this.value = value;
110 }
111
112 /**
113 * Get the parameter value.
114 *
115 * @return the parameter value.
116 */
117 public String getValue() {
118 return value;
119 }
120 }
121
122 /**
123 * A project aware class used for Javadoc extensions which take a name
124 * and a path such as doclet and taglet arguments.
125 *
126 */
127 public static class ExtensionInfo extends ProjectComponent {
128 /** The name of the extension */
129 private String name;
130
131 /** The optional path to use to load the extension */
132 private Path path;
133
134 /**
135 * Set the name of the extension
136 *
137 * @param name the extension's name.
138 */
139 public void setName(String name) {
140 this.name = name;
141 }
142
143 /**
144 * Get the name of the extension.
145 *
146 * @return the extension's name.
147 */
148 public String getName() {
149 return name;
150 }
151
152 /**
153 * Set the path to use when loading the component.
154 *
155 * @param path a Path instance containing the classpath to use.
156 */
157 public void setPath(Path path) {
158 if (this.path == null) {
159 this.path = path;
160 } else {
161 this.path.append(path);
162 }
163 }
164
165 /**
166 * Get the extension's path.
167 *
168 * @return the path to be used to load the extension.
169 * May be <code>null</code>
170 */
171 public Path getPath() {
172 return path;
173 }
174
175 /**
176 * Create an empty nested path to be configured by Ant with the
177 * classpath for the extension.
178 *
179 * @return a new Path instance to be configured.
180 */
181 public Path createPath() {
182 if (path == null) {
183 path = new Path(getProject());
184 }
185 return path.createPath();
186 }
187
188 /**
189 * Adds a reference to a CLASSPATH defined elsewhere.
190 *
191 * @param r the reference containing the path.
192 */
193 public void setPathRef(Reference r) {
194 createPath().setRefid(r);
195 }
196 }
197
198 /**
199 * This class stores info about doclets.
200 *
201 */
202 public class DocletInfo extends ExtensionInfo {
203
204 /** Collection of doclet parameters. */
205 private Vector params = new Vector();
206
207 /**
208 * Create a doclet parameter to be configured by Ant.
209 *
210 * @return a new DocletParam instance to be configured.
211 */
212 public DocletParam createParam() {
213 DocletParam param = new DocletParam();
214 params.addElement(param);
215
216 return param;
217 }
218
219 /**
220 * Get the doclet's parameters.
221 *
222 * @return an Enumeration of DocletParam instances.
223 */
224 public Enumeration getParams() {
225 return params.elements();
226 }
227 }
228
229 /**
230 * Used to track info about the packages to be javadoc'd
231 */
232 public static class PackageName {
233 /** The package name */
234 private String name;
235
236 /**
237 * Set the name of the package
238 *
239 * @param name the package name.
240 */
241 public void setName(String name) {
242 this.name = name.trim();
243 }
244
245 /**
246 * Get the package name.
247 *
248 * @return the package's name.
249 */
250 public String getName() {
251 return name;
252 }
253
254 /**
255 * @see java.lang.Object#toString
256 */
257 public String toString() {
258 return getName();
259 }
260 }
261
262 /**
263 * This class is used to manage the source files to be processed.
264 */
265 public static class SourceFile {
266 /** The source file */
267 private File file;
268
269 /**
270 * Default constructor
271 */
272 public SourceFile() {
273 }
274
275 /**
276 * Constructor specifying the source file directly
277 *
278 * @param file the source file
279 */
280 public SourceFile(File file) {
281 this.file = file;
282 }
283
284 /**
285 * Set the source file.
286 *
287 * @param file the source file.
288 */
289 public void setFile(File file) {
290 this.file = file;
291 }
292
293 /**
294 * Get the source file.
295 *
296 * @return the source file.
297 */
298 public File getFile() {
299 return file;
300 }
301 }
302
303 /**
304 * An HTML element in the javadoc.
305 *
306 * This class is used for those javadoc elements which contain HTML such as
307 * footers, headers, etc.
308 */
309 public static class Html {
310 /** The text for the element */
311 private StringBuffer text = new StringBuffer();
312
313 /**
314 * Add text to the element.
315 *
316 * @param t the text to be added.
317 */
318 public void addText(String t) {
319 text.append(t);
320 }
321
322 /**
323 * Get the current text for the element.
324 *
325 * @return the current text.
326 */
327 public String getText() {
328 return text.substring(0);
329 }
330 }
331
332 /**
333 * EnumeratedAttribute implementation supporting the javadoc scoping
334 * values.
335 */
336 public static class AccessType extends EnumeratedAttribute {
337 /**
338 * @see EnumeratedAttribute#getValues().
339 */
340 public String[] getValues() {
341 // Protected first so if any GUI tool offers a default
342 // based on enum #0, it will be right.
343 return new String[] {"protected", "public", "package", "private"};
344 }
345 }
346
347 /** The command line built to execute Javadoc. */
348 private Commandline cmd = new Commandline();
349
350 /**
351 * Utility method to add an argument to the command line conditionally
352 * based on the given flag.
353 *
354 * @param b the flag which controls if the argument is added.
355 * @param arg the argument value.
356 */
357 private void addArgIf(boolean b, String arg) {
358 if (b) {
359 cmd.createArgument().setValue(arg);
360 }
361 }
362
363 /**
364 * Utility method to add a javadoc argument.
365 *
366 * @param key the argument name.
367 * @param value the argument value.
368 */
369 private void addArgIfNotEmpty(String key, String value) {
370 if (value != null && value.length() != 0) {
371 cmd.createArgument().setValue(key);
372 cmd.createArgument().setValue(value);
373 } else {
374 log("Warning: Leaving out empty argument '" + key + "'",
375 Project.MSG_WARN);
376 }
377 }
378
379 /**
380 * Flag which indicates if the task should fail if there is a
381 * javadoc error.
382 */
383 private boolean failOnError = false;
384 private Path sourcePath = null;
385 private File destDir = null;
386 private Vector sourceFiles = new Vector();
387 private Vector packageNames = new Vector();
388 private Vector excludePackageNames = new Vector(1);
389 private boolean author = true;
390 private boolean version = true;
391 private DocletInfo doclet = null;
392 private Path classpath = null;
393 private Path bootclasspath = null;
394 private String group = null;
395 private String packageList = null;
396 private Vector links = new Vector();
397 private Vector groups = new Vector();
398 private Vector tags = new Vector();
399 private boolean useDefaultExcludes = true;
400 private Html doctitle = null;
401 private Html header = null;
402 private Html footer = null;
403 private Html bottom = null;
404 private boolean useExternalFile = false;
405 private FileUtils fileUtils = FileUtils.newFileUtils();
406 private String source = null;
407 private boolean linksource = false;
408 private boolean breakiterator = false;
409 private String noqualifier;
410 private boolean includeNoSourcePackages = false;
411 private boolean old = false;
412 private String executable = null;
413
414 private Vector fileSets = new Vector();
415 private Vector packageSets = new Vector();
416
417 /**
418 * Work around command line length limit by using an external file
419 * for the sourcefiles.
420 *
421 * @param b true if an external file is to be used.
422 */
423 public void setUseExternalFile(boolean b) {
424 useExternalFile = b;
425 }
426
427 /**
428 * Sets whether default exclusions should be used or not.
429 *
430 * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions
431 * should be used, "false"|"off"|"no" when they
432 * shouldn't be used.
433 */
434 public void setDefaultexcludes(boolean useDefaultExcludes) {
435 this.useDefaultExcludes = useDefaultExcludes;
436 }
437
438 /**
439 * Set the maximum memory to be used by the javadoc process
440 *
441 * @param max a string indicating the maximum memory according to the
442 * JVM conventions (e.g. 128m is 128 Megabytes)
443 */
444 public void setMaxmemory(String max) {
445 cmd.createArgument().setValue("-J-Xmx" + max);
446 }
447
448 /**
449 * Set an additional parameter on the command line
450 *
451 * @param add the additional command line parameter for the javadoc task.
452 */
453 public void setAdditionalparam(String add) {
454 cmd.createArgument().setLine(add);
455 }
456
457 /**
458 * Adds a command-line argument.
459 * @since Ant 1.6
460 */
461 public Commandline.Argument createArg() {
462 return cmd.createArgument();
463 }
464
465 /**
466 * Specify where to find source file
467 *
468 * @param src a Path instance containing the various source directories.
469 */
470 public void setSourcepath(Path src) {
471 if (sourcePath == null) {
472 sourcePath = src;
473 } else {
474 sourcePath.append(src);
475 }
476 }
477
478 /**
479 * Create a path to be configured with the locations of the source
480 * files.
481 *
482 * @return a new Path instance to be configured by the Ant core.
483 */
484 public Path createSourcepath() {
485 if (sourcePath == null) {
486 sourcePath = new Path(getProject());
487 }
488 return sourcePath.createPath();
489 }
490
491 /**
492 * Adds a reference to a CLASSPATH defined elsewhere.
493 *
494 * @param r the reference containing the source path definition.
495 */
496 public void setSourcepathRef(Reference r) {
497 createSourcepath().setRefid(r);
498 }
499
500 /**
501 * Set the directory where the Javadoc output will be generated.
502 *
503 * @param dir the destination directory.
504 */
505 public void setDestdir(File dir) {
506 destDir = dir;
507 cmd.createArgument().setValue("-d");
508 cmd.createArgument().setFile(destDir);
509 }
510
511 /**
512 * Set the list of source files to process.
513 *
514 * @param src a comma separated list of source files.
515 */
516 public void setSourcefiles(String src) {
517 StringTokenizer tok = new StringTokenizer(src, ",");
518 while (tok.hasMoreTokens()) {
519 String f = tok.nextToken();
520 SourceFile sf = new SourceFile();
521 sf.setFile(getProject().resolveFile(f.trim()));
522 addSource(sf);
523 }
524 }
525
526 /**
527 * Add a single source file.
528 *
529 * @param sf the source file to be processed.
530 */
531 public void addSource(SourceFile sf) {
532 sourceFiles.addElement(sf);
533 }
534
535 /**
536 * Set the package names to be processed.
537 *
538 * @param packages a comma separated list of packages specs
539 * (may be wildcarded).
540 *
541 * @see #addPackage for wildcard information.
542 */
543 public void setPackagenames(String packages) {
544 StringTokenizer tok = new StringTokenizer(packages, ",");
545 while (tok.hasMoreTokens()) {
546 String p = tok.nextToken();
547 PackageName pn = new PackageName();
548 pn.setName(p);
549 addPackage(pn);
550 }
551 }
552
553 /**
554 * Add a single package to be processed.
555 *
556 * If the package name ends with &quot;.*&quot; the Javadoc task
557 * will find and process all subpackages.
558 *
559 * @param pn the package name, possibly wildcarded.
560 */
561 public void addPackage(PackageName pn) {
562 packageNames.addElement(pn);
563 }
564
565 /**
566 * Set the list of packages to be excluded.
567 *
568 * @param packages a comma separated list of packages to be excluded.
569 * This may not include wildcards.
570 */
571 public void setExcludePackageNames(String packages) {
572 StringTokenizer tok = new StringTokenizer(packages, ",");
573 while (tok.hasMoreTokens()) {
574 String p = tok.nextToken();
575 PackageName pn = new PackageName();
576 pn.setName(p);
577 addExcludePackage(pn);
578 }
579 }
580
581 /**
582 * Add a package to be excluded from the javadoc run.
583 *
584 * @param pn the name of the package (wildcards are not permitted).
585 */
586 public void addExcludePackage(PackageName pn) {
587 excludePackageNames.addElement(pn);
588 }
589
590 /**
591 * Specify the file containing the overview to be included in the generated
592 * documentation.
593 *
594 * @param f the file containing the overview.
595 */
596 public void setOverview(File f) {
597 cmd.createArgument().setValue("-overview");
598 cmd.createArgument().setFile(f);
599 }
600
601 /**
602 * Indicate whether only public classes and members are to be included in
603 * the scope processed
604 *
605 * @param b true if scope is to be public.
606 */
607 public void setPublic(boolean b) {
608 addArgIf(b, "-public");
609 }
610
611 /**
612 * Indicate whether only protected and public classes and members are to
613 * be included in the scope processed
614 *
615 * @param b true if scope is to be protected.
616 */
617 public void setProtected(boolean b) {
618 addArgIf(b, "-protected");
619 }
620
621 /**
622 * Indicate whether only package, protected and public classes and
623 * members are to be included in the scope processed
624 *
625 * @param b true if scope is to be package level.
626 */
627 public void setPackage(boolean b) {
628 addArgIf(b, "-package");
629 }
630
631 /**
632 * Indicate whether all classes and
633 * members are to be included in the scope processed
634 *
635 * @param b true if scope is to be private level.
636 */
637 public void setPrivate(boolean b) {
638 addArgIf(b, "-private");
639 }
640
641 /**
642 * Set the scope to be processed. This is an alternative to the
643 * use of the setPublic, setPrivate, etc methods. It gives better build
644 * file control over what scope is processed.
645 *
646 * @param at the scope to be processed.
647 */
648 public void setAccess(AccessType at) {
649 cmd.createArgument().setValue("-" + at.getValue());
650 }
651
652 /**
653 * Set the class that starts the doclet used in generating the
654 * documentation.
655 *
656 * @param docletName the name of the doclet class.
657 */
658 public void setDoclet(String docletName) {
659 if (doclet == null) {
660 doclet = new DocletInfo();
661 doclet.setProject(getProject());
662 }
663 doclet.setName(docletName);
664 }
665
666 /**
667 * Set the classpath used to find the doclet class.
668 *
669 * @param docletPath the doclet classpath.
670 */
671 public void setDocletPath(Path docletPath) {
672 if (doclet == null) {
673 doclet = new DocletInfo();
674 doclet.setProject(getProject());
675 }
676 doclet.setPath(docletPath);
677 }
678
679 /**
680 * Set the classpath used to find the doclet class by reference.
681 *
682 * @param r the reference to the Path instance to use as the doclet
683 * classpath.
684 */
685 public void setDocletPathRef(Reference r) {
686 if (doclet == null) {
687 doclet = new DocletInfo();
688 doclet.setProject(getProject());
689 }
690 doclet.createPath().setRefid(r);
691 }
692
693 /**
694 * Create a doclet to be used in the documentation generation.
695 *
696 * @return a new DocletInfo instance to be configured.
697 */
698 public DocletInfo createDoclet() {
699 doclet = new DocletInfo();
700 return doclet;
701 }
702
703 /**
704 * Add a taglet
705 *
706 * @param tagletInfo information about the taglet.
707 */
708 public void addTaglet(ExtensionInfo tagletInfo) {
709 tags.addElement(tagletInfo);
710 }
711
712 /**
713 * Indicate whether Javadoc should produce old style (JDK 1.1)
714 * documentation.
715 *
716 * This is not supported by JDK 1.1 and has been phased out in JDK 1.4
717 *
718 * @param b if true attempt to generate old style documentation.
719 */
720 public void setOld(boolean b) {
721 old = b;
722 }
723
724 /**
725 * Set the classpath to be used for this javadoc run.
726 *
727 * @param path an Ant Path object containing the compilation
728 * classpath.
729 */
730 public void setClasspath(Path path) {
731 if (classpath == null) {
732 classpath = path;
733 } else {
734 classpath.append(path);
735 }
736 }
737
738 /**
739 * Create a Path to be configured with the classpath to use
740 *
741 * @return a new Path instance to be configured with the classpath.
742 */
743 public Path createClasspath() {
744 if (classpath == null) {
745 classpath = new Path(getProject());
746 }
747 return classpath.createPath();
748 }
749
750 /**
751 * Adds a reference to a CLASSPATH defined elsewhere.
752 *
753 * @param r the reference to an instance defining the classpath.
754 */
755 public void setClasspathRef(Reference r) {
756 createClasspath().setRefid(r);
757 }
758
759 /**
760 * Set the boot classpath to use.
761 *
762 * @param path the boot classpath.
763 */
764 public void setBootclasspath(Path path) {
765 if (bootclasspath == null) {
766 bootclasspath = path;
767 } else {
768 bootclasspath.append(path);
769 }
770 }
771
772 /**
773 * Create a Path to be configured with the boot classpath
774 *
775 * @return a new Path instance to be configured with the boot classpath.
776 */
777 public Path createBootclasspath() {
778 if (bootclasspath == null) {
779 bootclasspath = new Path(getProject());
780 }
781 return bootclasspath.createPath();
782 }
783
784 /**
785 * Adds a reference to a CLASSPATH defined elsewhere.
786 *
787 * @param r the reference to an instance defining the bootclasspath.
788 */
789 public void setBootClasspathRef(Reference r) {
790 createBootclasspath().setRefid(r);
791 }
792
793 /**
794 * Set the location of the extensions directories.
795 *
796 * @param path the string version of the path.
797 * @deprecated Use the {@link #setExtdirs(Path)} version.
798 */
799 public void setExtdirs(String path) {
800 cmd.createArgument().setValue("-extdirs");
801 cmd.createArgument().setValue(path);
802 }
803
804 /**
805 * Set the location of the extensions directories.
806 *
807 * @param path a path containing the extension directories.
808 */
809 public void setExtdirs(Path path) {
810 cmd.createArgument().setValue("-extdirs");
811 cmd.createArgument().setPath(path);
812 }
813
814 /**
815 * Run javadoc in verbose mode
816 *
817 * @param b true if operation is to be verbose.
818 */
819 public void setVerbose(boolean b) {
820 addArgIf(b, "-verbose");
821 }
822
823 /**
824 * Set the local to use in documentation generation.
825 *
826 * @param locale the locale to use.
827 */
828 public void setLocale(String locale) {
829 // createArgument(true) is necessary to make sure, -locale
830 // is the first argument (required in 1.3+).
831 cmd.createArgument(true).setValue(locale);
832 cmd.createArgument(true).setValue("-locale");
833 }
834
835 /**
836 * Set the encoding name of the source files,
837 *
838 * @param enc the name of the encoding for the source files.
839 */
840 public void setEncoding(String enc) {
841 cmd.createArgument().setValue("-encoding");
842 cmd.createArgument().setValue(enc);
843 }
844
845 /**
846 * Include the version tag in the generated documentation.
847 *
848 * @param b true if the version tag should be included.
849 */
850 public void setVersion(boolean b) {
851 this.version = b;
852 }
853
854 /**
855 * Generate the &quot;use&quot page for each package.
856 *
857 * @param b true if the use page should be generated.
858 */
859 public void setUse(boolean b) {
860 addArgIf(b, "-use");
861 }
862
863
864 /**
865 * Include the author tag in the generated documentation.
866 *
867 * @param b true if the author tag should be included.
868 */
869 public void setAuthor(boolean b) {
870 author = b;
871 }
872
873 /**
874 * Generate a split index
875 *
876 * @param b true if the index should be split into a file per letter.
877 */
878 public void setSplitindex(boolean b) {
879 addArgIf(b, "-splitindex");
880 }
881
882 /**
883 * Set the title to be placed in the HTML &lt;title&gt; tag of the
884 * generated documentation.
885 *
886 * @param title the window title to use.
887 */
888 public void setWindowtitle(String title) {
889 addArgIfNotEmpty("-windowtitle", title);
890 }
891
892 /**
893 * Set the title of the generated overview page.
894 *
895 * @param doctitle the Document title.
896 */
897 public void setDoctitle(String doctitle) {
898 Html h = new Html();
899 h.addText(doctitle);
900 addDoctitle(h);
901 }
902
903 /**
904 * Add a document title to use for the overview page.
905 *
906 * @param text the HTML element containing the document title.
907 */
908 public void addDoctitle(Html text) {
909 doctitle = text;
910 }
911
912 /**
913 * Set the header text to be placed at the top of each output file.
914 *
915 * @param header the header text
916 */
917 public void setHeader(String header) {
918 Html h = new Html();
919 h.addText(header);
920 addHeader(h);
921 }
922
923 /**
924 * Set the header text to be placed at the top of each output file.
925 *
926 * @param text the header text
927 */
928 public void addHeader(Html text) {
929 header = text;
930 }
931
932 /**
933 * Set the footer text to be placed at the bottom of each output file.
934 *
935 * @param footer the footer text.
936 */
937 public void setFooter(String footer) {
938 Html h = new Html();
939 h.addText(footer);
940 addFooter(h);
941 }
942
943 /**
944 * Set the footer text to be placed at the bottom of each output file.
945 *
946 * @param text the footer text.
947 */
948 public void addFooter(Html text) {
949 footer = text;
950 }
951
952 /**
953 * Set the text to be placed at the bottom of each output file.
954 *
955 * @param bottom the bottom text.
956 */
957 public void setBottom(String bottom) {
958 Html h = new Html();
959 h.addText(bottom);
960 addBottom(h);
961 }
962
963 /**
964 * Set the text to be placed at the bottom of each output file.
965 *
966 * @param text the bottom text.
967 */
968 public void addBottom(Html text) {
969 bottom = text;
970 }
971
972 /**
973 * Link to docs at "url" using package list at "url2"
974 * - separate the URLs by using a space character.
975 *
976 * @param src the offline link specification (url and package list)
977 */
978 public void setLinkoffline(String src) {
979 if (/*1.2+*/true) {
980 LinkArgument le = createLink();
981 le.setOffline(true);
982 String linkOfflineError = "The linkoffline attribute must include"
983 + " a URL and a package-list file location separated by a"
984 + " space";
985 if (src.trim().length() == 0) {
986 throw new BuildException(linkOfflineError);
987 }
988 StringTokenizer tok = new StringTokenizer(src, " ", false);
989 le.setHref(tok.nextToken());
990
991 if (!tok.hasMoreTokens()) {
992 throw new BuildException(linkOfflineError);
993 }
994 le.setPackagelistLoc(getProject().resolveFile(tok.nextToken()));
995 }
996 }
997
998 /**
999 * Group specified packages together in overview page.
1000 *
1001 * @param src the group packages - a command separated list of group specs,
1002 * each one being a group name and package specification separated
1003 * by a space.
1004 */
1005 public void setGroup(String src) {
1006 group = src;
1007 }
1008
1009 /**
1010 * Create links to javadoc output at the given URL.
1011 */
1012 public void setLink(String src) {
1013 createLink().setHref(src);
1014 }
1015
1016 /**
1017 * Control deprecation infromation
1018 *
1019 * @param b If true, do not include deprecated information.
1020 */
1021 public void setNodeprecated(boolean b) {
1022 addArgIf(b, "-nodeprecated");
1023 }
1024
1025 /**
1026 * Control deprecated list generation
1027 *
1028 * @param b if true, do not generate deprecated list.
1029 */
1030 public void setNodeprecatedlist(boolean b) {
1031 addArgIf(b, "-nodeprecatedlist");
1032 }
1033
1034 /**
1035 * Control class tree generation.
1036 *
1037 * @param b if true, do not generate class hierarchy.
1038 */
1039 public void setNotree(boolean b) {
1040 addArgIf(b, "-notree");
1041 }
1042
1043 /**
1044 * Control generation of index.
1045 *
1046 * @param b if true, do not generate index.
1047 */
1048 public void setNoindex(boolean b) {
1049 addArgIf(b, "-noindex");
1050 }
1051
1052 /**
1053 * Control generation of help link.
1054 *
1055 * @param b if true, do not generate help link
1056 */
1057 public void setNohelp(boolean b) {
1058 addArgIf(b, "-nohelp");
1059 }
1060
1061 /**
1062 * Control generation of the navigation bar.
1063 *
1064 * @param b if true, do not generate navigation bar.
1065 */
1066 public void setNonavbar(boolean b) {
1067 addArgIf(b, "-nonavbar");
1068 }
1069
1070 /**
1071 * Control warnings about serial tag.
1072 *
1073 * @param b if true, generate warning about the serial tag.
1074 */
1075 public void setSerialwarn(boolean b) {
1076 addArgIf(b, "-serialwarn");
1077 }
1078
1079 /**
1080 * Specifies the CSS stylesheet file to use.
1081 *
1082 * @param f the file with the CSS to use.
1083 */
1084 public void setStylesheetfile(File f) {
1085 cmd.createArgument().setValue("-stylesheetfile");
1086 cmd.createArgument().setFile(f);
1087 }
1088
1089 /**
1090 * Specifies the HTML help file to use.
1091 *
1092 * @param f the file containing help content.
1093 */
1094 public void setHelpfile(File f) {
1095 cmd.createArgument().setValue("-helpfile");
1096 cmd.createArgument().setFile(f);
1097 }
1098
1099 /**
1100 * Output file encoding name.
1101 *
1102 * @param enc name of the encoding to use.
1103 */
1104 public void setDocencoding(String enc) {
1105 cmd.createArgument().setValue("-docencoding");
1106 cmd.createArgument().setValue(enc);
1107 }
1108
1109 /**
1110 * The name of a file containing the packages to process.
1111 *
1112 * @param src the file containing the package list.
1113 */
1114 public void setPackageList(String src) {
1115 packageList = src;
1116 }
1117
1118 /**
1119 * Create link to javadoc output at the given URL.
1120 *
1121 * @return link argument to configure
1122 */
1123 public LinkArgument createLink() {
1124 LinkArgument la = new LinkArgument();
1125 links.addElement(la);
1126 return la;
1127 }
1128
1129 /**
1130 * Represents a link triplet (href, whether link is offline, location of the
1131 * package list if off line)
1132 */
1133 public class LinkArgument {
1134 private String href;
1135 private boolean offline = false;
1136 private File packagelistLoc;
1137 private boolean resolveLink = false;
1138
1139 public LinkArgument() {
1140 }
1141
1142 public void setHref(String hr) {
1143 href = hr;
1144 }
1145
1146 public String getHref() {
1147 return href;
1148 }
1149
1150 public void setPackagelistLoc(File src) {
1151 packagelistLoc = src;
1152 }
1153
1154 public File getPackagelistLoc() {
1155 return packagelistLoc;
1156 }
1157
1158 public void setOffline(boolean offline) {
1159 this.offline = offline;
1160 }
1161
1162 public boolean isLinkOffline() {
1163 return offline;
1164 }
1165
1166 /**
1167 * Sets whether Ant should resolve the link attribute relative
1168 * to the current basedir.
1169 * @param resolve a <code>boolean</code> value
1170 */
1171 public void setResolveLink(boolean resolve) {
1172 this.resolveLink = resolve;
1173 }
1174
1175 /**
1176 * should Ant resolve the link attribute relative to the
1177 * current basedir?
1178 */
1179 public boolean shouldResolveLink() {
1180 return resolveLink;
1181 }
1182
1183 }
1184
1185 /**
1186 * Creates and adds a -tag argument. This is used to specify
1187 * custom tags. This argument is only available for JavaDoc 1.4,
1188 * and will generate a verbose message (and then be ignored)
1189 * when run on Java versions below 1.4.
1190 */
1191 public TagArgument createTag() {
1192 TagArgument ta = new TagArgument();
1193 tags.addElement (ta);
1194 return ta;
1195 }
1196
1197 /**
1198 * Scope element verbose names. (Defined here as fields
1199 * cannot be static in inner classes.) The first letter
1200 * from each element is used to build up the scope string.
1201 */
1202 static final String[] SCOPE_ELEMENTS = {
1203 "overview", "packages", "types", "constructors",
1204 "methods", "fields"
1205 };
1206
1207 /**
1208 * Class representing a -tag argument.
1209 */
1210 public class TagArgument extends FileSet {
1211 /** Name of the tag. */
1212 private String name = null;
1213 /** Description of the tag to place in the JavaDocs. */
1214 private String description = null;
1215 /** Whether or not the tag is enabled. */
1216 private boolean enabled = true;
1217 /**
1218 * Scope string of the tag. This will form the middle
1219 * argument of the -tag parameter when the tag is enabled
1220 * (with an X prepended for and is parsed from human-readable form.
1221 */
1222 private String scope = "a";
1223
1224 /** Sole constructor. */
1225 public TagArgument () {
1226 }
1227
1228 /**
1229 * Sets the name of the tag.
1230 *
1231 * @param name The name of the tag.
1232 * Must not be <code>null</code> or empty.
1233 */
1234 public void setName (String name) {
1235 this.name = name;
1236 }
1237
1238 /**
1239 * Sets the description of the tag. This is what appears in
1240 * the JavaDoc.
1241 *
1242 * @param description The description of the tag.
1243 * Must not be <code>null</code> or empty.
1244 */
1245 public void setDescription (String description) {
1246 this.description = description;
1247 }
1248
1249 /**
1250 * Sets the scope of the tag. This is in comma-separated
1251 * form, with each element being one of "all" (the default),
1252 * "overview", "packages", "types", "constructors", "methods",
1253 * "fields". The elements are treated in a case-insensitive
1254 * manner.
1255 *
1256 * @param verboseScope The scope of the tag.
1257 * Must not be <code>null</code>,
1258 * should not be empty.
1259 *
1260 * @exception BuildException if all is specified along with
1261 * other elements, if any elements are repeated, if no
1262 * elements are specified, or if any unrecognised elements are
1263 * specified.
1264 */
1265 public void setScope (String verboseScope) throws BuildException {
1266 verboseScope = verboseScope.toLowerCase(Locale.US);
1267
1268 boolean[] elements = new boolean[SCOPE_ELEMENTS.length];
1269
1270 boolean gotAll = false;
1271 boolean gotNotAll = false;
1272
1273 // Go through the tokens one at a time, updating the
1274 // elements array and issuing warnings where appropriate.
1275 StringTokenizer tok = new StringTokenizer (verboseScope, ",");
1276 while (tok.hasMoreTokens()) {
1277 String next = tok.nextToken().trim();
1278 if (next.equals("all")) {
1279 if (gotAll) {
1280 getProject().log ("Repeated tag scope element: all",
1281 Project.MSG_VERBOSE);
1282 }
1283 gotAll = true;
1284 } else {
1285 int i;
1286 for (i = 0; i < SCOPE_ELEMENTS.length; i++) {
1287 if (next.equals (SCOPE_ELEMENTS[i])) {
1288 break;
1289 }
1290 }
1291 if (i == SCOPE_ELEMENTS.length) {
1292 throw new BuildException ("Unrecognised scope element: "
1293 + next);
1294 } else {
1295 if (elements[i]) {
1296 getProject().log ("Repeated tag scope element: "
1297 + next, Project.MSG_VERBOSE);
1298 }
1299 elements[i] = true;
1300 gotNotAll = true;
1301 }
1302 }
1303 }
1304
1305 if (gotNotAll && gotAll) {
1306 throw new BuildException ("Mixture of \"all\" and other scope "
1307 + "elements in tag parameter.");
1308 }
1309 if (!gotNotAll && !gotAll) {
1310 throw new BuildException ("No scope elements specified in tag "
1311 + "parameter.");
1312 }
1313 if (gotAll) {
1314 this.scope = "a";
1315 } else {
1316 StringBuffer buff = new StringBuffer (elements.length);
1317 for (int i = 0; i < elements.length; i++) {
1318 if (elements[i]) {
1319 buff.append (SCOPE_ELEMENTS[i].charAt(0));
1320 }
1321 }
1322 this.scope = buff.toString();
1323 }
1324 }
1325
1326 /**
1327 * Sets whether or not the tag is enabled.
1328 *
1329 * @param enabled Whether or not this tag is enabled.
1330 */
1331 public void setEnabled (boolean enabled) {
1332 this.enabled = enabled;
1333 }
1334
1335 /**
1336 * Returns the -tag parameter this argument represented.
1337 *
1338 * @exception BuildException if either the name or description
1339 * is <code>null</code> or empty.
1340 */
1341 public String getParameter () throws BuildException {
1342 if (name == null || name.equals("")) {
1343 throw new BuildException ("No name specified for custom tag.");
1344 }
1345 if (description != null) {
1346 return name + ":" + (enabled ? "" : "X")
1347 + scope + ":" + description;
1348 } else {
1349 return name;
1350 }
1351 }
1352 }
1353
1354 /**
1355 * Separates packages on the overview page into whatever
1356 * groups you specify, one group per table.
1357 */
1358 public GroupArgument createGroup() {
1359 GroupArgument ga = new GroupArgument();
1360 groups.addElement(ga);
1361 return ga;
1362 }
1363
1364 public class GroupArgument {
1365 private Html title;
1366 private Vector packages = new Vector();
1367
1368 public GroupArgument() {
1369 }
1370
1371 public void setTitle(String src) {
1372 Html h = new Html();
1373 h.addText(src);
1374 addTitle(h);
1375 }
1376 public void addTitle(Html text) {
1377 title = text;
1378 }
1379
1380 public String getTitle() {
1381 return title != null ? title.getText() : null;
1382 }
1383
1384 public void setPackages(String src) {
1385 StringTokenizer tok = new StringTokenizer(src, ",");
1386 while (tok.hasMoreTokens()) {
1387 String p = tok.nextToken();
1388 PackageName pn = new PackageName();
1389 pn.setName(p);
1390 addPackage(pn);
1391 }
1392 }
1393 public void addPackage(PackageName pn) {
1394 packages.addElement(pn);
1395 }
1396
1397 public String getPackages() {
1398 StringBuffer p = new StringBuffer();
1399 for (int i = 0; i < packages.size(); i++) {
1400 if (i > 0) {
1401 p.append(":");
1402 }
1403 p.append(packages.elementAt(i).toString());
1404 }
1405 return p.toString();
1406 }
1407 }
1408
1409 /**
1410 * Charset for cross-platform viewing of generated documentation.
1411 */
1412 public void setCharset(String src) {
1413 this.addArgIfNotEmpty("-charset", src);
1414 }
1415
1416 /**
1417 * Should the build process fail if javadoc fails (as indicated by
1418 * a non zero return code)?
1419 *
1420 * <p>Default is false.</p>
1421 */
1422 public void setFailonerror(boolean b) {
1423 failOnError = b;
1424 }
1425
1426 /**
1427 * Enables the -source switch, will be ignored if javadoc is not
1428 * the 1.4 version.
1429 *
1430 * @since Ant 1.5
1431 */
1432 public void setSource(String source) {
1433 this.source = source;
1434 }
1435
1436 /**
1437 * Sets the actual executable command to invoke, instead of the binary
1438 * <code>javadoc</code> found in Ant's JDK.
1439 * @since Ant 1.6.3
1440 */
1441 public void setExecutable(String executable) {
1442 this.executable = executable;
1443 }
1444
1445 /**
1446 * Adds a packageset.
1447 *
1448 * <p>All included directories will be translated into package
1449 * names be converting the directory separator into dots.</p>
1450 *
1451 * @since 1.5
1452 */
1453 public void addPackageset(DirSet packageSet) {
1454 packageSets.addElement(packageSet);
1455 }
1456
1457 /**
1458 * Adds a fileset.
1459 *
1460 * <p>All included files will be added as sourcefiles. The task
1461 * will automatically add
1462 * <code>includes=&quot;**&#47;*.java&quot;</code> to the
1463 * fileset.</p>
1464 *
1465 * @since 1.5
1466 */
1467 public void addFileset(FileSet fs) {
1468 fileSets.addElement(fs);
1469 }
1470
1471 /**
1472 * Enables the -linksource switch, will be ignored if javadoc is not
1473 * the 1.4 version. Default is false
1474 *
1475 * @since Ant 1.6
1476 */
1477 public void setLinksource(boolean b) {
1478 this.linksource = b;
1479 }
1480
1481 /**
1482 * Enables the -linksource switch, will be ignored if javadoc is not
1483 * the 1.4 version. Default is false
1484 *
1485 * @since Ant 1.6
1486 */
1487 public void setBreakiterator(boolean b) {
1488 this.breakiterator = b;
1489 }
1490
1491 /**
1492 * Enables the -noqualifier switch, will be ignored if javadoc is not
1493 * the 1.4 version.
1494 *
1495 * @since Ant 1.6
1496 */
1497 public void setNoqualifier(String noqualifier) {
1498 this.noqualifier = noqualifier;
1499 }
1500
1501 /**
1502 * If set to true, Ant will also accept packages that only hold
1503 * package.html files but no Java sources.
1504 * @since Ant 1.6.3
1505 */
1506 public void setIncludeNoSourcePackages(boolean b) {
1507 this.includeNoSourcePackages = b;
1508 }
1509
1510 public void execute() throws BuildException {
1511 if ("javadoc2".equals(getTaskType())) {
1512 log("!! javadoc2 is deprecated. Use javadoc instead. !!");
1513 }
1514
1515 // Whether *this VM* is 1.4+ (but also check executable != null).
1516 boolean javadoc4 =
1517 !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2) &&
1518 !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_3);
1519
1520 Vector packagesToDoc = new Vector();
1521 Path sourceDirs = new Path(getProject());
1522
1523 if (packageList != null && sourcePath == null) {
1524 String msg = "sourcePath attribute must be set when "
1525 + "specifying packagelist.";
1526 throw new BuildException(msg);
1527 }
1528
1529 if (sourcePath != null) {
1530 sourceDirs.addExisting(sourcePath);
1531 }
1532
1533 parsePackages(packagesToDoc, sourceDirs);
1534
1535 if (packagesToDoc.size() != 0 && sourceDirs.size() == 0) {
1536 String msg = "sourcePath attribute must be set when "
1537 + "specifying package names.";
1538 throw new BuildException(msg);
1539 }
1540
1541 Vector sourceFilesToDoc = (Vector) sourceFiles.clone();
1542 addFileSets(sourceFilesToDoc);
1543
1544 if (packageList == null && packagesToDoc.size() == 0
1545 && sourceFilesToDoc.size() == 0) {
1546 throw new BuildException("No source files and no packages have "
1547 + "been specified.");
1548 }
1549
1550 log("Generating Javadoc", Project.MSG_INFO);
1551
1552 Commandline toExecute = (Commandline) cmd.clone();
1553 if (executable != null) {
1554 toExecute.setExecutable(executable);
1555 } else {
1556 toExecute.setExecutable(JavaEnvUtils.getJdkExecutable("javadoc"));
1557 }
1558
1559 // ------------------------------------------ general javadoc arguments
1560 if (doctitle != null) {
1561 toExecute.createArgument().setValue("-doctitle");
1562 toExecute.createArgument().setValue(expand(doctitle.getText()));
1563 }
1564 if (header != null) {
1565 toExecute.createArgument().setValue("-header");
1566 toExecute.createArgument().setValue(expand(header.getText()));
1567 }
1568 if (footer != null) {
1569 toExecute.createArgument().setValue("-footer");
1570 toExecute.createArgument().setValue(expand(footer.getText()));
1571 }
1572 if (bottom != null) {
1573 toExecute.createArgument().setValue("-bottom");
1574 toExecute.createArgument().setValue(expand(bottom.getText()));
1575 }
1576
1577 if (classpath == null) {
1578 classpath = (new Path(getProject())).concatSystemClasspath("last");
1579 } else {
1580 classpath = classpath.concatSystemClasspath("ignore");
1581 }
1582
1583 if (/*1.2+*/true) {
1584 if (classpath.size() > 0) {
1585 toExecute.createArgument().setValue("-classpath");
1586 toExecute.createArgument().setPath(classpath);
1587 }
1588 if (sourceDirs.size() > 0) {
1589 toExecute.createArgument().setValue("-sourcepath");
1590 toExecute.createArgument().setPath(sourceDirs);
1591 }
1592 }
1593
1594 if (version && doclet == null) {
1595 toExecute.createArgument().setValue("-version");
1596 }
1597 if (author && doclet == null) {
1598 toExecute.createArgument().setValue("-author");
1599 }
1600
1601 if (doclet == null) {
1602 if (destDir == null) {
1603 String msg = "destDir attribute must be set!";
1604 throw new BuildException(msg);
1605 }
1606 }
1607
1608 // ---------------------------- javadoc2 arguments for default doclet
1609
1610 if (/*1.2+*/true) {
1611 if (doclet != null) {
1612 if (doclet.getName() == null) {
1613 throw new BuildException("The doclet name must be "
1614 + "specified.", getLocation());
1615 } else {
1616 toExecute.createArgument().setValue("-doclet");
1617 toExecute.createArgument().setValue(doclet.getName());
1618 if (doclet.getPath() != null) {
1619 Path docletPath
1620 = doclet.getPath().concatSystemClasspath("ignore");
1621 if (docletPath.size() != 0) {
1622 toExecute.createArgument().setValue("-docletpath");
1623 toExecute.createArgument().setPath(docletPath);
1624 }
1625 }
1626 for (Enumeration e = doclet.getParams();
1627 e.hasMoreElements();) {
1628 DocletParam param = (DocletParam) e.nextElement();
1629 if (param.getName() == null) {
1630 throw new BuildException("Doclet parameters must "
1631 + "have a name");
1632 }
1633
1634 toExecute.createArgument().setValue(param.getName());
1635 if (param.getValue() != null) {
1636 toExecute.createArgument()
1637 .setValue(param.getValue());
1638 }
1639 }
1640 }
1641 }
1642 if (bootclasspath != null && bootclasspath.size() > 0) {
1643 toExecute.createArgument().setValue("-bootclasspath");
1644 toExecute.createArgument().setPath(bootclasspath);
1645 }
1646
1647 // add the links arguments
1648 if (links.size() != 0) {
1649 for (Enumeration e = links.elements(); e.hasMoreElements();) {
1650 LinkArgument la = (LinkArgument) e.nextElement();
1651
1652 if (la.getHref() == null || la.getHref().length() == 0) {
1653 log("No href was given for the link - skipping",
1654 Project.MSG_VERBOSE);
1655 continue;
1656 }
1657 String link = null;
1658 if (la.shouldResolveLink()) {
1659 File hrefAsFile =
1660 getProject().resolveFile(la.getHref());
1661 if (hrefAsFile.exists()) {
1662 try {
1663 link = fileUtils.getFileURL(hrefAsFile)
1664 .toExternalForm();
1665 } catch (MalformedURLException ex) {
1666 // should be impossible
1667 log("Warning: link location was invalid "
1668 + hrefAsFile, Project.MSG_WARN);
1669 }
1670 }
1671 }
1672 if (link == null) {
1673 // is the href a valid URL
1674 try {
1675 URL base = new URL("file://.");
1676 new URL(base, la.getHref());
1677 link = la.getHref();
1678 } catch (MalformedURLException mue) {
1679 // ok - just skip
1680 log("Link href \"" + la.getHref()
1681 + "\" is not a valid url - skipping link",
1682 Project.MSG_WARN);
1683 continue;
1684 }
1685 }
1686
1687 if (la.isLinkOffline()) {
1688 File packageListLocation = la.getPackagelistLoc();
1689 if (packageListLocation == null) {
1690 throw new BuildException("The package list "
1691 + " location for link " + la.getHref()
1692 + " must be provided because the link is "
1693 + "offline");
1694 }
1695 File packageListFile =
1696 new File(packageListLocation, "package-list");
1697 if (packageListFile.exists()) {
1698 try {
1699 String packageListURL =
1700 fileUtils.getFileURL(packageListLocation)
1701 .toExternalForm();
1702 toExecute.createArgument()
1703 .setValue("-linkoffline");
1704 toExecute.createArgument()
1705 .setValue(link);
1706 toExecute.createArgument()
1707 .setValue(packageListURL);
1708 } catch (MalformedURLException ex) {
1709 log("Warning: Package list location was "
1710 + "invalid " + packageListLocation,
1711 Project.MSG_WARN);
1712 }
1713 } else {
1714 log("Warning: No package list was found at "
1715 + packageListLocation, Project.MSG_VERBOSE);
1716 }
1717 } else {
1718 toExecute.createArgument().setValue("-link");
1719 toExecute.createArgument().setValue(link);
1720 }
1721 }
1722 }
1723
1724 // add the single group arguments
1725 // Javadoc 1.2 rules:
1726 // Multiple -group args allowed.
1727 // Each arg includes 3 strings: -group [name] [packagelist].
1728 // Elements in [packagelist] are colon-delimited.
1729 // An element in [packagelist] may end with the * wildcard.
1730
1731 // Ant javadoc task rules for group attribute:
1732 // Args are comma-delimited.
1733 // Each arg is 2 space-delimited strings.
1734 // E.g., group="XSLT_Packages org.apache.xalan.xslt*,
1735 // XPath_Packages org.apache.xalan.xpath*"
1736 if (group != null) {
1737 StringTokenizer tok = new StringTokenizer(group, ",", false);
1738 while (tok.hasMoreTokens()) {
1739 String grp = tok.nextToken().trim();
1740 int space = grp.indexOf(" ");
1741 if (space > 0) {
1742 String name = grp.substring(0, space);
1743 String pkgList = grp.substring(space + 1);
1744 toExecute.createArgument().setValue("-group");
1745 toExecute.createArgument().setValue(name);
1746 toExecute.createArgument().setValue(pkgList);
1747 }
1748 }
1749 }
1750
1751 // add the group arguments
1752 if (groups.size() != 0) {
1753 for (Enumeration e = groups.elements(); e.hasMoreElements();) {
1754 GroupArgument ga = (GroupArgument) e.nextElement();
1755 String title = ga.getTitle();
1756 String packages = ga.getPackages();
1757 if (title == null || packages == null) {
1758 throw new BuildException("The title and packages must "
1759 + "be specified for group "
1760 + "elements.");
1761 }
1762 toExecute.createArgument().setValue("-group");
1763 toExecute.createArgument().setValue(expand(title));
1764 toExecute.createArgument().setValue(packages);
1765 }
1766 }
1767
1768 // JavaDoc 1.4 parameters
1769 if (javadoc4 || executable != null) {
1770 for (Enumeration e = tags.elements(); e.hasMoreElements();) {
1771 Object element = e.nextElement();
1772 if (element instanceof TagArgument) {
1773 TagArgument ta = (TagArgument) element;
1774 File tagDir = ta.getDir(getProject());
1775 if (tagDir == null) {
1776 // The tag element is not used as a fileset,
1777 // but specifies the tag directly.
1778 toExecute.createArgument().setValue ("-tag");
1779 toExecute.createArgument().setValue (ta.getParameter());
1780 } else {
1781 // The tag element is used as a fileset. Parse all the files and
1782 // create -tag arguments.
1783 DirectoryScanner tagDefScanner = ta.getDirectoryScanner(getProject());
1784 String[] files = tagDefScanner.getIncludedFiles();
1785 for (int i = 0; i < files.length; i++) {
1786 File tagDefFile = new File(tagDir, files[i]);
1787 try {
1788 BufferedReader in
1789 = new BufferedReader(new FileReader(tagDefFile));
1790 String line = null;
1791 while ((line = in.readLine()) != null) {
1792 toExecute.createArgument().setValue ("-tag");
1793 toExecute.createArgument().setValue (line);
1794 }
1795 in.close();
1796 } catch (IOException ioe) {
1797 throw new BuildException("Couldn't read "
1798 + " tag file from "
1799 + tagDefFile.getAbsolutePath(), ioe);
1800 }
1801 }
1802 }
1803 } else {
1804 ExtensionInfo tagletInfo = (ExtensionInfo) element;
1805 toExecute.createArgument().setValue("-taglet");
1806 toExecute.createArgument().setValue(tagletInfo
1807 .getName());
1808 if (tagletInfo.getPath() != null) {
1809 Path tagletPath = tagletInfo.getPath()
1810 .concatSystemClasspath("ignore");
1811 if (tagletPath.size() != 0) {
1812 toExecute.createArgument()
1813 .setValue("-tagletpath");
1814 toExecute.createArgument().setPath(tagletPath);
1815 }
1816 }
1817 }
1818 }
1819
1820 if (source != null) {
1821 toExecute.createArgument().setValue("-source");
1822 toExecute.createArgument().setValue(source);
1823 }
1824
1825 if (linksource && doclet == null) {
1826 toExecute.createArgument().setValue("-linksource");
1827 }
1828 if (breakiterator && doclet == null) {
1829 toExecute.createArgument().setValue("-breakiterator");
1830 }
1831 if (noqualifier != null && doclet == null) {
1832 toExecute.createArgument().setValue("-noqualifier");
1833 toExecute.createArgument().setValue(noqualifier);
1834 }
1835 } else {
1836 // Not 1.4+.
1837 if (!tags.isEmpty()) {
1838 log("-tag and -taglet options not supported on Javadoc < 1.4",
1839 Project.MSG_VERBOSE);
1840 }
1841 if (source != null) {
1842 log("-source option not supported on JavaDoc < 1.4",
1843 Project.MSG_VERBOSE);
1844 }
1845 if (linksource) {
1846 log("-linksource option not supported on JavaDoc < 1.4",
1847 Project.MSG_VERBOSE);
1848 }
1849 if (breakiterator) {
1850 log("-breakiterator option not supported on JavaDoc < 1.4",
1851 Project.MSG_VERBOSE);
1852 }
1853 if (noqualifier != null) {
1854 log("-noqualifier option not supported on JavaDoc < 1.4",
1855 Project.MSG_VERBOSE);
1856 }
1857 }
1858 // Javadoc 1.2/1.3 parameters:
1859 if (!javadoc4 || executable != null) {
1860 if (old) {
1861 toExecute.createArgument().setValue("-1.1");
1862 }
1863 } else {
1864 if (old) {
1865 log("Javadoc 1.4 doesn't support the -1.1 switch anymore",
1866 Project.MSG_WARN);
1867 }
1868 }
1869
1870 }
1871
1872 File tmpList = null;
1873 PrintWriter srcListWriter = null;
1874 try {
1875
1876 /**
1877 * Write sourcefiles and package names to a temporary file
1878 * if requested.
1879 */
1880 if (useExternalFile) {
1881 if (tmpList == null) {
1882 tmpList = fileUtils.createTempFile("javadoc", "", null);
1883 tmpList.deleteOnExit();
1884 toExecute.createArgument()
1885 .setValue("@" + tmpList.getAbsolutePath());
1886 }
1887 srcListWriter = new PrintWriter(
1888 new FileWriter(tmpList.getAbsolutePath(),
1889 true));
1890 }
1891
1892 Enumeration e = packagesToDoc.elements();
1893 while (e.hasMoreElements()) {
1894 String packageName = (String) e.nextElement();
1895 if (useExternalFile) {
1896 srcListWriter.println(packageName);
1897 } else {
1898 toExecute.createArgument().setValue(packageName);
1899 }
1900 }
1901
1902 e = sourceFilesToDoc.elements();
1903 while (e.hasMoreElements()) {
1904 SourceFile sf = (SourceFile) e.nextElement();
1905 String sourceFileName = sf.getFile().getAbsolutePath();
1906 if (useExternalFile) {
1907 if (javadoc4 && sourceFileName.indexOf(" ") > -1) {
1908 String name = sourceFileName;
1909 if (File.separatorChar == '\\') {
1910 name = sourceFileName.replace(File.separatorChar, '/');
1911 }
1912 srcListWriter.println("\"" + name + "\"");
1913 } else {
1914 srcListWriter.println(sourceFileName);
1915 }
1916 } else {
1917 toExecute.createArgument().setValue(sourceFileName);
1918 }
1919 }
1920
1921 } catch (IOException e) {
1922 tmpList.delete();
1923 throw new BuildException("Error creating temporary file",
1924 e, getLocation());
1925 } finally {
1926 if (srcListWriter != null) {
1927 srcListWriter.close();
1928 }
1929 }
1930
1931 if (packageList != null) {
1932 toExecute.createArgument().setValue("@" + packageList);
1933 }
1934 log(toExecute.describeCommand(), Project.MSG_VERBOSE);
1935
1936 log("Javadoc execution", Project.MSG_INFO);
1937
1938 JavadocOutputStream out = new JavadocOutputStream(Project.MSG_INFO);
1939 JavadocOutputStream err = new JavadocOutputStream(Project.MSG_WARN);
1940 Execute exe = new Execute(new PumpStreamHandler(out, err));
1941 exe.setAntRun(getProject());
1942
1943 /*
1944 * No reason to change the working directory as all filenames and
1945 * path components have been resolved already.
1946 *
1947 * Avoid problems with command line length in some environments.
1948 */
1949 exe.setWorkingDirectory(null);
1950 try {
1951 exe.setCommandline(toExecute.getCommandline());
1952 int ret = exe.execute();
1953 if (ret != 0 && failOnError) {
1954 throw new BuildException("Javadoc returned " + ret, getLocation());
1955 }
1956 } catch (IOException e) {
1957 throw new BuildException("Javadoc failed: " + e, e, getLocation());
1958 } finally {
1959 if (tmpList != null) {
1960 tmpList.delete();
1961 tmpList = null;
1962 }
1963
1964 out.logFlush();
1965 err.logFlush();
1966 try {
1967 out.close();
1968 err.close();
1969 } catch (IOException e) {
1970 // ignore
1971 }
1972 }
1973 }
1974
1975 /**
1976 * Add the files matched by the nested filesets to the Vector as
1977 * SourceFile instances.
1978 *
1979 * @since 1.5
1980 */
1981 private void addFileSets(Vector sf) {
1982 Enumeration e = fileSets.elements();
1983 while (e.hasMoreElements()) {
1984 FileSet fs = (FileSet) e.nextElement();
1985 if (!fs.hasPatterns() && !fs.hasSelectors()) {
1986 fs = (FileSet) fs.clone();
1987 fs.createInclude().setName("**/*.java");
1988 if (includeNoSourcePackages) {
1989 fs.createInclude().setName("**/package.html");
1990 }
1991 }
1992 File baseDir = fs.getDir(getProject());
1993 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
1994 String[] files = ds.getIncludedFiles();
1995 for (int i = 0; i < files.length; i++) {
1996 sf.addElement(new SourceFile(new File(baseDir, files[i])));
1997 }
1998 }
1999 }
2000
2001 /**
2002 * Add the directories matched by the nested dirsets to the Vector
2003 * and the base directories of the dirsets to the Path. It also
2004 * handles the packages and excludepackages attributes and
2005 * elements.
2006 *
2007 * @since 1.5
2008 */
2009 private void parsePackages(Vector pn, Path sp) {
2010 Vector addedPackages = new Vector();
2011 Vector dirSets = (Vector) packageSets.clone();
2012
2013 // for each sourcePath entry, add a directoryset with includes
2014 // taken from packagenames attribute and nested package
2015 // elements and excludes taken from excludepackages attribute
2016 // and nested excludepackage elements
2017 if (sourcePath != null && packageNames.size() > 0) {
2018 PatternSet ps = new PatternSet();
2019 Enumeration e = packageNames.elements();
2020 while (e.hasMoreElements()) {
2021 PackageName p = (PackageName) e.nextElement();
2022 String pkg = p.getName().replace('.', '/');
2023 if (pkg.endsWith("*")) {
2024 pkg += "*";
2025 }
2026 ps.createInclude().setName(pkg);
2027 }
2028
2029 e = excludePackageNames.elements();
2030 while (e.hasMoreElements()) {
2031 PackageName p = (PackageName) e.nextElement();
2032 String pkg = p.getName().replace('.', '/');
2033 if (pkg.endsWith("*")) {
2034 pkg += "*";
2035 }
2036 ps.createExclude().setName(pkg);
2037 }
2038
2039
2040 String[] pathElements = sourcePath.list();
2041 for (int i = 0; i < pathElements.length; i++) {
2042 DirSet ds = new DirSet();
2043 ds.setDefaultexcludes(useDefaultExcludes);
2044 ds.setDir(new File(pathElements[i]));
2045 ds.createPatternSet().addConfiguredPatternset(ps);
2046 dirSets.addElement(ds);
2047 }
2048 }
2049
2050 Enumeration e = dirSets.elements();
2051 while (e.hasMoreElements()) {
2052 DirSet ds = (DirSet) e.nextElement();
2053 File baseDir = ds.getDir(getProject());
2054 log("scanning " + baseDir + " for packages.", Project.MSG_DEBUG);
2055 DirectoryScanner dsc = ds.getDirectoryScanner(getProject());
2056 String[] dirs = dsc.getIncludedDirectories();
2057 boolean containsPackages = false;
2058 for (int i = 0; i < dirs.length; i++) {
2059 // are there any java files in this directory?
2060 File pd = new File(baseDir, dirs[i]);
2061 String[] files = pd.list(new FilenameFilter () {
2062 public boolean accept(File dir1, String name) {
2063 return name.endsWith(".java")
2064 || (includeNoSourcePackages
2065 && name.equals("package.html"));
2066 }
2067 });
2068
2069 if (files.length > 0) {
2070 containsPackages = true;
2071 String packageName =
2072 dirs[i].replace(File.separatorChar, '.');
2073 if (!addedPackages.contains(packageName)) {
2074 addedPackages.addElement(packageName);
2075 pn.addElement(packageName);
2076 }
2077 }
2078 }
2079 if (containsPackages) {
2080 // We don't need to care for duplicates here,
2081 // Path.list does it for us.
2082 sp.createPathElement().setLocation(baseDir);
2083 } else {
2084 log(baseDir + " doesn\'t contain any packages, dropping it.",
2085 Project.MSG_VERBOSE);
2086 }
2087 }
2088 }
2089
2090 private class JavadocOutputStream extends LogOutputStream {
2091 JavadocOutputStream(int level) {
2092 super(Javadoc.this, level);
2093 }
2094
2095 //
2096 // Override the logging of output in order to filter out Generating
2097 // messages. Generating messages are set to a priority of VERBOSE
2098 // unless they appear after what could be an informational message.
2099 //
2100 private String queuedLine = null;
2101 protected void processLine(String line, int messageLevel) {
2102 if (messageLevel == Project.MSG_INFO
2103 && line.startsWith("Generating ")) {
2104 if (queuedLine != null) {
2105 super.processLine(queuedLine, Project.MSG_VERBOSE);
2106 }
2107 queuedLine = line;
2108 } else {
2109 if (queuedLine != null) {
2110 if (line.startsWith("Building ")) {
2111 super.processLine(queuedLine, Project.MSG_VERBOSE);
2112 } else {
2113 super.processLine(queuedLine, Project.MSG_INFO);
2114 }
2115 queuedLine = null;
2116 }
2117 super.processLine(line, messageLevel);
2118 }
2119 }
2120
2121
2122 protected void logFlush() {
2123 if (queuedLine != null) {
2124 super.processLine(queuedLine, Project.MSG_VERBOSE);
2125 queuedLine = null;
2126 }
2127 }
2128 }
2129
2130 /**
2131 * Convenience method to expand properties.
2132 */
2133 protected String expand(String content) {
2134 return getProject().replaceProperties(content);
2135 }
2136
2137}
Note: See TracBrowser for help on using the repository browser.