1/* 2 * Copyright (c) 1997, 2017, 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.util.*; 29 30import javax.lang.model.element.ModuleElement; 31import javax.lang.model.element.PackageElement; 32import javax.lang.model.element.TypeElement; 33 34import jdk.javadoc.doclet.Doclet.Option; 35import jdk.javadoc.doclet.DocletEnvironment; 36import jdk.javadoc.doclet.Reporter; 37import jdk.javadoc.internal.doclets.toolkit.AbstractDoclet; 38import jdk.javadoc.internal.doclets.toolkit.DocletException; 39import jdk.javadoc.internal.doclets.toolkit.Messages; 40import jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder; 41import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; 42import jdk.javadoc.internal.doclets.toolkit.util.DocFile; 43import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; 44import jdk.javadoc.internal.doclets.toolkit.util.DocPath; 45import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 46import 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 */ 61public class HtmlDoclet extends AbstractDoclet { 62 63 public HtmlDoclet() { 64 configuration = new ConfigurationImpl(this); 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 ConfigurationImpl 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 ConfigurationImpl 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 * @see jdk.doclet.DocletEnvironment 112 */ 113 @Override // defined by AbstractDoclet 114 protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree) 115 throws DocletException { 116 super.generateOtherFiles(docEnv, classtree); 117 if (configuration.linksource) { 118 SourceToHTMLConverter.convertRoot(configuration, 119 docEnv, DocPaths.SOURCE_OUTPUT); 120 } 121 122 if (configuration.topFile.isEmpty()) { 123 messages.error("doclet.No_Non_Deprecated_Classes_To_Document"); 124 return; 125 } 126 boolean nodeprecated = configuration.nodeprecated; 127 performCopy(configuration.helpfile); 128 performCopy(configuration.stylesheetfile); 129 // do early to reduce memory footprint 130 if (configuration.classuse) { 131 ClassUseWriter.generate(configuration, classtree); 132 } 133 IndexBuilder indexbuilder = new IndexBuilder(configuration, nodeprecated); 134 135 if (configuration.createtree) { 136 TreeWriter.generate(configuration, classtree); 137 } 138 if (configuration.createindex) { 139 configuration.buildSearchTagIndex(); 140 if (configuration.splitindex) { 141 SplitIndexWriter.generate(configuration, indexbuilder); 142 } else { 143 SingleIndexWriter.generate(configuration, indexbuilder); 144 } 145 } 146 147 if (!(configuration.nodeprecatedlist || nodeprecated)) { 148 DeprecatedListWriter.generate(configuration); 149 } 150 151 AllClassesFrameWriter.generate(configuration, 152 new IndexBuilder(configuration, nodeprecated, true)); 153 154 if (configuration.frames) { 155 FrameOutputWriter.generate(configuration); 156 } 157 158 if (configuration.createoverview) { 159 if (configuration.showModules) { 160 ModuleIndexWriter.generate(configuration); 161 } else { 162 PackageIndexWriter.generate(configuration); 163 } 164 } 165 166 if (!configuration.frames && !configuration.createoverview) { 167 IndexRedirectWriter.generate(configuration); 168 } 169 170 if (configuration.helpfile.isEmpty() && !configuration.nohelp) { 171 HelpWriter.generate(configuration); 172 } 173 // If a stylesheet file is not specified, copy the default stylesheet 174 // and replace newline with platform-specific newline. 175 DocFile f; 176 if (configuration.stylesheetfile.length() == 0) { 177 f = DocFile.createFileForOutput(configuration, DocPaths.STYLESHEET); 178 f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.STYLESHEET), false, true); 179 } 180 f = DocFile.createFileForOutput(configuration, DocPaths.JAVASCRIPT); 181 f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.JAVASCRIPT), true, true); 182 if (configuration.createindex) { 183 f = DocFile.createFileForOutput(configuration, DocPaths.SEARCH_JS); 184 f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.SEARCH_JS), true, true); 185 186 f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.GLASS_IMG)); 187 f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.GLASS_IMG), true, false); 188 189 f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.X_IMG)); 190 f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.X_IMG), true, false); 191 copyJqueryFiles(); 192 } 193 } 194 195 protected void copyJqueryFiles() throws DocletException { 196 List<String> files = Arrays.asList( 197 "jquery-1.10.2.js", 198 "jquery-ui.js", 199 "jquery-ui.css", 200 "jquery-ui.min.js", 201 "jquery-ui.min.css", 202 "jquery-ui.structure.min.css", 203 "jquery-ui.structure.css", 204 "external/jquery/jquery.js", 205 "jszip/dist/jszip.js", 206 "jszip/dist/jszip.min.js", 207 "jszip-utils/dist/jszip-utils.js", 208 "jszip-utils/dist/jszip-utils.min.js", 209 "jszip-utils/dist/jszip-utils-ie.js", 210 "jszip-utils/dist/jszip-utils-ie.min.js", 211 "images/ui-bg_flat_0_aaaaaa_40x100.png", 212 "images/ui-icons_454545_256x240.png", 213 "images/ui-bg_glass_95_fef1ec_1x400.png", 214 "images/ui-bg_glass_75_dadada_1x400.png", 215 "images/ui-bg_highlight-soft_75_cccccc_1x100.png", 216 "images/ui-icons_888888_256x240.png", 217 "images/ui-icons_2e83ff_256x240.png", 218 "images/ui-bg_glass_65_ffffff_1x400.png", 219 "images/ui-icons_cd0a0a_256x240.png", 220 "images/ui-bg_glass_55_fbf9ee_1x400.png", 221 "images/ui-icons_222222_256x240.png", 222 "images/ui-bg_glass_75_e6e6e6_1x400.png", 223 "images/ui-bg_flat_75_ffffff_40x100.png"); 224 DocFile f; 225 for (String file : files) { 226 DocPath filePath = DocPaths.JQUERY_FILES.resolve(file); 227 f = DocFile.createFileForOutput(configuration, filePath); 228 f.copyResource(DOCLET_RESOURCES.resolve(filePath), true, false); 229 } 230 } 231 232 /** 233 * {@inheritDoc} 234 */ 235 @Override // defined by AbstractDoclet 236 protected void generateClassFiles(SortedSet<TypeElement> arr, ClassTree classtree) 237 throws DocletException { 238 List<TypeElement> list = new ArrayList<>(arr); 239 ListIterator<TypeElement> iterator = list.listIterator(); 240 TypeElement klass = null; 241 while (iterator.hasNext()) { 242 TypeElement prev = iterator.hasPrevious() ? klass : null; 243 klass = iterator.next(); 244 TypeElement next = iterator.nextIndex() == list.size() 245 ? null : list.get(iterator.nextIndex()); 246 247 if (utils.isHidden(klass) || 248 !(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) { 249 continue; 250 } 251 252 if (utils.isAnnotationType(klass)) { 253 AbstractBuilder annotationTypeBuilder = 254 configuration.getBuilderFactory() 255 .getAnnotationTypeBuilder(klass, 256 prev == null ? null : prev.asType(), 257 next == null ? null : next.asType()); 258 annotationTypeBuilder.build(); 259 } else { 260 AbstractBuilder classBuilder = 261 configuration.getBuilderFactory().getClassBuilder(klass, 262 prev, next, classtree); 263 classBuilder.build(); 264 } 265 } 266 } 267 268 /** 269 * {@inheritDoc} 270 */ 271 @Override // defined by AbstractDoclet 272 protected void generateModuleFiles() throws DocletException { 273 if (configuration.showModules) { 274 if (configuration.frames && configuration.modules.size() > 1) { 275 ModuleIndexFrameWriter.generate(configuration); 276 } 277 ModuleElement prevModule = null, nextModule; 278 List<ModuleElement> mdles = new ArrayList<>(configuration.modulePackages.keySet()); 279 int i = 0; 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 nextModule = (i + 1 < mdles.size()) ? mdles.get(i + 1) : null; 286 AbstractBuilder moduleSummaryBuilder = 287 configuration.getBuilderFactory().getModuleSummaryBuilder( 288 mdle, prevModule, nextModule); 289 moduleSummaryBuilder.build(); 290 prevModule = mdle; 291 i++; 292 } 293 } 294 } 295 296 PackageElement getNamedPackage(List<PackageElement> list, int idx) { 297 if (idx < list.size()) { 298 PackageElement pkg = list.get(idx); 299 if (pkg != null && !pkg.isUnnamed()) { 300 return pkg; 301 } 302 } 303 return null; 304 } 305 306 /** 307 * {@inheritDoc} 308 */ 309 @Override // defined by AbstractDoclet 310 protected void generatePackageFiles(ClassTree classtree) throws DocletException { 311 Set<PackageElement> packages = configuration.packages; 312 if (packages.size() > 1 && configuration.frames) { 313 PackageIndexFrameWriter.generate(configuration); 314 } 315 List<PackageElement> pList = new ArrayList<>(packages); 316 PackageElement prev = null; 317 for (int i = 0 ; i < pList.size() ; i++) { 318 // if -nodeprecated option is set and the package is marked as 319 // deprecated, do not generate the package-summary.html, package-frame.html 320 // and package-tree.html pages for that package. 321 PackageElement pkg = pList.get(i); 322 if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) { 323 if (configuration.frames) { 324 PackageFrameWriter.generate(configuration, pkg); 325 } 326 int nexti = i + 1; 327 PackageElement next = null; 328 if (nexti < pList.size()) { 329 next = pList.get(nexti); 330 // If the next package is unnamed package, skip 2 ahead if possible 331 if (next.isUnnamed() && ++nexti < pList.size()) { 332 next = pList.get(nexti); 333 } 334 } 335 AbstractBuilder packageSummaryBuilder = 336 configuration.getBuilderFactory().getPackageSummaryBuilder( 337 pkg, prev, next); 338 packageSummaryBuilder.build(); 339 if (configuration.createtree) { 340 PackageTreeWriter.generate(configuration, pkg, prev, next, 341 configuration.nodeprecated); 342 } 343 prev = pkg; 344 } 345 } 346 } 347 348 @Override // defined by Doclet 349 public Set<Option> getSupportedOptions() { 350 return configuration.getSupportedOptions(); 351 } 352 353 private void performCopy(String filename) throws DocFileIOException { 354 if (filename.isEmpty()) 355 return; 356 357 DocFile fromfile = DocFile.createFileForInput(configuration, filename); 358 DocPath path = DocPath.create(fromfile.getName()); 359 DocFile toFile = DocFile.createFileForOutput(configuration, path); 360 if (toFile.isSameFile(fromfile)) 361 return; 362 363 messages.notice("doclet.Copying_File_0_To_File_1", 364 fromfile.toString(), path.getPath()); 365 toFile.copyFile(fromfile); 366 } 367} 368