HtmlDoclet.java revision 3294:9adfb22ff08f
1/*
2 * Copyright (c) 1997, 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.formats.html;
27
28import java.io.*;
29import java.util.*;
30
31import javax.lang.model.element.ModuleElement;
32import javax.lang.model.element.PackageElement;
33import javax.lang.model.element.TypeElement;
34
35import com.sun.javadoc.PackageDoc;
36import jdk.javadoc.doclet.Doclet.Option;
37import jdk.javadoc.doclet.DocletEnvironment;
38import jdk.javadoc.doclet.Reporter;
39import jdk.javadoc.internal.doclets.toolkit.AbstractDoclet;
40import jdk.javadoc.internal.doclets.toolkit.Configuration;
41import jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder;
42import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
43import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
44import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
45import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
46import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
47import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder;
48
49/**
50 * The class with "start" method, calls individual Writers.
51 *
52 *  <p><b>This is NOT part of any supported API.
53 *  If you write code that depends on this, you do so at your own risk.
54 *  This code and its internal interfaces are subject to change or
55 *  deletion without notice.</b>
56 *
57 * @author Atul M Dambalkar
58 * @author Robert Field
59 * @author Jamie Ho
60 *
61 */
62public class HtmlDoclet extends AbstractDoclet {
63
64    public HtmlDoclet() {
65        configuration = new ConfigurationImpl();
66    }
67
68    /**
69     * The global configuration information for this run.
70     */
71    public final ConfigurationImpl configuration;
72
73
74    private static final DocPath DOCLET_RESOURCES = DocPath
75            .create("/jdk/javadoc/internal/doclets/formats/html/resources");
76
77    public void init(Locale locale, Reporter reporter) {
78        configuration.reporter = reporter;
79        configuration.locale = locale;
80    }
81
82    /**
83     * The "start" method as required by Javadoc.
84     *
85     * @param root the root of the documentation tree.
86     * @see jdk.doclet.DocletEnvironment
87     * @return true if the doclet ran without encountering any errors.
88     */
89    public boolean run(DocletEnvironment root) {
90        return startDoclet(root);
91    }
92
93    /**
94     * Create the configuration instance.
95     * Override this method to use a different
96     * configuration.
97     */
98    public Configuration configuration() {
99        return configuration;
100    }
101
102    /**
103     * Start the generation of files. Call generate methods in the individual
104     * writers, which will in turn genrate the documentation files. Call the
105     * TreeWriter generation first to ensure the Class Hierarchy is built
106     * first and then can be used in the later generation.
107     *
108     * For new format.
109     *
110     * @see jdk.doclet.RootDoc
111     */
112    protected void generateOtherFiles(DocletEnvironment root, ClassTree classtree)
113            throws Exception {
114        super.generateOtherFiles(root, classtree);
115        if (configuration.linksource) {
116            SourceToHTMLConverter.convertRoot(configuration,
117                root, DocPaths.SOURCE_OUTPUT);
118        }
119
120        if (configuration.topFile.isEmpty()) {
121            configuration.standardmessage.
122                error("doclet.No_Non_Deprecated_Classes_To_Document");
123            return;
124        }
125        boolean nodeprecated = configuration.nodeprecated;
126        performCopy(configuration.helpfile);
127        performCopy(configuration.stylesheetfile);
128        // do early to reduce memory footprint
129        if (configuration.classuse) {
130            ClassUseWriter.generate(configuration, classtree);
131        }
132        IndexBuilder indexbuilder = new IndexBuilder(configuration, nodeprecated);
133
134        if (configuration.createtree) {
135            TreeWriter.generate(configuration, classtree);
136        }
137        if (configuration.createindex) {
138            configuration.buildSearchTagIndex();
139            if (configuration.splitindex) {
140                SplitIndexWriter.generate(configuration, indexbuilder);
141            } else {
142                SingleIndexWriter.generate(configuration, indexbuilder);
143            }
144        }
145
146        if (!(configuration.nodeprecatedlist || nodeprecated)) {
147            DeprecatedListWriter.generate(configuration);
148        }
149
150        AllClassesFrameWriter.generate(configuration,
151            new IndexBuilder(configuration, nodeprecated, true));
152
153        FrameOutputWriter.generate(configuration);
154
155        if (configuration.createoverview) {
156            PackageIndexWriter.generate(configuration);
157        }
158        if (configuration.helpfile.length() == 0 &&
159            !configuration.nohelp) {
160            HelpWriter.generate(configuration);
161        }
162        // If a stylesheet file is not specified, copy the default stylesheet
163        // and replace newline with platform-specific newline.
164        DocFile f;
165        if (configuration.stylesheetfile.length() == 0) {
166            f = DocFile.createFileForOutput(configuration, DocPaths.STYLESHEET);
167            f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.STYLESHEET), false, true);
168        }
169        f = DocFile.createFileForOutput(configuration, DocPaths.JAVASCRIPT);
170        f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.JAVASCRIPT), true, true);
171        if (configuration.createindex) {
172            f = DocFile.createFileForOutput(configuration, DocPaths.SEARCH_JS);
173            f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.SEARCH_JS), true, true);
174
175            f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.GLASS_IMG));
176            f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.GLASS_IMG), true, false);
177
178            f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.X_IMG));
179            f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.X_IMG), true, false);
180            copyJqueryFiles();
181        }
182    }
183
184    protected void copyJqueryFiles() {
185        List<String> files = Arrays.asList(
186                "jquery-1.10.2.js",
187                "jquery-ui.js",
188                "jquery-ui.css",
189                "jquery-ui.min.js",
190                "jquery-ui.min.css",
191                "jquery-ui.structure.min.css",
192                "jquery-ui.structure.css",
193                "external/jquery/jquery.js",
194                "jszip/dist/jszip.js",
195                "jszip/dist/jszip.min.js",
196                "jszip-utils/dist/jszip-utils.js",
197                "jszip-utils/dist/jszip-utils.min.js",
198                "jszip-utils/dist/jszip-utils-ie.js",
199                "jszip-utils/dist/jszip-utils-ie.min.js",
200                "images/ui-bg_flat_0_aaaaaa_40x100.png",
201                "images/ui-icons_454545_256x240.png",
202                "images/ui-bg_glass_95_fef1ec_1x400.png",
203                "images/ui-bg_glass_75_dadada_1x400.png",
204                "images/ui-bg_highlight-soft_75_cccccc_1x100.png",
205                "images/ui-icons_888888_256x240.png",
206                "images/ui-icons_2e83ff_256x240.png",
207                "images/ui-bg_glass_65_ffffff_1x400.png",
208                "images/ui-icons_cd0a0a_256x240.png",
209                "images/ui-bg_glass_55_fbf9ee_1x400.png",
210                "images/ui-icons_222222_256x240.png",
211                "images/ui-bg_glass_75_e6e6e6_1x400.png",
212                "images/ui-bg_flat_75_ffffff_40x100.png");
213        DocFile f;
214        for (String file : files) {
215            DocPath filePath = DocPaths.JQUERY_FILES.resolve(file);
216            f = DocFile.createFileForOutput(configuration, filePath);
217            f.copyResource(DOCLET_RESOURCES.resolve(filePath), true, false);
218        }
219    }
220
221    /**
222     * {@inheritDoc}
223     */
224    protected void generateClassFiles(SortedSet<TypeElement> arr, ClassTree classtree) {
225        List<TypeElement> list = new ArrayList<>(arr);
226        ListIterator<TypeElement> iterator = list.listIterator();
227        TypeElement klass = null;
228        while (iterator.hasNext()) {
229            TypeElement prev = iterator.hasPrevious() ? klass : null;
230            klass = iterator.next();
231            TypeElement next = iterator.nextIndex() == list.size()
232                    ? null : list.get(iterator.nextIndex());
233            if (!(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) {
234                continue;
235            }
236            try {
237                if (utils.isAnnotationType(klass)) {
238                    AbstractBuilder annotationTypeBuilder =
239                        configuration.getBuilderFactory()
240                            .getAnnotationTypeBuilder(klass,
241                                prev == null ? null : prev.asType(),
242                                next == null ? null : next.asType());
243                    annotationTypeBuilder.build();
244                } else {
245                    AbstractBuilder classBuilder =
246                        configuration.getBuilderFactory().getClassBuilder(klass,
247                                prev, next, classtree);
248                    classBuilder.build();
249                }
250            } catch (IOException e) {
251                throw new DocletAbortException(e);
252            } catch (DocletAbortException de) {
253                de.printStackTrace();
254                throw de;
255            } catch (Exception e) {
256                e.printStackTrace();
257                throw new DocletAbortException(e);
258            }
259        }
260    }
261
262    /**
263     * {@inheritDoc}
264     */
265    protected void generateModuleFiles() throws Exception {
266        if (configuration.showModules) {
267            ModuleIndexFrameWriter.generate(configuration);
268            ModuleElement prevModule = null, nextModule;
269            List<ModuleElement> mdles = new ArrayList<>(configuration.modulePackages.keySet());
270            int i = 0;
271            for (ModuleElement mdle : mdles) {
272                ModulePackageIndexFrameWriter.generate(configuration, mdle);
273                nextModule = (i + 1 < mdles.size()) ? mdles.get(i + 1) : null;
274                AbstractBuilder moduleSummaryBuilder =
275                        configuration.getBuilderFactory().getModuleSummaryBuilder(
276                        mdle, prevModule, nextModule);
277                moduleSummaryBuilder.build();
278                prevModule = mdle;
279                i++;
280            }
281        }
282    }
283
284    PackageElement getNamedPackage(List<PackageElement> list, int idx) {
285        if (idx < list.size()) {
286            PackageElement pkg = list.get(idx);
287            if (pkg != null && !pkg.isUnnamed()) {
288                return pkg;
289            }
290        }
291        return null;
292    }
293
294    /**
295     * {@inheritDoc}
296     */
297    protected void generatePackageFiles(ClassTree classtree) throws Exception {
298        Set<PackageElement> packages = configuration.packages;
299        if (packages.size() > 1) {
300            PackageIndexFrameWriter.generate(configuration);
301        }
302        List<PackageElement> pList = new ArrayList<>(packages);
303        PackageElement prev = null;
304        for (int i = 0 ; i < pList.size() ; i++) {
305            // if -nodeprecated option is set and the package is marked as
306            // deprecated, do not generate the package-summary.html, package-frame.html
307            // and package-tree.html pages for that package.
308            PackageElement pkg = pList.get(i);
309            if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
310                PackageFrameWriter.generate(configuration, pkg);
311                int nexti = i + 1;
312                PackageElement next = null;
313                if (nexti < pList.size()) {
314                    next = pList.get(nexti);
315                    // If the next package is unnamed package, skip 2 ahead if possible
316                    if (next.isUnnamed() && ++nexti < pList.size()) {
317                       next = pList.get(nexti);
318                    }
319                }
320                AbstractBuilder packageSummaryBuilder =
321                        configuration.getBuilderFactory().getPackageSummaryBuilder(
322                        pkg, prev, next);
323                packageSummaryBuilder.build();
324                if (configuration.createtree) {
325                    PackageTreeWriter.generate(configuration, pkg, prev, next,
326                            configuration.nodeprecated);
327                }
328                prev = pkg;
329            }
330        }
331    }
332
333    public Set<Option> getSupportedOptions() {
334        return configuration.getSupportedOptions();
335    }
336
337    private void performCopy(String filename) {
338        if (filename.isEmpty())
339            return;
340
341        try {
342            DocFile fromfile = DocFile.createFileForInput(configuration, filename);
343            DocPath path = DocPath.create(fromfile.getName());
344            DocFile toFile = DocFile.createFileForOutput(configuration, path);
345            if (toFile.isSameFile(fromfile))
346                return;
347
348            configuration.message.notice("doclet.Copying_File_0_To_File_1",
349                    fromfile.toString(), path.getPath());
350            toFile.copyFile(fromfile);
351        } catch (IOException exc) {
352            configuration.message.error("doclet.perform_copy_exception_encountered",
353                    exc.toString());
354            throw new DocletAbortException(exc);
355        }
356    }
357}
358