Doclet Overview (original) (raw)

Home Page

Contents

The Basics

Doclets are programs written in the Java™ programming language that use the doclet API to specify the content and format of the output of the Javadoc tool. By default, the Javadoc tool uses the "standard" doclet provided by Sun™ to generate API documentation in HTML form. However, you can supply your own doclets to customize the output of Javadoc as you like. You can write the doclets from scratch using the doclet API, or you can start with the standard doclet and modify it to suit your needs.

Here are the basic steps you need to follow to create and use your own doclet:

  1. Write the Java program that constitutes your doclet. Your program should import com.sun.javadoc.* in order to use the doclet API. The entry point of your program is a class with a public static boolean start method that takes a RootDocas a parameter.
  2. Compile your doclet. You can use the compiler in the Java 2 SDK, javac.
  3. Run the javadoc tool using the -doclet startingclass option to produce the output specified by your doclet, where startingclass is the fully-qualified name of the starting class mentioned in step 1 above.

The doclet API class files are in the

lib/tools.jar

file in the SDK. When you compile a doclet, the

tools.jar

must be on the class path. You can use the

-classpath

option on javac for this purpose.

If you run javadoc without the -doclet command-line option, it will default to the standard doclet to produce HTML-format API documentation.

Package com.sun.javadoc consists of interfaces that define the doclet API. The lib/tools.jar file in the Java 2 SDK contains these interfaces and also a private package with classes that implement the interfaces. The tools.jar file also contains the classes implementing the standard doclet.

A Simple Example Doclet

You can get a feeling for the way doclets work by looking at this simple example doclet that consists of one short class:

import com.sun.javadoc.*;

public class ListClass { public static boolean start(RootDoc root) { ClassDoc[] classes = root.classes(); for (int i = 0; i < classes.length; ++i) { System.out.println(classes[i]); } return true; } }

As you might be able to guess by looking at the code, this doclet takes the classes upon which Javadoc is operating and prints their names to standard out.

This first thing to notice about the doclet is that it imports the com.sun.javadoc package in order to use the doclet APIs. As with all doclets, the entry point is thepublic static boolean start method. Thestart method takes a RootDoc as a parameter. This parameter carries information about any options specified on the command line when javadoc is run, and also about the classes and packages upon which javadoc is operating.

RootDoc defines a classes method that returns a ClassDoc array whose elements represent the classes that Javadoc parses. The for loop then prints out the names of each class in the array. (Passing a ClassDoc to println results in the printing of the name of the class that the ClassDoc represents.)

To run this doclet, you first have to compile it. You can compile it with the javac compiler. The doclet API classfiles are in the file lib/tools.jar in the Java 2 SDK which javac does not automatically load. You therefore need to includetools.jar on the compiler's classpath, as in this example:

javac -classpath C:\jdk1.3\lib\tools.jar ListClass.java

To run the ListClass doclet, you point to the compiled doclet with Javadoc's

-doclet

and

-docletpath

tags. For example, to run the doclet on a file called

MyClass.java

, you could use this command, assuming

ListClass.class

is in the current directory:

% javadoc -doclet ListClass -docletpath . MyClass.java

The output will be the string "

MyClass

". Note that this command does not require

tools.jar

to be on the class path, as the Javdoc tool automatically loads it.

A note about command-line options: If you runjavadoc -help, you'll see that the Javadoc tool has two sets of command-line options. One set is generic and will work with any doclet. The second set of options is special to the standard doclet. Options in this second set will not be available when using custom doclets. Your custom doclets can also define their own command-line options. See the example below.

To generate API documentation, a doclet will have to be considerably more complex than this simple example. If you want to customize the format of the API documentation generated by Javadoc, you may want to start with the default standard doclet and modify it as necessary rather than write your own doclet from scratch.

Example - Subclassing the Standard Doclet

To customize the output of the Javadoc tool, you need to write your own doclet that specifies the content and format of the output that you desire. If you want HTML output with roughly the same format as the default output, you can use the standard doclet as a starting point for creating your doclet. You can subclass appropriate classes in the standard doclet and then add or override methods as necessary to produce the output you want. Or you can copy the whole standard doclet and modify it. If you use a copy of the standard doclet as your starting point, you may want to remove the

package

statements at the beginning of each source file and replace them with the name of your own, new package.

For an example, see How can I modify the standard doclet to produce links to source code from the API documentation?

Example - Creating and handling custom tags

Suppose, for example, that you want use a custom tag, say

@mytag

, in your documentation comments in addition to the standard tags like

@param

and

@return

. To make use of the information in your custom tags, you need to have your doclet use instances of

Tag

that represent your custom tags. One of the easiest ways to do that is to use the

tags(String)

method of

Doc

or one of

Doc

's subclasses. This method returns an array of

Tag

objects representing any tags whose name matches the string argument. For example, if

method

is an instance of

MethodDoc

, then

method.tags("mytag")

would return an array of

Tag

objects representing any

@mytag

tags in the method's documentation comment. You can then access the information in your

@mytag

tags with

Tag

's

text

method. That method returns a string representing the content of the tag which you can parse or use as needed. For example, if a documentation comment contained one of your custom tags like this:

@mytag Some dummy text.

then the

text

method would return the string

"Some dummy text."

.

Here's a standalone doclet (not a subclass of the standard doclet) that uses these ideas to print out the text associated with all instances of a specified tag that it finds in method comments. It could be extended to find all instances of that tag in all comments.

import com.sun.javadoc.*;

public class ListTags { public static boolean start(RootDoc root){ String tagName = "mytag"; writeContents(root.classes(), tagName); return true; }

private static void writeContents(ClassDoc[] classes, String tagName) {
    for (int i=0; i < classes.length; i++) {
        boolean classNamePrinted = false;
        MethodDoc[] methods = classes[i].methods();
        for (int j=0; j < methods.length; j++) {
            Tag[] tags = methods[j].tags(tagName);
            if (tags.length > 0) {
                if (!classNamePrinted) {
                    System.out.println("\n" + classes[i].name() + "\n");
                    classNamePrinted = true;
                }
                System.out.println(methods[j].name());
                for (int k=0; k < tags.length; k++) {
                    System.out.println("   " + tags[k].name() + ": " 
                        + tags[k].text());
                }
            } 
        }
    }
}

}

The tag for which this doclet searches is specified by the variable

tagName

. The value of the

tagName

string can be any tag name, custom or standard. This doclet writes to standard out, but its output format could be modified, for example, to write HTML output to a file.

Example - Using custom command-line options

You can write doclets that accept custom command-line options. To see how that works, let's augment the example doclet above so that it allows you to use a command-line option to specify the tag name to search for.

Any doclet that uses custom options must have a method calledoptionLength(String option) that returns an int. For each custom option that you want your doclet to recognize,optionLength must return the number of separate pieces or tokens in the option. For our example, we want to be able to use the custom option of the form -tag mytag. This option has two pieces, the -tag option itself and its value, so theoptionLength method in our doclet must return 2for the -tag option. The optionsLength method should return 0 for unrecognized options.

Here's the full, augmented doclet:

import com.sun.javadoc.*;

public class ListTags { public static boolean start(RootDoc root){ String tagName = readOptions(root.options()); writeContents(root.classes(), tagName); return true; }

private static void writeContents(ClassDoc[] classes, String tagName) {
    for (int i=0; i < classes.length; i++) {
        boolean classNamePrinted = false;
        MethodDoc[] methods = classes[i].methods();
        for (int j=0; j < methods.length; j++) {
            Tag[] tags = methods[j].tags(tagName);
            if (tags.length > 0) {
                if (!classNamePrinted) {
                    System.out.println("\n" + classes[i].name() + "\n");
                    classNamePrinted = true;
                }
                System.out.println(methods[j].name());
                for (int k=0; k < tags.length; k++) {
                    System.out.println("   " + tags[k].name() + ": " + tags[k].text());
                }
            } 
        }
    }
}

private static String readOptions(String[][] options) {
    String tagName = null;
    for (int i = 0; i < options.length; i++) {
        String[] opt = options[i];
        if (opt[0].equals("-tag")) {
            tagName = opt[1];
        }
    }
    return tagName;
}

public static int optionLength(String option) {
    if(option.equals("-tag")) {
        return 2;
    }
    return 0;
}

public static boolean validOptions(String options[][], 
                                   DocErrorReporter reporter) {
    boolean foundTagOption = false;
    for (int i = 0; i < options.length; i++) {
        String[] opt = options[i];
        if (opt[0].equals("-tag")) {
            if (foundTagOption) {
                reporter.printError("Only one -tag option allowed.");
                return false;
            } else { 
                foundTagOption = true;
            }
        } 
    }
    if (!foundTagOption) {
        reporter.printError("Usage: javadoc -tag mytag -doclet ListTags ...");
    }
    return foundTagOption;
}

}

In this modified doclet, the variable

tagName

is set with the command-line option

-tag

. It has a

optionLength

method returns two for our custom option. Note that an explicit call to

optionLength

isn't required.

This doclet also adds the readOptions methods that actually parses the command-line options looking for the-tag option. It makes use of the fact that the Rootdoc.options method returns a two-dimensional String array containing option information. For example, given the command

javadoc -foo this that -bar other ...

the

RootDoc.options

method will return

options()[0][0] = "-foo" options()[0][1] = "this" options()[0][2] = "that" options()[1][0] = "-bar" options()[1][1] = "other"

The number of elements in the array's second index is determined by the

optionLength

method. In this example,

optionLength

returns

3

for option

-foo

and returns

2

for option

-bar

.

The validOptions method is an optional method that you can use to test the validity of the usage of command-line tags. If the validOptions method is present, it is automatically invoked; you don't have to explicitly call it. It should returntrue if the option usage is valid, and falseotherwise. You can also print appropriate error messages fromvalidOptions when improper usages of command-line options are found. The validOptions method in this example doclet checks that the -tag option is used once and only once.