src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
branchhttp-client-branch
changeset 55844 dbcbcda0e413
parent 55842 cb8fcde5b5c8
parent 47873 7944849362f3
child 55845 a88515bdd90a
equal deleted inserted replaced
55842:cb8fcde5b5c8 55844:dbcbcda0e413
     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 
       
    26 package jdk.javadoc.internal.doclets.formats.html.markup;
       
    27 
       
    28 import java.io.*;
       
    29 import java.util.*;
       
    30 
       
    31 import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
       
    32 import jdk.javadoc.internal.doclets.toolkit.Content;
       
    33 import jdk.javadoc.internal.doclets.toolkit.Resources;
       
    34 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
       
    35 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
       
    36 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
       
    37 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
       
    38 import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes;
       
    39 import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
       
    40 
       
    41 
       
    42 /**
       
    43  * Class for the Html format code generation.
       
    44  * Initializes PrintWriter with FileWriter, to enable print
       
    45  * related methods to generate the code to the named File through FileWriter.
       
    46  *
       
    47  *  <p><b>This is NOT part of any supported API.
       
    48  *  If you write code that depends on this, you do so at your own risk.
       
    49  *  This code and its internal interfaces are subject to change or
       
    50  *  deletion without notice.</b>
       
    51  *
       
    52  * @author Atul M Dambalkar
       
    53  * @author Bhavesh Patel (Modified)
       
    54  */
       
    55 public class HtmlWriter {
       
    56 
       
    57     /**
       
    58      * The window title of this file.
       
    59      */
       
    60     protected String winTitle;
       
    61 
       
    62     /**
       
    63      * The configuration.
       
    64      */
       
    65     protected HtmlConfiguration configuration;
       
    66 
       
    67     private final DocFile docFile;
       
    68 
       
    69     protected Content script;
       
    70 
       
    71 
       
    72     /**
       
    73      * Constructor.
       
    74      *
       
    75      * @param configuration the configuration
       
    76      * @param path the directory path to be created for this file,
       
    77      *             or null if none to be created
       
    78      */
       
    79     public HtmlWriter(HtmlConfiguration configuration, DocPath path) {
       
    80         this.configuration = configuration;
       
    81         docFile = DocFile.createFileForOutput(configuration, path);
       
    82 
       
    83         // The following should be converted to shared Content objects
       
    84         // and moved to Contents, but that will require additional
       
    85         // changes at the use sites.
       
    86         Resources resources = configuration.getResources();
       
    87     }
       
    88 
       
    89     public void write(Content c) throws DocFileIOException {
       
    90         try (Writer writer = docFile.openWriter()) {
       
    91             c.write(writer, true);
       
    92         } catch (IOException e) {
       
    93             throw new DocFileIOException(docFile, DocFileIOException.Mode.WRITE, e);
       
    94         }
       
    95     }
       
    96 
       
    97     /**
       
    98      * Returns an HtmlTree for the SCRIPT tag.
       
    99      *
       
   100      * @return an HtmlTree for the SCRIPT tag
       
   101      */
       
   102     protected HtmlTree getWinTitleScript(){
       
   103         HtmlTree scriptTree = HtmlTree.SCRIPT();
       
   104         if(winTitle != null && winTitle.length() > 0) {
       
   105             String scriptCode = "<!--\n" +
       
   106                     "    try {\n" +
       
   107                     "        if (location.href.indexOf('is-external=true') == -1) {\n" +
       
   108                     "            parent.document.title=\"" + escapeJavaScriptChars(winTitle) + "\";\n" +
       
   109                     "        }\n" +
       
   110                     "    }\n" +
       
   111                     "    catch(err) {\n" +
       
   112                     "    }\n" +
       
   113                     "//-->\n";
       
   114             RawHtml scriptContent = new RawHtml(scriptCode.replace("\n", DocletConstants.NL));
       
   115             scriptTree.addContent(scriptContent);
       
   116         }
       
   117         return scriptTree;
       
   118     }
       
   119 
       
   120     /**
       
   121      * Returns a String with escaped special JavaScript characters.
       
   122      *
       
   123      * @param s String that needs to be escaped
       
   124      * @return a valid escaped JavaScript string
       
   125      */
       
   126     private static String escapeJavaScriptChars(String s) {
       
   127         StringBuilder sb = new StringBuilder();
       
   128         for (int i = 0; i < s.length(); i++) {
       
   129             char ch = s.charAt(i);
       
   130             switch (ch) {
       
   131                 case '\b':
       
   132                     sb.append("\\b");
       
   133                     break;
       
   134                 case '\t':
       
   135                     sb.append("\\t");
       
   136                     break;
       
   137                 case '\n':
       
   138                     sb.append("\\n");
       
   139                     break;
       
   140                 case '\f':
       
   141                     sb.append("\\f");
       
   142                     break;
       
   143                 case '\r':
       
   144                     sb.append("\\r");
       
   145                     break;
       
   146                 case '"':
       
   147                     sb.append("\\\"");
       
   148                     break;
       
   149                 case '\'':
       
   150                     sb.append("\\\'");
       
   151                     break;
       
   152                 case '\\':
       
   153                     sb.append("\\\\");
       
   154                     break;
       
   155                 default:
       
   156                     if (ch < 32 || ch >= 127) {
       
   157                         sb.append(String.format("\\u%04X", (int)ch));
       
   158                     } else {
       
   159                         sb.append(ch);
       
   160                     }
       
   161                     break;
       
   162             }
       
   163         }
       
   164         return sb.toString();
       
   165     }
       
   166 
       
   167     /**
       
   168      * Returns a content tree for the SCRIPT tag for the main page(index.html).
       
   169      *
       
   170      * @return a content for the SCRIPT tag
       
   171      */
       
   172     protected Content getFramesJavaScript() {
       
   173         HtmlTree scriptTree = HtmlTree.SCRIPT();
       
   174         String scriptCode = "\n" +
       
   175                 "    tmpTargetPage = \"\" + window.location.search;\n" +
       
   176                 "    if (tmpTargetPage != \"\" && tmpTargetPage != \"undefined\")\n" +
       
   177                 "        tmpTargetPage = tmpTargetPage.substring(1);\n" +
       
   178                 "    if (tmpTargetPage.indexOf(\":\") != -1 || (tmpTargetPage != \"\" && !validURL(tmpTargetPage)))\n" +
       
   179                 "        tmpTargetPage = \"undefined\";\n" +
       
   180                 "    targetPage = tmpTargetPage;\n" +
       
   181                 "    function validURL(url) {\n" +
       
   182                 "        try {\n" +
       
   183                 "            url = decodeURIComponent(url);\n" +
       
   184                 "        }\n" +
       
   185                 "        catch (error) {\n" +
       
   186                 "            return false;\n" +
       
   187                 "        }\n" +
       
   188                 "        var pos = url.indexOf(\".html\");\n" +
       
   189                 "        if (pos == -1 || pos != url.length - 5)\n" +
       
   190                 "            return false;\n" +
       
   191                 "        var allowNumber = false;\n" +
       
   192                 "        var allowSep = false;\n" +
       
   193                 "        var seenDot = false;\n" +
       
   194                 "        for (var i = 0; i < url.length - 5; i++) {\n" +
       
   195                 "            var ch = url.charAt(i);\n" +
       
   196                 "            if ('a' <= ch && ch <= 'z' ||\n" +
       
   197                 "                    'A' <= ch && ch <= 'Z' ||\n" +
       
   198                 "                    ch == '$' ||\n" +
       
   199                 "                    ch == '_' ||\n" +
       
   200                 "                    ch.charCodeAt(0) > 127) {\n" +
       
   201                 "                allowNumber = true;\n" +
       
   202                 "                allowSep = true;\n" +
       
   203                 "            } else if ('0' <= ch && ch <= '9'\n" +
       
   204                 "                    || ch == '-') {\n" +
       
   205                 "                if (!allowNumber)\n" +
       
   206                 "                     return false;\n" +
       
   207                 "            } else if (ch == '/' || ch == '.') {\n" +
       
   208                 "                if (!allowSep)\n" +
       
   209                 "                    return false;\n" +
       
   210                 "                allowNumber = false;\n" +
       
   211                 "                allowSep = false;\n" +
       
   212                 "                if (ch == '.')\n" +
       
   213                 "                     seenDot = true;\n" +
       
   214                 "                if (ch == '/' && seenDot)\n" +
       
   215                 "                     return false;\n" +
       
   216                 "            } else {\n" +
       
   217                 "                return false;\n" +
       
   218                 "            }\n" +
       
   219                 "        }\n" +
       
   220                 "        return true;\n" +
       
   221                 "    }\n" +
       
   222                 "    function loadFrames() {\n" +
       
   223                 "        if (targetPage != \"\" && targetPage != \"undefined\")\n" +
       
   224                 "             top.classFrame.location = top.targetPage;\n" +
       
   225                 "    }\n";
       
   226         RawHtml scriptContent = new RawHtml(scriptCode.replace("\n", DocletConstants.NL));
       
   227         scriptTree.addContent(scriptContent);
       
   228         return scriptTree;
       
   229     }
       
   230 
       
   231     /**
       
   232      * Returns an HtmlTree for the BODY tag.
       
   233      *
       
   234      * @param includeScript  set true if printing windowtitle script
       
   235      * @param title title for the window
       
   236      * @return an HtmlTree for the BODY tag
       
   237      */
       
   238     public HtmlTree getBody(boolean includeScript, String title) {
       
   239         HtmlTree body = new HtmlTree(HtmlTag.BODY);
       
   240         // Set window title string which is later printed
       
   241         this.winTitle = title;
       
   242         // Don't print windowtitle script for overview-frame, allclasses-frame
       
   243         // and package-frame
       
   244         if (includeScript) {
       
   245             this.script = getWinTitleScript();
       
   246             body.addContent(script);
       
   247             Content noScript = HtmlTree.NOSCRIPT(
       
   248                     HtmlTree.DIV(configuration.getContent("doclet.No_Script_Message")));
       
   249             body.addContent(noScript);
       
   250         }
       
   251         return body;
       
   252     }
       
   253 
       
   254     /**
       
   255      * Generated javascript variables for the document.
       
   256      *
       
   257      * @param typeMap map comprising of method and type relationship
       
   258      * @param tabTypes set comprising of all table tab types for this class
       
   259      * @param elementName packages or methods table for which tabs need to be displayed
       
   260      */
       
   261     public void generateTableTabTypesScript(Map<String,Integer> typeMap,
       
   262             Set<? extends TableTabTypes> tabTypes, String elementName) {
       
   263         String sep = "";
       
   264         StringBuilder vars = new StringBuilder("var ");
       
   265         vars.append(elementName)
       
   266                 .append(" = {");
       
   267         for (Map.Entry<String,Integer> entry : typeMap.entrySet()) {
       
   268             vars.append(sep);
       
   269             sep = ",";
       
   270             vars.append("\"")
       
   271                     .append(entry.getKey())
       
   272                     .append("\":")
       
   273                     .append(entry.getValue());
       
   274         }
       
   275         vars.append("};").append(DocletConstants.NL);
       
   276         sep = "";
       
   277         vars.append("var tabs = {");
       
   278         for (TableTabTypes entry : tabTypes) {
       
   279             vars.append(sep);
       
   280             sep = ",";
       
   281             vars.append(entry.tableTabs().value())
       
   282                     .append(":")
       
   283                     .append("[")
       
   284                     .append("\"")
       
   285                     .append(entry.tableTabs().tabId())
       
   286                     .append("\"")
       
   287                     .append(sep)
       
   288                     .append("\"")
       
   289                     .append(configuration.getText(entry.tableTabs().resourceKey()))
       
   290                     .append("\"]");
       
   291         }
       
   292         vars.append("};")
       
   293                 .append(DocletConstants.NL);
       
   294         addStyles(HtmlStyle.altColor, vars);
       
   295         addStyles(HtmlStyle.rowColor, vars);
       
   296         addStyles(HtmlStyle.tableTab, vars);
       
   297         addStyles(HtmlStyle.activeTableTab, vars);
       
   298         script.addContent(new RawHtml(vars));
       
   299     }
       
   300 
       
   301     /**
       
   302      * Generated javascript variables for the document.
       
   303      *
       
   304      * @param groupTypeMap map comprising of group relationship
       
   305      * @param groupTypes map comprising of all table tab types
       
   306      */
       
   307     public void generateGroupTypesScript(Map<String,Integer> groupTypeMap,
       
   308             Map<String,TableTabs> groupTypes) {
       
   309         String sep = "";
       
   310         StringBuilder vars = new StringBuilder("var groups");
       
   311         vars.append(" = {");
       
   312         for (Map.Entry<String,Integer> entry : groupTypeMap.entrySet()) {
       
   313             vars.append(sep);
       
   314             sep = ",";
       
   315             vars.append("\"")
       
   316                     .append(entry.getKey())
       
   317                     .append("\":")
       
   318                     .append(entry.getValue());
       
   319         }
       
   320         vars.append("};").append(DocletConstants.NL);
       
   321         sep = "";
       
   322         vars.append("var tabs = {");
       
   323         for (String group : groupTypes.keySet()) {
       
   324             TableTabs tab = groupTypes.get(group);
       
   325             vars.append(sep);
       
   326             sep = ",";
       
   327             vars.append(tab.value())
       
   328                     .append(":")
       
   329                     .append("[")
       
   330                     .append("\"")
       
   331                     .append(tab.tabId())
       
   332                     .append("\"")
       
   333                     .append(sep)
       
   334                     .append("\"")
       
   335                     .append(new StringContent(tab.resourceKey()))
       
   336                     .append("\"]");
       
   337         }
       
   338         vars.append("};")
       
   339                 .append(DocletConstants.NL);
       
   340         addStyles(HtmlStyle.altColor, vars);
       
   341         addStyles(HtmlStyle.rowColor, vars);
       
   342         addStyles(HtmlStyle.tableTab, vars);
       
   343         addStyles(HtmlStyle.activeTableTab, vars);
       
   344         script.addContent(new RawHtml(vars));
       
   345     }
       
   346 
       
   347     /**
       
   348      * Adds javascript style variables to the document.
       
   349      *
       
   350      * @param style style to be added as a javascript variable
       
   351      * @param vars variable string to which the style variable will be added
       
   352      */
       
   353     public void addStyles(HtmlStyle style, StringBuilder vars) {
       
   354         vars.append("var ").append(style).append(" = \"").append(style)
       
   355                 .append("\";").append(DocletConstants.NL);
       
   356     }
       
   357 
       
   358     /**
       
   359      * Returns an HtmlTree for the TITLE tag.
       
   360      *
       
   361      * @return an HtmlTree for the TITLE tag
       
   362      */
       
   363     public HtmlTree getTitle() {
       
   364         HtmlTree title = HtmlTree.TITLE(new StringContent(winTitle));
       
   365         return title;
       
   366     }
       
   367 }