/* gnu.classpath.tools.doclets.AbstractDoclet Copyright (C) 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ package gnu.classpath.tools.doclets; import com.sun.javadoc.ClassDoc; import com.sun.javadoc.ConstructorDoc; import com.sun.javadoc.Doc; import com.sun.javadoc.Doclet; import com.sun.javadoc.FieldDoc; import com.sun.javadoc.MethodDoc; import com.sun.javadoc.PackageDoc; import com.sun.javadoc.Parameter; import com.sun.javadoc.RootDoc; import com.sun.javadoc.Tag; import com.sun.tools.doclets.Taglet; import gnu.classpath.tools.taglets.AuthorTaglet; import gnu.classpath.tools.taglets.DeprecatedTaglet; import gnu.classpath.tools.taglets.GenericTaglet; import gnu.classpath.tools.taglets.SinceTaglet; import gnu.classpath.tools.taglets.VersionTaglet; import gnu.classpath.tools.taglets.TagletContext; import gnu.classpath.tools.IOToolkit; import gnu.classpath.tools.FileSystemClassLoader; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import java.util.Set; import java.util.SortedSet; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.TreeSet; /** * An abstract Doclet implementation with helpers for common tasks * performed by Doclets. */ public abstract class AbstractDoclet { /** * Mapping from tag type to Taglet for user Taglets specified on * the command line. */ private Map tagletMap = new LinkedHashMap(); /** * Stores the package groups specified in the user * options. Contains objects of type PackageGroup. */ private List packageGroups = new LinkedList(); /** * The current classpath for loading taglet classes. */ private String tagletPath; /** * Keeps track of the tags mentioned by the user during option * processiong so that an error can be emitted if a tag is * mentioned more than once. */ private List mentionedTags = new LinkedList(); public static int optionLength(String option) { return instance.getOptionLength(option); } public static boolean validOptions(String[][] options) { return true; } private static AbstractDoclet instance; protected static void setInstance(AbstractDoclet instance) { AbstractDoclet.instance = instance; } protected abstract void run() throws IOException; public static boolean start(RootDoc rootDoc) { try { instance.startInstance(rootDoc); return true; } catch (DocletConfigurationException e) { System.err.println(e.getMessage()); return false; } catch (Exception e) { e.printStackTrace(); return false; } } protected RootDoc getRootDoc() { return this.rootDoc; } private RootDoc rootDoc; private void startInstance(RootDoc rootDoc) throws DocletConfigurationException, IOException { this.rootDoc = rootDoc; // Set the default Taglet order registerTaglet(new VersionTaglet()); registerTaglet(new AuthorTaglet()); registerTaglet(new SinceTaglet()); registerTaglet(new StandardTaglet("deprecated")); registerTaglet(new StandardTaglet("see")); registerTaglet(new StandardTaglet("param")); // Process command line options for (int i=0, ilim=rootDoc.options().length; i 0) { printError("Taglet class '" + optionArr[1] + "' found, but register method contains throws clause."); } else if ((registerTagletMethod.getModifiers() & (Modifier.STATIC | Modifier.PUBLIC | Modifier.ABSTRACT)) != (Modifier.STATIC | Modifier.PUBLIC)) { printError("Taglet class '" + optionArr[1] + "' found, but register method isn't public static, or is abstract.."); } else { Map tempMap = new HashMap(); registerTagletMethod.invoke(null, new Object[] { tempMap }); tagletLoaded = true; String name = (String)tempMap.keySet().iterator().next(); Taglet taglet = (Taglet)tempMap.get(name); tagletMap.put(name, taglet); mentionedTags.add(taglet); } } catch (NoSuchMethodException e) { printError("Taglet class '" + optionArr[1] + "' found, but doesn't contain the register method."); } catch (SecurityException e) { printError("Taglet class '" + optionArr[1] + "' cannot be loaded: " + e.getMessage()); } catch (InvocationTargetException e) { printError("Taglet class '" + optionArr[1] + "' found, but register method throws exception: " + e.toString()); } catch (IllegalAccessException e) { printError("Taglet class '" + optionArr[1] + "' found, but there was a problem when accessing the register method: " + e.toString()); } catch (IllegalArgumentException e) { printError("Taglet class '" + optionArr[1] + "' found, but there was a problem when accessing the register method: " + e.toString()); } catch (ClassNotFoundException e) { printError("Taglet class '" + optionArr[1] + "' cannot be found."); } return tagletLoaded; } } private class DocletOptionGroup extends DocletOption { DocletOptionGroup(String optionName) { super(optionName); } public int getLength() { return 3; } public boolean set(String[] optionArr) { try { PackageMatcher packageMatcher = new PackageMatcher(); StringTokenizer tokenizer = new StringTokenizer(optionArr[2], ":"); while (tokenizer.hasMoreTokens()) { String packageWildcard = tokenizer.nextToken(); packageMatcher.addWildcard(packageWildcard); } SortedSet groupPackages = packageMatcher.match(rootDoc.specifiedPackages()); packageGroups.add(new PackageGroup(optionArr[1], groupPackages)); return true; } catch (InvalidPackageWildcardException e) { return false; } } } private class DocletOptionTagletPath extends DocletOption { DocletOptionTagletPath(String optionName) { super(optionName); } public int getLength() { return 2; } public boolean set(String[] optionArr) { AbstractDoclet.this.tagletPath = optionArr[1]; return true; } } private class DocletOptionTag extends DocletOption { DocletOptionTag(String optionName) { super(optionName); } public int getLength() { return 2; } public boolean set(String[] optionArr) { String tagSpec = optionArr[1]; boolean validTagSpec = false; int ndx1 = tagSpec.indexOf(':'); if (ndx1 < 0) { Taglet taglet = (Taglet)tagletMap.get(tagSpec); if (null == taglet) { printError("There is no standard tag '" + tagSpec + "'."); } else { if (mentionedTags.contains(taglet)) { printError("Tag '" + tagSpec + "' has been added or moved before."); } else { mentionedTags.add(taglet); // re-append taglet tagletMap.remove(tagSpec); tagletMap.put(tagSpec, taglet); } } } else { int ndx2 = tagSpec.indexOf(':', ndx1 + 1); if (ndx2 > ndx1 && ndx2 < tagSpec.length() - 1) { String tagName = tagSpec.substring(0, ndx1); String tagHead = null; if (tagSpec.charAt(ndx2 + 1) == '\"') { if (tagSpec.charAt(tagSpec.length() - 1) == '\"') { tagHead = tagSpec.substring(ndx2 + 2, tagSpec.length() - 1); validTagSpec = true; } } else { tagHead = tagSpec.substring(ndx2 + 1); validTagSpec = true; } boolean tagScopeOverview = false; boolean tagScopePackages = false; boolean tagScopeTypes = false; boolean tagScopeConstructors = false; boolean tagScopeMethods = false; boolean tagScopeFields = false; boolean tagDisabled = false; tag_option_loop: for (int n=ndx1+1; n:Xaoptcmf:\"."); } return validTagSpec; } } private DocletOption[] commonOptions = { optionTargetDirectory, optionAuthor, optionVersion, optionNoSince, optionNoDeprecated, optionGroup, optionDocFilesSubDirs, optionExcludeDocFilesSubDir, optionTagletPath, optionTaglet, optionTag, }; private void registerOptions() { if (!optionsRegistered) { for (int i=0; i Title for this set of API documentation (deprecated, -doctitle should be used instead).\n" + " -link Link to external javadoc-generated documentation you want to link to\n" + " -linkoffline Link to external javadoc-generated documentation for the specified package-list\n" + " -noqualifier all| Do not qualify package name from ahead of class names\n" + " -nocomment Suppress the entire comment body including the main description and all tags, only generate the declarations\n" */