AbstractDoclet.java revision 3595:81692f730015
1/*
2 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.javadoc.internal.doclets.toolkit;
27
28import java.util.SortedSet;
29import java.util.TreeSet;
30
31import javax.lang.model.SourceVersion;
32import javax.lang.model.element.PackageElement;
33import javax.lang.model.element.TypeElement;
34
35import jdk.javadoc.doclet.Doclet;
36import jdk.javadoc.doclet.DocletEnvironment;
37import jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder;
38import jdk.javadoc.internal.doclets.toolkit.builders.BuilderFactory;
39import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
40import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
41import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
42import jdk.javadoc.internal.doclets.toolkit.util.PackageListWriter;
43import jdk.javadoc.internal.doclets.toolkit.util.Utils;
44
45import static javax.tools.Diagnostic.Kind.*;
46
47/**
48 * An abstract implementation of a Doclet.
49 *
50 *  <p><b>This is NOT part of any supported API.
51 *  If you write code that depends on this, you do so at your own risk.
52 *  This code and its internal interfaces are subject to change or
53 *  deletion without notice.</b>
54 *
55 * @author Jamie Ho
56 */
57public abstract class AbstractDoclet implements Doclet {
58
59    /**
60     * The global configuration information for this run.
61     */
62    private Configuration configuration;
63
64    protected Messages messages;
65
66    /*
67     *  a handle to our utility methods
68     */
69    protected Utils utils;
70
71    /**
72     * The only doclet that may use this toolkit is {@value}
73     */
74    private static final String TOOLKIT_DOCLET_NAME =
75        jdk.javadoc.internal.doclets.formats.html.HtmlDoclet.class.getName();
76
77    /**
78     * Verify that the only doclet that is using this toolkit is
79     * {@value #TOOLKIT_DOCLET_NAME}.
80     */
81    private boolean isValidDoclet() {
82        if (!getClass().getName().equals(TOOLKIT_DOCLET_NAME)) {
83            messages.error("doclet.Toolkit_Usage_Violation",
84                TOOLKIT_DOCLET_NAME);
85            return false;
86        }
87        return true;
88    }
89
90    /**
91     * The method that starts the execution of the doclet.
92     *
93     * @param docEnv   the {@link DocletEnvironment}.
94     * @return true if the doclet executed without error.  False otherwise.
95     */
96    @Override
97    public boolean run(DocletEnvironment docEnv) {
98        configuration = configuration();
99        configuration.docEnv = docEnv;
100        configuration.cmtUtils = new CommentUtils(configuration);
101        configuration.utils = new Utils(configuration);
102        utils = configuration.utils;
103        configuration.workArounds = new WorkArounds(configuration);
104        messages = configuration.getMessages();
105
106        if (!isValidDoclet()) {
107            return false;
108        }
109
110        try {
111            startGeneration(docEnv);
112        } catch (Configuration.Fault f) {
113            configuration.reporter.print(ERROR, f.getMessage());
114            return false;
115        } catch (DocletAbortException e) {
116            Throwable cause = e.getCause();
117            if (cause != null) {
118                if (cause.getLocalizedMessage() != null) {
119                    configuration.reporter.print(ERROR, cause.getLocalizedMessage());
120                } else {
121                    configuration.reporter.print(ERROR, cause.toString());
122                }
123            }
124            return false;
125        } catch (Exception exc) {
126            exc.printStackTrace(System.err);
127            return false;
128        }
129        return true;
130    }
131
132    /**
133     * Returns the SourceVersion indicating the features supported by this doclet.
134     * @return SourceVersion
135     */
136    @Override
137    public SourceVersion getSupportedSourceVersion() {
138        return SourceVersion.RELEASE_9;
139    }
140
141
142    /**
143     * Create the configuration instance and returns it.
144     * @return the configuration of the doclet.
145     */
146    public abstract Configuration configuration();
147
148    /**
149     * Start the generation of files. Call generate methods in the individual
150     * writers, which will in turn generate the documentation files. Call the
151     * TreeWriter generation first to ensure the Class Hierarchy is built
152     * first and then can be used in the later generation.
153     *
154     * @see jdk.doclet.DocletEnvironment
155     */
156    private void startGeneration(DocletEnvironment docEnv) throws Configuration.Fault, Exception {
157        if (docEnv.getIncludedTypeElements().isEmpty()) {
158            messages.error("doclet.No_Public_Classes_To_Document");
159            return;
160        }
161        if (!configuration.setOptions()) {
162            return;
163        }
164        messages.notice("doclet.build_version",
165            configuration.getDocletSpecificBuildDate());
166        ClassTree classtree = new ClassTree(configuration, configuration.nodeprecated);
167
168        generateClassFiles(docEnv, classtree);
169        configuration.utils.copyDocFiles(DocPaths.DOC_FILES);
170
171        PackageListWriter.generate(configuration);
172        generatePackageFiles(classtree);
173        generateModuleFiles();
174
175        generateOtherFiles(docEnv, classtree);
176        configuration.tagletManager.printReport();
177    }
178
179    /**
180     * Generate additional documentation that is added to the API documentation.
181     *
182     * @param docEnv     the DocletEnvironment.
183     * @param classtree the data structure representing the class tree.
184     */
185    protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree) throws Exception {
186        BuilderFactory builderFactory = configuration.getBuilderFactory();
187        AbstractBuilder constantsSummaryBuilder = builderFactory.getConstantsSummaryBuilder();
188        constantsSummaryBuilder.build();
189        AbstractBuilder serializedFormBuilder = builderFactory.getSerializedFormBuilder();
190        serializedFormBuilder.build();
191    }
192
193    /**
194     * Generate the module documentation.
195     *
196     */
197    protected abstract void generateModuleFiles() throws Exception;
198
199    /**
200     * Generate the package documentation.
201     *
202     * @param classtree the data structure representing the class tree.
203     */
204    protected abstract void generatePackageFiles(ClassTree classtree) throws Exception;
205
206    /**
207     * Generate the class documentation.
208     *
209     * @param classtree the data structure representing the class tree.
210     */
211    protected abstract void generateClassFiles(SortedSet<TypeElement> arr, ClassTree classtree);
212
213    /**
214     * Iterate through all classes and construct documentation for them.
215     *
216     * @param docEnv      the DocletEnvironment.
217     * @param classtree the data structure representing the class tree.
218     */
219    protected void generateClassFiles(DocletEnvironment docEnv, ClassTree classtree) {
220        generateClassFiles(classtree);
221        SortedSet<PackageElement> packages = new TreeSet<>(utils.makePackageComparator());
222        packages.addAll(configuration.getSpecifiedPackages());
223        configuration.modulePackages.values().stream().forEach(pset -> {
224            packages.addAll(pset);
225        });
226        packages.stream().forEach((pkg) -> {
227            generateClassFiles(utils.getAllClasses(pkg), classtree);
228        });
229    }
230
231    /**
232     * Generate the class files for single classes specified on the command line.
233     *
234     * @param classtree the data structure representing the class tree.
235     */
236    private void generateClassFiles(ClassTree classtree) {
237        SortedSet<PackageElement> packages = configuration.typeElementCatalog.packages();
238        packages.stream().forEach((pkg) -> {
239            generateClassFiles(configuration.typeElementCatalog.allClasses(pkg), classtree);
240        });
241    }
242}
243