KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > Javadoc


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18 package org.apache.tools.ant.taskdefs;
19
20 import java.io.File JavaDoc;
21 import java.io.FileWriter JavaDoc;
22 import java.io.FilenameFilter JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.PrintWriter JavaDoc;
25 import java.io.BufferedReader JavaDoc;
26 import java.io.FileReader JavaDoc;
27 import java.net.MalformedURLException JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.Locale JavaDoc;
33 import java.util.StringTokenizer JavaDoc;
34 import java.util.Vector JavaDoc;
35 import org.apache.tools.ant.BuildException;
36 import org.apache.tools.ant.DirectoryScanner;
37 import org.apache.tools.ant.MagicNames;
38 import org.apache.tools.ant.Project;
39 import org.apache.tools.ant.ProjectComponent;
40 import org.apache.tools.ant.Task;
41 import org.apache.tools.ant.types.Commandline;
42 import org.apache.tools.ant.types.DirSet;
43 import org.apache.tools.ant.types.EnumeratedAttribute;
44 import org.apache.tools.ant.types.FileSet;
45 import org.apache.tools.ant.types.Path;
46 import org.apache.tools.ant.types.PatternSet;
47 import org.apache.tools.ant.types.Reference;
48 import org.apache.tools.ant.types.ResourceCollection;
49 import org.apache.tools.ant.types.resources.FileResource;
50 import org.apache.tools.ant.util.FileUtils;
51 import org.apache.tools.ant.util.JavaEnvUtils;
52
53 /**
54  * Generates Javadoc documentation for a collection
55  * of source code.
56  *
57  * <p>Current known limitations are:
58  *
59  * <p><ul>
60  * <li>patterns must be of the form "xxx.*", every other pattern doesn't
61  * work.
62  * <li>there is no control on arguments sanity since they are left
63  * to the Javadoc implementation.
64  * </ul>
65  *
66  * <p>If no <code>doclet</code> is set, then the <code>version</code> and
67  * <code>author</code> are by default <code>"yes"</code>.
68  *
69  * <p>Note: This task is run on another VM because the Javadoc code calls
70  * <code>System.exit()</code> which would break Ant functionality.
71  *
72  * @since Ant 1.1
73  *
74  * @ant.task category="java"
75  */

76 public class Javadoc extends Task {
77     /**
78      * Inner class used to manage doclet parameters.
79      */

80     public class DocletParam {
81         /** The parameter name */
82         private String JavaDoc name;
83
84         /** The parameter value */
85         private String JavaDoc value;
86
87         /**
88          * Set the name of the parameter.
89          *
90          * @param name the name of the doclet parameter
91          */

92         public void setName(String JavaDoc name) {
93             this.name = name;
94         }
95
96         /**
97          * Get the parameter name.
98          *
99          * @return the parameter's name.
100          */

101         public String JavaDoc getName() {
102             return name;
103         }
104
105         /**
106          * Set the parameter value.
107          *
108          * Note that only string values are supported. No resolution of file
109          * paths is performed.
110          *
111          * @param value the parameter value.
112          */

113         public void setValue(String JavaDoc value) {
114             this.value = value;
115         }
116
117         /**
118          * Get the parameter value.
119          *
120          * @return the parameter value.
121          */

122         public String JavaDoc getValue() {
123             return value;
124         }
125     }
126
127     /**
128      * A project aware class used for Javadoc extensions which take a name
129      * and a path such as doclet and taglet arguments.
130      *
131      */

132     public static class ExtensionInfo extends ProjectComponent {
133         /** The name of the extension */
134         private String JavaDoc name;
135
136         /** The optional path to use to load the extension */
137         private Path path;
138
139         /**
140          * Set the name of the extension
141          *
142          * @param name the extension's name.
143          */

144         public void setName(String JavaDoc name) {
145             this.name = name;
146         }
147
148         /**
149          * Get the name of the extension.
150          *
151          * @return the extension's name.
152          */

153         public String JavaDoc getName() {
154             return name;
155         }
156
157         /**
158          * Set the path to use when loading the component.
159          *
160          * @param path a Path instance containing the classpath to use.
161          */

162         public void setPath(Path path) {
163             if (this.path == null) {
164                 this.path = path;
165             } else {
166                 this.path.append(path);
167             }
168         }
169
170         /**
171          * Get the extension's path.
172          *
173          * @return the path to be used to load the extension.
174          * May be <code>null</code>
175          */

176         public Path getPath() {
177             return path;
178         }
179
180         /**
181          * Create an empty nested path to be configured by Ant with the
182          * classpath for the extension.
183          *
184          * @return a new Path instance to be configured.
185          */

186         public Path createPath() {
187             if (path == null) {
188                 path = new Path(getProject());
189             }
190             return path.createPath();
191         }
192
193         /**
194          * Adds a reference to a CLASSPATH defined elsewhere.
195          *
196          * @param r the reference containing the path.
197          */

198         public void setPathRef(Reference r) {
199             createPath().setRefid(r);
200         }
201     }
202
203     /**
204      * This class stores info about doclets.
205      *
206      */

207     public class DocletInfo extends ExtensionInfo {
208
209         /** Collection of doclet parameters. */
210         private Vector JavaDoc params = new Vector JavaDoc();
211
212         /**
213          * Create a doclet parameter to be configured by Ant.
214          *
215          * @return a new DocletParam instance to be configured.
216          */

217         public DocletParam createParam() {
218             DocletParam param = new DocletParam();
219             params.addElement(param);
220
221             return param;
222         }
223
224         /**
225          * Get the doclet's parameters.
226          *
227          * @return an Enumeration of DocletParam instances.
228          */

229         public Enumeration JavaDoc getParams() {
230             return params.elements();
231         }
232     }
233
234     /**
235      * Used to track info about the packages to be javadoc'd
236      */

237     public static class PackageName {
238         /** The package name */
239         private String JavaDoc name;
240
241         /**
242          * Set the name of the package
243          *
244          * @param name the package name.
245          */

246         public void setName(String JavaDoc name) {
247             this.name = name.trim();
248         }
249
250         /**
251          * Get the package name.
252          *
253          * @return the package's name.
254          */

255         public String JavaDoc getName() {
256             return name;
257         }
258
259         /**
260          * Return a string rep for this object.
261          * @return the package name.
262          */

263         public String JavaDoc toString() {
264             return getName();
265         }
266     }
267
268     /**
269      * This class is used to manage the source files to be processed.
270      */

271     public static class SourceFile {
272         /** The source file */
273         private File JavaDoc file;
274
275         /**
276          * Default constructor
277          */

278         public SourceFile() {
279             //empty
280
}
281
282         /**
283          * Constructor specifying the source file directly
284          *
285          * @param file the source file
286          */

287         public SourceFile(File JavaDoc file) {
288             this.file = file;
289         }
290
291         /**
292          * Set the source file.
293          *
294          * @param file the source file.
295          */

296         public void setFile(File JavaDoc file) {
297             this.file = file;
298         }
299
300         /**
301          * Get the source file.
302          *
303          * @return the source file.
304          */

305         public File JavaDoc getFile() {
306             return file;
307         }
308     }
309
310     /**
311      * An HTML element in the Javadoc.
312      *
313      * This class is used for those Javadoc elements which contain HTML such as
314      * footers, headers, etc.
315      */

316     public static class Html {
317         /** The text for the element */
318         private StringBuffer JavaDoc text = new StringBuffer JavaDoc();
319
320         /**
321          * Add text to the element.
322          *
323          * @param t the text to be added.
324          */

325         public void addText(String JavaDoc t) {
326             text.append(t);
327         }
328
329         /**
330          * Get the current text for the element.
331          *
332          * @return the current text.
333          */

334         public String JavaDoc getText() {
335             return text.substring(0);
336         }
337     }
338
339     /**
340      * EnumeratedAttribute implementation supporting the Javadoc scoping
341      * values.
342      */

343     public static class AccessType extends EnumeratedAttribute {
344         /**
345          * @return the allowed values for the access type.
346          */

347         public String JavaDoc[] getValues() {
348             // Protected first so if any GUI tool offers a default
349
// based on enum #0, it will be right.
350
return new String JavaDoc[] {"protected", "public", "package", "private"};
351         }
352     }
353
354     /**
355      * Holds a collection of ResourceCollections.
356      *
357      * <p>A separate kind of container is needed since this task
358      * contains special handling for FileSets that has to occur at
359      * task runtime.</p>
360      */

361     public class ResourceCollectionContainer {
362         private ArrayList JavaDoc rcs = new ArrayList JavaDoc();
363         /**
364          * Add a resource collection to the container.
365          * @param rc the collection to add.
366          */

367         public void add(ResourceCollection rc) {
368             rcs.add(rc);
369         }
370
371         /**
372          * Get an iterator on the collection.
373          * @return an iterator.
374          */

375         private Iterator JavaDoc iterator() {
376             return rcs.iterator();
377         }
378     }
379
380     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
381
382     /** The command line built to execute Javadoc. */
383     private Commandline cmd = new Commandline();
384
385     /**
386      * Utility method to add an argument to the command line conditionally
387      * based on the given flag.
388      *
389      * @param b the flag which controls if the argument is added.
390      * @param arg the argument value.
391      */

392     private void addArgIf(boolean b, String JavaDoc arg) {
393         if (b) {
394             cmd.createArgument().setValue(arg);
395         }
396     }
397
398     /**
399      * Utility method to add a Javadoc argument.
400      *
401      * @param key the argument name.
402      * @param value the argument value.
403      */

404     private void addArgIfNotEmpty(String JavaDoc key, String JavaDoc value) {
405         if (value != null && value.length() != 0) {
406             cmd.createArgument().setValue(key);
407             cmd.createArgument().setValue(value);
408         } else {
409             log("Warning: Leaving out empty argument '" + key + "'",
410                 Project.MSG_WARN);
411         }
412     }
413
414     /**
415      * Flag which indicates if the task should fail if there is a
416      * Javadoc error.
417      */

418     private boolean failOnError = false;
419     private Path sourcePath = null;
420     private File JavaDoc destDir = null;
421     private Vector JavaDoc sourceFiles = new Vector JavaDoc();
422     private Vector JavaDoc packageNames = new Vector JavaDoc();
423     private Vector JavaDoc excludePackageNames = new Vector JavaDoc(1);
424     private boolean author = true;
425     private boolean version = true;
426     private DocletInfo doclet = null;
427     private Path classpath = null;
428     private Path bootclasspath = null;
429     private String JavaDoc group = null;
430     private String JavaDoc packageList = null;
431     private Vector JavaDoc links = new Vector JavaDoc();
432     private Vector JavaDoc groups = new Vector JavaDoc();
433     private Vector JavaDoc tags = new Vector JavaDoc();
434     private boolean useDefaultExcludes = true;
435     private Html doctitle = null;
436     private Html header = null;
437     private Html footer = null;
438     private Html bottom = null;
439     private boolean useExternalFile = false;
440     private String JavaDoc source = null;
441     private boolean linksource = false;
442     private boolean breakiterator = false;
443     private String JavaDoc noqualifier;
444     private boolean includeNoSourcePackages = false;
445     private boolean old = false;
446     private String JavaDoc executable = null;
447
448     private ResourceCollectionContainer nestedSourceFiles
449         = new ResourceCollectionContainer();
450     private Vector JavaDoc packageSets = new Vector JavaDoc();
451
452     /**
453      * Work around command line length limit by using an external file
454      * for the sourcefiles.
455      *
456      * @param b true if an external file is to be used.
457      */

458     public void setUseExternalFile(boolean b) {
459         useExternalFile = b;
460     }
461
462     /**
463      * Sets whether default exclusions should be used or not.
464      *
465      * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions
466      * should be used, "false"|"off"|"no" when they
467      * shouldn't be used.
468      */

469     public void setDefaultexcludes(boolean useDefaultExcludes) {
470         this.useDefaultExcludes = useDefaultExcludes;
471     }
472
473     /**
474      * Set the maximum memory to be used by the javadoc process
475      *
476      * @param max a string indicating the maximum memory according to the
477      * JVM conventions (e.g. 128m is 128 Megabytes)
478      */

479     public void setMaxmemory(String JavaDoc max) {
480         cmd.createArgument().setValue("-J-Xmx" + max);
481     }
482
483     /**
484      * Set an additional parameter on the command line
485      *
486      * @param add the additional command line parameter for the javadoc task.
487      */

488     public void setAdditionalparam(String JavaDoc add) {
489         cmd.createArgument().setLine(add);
490     }
491
492     /**
493      * Adds a command-line argument.
494      * @return a command-line argument to configure
495      * @since Ant 1.6
496      */

497     public Commandline.Argument createArg() {
498         return cmd.createArgument();
499     }
500
501     /**
502      * Specify where to find source file
503      *
504      * @param src a Path instance containing the various source directories.
505      */

506     public void setSourcepath(Path src) {
507         if (sourcePath == null) {
508             sourcePath = src;
509         } else {
510             sourcePath.append(src);
511         }
512     }
513
514     /**
515      * Create a path to be configured with the locations of the source
516      * files.
517      *
518      * @return a new Path instance to be configured by the Ant core.
519      */

520     public Path createSourcepath() {
521         if (sourcePath == null) {
522             sourcePath = new Path(getProject());
523         }
524         return sourcePath.createPath();
525     }
526
527     /**
528      * Adds a reference to a CLASSPATH defined elsewhere.
529      *
530      * @param r the reference containing the source path definition.
531      */

532     public void setSourcepathRef(Reference r) {
533         createSourcepath().setRefid(r);
534     }
535
536     /**
537      * Set the directory where the Javadoc output will be generated.
538      *
539      * @param dir the destination directory.
540      */

541     public void setDestdir(File JavaDoc dir) {
542         destDir = dir;
543         cmd.createArgument().setValue("-d");
544         cmd.createArgument().setFile(destDir);
545     }
546
547     /**
548      * Set the list of source files to process.
549      *
550      * @param src a comma separated list of source files.
551      */

552     public void setSourcefiles(String JavaDoc src) {
553         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(src, ",");
554         while (tok.hasMoreTokens()) {
555             String JavaDoc f = tok.nextToken();
556             SourceFile sf = new SourceFile();
557             sf.setFile(getProject().resolveFile(f.trim()));
558             addSource(sf);
559         }
560     }
561
562     /**
563      * Add a single source file.
564      *
565      * @param sf the source file to be processed.
566      */

567     public void addSource(SourceFile sf) {
568         sourceFiles.addElement(sf);
569     }
570
571     /**
572      * Set the package names to be processed.
573      *
574      * @param packages a comma separated list of packages specs
575      * (may be wildcarded).
576      *
577      * @see #addPackage for wildcard information.
578      */

579     public void setPackagenames(String JavaDoc packages) {
580         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(packages, ",");
581         while (tok.hasMoreTokens()) {
582             String JavaDoc p = tok.nextToken();
583             PackageName pn = new PackageName();
584             pn.setName(p);
585             addPackage(pn);
586         }
587     }
588
589     /**
590      * Add a single package to be processed.
591      *
592      * If the package name ends with &quot;.*&quot; the Javadoc task
593      * will find and process all subpackages.
594      *
595      * @param pn the package name, possibly wildcarded.
596      */

597     public void addPackage(PackageName pn) {
598         packageNames.addElement(pn);
599     }
600
601     /**
602      * Set the list of packages to be excluded.
603      *
604      * @param packages a comma separated list of packages to be excluded.
605      * This may not include wildcards.
606      */

607     public void setExcludePackageNames(String JavaDoc packages) {
608         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(packages, ",");
609         while (tok.hasMoreTokens()) {
610             String JavaDoc p = tok.nextToken();
611             PackageName pn = new PackageName();
612             pn.setName(p);
613             addExcludePackage(pn);
614         }
615     }
616
617     /**
618      * Add a package to be excluded from the Javadoc run.
619      *
620      * @param pn the name of the package (wildcards are not permitted).
621      */

622     public void addExcludePackage(PackageName pn) {
623         excludePackageNames.addElement(pn);
624     }
625
626     /**
627      * Specify the file containing the overview to be included in the generated
628      * documentation.
629      *
630      * @param f the file containing the overview.
631      */

632     public void setOverview(File JavaDoc f) {
633         cmd.createArgument().setValue("-overview");
634         cmd.createArgument().setFile(f);
635     }
636
637     /**
638      * Indicate whether only public classes and members are to be included in
639      * the scope processed
640      *
641      * @param b true if scope is to be public.
642      */

643     public void setPublic(boolean b) {
644         addArgIf(b, "-public");
645     }
646
647     /**
648      * Indicate whether only protected and public classes and members are to
649      * be included in the scope processed
650      *
651      * @param b true if scope is to be protected.
652      */

653     public void setProtected(boolean b) {
654         addArgIf(b, "-protected");
655     }
656
657     /**
658      * Indicate whether only package, protected and public classes and
659      * members are to be included in the scope processed
660      *
661      * @param b true if scope is to be package level.
662      */

663     public void setPackage(boolean b) {
664         addArgIf(b, "-package");
665     }
666
667     /**
668      * Indicate whether all classes and
669      * members are to be included in the scope processed
670      *
671      * @param b true if scope is to be private level.
672      */

673     public void setPrivate(boolean b) {
674         addArgIf(b, "-private");
675     }
676
677     /**
678      * Set the scope to be processed. This is an alternative to the
679      * use of the setPublic, setPrivate, etc methods. It gives better build
680      * file control over what scope is processed.
681      *
682      * @param at the scope to be processed.
683      */

684     public void setAccess(AccessType at) {
685         cmd.createArgument().setValue("-" + at.getValue());
686     }
687
688     /**
689      * Set the class that starts the doclet used in generating the
690      * documentation.
691      *
692      * @param docletName the name of the doclet class.
693      */

694     public void setDoclet(String JavaDoc docletName) {
695         if (doclet == null) {
696             doclet = new DocletInfo();
697             doclet.setProject(getProject());
698         }
699         doclet.setName(docletName);
700     }
701
702     /**
703      * Set the classpath used to find the doclet class.
704      *
705      * @param docletPath the doclet classpath.
706      */

707     public void setDocletPath(Path docletPath) {
708         if (doclet == null) {
709             doclet = new DocletInfo();
710             doclet.setProject(getProject());
711         }
712         doclet.setPath(docletPath);
713     }
714
715     /**
716      * Set the classpath used to find the doclet class by reference.
717      *
718      * @param r the reference to the Path instance to use as the doclet
719      * classpath.
720      */

721     public void setDocletPathRef(Reference r) {
722         if (doclet == null) {
723             doclet = new DocletInfo();
724             doclet.setProject(getProject());
725         }
726         doclet.createPath().setRefid(r);
727     }
728
729     /**
730      * Create a doclet to be used in the documentation generation.
731      *
732      * @return a new DocletInfo instance to be configured.
733      */

734     public DocletInfo createDoclet() {
735         if (doclet == null) {
736             doclet = new DocletInfo();
737         }
738         return doclet;
739     }
740
741     /**
742      * Add a taglet
743      *
744      * @param tagletInfo information about the taglet.
745      */

746     public void addTaglet(ExtensionInfo tagletInfo) {
747         tags.addElement(tagletInfo);
748     }
749
750     /**
751      * Indicate whether Javadoc should produce old style (JDK 1.1)
752      * documentation.
753      *
754      * This is not supported by JDK 1.1 and has been phased out in JDK 1.4
755      *
756      * @param b if true attempt to generate old style documentation.
757      */

758     public void setOld(boolean b) {
759         old = b;
760     }
761
762     /**
763      * Set the classpath to be used for this Javadoc run.
764      *
765      * @param path an Ant Path object containing the compilation
766      * classpath.
767      */

768     public void setClasspath(Path path) {
769         if (classpath == null) {
770             classpath = path;
771         } else {
772             classpath.append(path);
773         }
774     }
775
776     /**
777      * Create a Path to be configured with the classpath to use
778      *
779      * @return a new Path instance to be configured with the classpath.
780      */

781     public Path createClasspath() {
782         if (classpath == null) {
783             classpath = new Path(getProject());
784         }
785         return classpath.createPath();
786     }
787
788     /**
789      * Adds a reference to a CLASSPATH defined elsewhere.
790      *
791      * @param r the reference to an instance defining the classpath.
792      */

793     public void setClasspathRef(Reference r) {
794         createClasspath().setRefid(r);
795     }
796
797     /**
798      * Set the boot classpath to use.
799      *
800      * @param path the boot classpath.
801      */

802     public void setBootclasspath(Path path) {
803         if (bootclasspath == null) {
804             bootclasspath = path;
805         } else {
806             bootclasspath.append(path);
807         }
808     }
809
810     /**
811      * Create a Path to be configured with the boot classpath
812      *
813      * @return a new Path instance to be configured with the boot classpath.
814      */

815     public Path createBootclasspath() {
816         if (bootclasspath == null) {
817             bootclasspath = new Path(getProject());
818         }
819         return bootclasspath.createPath();
820     }
821
822     /**
823      * Adds a reference to a CLASSPATH defined elsewhere.
824      *
825      * @param r the reference to an instance defining the bootclasspath.
826      */

827     public void setBootClasspathRef(Reference r) {
828         createBootclasspath().setRefid(r);
829     }
830
831     /**
832      * Set the location of the extensions directories.
833      *
834      * @param path the string version of the path.
835      * @deprecated since 1.5.x.
836      * Use the {@link #setExtdirs(Path)} version.
837      */

838     public void setExtdirs(String JavaDoc path) {
839         cmd.createArgument().setValue("-extdirs");
840         cmd.createArgument().setValue(path);
841     }
842
843     /**
844      * Set the location of the extensions directories.
845      *
846      * @param path a path containing the extension directories.
847      */

848     public void setExtdirs(Path path) {
849         cmd.createArgument().setValue("-extdirs");
850         cmd.createArgument().setPath(path);
851     }
852
853     /**
854      * Run javadoc in verbose mode
855      *
856      * @param b true if operation is to be verbose.
857      */

858     public void setVerbose(boolean b) {
859         addArgIf(b, "-verbose");
860     }
861
862     /**
863      * Set the local to use in documentation generation.
864      *
865      * @param locale the locale to use.
866      */

867     public void setLocale(String JavaDoc locale) {
868         // createArgument(true) is necessary to make sure -locale
869
// is the first argument (required in 1.3+).
870
cmd.createArgument(true).setValue(locale);
871         cmd.createArgument(true).setValue("-locale");
872     }
873
874     /**
875      * Set the encoding name of the source files,
876      *
877      * @param enc the name of the encoding for the source files.
878      */

879     public void setEncoding(String JavaDoc enc) {
880         cmd.createArgument().setValue("-encoding");
881         cmd.createArgument().setValue(enc);
882     }
883
884     /**
885      * Include the version tag in the generated documentation.
886      *
887      * @param b true if the version tag should be included.
888      */

889     public void setVersion(boolean b) {
890         this.version = b;
891     }
892
893     /**
894      * Generate the &quot;use&quot page for each package.
895      *
896      * @param b true if the use page should be generated.
897      */

898     public void setUse(boolean b) {
899         addArgIf(b, "-use");
900     }
901
902
903     /**
904      * Include the author tag in the generated documentation.
905      *
906      * @param b true if the author tag should be included.
907      */

908     public void setAuthor(boolean b) {
909         author = b;
910     }
911
912     /**
913      * Generate a split index
914      *
915      * @param b true if the index should be split into a file per letter.
916      */

917     public void setSplitindex(boolean b) {
918         addArgIf(b, "-splitindex");
919     }
920
921     /**
922      * Set the title to be placed in the HTML &lt;title&gt; tag of the
923      * generated documentation.
924      *
925      * @param title the window title to use.
926      */

927     public void setWindowtitle(String JavaDoc title) {
928         addArgIfNotEmpty("-windowtitle", title);
929     }
930
931     /**
932      * Set the title of the generated overview page.
933      *
934      * @param doctitle the Document title.
935      */

936     public void setDoctitle(String JavaDoc doctitle) {
937         Html h = new Html();
938         h.addText(doctitle);
939         addDoctitle(h);
940     }
941
942     /**
943      * Add a document title to use for the overview page.
944      *
945      * @param text the HTML element containing the document title.
946      */

947     public void addDoctitle(Html text) {
948         doctitle = text;
949     }
950
951     /**
952      * Set the header text to be placed at the top of each output file.
953      *
954      * @param header the header text
955      */

956     public void setHeader(String JavaDoc header) {
957         Html h = new Html();
958         h.addText(header);
959         addHeader(h);
960     }
961
962     /**
963      * Set the header text to be placed at the top of each output file.
964      *
965      * @param text the header text
966      */

967     public void addHeader(Html text) {
968         header = text;
969     }
970
971     /**
972      * Set the footer text to be placed at the bottom of each output file.
973      *
974      * @param footer the footer text.
975      */

976     public void setFooter(String JavaDoc footer) {
977         Html h = new Html();
978         h.addText(footer);
979         addFooter(h);
980     }
981
982     /**
983      * Set the footer text to be placed at the bottom of each output file.
984      *
985      * @param text the footer text.
986      */

987     public void addFooter(Html text) {
988         footer = text;
989     }
990
991     /**
992      * Set the text to be placed at the bottom of each output file.
993      *
994      * @param bottom the bottom text.
995      */

996     public void setBottom(String JavaDoc bottom) {
997         Html h = new Html();
998         h.addText(bottom);
999         addBottom(h);
1000    }
1001
1002    /**
1003     * Set the text to be placed at the bottom of each output file.
1004     *
1005     * @param text the bottom text.
1006     */

1007    public void addBottom(Html text) {
1008        bottom = text;
1009    }
1010
1011    /**
1012     * Link to docs at "url" using package list at "url2"
1013     * - separate the URLs by using a space character.
1014     *
1015     * @param src the offline link specification (url and package list)
1016     */

1017    public void setLinkoffline(String JavaDoc src) {
1018        LinkArgument le = createLink();
1019        le.setOffline(true);
1020        String JavaDoc linkOfflineError = "The linkoffline attribute must include"
1021            + " a URL and a package-list file location separated by a"
1022            + " space";
1023        if (src.trim().length() == 0) {
1024            throw new BuildException(linkOfflineError);
1025        }
1026        StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(src, " ", false);
1027        le.setHref(tok.nextToken());
1028
1029        if (!tok.hasMoreTokens()) {
1030            throw new BuildException(linkOfflineError);
1031        }
1032        le.setPackagelistLoc(getProject().resolveFile(tok.nextToken()));
1033    }
1034
1035    /**
1036     * Group specified packages together in overview page.
1037     *
1038     * @param src the group packages - a command separated list of group specs,
1039     * each one being a group name and package specification separated
1040     * by a space.
1041     */

1042    public void setGroup(String JavaDoc src) {
1043        group = src;
1044    }
1045
1046    /**
1047     * Create links to Javadoc output at the given URL.
1048     * @param src the URL to link to
1049     */

1050    public void setLink(String JavaDoc src) {
1051        createLink().setHref(src);
1052    }
1053
1054    /**
1055     * Control deprecation infromation
1056     *
1057     * @param b If true, do not include deprecated information.
1058     */

1059    public void setNodeprecated(boolean b) {
1060        addArgIf(b, "-nodeprecated");
1061    }
1062
1063    /**
1064     * Control deprecated list generation
1065     *
1066     * @param b if true, do not generate deprecated list.
1067     */

1068    public void setNodeprecatedlist(boolean b) {
1069        addArgIf(b, "-nodeprecatedlist");
1070    }
1071
1072    /**
1073     * Control class tree generation.
1074     *
1075     * @param b if true, do not generate class hierarchy.
1076     */

1077    public void setNotree(boolean b) {
1078        addArgIf(b, "-notree");
1079    }
1080
1081    /**
1082     * Control generation of index.
1083     *
1084     * @param b if true, do not generate index.
1085     */

1086    public void setNoindex(boolean b) {
1087        addArgIf(b, "-noindex");
1088    }
1089
1090    /**
1091     * Control generation of help link.
1092     *
1093     * @param b if true, do not generate help link
1094     */

1095    public void setNohelp(boolean b) {
1096        addArgIf(b, "-nohelp");
1097    }
1098
1099    /**
1100     * Control generation of the navigation bar.
1101     *
1102     * @param b if true, do not generate navigation bar.
1103     */

1104    public void setNonavbar(boolean b) {
1105        addArgIf(b, "-nonavbar");
1106    }
1107
1108    /**
1109     * Control warnings about serial tag.
1110     *
1111     * @param b if true, generate warning about the serial tag.
1112     */

1113    public void setSerialwarn(boolean b) {
1114        addArgIf(b, "-serialwarn");
1115    }
1116
1117    /**
1118     * Specifies the CSS stylesheet file to use.
1119     *
1120     * @param f the file with the CSS to use.
1121     */

1122    public void setStylesheetfile(File JavaDoc f) {
1123        cmd.createArgument().setValue("-stylesheetfile");
1124        cmd.createArgument().setFile(f);
1125    }
1126
1127    /**
1128     * Specifies the HTML help file to use.
1129     *
1130     * @param f the file containing help content.
1131     */

1132    public void setHelpfile(File JavaDoc f) {
1133        cmd.createArgument().setValue("-helpfile");
1134        cmd.createArgument().setFile(f);
1135    }
1136
1137    /**
1138     * Output file encoding name.
1139     *
1140     * @param enc name of the encoding to use.
1141     */

1142    public void setDocencoding(String JavaDoc enc) {
1143        cmd.createArgument().setValue("-docencoding");
1144        cmd.createArgument().setValue(enc);
1145    }
1146
1147    /**
1148     * The name of a file containing the packages to process.
1149     *
1150     * @param src the file containing the package list.
1151     */

1152    public void setPackageList(String JavaDoc src) {
1153        packageList = src;
1154    }
1155
1156    /**
1157     * Create link to Javadoc output at the given URL.
1158     *
1159     * @return link argument to configure
1160     */

1161    public LinkArgument createLink() {
1162        LinkArgument la = new LinkArgument();
1163        links.addElement(la);
1164        return la;
1165    }
1166
1167    /**
1168     * Represents a link triplet (href, whether link is offline,
1169     * location of the package list if off line)
1170     */

1171    public class LinkArgument {
1172        private String JavaDoc href;
1173        private boolean offline = false;
1174        private File JavaDoc packagelistLoc;
1175        private boolean resolveLink = false;
1176
1177        /** Constructor for LinkArguement */
1178        public LinkArgument() {
1179            //empty
1180
}
1181
1182        /**
1183         * Set the href attribute.
1184         * @param hr a <code>String</code> value
1185         */

1186        public void setHref(String JavaDoc hr) {
1187            href = hr;
1188        }
1189
1190        /**
1191         * Get the href attribute.
1192         * @return the href attribute.
1193         */

1194        public String JavaDoc getHref() {
1195            return href;
1196        }
1197
1198        /**
1199         * Set the packetlist location attribute.
1200         * @param src a <code>File</code> value
1201         */

1202        public void setPackagelistLoc(File JavaDoc src) {
1203            packagelistLoc = src;
1204        }
1205
1206        /**
1207         * Get the packetList location attribute.
1208         * @return the packetList location attribute.
1209         */

1210        public File JavaDoc getPackagelistLoc() {
1211            return packagelistLoc;
1212        }
1213
1214        /**
1215         * Set the offline attribute.
1216         * @param offline a <code>boolean</code> value
1217         */

1218        public void setOffline(boolean offline) {
1219            this.offline = offline;
1220        }
1221
1222        /**
1223         * Get the linkOffline attribute.
1224         * @return the linkOffline attribute.
1225         */

1226        public boolean isLinkOffline() {
1227            return offline;
1228        }
1229
1230        /**
1231         * Sets whether Ant should resolve the link attribute relative
1232         * to the current basedir.
1233         * @param resolve a <code>boolean</code> value
1234         */

1235        public void setResolveLink(boolean resolve) {
1236            this.resolveLink = resolve;
1237        }
1238
1239        /**
1240         * should Ant resolve the link attribute relative to the
1241         * current basedir?
1242         * @return the resolveLink attribute.
1243         */

1244        public boolean shouldResolveLink() {
1245            return resolveLink;
1246        }
1247
1248    }
1249
1250    /**
1251     * Creates and adds a -tag argument. This is used to specify
1252     * custom tags. This argument is only available for Javadoc 1.4,
1253     * and will generate a verbose message (and then be ignored)
1254     * when run on Java versions below 1.4.
1255     * @return tag argument to be configured
1256     */

1257    public TagArgument createTag() {
1258        TagArgument ta = new TagArgument();
1259        tags.addElement (ta);
1260        return ta;
1261    }
1262
1263    /**
1264     * Scope element verbose names. (Defined here as fields
1265     * cannot be static in inner classes.) The first letter
1266     * from each element is used to build up the scope string.
1267     */

1268    static final String JavaDoc[] SCOPE_ELEMENTS = {
1269        "overview", "packages", "types", "constructors",
1270        "methods", "fields"
1271    };
1272
1273    /**
1274     * Class representing a -tag argument.
1275     */

1276    public class TagArgument extends FileSet {
1277        /** Name of the tag. */
1278        private String JavaDoc name = null;
1279        /** Whether or not the tag is enabled. */
1280        private boolean enabled = true;
1281        /**
1282         * Scope string of the tag. This will form the middle
1283         * argument of the -tag parameter when the tag is enabled
1284         * (with an X prepended for and is parsed from human-readable form.
1285         */

1286        private String JavaDoc scope = "a";
1287
1288        /** Sole constructor. */
1289        public TagArgument () {
1290            //empty
1291
}
1292
1293        /**
1294         * Sets the name of the tag.
1295         *
1296         * @param name The name of the tag.
1297         * Must not be <code>null</code> or empty.
1298         */

1299        public void setName (String JavaDoc name) {
1300            this.name = name;
1301        }
1302
1303        /**
1304         * Sets the scope of the tag. This is in comma-separated
1305         * form, with each element being one of "all" (the default),
1306         * "overview", "packages", "types", "constructors", "methods",
1307         * "fields". The elements are treated in a case-insensitive
1308         * manner.
1309         *
1310         * @param verboseScope The scope of the tag.
1311         * Must not be <code>null</code>,
1312         * should not be empty.
1313         *
1314         * @exception BuildException if all is specified along with
1315         * other elements, if any elements are repeated, if no
1316         * elements are specified, or if any unrecognised elements are
1317         * specified.
1318         */

1319        public void setScope (String JavaDoc verboseScope) throws BuildException {
1320            verboseScope = verboseScope.toLowerCase(Locale.US);
1321
1322            boolean[] elements = new boolean[SCOPE_ELEMENTS.length];
1323
1324            boolean gotAll = false;
1325            boolean gotNotAll = false;
1326
1327            // Go through the tokens one at a time, updating the
1328
// elements array and issuing warnings where appropriate.
1329
StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc (verboseScope, ",");
1330            while (tok.hasMoreTokens()) {
1331                String JavaDoc next = tok.nextToken().trim();
1332                if (next.equals("all")) {
1333                    if (gotAll) {
1334                        getProject().log ("Repeated tag scope element: all",
1335                                          Project.MSG_VERBOSE);
1336                    }
1337                    gotAll = true;
1338                } else {
1339                    int i;
1340                    for (i = 0; i < SCOPE_ELEMENTS.length; i++) {
1341                        if (next.equals (SCOPE_ELEMENTS[i])) {
1342                            break;
1343                        }
1344                    }
1345                    if (i == SCOPE_ELEMENTS.length) {
1346                        throw new BuildException ("Unrecognised scope element: "
1347                                                  + next);
1348                    } else {
1349                        if (elements[i]) {
1350                            getProject().log ("Repeated tag scope element: "
1351                                              + next, Project.MSG_VERBOSE);
1352                        }
1353                        elements[i] = true;
1354                        gotNotAll = true;
1355                    }
1356                }
1357            }
1358
1359            if (gotNotAll && gotAll) {
1360                throw new BuildException ("Mixture of \"all\" and other scope "
1361                                          + "elements in tag parameter.");
1362            }
1363            if (!gotNotAll && !gotAll) {
1364                throw new BuildException ("No scope elements specified in tag "
1365                                          + "parameter.");
1366            }
1367            if (gotAll) {
1368                this.scope = "a";
1369            } else {
1370                StringBuffer JavaDoc buff = new StringBuffer JavaDoc (elements.length);
1371                for (int i = 0; i < elements.length; i++) {
1372                    if (elements[i]) {
1373                        buff.append (SCOPE_ELEMENTS[i].charAt(0));
1374                    }
1375                }
1376                this.scope = buff.toString();
1377            }
1378        }
1379
1380        /**
1381         * Sets whether or not the tag is enabled.
1382         *
1383         * @param enabled Whether or not this tag is enabled.
1384         */

1385        public void setEnabled (boolean enabled) {
1386            this.enabled = enabled;
1387        }
1388
1389        /**
1390         * Returns the -tag parameter this argument represented.
1391         * @return the -tag parameter as a string
1392         * @exception BuildException if either the name or description
1393         * is <code>null</code> or empty.
1394         */

1395        public String JavaDoc getParameter() throws BuildException {
1396            if (name == null || name.equals("")) {
1397                throw new BuildException ("No name specified for custom tag.");
1398            }
1399            if (getDescription() != null) {
1400                return name + ":" + (enabled ? "" : "X")
1401                    + scope + ":" + getDescription();
1402            } else {
1403                return name + ":" + (enabled ? "" : "X")
1404                    + scope + ":" + name;
1405            }
1406        }
1407    }
1408
1409    /**
1410     * Separates packages on the overview page into whatever
1411     * groups you specify, one group per table.
1412     * @return a group argument to be configured
1413     */

1414    public GroupArgument createGroup() {
1415        GroupArgument ga = new GroupArgument();
1416        groups.addElement(ga);
1417        return ga;
1418    }
1419
1420
1421    /**
1422     * A class corresponding to the group nested element.
1423     */

1424    public class GroupArgument {
1425        private Html title;
1426        private Vector JavaDoc packages = new Vector JavaDoc();
1427
1428        /** Constructor for GroupArgument */
1429        public GroupArgument() {
1430            //empty
1431
}
1432
1433        /**
1434         * Set the title attribute using a string.
1435         * @param src a <code>String</code> value
1436         */

1437        public void setTitle(String JavaDoc src) {
1438            Html h = new Html();
1439            h.addText(src);
1440            addTitle(h);
1441        }
1442        /**
1443         * Set the title attribute using a nested Html value.
1444         * @param text a <code>Html</code> value
1445         */

1446        public void addTitle(Html text) {
1447            title = text;
1448        }
1449
1450        /**
1451         * Get the title.
1452         * @return the title
1453         */

1454        public String JavaDoc getTitle() {
1455            return title != null ? title.getText() : null;
1456        }
1457
1458        /**
1459         * Set the packages to Javadoc on.
1460         * @param src a comma separated list of packages
1461         */

1462        public void setPackages(String JavaDoc src) {
1463            StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(src, ",");
1464            while (tok.hasMoreTokens()) {
1465                String JavaDoc p = tok.nextToken();
1466                PackageName pn = new PackageName();
1467                pn.setName(p);
1468                addPackage(pn);
1469            }
1470        }
1471        /**
1472         * Add a package nested element.
1473         * @param pn a nested element specifing the package.
1474         */

1475        public void addPackage(PackageName pn) {
1476            packages.addElement(pn);
1477        }
1478
1479        /**
1480         * Get the packages as a collon separated list.
1481         * @return the packages as a string
1482         */

1483        public String JavaDoc getPackages() {
1484            StringBuffer JavaDoc p = new StringBuffer JavaDoc();
1485            for (int i = 0; i < packages.size(); i++) {
1486                if (i > 0) {
1487                    p.append(":");
1488                }
1489                p.append(packages.elementAt(i).toString());
1490            }
1491            return p.toString();
1492        }
1493    }
1494
1495    /**
1496     * Charset for cross-platform viewing of generated documentation.
1497     * @param src the name of the charset
1498     */

1499    public void setCharset(String JavaDoc src) {
1500        this.addArgIfNotEmpty("-charset", src);
1501    }
1502
1503    /**
1504     * Should the build process fail if Javadoc fails (as indicated by
1505     * a non zero return code)?
1506     *
1507     * <p>Default is false.</p>
1508     * @param b a <code>boolean</code> value
1509     */

1510    public void setFailonerror(boolean b) {
1511        failOnError = b;
1512    }
1513
1514    /**
1515     * Enables the -source switch, will be ignored if Javadoc is not
1516     * the 1.4 version.
1517     * @param source a <code>String</code> value
1518     * @since Ant 1.5
1519     */

1520    public void setSource(String JavaDoc source) {
1521        this.source = source;
1522    }
1523
1524    /**
1525     * Sets the actual executable command to invoke, instead of the binary
1526     * <code>javadoc</code> found in Ant's JDK.
1527     * @param executable the command to invoke.
1528     * @since Ant 1.6.3
1529     */

1530    public void setExecutable(String JavaDoc executable) {
1531        this.executable = executable;
1532    }
1533
1534    /**
1535     * Adds a packageset.
1536     *
1537     * <p>All included directories will be translated into package
1538     * names be converting the directory separator into dots.</p>
1539     * @param packageSet a directory set
1540     * @since 1.5
1541     */

1542    public void addPackageset(DirSet packageSet) {
1543        packageSets.addElement(packageSet);
1544    }
1545
1546    /**
1547     * Adds a fileset.
1548     *
1549     * <p>All included files will be added as sourcefiles. The task
1550     * will automatically add
1551     * <code>includes=&quot;**&#47;*.java&quot;</code> to the
1552     * fileset.</p>
1553     * @param fs a file set
1554     * @since 1.5
1555     */

1556    public void addFileset(FileSet fs) {
1557        createSourceFiles().add(fs);
1558    }
1559
1560    /**
1561     * Adds a container for resource collections.
1562     *
1563     * <p>All included files will be added as sourcefiles.</p>
1564     * @return the source files to configure.
1565     * @since 1.7
1566     */

1567    public ResourceCollectionContainer createSourceFiles() {
1568        return nestedSourceFiles;
1569    }
1570
1571    /**
1572     * Enables the -linksource switch, will be ignored if Javadoc is not
1573     * the 1.4 version. Default is false
1574     * @param b a <code>String</code> value
1575     * @since Ant 1.6
1576     */

1577    public void setLinksource(boolean b) {
1578        this.linksource = b;
1579    }
1580
1581    /**
1582     * Enables the -linksource switch, will be ignored if Javadoc is not
1583     * the 1.4 version. Default is false
1584     * @param b a <code>String</code> value
1585     * @since Ant 1.6
1586     */

1587    public void setBreakiterator(boolean b) {
1588        this.breakiterator = b;
1589    }
1590
1591    /**
1592     * Enables the -noqualifier switch, will be ignored if Javadoc is not
1593     * the 1.4 version.
1594     * @param noqualifier the parameter to the -noqualifier switch
1595     * @since Ant 1.6
1596     */

1597    public void setNoqualifier(String JavaDoc noqualifier) {
1598        this.noqualifier = noqualifier;
1599    }
1600
1601    /**
1602     * If set to true, Ant will also accept packages that only hold
1603     * package.html files but no Java sources.
1604     * @param b a <code>boolean</code> value.
1605     * @since Ant 1.6.3
1606     */

1607    public void setIncludeNoSourcePackages(boolean b) {
1608        this.includeNoSourcePackages = b;
1609    }
1610
1611    /**
1612     * Execute the task.
1613     * @throws BuildException on error
1614     */

1615    public void execute() throws BuildException {
1616        if ("javadoc2".equals(getTaskType())) {
1617            log("Warning: the task name <javadoc2> is deprecated. Use <javadoc> instead.",
1618                Project.MSG_WARN);
1619        }
1620
1621        // Whether *this VM* is 1.4+ (but also check executable != null).
1622
boolean javadoc4 =
1623            !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)
1624            && !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_3);
1625        boolean javadoc5 = javadoc4
1626            && !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_4);
1627
1628        Vector JavaDoc packagesToDoc = new Vector JavaDoc();
1629        Path sourceDirs = new Path(getProject());
1630
1631        if (packageList != null && sourcePath == null) {
1632            String JavaDoc msg = "sourcePath attribute must be set when "
1633                + "specifying packagelist.";
1634            throw new BuildException(msg);
1635        }
1636
1637        if (sourcePath != null) {
1638            sourceDirs.addExisting(sourcePath);
1639        }
1640
1641        parsePackages(packagesToDoc, sourceDirs);
1642
1643        if (packagesToDoc.size() != 0 && sourceDirs.size() == 0) {
1644            String JavaDoc msg = "sourcePath attribute must be set when "
1645                + "specifying package names.";
1646            throw new BuildException(msg);
1647        }
1648
1649        Vector JavaDoc sourceFilesToDoc = (Vector JavaDoc) sourceFiles.clone();
1650        addSourceFiles(sourceFilesToDoc);
1651
1652        if (packageList == null && packagesToDoc.size() == 0
1653            && sourceFilesToDoc.size() == 0) {
1654            throw new BuildException("No source files and no packages have "
1655                                     + "been specified.");
1656        }
1657
1658        log("Generating Javadoc", Project.MSG_INFO);
1659
1660        Commandline toExecute = (Commandline) cmd.clone();
1661        if (executable != null) {
1662            toExecute.setExecutable(executable);
1663        } else {
1664            toExecute.setExecutable(JavaEnvUtils.getJdkExecutable("javadoc"));
1665        }
1666
1667        // ------------------------------------------ general Javadoc arguments
1668
if (doctitle != null) {
1669            toExecute.createArgument().setValue("-doctitle");
1670            toExecute.createArgument().setValue(expand(doctitle.getText()));
1671        }
1672        if (header != null) {
1673            toExecute.createArgument().setValue("-header");
1674            toExecute.createArgument().setValue(expand(header.getText()));
1675        }
1676        if (footer != null) {
1677            toExecute.createArgument().setValue("-footer");
1678            toExecute.createArgument().setValue(expand(footer.getText()));
1679        }
1680        if (bottom != null) {
1681            toExecute.createArgument().setValue("-bottom");
1682            toExecute.createArgument().setValue(expand(bottom.getText()));
1683        }
1684
1685        if (classpath == null) {
1686            classpath = (new Path(getProject())).concatSystemClasspath("last");
1687        } else {
1688            classpath = classpath.concatSystemClasspath("ignore");
1689        }
1690
1691        if (classpath.size() > 0) {
1692            toExecute.createArgument().setValue("-classpath");
1693            toExecute.createArgument().setPath(classpath);
1694        }
1695        if (sourceDirs.size() > 0) {
1696            toExecute.createArgument().setValue("-sourcepath");
1697            toExecute.createArgument().setPath(sourceDirs);
1698        }
1699
1700        if (version && doclet == null) {
1701            toExecute.createArgument().setValue("-version");
1702        }
1703        if (author && doclet == null) {
1704            toExecute.createArgument().setValue("-author");
1705        }
1706
1707        if (doclet == null && destDir == null) {
1708            throw new BuildException("destdir attribute must be set!");
1709        }
1710
1711        // ---------------------------- javadoc2 arguments for default doclet
1712

1713        if (doclet != null) {
1714            if (doclet.getName() == null) {
1715                throw new BuildException("The doclet name must be "
1716                                         + "specified.", getLocation());
1717            } else {
1718                toExecute.createArgument().setValue("-doclet");
1719                toExecute.createArgument().setValue(doclet.getName());
1720                if (doclet.getPath() != null) {
1721                    Path docletPath
1722                        = doclet.getPath().concatSystemClasspath("ignore");
1723                    if (docletPath.size() != 0) {
1724                        toExecute.createArgument().setValue("-docletpath");
1725                        toExecute.createArgument().setPath(docletPath);
1726                    }
1727                }
1728                for (Enumeration JavaDoc e = doclet.getParams();
1729                     e.hasMoreElements();) {
1730                    DocletParam param = (DocletParam) e.nextElement();
1731                    if (param.getName() == null) {
1732                        throw new BuildException("Doclet parameters must "
1733                                                 + "have a name");
1734                    }
1735
1736                    toExecute.createArgument().setValue(param.getName());
1737                    if (param.getValue() != null) {
1738                        toExecute.createArgument()
1739                            .setValue(param.getValue());
1740                    }
1741                }
1742            }
1743        }
1744        Path bcp = new Path(getProject());
1745        if (bootclasspath != null) {
1746            bcp.append(bootclasspath);
1747        }
1748        bcp = bcp.concatSystemBootClasspath("ignore");
1749        if (bcp.size() > 0) {
1750            toExecute.createArgument().setValue("-bootclasspath");
1751            toExecute.createArgument().setPath(bcp);
1752        }
1753
1754        // add the links arguments
1755
if (links.size() != 0) {
1756            for (Enumeration JavaDoc e = links.elements(); e.hasMoreElements();) {
1757                LinkArgument la = (LinkArgument) e.nextElement();
1758
1759                if (la.getHref() == null || la.getHref().length() == 0) {
1760                    log("No href was given for the link - skipping",
1761                        Project.MSG_VERBOSE);
1762                    continue;
1763                }
1764                String JavaDoc link = null;
1765                if (la.shouldResolveLink()) {
1766                    File JavaDoc hrefAsFile =
1767                        getProject().resolveFile(la.getHref());
1768                    if (hrefAsFile.exists()) {
1769                        try {
1770                            link = FILE_UTILS.getFileURL(hrefAsFile)
1771                                .toExternalForm();
1772                        } catch (MalformedURLException JavaDoc ex) {
1773                            // should be impossible
1774
log("Warning: link location was invalid "
1775                                + hrefAsFile, Project.MSG_WARN);
1776                        }
1777                    }
1778                }
1779                if (link == null) {
1780                    // is the href a valid URL
1781
try {
1782                        URL JavaDoc base = new URL JavaDoc("file://.");
1783                        new URL JavaDoc(base, la.getHref());
1784                        link = la.getHref();
1785                    } catch (MalformedURLException JavaDoc mue) {
1786                        // ok - just skip
1787
log("Link href \"" + la.getHref()
1788                            + "\" is not a valid url - skipping link",
1789                            Project.MSG_WARN);
1790                        continue;
1791                    }
1792                }
1793
1794                if (la.isLinkOffline()) {
1795                    File JavaDoc packageListLocation = la.getPackagelistLoc();
1796                    if (packageListLocation == null) {
1797                        throw new BuildException("The package list"
1798                                                 + " location for link "
1799                                                 + la.getHref()
1800                                                 + " must be provided "
1801                                                 + "because the link is "
1802                                                 + "offline");
1803                    }
1804                    File JavaDoc packageListFile =
1805                        new File JavaDoc(packageListLocation, "package-list");
1806                    if (packageListFile.exists()) {
1807                        try {
1808                            String JavaDoc packageListURL =
1809                                FILE_UTILS.getFileURL(packageListLocation)
1810                                .toExternalForm();
1811                            toExecute.createArgument()
1812                                .setValue("-linkoffline");
1813                            toExecute.createArgument()
1814                                .setValue(link);
1815                            toExecute.createArgument()
1816                                .setValue(packageListURL);
1817                        } catch (MalformedURLException JavaDoc ex) {
1818                            log("Warning: Package list location was "
1819                                + "invalid " + packageListLocation,
1820                                Project.MSG_WARN);
1821                        }
1822                    } else {
1823                        log("Warning: No package list was found at "
1824                            + packageListLocation, Project.MSG_VERBOSE);
1825                    }
1826                } else {
1827                    toExecute.createArgument().setValue("-link");
1828                    toExecute.createArgument().setValue(link);
1829                }
1830            }
1831        }
1832
1833        // add the single group arguments
1834
// Javadoc 1.2 rules:
1835
// Multiple -group args allowed.
1836
// Each arg includes 3 strings: -group [name] [packagelist].
1837
// Elements in [packagelist] are colon-delimited.
1838
// An element in [packagelist] may end with the * wildcard.
1839

1840        // Ant javadoc task rules for group attribute:
1841
// Args are comma-delimited.
1842
// Each arg is 2 space-delimited strings.
1843
// E.g., group="XSLT_Packages org.apache.xalan.xslt*,
1844
// XPath_Packages org.apache.xalan.xpath*"
1845
if (group != null) {
1846            StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(group, ",", false);
1847            while (tok.hasMoreTokens()) {
1848                String JavaDoc grp = tok.nextToken().trim();
1849                int space = grp.indexOf(" ");
1850                if (space > 0) {
1851                    String JavaDoc name = grp.substring(0, space);
1852                    String JavaDoc pkgList = grp.substring(space + 1);
1853                    toExecute.createArgument().setValue("-group");
1854                    toExecute.createArgument().setValue(name);
1855                    toExecute.createArgument().setValue(pkgList);
1856                }
1857            }
1858        }
1859
1860        // add the group arguments
1861
if (groups.size() != 0) {
1862            for (Enumeration JavaDoc e = groups.elements(); e.hasMoreElements();) {
1863                GroupArgument ga = (GroupArgument) e.nextElement();
1864                String JavaDoc title = ga.getTitle();
1865                String JavaDoc packages = ga.getPackages();
1866                if (title == null || packages == null) {
1867                    throw new BuildException("The title and packages must "
1868                                             + "be specified for group "
1869                                             + "elements.");
1870                }
1871                toExecute.createArgument().setValue("-group");
1872                toExecute.createArgument().setValue(expand(title));
1873                toExecute.createArgument().setValue(packages);
1874            }
1875        }
1876
1877        // Javadoc 1.4 parameters
1878
if (javadoc4 || executable != null) {
1879            for (Enumeration JavaDoc e = tags.elements(); e.hasMoreElements();) {
1880                Object JavaDoc element = e.nextElement();
1881                if (element instanceof TagArgument) {
1882                    TagArgument ta = (TagArgument) element;
1883                    File JavaDoc tagDir = ta.getDir(getProject());
1884                    if (tagDir == null) {
1885                        // The tag element is not used as a fileset,
1886
// but specifies the tag directly.
1887
toExecute.createArgument().setValue ("-tag");
1888                        toExecute.createArgument()
1889                            .setValue (ta.getParameter());
1890                    } else {
1891                        // The tag element is used as a
1892
// fileset. Parse all the files and create
1893
// -tag arguments.
1894
DirectoryScanner tagDefScanner =
1895                            ta.getDirectoryScanner(getProject());
1896                        String JavaDoc[] files = tagDefScanner.getIncludedFiles();
1897                        for (int i = 0; i < files.length; i++) {
1898                            File JavaDoc tagDefFile = new File JavaDoc(tagDir, files[i]);
1899                            try {
1900                                BufferedReader JavaDoc in
1901                                    = new BufferedReader JavaDoc(
1902                                          new FileReader JavaDoc(tagDefFile)
1903                                          );
1904                                String JavaDoc line = null;
1905                                while ((line = in.readLine()) != null) {
1906                                    toExecute.createArgument()
1907                                        .setValue("-tag");
1908                                    toExecute.createArgument()
1909                                        .setValue(line);
1910                                }
1911                                in.close();
1912                            } catch (IOException JavaDoc ioe) {
1913                                throw new BuildException("Couldn't read "
1914                                    + " tag file from "
1915                                    + tagDefFile.getAbsolutePath(), ioe);
1916                            }
1917                        }
1918                    }
1919                } else {
1920                    ExtensionInfo tagletInfo = (ExtensionInfo) element;
1921                    toExecute.createArgument().setValue("-taglet");
1922                    toExecute.createArgument().setValue(tagletInfo
1923                                                        .getName());
1924                    if (tagletInfo.getPath() != null) {
1925                        Path tagletPath = tagletInfo.getPath()
1926                            .concatSystemClasspath("ignore");
1927                        if (tagletPath.size() != 0) {
1928                            toExecute.createArgument()
1929                                .setValue("-tagletpath");
1930                            toExecute.createArgument().setPath(tagletPath);
1931                        }
1932                    }
1933                }
1934            }
1935
1936            String JavaDoc sourceArg = source != null ? source
1937                : getProject().getProperty(MagicNames.BUILD_JAVAC_SOURCE);
1938            if (sourceArg != null) {
1939                toExecute.createArgument().setValue("-source");
1940                toExecute.createArgument().setValue(sourceArg);
1941            }
1942
1943            if (linksource && doclet == null) {
1944                toExecute.createArgument().setValue("-linksource");
1945            }
1946            if (breakiterator && (doclet == null || javadoc5)) {
1947                toExecute.createArgument().setValue("-breakiterator");
1948            }
1949            if (noqualifier != null && doclet == null) {
1950                toExecute.createArgument().setValue("-noqualifier");
1951                toExecute.createArgument().setValue(noqualifier);
1952            }
1953        } else {
1954            // Not 1.4+.
1955
if (!tags.isEmpty()) {
1956                log("-tag and -taglet options not supported on Javadoc < 1.4",
1957                     Project.MSG_VERBOSE);
1958            }
1959            if (source != null) {
1960                log("-source option not supported on Javadoc < 1.4",
1961                     Project.MSG_VERBOSE);
1962            }
1963            if (linksource) {
1964                log("-linksource option not supported on Javadoc < 1.4",
1965                     Project.MSG_VERBOSE);
1966            }
1967            if (breakiterator) {
1968                log("-breakiterator option not supported on Javadoc < 1.4",
1969                     Project.MSG_VERBOSE);
1970            }
1971            if (noqualifier != null) {
1972                log("-noqualifier option not supported on Javadoc < 1.4",
1973                     Project.MSG_VERBOSE);
1974            }
1975        }
1976        // Javadoc 1.2/1.3 parameters:
1977
if (!javadoc4 || executable != null) {
1978            if (old) {
1979                toExecute.createArgument().setValue("-1.1");
1980            }
1981        } else {
1982            if (old) {
1983                log("Javadoc 1.4 doesn't support the -1.1 switch anymore",
1984                    Project.MSG_WARN);
1985            }
1986        }
1987        // If using an external file, write the command line options to it
1988
if (useExternalFile && javadoc4) {
1989            writeExternalArgs(toExecute);
1990        }
1991
1992        File JavaDoc tmpList = null;
1993        PrintWriter JavaDoc srcListWriter = null;
1994
1995        try {
1996
1997            /**
1998             * Write sourcefiles and package names to a temporary file
1999             * if requested.
2000             */

2001            if (useExternalFile) {
2002                if (tmpList == null) {
2003                    tmpList = FILE_UTILS.createTempFile("javadoc", "", null);
2004                    tmpList.deleteOnExit();
2005                    toExecute.createArgument()
2006                        .setValue("@" + tmpList.getAbsolutePath());
2007                }
2008                srcListWriter = new PrintWriter JavaDoc(
2009                                    new FileWriter JavaDoc(tmpList.getAbsolutePath(),
2010                                                   true));
2011            }
2012
2013            Enumeration JavaDoc e = packagesToDoc.elements();
2014            while (e.hasMoreElements()) {
2015                String JavaDoc packageName = (String JavaDoc) e.nextElement();
2016                if (useExternalFile) {
2017                    srcListWriter.println(packageName);
2018                } else {
2019                    toExecute.createArgument().setValue(packageName);
2020                }
2021            }
2022
2023            e = sourceFilesToDoc.elements();
2024            while (e.hasMoreElements()) {
2025                SourceFile sf = (SourceFile) e.nextElement();
2026                String JavaDoc sourceFileName = sf.getFile().getAbsolutePath();
2027                if (useExternalFile) {
2028                    // XXX what is the following doing?
2029
// should it run if !javadoc4 && executable != null?
2030
if (javadoc4 && sourceFileName.indexOf(" ") > -1) {
2031                        String JavaDoc name = sourceFileName;
2032                        if (File.separatorChar == '\\') {
2033                            name = sourceFileName.replace(File.separatorChar, '/');
2034                        }
2035                        srcListWriter.println("\"" + name + "\"");
2036                    } else {
2037                        srcListWriter.println(sourceFileName);
2038                    }
2039                } else {
2040                    toExecute.createArgument().setValue(sourceFileName);
2041                }
2042            }
2043
2044        } catch (IOException JavaDoc e) {
2045            tmpList.delete();
2046            throw new BuildException("Error creating temporary file",
2047                                     e, getLocation());
2048        } finally {
2049            if (srcListWriter != null) {
2050                srcListWriter.close();
2051            }
2052        }
2053
2054        if (packageList != null) {
2055            toExecute.createArgument().setValue("@" + packageList);
2056        }
2057        log(toExecute.describeCommand(), Project.MSG_VERBOSE);
2058
2059        log("Javadoc execution", Project.MSG_INFO);
2060
2061        JavadocOutputStream out = new JavadocOutputStream(Project.MSG_INFO);
2062        JavadocOutputStream err = new JavadocOutputStream(Project.MSG_WARN);
2063        Execute exe = new Execute(new PumpStreamHandler(out, err));
2064        exe.setAntRun(getProject());
2065
2066        /*
2067         * No reason to change the working directory as all filenames and
2068         * path components have been resolved already.
2069         *
2070         * Avoid problems with command line length in some environments.
2071         */

2072        exe.setWorkingDirectory(null);
2073        try {
2074            exe.setCommandline(toExecute.getCommandline());
2075            int ret = exe.execute();
2076            if (ret != 0 && failOnError) {
2077                throw new BuildException("Javadoc returned " + ret,
2078                                         getLocation());
2079            }
2080        } catch (IOException JavaDoc e) {
2081            throw new BuildException("Javadoc failed: " + e, e, getLocation());
2082        } finally {
2083            if (tmpList != null) {
2084                tmpList.delete();
2085                tmpList = null;
2086            }
2087
2088            out.logFlush();
2089            err.logFlush();
2090            try {
2091                out.close();
2092                err.close();
2093            } catch (IOException JavaDoc e) {
2094                // ignore
2095
}
2096        }
2097    }
2098
2099    private void writeExternalArgs(Commandline toExecute) {
2100        // If using an external file, write the command line options to it
2101
File JavaDoc optionsTmpFile = null;
2102        PrintWriter JavaDoc optionsListWriter = null;
2103        try {
2104            optionsTmpFile = FILE_UTILS.createTempFile(
2105                "javadocOptions", "", null);
2106            optionsTmpFile.deleteOnExit();
2107            String JavaDoc[] listOpt = toExecute.getArguments();
2108            toExecute.clearArgs();
2109            toExecute.createArgument().setValue(
2110                "@" + optionsTmpFile.getAbsolutePath());
2111            optionsListWriter = new PrintWriter JavaDoc(
2112                new FileWriter JavaDoc(optionsTmpFile.getAbsolutePath(), true));
2113            for (int i = 0; i < listOpt.length; i++) {
2114                String JavaDoc string = listOpt[i];
2115                if (string.startsWith("-J-")) {
2116                    toExecute.createArgument().setValue(string);
2117                } else {
2118                    if (string.startsWith("-")) {
2119                        optionsListWriter.print(string);
2120                        optionsListWriter.print(" ");
2121                    } else {
2122                        optionsListWriter.println(quoteString(string));
2123                    }
2124                }
2125            }
2126            optionsListWriter.close();
2127        } catch (IOException JavaDoc ex) {
2128            if (optionsTmpFile != null) {
2129                optionsTmpFile.delete();
2130            }
2131            throw new BuildException(
2132                "Error creating or writing temporary file for javadoc options",
2133                ex, getLocation());
2134        } finally {
2135            FILE_UTILS.close(optionsListWriter);
2136        }
2137    }
2138
2139    /**
2140     * Quote a string to place in a @ file.
2141     * @param str the string to quote
2142     * @return the quoted string, if there is no need to quote the string,
2143     * return the original string.
2144     */

2145    private String JavaDoc quoteString(String JavaDoc str) {
2146        if (str.indexOf(' ') == -1
2147            && str.indexOf('\'') == -1
2148            && str.indexOf('"') == -1) {
2149            return str;
2150        }
2151        if (str.indexOf('\'') == -1) {
2152            return quoteString(str, '\'');
2153        } else {
2154            return quoteString(str, '"');
2155        }
2156    }
2157
2158    private String JavaDoc quoteString(String JavaDoc str, char delim) {
2159        StringBuffer JavaDoc buf = new StringBuffer JavaDoc(str.length() * 2);
2160        buf.append(delim);
2161        if (str.indexOf('\\') != -1) {
2162            str = replace(str, '\\', "\\\\");
2163        }
2164        if (str.indexOf(delim) != -1) {
2165            str = replace(str, delim, "\\" + delim);
2166        }
2167        buf.append(str);
2168        buf.append(delim);
2169        return buf.toString();
2170    }
2171
2172    private String JavaDoc replace(String JavaDoc str, char fromChar, String JavaDoc toString) {
2173        StringBuffer JavaDoc buf = new StringBuffer JavaDoc(str.length() * 2);
2174        for (int i = 0; i < str.length(); ++i) {
2175            char ch = str.charAt(i);
2176            if (ch == fromChar) {
2177                buf.append(toString);
2178            } else {
2179                buf.append(ch);
2180            }
2181        }
2182        return buf.toString();
2183    }
2184
2185    /**
2186     * Add the files matched by the nested source files to the Vector
2187     * as SourceFile instances.
2188     *
2189     * @since 1.7
2190     */

2191    private void addSourceFiles(Vector JavaDoc sf) {
2192        Iterator JavaDoc e = nestedSourceFiles.iterator();
2193        while (e.hasNext()) {
2194            ResourceCollection rc = (ResourceCollection) e.next();
2195            if (!rc.isFilesystemOnly()) {
2196                throw new BuildException("only file system based resources are"
2197                                         + " supported by javadoc");
2198            }
2199            if (rc instanceof FileSet) {
2200                FileSet fs = (FileSet) rc;
2201                if (!fs.hasPatterns() && !fs.hasSelectors()) {
2202                    fs = (FileSet) fs.clone();
2203                    fs.createInclude().setName("**/*.java");
2204                    if (includeNoSourcePackages) {
2205                        fs.createInclude().setName("**/package.html");
2206                    }
2207                }
2208            }
2209            Iterator JavaDoc iter = rc.iterator();
2210            while (iter.hasNext()) {
2211                sf.addElement(new SourceFile(((FileResource) iter.next())
2212                                             .getFile()));
2213            }
2214        }
2215    }
2216
2217    /**
2218     * Add the directories matched by the nested dirsets to the Vector
2219     * and the base directories of the dirsets to the Path. It also
2220     * handles the packages and excludepackages attributes and
2221     * elements.
2222     *
2223     * @since 1.5
2224     */

2225    private void parsePackages(Vector JavaDoc pn, Path sp) {
2226        Vector JavaDoc addedPackages = new Vector JavaDoc();
2227        Vector JavaDoc dirSets = (Vector JavaDoc) packageSets.clone();
2228
2229        // for each sourcePath entry, add a directoryset with includes
2230
// taken from packagenames attribute and nested package
2231
// elements and excludes taken from excludepackages attribute
2232
// and nested excludepackage elements
2233
if (sourcePath != null) {
2234            PatternSet ps = new PatternSet();
2235            if (packageNames.size() > 0) {
2236                Enumeration JavaDoc e = packageNames.elements();
2237                while (e.hasMoreElements()) {
2238                    PackageName p = (PackageName) e.nextElement();
2239                    String JavaDoc pkg = p.getName().replace('.', '/');
2240                    if (pkg.endsWith("*")) {
2241                        pkg += "*";
2242                    }
2243                    ps.createInclude().setName(pkg);
2244                }
2245            } else {
2246                ps.createInclude().setName("**");
2247            }
2248
2249            Enumeration JavaDoc e = excludePackageNames.elements();
2250            while (e.hasMoreElements()) {
2251                PackageName p = (PackageName) e.nextElement();
2252                String JavaDoc pkg = p.getName().replace('.', '/');
2253                if (pkg.endsWith("*")) {
2254                    pkg += "*";
2255                }
2256                ps.createExclude().setName(pkg);
2257            }
2258
2259
2260            String JavaDoc[] pathElements = sourcePath.list();
2261            for (int i = 0; i < pathElements.length; i++) {
2262                File JavaDoc dir = new File JavaDoc(pathElements[i]);
2263                if (dir.isDirectory()) {
2264                    DirSet ds = new DirSet();
2265                    ds.setDefaultexcludes(useDefaultExcludes);
2266                    ds.setDir(dir);
2267                    ds.createPatternSet().addConfiguredPatternset(ps);
2268                    dirSets.addElement(ds);
2269                } else {
2270                    log("Skipping " + pathElements[i]
2271                        + " since it is no directory.", Project.MSG_WARN);
2272                }
2273            }
2274        }
2275
2276        Enumeration JavaDoc e = dirSets.elements();
2277        while (e.hasMoreElements()) {
2278            DirSet ds = (DirSet) e.nextElement();
2279            File JavaDoc baseDir = ds.getDir(getProject());
2280            log("scanning " + baseDir + " for packages.", Project.MSG_DEBUG);
2281            DirectoryScanner dsc = ds.getDirectoryScanner(getProject());
2282            String JavaDoc[] dirs = dsc.getIncludedDirectories();
2283            boolean containsPackages = false;
2284            for (int i = 0; i < dirs.length; i++) {
2285                // are there any java files in this directory?
2286
File JavaDoc pd = new File JavaDoc(baseDir, dirs[i]);
2287                String JavaDoc[] files = pd.list(new FilenameFilter JavaDoc () {
2288                        public boolean accept(File JavaDoc dir1, String JavaDoc name) {
2289                            return name.endsWith(".java")
2290                                || (includeNoSourcePackages
2291                                    && name.equals("package.html"));
2292                        }
2293                    });
2294
2295                if (files.length > 0) {
2296                    if ("".equals(dirs[i])) {
2297                        log(baseDir
2298                            + " contains source files in the default package,"
2299                            + " you must specify them as source files"
2300                            + " not packages.",
2301                            Project.MSG_WARN);
2302                    } else {
2303                        containsPackages = true;
2304                        String JavaDoc packageName =
2305                            dirs[i].replace(File.separatorChar, '.');
2306                        if (!addedPackages.contains(packageName)) {
2307                            addedPackages.addElement(packageName);
2308                            pn.addElement(packageName);
2309                        }
2310                    }
2311                }
2312            }
2313            if (containsPackages) {
2314                // We don't need to care for duplicates here,
2315
// Path.list does it for us.
2316
sp.createPathElement().setLocation(baseDir);
2317            } else {
2318                log(baseDir + " doesn\'t contain any packages, dropping it.",
2319                    Project.MSG_VERBOSE);
2320            }
2321        }
2322    }
2323
2324    private class JavadocOutputStream extends LogOutputStream {
2325        JavadocOutputStream(int level) {
2326            super(Javadoc.this, level);
2327        }
2328
2329        //
2330
// Override the logging of output in order to filter out Generating
2331
// messages. Generating messages are set to a priority of VERBOSE
2332
// unless they appear after what could be an informational message.
2333
//
2334
private String JavaDoc queuedLine = null;
2335        protected void processLine(String JavaDoc line, int messageLevel) {
2336            if (messageLevel == Project.MSG_INFO
2337                && line.startsWith("Generating ")) {
2338                if (queuedLine != null) {
2339                    super.processLine(queuedLine, Project.MSG_VERBOSE);
2340                }
2341                queuedLine = line;
2342            } else {
2343                if (queuedLine != null) {
2344                    if (line.startsWith("Building ")) {
2345                        super.processLine(queuedLine, Project.MSG_VERBOSE);
2346                    } else {
2347                        super.processLine(queuedLine, Project.MSG_INFO);
2348                    }
2349                    queuedLine = null;
2350                }
2351                super.processLine(line, messageLevel);
2352            }
2353        }
2354
2355
2356        protected void logFlush() {
2357            if (queuedLine != null) {
2358                super.processLine(queuedLine, Project.MSG_VERBOSE);
2359                queuedLine = null;
2360            }
2361        }
2362    }
2363
2364    /**
2365     * Convenience method to expand properties.
2366     * @param content the string to expand
2367     * @return the converted string
2368     */

2369    protected String JavaDoc expand(String JavaDoc content) {
2370        return getProject().replaceProperties(content);
2371    }
2372
2373}
2374
Popular Tags