AbstractDoclet.java revision 3896:8e4dbcb99277
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.doclets.StandardDoclet;
38import jdk.javadoc.internal.doclets.formats.html.HtmlDoclet;
39import jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder;
40import jdk.javadoc.internal.doclets.toolkit.builders.BuilderFactory;
41import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
42import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
43import jdk.javadoc.internal.doclets.toolkit.util.UncheckedDocletException;
44import jdk.javadoc.internal.doclets.toolkit.util.InternalException;
45import jdk.javadoc.internal.doclets.toolkit.util.PackageListWriter;
46import jdk.javadoc.internal.doclets.toolkit.util.ResourceIOException;
47import jdk.javadoc.internal.doclets.toolkit.util.SimpleDocletException;
48import jdk.javadoc.internal.doclets.toolkit.util.Utils;
49
50import static javax.tools.Diagnostic.Kind.*;
51
52/**
53 * An abstract implementation of a Doclet.
54 *
55 *  <p><b>This is NOT part of any supported API.
56 *  If you write code that depends on this, you do so at your own risk.
57 *  This code and its internal interfaces are subject to change or
58 *  deletion without notice.</b>
59 *
60 * @author Jamie Ho
61 */
62public abstract class AbstractDoclet implements Doclet {
63
64    /**
65     * The global configuration information for this run.
66     */
67    private Configuration configuration;
68
69    protected Messages messages;
70
71    /*
72     *  a handle to our utility methods
73     */
74    protected Utils utils;
75
76    /**
77     * The only doclet that may use this toolkit is {@value}
78     */
79    private static final String TOOLKIT_DOCLET_NAME =
80        jdk.javadoc.internal.doclets.formats.html.HtmlDoclet.class.getName();
81
82    /**
83     * Verify that the only doclet that is using this toolkit is
84     * {@value #TOOLKIT_DOCLET_NAME}.
85     */
86    private boolean isValidDoclet() {
87        if (!getClass().getName().equals(TOOLKIT_DOCLET_NAME)) {
88            messages.error("doclet.Toolkit_Usage_Violation",
89                TOOLKIT_DOCLET_NAME);
90            return false;
91        }
92        return true;
93    }
94
95    /**
96     * The method that starts the execution of the doclet.
97     *
98     * @param docEnv   the {@link DocletEnvironment}.
99     * @return true if the doclet executed without error.  False otherwise.
100     */
101    @Override
102    public boolean run(DocletEnvironment docEnv) {
103        configuration = getConfiguration();
104        configuration.initConfiguration(docEnv);
105        configuration.cmtUtils = new CommentUtils(configuration);
106        configuration.utils = new Utils(configuration);
107        utils = configuration.utils;
108        configuration.workArounds = new WorkArounds(configuration);
109        messages = configuration.getMessages();
110
111        if (!isValidDoclet()) {
112            return false;
113        }
114
115        try {
116            try {
117                startGeneration(docEnv);
118                return true;
119            } catch (UncheckedDocletException e) {
120                throw (DocletException) e.getCause();
121            }
122
123        } catch (DocFileIOException e) {
124            switch (e.mode) {
125                case READ:
126                    messages.error("doclet.exception.read.file",
127                            e.fileName.getPath(), e.getCause());
128                    break;
129                case WRITE:
130                    messages.error("doclet.exception.write.file",
131                            e.fileName.getPath(), e.getCause());
132            }
133            dumpStack(configuration.dumpOnError, e);
134
135        } catch (ResourceIOException e) {
136            messages.error("doclet.exception.read.resource",
137                    e.resource.getPath(), e.getCause());
138            dumpStack(configuration.dumpOnError, e);
139
140        } catch (SimpleDocletException e) {
141            configuration.reporter.print(ERROR, e.getMessage());
142            dumpStack(configuration.dumpOnError, e);
143
144        } catch (InternalException e) {
145            configuration.reporter.print(ERROR, e.getMessage());
146            reportInternalError(e.getCause());
147
148        } catch (DocletException | RuntimeException | Error e) {
149            messages.error("doclet.internal.exception", e);
150            reportInternalError(e);
151        }
152
153        return false;
154    }
155
156    private void reportInternalError(Throwable t) {
157        if (getClass().equals(StandardDoclet.class) || getClass().equals(HtmlDoclet.class)) {
158            System.err.println(configuration.getResources().getText("doclet.internal.report.bug"));
159        }
160        dumpStack(true, t);
161    }
162
163    private void dumpStack(boolean enabled, Throwable t) {
164        if (enabled && t != null) {
165            t.printStackTrace(System.err);
166        }
167    }
168
169    /**
170     * Returns the SourceVersion indicating the features supported by this doclet.
171     *
172     * @return SourceVersion
173     */
174    @Override
175    public SourceVersion getSupportedSourceVersion() {
176        return SourceVersion.RELEASE_9;
177    }
178
179    /**
180     * Create the configuration instance and returns it.
181     *
182     * @return the configuration of the doclet.
183     */
184    public abstract Configuration getConfiguration();
185
186    /**
187     * Start the generation of files. Call generate methods in the individual
188     * writers, which will in turn generate the documentation files. Call the
189     * TreeWriter generation first to ensure the Class Hierarchy is built
190     * first and then can be used in the later generation.
191     *
192     * @see jdk.doclet.DocletEnvironment
193     * @throws DocletException if there is a problem while generating the documentation
194     */
195    private void startGeneration(DocletEnvironment docEnv) throws DocletException {
196        if (configuration.getIncludedTypeElements().isEmpty()) {
197            messages.error("doclet.No_Public_Classes_To_Document");
198            return;
199        }
200        if (!configuration.setOptions()) {
201            return;
202        }
203        messages.notice("doclet.build_version",
204            configuration.getDocletSpecificBuildDate());
205        ClassTree classtree = new ClassTree(configuration, configuration.nodeprecated);
206
207        generateClassFiles(docEnv, classtree);
208
209        PackageListWriter.generate(configuration);
210        generatePackageFiles(classtree);
211        generateModuleFiles();
212
213        generateOtherFiles(docEnv, classtree);
214        configuration.tagletManager.printReport();
215    }
216
217    /**
218     * Generate additional documentation that is added to the API documentation.
219     *
220     * @param docEnv     the DocletEnvironment
221     * @param classtree the data structure representing the class tree
222     * @throws DocletException if there is a problem while generating the documentation
223     */
224    protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree)
225            throws DocletException {
226        BuilderFactory builderFactory = configuration.getBuilderFactory();
227        AbstractBuilder constantsSummaryBuilder = builderFactory.getConstantsSummaryBuilder();
228        constantsSummaryBuilder.build();
229        AbstractBuilder serializedFormBuilder = builderFactory.getSerializedFormBuilder();
230        serializedFormBuilder.build();
231    }
232
233    /**
234     * Generate the module documentation.
235     *
236     * @throws DocletException if there is a problem while generating the documentation
237     *
238     */
239    protected abstract void generateModuleFiles() throws DocletException;
240
241    /**
242     * Generate the package documentation.
243     *
244     * @param classtree the data structure representing the class tree
245     * @throws DocletException if there is a problem while generating the documentation
246     */
247    protected abstract void generatePackageFiles(ClassTree classtree) throws DocletException;
248
249    /**
250     * Generate the class documentation.
251     *
252     * @param arr the set of types to be documented
253     * @param classtree the data structure representing the class tree
254     * @throws DocletException if there is a problem while generating the documentation
255     */
256    protected abstract void generateClassFiles(SortedSet<TypeElement> arr, ClassTree classtree)
257            throws DocletException;
258
259    /**
260     * Iterate through all classes and construct documentation for them.
261     *
262     * @param docEnv      the DocletEnvironment
263     * @param classtree the data structure representing the class tree
264     * @throws DocletException if there is a problem while generating the documentation
265     */
266    protected void generateClassFiles(DocletEnvironment docEnv, ClassTree classtree)
267            throws DocletException {
268        generateClassFiles(classtree);
269        SortedSet<PackageElement> packages = new TreeSet<>(utils.makePackageComparator());
270        packages.addAll(configuration.getSpecifiedPackageElements());
271        configuration.modulePackages.values().stream().forEach(packages::addAll);
272        for (PackageElement pkg : packages) {
273            generateClassFiles(utils.getAllClasses(pkg), classtree);
274        }
275    }
276
277    /**
278     * Generate the class files for single classes specified on the command line.
279     *
280     * @param classtree the data structure representing the class tree
281     * @throws DocletException if there is a problem while generating the documentation
282     */
283    private void generateClassFiles(ClassTree classtree) throws DocletException {
284        SortedSet<PackageElement> packages = configuration.typeElementCatalog.packages();
285        for (PackageElement pkg : packages) {
286            generateClassFiles(configuration.typeElementCatalog.allClasses(pkg), classtree);
287        }
288    }
289}
290