Return-Path: <env_35539535-36517053@hermes.sun.com>
Received: from po10.mit.edu (po10.mit.edu [18.7.21.66]) (authenticated user=env_35539535-36517053@hermes.sun.com bits=0)
	by po10.mit.edu (Cyrus v2.1.5) with LMTP; Tue, 20 May 2003 19:36:40 -0400
X-Sieve: CMU Sieve 2.2
Received: from po10.mit.edu by po10.mit.edu (8.12.4/4.7) id h4KNael2004101; Tue, 20 May 2003 19:36:40 -0400 (EDT)
Received: (from mdefang@localhost)
	by po10.mit.edu (8.12.4/8.12.4/Submit) id h4KNaeYQ004015
	for <alexp+Spamscreen@PO10.LOCAL>; Tue, 20 May 2003 19:36:40 -0400 (EDT)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by pacific-carrier-annex.mit.edu (8.12.4/8.9.2) with SMTP id h4KNTlS1026103
	for <alexp@mit.edu>; Tue, 20 May 2003 19:29:47 -0400 (EDT)
Date: 20 May 2003 14:46:29 -0800
From: "JDC Tech Tips" <sunmail@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <35539535-36517053@hermes.sun.com>
Subject: Core Java Technologies Tech Tips, May 20, 2003 (Dashed Lines With Stroke, Custom Doclets)
Mime-Version: 1.0
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Mailer: SunMail 1.0
X-Spam-Score: 2.6
X-Spam-Level: ** (2.6)
X-Spam-Flag: YES
X-Scanned-By: MIMEDefang 2.28 (www . roaringpenguin . com / mimedefang)

<!DOCtype HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Core Java Technologies Technical Tips</title>

<style type="text/css">

code {color: #333333; font-family: verdana, courier, monospace; font-size: 10pt}
pre {color: #333333; font-family: verdana, courier, monospace; font-size: 10pt}
body, div, span {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
td, th {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
tr {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
table {font-family: arial, helvetica, sans-serif; font-size: 10pt}
p {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
li {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
br {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
div {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
sup {font-family: arial, helvetica, sans-serif; font-size: 5pt}
h3 {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 11pt}
h4, b {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
blockquote, input, select {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
ul, ol {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
a:link {font-size: 10pt; font-family: arial, helvetica, sans-serif; color:#666699 }
span.purple {font-weight: bold; color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
span.small {font-size: 8pt; font-family: arial, helvetica, sans-serif; color:#333333 }
span.link {font-size: 8pt; font-family: arial, helvetica, sans-serif; color:#666699 }
</style>

</head>

<body bgcolor="#ffffff">
<a name="top"></a>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>

<tr>
<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>

<td>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="2"><a href="http://bulkmail2.sun.com/CTServlet?id=1053467037428"><img src="http://developer.java.sun.com/images/headers/core_ttips_hdr.jpg" width="611" height="160" alt="Core Java Technologies Technical Tips" border="0"></a></td>
</tr>

<tr>
<td colspan="2" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>

<!-- ================== -->
<!-- Start Main Content -->
<!-- ================== -->

<tr>
<td height="20">&nbsp;&nbsp;&nbsp;<a href="http://bulkmail2.sun.com/CTServlet?id=1053467037446" style="text-decoration:none;">View this issue as simple text</a></td>
<td align="right" height="20"><span class="purple">May 20, 2003</span>&nbsp;&nbsp;&nbsp;&nbsp;</td>
</tr>

<tr><td colspan="2">

<table border="0" cellpadding="10" cellspacing="0" width="100%">
<tr>
<td>
     
<form method="get" action="http://search.java.sun.com/search/java/">   
<table border="0" cellpadding="3" cellspacing="0" width="100%">
<tr> 
<td align="left" valign="middle" width="20%"><h3>In this Issue</h3></td>
              
<td valign="middle" align="right" width="70%">
<font size="2">
<input type="text" size="15" maxlength="128" name="qt"></font></td>
            
<td valign="middle" width="55">
<input type="image" src="http://developer.java.sun.com/images/v4a_search.gif" alt="Search" value="search" border="0" width="55"></td>
</tr>
</table>
</form>

<p>
Welcome to the Core Java Technologies Tech Tips, May 20, 2003. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
</p>

<p>
This issue covers:
</p>

<p>
<a href="#1"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=".">Drawing Dashed Lines with Stroke</a>
<br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=".">Generating Custom Doclets</a>
</p>

<p>
These tips were developed using Java 2 SDK, Standard Edition, v 1.4. 
</p>

<p>
This issue of the Core Java Technologies Tech Tips is written by John Zukowski, president of <a href="http://bulkmail2.sun.com/CTServlet?id=1053467036917">JZ Ventures, Inc.</a>
</p>

<p>
See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="1"></a>

<h3>DRAWING DASHED LINES WITH <code>STROKE</code></h3>

<p>
The initial drawing libraries for the Java platform were rather limited. You could draw any line you wanted as long as it was a single pixel wide solid line of one color. As you can imagine, this was rather limiting. If you wanted something like a dashed line or a line multiple pixels wide, you literally had to calculate and draw each stroke gradually.
</p>

<p>
With the version 1.2 release of J2SE, the Java 2D API was introduced -- it has been subsequently enhanced with many improvements. One of the key pieces of the 2D API is its ability to draw lines that aren't just a single pixel wide of a single color. Instead, you can use the 2D API to draw lines of any pixel width and with a series of attributes for segment connections (corners) and end caps of dashed segments. This support is defined by the <code>Stroke</code> interface, primarily through the <code>BasicStroke</code> implementation.
</p>

<p>
The way to use <code>BasicStroke</code> is to set the drawing stroke when painting with a <code>Graphics2D</code> object:
</p>

<pre>
    Stroke drawingStroke = ...;
  
    public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D)g;
      g2d.setStroke(drawingStroke);
      // draw
    }
</pre>

<p>
If you can spare the memory, you can create the <code>Stroke</code> outside the <code>paint</code> method. That way, you don't have to create the same object with each drawing pass.
</p>

<p>
To demonstrate, the following program draws a rectangle with a five-pixel-wide line.
</p>

<pre>
    import javax.swing.*;
    import java.awt.*;
    import java.awt.geom.*;

    public class Stroke1 extends JFrame {
      Stroke drawingStroke = new BasicStroke(5);
      Rectangle2D rect = 
          new Rectangle2D.Double(20, 40, 100, 40);

      public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setStroke(drawingStroke);
        g2d.draw(rect);
      }

      public static void main(String args[]) {
        JFrame frame = new Stroke1();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setSize(200, 100);
        frame.show();
      }
    }
</pre>


<p>
<div align="center"><img src="http://developer.java.sun.com/developer/JDCTechTips/images/tt052003_Stroke1.gif" alt="" border="0"></div>
</p>    


<p>
In the <code>Stroke1</code> example, the <code>BasicStroke</code> constructor was passed a width of 5. Technically, the argument is a float, but the compiler is smart enough to upcast the argument. This constructor is one five constructors available for <code>BasicStroke</code>:
</p>

<ul>
<li><code>BasicStroke()</code></li>
<li><code>BasicStroke(float width)</code></li>
<li><code>BasicStroke(float width, int cap, int join)</code></li>
<li><code>BasicStroke(float width, int cap, int join, float miterlimit)</code></li>
<li><code>BasicStroke(float width, int cap, int join, float miterlimit, float[] dash, float dash_phase)</code></li>
</ul>

<p>
You can think of the first constructor as the &quot;old&quot; style, that is, it's used to draw a single-pixel-wide solid line. You've already seen the second constructor in the <code>Stroke1</code> example. The last three constructors require you to understand the settings for cap and segment joining. When a path is unclosed, then a cap is used on both of the ends of the path. If the path is explicitly closed, then segment joining is used between the last segment and the first.
</p>

<p>
There are three constants in the <code>BasicStroke</code> class for end cap settings: <code>CAP_BUTT</code>, <code>CAP_ROUND</code>, and <code>CAP_SQUARE</code>. These are used at the beginning and end of any unclosed paths, as well as at the ends of dash segments. Unclosed paths are those that aren't explicitly closed. For instance, a <code>Polygon</code> always closes its path, whereas a <code>GeneralPath</code> does not (unless you explicitly call its <code>closePath</code> method on a given subpath). The default setting, <code>CAP_SQUARE</code>, is used when a constructor doesn't offer an end cap argument.
</p>

<ul>
<li><code>CAP_BUTT</code>: Offers dash segments with no decorations.</li>
<li><code>CAP_ROUND</code>: Offers dash segments with rounded ends.</li>
<li><code>CAP_SQUARE</code>: Offers dash segments with squared-off ends.</li>
</ul>

<p>
For both <code>CAP_ROUND</code> and <code>CAP_SQUARE</code>, the decorations extend beyond the original segment end by a distance equal to half the width of the line stroke.
</p>


<p>
Here's what each of the end caps look like:<br><br>
<div align="center"><img src="http://developer.java.sun.com/developer/JDCTechTips/images/tt052003_endcaps.gif" alt="" border="0"></div>
</p>   

<p>
There are another three constants in the <code>BasicStroke</code> class for the segment connection settings: <code>JOIN_BEVEL</code>, <code>JOIN_MITER</code>, and <code>JOIN_ROUND</code>. These define how a corner looks where two path segments connect, such as for the corners of a rectangle (although the angle doesn't have to be 90 degrees to be a connection).
</p>

<ul>
<li><code>JOIN_BEVEL</code>: Joins line segments by directly connecting outside edges.</li>
<li><code>JOIN_MITER</code>: Joins line segments by connecting outside edges, however, instead of directly connecting the two lines like <code>JOIN_BEVEL</code>, it extends the segments from the outside edge until the segments meet.</li>
<li><code>JOIN_ROUND</code>: Joins line segments with a rounded corner.</li>
</ul>

<p>
Here's what each of the segment connections look like:<br><br>
<div align="center"><img src="http://developer.java.sun.com/developer/JDCTechTips/images/tt052003_joins.gif" alt="" border="0"></div>
</p>   

<p>
Now let's look at the remaining <code>BasicStroke</code> constructor options: <code>miterlimit</code>, <code>dash[]</code>, and <code>dash_phase</code>.
</p>

<ul>
<li><code>miterlimit</code>: Specifies the miter limit to use when the join style is <code>JOIN_MITER</code>. This means how far the outside edges can extend before a join is possible. The miter limit affects the join style: if the length of a miter is greater than the miter limit (default of 10) multiplied by half the stroke width, then a <code>JOIN_BEVEL</code> is used instead of a <code>JOIN_MITER</code>.</li>

<li><code>dash[]</code>: An array of float values to use as repeating dash lengths and clear sections. Use only one value in the array if all the dashes and all the clear sections have the same length. For different lengths, have an array of the different sizes. For instance, the array new <code>float[] {5.0f}</code> produces a repeating five-pixel dash, while the array new <code>float[] {5.0f, 10.0f}</code>  produces five-pixel dashes followed by ten empty pixels. The array acts in a circular fashion, wrapping back to the beginning if the array if more drawing space is available than the combined path length.</li>

<li><code>dash_phase</code>: Acts as an offset into dashes. For instance, if <code>dash_phase</code> is zero, the first dash starts at the beginning of the coordinate space from the drawing origin. When <code>dash_phase</code> is not zero, the dash starts the specified number of pixels into the dash. This means that for a ten-pixel dash and a <code>dash_phase</code> of 4, you only see six drawing pixels for the first dash.</li>
</ul>

<p>
The following program demonstrates the different <code>JOIN_*</code> constants. The program uses dashed lines to draw a figure that looks like a &quot;Star Trek: The Next Generation&quot; communicator. Adjust the <code>CAP_*</code> constants, <code>dash[]</code>, miter limit, and phase to see what changes to those settings do to the output. Notice especially what happens in the figure to the bottom corners of the polygon.
</p>

<pre>
    import javax.swing.*;
    import java.awt.*;
    import java.awt.geom.*;

    public class Stroke2 extends JFrame {
      Stroke drawingStroke1 = 
        new BasicStroke(
          10, 
          BasicStroke.CAP_BUTT,
          BasicStroke.JOIN_BEVEL,
          0,
          new float[] {9}, 
          0
        );
      Stroke drawingStroke2 = 
        new BasicStroke(
          10, 
          BasicStroke.CAP_BUTT,
          BasicStroke.JOIN_MITER,
          50,
          new float[] {9}, 
          0
        );
      Stroke drawingStroke3 = 
        new BasicStroke(
          10, 
          BasicStroke.CAP_BUTT,
          BasicStroke.JOIN_ROUND,
          0,
          new float[] {9}, 
          0
        );

      GeneralPath shape;

      public Stroke2() {
        shape = new GeneralPath();
        shape.moveTo(50, 0);
        shape.lineTo(100, 100);
        shape.lineTo(50, 50);
        shape.lineTo(0, 100);
        shape.lineTo(50, 0);
      }

      public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.translate(50, 50);
        g2d.setStroke(drawingStroke1);
        g2d.draw(shape);
        g2d.translate(0, 100);
        g2d.setStroke(drawingStroke2);
        g2d.draw(shape);
        g2d.translate(0, 100);
        g2d.setStroke(drawingStroke3);
        g2d.draw(shape);
      }

      public static void main(String args[]) {
        JFrame frame = new Stroke2();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setSize(200, 400);
        frame.show();
      }
    }
</pre>    

<p>
<div align="center"><img src="http://developer.java.sun.com/developer/JDCTechTips/images/tt052003_Stroke2.gif" alt="" border="0"></div>
</p> 

<p>
For additional information on the Java 2D API, see the <a href="http://bulkmail2.sun.com/CTServlet?id=1053467037029">Java 2D documentation</a> and the Displaying Graphics with Graphis2D trail of the <a href="http://bulkmail2.sun.com/CTServlet?id=1053467037069">Sun Java Tutorial</a>.
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td>
</tr>

<tr>
<td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="2"></a>

<h3>GENERATING CUSTOM <code>DOCLETS</code></h3>

<p>
Putting comments in code is good programming practice, but something that is often overlooked. To help with this lack of documentation, the early designers of the Java programming language devised a plan for self-documenting code. They devised a little tool called javadoc that you could run against a set of classes, and by doing so, generate documentation for those classes.
</p>

<p>
Running the javadoc tool generates a series of HTML pages that lists class names with their set of methods and fields. This result is similar to what developers produced prior to the existence of the Java programming language by running scripts, typically in Perl, against a series of source files.
</p>

<p>
The <code>javadoc</code> tool can also provide more extensive commenting. What the designers added for the Java programming language, was a special form of comment called a <code>javadoc</code> comment. When a <code>javadoc</code> comment is included in a class definition, it is also included in the generated output when that class is passed through the <code>javadoc</code> tool.
</p>

<p>
The Java programming language provides for single-line comments or multi-line comments. Single-line comments start with <code>//</code> and go to end of the line. Multi-line comments start with <code>/*</code> and go to <code>*/</code>. While multi-line comments could be on a single line, the end-of-line doesn't signal the end of the comment. The first <code>*/</code> after the opening <code>/*</code> indicates the end.
</p>

<p>
The javadoc comment extends the multi-line comment. Instead of starting with a slash (<code>/</code>) followed by one star (<code>*</code>), the javadoc comment begins with a slash followed by two stars. Everything between the starting <code>/**</code> tag and the end <code>*/</code> tag is the comment.
</p>

<p>
So, if a class definition is as follows:
</p>

<pre>
    /**
      * This is a javadoc comment
      */

    public class Comment {
             /**
              * So is this
              */
             public Comment() {
             }
    }
</pre>

<p>
and you run the <code>javadoc</code> command as follows:
</p>

<pre>
   javadoc Comment.java
</pre>

<p>
you get several support files and one file named <code>Comment.html</code>. The <code>Comment.html</code> file provides the documentation for the class. This file would include the &quot;This is a <code>javadoc</code> comment&quot; as the text for the class definition and &quot;So is this&quot; with the constructor.
</p>

<p>
This, in itself is useful, but the <code>javadoc</code> tool is more flexible than that. If you don't like the default output of the <code>javadoc</code> command, you can change it. By creating a custom doclet, you can customize the output format. The format could be something as simple as a text dump of the classes found by the tool, or something as complicated as a FrameMaker document or a comment checker. If you have a PDF file generator available, or if you just want to convert the <code>FrameMaker</code> output to PDF, you could even generate <code>javadoc</code> output as PDF.
</p>

<p>
You'll find the doclet classes in the <code>com.sun.javadoc</code> package, in the <code>lib/tools.jar</code> file. That means they are found in the J2SE development kit, but not in the standard Java runtime environment.
</p>

<p>
Here are the steps to create a simple <code>doclet</code>, one that prints class signatures. The signatures include the <code>access modifiers</code>, <code>name</code>, <code>interfaces implemented</code>, and <code>extended class</code>.
</p>

<p>
As you follow the steps it's important to understand that a <code>doclet</code> is run from the <code>javadoc</code> command, not the java command. This equates to no <code>main</code> method. Another thing to note is that a <code>doclet</code> extends <code>Doclet</code>. 
</p>

<p>
So let's start with the following framework:
</p>

<pre>
    import com.sun.javadoc.*;

    public class DocIt extends Doclet {
      public static boolean start(RootDoc root) {
        // Do work
        return true;
      }
    }
</pre>

<p>
The <code>start</code> method returns true to indicate success, false otherwise. The <code>RootDoc</code> passed to the <code>start</code> method holds the information from one run of <code>javadoc</code>.
</p>

<p>
For the &quot;Do work&quot; part of the method, you can literally do whatever you want, as long as it is valid code. Typically, you would get all the classes (and interfaces) to be documented, and loop through each to do whatever you wanted to do for that one. You do this using the classes method of the <code>RootDoc</code>, with the help of a <code>for-loop</code>:
</p>

<pre>
    public static boolean start(RootDoc root) {
      ClassDoc[] classes = root.classes();
      for (int i = 0; i &lt; classes.length; ++i) {
        ClassDoc cd = classes[i];
        // Do work for specific ClassDoc
      }
      return true;
   }
</pre>

<p>
Imagine a simple &quot;Hello, World&quot; <code>doclet</code>. That sort of <code>doclet</code> would likely just print the class name. However, a more sophisticated <code>doclet</code> might print the whole class signature. In order to do that, you use the <code>ClassDoc</code> interface. This interface extends the <code>ProgramElementDoc</code> and <code>Type</code> interfaces (which in turn extend <code>Doc</code> and <code>Comparable</code>). The four interfaces together give you a way to find out quite a bit about a class. Specifically, they allow you to take advantage of the following methods:
</p>

<ul>
<li><code>modifiers</code>: Generates a string, combining all the modifiers.</li>
<li><code>isClass</code>: Finds out if something is a class or interface.</li>
<li><code>qualifiedName</code>: Gets the fully qualified name for a class or interface.</li>
<li><code>typeName</code>: Returns an unqualified name.</li>
<li><code>interfaces</code>: Provides an array of <code>ClassDoc</code> objects, one for each interface implemented by the class.</li>
<li><code>superclass</code>: Identifies the class that this class extends.</li>
</ul>

<p>
Putting all this together, gives you the following method. The method would be called for each <code>ClassDoc</code> in start.
</p>

<pre>
    static void printSignature(ClassDoc cd) {
      System.out.print(cd.modifiers());
      System.out.print(
        cd.isClass() ? &quot; class &quot; : &quot; interface &quot;);
      System.out.println(&quot; &quot; + cd.qualifiedName());
      ClassDoc interfaces[] = cd.interfaces();
      for (int i=0, n=interfaces.length; i&lt;n; i++) {
        System.out.println(&quot;  implements &quot; +
          interfaces[i].qualifiedName());
      }
      ClassDoc parent = cd.superclass();
      if (parent != null) {
        System.out.println(&quot;  extends &quot; +
          parent.qualifiedName());
      }
    }
</pre>

<p>
For the <code>DocIt</code> class, <code>printSignature</code> would print the following output:
</p>

<pre>
    public class DocIt
        extends com.sun.javadoc.Doclet
</pre>

<p>
At this point you need to compile the class. You need to use the <code>-classpath</code> option when you compile. That's because the <code>tools.jar</code> file where the <code>Doclet</code> and related classes are located is outside the default <code>classpath</code>. To compile the command, issue the following command (although shown on two lines, the command needs to go on one line).
</p>

<p>
In Windows:
</p>

<pre>
    javac -classpath 
        c:\j2se1.4.1\lib\tools.jar DocIt.java
</pre>

<p>        
In Unix:
</p>

<pre>
    javac -classpath 
        /homedir/jdk14/j2sdk1.4.1/lib/tools.jar DocIt.java
</pre>

<p>       
Then, to run it, use the <code>javadoc</code> command. You need to specify the <code>-doclet</code> option to identify the doclet to run. You also need to specify the <code>-docletpath</code> option to tell <code>javadoc</code> where to find the <code>doclet</code>. You don't have to specify the <code>tools.jar</code> file in the <code>classpath</code> when you run the <code>doclet</code>. However, if you want to run the <code>doclet</code> on itself, you should include <code>tools.jar</code> in the classpath. That way, the <code>doclet</code> will find the <code>com.sun.javadoc</code> classes, and can fully specify them as coming from that package. So, to run the <code>DocIt doclet</code> on itself, issue the following command (on one line).
</p>

<p> 
In Windows:
</p>

<pre>
    javadoc -doclet DocIt -docletpath .
        -classpath c:\jdk1.4.1\lib\tools.jar DocIt.java
</pre>

<p>        
In Unix:     
</p>

<pre>
   javadoc -doclet DocIt -docletpath .
        -classpath /homedir/jdk14/j2sdk1.4.1/lib/tools.jar 
        DocIt.java   
</pre>

<p>
And, as expected, you get output:
</p>

<pre>
    public class DocIt
      extends com.sun.javadoc.Doclet
</pre>

<p>
To run the <code>doclet</code> against more classes, simply include more classes on the command line.
</p>

<p>
You can use <code>doclets</code> to do more than print the class signature. A <code>doclet</code> can print information about the constructors, fields, and methods of the class. There is a <code>xxxDoc</code> interface available for each type of information: <code>ConstructorDoc</code> for constructors, <code>FieldDoc</code> for fields, and <code>MethodDoc</code> for methods. And because the <code>xxxDoc</code> classes implement <code>Comparable</code>, the information they produce is directly sortable.
</p>

<p>
Here's an example that demonstrates the power of <code>doclets</code>. The following <code>DocIt</code> class combines the <code>printSignature</code> method introduced earlier, with similar methods that print the name, constructors, fields, and methods, respectively. The output of <code>DocIt</code> is similar to the output produced by the <code>javap</code> command (the Java disassembler), although the output format is slightly different. The <code>DocIt</code> output includes headers for each type of output, and no semicolons at the end of lines.
</p>

<pre>
    import com.sun.javadoc.*;
    import java.util.*;

    public class DocIt extends Doclet {

       public static boolean start(RootDoc root) {
         ClassDoc[] classes = root.classes();
         for (int i = 0; i &lt; classes.length; ++i) {
           ClassDoc cd = classes[i];
           printName(cd);
           printSignature(cd);
           printConstructors(cd.constructors());
           printFields(cd.fields());
           printMethods(cd.methods());
         }
         return true;
       }

       static void printName(ClassDoc cd) {
         System.out.println(cd.typeName());
       }

       static void printSignature(ClassDoc cd) {
         System.out.print(cd.modifiers());
         System.out.print(
             cd.isClass() ? &quot; class &quot; : &quot; interface &quot;);
         System.out.println(cd.qualifiedName());
         ClassDoc interfaces[] = cd.interfaces();
         for (int i=0, n=interfaces.length; i&lt;n; i++) {
           System.out.println(&quot;  implements &quot; 
               + interfaces[i].qualifiedName());
         }
         ClassDoc parent = cd.superclass();
         if (parent != null) {
           System.out.println(&quot;  extends &quot; + 
               parent.qualifiedName());
         }
       }

       static void printConstructors(
        ConstructorDoc cons[]) {
         if (cons.length &gt; 0) {
           System.out.println(&quot;Constructors&quot;);
           Arrays.sort(cons);
         }
         for (int i=0, n=cons.length; i&lt;n; i++) {
           System.out.print(cons[i].modifiers());
           System.out.print(&quot; &quot; + cons[i].name());
           System.out.println(
               cons[i].flatSignature());
         }
       }

       static void printFields(FieldDoc fields[]) {
         if (fields.length &gt; 0) {
           System.out.println(&quot;Fields&quot;);
           Arrays.sort(fields);
         }
         for (int i=0, n=fields.length; i&lt;n; i++) {
           System.out.print(fields[i].modifiers());
           Type type = fields[i].type();
           System.out.print(&quot; &quot; + 
               type.qualifiedTypeName());
           System.out.println(&quot; &quot; + fields[i].name());
         }
       }

       static void printMethods(MethodDoc methods[]) {
         if (methods.length &gt; 0) {
           System.out.println(&quot;Methods&quot;);
           Arrays.sort(methods);
         }
         for (int i=0, n=methods.length; i&lt;n; i++) {
           System.out.print(methods[i].modifiers());
           Type type = methods[i].returnType();
           System.out.print(&quot; &quot; + 
               type.qualifiedTypeName());
           System.out.print(&quot; &quot; + methods[i].name());
           System.out.println(
               methods[i].flatSignature());
         }
         System.out.println();
       }
    }
</pre>

<p>    
For example, if you compile <code>DocIt</code> (remember to specify the <code>-classpath</code> option when you compile) and then run it against the <code>Stroke2.java</code> class described in the first tip in this issue &quot;Drawing Dashed Lines with <code>Stroke</code>&quot;, you should see the following:
</p>

<pre>
    Loading source file Stroke2.java...
    Constructing Javadoc information...
    Stroke2
    public class Stroke2
      extends javax.swing.JFrame
    Constructors
    public Stroke2()
    Methods
    public static void main(String[])
    public void paint(Graphics)
</pre>

<p>
There is much more that could be done here to print fancier output or do some of the behavior yourself. For instance, the <code>flatSignature</code> method in the interface <code>ExecutableMemberDoc</code> combines all the parameters to the method or constructor for you. You could get the <code>Parameter array</code> from a <code>ConstructorDoc</code> or <code>MethodDoc</code> through parameters, and generate that output yourself. You can also add the <code>Throws</code> tag to print the exceptions that can be thrown. And, if you want to include those <code>javadoc</code> comments in the output, the <code>commentText</code> and <code>setRawCommentText</code> methods of the <code>Doc</code> class come in handy.
</p>

<p>
If you're interested in generating doclets from within a Java program, try out the execute method of the <code>com.sun.tools.javadoc.Main</code> class.
</p>

<p>
For more information about the javadoc tool and the API for doclets, see the resources listed on the <a href="http://bulkmail2.sun.com/CTServlet?id=1053467037088">Javadoc 1.4 Tool page</a>.
</p>


<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<form method="POST" action="http://developer.java.sun.com/servlet/jdc.survey.TabulationServlet">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<tr><td>
<h3>Reader Feedback</h3> 

<input type="hidden" name="survey_id" value="2600">
<input type="hidden" name="anonymous" value="True">
<input type="hidden" name="answer_count" value="3">
<input type="hidden" name="answer1" value="MayCore_tt052003">
<input name="answer2" type="radio" value="2">&nbsp; Very worth reading&nbsp; 
<input name="answer2" type="radio" value="1">&nbsp; Worth reading&nbsp; 
<input name="answer2" type="radio" value="0">&nbsp; Not worth reading&nbsp; 
 
<p>
If you have other comments or ideas for future technical tips, please type them  here: 
</p>
 
<p>
<textarea name="answer3" rows="6" cols="50"></textarea> 
</p>
 
<p>
<input type="Submit" value="Submit"> &nbsp; <input type="Reset"> 
</p>

<p> 
Have a question about Java programming? Use  
<a href="http://bulkmail2.sun.com/CTServlet?id=1053467037463">Java Online Support.</a> 
</p>

</td></tr></table>
</form> 

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<br>

<span class="small">IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:<br>
<a href="http://bulkmail2.sun.com/CTServlet?id=1053467037146"><span class="link">http://www.sun.com/share/text/termsofuse.html</span></a><br>
<a href="http://bulkmail2.sun.com/CTServlet?id=1053467037168"><span class="link">http://www.sun.com/privacy/</span></a><br> 
<a href="http://bulkmail2.sun.com/CTServlet?id=1053467037299"><span class="link">http://developer.java.sun.com/berkeley_license.html</span></a>
</span><br><br>


<span class="small">
Comments? Send your feedback on the Core Java Technologies Tech Tips to: <a href="mailto:jdc-webmaster@sun.com"><span class="link">jdc-webmaster@sun.com</span></a>
</span><br><br>

<span class="small">
Subscribe to other Java developer Tech Tips:
</span><br><br>

<span class="small">
- Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE).<br>
- Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME).<br><br>
</span>
   
<span class="small">
To subscribe to these and other JDC publications:<br>
- Go to the JDC Newsletters and Publications page, choose the newsletters you want to <a href="http://bulkmail2.sun.com/CTServlet?id=1053467037335"><span class="link">subscribe</span></a> to and click &quot;Update&quot;.<br>
  - To unsubscribe, go to the <a href="http://bulkmail2.sun.com/CTServlet?id=1053467037335"><span class="link">subscriptions page</span></a>, uncheck the appropriate checkbox, and click &quot;Update&quot;.
</span><br><br>

<span class="small">ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at:<br>
<a href="http://bulkmail2.sun.com/CTServlet?id=1053467037481"><span class="link">http://java.sun.com/jdc/TechTips/index.html</span></a>
</span><br><br>

<span class="small">Copyright 2003 <a href="http://bulkmail2.sun.com/CTServlet?id=1053467037499"><span class="link">Sun Microsystems, Inc.</span></a> All rights reserved.
<br>4150 Network Circle, Santa Clara, CA 95054 USA.
</span><br><br>

<span class="small">This document is protected by copyright. For more information, see:
<br><a href="http://bulkmail2.sun.com/CTServlet?id=1053467037374"><span class="link">http://java.sun.com/jdc/copyright.html</span></a>
</span><br><br>

<span class="small">Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks or registered trademarks (<a href="http://bulkmail2.sun.com/CTServlet?id=1053467037398"><span class="link">http://www.sun.com/suntrademarks/</span></a>) of Sun Microsystems, Inc. in the United States and other countries.<br><br>

<!-- ================ -->
<!-- End Main Content -->
<!-- ================ -->

<center>
<a href="http://bulkmail2.sun.com/CTServlet?id=1053467037499"><img src="http://developer.java.sun.com/images/lgsun.gif" border="0" alt="Sun Microsystems, Inc."></a>
</center>

</td>
</tr>
</table>

</td></tr>
</table>
</td>

<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>
</table>

<table bgcolor = "#efefef"><tr><td><a href="http://subscriptions.sun.com/unsubscribe?35539535-36517053">Please unsubscribe me from this newsletter.</a><img src="http://bulkmail2.sun.com/OTServlet?id=35539535-36517053" width=1 height=1></td></tr></table></body>
</html>

