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