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