123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- /* -*- Mode: JDE; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * This file is part of the debugger and core tools for the AspectJ(tm)
- * programming language; see http://aspectj.org
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is AspectJ.
- *
- * The Initial Developer of the Original Code is Xerox Corporation. Portions
- * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
- * All Rights Reserved.
- */
- package org.aspectj.tools.doclets.standard;
-
- import org.aspectj.ajdoc.AspectDoc;
-
- import com.sun.javadoc.ClassDoc;
- import com.sun.javadoc.DocErrorReporter;
- import com.sun.javadoc.PackageDoc;
- import com.sun.javadoc.RootDoc;
- import com.sun.tools.doclets.ClassTree;
- import com.sun.tools.doclets.DocletAbortException;
- import com.sun.tools.doclets.HtmlDocWriter;
- import com.sun.tools.doclets.IndexBuilder;
-
- import java.io.IOException;
- import java.lang.reflect.Constructor;
- import java.util.Arrays;
-
- /**
- * An abstract allowing one to customize the writers
- * used in ajdoc. Subclasses should define the three
- * generate methods to specify the documentation made.
- *
- * @see #preGenerationClasses()
- * @see #postGenerationClasses()
- * @see #checkClasses()
- * @author Jeff Palm
- */
- public abstract class AbstractStandard
- extends com.sun.tools.doclets.standard.Standard {
-
- // todo wes removed restriction, but implemented Standard as singleton via proxy
- private static int refCount = 0;
- {
- if (refCount > 0) {
- System.err.println("Warning: " + refCount + " AbstractStandard already ");
- }
- refCount++;
- }
-
- /**
- * The ClassTree that is available to subclasses and it gaurateed
- * to be created before pre-generating classes.
- */
- protected ClassTree classtree;
-
- protected static boolean start(AbstractStandard as,
- RootDoc root) throws IOException {
- try {
- as.getConfiguration().setOptions(root);
- as.startGeneration(root);
- } catch (DocletAbortException exc) {
- return false;
- }
- return true;
- }
-
- /**
- * Returns the types of {@link Pass}es that will
- * run before generating classes.
- *
- * @return an array of Class, where each entry
- * is a subclass of {@link Pass}, ordered
- * to run directly before generating the
- * classes.
- */
- protected abstract Class[] preGenerationClasses();
-
- /**
- * Returns the types of {@link Pass}es that will
- * run after generating classes.
- *
- * @return an array of Class, where each entry
- * is a subclass of {@link Pass}, ordered
- * to run directly after generating the
- * classes.
- */
- protected abstract Class[] postGenerationClasses();
-
- /**
- * Returns the types of {@link CheckPass}es that will
- * run to check the classes.
- *
- * @return an array of Class, where each entry
- * is a subclass of {@link CheckPass}, ordered
- * to run in order to check the classes passed
- * into the class generation phase.
- */
- protected abstract Class[] checkClasses();
-
- /**
- * Return the configuration used by a subclass. This
- * allows the subclass to specify it's own kind.
- *
- * @return a customized configuration.
- */
- public abstract ConfigurationStandard getConfiguration();
-
- protected ConfigurationStandard makeConfiguration() {
- return new ConfigurationStandard();
- }
-
-
- /**
- * Returns the configuration, and ensures that
- * HtmlDocWriter.configuration is of the type used by
- * this class.
- *
- * @return the current instanceof ConfigurationStandard being
- * used and creates one if needed. This will <b>not</b>
- * be null.
- */
- // todo these are the heinous globals that impose one process per classloader
- public static com.sun.tools.doclets.standard.ConfigurationStandard
- configuration() {
- if (HtmlDocWriter.configuration == null ||
- !(HtmlDocWriter.configuration instanceof ConfigurationStandard)) {
- HtmlDocWriter.configuration = new ConfigurationStandard();
- //TODO: change to makeConfiguration()
- }
- return (ConfigurationStandard)HtmlDocWriter.configuration;
- }
-
- /**
- * Creates and returns an IndexBuilder that includes aspects.
- *
- * @param root RootDoc to pass the new IndexBuilder.
- * @param classesOnly <code>true</code> if only classes
- * should be included.
- * @return an IndexBuilder that includes aspects.
- */
- protected IndexBuilder indexBuilder(RootDoc root, boolean classesOnly) {
- class MyIndexBuilder extends IndexBuilder {
- public MyIndexBuilder(RootDoc r, boolean n) {
- super(r, n);
- }
- public MyIndexBuilder(RootDoc r, boolean n, boolean b) {
- super(r, n, b);
- }
- protected void putMembersInIndexMap(ClassDoc classdoc) {
- super.putMembersInIndexMap(classdoc);
- if (classdoc instanceof org.aspectj.ajdoc.ClassDoc) {
- org.aspectj.ajdoc.ClassDoc cd =
- (org.aspectj.ajdoc.ClassDoc)classdoc;
- adjustIndexMap(cd.pointcuts());
- if (cd instanceof AspectDoc) {
- adjustIndexMap(((AspectDoc)cd).advice());
- }
- }
- }
- }
- return new MyIndexBuilder(root, configuration().nodeprecated, classesOnly);
- }
-
-
- /**
- * Does the work in generating the documentation.
- * First, call all the passes return from {@link #generateCheckPasses}
- * them perform some copying. Second build the classtree, run the
- * pre-classgeneration passes, generate the packages, generate the
- * classes, then call all the postGenerationClasses.
- *
- * @param root the root of the documentation.
- */
- protected void startGeneration(RootDoc root) throws DocletAbortException {
-
- if (!generateCheckPasses(getConfiguration(), root)) return;
-
- performCopy(getConfiguration().destdirname,
- getConfiguration().helpfile);
- performCopy(getConfiguration().destdirname,
- getConfiguration().stylesheetfile);
-
- classtree = new ClassTree(root, getConfiguration().nodeprecated);
-
- generatePrePasses(getConfiguration(), root);
-
- generatePackageCycle(getConfiguration().packages,
- getConfiguration().createtree,
- getConfiguration().nodeprecated);
- generateClassFiles(root, classtree);
- generatePostPasses(getConfiguration(), root);
- }
-
- /**
- * A class representing a single pass in the generation cycles. It
- * does some of the dirty work for you.
- */
- public static abstract class Pass {
-
- /** The root available to this pass. */
- protected RootDoc root;
-
- /** The configuration available to this pass. */
- protected ConfigurationStandard cs;
-
- /** The doclet available to this pass. */
- protected AbstractStandard std;
-
- public Pass() {}
-
- /**
- * Returns the title of the pass for logging.
- *
- * @return the unique title of this pass. This can
- * be <code>null</code> to disable display.
- */
- public abstract String title();
-
- /**
- * Do the generation work. All instance variables
- * are guaranteed to be set.
- */
- protected abstract void gen() throws DocletAbortException;
-
- /**
- * Do the actual generation if {@link #cond} returns
- * <code>true</code>. Do some other logging, too.
- *
- * @param std the AbstractStandard to use.
- * @param cs the ConfigurationStandard to use.
- * @param root the RootDoc to use.
- */
- public final void generate(AbstractStandard std,
- ConfigurationStandard cs,
- RootDoc root)
- throws DocletAbortException {
- this.std = std;
- this.cs = cs;
- this.root = root;
- if (cond()) {
- String title = title();
- long start = System.currentTimeMillis();
- if (cs.log && title != null) {
- cs.standardmessage.notice("doclet.pass_msg", title);
- }
- gen();
- if (cs.log && title != null) {
- long stop = System.currentTimeMillis();
- cs.standardmessage.notice("doclet.done_msg",
- title, (stop-start)+"");
- }
- }
- }
-
- /**
- * Returns whether the generation should proceed. Override
- * this method for conditional passes.
- *
- * @return <code>true</code> is this pass shoulud proceed.
- */
- protected boolean cond() {
- return true;
- }
- }
-
- /**
- * A convenience class for doing checks.
- */
- public abstract static class Check extends Pass {
-
- /**
- * Returns the error message if check fails.
- *
- * @return error message if check fails.
- */
- protected abstract String message();
-
- /**
- * Returns whether check has failed or not.
- *
- * @return <code>true</code> is check fails.
- */
- protected abstract boolean cond();
-
- /**
- * Prints message, because we've failed and throws
- * a DocletAbortException to notify the doclet
- * that we've failed.
- */
- protected void gen() throws DocletAbortException {
- cs.standardmessage.error(message());
- throw new DocletAbortException();
- }
-
- /**
- * Returns null, because we don't want to be displayed.
- *
- * @return <code>null</code>.
- */
- public String title() { return null; }
- }
-
- /**
- * Generates the passes to run before generating the classes.
- */
- private final void generatePrePasses(ConfigurationStandard cs,
- RootDoc root)
- throws DocletAbortException {
- generatePasses(cs, root, preGenerationClasses());
- }
-
- /**
- * Generates the passes to run after generating the classes.
- */
- private final void generatePostPasses(ConfigurationStandard cs,
- RootDoc root)
- throws DocletAbortException {
- generatePasses(cs, root, postGenerationClasses());
- }
-
- /**
- * Generates the passes that run before doing anything. These
- * passes check that it's OK to do anything.
- */
- private final boolean generateCheckPasses(ConfigurationStandard cs,
- RootDoc root)
- throws DocletAbortException {
- try {
- generatePasses(cs, root, checkClasses());
- } catch (DocletAbortException e) {
- return false;
- }
- return true;
- }
-
- /**
- * Generates passes from <code>classes</code>. For each
- * class found in <code>classes</code> a constructor taking zero
- * or one-argument is called. Then the generate method is
- * called on that Pass passing it <code>this</code>, the
- * configuration, and root.
- *
- * @param cs configuration to use.
- * @param root root we're documenting.
- * @param classes list of subtypes of {@link Pass} that
- * will be run.
- */
- private final void generatePasses(ConfigurationStandard cs,
- RootDoc root,
- Class[] classes)
- throws DocletAbortException {
- if (classes == null) return;
- nextClass:
- for (int i = 0; i < classes.length; i++) {
- try {
- Constructor[] ctrs = classes[i].getConstructors();
- nextCtr:
- for (int j = 0; j < ctrs.length; j++) {
- Pass pass = null;
- if (ctrs[j].getParameterTypes().length == 0) {
- pass = (Pass)ctrs[j].newInstance(new Object[]{});
- } else if (ctrs[j].getParameterTypes().length == 1) {
- pass = (Pass)ctrs[j].newInstance(new Object[]{this});
- }
- if (pass != null) {
- pass.generate(this,cs,root);
- continue nextClass;
- }
- }
- throw new Exception("Can't create pass for class " + classes[i]);
- } catch (Exception e) {
- e.printStackTrace();
- Standard.configuration().standardmessage.
- error("doclet.exception", e+"");
- throw new DocletAbortException();
- }
- }
- }
-
-
- /**
- * Generates the packages.
- */
- protected void generatePackageCycle(PackageDoc[] pkgs,
- boolean createtree,
- boolean nodeprecated)
- throws DocletAbortException {
- Arrays.sort(pkgs);
- for (int i = 0; i < pkgs.length; i++) {
- PackageDoc prev = i == 0 ? null : pkgs[i-1];
- PackageDoc curr = pkgs[i];
- PackageDoc next = i == pkgs.length-1 ? null : pkgs[i+1];
- generatePackages(prev, curr, next,
- createtree, nodeprecated);
- }
- }
-
- /**
- * Generates a package doc for the three PackageDocs passed.
- */
- protected void generatePackages(PackageDoc prev,
- PackageDoc curr,
- PackageDoc next,
- boolean createtree,
- boolean nodeprecated)
- throws DocletAbortException {
- PackageWriter.generate(curr, prev, next);
- if (createtree) {
- PackageTreeWriter.generate(curr, prev,
- next, nodeprecated);
- }
- PackageFrameWriter.generate(curr);
- }
-
- /**
- * Generates all the classes.
- */
- protected void generateClassCycle(ClassDoc[] cs,
- ClassTree classtree,
- boolean nopackage)
- throws DocletAbortException {
- Arrays.sort(cs);
- for(int i = 0; i < cs.length; i++) {
- if (configuration().nodeprecated &&
- cs[i].tags("deprecated").length > 0) {
- continue;
- }
- ClassDoc prev = i == 0 ? null : cs[i-1];
- ClassDoc curr = cs[i];
- ClassDoc next = i == cs.length-1 ? null : cs[i+1];
- generateClasses(prev, curr, next,
- classtree, nopackage);
- }
- }
-
- /**
- * Generates class docs for the three ClassDocs passed.
- */
- protected void generateClasses(ClassDoc prev,
- ClassDoc curr,
- ClassDoc next,
- ClassTree classtree,
- boolean nopackage)
- throws DocletAbortException {
- ClassWriter.generate(curr, prev, next,
- classtree, nopackage);
- }
-
- /**
- * Returns the delegation to {@link #configuration()}.
- */
- public static int optionLength(String option) {
- return configuration().optionLength(option);
- }
-
- /**
- * Returns the delegation to {@link #configuration()}.
- */
- public static boolean validOptions(String options[][],
- DocErrorReporter reporter)
- throws IOException {
- return configuration().validOptions(options, reporter);
- }
- }
-
|