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