View Javadoc

1   package org.apache.maven.jellydoc;
2   
3   /* ====================================================================
4    *   Copyright 2001-2004 The Apache Software Foundation.
5    *
6    *   Licensed under the Apache License, Version 2.0 (the "License");
7    *   you may not use this file except in compliance with the License.
8    *   You may obtain a copy of the License at
9    *
10   *       http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing, software
13   *   distributed under the License is distributed on an "AS IS" BASIS,
14   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *   See the License for the specific language governing permissions and
16   *   limitations under the License.
17   * ====================================================================
18   */
19  
20  import java.io.IOException;
21  import java.io.File;
22  import java.io.FileOutputStream;
23  import java.util.Enumeration;
24  import java.util.Vector;
25  
26  import com.sun.javadoc.ClassDoc;
27  import com.sun.javadoc.ConstructorDoc;
28  import com.sun.javadoc.Doc;
29  import com.sun.javadoc.DocErrorReporter;
30  import com.sun.javadoc.Doclet;
31  import com.sun.javadoc.ExecutableMemberDoc;
32  import com.sun.javadoc.FieldDoc;
33  import com.sun.javadoc.MethodDoc;
34  import com.sun.javadoc.PackageDoc;
35  import com.sun.javadoc.Parameter;
36  import com.sun.javadoc.RootDoc;
37  import com.sun.javadoc.Tag;
38  import com.sun.javadoc.ThrowsTag;
39  import com.sun.javadoc.Type;
40  
41  import org.dom4j.io.OutputFormat;
42  import org.dom4j.io.XMLWriter;
43  
44  import org.xml.sax.Attributes;
45  import org.xml.sax.ContentHandler;
46  import org.xml.sax.SAXException;
47  import org.xml.sax.helpers.AttributesImpl;
48  
49  /**
50   * Main Doclet class to generate JavaDocXML.  This doclet generates the
51   * document conforming to DTD specified in javadoc-v04draft.dtd.
52   * @author <a href="mailto:gopi@aztecsoft.com">Gopinath M.R.</a>
53    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
54   */
55  
56  public class XMLDoclet extends Doclet
57  {
58  
59      private String xmlns = "jvx";
60      private String encodingFormat="UTF-8";
61      private String localName = "javadoc";
62      private ContentHandler cm = null;
63      private String targetFileName = null;
64      private Attributes emptyAtts = new AttributesImpl();
65  
66      public XMLDoclet (RootDoc root) throws Exception {
67          readOptions(root);
68          File targetFile = new File(targetFileName);
69          targetFile.getParentFile().mkdirs();
70          FileOutputStream writer = new FileOutputStream(targetFileName);
71          OutputFormat format = OutputFormat.createPrettyPrint();
72          format.setEncoding(encodingFormat);
73          XMLWriter xmlWriter = new XMLWriter(writer, format);
74          try
75          {
76              cm = xmlWriter;
77              cm.startDocument();
78              javadocXML(root);
79              cm.endDocument();
80              xmlWriter.close();
81          } 
82          catch (IOException e)
83          {
84              xmlWriter.close();
85              throw e;
86          }
87      }
88  
89      /**
90       * Generates the xml data for the top element.
91       * <xmp><!ELEMENT javadoc (package*, class*, interface*)></xmp>
92       */
93      private void javadocXML(RootDoc root) throws SAXException {
94          cm.startElement(xmlns, localName, "javadoc", emptyAtts);
95          PackageDoc[] packageArray = root.specifiedPackages();
96  
97          // Generate for packages.
98          for (int i = 0; i < packageArray.length; ++i) {
99              packageXML(packageArray[i]);
100         }
101 
102         // Generate for classes.
103         ClassDoc[] classArray = root.specifiedClasses();
104         Vector interfaceVector = new Vector();
105         for (int i = 0; i < classArray.length; ++i) {
106             if (classArray[i].isInterface()) {
107                 interfaceVector.addElement(classArray[i]);
108             } else {
109                 classXML(classArray[i]);
110             }
111         }
112 
113         // Generate for interfaces.
114         Enumeration interfaceEnum = interfaceVector.elements();
115         if (interfaceEnum.hasMoreElements()) {
116             ClassDoc interfaceDoc = (ClassDoc)interfaceEnum.nextElement();
117             interfaceXML(interfaceDoc);
118         }
119         cm.endElement(xmlns, localName, "javadoc");
120     }
121 
122     /**
123      * Generates doc for "package".
124      * <xmp><!ELEMENT package (doc?, package*, class*, interface*)>
125      *<!ATTLIST package
126      *              name CDATA #REQUIRED></xmp>
127      */
128     private void packageXML(PackageDoc packageDoc) throws SAXException {
129         AttributesImpl atts = new AttributesImpl();
130         atts.addAttribute(xmlns, localName, "name", "String", packageDoc.name());
131         cm.startElement(xmlns, localName, "package", atts);
132 
133         // generate Doc element.
134         docXML(packageDoc);
135 
136         // TODO:generate Package elements.
137         // doubt: How package can exist inside a package?
138 
139         /* Generate for classes. */
140         // for ordinary classes.
141         ClassDoc[] classArray = packageDoc.ordinaryClasses();
142         for (int i = 0; i < classArray.length; ++i) {
143             classXML(classArray[i]);
144         }
145         // for Exception classes.
146         classArray = packageDoc.exceptions();
147         for (int i = 0; i < classArray.length; ++i) {
148             classXML(classArray[i]);
149         }
150         // for Error classes
151         classArray = packageDoc.errors();
152         for (int i = 0; i < classArray.length; ++i) {
153             classXML(classArray[i]);
154         }
155 
156         /* Generate for interfaces. */
157         ClassDoc[] interfaceArray = packageDoc.interfaces();
158         for (int i = 0; i < interfaceArray.length; ++i) {
159             interfaceXML(interfaceArray[i]);
160         }
161 
162         cm.endElement(xmlns, localName, "package");
163     }
164 
165     /**
166      * Generates doc for element "class".
167      * <xmp> <!ELEMENT class (doc?,
168      *                  extends_class?,
169      *                  implements?,
170      *                  constructor*,
171      *                  method*,
172      *                  innerclass*)>
173      * <!ATTLIST class
174      *     %name;
175      *     %extensibility;
176      *     %class.access;></xmp>
177      */
178     private void classXML(ClassDoc classDoc) throws SAXException {
179         AttributesImpl atts = new AttributesImpl();
180         atts.addAttribute(xmlns, localName, "name", "String", classDoc.name());
181 
182         String extensibility = "default";
183         if (classDoc.isAbstract()) {
184             extensibility = "abstract";
185         } else if (classDoc.isFinal()) {
186             extensibility = "final";
187         }
188         atts.addAttribute(xmlns, localName, "extensibility", "String", extensibility);
189         String access = "package";
190         if (classDoc.isPublic()) {
191             access = "public";
192         }
193         atts.addAttribute(xmlns, localName, "access", "String", access);
194         cm.startElement(xmlns, localName, "class", atts);
195 
196         // generate "doc" sub-element
197         docXML(classDoc);
198 
199         // generate "extends_class" sub-element
200         extendsXML(classDoc);
201 
202         // generate "implements" sub-element
203         implementsXML(classDoc);
204 
205         // generate "field" sub-elements
206         FieldDoc[] fieldArray = classDoc.fields();
207         for (int i = 0; i < fieldArray.length; ++i) {
208             fieldXML(fieldArray[i]);
209         }
210 
211         // generate "constructor" sub-elements
212         ConstructorDoc[] constructorArray = classDoc.constructors();
213         for (int i = 0; i < constructorArray.length; ++i) {
214             constructorXML(constructorArray[i]);
215         }
216 
217         // generate "method" sub-elements
218         MethodDoc[] methodArray = classDoc.methods();
219         for (int i = 0; i < methodArray.length; ++i) {
220             methodXML(methodArray[i]);
221         }
222 
223         // generate "innerclass" sub-elements
224         ClassDoc[] innerClassArray = classDoc.innerClasses();
225         for (int i = 0; i < innerClassArray.length; ++i) {
226             innerClassXML(innerClassArray[i]);
227         }
228 
229         cm.endElement(xmlns, localName, "class");
230     }
231 
232     /**
233      * Generates doc for element "extends_class"
234      * <xmp><!ELEMENT extends_class (classref+)></xmp>
235      */
236     private void extendsXML(ClassDoc classDoc) throws SAXException {
237         if (classDoc.superclass() != null) {
238             cm.startElement(xmlns, localName, "extends_class", emptyAtts);
239             createRefXML("classref", classDoc.superclass().qualifiedName());
240             cm.endElement(xmlns, localName, "extends_class");
241         }
242     }
243 
244     /**
245      * Generates doc for element "innerclass"
246      * <xmp> <!ELEMENT innerclass (doc?,
247      *                 extends?,
248      *                 implements?,
249      *                 field*,
250      *                 constructor*,
251      *                 method*)>
252      * <!ATTLIST innerclass
253      *    %name;
254      *    %access;
255      *    %abstract;
256      *    %anonymous;
257      *    %final;
258      *    %static;></xmp>
259      */
260     private void innerClassXML(ClassDoc classDoc) throws SAXException {
261         AttributesImpl atts = new AttributesImpl();
262         atts.addAttribute(xmlns, localName, "name", "String", classDoc.name());
263         String access = "package";
264         if (classDoc.isPublic()) {
265             access = "public";
266         }
267         atts.addAttribute(xmlns, localName, "access", "String", access);
268         atts.addAttribute(xmlns, localName, "abstract", "String", ""+ classDoc.isAbstract());
269         String anonymous = "false";
270         if (classDoc.name().equals("")) {
271             anonymous = "true";
272         }
273         atts.addAttribute(xmlns, localName, "anonymous", "String", ""+ anonymous);
274         atts.addAttribute(xmlns, localName, "final", "String", ""+ "" + classDoc.isFinal());
275         atts.addAttribute(xmlns, localName, "static", "String", ""+ "" + classDoc.isStatic());
276         cm.startElement(xmlns, localName, "innerclass", atts);
277 
278         // generate "doc" sub-element
279         docXML(classDoc);
280 
281         // generate "extends" sub-element
282         extendsXML(classDoc);
283 
284         // generate "implements" sub-element
285         implementsXML(classDoc);
286 
287         // generate "field" sub-elements
288         FieldDoc[] fieldArray = classDoc.fields();
289         for (int i = 0; i < fieldArray.length; ++i) {
290             fieldXML(fieldArray[i]);
291         }
292 
293         // generate "constructor" sub-elements
294         ConstructorDoc[] constructorArray = classDoc.constructors();
295         for (int i = 0; i < constructorArray.length; ++i) {
296             constructorXML(constructorArray[i]);
297         }
298 
299         // generate "method" sub-elements
300         MethodDoc[] methodArray = classDoc.methods();
301         for (int i = 0; i < methodArray.length; ++i) {
302             methodXML(methodArray[i]);
303         }
304 
305         cm.endElement(xmlns, localName,"innerclass");
306     }
307 
308     /**
309      * Generates doc for element "interface"
310      * <xmp><!ELEMENT interface (doc?,
311      *               extends_interface?,
312      *               field*,
313      *               method*)>
314      * <!ATTLIST interface
315      *             %name;
316      *             %access;></xmp>
317      */
318     private void interfaceXML(ClassDoc interfaceDoc) throws SAXException {
319         AttributesImpl atts = new AttributesImpl();
320         atts.addAttribute(xmlns, localName, "name", "String", interfaceDoc.name());
321         String access = "package";
322         if (interfaceDoc.isPublic()) {
323             access = "public";
324         }
325         atts.addAttribute(xmlns, localName, "access", "String", access);
326         cm.startElement(xmlns, localName, "interface", atts);
327 
328         // generate "doc" sub-element
329         docXML(interfaceDoc);
330 
331         // generate "extends_interface"
332         extends_interfaceXML(interfaceDoc);
333 
334         // generate "field" sub-elements
335         FieldDoc[] fieldArray = interfaceDoc.fields();
336         for (int i = 0; i < fieldArray.length; ++i) {
337             fieldXML(fieldArray[i]);
338         }
339 
340         // generate "method" sub-elements
341         MethodDoc[] methodArray = interfaceDoc.methods();
342         for (int i = 0; i < methodArray.length; ++i) {
343             methodXML(methodArray[i]);
344         }
345         cm.endElement(xmlns, localName, "interface");
346     }
347 
348     /**
349      * Generates doc for element "extends_interface"
350      * <xmp><!ELEMENT extends_interface (interfaceref+)></xmp>
351      */
352     private void extends_interfaceXML(ClassDoc interfaceDoc) throws SAXException {
353         ClassDoc[] interfaceArray = interfaceDoc.interfaces();
354         if (interfaceArray.length > 0) {
355             cm.startElement(xmlns, localName, "extends_interface", emptyAtts);
356             for (int i = 0; i < interfaceArray.length; ++i) {
357                 createRefXML("interfaceref", interfaceArray[i].qualifiedName());
358             }
359             cm.endElement(xmlns, localName, "extends_interface");
360         }
361     }
362 
363     /**
364      * Generates doc for element "implements"
365      * <xmp><!ELEMENT implements (interfaceref+)></xmp>
366      */
367     private void implementsXML(ClassDoc classDoc) throws SAXException {
368         ClassDoc[] interfaceArray = classDoc.interfaces();
369         if (interfaceArray.length > 0) {
370             cm.startElement(xmlns, localName, "implements", emptyAtts);
371             for (int i = 0; i < interfaceArray.length; ++i) {
372                 createRefXML("interfaceref", interfaceArray[i].qualifiedName());
373             }
374             cm.endElement(xmlns, localName, "implements");
375         }
376         if (classDoc.superclass() != null) {
377             implementsXML(classDoc.superclass());
378         }        
379     }
380 
381     /**
382      * Generates doc for element "throws"
383      * <xmp><!ELEMENT throws (classref)+></xmp>
384      */
385     private void throwsXML(ExecutableMemberDoc member) throws SAXException {
386         ThrowsTag[] tagArray = member.throwsTags();
387         if(tagArray.length > 0) {
388             cm.startElement(xmlns, localName, "throws", emptyAtts);
389             for (int i = 0; i < tagArray.length; ++i) {
390                 ClassDoc exceptionClass = tagArray[i].exception();
391                 String name = null;
392                 if (exceptionClass == null) {
393                     name = tagArray[i].exceptionName();
394                 } else {
395                     name = tagArray[i].exception().qualifiedName();
396                 }
397                 createRefXML("classref", name);
398             }
399             cm.endElement(xmlns, localName, "throws");
400         }
401     }
402 
403     /**
404      * Generates doc for following elements
405      * <xmp> <!ELEMENT classref EMPTY>
406      * <!ATTLIST classref %name;>
407      * <!ELEMENT interfaceref EMPTY>
408      * <!ATTLIST interfaceref %name;>
409      * <!ELEMENT methodref EMPTY>
410      * <!ATTLIST methodref %name;>
411      * <!ELEMENT packageref EMPTY>
412      * <!ATTLIST packageref %name;></xmp>
413      */
414     private void createRefXML(String elementName, String nameValue) throws SAXException {
415         AttributesImpl atts = new AttributesImpl();
416         atts.addAttribute(xmlns, localName, "name", "String", nameValue);
417         cm.startElement(xmlns, localName, elementName, atts);
418         cm.endElement(xmlns, localName, elementName);
419     }
420 
421     /**
422      * Generates doc for "(classref|interfaceref|primitive)" sub-element
423      */
424     private void createTypeRef(Type type) throws SAXException {
425         String qualifiedName = type.qualifiedTypeName();
426         ClassDoc fieldType = type.asClassDoc();
427         if (fieldType == null) {
428             // primitive data type
429             AttributesImpl subElmAtts = new AttributesImpl();
430             subElmAtts.addAttribute(xmlns, localName, "type", "String", qualifiedName);
431             cm.startElement(xmlns, localName, "primitive", subElmAtts);
432             cm.endElement(xmlns, localName, "primitive");
433         } else if (fieldType.isInterface()) {
434             // interface
435             createRefXML("interfaceref", qualifiedName);
436         } else {
437             // class
438             createRefXML("classref", qualifiedName);
439         }
440     }
441 
442     /**
443      * Generates doc for element "field"
444      * <xmp> <!ELEMENT field (doc?, (classref | interfaceref | primitive))>
445      * <!ATTLIST field
446      *    %name;
447      *    %access;
448      *    %dimension;
449      *    %synthetic;
450      *    %static;
451      *    %final;
452      *    %transient;
453      *    %volatile;></xmp>
454      */
455     private void fieldXML(FieldDoc field) throws SAXException {
456         AttributesImpl atts = new AttributesImpl();
457 
458         atts.addAttribute(xmlns, localName, "name", "String", field.name());
459 
460         String access = "package";
461         if (field.isPrivate()) {
462             access = "private";
463         } else if (field.isProtected()) {
464             access = "protected";
465         } else if (field.isPublic()) {
466             access = "public";
467         }
468         atts.addAttribute(xmlns, localName, "access", "String", access);
469 
470         atts.addAttribute(xmlns, localName, "dimension", "String", field.type().dimension());
471         atts.addAttribute(xmlns, localName, "synthetic", "String", "" + field.isSynthetic());
472         atts.addAttribute(xmlns, localName, "static", "String", "" + field.isStatic());
473         atts.addAttribute(xmlns, localName, "final", "String", "" + field.isFinal());
474         atts.addAttribute(xmlns, localName, "transient", "String", "" + field.isTransient());
475         atts.addAttribute(xmlns, localName, "volatile", "String", "" + field.isVolatile());
476         cm.startElement(xmlns, localName, "field", atts);
477 
478         // generate "doc" sub-element
479         docXML(field);
480 
481         // generate "(classref|interfaceref|primitive)" sub-element
482         createTypeRef(field.type()); // foo , field.qualifiedName());
483 
484         cm.endElement(xmlns, localName, "field");
485     }
486 
487     /**
488      * Generates doc for element "constructor"
489      * <xmp><!ELEMENT constructor (doc?, parameter*, throws*)>
490      * <!ATTLIST constructor
491      *     %name;
492      *     %access;
493      *     %synthetic;></xmp>
494      */
495     private void constructorXML(ConstructorDoc constrDoc) throws SAXException {
496         AttributesImpl atts = new AttributesImpl();
497         atts.addAttribute(xmlns, localName, "name", "String", constrDoc.qualifiedName());
498         String access = "package";
499         if (constrDoc.isPrivate()) {
500             access = "private";
501         } else if (constrDoc.isProtected()) {
502             access = "protected";
503         } else if (constrDoc.isPublic()) {
504             access = "public";
505         }
506         atts.addAttribute(xmlns, localName, "access", "String", access);
507         atts.addAttribute(xmlns, localName, "synthetic", "String", "" + constrDoc.isSynthetic());
508         cm.startElement(xmlns, localName, "constructor", atts);
509 
510         // generate "doc" sub-element
511         docXML(constrDoc);
512 
513         // generate "parameter" sub-elements
514         Parameter[] parameterArray = constrDoc.parameters();
515         for (int i = 0; i < parameterArray.length; ++i) {
516             parameterXML(parameterArray[i]);
517         }
518 
519         // generate "throws" sub-element
520         throwsXML(constrDoc);
521 
522         cm.endElement(xmlns, localName, "constructor");
523     }
524 
525     /**
526      * Generates doc for element "method"
527      * <xmp> <!ELEMENT method (doc?, returns, parameter*, throws*)>
528      * <!ATTLIST method
529      *         %name;
530      *         %access;
531      *         %extensibility;
532      *         %native;
533      *         %synthetic;
534      *         %static;
535      *         %synchronized;></xmp>
536      */
537     private void methodXML(MethodDoc methodDoc) throws SAXException {
538         AttributesImpl atts = new AttributesImpl();
539         //atts.addAttribute(xmlns, localName, "", String, );
540         atts.addAttribute(xmlns, localName, "name", "String", methodDoc.name());
541 
542         String access = "package";
543         if (methodDoc.isPrivate()) {
544             access = "private";
545         } else if (methodDoc.isProtected()) {
546             access = "protected";
547         } else if (methodDoc.isPublic()) {
548             access = "public";
549         }
550         atts.addAttribute(xmlns, localName, "access", "String", access);
551 
552         String extensibility = "default";
553         if (methodDoc.isAbstract()) {
554             extensibility = "abstract";
555         } else if (methodDoc.isFinal()) {
556             extensibility = "final";
557         }
558         atts.addAttribute(xmlns, localName, "extensiblity", "String", extensibility);
559 
560         atts.addAttribute(xmlns, localName, "native", "String", ""+ methodDoc.isNative());
561         atts.addAttribute(xmlns, localName, "synthetic", "String", "" + methodDoc.isSynthetic());
562         atts.addAttribute(xmlns, localName, "static", "String", "" + methodDoc.isStatic());
563         atts.addAttribute(xmlns, localName, "synchronized", "String", ""+ methodDoc.isSynchronized());
564         cm.startElement(xmlns, localName, "method", atts);
565 
566         // generate "doc" sub-element
567         docXML(methodDoc);
568 
569         // generate "returns" sub-element
570         returnsXML(methodDoc.returnType());
571 
572         // generate "parameter" sub-elements
573         Parameter[] parameterArray = methodDoc.parameters();
574         for (int i = 0; i < parameterArray.length; ++i) {
575             parameterXML(parameterArray[i]);
576         }
577 
578         // generate "throws" sub-element
579         throwsXML(methodDoc);
580 
581         cm.endElement(xmlns, localName, "method");
582     }
583 
584     /**
585      * Generates doc for element "returns"
586      * <xmp> <!ELEMENT returns (classref | interfaceref | primitive)>
587      * <!ATTLIST returns %dimension;></xmp>
588      */
589     private void returnsXML(Type type) throws SAXException {
590         AttributesImpl atts = new AttributesImpl();
591         atts.addAttribute(xmlns, localName, "dimension", "String", type.dimension());
592         cm.startElement(xmlns, localName, "returns", atts);
593 
594         // generate "(classref|interfaceref|primitive)" sub-element
595         createTypeRef(type);
596 
597         cm.endElement(xmlns, localName, "returns");
598     }
599 
600     /**
601      * Generates doc for element "parameter"
602      * <xmp> <!ELEMENT parameter (classref | interfaceref | primitive)>
603      * <!ATTLIST parameter
604      *         %name;
605      *         %final;
606      *         %dimension;></xmp>
607      */
608     private void parameterXML(Parameter parameter) throws SAXException {
609         AttributesImpl atts = new AttributesImpl();
610         atts.addAttribute(xmlns, localName, "name", "String", parameter.name());
611         boolean isFinal = false;
612         Type type = parameter.type();
613         if (type.asClassDoc() == null) {
614             isFinal = true;
615         }
616         atts.addAttribute(xmlns, localName, "final", "String", ""+ "" + isFinal);
617         atts.addAttribute(xmlns, localName, "dimension", "String", parameter.type().dimension());
618         cm.startElement(xmlns, localName, "parameter", atts);
619 
620         // generate "(classref|interfaceref|primitive)" sub-element
621         createTypeRef(parameter.type());
622 
623         cm.endElement(xmlns, localName,"parameter");
624     }
625 
626     /**
627      * Generates doc for element "doc"
628      * <xmp><!ELEMENT doc (#PCDATA |
629      *              linktag |
630      *              authortag |
631      *              versiontag |
632      *              paramtag |
633      *              returntag |
634      *              exceptiontag |
635      *              throwstag |
636      *              seetag |
637      *              sincetag |
638      *              deprecatedtag |
639      *              serialtag |
640      *              serialfieldtag |
641      *              serialdatatag)*></xmp>
642      */
643     private void docXML(Doc doc) throws SAXException {
644         String commentText = "";
645         boolean createDoc = false;
646         commentText = doc.commentText();
647         if (! commentText.equals("")) {
648             createDoc = true;
649         }
650         Tag[] tags = doc.tags();
651         if (tags.length > 0) {
652             createDoc = true;
653         }
654         if (createDoc) {
655             cm.startElement(xmlns, localName, "doc", emptyAtts);
656             if (! commentText.equals("")) {
657                 cm.characters(commentText.toCharArray(), 0, commentText.length());
658             }
659             for (int i = 0; i < tags.length; ++i) {
660                 tagXML(tags[i]);
661             }
662             cm.endElement(xmlns, localName, "doc");
663         }
664     }
665 
666     /**
667      * Generates doc for all tag elements.
668      */
669     private void tagXML(Tag tag) throws SAXException {
670         String name = tag.name().substring(1) + "tag";
671         if (! tag.text().equals("")) {
672             cm.startElement(xmlns, localName, name, emptyAtts);
673             cm.characters(tag.text().toCharArray(), 0, tag.text().length());
674             cm.endElement(xmlns, localName, name);
675         }
676     }
677 
678     public static boolean start(RootDoc root) {
679         try {
680             new XMLDoclet(root);
681             return true;
682         } catch (Exception e) {
683             e.printStackTrace();
684             System.exit(1);
685             return false;
686         }
687     }
688     
689     private void readOptions(RootDoc root)
690     {
691         String[][] options = root.options();
692         for (int i = 0; i < options.length; i++)
693         {
694             String[] opt = options[i];
695             if (opt[0].equals("-d"))
696             {
697                 targetFileName = opt[1] + "/javadoc.xml";
698             }
699             if (opt[0].equals("-encoding"))
700             {
701                 encodingFormat = opt[1];
702             }
703         }
704     }
705     
706     public static int optionLength(String option)
707     {
708         if(option.equals("-d"))
709         {
710             return 2;
711         }
712         if(option.equals("-encoding"))
713         {
714             return 2;
715         }
716         return 0;
717     }
718     
719     public static boolean validOptions(String options[][], 
720         DocErrorReporter reporter)
721     {
722         boolean foundEncodingOption = false;
723         boolean foundDirOption = false;
724         for (int i = 0; i < options.length; i++)
725         {
726             String[] opt = options[i];
727             if (opt[0].equals("-d"))
728             {
729                 if (foundDirOption)
730                 {
731                     reporter.printError("Only one -d option allowed.");
732                     return false;
733                 }
734                 else
735                 { 
736                     foundDirOption = true;
737                 }
738             } 
739             if (opt[0].equals("-encoding"))
740             {
741                 if (foundEncodingOption)
742                 {
743                     reporter.printError("Only one -encoding option allowed.");
744                     return false;
745                 }
746                 else
747                 { 
748                     foundEncodingOption = true;
749                 }
750             } 
751         }
752         if (!foundDirOption)
753         {
754             reporter.printError("Usage: javadoc -d <directory> -doclet TagXMLDoclet ...");
755             return false;
756         }
757         return true;
758     }
759 }