src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java
changeset 54409 94986cf5e969
parent 54408 8fe16bf92ebd
parent 54373 13935056b05e
child 54410 7feb5e303c83
equal deleted inserted replaced
54408:8fe16bf92ebd 54409:94986cf5e969
     1 /*
       
     2  * Copyright (c) 1997, 2019, 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 jdk.javadoc.internal.doclets.formats.html.markup.Head;
       
    29 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
       
    30 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
       
    31 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
       
    32 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
       
    33 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
       
    34 import jdk.javadoc.internal.doclets.formats.html.markup.Script;
       
    35 import jdk.javadoc.internal.doclets.toolkit.Content;
       
    36 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
       
    37 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
       
    38 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
       
    39 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
       
    40 
       
    41 
       
    42 /**
       
    43  * Generate the documentation in the Html "frame" format in the browser. The
       
    44  * generated documentation will have two or three frames depending upon the
       
    45  * number of packages on the command line. In general there will be three frames
       
    46  * in the output, a left-hand top frame will have a list of all packages with
       
    47  * links to target left-hand bottom frame. The left-hand bottom frame will have
       
    48  * the particular package contents or the all-classes list, where as the single
       
    49  * right-hand frame will have overview or package summary or class file. Also
       
    50  * take care of browsers which do not support Html frames.
       
    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  */
       
    59 public class FrameOutputWriter extends HtmlDocletWriter {
       
    60 
       
    61     /**
       
    62      * Number of packages specified on the command line.
       
    63      */
       
    64     int noOfPackages;
       
    65 
       
    66     /**
       
    67      * Constructor to construct FrameOutputWriter object.
       
    68      *
       
    69      * @param configuration for this run
       
    70      * @param filename File to be generated.
       
    71      */
       
    72     public FrameOutputWriter(HtmlConfiguration configuration, DocPath filename) {
       
    73         super(configuration, filename);
       
    74         noOfPackages = configuration.packages.size();
       
    75     }
       
    76 
       
    77     /**
       
    78      * Construct FrameOutputWriter object and then use it to generate the Html
       
    79      * file which will have the description of all the frames in the
       
    80      * documentation. The name of the generated file is "index.html" which is
       
    81      * the default first file for Html documents.
       
    82      * @param configuration the configuration for this doclet
       
    83      * @throws DocFileIOException if there is a problem generating the frame file
       
    84      */
       
    85     public static void generate(HtmlConfiguration configuration) throws DocFileIOException {
       
    86         FrameOutputWriter framegen = new FrameOutputWriter(configuration, DocPaths.INDEX);
       
    87         framegen.generateFrameFile();
       
    88     }
       
    89 
       
    90     /**
       
    91      * Generate the constants in the "index.html" file. Print the frame details
       
    92      * as well as warning if browser is not supporting the Html frames.
       
    93      * @throws DocFileIOException if there is a problem generating the frame file
       
    94      */
       
    95     protected void generateFrameFile() throws DocFileIOException {
       
    96         Content frame = getFrameDetails();
       
    97         HtmlTree body = new HtmlTree(HtmlTag.BODY);
       
    98         body.put(HtmlAttr.CLASS, "frames");
       
    99         body.put(HtmlAttr.ONLOAD, "loadFrames()");
       
   100         String topFilePath = configuration.topFile.getPath();
       
   101         Script script = new Script(
       
   102                 "\nif (targetPage == \"\" || targetPage == \"undefined\")\n" +
       
   103                 "     window.location.replace(")
       
   104                 .appendStringLiteral(topFilePath, '\'')
       
   105                 .append(");\n");
       
   106         body.add(script.asContent());
       
   107         Content noScript = HtmlTree.NOSCRIPT(contents.noScriptMessage);
       
   108         body.add(noScript);
       
   109         HtmlTree main = HtmlTree.MAIN(frame);
       
   110         body.add(main);
       
   111         if (configuration.windowtitle.length() > 0) {
       
   112             printFramesDocument(configuration.windowtitle, body);
       
   113         } else {
       
   114             printFramesDocument(resources.getText("doclet.Generated_Docs_Untitled"), body);
       
   115         }
       
   116     }
       
   117 
       
   118     /**
       
   119      * Print the frames version of the Html file header.
       
   120      * Called only when generating an HTML frames file.
       
   121      *
       
   122      * @param title Title of this HTML document
       
   123      * @param body the body content tree to be added to the HTML document
       
   124      * @throws DocFileIOException if there is an error writing the frames document
       
   125      */
       
   126     private void printFramesDocument(String title, HtmlTree body) throws DocFileIOException {
       
   127         Content htmlComment = contents.newPage;
       
   128         Head head = new Head(path, configuration.docletVersion)
       
   129                 .setTimestamp(!configuration.notimestamp)
       
   130                 .setTitle(title)
       
   131                 .setDescription("frames")
       
   132                 .setGenerator(getGenerator(getClass()))
       
   133                 .setCharset(configuration.charset)
       
   134                 .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets())
       
   135                 .addDefaultScript(false)
       
   136                 .addScript(getFramesScript());
       
   137 
       
   138         Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), head.toContent(), body);
       
   139         HtmlDocument htmlDocument = new HtmlDocument(htmlComment, htmlTree);
       
   140         htmlDocument.write(DocFile.createFileForOutput(configuration, path));
       
   141    }
       
   142 
       
   143     /**
       
   144      * Get the frame sizes and their contents.
       
   145      *
       
   146      * @return a content tree for the frame details
       
   147      */
       
   148     protected Content getFrameDetails() {
       
   149         HtmlTree leftContainerDiv = new HtmlTree(HtmlTag.DIV);
       
   150         HtmlTree rightContainerDiv = new HtmlTree(HtmlTag.DIV);
       
   151         leftContainerDiv.setStyle(HtmlStyle.leftContainer);
       
   152         rightContainerDiv.setStyle(HtmlStyle.rightContainer);
       
   153         if (configuration.showModules && configuration.modules.size() > 1) {
       
   154             addAllModulesFrameTag(leftContainerDiv);
       
   155         } else if (noOfPackages > 1) {
       
   156             addAllPackagesFrameTag(leftContainerDiv);
       
   157         }
       
   158         addAllClassesFrameTag(leftContainerDiv);
       
   159         addClassFrameTag(rightContainerDiv);
       
   160         HtmlTree mainContainer = HtmlTree.DIV(HtmlStyle.mainContainer, leftContainerDiv);
       
   161         mainContainer.add(rightContainerDiv);
       
   162         return mainContainer;
       
   163     }
       
   164 
       
   165     /**
       
   166      * Add the IFRAME tag for the frame that lists all modules.
       
   167      *
       
   168      * @param contentTree to which the information will be added
       
   169      */
       
   170     private void addAllModulesFrameTag(Content contentTree) {
       
   171         HtmlTree frame = HtmlTree.IFRAME(DocPaths.MODULE_OVERVIEW_FRAME.getPath(),
       
   172                 "packageListFrame", resources.getText("doclet.All_Modules"));
       
   173         HtmlTree leftTop = HtmlTree.DIV(HtmlStyle.leftTop, frame);
       
   174         contentTree.add(leftTop);
       
   175     }
       
   176 
       
   177     /**
       
   178      * Add the IFRAME tag for the frame that lists all packages.
       
   179      *
       
   180      * @param contentTree the content tree to which the information will be added
       
   181      */
       
   182     private void addAllPackagesFrameTag(Content contentTree) {
       
   183         HtmlTree frame = HtmlTree.IFRAME(DocPaths.OVERVIEW_FRAME.getPath(),
       
   184                 "packageListFrame", resources.getText("doclet.All_Packages"));
       
   185         HtmlTree leftTop = HtmlTree.DIV(HtmlStyle.leftTop, frame);
       
   186         contentTree.add(leftTop);
       
   187     }
       
   188 
       
   189     /**
       
   190      * Add the IFRAME tag for the frame that lists all classes.
       
   191      *
       
   192      * @param contentTree the content tree to which the information will be added
       
   193      */
       
   194     private void addAllClassesFrameTag(Content contentTree) {
       
   195         HtmlTree frame = HtmlTree.IFRAME(DocPaths.ALLCLASSES_FRAME.getPath(),
       
   196                 "packageFrame", resources.getText("doclet.All_classes_and_interfaces"));
       
   197         HtmlTree leftBottom = HtmlTree.DIV(HtmlStyle.leftBottom, frame);
       
   198         contentTree.add(leftBottom);
       
   199     }
       
   200 
       
   201     /**
       
   202      * Add the IFRAME tag for the frame that describes the class in detail.
       
   203      *
       
   204      * @param contentTree the content tree to which the information will be added
       
   205      */
       
   206     private void addClassFrameTag(Content contentTree) {
       
   207         HtmlTree frame = HtmlTree.IFRAME(configuration.topFile.getPath(), "classFrame",
       
   208                 resources.getText("doclet.Package_class_and_interface_descriptions"));
       
   209         frame.setStyle(HtmlStyle.rightIframe);
       
   210         contentTree.add(frame);
       
   211     }
       
   212 
       
   213     /**
       
   214      * Returns a content tree for the SCRIPT tag for the main page(index.html).
       
   215      *
       
   216      * @return a content for the SCRIPT tag
       
   217      */
       
   218     protected Script getFramesScript() {
       
   219         return new Script("\n" +
       
   220                 "    tmpTargetPage = \"\" + window.location.search;\n" +
       
   221                 "    if (tmpTargetPage != \"\" && tmpTargetPage != \"undefined\")\n" +
       
   222                 "        tmpTargetPage = tmpTargetPage.substring(1);\n" +
       
   223                 "    if (tmpTargetPage.indexOf(\":\") != -1 || (tmpTargetPage != \"\" && !validURL(tmpTargetPage)))\n" +
       
   224                 "        tmpTargetPage = \"undefined\";\n" +
       
   225                 "    targetPage = tmpTargetPage;\n" +
       
   226                 "    function validURL(url) {\n" +
       
   227                 "        try {\n" +
       
   228                 "            url = decodeURIComponent(url);\n" +
       
   229                 "        }\n" +
       
   230                 "        catch (error) {\n" +
       
   231                 "            return false;\n" +
       
   232                 "        }\n" +
       
   233                 "        var pos = url.indexOf(\".html\");\n" +
       
   234                 "        if (pos == -1 || pos != url.length - 5)\n" +
       
   235                 "            return false;\n" +
       
   236                 "        var allowNumber = false;\n" +
       
   237                 "        var allowSep = false;\n" +
       
   238                 "        var seenDot = false;\n" +
       
   239                 "        for (var i = 0; i < url.length - 5; i++) {\n" +
       
   240                 "            var ch = url.charAt(i);\n" +
       
   241                 "            if ('a' <= ch && ch <= 'z' ||\n" +
       
   242                 "                    'A' <= ch && ch <= 'Z' ||\n" +
       
   243                 "                    ch == '$' ||\n" +
       
   244                 "                    ch == '_' ||\n" +
       
   245                 "                    ch.charCodeAt(0) > 127) {\n" +
       
   246                 "                allowNumber = true;\n" +
       
   247                 "                allowSep = true;\n" +
       
   248                 "            } else if ('0' <= ch && ch <= '9'\n" +
       
   249                 "                    || ch == '-') {\n" +
       
   250                 "                if (!allowNumber)\n" +
       
   251                 "                     return false;\n" +
       
   252                 "            } else if (ch == '/' || ch == '.') {\n" +
       
   253                 "                if (!allowSep)\n" +
       
   254                 "                    return false;\n" +
       
   255                 "                allowNumber = false;\n" +
       
   256                 "                allowSep = false;\n" +
       
   257                 "                if (ch == '.')\n" +
       
   258                 "                     seenDot = true;\n" +
       
   259                 "                if (ch == '/' && seenDot)\n" +
       
   260                 "                     return false;\n" +
       
   261                 "            } else {\n" +
       
   262                 "                return false;\n" +
       
   263                 "            }\n" +
       
   264                 "        }\n" +
       
   265                 "        return true;\n" +
       
   266                 "    }\n" +
       
   267                 "    function loadFrames() {\n" +
       
   268                 "        if (targetPage != \"\" && targetPage != \"undefined\")\n" +
       
   269                 "             top.classFrame.location = top.targetPage;\n" +
       
   270                 "    }\n");
       
   271     }
       
   272 }