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