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         if (configuration.createindex) {
143             configuration.buildSearchTagIndex();
144             if (configuration.splitindex) {
145                 SplitIndexWriter.generate(configuration, indexbuilder);
146             } else {
147                 SingleIndexWriter.generate(configuration, indexbuilder);
148             }
149             AllClassesIndexWriter.generate(configuration,
150                     new IndexBuilder(configuration, nodeprecated, true));
151             if (!configuration.packages.isEmpty()) {
152                 AllPackagesIndexWriter.generate(configuration);
153             }
154         }
155 
156         if (!(configuration.nodeprecatedlist || nodeprecated)) {
157             DeprecatedListWriter.generate(configuration);
158         }
159 
160         AllClassesFrameWriter.generate(configuration,
161             new IndexBuilder(configuration, nodeprecated, true));
162 
163         if (configuration.frames) {
164             FrameOutputWriter.generate(configuration);
165         }
166 
167         if (configuration.createoverview) {
168             if (configuration.showModules) {
169                 ModuleIndexWriter.generate(configuration);
170             } else {
171                 PackageIndexWriter.generate(configuration);
172             }
173         }
174 
175         if (!configuration.frames) {
176             if (configuration.createoverview) {
177                 IndexRedirectWriter.generate(configuration, DocPaths.OVERVIEW_SUMMARY, DocPaths.INDEX);
178             } else {
179                 IndexRedirectWriter.generate(configuration);
180             }
181         }
182 
183         if (configuration.helpfile.isEmpty() && !configuration.nohelp) {
184             HelpWriter.generate(configuration);
185         }
186         // If a stylesheet file is not specified, copy the default stylesheet
187         // and replace newline with platform-specific newline.
188         DocFile f;
189         if (configuration.stylesheetfile.length() == 0) {
190             f = DocFile.createFileForOutput(configuration, DocPaths.STYLESHEET);
191             f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.STYLESHEET), true, true);
192         }
193         f = DocFile.createFileForOutput(configuration, DocPaths.JAVASCRIPT);
194         f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.JAVASCRIPT), true, true);
195         if (configuration.createindex) {
196             f = DocFile.createFileForOutput(configuration, DocPaths.SEARCH_JS);
197             f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.SEARCH_JS), true, true);
198 
199             f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.GLASS_IMG));
200             f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.GLASS_IMG), true, false);
201 
202             f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.X_IMG));
203             f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.X_IMG), true, false);
204             copyJqueryFiles();
205         }
206     }
207 
copyJqueryFiles()208     private void copyJqueryFiles() throws DocletException {
209         List<String> files = Arrays.asList(
210                 "jquery-3.5.1.js",
211                 "jquery-ui.js",
212                 "jquery-ui.css",
213                 "jquery-ui.min.js",
214                 "jquery-ui.min.css",
215                 "jquery-ui.structure.min.css",
216                 "jquery-ui.structure.css",
217                 "external/jquery/jquery.js",
218                 "jszip/dist/jszip.js",
219                 "jszip/dist/jszip.min.js",
220                 "jszip-utils/dist/jszip-utils.js",
221                 "jszip-utils/dist/jszip-utils.min.js",
222                 "jszip-utils/dist/jszip-utils-ie.js",
223                 "jszip-utils/dist/jszip-utils-ie.min.js",
224                 "images/ui-bg_glass_65_dadada_1x400.png",
225                 "images/ui-icons_454545_256x240.png",
226                 "images/ui-bg_glass_95_fef1ec_1x400.png",
227                 "images/ui-bg_glass_75_dadada_1x400.png",
228                 "images/ui-bg_highlight-soft_75_cccccc_1x100.png",
229                 "images/ui-icons_888888_256x240.png",
230                 "images/ui-icons_2e83ff_256x240.png",
231                 "images/ui-icons_cd0a0a_256x240.png",
232                 "images/ui-bg_glass_55_fbf9ee_1x400.png",
233                 "images/ui-icons_222222_256x240.png",
234                 "images/ui-bg_glass_75_e6e6e6_1x400.png");
235         DocFile f;
236         for (String file : files) {
237             DocPath filePath = DocPaths.JQUERY_FILES.resolve(file);
238             f = DocFile.createFileForOutput(configuration, filePath);
239             f.copyResource(DOCLET_RESOURCES.resolve(filePath), true, false);
240         }
241     }
242 
243     /**
244      * {@inheritDoc}
245      */
246     @Override // defined by AbstractDoclet
generateClassFiles(SortedSet<TypeElement> arr, ClassTree classtree)247     protected void generateClassFiles(SortedSet<TypeElement> arr, ClassTree classtree)
248             throws DocletException {
249         List<TypeElement> list = new ArrayList<>(arr);
250         for (TypeElement klass : list) {
251             if (utils.hasHiddenTag(klass) ||
252                     !(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) {
253                 continue;
254             }
255             if (utils.isAnnotationType(klass)) {
256                 AbstractBuilder annotationTypeBuilder =
257                     configuration.getBuilderFactory()
258                         .getAnnotationTypeBuilder(klass);
259                 annotationTypeBuilder.build();
260             } else {
261                 AbstractBuilder classBuilder =
262                     configuration.getBuilderFactory().getClassBuilder(klass, classtree);
263                 classBuilder.build();
264             }
265         }
266     }
267 
268     /**
269      * {@inheritDoc}
270      */
271     @Override // defined by AbstractDoclet
generateModuleFiles()272     protected void generateModuleFiles() throws DocletException {
273         if (configuration.showModules) {
274             if (configuration.frames  && configuration.modules.size() > 1) {
275                 ModuleIndexFrameWriter.generate(configuration);
276             }
277             List<ModuleElement> mdles = new ArrayList<>(configuration.modulePackages.keySet());
278             for (ModuleElement mdle : mdles) {
279                 if (configuration.frames && configuration.modules.size() > 1) {
280                     ModulePackageIndexFrameWriter.generate(configuration, mdle);
281                     ModuleFrameWriter.generate(configuration, mdle);
282                 }
283                 AbstractBuilder moduleSummaryBuilder =
284                         configuration.getBuilderFactory().getModuleSummaryBuilder(mdle);
285                 moduleSummaryBuilder.build();
286             }
287         }
288     }
289 
290     /**
291      * {@inheritDoc}
292      */
293     @Override // defined by AbstractDoclet
generatePackageFiles(ClassTree classtree)294     protected void generatePackageFiles(ClassTree classtree) throws DocletException {
295         Set<PackageElement> packages = configuration.packages;
296         if (packages.size() > 1 && configuration.frames) {
297             PackageIndexFrameWriter.generate(configuration);
298         }
299         List<PackageElement> pList = new ArrayList<>(packages);
300         for (PackageElement pkg : pList) {
301             // if -nodeprecated option is set and the package is marked as
302             // deprecated, do not generate the package-summary.html, package-frame.html
303             // and package-tree.html pages for that package.
304             if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
305                 if (configuration.frames) {
306                     PackageFrameWriter.generate(configuration, pkg);
307                 }
308                 AbstractBuilder packageSummaryBuilder =
309                         configuration.getBuilderFactory().getPackageSummaryBuilder(pkg);
310                 packageSummaryBuilder.build();
311                 if (configuration.createtree) {
312                     PackageTreeWriter.generate(configuration, pkg, configuration.nodeprecated);
313                 }
314             }
315         }
316     }
317 
318     @Override // defined by Doclet
getSupportedOptions()319     public Set<Option> getSupportedOptions() {
320         return configuration.getSupportedOptions();
321     }
322 
performCopy(String filename)323     private void performCopy(String filename) throws DocFileIOException {
324         if (filename.isEmpty())
325             return;
326 
327         DocFile fromfile = DocFile.createFileForInput(configuration, filename);
328         DocPath path = DocPath.create(fromfile.getName());
329         DocFile toFile = DocFile.createFileForOutput(configuration, path);
330         if (toFile.isSameFile(fromfile))
331             return;
332 
333         messages.notice("doclet.Copying_File_0_To_File_1",
334                 fromfile.toString(), path.getPath());
335         toFile.copyFile(fromfile);
336     }
337 }
338