8162353: javadoc should provide a way to disable use of frames
Reviewed-by: bpatel, ksrini
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesFrameWriter.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesFrameWriter.java Mon Aug 15 18:00:36 2016 -0700
@@ -25,7 +25,7 @@
package jdk.javadoc.internal.doclets.formats.html;
-import java.io.*;
+import java.io.IOException;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
@@ -89,25 +89,32 @@
* "allclasses-frame.html" file. Generate the file in the current or the
* destination directory.
*
- * @param indexbuilder IndexBuilder object for all classes index.
+ * @param indexBuilder IndexBuilder object for all classes index.
* @throws DocletAbortException
*/
public static void generate(ConfigurationImpl configuration,
- IndexBuilder indexbuilder) {
- AllClassesFrameWriter allclassgen;
- DocPath filename = DocPaths.ALLCLASSES_FRAME;
+ IndexBuilder indexBuilder) {
+ if (configuration.frames) {
+ generate(configuration, indexBuilder, DocPaths.ALLCLASSES_FRAME, true);
+ generate(configuration, indexBuilder, DocPaths.ALLCLASSES_NOFRAME, false);
+ } else {
+ generate(configuration, indexBuilder, DocPaths.ALLCLASSES, false);
+ }
+ }
+
+ private static void generate(ConfigurationImpl configuration, IndexBuilder indexBuilder,
+ DocPath fileName, boolean wantFrames) {
try {
+ AllClassesFrameWriter allclassgen = new AllClassesFrameWriter(configuration,
+ fileName, indexBuilder);
+ allclassgen.buildAllClassesFile(wantFrames);
allclassgen = new AllClassesFrameWriter(configuration,
- filename, indexbuilder);
- allclassgen.buildAllClassesFile(true);
- filename = DocPaths.ALLCLASSES_NOFRAME;
- allclassgen = new AllClassesFrameWriter(configuration,
- filename, indexbuilder);
+ fileName, indexBuilder);
allclassgen.buildAllClassesFile(false);
} catch (IOException exc) {
Messages messages = configuration.getMessages();
messages.error("doclet.exception_encountered",
- exc.toString(), filename);
+ exc.toString(), fileName);
throw new DocletAbortException(exc);
}
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java Mon Aug 15 18:00:36 2016 -0700
@@ -198,6 +198,12 @@
public boolean createoverview = false;
/**
+ * Specifies whether or not frames should be generated.
+ * Defaults to true; can be set by --frames; can be set to false by --no-frames; last one wins.
+ */
+ public boolean frames = true;
+
+ /**
* This is the HTML version of the generated pages. HTML 4.01 is the default output version.
*/
public HtmlVersion htmlVersion = HtmlVersion.HTML4;
@@ -414,18 +420,18 @@
* package to document. It will be a class page(first in the sorted order),
* if only classes are provided on the command line.
*
- * @param root Root of the program structure.
+ * @param docEnv Root of the program structure.
*/
- protected void setTopFile(DocletEnvironment root) {
- if (!checkForDeprecation(root)) {
+ protected void setTopFile(DocletEnvironment docEnv) {
+ if (!checkForDeprecation(docEnv)) {
return;
}
if (createoverview) {
- topFile = DocPaths.OVERVIEW_SUMMARY;
+ topFile = DocPaths.overviewSummary(frames);
} else {
if (packages.size() == 1 && packages.first().isUnnamed()) {
- if (!root.getIncludedClasses().isEmpty()) {
- List<TypeElement> classes = new ArrayList<>(root.getIncludedClasses());
+ if (!docEnv.getIncludedClasses().isEmpty()) {
+ List<TypeElement> classes = new ArrayList<>(docEnv.getIncludedClasses());
TypeElement te = getValidClass(classes);
topFile = DocPath.forClass(utils, te);
}
@@ -727,6 +733,22 @@
return true;
}
},
+ new Option(this, "--frames") {
+ @Override
+ public boolean process(String opt, ListIterator<String> args) {
+ optionsProcessed.add(this);
+ frames = true;
+ return true;
+ }
+ },
+ new Option(this, "--no-frames") {
+ @Override
+ public boolean process(String opt, ListIterator<String> args) {
+ optionsProcessed.add(this);
+ frames = false;
+ return true;
+ }
+ },
new Hidden(this, "-packagesheader", 1) {
@Override
public boolean process(String opt, ListIterator<String> args) {
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java Mon Aug 15 18:00:36 2016 -0700
@@ -141,7 +141,7 @@
? HtmlTree.SECTION(overviewHeading)
: HtmlTree.LI(HtmlStyle.blockList, overviewHeading);
Content line3 = contents.getContent("doclet.Help_line_3",
- getHyperLink(DocPaths.OVERVIEW_SUMMARY,
+ getHyperLink(DocPaths.overviewSummary(configuration.frames),
configuration.getText("doclet.Overview")));
Content overviewPara = HtmlTree.P(line3);
htmlTree.addContent(overviewPara);
@@ -362,26 +362,31 @@
} else {
ul.addContent(htmlTree);
}
- Content frameHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
- contents.getContent("doclet.Help_line_25"));
- htmlTree = (configuration.allowTag(HtmlTag.SECTION))
- ? HtmlTree.SECTION(frameHead)
- : HtmlTree.LI(HtmlStyle.blockList, frameHead);
- Content line26 = contents.getContent("doclet.Help_line_26");
- Content framePara = HtmlTree.P(line26);
- htmlTree.addContent(framePara);
+
+ if (configuration.frames) {
+ Content frameHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
+ contents.getContent("doclet.Help_line_25"));
+ htmlTree = (configuration.allowTag(HtmlTag.SECTION))
+ ? HtmlTree.SECTION(frameHead)
+ : HtmlTree.LI(HtmlStyle.blockList, frameHead);
+ Content line26 = contents.getContent("doclet.Help_line_26");
+ Content framePara = HtmlTree.P(line26);
+ htmlTree.addContent(framePara);
+ }
+
if (configuration.allowTag(HtmlTag.SECTION)) {
ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree));
} else {
ul.addContent(htmlTree);
}
+
Content allclassesHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
contents.allClassesLabel);
htmlTree = (configuration.allowTag(HtmlTag.SECTION))
? HtmlTree.SECTION(allclassesHead)
: HtmlTree.LI(HtmlStyle.blockList, allclassesHead);
Content line27 = contents.getContent("doclet.Help_line_27",
- getHyperLink(DocPaths.ALLCLASSES_NOFRAME,
+ getHyperLink(DocPaths.AllClasses(configuration.frames),
resources.getText("doclet.All_Classes")));
Content allclassesPara = HtmlTree.P(line27);
htmlTree.addContent(allclassesPara);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java Mon Aug 15 18:00:36 2016 -0700
@@ -106,7 +106,7 @@
*
* For new format.
*
- * @see jdk.doclet.RootDoc
+ * @see jdk.doclet.DocletEnvironment
*/
@Override // defined by AbstractDoclet
protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree)
@@ -149,7 +149,9 @@
AllClassesFrameWriter.generate(configuration,
new IndexBuilder(configuration, nodeprecated, true));
- FrameOutputWriter.generate(configuration);
+ if (configuration.frames) {
+ FrameOutputWriter.generate(configuration);
+ }
if (configuration.createoverview) {
if (configuration.showModules) {
@@ -158,6 +160,11 @@
PackageIndexWriter.generate(configuration);
}
}
+
+ if (!configuration.frames && !configuration.createoverview) {
+ IndexRedirectWriter.generate(configuration);
+ }
+
if (configuration.helpfile.length() == 0 &&
!configuration.nohelp) {
HelpWriter.generate(configuration);
@@ -270,13 +277,17 @@
@Override // defined by AbstractDoclet
protected void generateModuleFiles() throws Exception {
if (configuration.showModules) {
- ModuleIndexFrameWriter.generate(configuration);
+ if (configuration.frames) {
+ ModuleIndexFrameWriter.generate(configuration);
+ }
ModuleElement prevModule = null, nextModule;
List<ModuleElement> mdles = new ArrayList<>(configuration.modulePackages.keySet());
int i = 0;
for (ModuleElement mdle : mdles) {
- ModulePackageIndexFrameWriter.generate(configuration, mdle);
- ModuleFrameWriter.generate(configuration, mdle);
+ if (configuration.frames) {
+ ModulePackageIndexFrameWriter.generate(configuration, mdle);
+ ModuleFrameWriter.generate(configuration, mdle);
+ }
nextModule = (i + 1 < mdles.size()) ? mdles.get(i + 1) : null;
AbstractBuilder moduleSummaryBuilder =
configuration.getBuilderFactory().getModuleSummaryBuilder(
@@ -304,7 +315,7 @@
@Override // defined by AbstractDoclet
protected void generatePackageFiles(ClassTree classtree) throws Exception {
Set<PackageElement> packages = configuration.packages;
- if (packages.size() > 1) {
+ if (packages.size() > 1 && configuration.frames) {
PackageIndexFrameWriter.generate(configuration);
}
List<PackageElement> pList = new ArrayList<>(packages);
@@ -315,7 +326,9 @@
// and package-tree.html pages for that package.
PackageElement pkg = pList.get(i);
if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
- PackageFrameWriter.generate(configuration, pkg);
+ if (configuration.frames) {
+ PackageFrameWriter.generate(configuration, pkg);
+ }
int nexti = i + 1;
PackageElement next = null;
if (nexti < pList.size()) {
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Mon Aug 15 18:00:36 2016 -0700
@@ -615,12 +615,13 @@
} else {
tree.addContent(navDiv);
}
- Content ulNav = HtmlTree.UL(HtmlStyle.navList, getNavLinkPrevious());
- ulNav.addContent(getNavLinkNext());
+ Content ulNav = HtmlTree.UL(HtmlStyle.navList, getNavLinkPrevious(), getNavLinkNext());
Content subDiv = HtmlTree.DIV(HtmlStyle.subNav, ulNav);
- Content ulFrames = HtmlTree.UL(HtmlStyle.navList, getNavShowLists());
- ulFrames.addContent(getNavHideLists(filename));
- subDiv.addContent(ulFrames);
+ if (configuration.frames) {
+ Content ulFrames = HtmlTree.UL(HtmlStyle.navList,
+ getNavShowLists(), getNavHideLists(filename));
+ subDiv.addContent(ulFrames);
+ }
HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex());
ulAllClasses.addAttr(HtmlAttr.ID, allClassesId);
subDiv.addContent(ulAllClasses);
@@ -688,7 +689,7 @@
* @return a content tree for the link
*/
protected Content getNavLinkContents() {
- Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_SUMMARY),
+ Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.overviewSummary(configuration.frames)),
contents.overviewLabel, "", "");
Content li = HtmlTree.LI(linkContent);
return li;
@@ -875,7 +876,7 @@
*/
protected Content getNavLinkClassIndex() {
Content allClassesContent = getHyperLink(pathToRoot.resolve(
- DocPaths.ALLCLASSES_NOFRAME),
+ DocPaths.AllClasses(configuration.frames)),
contents.allClassesLabel, "", "");
Content li = HtmlTree.LI(allClassesContent);
return li;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Mon Aug 15 18:00:36 2016 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html;
+
+import java.io.IOException;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.Messages;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
+
+import static jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocWriter.CONTENT_TYPE;
+
+/**
+ * Writes an index.html file that tries to redirect to an alternate page.
+ * The redirect uses JavaSCript, if enabled, falling back on
+ * {@code <meta http-eqiv=refresh content="0,<uri>">}.
+ * If neither are supported/enabled in a browser, the page displays the
+ * standard "JavaScipt not enabled" message, and a link to the alternate page.
+ */
+public class IndexRedirectWriter extends HtmlDocletWriter {
+
+ public static void generate(ConfigurationImpl configuration) {
+ IndexRedirectWriter indexRedirect;
+ DocPath filename = DocPath.empty;
+ try {
+ filename = DocPaths.INDEX;
+ indexRedirect = new IndexRedirectWriter(configuration, filename);
+ indexRedirect.generateIndexFile();
+ } catch (IOException exc) {
+ Messages messages = configuration.getMessages();
+ messages.error(
+ "doclet.exception_encountered",
+ exc.toString(), filename);
+ throw new DocletAbortException(exc);
+ }
+ }
+
+ IndexRedirectWriter(ConfigurationImpl configuration, DocPath filename)
+ throws IOException {
+ super(configuration, filename);
+ }
+
+ void generateIndexFile() throws IOException {
+ Content htmlDocType = configuration.isOutputHtml5()
+ ? DocType.HTML5
+ : DocType.TRANSITIONAL;
+ Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
+ Content head = new HtmlTree(HtmlTag.HEAD);
+ head.addContent(getGeneratedBy(!configuration.notimestamp));
+
+ String title = (configuration.windowtitle.length() > 0)
+ ? configuration.windowtitle
+ : configuration.getText("doclet.Generated_Docs_Untitled");
+
+ Content windowTitle = HtmlTree.TITLE(new StringContent(title));
+ head.addContent(windowTitle);
+ Content metaContentType = HtmlTree.META("Content", CONTENT_TYPE,
+ (configuration.charset.length() > 0) ?
+ configuration.charset : HtmlConstants.HTML_DEFAULT_CHARSET);
+ head.addContent(metaContentType);
+
+ String topFilePath = configuration.topFile.getPath();
+ String javaScriptRefresh = "window.location.replace('" + topFilePath + "')";
+ HtmlTree scriptTree = HtmlTree.SCRIPT();
+ scriptTree.addContent(javaScriptRefresh);
+ head.addContent(scriptTree);
+ HtmlTree metaRefresh = new HtmlTree(HtmlTag.META);
+ metaRefresh.addAttr(HtmlAttr.HTTP_EQUIV, "Refresh");
+ metaRefresh.addAttr(HtmlAttr.CONTENT, "0;" + topFilePath);
+ if (configuration.isOutputHtml5()) {
+ head.addContent(HtmlTree.NOSCRIPT(metaRefresh));
+ } else {
+ head.addContent(metaRefresh);
+ }
+
+ head.addContent(getStyleSheetProperties(configuration));
+
+ ContentBuilder bodyContent = new ContentBuilder();
+ bodyContent.addContent(HtmlTree.NOSCRIPT(
+ HtmlTree.P(configuration.getContent("doclet.No_Script_Message"))));
+
+ bodyContent.addContent(HtmlTree.P(HtmlTree.A(topFilePath, new StringContent(topFilePath))));
+
+ Content body = new HtmlTree(HtmlTag.BODY);
+ if (configuration.allowTag(HtmlTag.MAIN)) {
+ HtmlTree main = HtmlTree.MAIN(bodyContent);
+ body.addContent(main);
+ } else {
+ body.addContent(bodyContent);
+ }
+
+ Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
+ head, body);
+ Content htmlDocument = new HtmlDocument(htmlDocType,
+ htmlComment, htmlTree);
+ write(htmlDocument);
+
+ }
+}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java Mon Aug 15 18:00:36 2016 -0700
@@ -88,7 +88,7 @@
*/
public static void generate(ConfigurationImpl configuration) {
ModuleIndexWriter mdlgen;
- DocPath filename = DocPaths.OVERVIEW_SUMMARY;
+ DocPath filename = DocPaths.overviewSummary(configuration.frames);
try {
mdlgen = new ModuleIndexWriter(configuration, filename);
mdlgen.buildModuleIndexFile("doclet.Window_Overview_Summary", true);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java Mon Aug 15 18:00:36 2016 -0700
@@ -101,7 +101,7 @@
*/
public static void generate(ConfigurationImpl configuration) {
PackageIndexWriter packgen;
- DocPath filename = DocPaths.OVERVIEW_SUMMARY;
+ DocPath filename = DocPaths.overviewSummary(configuration.frames);
try {
packgen = new PackageIndexWriter(configuration, filename);
packgen.buildPackageIndexFile("doclet.Window_Overview_Summary", true);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java Mon Aug 15 18:00:36 2016 -0700
@@ -833,13 +833,18 @@
* Generates a UL tag with the style class attribute and some content.
*
* @param styleClass style for the tag
- * @param body content for the tag
+ * @param first initial content to be added
+ * @param more a series of additional content nodes to be added
* @return an HtmlTree object for the UL tag
*/
- public static HtmlTree UL(HtmlStyle styleClass, Content body) {
- HtmlTree htmltree = new HtmlTree(HtmlTag.UL, nullCheck(body));
- htmltree.addStyle(nullCheck(styleClass));
- return htmltree;
+ public static HtmlTree UL(HtmlStyle styleClass, Content first, Content... more) {
+ HtmlTree htmlTree = new HtmlTree(HtmlTag.UL);
+ htmlTree.addContent(nullCheck(first));
+ for (Content c : more) {
+ htmlTree.addContent(nullCheck(c));
+ }
+ htmlTree.addStyle(nullCheck(styleClass));
+ return htmlTree;
}
/**
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties Mon Aug 15 18:00:36 2016 -0700
@@ -299,6 +299,10 @@
doclet.usage.docencoding.parameters=<name>
doclet.usage.docencoding.description=Specify the character encoding for the output
+doclet.usage.frames.description=Enable the use of frames in the generated output (default)
+
+doclet.usage.no-frames.description=Disable the use of frames in the generated output
+
doclet.xusage.xdocrootparent.parameters=<url>
doclet.xusage.xdocrootparent.description=Replaces all @docRoot followed by /..\n\
\ in doc comments with <url>
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java Mon Aug 15 18:00:36 2016 -0700
@@ -37,6 +37,8 @@
*
*/
public class DocPaths {
+ /** The name of the file for all classes, without using frames, when --no-frames is specified. */
+ public static final DocPath ALLCLASSES = DocPath.create("allclasses.html");
/** The name of the file for all classes, using frames. */
public static final DocPath ALLCLASSES_FRAME = DocPath.create("allclasses-frame.html");
@@ -44,6 +46,10 @@
/** The name of the file for all classes, without using frames. */
public static final DocPath ALLCLASSES_NOFRAME = DocPath.create("allclasses-noframe.html");
+ public static DocPath AllClasses(boolean frames) {
+ return frames ? ALLCLASSES_NOFRAME : ALLCLASSES;
+ }
+
/** The name of the sub-directory for storing class usage info. */
public static final DocPath CLASS_USE = DocPath.create("class-use");
@@ -121,6 +127,10 @@
/** The name of the file for the overview summary. */
public static final DocPath OVERVIEW_SUMMARY = DocPath.create("overview-summary.html");
+ public static DocPath overviewSummary(boolean frames) {
+ return frames ? OVERVIEW_SUMMARY : INDEX;
+ }
+
/** The name of the file for the overview tree. */
public static final DocPath OVERVIEW_TREE = DocPath.create("overview-tree.html");
--- a/langtools/test/jdk/javadoc/doclet/lib/JavadocTester.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/test/jdk/javadoc/doclet/lib/JavadocTester.java Mon Aug 15 18:00:36 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
import java.nio.file.Files;
import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
@@ -157,7 +158,7 @@
private final Map<File,SoftReference<String>> fileContentCache = new HashMap<>();
/** Stream used for logging messages. */
- private final PrintStream out = System.out;
+ protected final PrintStream out = System.out;
/** The directory containing the source code for the test. */
public static final String testSrc = System.getProperty("test.src");
@@ -416,6 +417,17 @@
* @param paths the files to check, within the most recent output directory.
* */
public void checkFiles(boolean expectedFound, String... paths) {
+ checkFiles(expectedFound, Arrays.asList(paths));
+ }
+
+ /**
+ * Check for files in (or not in) the generated output.
+ * @param expectedFound true if all of the files are expected
+ * to be found, or false if all of the files are expected to be
+ * not found
+ * @param paths the files to check, within the most recent output directory.
+ * */
+ public void checkFiles(boolean expectedFound, Collection<String> paths) {
for (String path: paths) {
// log.logCheckFile(path, expectedFound);
checking("checkFile");
@@ -574,7 +586,7 @@
return content;
content = new String(Files.readAllBytes(file.toPath()));
- fileContentCache.put(file, new SoftReference(content));
+ fileContentCache.put(file, new SoftReference<>(content));
return content;
} catch (FileNotFoundException e) {
System.err.println(e);
@@ -613,16 +625,19 @@
* Print a summary of the test results.
*/
protected void printSummary() {
-// log.write();
+ String javadocRuns = (javadocRunNum <= 1) ? ""
+ : ", in " + javadocRunNum + " runs of javadoc";
+
if (numTestsRun != 0 && numTestsPassed == numTestsRun) {
// Test passed
out.println();
- out.println("All " + numTestsPassed + " subtests passed");
+ out.println("All " + numTestsPassed + " subtests passed" + javadocRuns);
} else {
// Test failed
throw new Error((numTestsRun - numTestsPassed)
+ " of " + (numTestsRun)
- + " subtests failed");
+ + " subtests failed"
+ + javadocRuns);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testFramesNoFrames/TestFramesNoFrames.java Mon Aug 15 18:00:36 2016 -0700
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8162353
+ * @summary javadoc should provide a way to disable use of frames
+ * @library /tools/lib ../lib
+ * @modules
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.javadoc/jdk.javadoc.internal.tool
+ * @build toolbox.ModuleBuilder toolbox.ToolBox
+ * @build JavadocTester
+ * @run main TestFramesNoFrames
+ */
+
+import java.io.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.*;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import toolbox.ModuleBuilder;
+import toolbox.ToolBox;
+
+public class TestFramesNoFrames extends JavadocTester {
+
+ public static void main(String... args) throws Exception {
+ TestFramesNoFrames tester = new TestFramesNoFrames();
+ tester.generateSource();
+ tester.runTests();
+ }
+
+ ToolBox tb = new ToolBox();
+ Path gensrcModules = Paths.get("gensrc/modules");
+ Path gensrcPackages = Paths.get("gensrc/packages");
+
+ void generateSource() throws IOException {
+ String[] modules = { "", "m1", "m2", "m3" };
+ String[] packages = { "p1", "p2", "p3" };
+ String[] classes = { "C1", "C2", "C3" };
+ for (String m: modules) {
+ ModuleBuilder mb = m.equals("") ? null : new ModuleBuilder(tb, m);
+ for (String p: packages) {
+ Path pkgRoot;
+ if (m.equals("")) {
+ pkgRoot = gensrcPackages;
+ } else {
+ pkgRoot = gensrcModules.resolve(m);
+ mb.exports(m + p);
+ }
+ for (String c: classes) {
+ tb.writeJavaFiles(pkgRoot,
+ "package " + (m + p) + ";\n"
+ + "/** class " + (m + p + c).toUpperCase() + ". */\n"
+ + "public class " + (m + p + c).toUpperCase() + " { }"
+ );
+ }
+ }
+ if (!m.equals("")) {
+ mb.write(gensrcModules);
+ }
+ }
+ tb.writeFile("overview.html",
+ "<html><body>This is the overview file</body></html>");
+ }
+
+ enum FrameKind {
+ DEFAULT(),
+ FRAMES("--frames"),
+ NO_FRAMES("--no-frames");
+ FrameKind(String... opts) {
+ this.opts = Arrays.asList(opts);
+ }
+ final List<String> opts;
+ }
+
+ enum OverviewKind {
+ DEFAULT(),
+ OVERVIEW("-overview", "overview.html"),
+ NO_OVERVIEW("-nooverview");
+ OverviewKind(String... opts) {
+ this.opts = Arrays.asList(opts);
+ }
+ final List<String> opts;
+ }
+
+ enum HtmlKind {
+ HTML4("-html4"),
+ HTML5("-html5");
+ HtmlKind(String... opts) {
+ this.opts = Arrays.asList(opts);
+ }
+ final List<String> opts;
+ }
+
+ @Override
+ public void runTests() throws Exception {
+ for (Method m : getClass().getDeclaredMethods()) {
+ Annotation a = m.getAnnotation(Test.class);
+ if (a != null) {
+ for (FrameKind fk : FrameKind.values()) {
+ for (OverviewKind ok : OverviewKind.values()) {
+ for (HtmlKind hk : HtmlKind.values()) {
+ try {
+ out.println("Running test " + m.getName() + " " + fk + " " + ok + " " + hk);
+ Path base = Paths.get(m.getName() + "_" + fk + "_" + ok + "_" + hk);
+ Files.createDirectories(base);
+ m.invoke(this, new Object[]{base, fk, ok, hk});
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ throw (cause instanceof Exception) ? ((Exception) cause) : e;
+ }
+ out.println();
+ }
+ }
+ }
+ }
+ }
+ printSummary();
+ }
+
+ void javadoc(Path outDir, FrameKind fKind, OverviewKind oKind, HtmlKind hKind, String... rest) {
+ List<String> args = new ArrayList<>();
+ args.add("-d");
+ args.add(outDir.toString());
+ args.addAll(fKind.opts);
+ args.addAll(oKind.opts);
+ args.addAll(hKind.opts);
+ args.addAll(Arrays.asList(rest));
+ javadoc(args.toArray(new String[0]));
+ checkExit(Exit.OK);
+ }
+
+ @Test
+ void testClass(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws Exception {
+ javadoc(base, fKind, oKind, hKind,
+ gensrcPackages.resolve("p1/P1C1.java").toString());
+
+ new Checker(fKind, oKind, hKind)
+ .classes("p1.P1C1")
+ .check();
+ }
+
+ @Test
+ void testClasses(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws IOException {
+ javadoc(base, fKind, oKind, hKind,
+ gensrcPackages.resolve("p1/P1C1.java").toString(),
+ gensrcPackages.resolve("p1/P1C2.java").toString(),
+ gensrcPackages.resolve("p1/P1C3.java").toString());
+
+ new Checker(fKind, oKind, hKind)
+ .classes("p1.P1C1", "p1.P1C2", "p1.P1C3")
+ .check();
+ }
+
+ @Test
+ void testPackage(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws IOException {
+ javadoc(base, fKind, oKind, hKind,
+ "-sourcepath", gensrcPackages.toString(),
+ "p1");
+
+ new Checker(fKind, oKind, hKind)
+ .classes("p1.P1C1", "p1.P1C2", "p1.P1C3")
+ .check();
+ }
+
+ @Test
+ void testPackages(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws IOException {
+ javadoc(base, fKind, oKind, hKind,
+ "-sourcepath", gensrcPackages.toString(),
+ "p1", "p2", "p3");
+
+ new Checker(fKind, oKind, hKind)
+ .classes("p1.P1C1", "p1.P1C2", "p1.P1C3",
+ "p2.P2C1", "p2.P2C2", "p2.P2C3",
+ "p3.P3C1", "p3.P3C2", "p3.P3C3")
+ .check();
+ }
+
+ @Test
+ void testModules(Path base, FrameKind fKind, OverviewKind oKind, HtmlKind hKind) throws IOException {
+ javadoc(base, fKind, oKind, hKind,
+ "-modulesourcepath", gensrcModules.toString(),
+ "-addmods", "m1,m2,m3", // TEMPORARY, SHOULD NOT BE NECESSARY
+ "m1p1", "m1p2", "m1p3",
+ "m2p1", "m2p2", "m2p3",
+ "m3p1", "m3p2", "m3p3");
+
+ new Checker(fKind, oKind, hKind)
+ .classes("m1/m1p1.M1P1C1", "m1/m1p1.M1P1C2", "m1/m1p1.M1P1C3",
+ "m2/m2p1.M2P1C1", "m2/m2p1.M2P1C2", "m2/m2p1.M2P1C3",
+ "m3/m3p1.M3P1C1", "m3/m3p1.M3P1C2", "m3/m3p1.M3P1C3")
+ .check();
+ }
+
+ /**
+ * Check the contents of the generated output, according to the
+ * specified options.
+ */
+ class Checker {
+ private final FrameKind fKind;
+ private final OverviewKind oKind;
+ private final HtmlKind hKind;
+ List<String> classes;
+
+ private boolean frames;
+ private boolean overview;
+
+ Checker(FrameKind fKind, OverviewKind oKind, HtmlKind hKind) {
+ this.fKind = fKind;
+ this.oKind = oKind;
+ this.hKind = hKind;
+ }
+
+ Checker classes(String... classes) {
+ this.classes = Arrays.asList(classes);
+ return this;
+ }
+
+ void check() throws IOException {
+ switch (fKind) {
+ case DEFAULT:
+ case FRAMES:
+ frames = true;
+ break;
+
+ case NO_FRAMES:
+ frames = false;
+ break;
+ }
+
+ switch (oKind) {
+ case DEFAULT:
+ overview = (getPackageCount() > 1);
+ break;
+
+ case OVERVIEW:
+ overview = true;
+ break;
+
+ case NO_OVERVIEW:
+ overview = false;
+ break;
+ }
+
+ checkAllClassesFiles();
+ checkFrameFiles();
+ checkOverviewSummary();
+
+ checkIndex();
+ checkNavBar();
+ checkHelpDoc();
+
+ }
+
+ private void checkAllClassesFiles() {
+ // these files are only generated in frames mode
+ checkFiles(frames,
+ "allclasses-frame.html",
+ "allclasses-noframe.html");
+
+ // this file is only generated when not in frames mode
+ checkFiles(!frames,
+ "allclasses.html");
+ }
+
+ private void checkFrameFiles() {
+ // these files are all only generated in frames mode
+
+ // <module>-frame.html and <module>-type-frame.html files
+ checkFiles(frames, classes.stream()
+ .filter(c -> isInModule(c))
+ .map(c -> modulePart(c))
+ .flatMap(m -> Arrays.asList(
+ m + "-frame.html",
+ m + "-type-frame.html").stream())
+ .collect(Collectors.toSet()));
+
+ // <package>/package-frame.html files
+ checkFiles(frames, classes.stream()
+ .map(c -> packagePart(c) + "/package-frame.html")
+ .collect(Collectors.toSet()));
+ }
+
+ private void checkHelpDoc() {
+ // the Help page only describes Frame/NoFrames in frames mode
+ checkOutput("help-doc.html", frames,
+ "<h2>Frames/No Frames</h2>");
+ }
+
+ private void checkIndex() {
+ // the index.html page only contains frames in frames mode
+ checkOutput("index.html", frames,
+ "<iframe ",
+ "</iframe>");
+
+ // the index.html contains the overview if one
+ // has been given, and not in frames mode
+ checkOutput("index.html", !frames && oKind == OverviewKind.OVERVIEW,
+ "This is the overview file");
+
+ // the index.html file contains a summary table
+ // if an overview was generated and not in frames mode
+ checkOutput("index.html", !frames && overview,
+ "<table class=\"overviewSummary\"");
+
+ // the index.html file contains a redirect if
+ // no frames and no overview
+ checkOutput("index.html", !frames && !overview,
+ "<meta http-equiv=\"Refresh\" content=\"0;",
+ "<script type=\"text/javascript\">window.location.replace(");
+
+ // the index.html file <meta> refresh should only use <noscript> in HTML 5
+ if (!frames && !overview) {
+ checkOutput("index.html", hKind == HtmlKind.HTML5,
+ "<noscript>\n<meta http-equiv=\"Refresh\" content=\"0;");
+ }
+ }
+
+ private void checkNavBar() {
+ // the files containing a navigation bar should only
+ // contain FRAMES/NO-FRAMES links in frames mode
+ List<String> navbarFiles = new ArrayList<>();
+ navbarFiles.addAll(classes.stream()
+ .map(c -> toHtml(packageClassPart(c)))
+ .collect(Collectors.toSet()));
+ for (String f : navbarFiles) {
+ checkOutput(f, frames,
+ "target=\"_top\">Frames</a>",
+ "target=\"_top\">No Frames</a>");
+ }
+ }
+
+ private void checkOverviewSummary() {
+ // the overview-summary.html file only appears if
+ // in frames mode and (overview requested or multiple packages)
+ checkFiles(frames && overview,
+ "overview-summary.html");
+ }
+
+ private long getPackageCount() {
+ return this.classes.stream()
+ .filter(name -> name.contains("."))
+ .map(name -> name.substring(0, name.lastIndexOf(".")))
+ .distinct()
+ .count();
+ }
+
+ private String packagePart(String className) {
+ int slash = className.indexOf("/");
+ int lastDot = className.lastIndexOf(".");
+ return className.substring(slash + 1, lastDot);
+ }
+
+ private String packageClassPart(String className) {
+ int slash = className.indexOf("/");
+ return className.substring(slash + 1);
+ }
+
+ private boolean isInModule(String className) {
+ return className.contains("/");
+ }
+
+ private String modulePart(String className) {
+ int slash = className.indexOf("/");
+ return className.substring(0, slash);
+ }
+
+ private String toHtml(String className) {
+ return className.replace(".", "/") + ".html";
+ }
+ }
+}
--- a/langtools/test/tools/lib/toolbox/ModuleBuilder.java Mon Aug 15 13:42:34 2016 -0700
+++ b/langtools/test/tools/lib/toolbox/ModuleBuilder.java Mon Aug 15 18:00:36 2016 -0700
@@ -165,7 +165,7 @@
if (!comment.isEmpty()) {
sb.append("/**\n").append(comment.replace("\n", " *")).append(" */\n");
}
- sb.append("module ").append(name).append(" {");
+ sb.append("module ").append(name).append(" {\n");
requires.forEach(r -> sb.append(" " + r + "\n"));
exports.forEach(e -> sb.append(" " + e + "\n"));
uses.forEach(u -> sb.append(" " + u + "\n"));