sixlegs.com / blog / java / exclude-javadoc-tag.html

Root Beer Logo Root Beer

Chris Nokleberg's Fizzy Weblog

February 2005
Su M Tu W Th F Sa
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 18 19
20 23 24 25 26
27 28
Previous  |  Next  |  More...
#  Implementing @exclude using Dynamic Proxies

For our new PowerPoint rendering library, I needed access to some internal methods in a package from another product. Making the method public didn't seem like a good solution, though, because it would affect the published API, which we didn't want to do. I had read Martin Fowler's paper (PDF) on need for a distinction between public and published interfaces before, and now I finally understood what he meant. [Emoticon]

But since this was just a single method, I figured I would just hack around it by excluding that particular method from our javadoc. You know, something like an @exclude tag. To make a long story short: "There is currently no Javadoc option to hide, exclude or suppress public members from the javadoc-generated documentation" (from the javadoc FAQ), even though it is a proposed tag and the most requested javadoc enhancement.

As it turns out, there is a relatively simple way to implement @exclude. The basic idea is to implement a Doclet that delegates to Sun's standard doclet as necessary, while filtering out all the excluded classes/fields/methods from method return values. For example, the ClassDoc methods() method returns an array of MethodDoc objects. By wrapping the ClassDoc in a proxy and intercepting all method calls we can filter out excluded methods from the array before returning from the method.

Thankfully the Doclet API is very interface-based, so Dynamic Proxies are an option. Otherwise I might have to use CGLIB, bleh! [Emoticon]

The tricky parts are:
  • Making sure to wrap every com.sun.* object, including array elements.
  • When recreating a (filtered) array, using the right component type.
  • Certain methods in Sun's implementation assume that parameters will be a particular concrete type (arguably a bug on their part). For these methods (compareTo, overrides, and subclassOf) we need special code to unwrap the argument before calling the underlying method.

Actually using the doclet is really simple--just add a

  doclet="com.tonicsystems.doclet.ExcludeDoclet"

(and docletref) to the appropriate Ant task. On JDK 1.4 you may get some strange warnings printed:

Internal error: package sets don't match: [] with: null
Internal error: package sets don't match: [] with: null
...etc...

As far as I can tell, these "errors" do not affect the output. If someone knows better, I'd like to hear about it. Anyway, in JDK 1.5 they have disappeared altogether, perhaps as part of the standard doclet refactoring.

The full source for ExcludeDoclet is here. It's in the public domain, so go crazy.

[Powered By FreeMarker]  [Valid Atom 1.0]  [Weblog Commenting by HaloScan.com]