src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java

Fri, 27 Sep 2013 21:20:01 +0400

author
kizune
date
Fri, 27 Sep 2013 21:20:01 +0400
changeset 2071
2c24a04ebfb4
parent 2023
cf37c3775397
child 2225
b8ebde062692
permissions
-rw-r--r--

6978886: javadoc shows stacktrace after print error resulting from disk full
Reviewed-by: jjg

duke@1 1 /*
bpatel@1568 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
duke@1 24 */
duke@1 25 package com.sun.tools.doclets.formats.html;
duke@1 26
jjg@1357 27 import java.io.*;
jjg@1357 28 import java.util.*;
jjg@1357 29
jjg@1357 30 import com.sun.javadoc.*;
bpatel@1568 31 import com.sun.tools.javac.sym.Profiles;
bpatel@1568 32 import com.sun.tools.javac.jvm.Profile;
duke@1 33 import com.sun.tools.doclets.internal.toolkit.*;
duke@1 34 import com.sun.tools.doclets.internal.toolkit.builders.*;
duke@1 35 import com.sun.tools.doclets.internal.toolkit.util.*;
duke@1 36
duke@1 37 /**
duke@1 38 * The class with "start" method, calls individual Writers.
duke@1 39 *
jjg@1359 40 * <p><b>This is NOT part of any supported API.
jjg@1359 41 * If you write code that depends on this, you do so at your own risk.
jjg@1359 42 * This code and its internal interfaces are subject to change or
jjg@1359 43 * deletion without notice.</b>
jjg@1359 44 *
duke@1 45 * @author Atul M Dambalkar
duke@1 46 * @author Robert Field
duke@1 47 * @author Jamie Ho
duke@1 48 *
duke@1 49 */
duke@1 50 public class HtmlDoclet extends AbstractDoclet {
jjg@1410 51 // An instance will be created by validOptions, and used by start.
jjg@1410 52 private static HtmlDoclet docletToStart = null;
jjg@1410 53
jjg@140 54 public HtmlDoclet() {
jjg@1410 55 configuration = new ConfigurationImpl();
jjg@140 56 }
duke@1 57
duke@1 58 /**
duke@1 59 * The global configuration information for this run.
duke@1 60 */
jjg@1410 61 public final ConfigurationImpl configuration;
duke@1 62
duke@1 63 /**
duke@1 64 * The "start" method as required by Javadoc.
duke@1 65 *
duke@1 66 * @param root the root of the documentation tree.
duke@1 67 * @see com.sun.javadoc.RootDoc
duke@1 68 * @return true if the doclet ran without encountering any errors.
duke@1 69 */
duke@1 70 public static boolean start(RootDoc root) {
jjg@1410 71 // In typical use, options will have been set up by calling validOptions,
jjg@1410 72 // which will create an HtmlDoclet for use here.
jjg@1410 73 HtmlDoclet doclet;
jjg@1410 74 if (docletToStart != null) {
jjg@1410 75 doclet = docletToStart;
jjg@1410 76 docletToStart = null;
jjg@1410 77 } else {
jjg@1410 78 doclet = new HtmlDoclet();
jjg@140 79 }
jjg@1410 80 return doclet.start(doclet, root);
duke@1 81 }
duke@1 82
duke@1 83 /**
duke@1 84 * Create the configuration instance.
duke@1 85 * Override this method to use a different
duke@1 86 * configuration.
duke@1 87 */
duke@1 88 public Configuration configuration() {
jjg@1410 89 return configuration;
duke@1 90 }
duke@1 91
duke@1 92 /**
duke@1 93 * Start the generation of files. Call generate methods in the individual
duke@1 94 * writers, which will in turn genrate the documentation files. Call the
duke@1 95 * TreeWriter generation first to ensure the Class Hierarchy is built
duke@1 96 * first and then can be used in the later generation.
duke@1 97 *
duke@1 98 * For new format.
duke@1 99 *
duke@1 100 * @see com.sun.javadoc.RootDoc
duke@1 101 */
duke@1 102 protected void generateOtherFiles(RootDoc root, ClassTree classtree)
duke@1 103 throws Exception {
duke@1 104 super.generateOtherFiles(root, classtree);
duke@1 105 if (configuration.linksource) {
jjg@1372 106 SourceToHTMLConverter.convertRoot(configuration,
jjg@1372 107 root, DocPaths.SOURCE_OUTPUT);
duke@1 108 }
duke@1 109
jjg@1372 110 if (configuration.topFile.isEmpty()) {
duke@1 111 configuration.standardmessage.
duke@1 112 error("doclet.No_Non_Deprecated_Classes_To_Document");
duke@1 113 return;
duke@1 114 }
duke@1 115 boolean nodeprecated = configuration.nodeprecated;
jjg@1383 116 performCopy(configuration.helpfile);
jjg@1383 117 performCopy(configuration.stylesheetfile);
jjg@1383 118 copyResourceFile("background.gif");
jjg@1383 119 copyResourceFile("tab.gif");
jjg@1383 120 copyResourceFile("titlebar.gif");
jjg@1383 121 copyResourceFile("titlebar_end.gif");
bpatel@1417 122 copyResourceFile("activetitlebar.gif");
bpatel@1417 123 copyResourceFile("activetitlebar_end.gif");
duke@1 124 // do early to reduce memory footprint
duke@1 125 if (configuration.classuse) {
duke@1 126 ClassUseWriter.generate(configuration, classtree);
duke@1 127 }
duke@1 128 IndexBuilder indexbuilder = new IndexBuilder(configuration, nodeprecated);
duke@1 129
duke@1 130 if (configuration.createtree) {
duke@1 131 TreeWriter.generate(configuration, classtree);
duke@1 132 }
duke@1 133 if (configuration.createindex) {
duke@1 134 if (configuration.splitindex) {
duke@1 135 SplitIndexWriter.generate(configuration, indexbuilder);
duke@1 136 } else {
duke@1 137 SingleIndexWriter.generate(configuration, indexbuilder);
duke@1 138 }
duke@1 139 }
duke@1 140
duke@1 141 if (!(configuration.nodeprecatedlist || nodeprecated)) {
duke@1 142 DeprecatedListWriter.generate(configuration);
duke@1 143 }
duke@1 144
duke@1 145 AllClassesFrameWriter.generate(configuration,
duke@1 146 new IndexBuilder(configuration, nodeprecated, true));
duke@1 147
duke@1 148 FrameOutputWriter.generate(configuration);
duke@1 149
duke@1 150 if (configuration.createoverview) {
duke@1 151 PackageIndexWriter.generate(configuration);
duke@1 152 }
duke@1 153 if (configuration.helpfile.length() == 0 &&
duke@1 154 !configuration.nohelp) {
duke@1 155 HelpWriter.generate(configuration);
duke@1 156 }
bpatel@793 157 // If a stylesheet file is not specified, copy the default stylesheet
bpatel@793 158 // and replace newline with platform-specific newline.
bpatel@1417 159 DocFile f;
duke@1 160 if (configuration.stylesheetfile.length() == 0) {
bpatel@1417 161 f = DocFile.createFileForOutput(configuration, DocPaths.STYLESHEET);
jjg@1383 162 f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.STYLESHEET), false, true);
duke@1 163 }
bpatel@1417 164 f = DocFile.createFileForOutput(configuration, DocPaths.JAVASCRIPT);
bpatel@1417 165 f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.JAVASCRIPT), true, true);
duke@1 166 }
duke@1 167
duke@1 168 /**
duke@1 169 * {@inheritDoc}
duke@1 170 */
duke@1 171 protected void generateClassFiles(ClassDoc[] arr, ClassTree classtree) {
duke@1 172 Arrays.sort(arr);
duke@1 173 for(int i = 0; i < arr.length; i++) {
duke@1 174 if (!(configuration.isGeneratedDoc(arr[i]) && arr[i].isIncluded())) {
duke@1 175 continue;
duke@1 176 }
duke@1 177 ClassDoc prev = (i == 0)?
duke@1 178 null:
duke@1 179 arr[i-1];
duke@1 180 ClassDoc curr = arr[i];
duke@1 181 ClassDoc next = (i+1 == arr.length)?
duke@1 182 null:
duke@1 183 arr[i+1];
duke@1 184 try {
duke@1 185 if (curr.isAnnotationType()) {
duke@1 186 AbstractBuilder annotationTypeBuilder =
duke@1 187 configuration.getBuilderFactory()
duke@1 188 .getAnnotationTypeBuilder((AnnotationTypeDoc) curr,
duke@1 189 prev, next);
duke@1 190 annotationTypeBuilder.build();
duke@1 191 } else {
duke@1 192 AbstractBuilder classBuilder =
duke@1 193 configuration.getBuilderFactory()
duke@1 194 .getClassBuilder(curr, prev, next, classtree);
duke@1 195 classBuilder.build();
duke@1 196 }
kizune@2071 197 } catch (IOException e) {
kizune@2071 198 throw new DocletAbortException(e);
kizune@2071 199 } catch (DocletAbortException de) {
kizune@2071 200 throw de;
duke@1 201 } catch (Exception e) {
duke@1 202 e.printStackTrace();
jjg@1985 203 throw new DocletAbortException(e);
duke@1 204 }
duke@1 205 }
duke@1 206 }
duke@1 207
duke@1 208 /**
duke@1 209 * {@inheritDoc}
duke@1 210 */
bpatel@1568 211 protected void generateProfileFiles() throws Exception {
bpatel@2023 212 if (configuration.showProfiles && configuration.profilePackages.size() > 0) {
bpatel@1568 213 ProfileIndexFrameWriter.generate(configuration);
bpatel@1568 214 Profile prevProfile = null, nextProfile;
bpatel@2023 215 String profileName;
bpatel@1568 216 for (int i = 1; i < configuration.profiles.getProfileCount(); i++) {
bpatel@2023 217 profileName = Profile.lookup(i).name;
bpatel@2023 218 // Generate profile package pages only if there are any packages
bpatel@2023 219 // in a profile to be documented. The profilePackages map will not
bpatel@2023 220 // contain an entry for the profile if there are no packages to be documented.
bpatel@2023 221 if (!configuration.shouldDocumentProfile(profileName))
bpatel@2023 222 continue;
bpatel@2023 223 ProfilePackageIndexFrameWriter.generate(configuration, profileName);
bpatel@1568 224 PackageDoc[] packages = configuration.profilePackages.get(
bpatel@2023 225 profileName);
bpatel@1568 226 PackageDoc prev = null, next;
bpatel@1568 227 for (int j = 0; j < packages.length; j++) {
bpatel@1568 228 // if -nodeprecated option is set and the package is marked as
bpatel@1568 229 // deprecated, do not generate the profilename-package-summary.html
bpatel@1568 230 // and profilename-package-frame.html pages for that package.
bpatel@1568 231 if (!(configuration.nodeprecated && Util.isDeprecated(packages[j]))) {
bpatel@1568 232 ProfilePackageFrameWriter.generate(configuration, packages[j], i);
bpatel@1568 233 next = (j + 1 < packages.length
bpatel@1568 234 && packages[j + 1].name().length() > 0) ? packages[j + 1] : null;
bpatel@1568 235 AbstractBuilder profilePackageSummaryBuilder =
bpatel@1568 236 configuration.getBuilderFactory().getProfilePackageSummaryBuilder(
bpatel@1568 237 packages[j], prev, next, Profile.lookup(i));
bpatel@1568 238 profilePackageSummaryBuilder.build();
bpatel@1568 239 prev = packages[j];
bpatel@1568 240 }
bpatel@1568 241 }
bpatel@1568 242 nextProfile = (i + 1 < configuration.profiles.getProfileCount()) ?
bpatel@1568 243 Profile.lookup(i + 1) : null;
bpatel@1568 244 AbstractBuilder profileSummaryBuilder =
bpatel@1568 245 configuration.getBuilderFactory().getProfileSummaryBuilder(
bpatel@1568 246 Profile.lookup(i), prevProfile, nextProfile);
bpatel@1568 247 profileSummaryBuilder.build();
bpatel@1568 248 prevProfile = Profile.lookup(i);
bpatel@1568 249 }
bpatel@1568 250 }
bpatel@1568 251 }
bpatel@1568 252
bpatel@1568 253 /**
bpatel@1568 254 * {@inheritDoc}
bpatel@1568 255 */
duke@1 256 protected void generatePackageFiles(ClassTree classtree) throws Exception {
duke@1 257 PackageDoc[] packages = configuration.packages;
duke@1 258 if (packages.length > 1) {
duke@1 259 PackageIndexFrameWriter.generate(configuration);
duke@1 260 }
duke@1 261 PackageDoc prev = null, next;
bpatel@995 262 for (int i = 0; i < packages.length; i++) {
bpatel@995 263 // if -nodeprecated option is set and the package is marked as
bpatel@995 264 // deprecated, do not generate the package-summary.html, package-frame.html
bpatel@995 265 // and package-tree.html pages for that package.
bpatel@995 266 if (!(configuration.nodeprecated && Util.isDeprecated(packages[i]))) {
bpatel@995 267 PackageFrameWriter.generate(configuration, packages[i]);
bpatel@995 268 next = (i + 1 < packages.length &&
bpatel@995 269 packages[i + 1].name().length() > 0) ? packages[i + 1] : null;
bpatel@995 270 //If the next package is unnamed package, skip 2 ahead if possible
bpatel@995 271 next = (i + 2 < packages.length && next == null) ? packages[i + 2] : next;
bpatel@995 272 AbstractBuilder packageSummaryBuilder =
bpatel@995 273 configuration.getBuilderFactory().getPackageSummaryBuilder(
bpatel@995 274 packages[i], prev, next);
bpatel@995 275 packageSummaryBuilder.build();
bpatel@995 276 if (configuration.createtree) {
bpatel@995 277 PackageTreeWriter.generate(configuration,
bpatel@995 278 packages[i], prev, next,
bpatel@995 279 configuration.nodeprecated);
bpatel@995 280 }
bpatel@995 281 prev = packages[i];
duke@1 282 }
duke@1 283 }
duke@1 284 }
duke@1 285
jjg@1410 286 public static final ConfigurationImpl sharedInstanceForOptions =
jjg@1410 287 new ConfigurationImpl();
jjg@1410 288
duke@1 289 /**
duke@1 290 * Check for doclet added options here.
duke@1 291 *
duke@1 292 * @return number of arguments to option. Zero return means
duke@1 293 * option not known. Negative value means error occurred.
duke@1 294 */
duke@1 295 public static int optionLength(String option) {
duke@1 296 // Construct temporary configuration for check
jjg@1410 297 return sharedInstanceForOptions.optionLength(option);
duke@1 298 }
duke@1 299
duke@1 300 /**
duke@1 301 * Check that options have the correct arguments here.
duke@1 302 * <P>
duke@1 303 * This method is not required and will default gracefully
duke@1 304 * (to true) if absent.
duke@1 305 * <P>
duke@1 306 * Printing option related error messages (using the provided
duke@1 307 * DocErrorReporter) is the responsibility of this method.
duke@1 308 *
duke@1 309 * @return true if the options are valid.
duke@1 310 */
duke@1 311 public static boolean validOptions(String options[][],
duke@1 312 DocErrorReporter reporter) {
jjg@1410 313 docletToStart = new HtmlDoclet();
jjg@1410 314 return docletToStart.configuration.validOptions(options, reporter);
duke@1 315 }
duke@1 316
jjg@1383 317 /**
jjg@1383 318 * Copy a file in the resources directory to the destination directory.
jjg@1383 319 * @param resource The name of the resource file to copy
jjg@1383 320 */
jjg@1383 321 private void copyResourceFile(String resource) {
jjg@1383 322 DocPath p = DocPaths.RESOURCES.resolve(resource);
jjg@1383 323 DocFile f = DocFile.createFileForOutput(configuration, p);
jjg@1383 324 f.copyResource(p, false, false);
jjg@1383 325 }
jjg@1383 326
jjg@1383 327 private void performCopy(String filename) {
jjg@1383 328 if (filename.isEmpty())
jjg@1383 329 return;
jjg@1383 330
duke@1 331 try {
jjg@1383 332 DocFile fromfile = DocFile.createFileForInput(configuration, filename);
jjg@1383 333 DocPath path = DocPath.create(fromfile.getName());
jjg@1383 334 DocFile toFile = DocFile.createFileForOutput(configuration, path);
jjg@1383 335 if (toFile.isSameFile(fromfile))
jjg@1383 336 return;
jjg@1383 337
jjg@1383 338 configuration.message.notice((SourcePosition) null,
jjg@1383 339 "doclet.Copying_File_0_To_File_1",
jjg@1383 340 fromfile.toString(), path.getPath());
jjg@1383 341 toFile.copyFile(fromfile);
duke@1 342 } catch (IOException exc) {
jjg@1383 343 configuration.message.error((SourcePosition) null,
duke@1 344 "doclet.perform_copy_exception_encountered",
duke@1 345 exc.toString());
jjg@1985 346 throw new DocletAbortException(exc);
duke@1 347 }
duke@1 348 }
duke@1 349 }

mercurial