001    /*
002     * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.doclets.internal.toolkit;
027    
028    import com.sun.tools.doclets.internal.toolkit.builders.*;
029    import com.sun.tools.doclets.internal.toolkit.util.*;
030    import com.sun.javadoc.*;
031    import java.util.*;
032    import java.io.*;
033    
034    /**
035     * An abstract implementation of a Doclet.
036     *
037     * This code is not part of an API.
038     * It is implementation that is subject to change.
039     * Do not use it as an API.
040     *
041     * @author Jamie Ho
042     */
043    public abstract class AbstractDoclet {
044    
045        /**
046         * The global configuration information for this run.
047         */
048        public Configuration configuration;
049    
050        /**
051         * The only doclet that may use this toolkit is {@value}
052         */
053        private static final String TOOLKIT_DOCLET_NAME = new
054            com.sun.tools.doclets.formats.html.HtmlDoclet().getClass().getName();
055    
056        /**
057         * Verify that the only doclet that is using this toolkit is
058         * {@value #TOOLKIT_DOCLET_NAME}.
059         */
060        private boolean isValidDoclet(AbstractDoclet doclet) {
061            if (! doclet.getClass().getName().equals(TOOLKIT_DOCLET_NAME)) {
062                configuration.message.error("doclet.Toolkit_Usage_Violation",
063                    TOOLKIT_DOCLET_NAME);
064                return false;
065            }
066            return true;
067        }
068    
069        /**
070         * The method that starts the execution of the doclet.
071         *
072         * @param doclet the doclet to start the execution for.
073         * @param root   the {@link RootDoc} that points to the source to document.
074         * @return true if the doclet executed without error.  False otherwise.
075         */
076        public boolean start(AbstractDoclet doclet, RootDoc root) {
077            configuration = configuration();
078            configuration.root = root;
079            if (! isValidDoclet(doclet)) {
080                return false;
081            }
082            try {
083                doclet.startGeneration(root);
084            } catch (Exception exc) {
085                exc.printStackTrace();
086                return false;
087            }
088            return true;
089        }
090    
091        /**
092         * Indicate that this doclet supports the 1.5 language features.
093         * @return JAVA_1_5, indicating that the new features are supported.
094         */
095        public static LanguageVersion languageVersion() {
096            return LanguageVersion.JAVA_1_5;
097        }
098    
099    
100        /**
101         * Create the configuration instance and returns it.
102         * @return the configuration of the doclet.
103         */
104        public abstract Configuration configuration();
105    
106        /**
107         * Start the generation of files. Call generate methods in the individual
108         * writers, which will in turn genrate the documentation files. Call the
109         * TreeWriter generation first to ensure the Class Hierarchy is built
110         * first and then can be used in the later generation.
111         *
112         * @see com.sun.javadoc.RootDoc
113         */
114        private void startGeneration(RootDoc root) throws Exception {
115            if (root.classes().length == 0) {
116                configuration.message.
117                    error("doclet.No_Public_Classes_To_Document");
118                return;
119            }
120            configuration.setOptions();
121            configuration.getDocletSpecificMsg().notice("doclet.build_version",
122                configuration.getDocletSpecificBuildDate());
123            ClassTree classtree = new ClassTree(configuration, configuration.nodeprecated);
124    
125            generateClassFiles(root, classtree);
126            if (configuration.sourcepath != null && configuration.sourcepath.length() > 0) {
127                StringTokenizer pathTokens = new StringTokenizer(configuration.sourcepath,
128                    String.valueOf(File.pathSeparatorChar));
129                boolean first = true;
130                while(pathTokens.hasMoreTokens()){
131                    Util.copyDocFiles(configuration,
132                        pathTokens.nextToken() + File.separator,
133                        DocletConstants.DOC_FILES_DIR_NAME, first);
134                    first = false;
135                }
136            }
137    
138            PackageListWriter.generate(configuration);
139            generatePackageFiles(classtree);
140    
141            generateOtherFiles(root, classtree);
142            configuration.tagletManager.printReport();
143        }
144    
145        /**
146         * Generate additional documentation that is added to the API documentation.
147         *
148         * @param root      the RootDoc of source to document.
149         * @param classtree the data structure representing the class tree.
150         */
151        protected void generateOtherFiles(RootDoc root, ClassTree classtree) throws Exception {
152            BuilderFactory builderFactory = configuration.getBuilderFactory();
153            AbstractBuilder constantsSummaryBuilder = builderFactory.getConstantsSummaryBuider();
154            constantsSummaryBuilder.build();
155            AbstractBuilder serializedFormBuilder = builderFactory.getSerializedFormBuilder();
156            serializedFormBuilder.build();
157        }
158    
159        /**
160         * Generate the package documentation.
161         *
162         * @param classtree the data structure representing the class tree.
163         */
164        protected abstract void generatePackageFiles(ClassTree classtree) throws Exception;
165    
166        /**
167         * Generate the class documentation.
168         *
169         * @param classtree the data structure representing the class tree.
170         */
171        protected abstract void generateClassFiles(ClassDoc[] arr, ClassTree classtree);
172    
173        /**
174         * Iterate through all classes and construct documentation for them.
175         *
176         * @param root      the RootDoc of source to document.
177         * @param classtree the data structure representing the class tree.
178         */
179        protected void generateClassFiles(RootDoc root, ClassTree classtree) {
180            generateClassFiles(classtree);
181            PackageDoc[] packages = root.specifiedPackages();
182            for (int i = 0; i < packages.length; i++) {
183                generateClassFiles(packages[i].allClasses(), classtree);
184            }
185        }
186    
187        /**
188         * Generate the class files for single classes specified on the command line.
189         *
190         * @param classtree the data structure representing the class tree.
191         */
192        private void generateClassFiles(ClassTree classtree) {
193            String[] packageNames = configuration.classDocCatalog.packageNames();
194            for (int packageNameIndex = 0; packageNameIndex < packageNames.length;
195                    packageNameIndex++) {
196                generateClassFiles(configuration.classDocCatalog.allClasses(
197                    packageNames[packageNameIndex]), classtree);
198            }
199        }
200    }