diff -r 000000000000 -r 959103a6100f test/tools/javac/diags/HTMLWriter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/HTMLWriter.java Wed Apr 27 01:34:52 2016 +0800 @@ -0,0 +1,582 @@ +/* + * Copyright (c) 1996,2010, 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. + */ + + + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.net.URL; +import java.text.MessageFormat; +import java.util.ResourceBundle; + +/** + * A class to facilitate writing HTML via a stream. + */ +public class HTMLWriter +{ + /** + * Create an HTMLWriter object, using a default doctype for HTML 3.2. + * @param out a Writer to which to write the generated HTML + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out) throws IOException { + this(out, ""); + } + + /** + * Create an HTMLWriter object, using a specifed doctype header. + * @param out a Writer to which to write the generated HTML + * @param docType a string containing a doctype header for the HTML to be generetaed + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, String docType) throws IOException { + if (out instanceof BufferedWriter) + this.out = (BufferedWriter) out; + else + this.out = new BufferedWriter(out); + this.out.write(docType); + this.out.newLine(); + } + + /** + * Create an HTMLWriter object, using a specified bundle for localizing messages. + * @param out a Writer to which to write the generated HTML + * @param i18n a resource bundle to use to localize messages + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, ResourceBundle i18n) throws IOException { + this(out); + this.i18n = i18n; + } + + + /** + * Create an HTMLWriter object, using a specifed doctype header and + * using a specified bundle for l0calizing messages. + * @param out a Writer to which to write the generated HTML + * @param docType a string containing a doctype header for the HTML to be generetaed + * @param i18n a resource bundle to use to localize messages + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, String docType, ResourceBundle i18n) throws IOException { + this(out, docType); + this.i18n = i18n; + } + + /** + * Set the reource bundle to be used for localizing messages. + * @param i18n the resource bundle to be used for localizing messages + */ + public void setResourceBundle(ResourceBundle i18n) { + this.i18n = i18n; + } + + /** + * Flush the stream, and the underlying output stream. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void flush() throws IOException { + out.flush(); + } + + /** + * Close the stream, and the underlying output stream. + * @throws IOException if there is a problem closing the underlying stream + */ + public void close() throws IOException { + out.close(); + } + + /** + * Write a newline to the underlying output stream. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void newLine() throws IOException { + out.newLine(); + } + + /** + * Start an HTML tag. If a prior tag has been started, it will + * be closed first. Once a tag has been opened, attributes for the + * tag may be written out, followed by body content before finally + * ending the tag. + * @param tag the tag to be started + * @throws IOException if there is a problem writing to the underlying stream + * @see #writeAttr + * @see #write + * @see #endTag + */ + public void startTag(String tag) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + //newLine(); + out.write("<"); + out.write(tag); + state = IN_TAG; + } + + /** + * Finish an HTML tag. It is expected that a call to endTag will match + * a corresponding earlier call to startTag, but there is no formal check + * for this. + * @param tag the tag to be closed. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void endTag(String tag) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + out.newLine(); + } + out.write(""); + //out.newLine(); // PATCHED, jjg + state = IN_BODY; + } + + /** + * Finish an empty element tag, such as a META, BASE or LINK tag. + * This is expected to correspond with a startTag. + * @param tag the tag which is being closed. this is only useful for + * validation, it is not written out + * @throws IllegalStateException if this call does not follow startTag + * (stream is not currently inside a tag) + * @throws IOException if there is a problem writing to the underlying stream + */ + public void endEmptyTag(String tag) throws IOException { + if (state != IN_TAG) + throw new IllegalStateException(); + + out.write(">"); + state = IN_BODY; + out.newLine(); + } + + /** + * Write an attribute for a tag. A tag must previously have been started. + * All tag attributes must be written before any body text is written. + * The value will be quoted if necessary when writing it to the underlying + * stream. No check is made that the attribute is valid for the current tag. + * @param name the name of the attribute to be written + * @param value the value of the attribute to be written + * @throws IllegalStateException if the stream is not in a state to + * write attributes -- e.g. if this call does not follow startTag or other + * calls of writteAttr + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeAttr(String name, String value) throws IOException { + if (state != IN_TAG) + throw new IllegalStateException(); + + out.write(" "); + out.write(name); + out.write("="); + boolean alpha = true; + for (int i = 0; i < value.length() && alpha; i++) + alpha = Character.isLetter(value.charAt(i)); + if (!alpha) + out.write("\""); + out.write(value); + if (!alpha) + out.write("\""); + } + + /** + * Write an attribute for a tag. A tag must previously have been started. + * All tag attributes must be written before any body text is written. + * The value will be quoted if necessary when writing it to the underlying + * stream. No check is made that the attribute is valid for the current tag. + * @param name the name of the attribute to be written + * @param value the value of the attribute to be written + * @throws IllegalStateException if the stream is not in a state to + * write attributes -- e.g. if this call does not follow startTag or other + * calls of writteAttr + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeAttr(String name, int value) throws IOException { + writeAttr(name, Integer.toString(value)); + } + + /** + * Write a line of text, followed by a newline. + * The text will be escaped as necessary. + * @param text the text to be written. + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLine(String text) throws IOException { + write(text); + out.newLine(); + } + + /** + * Write body text, escaping it as necessary. + * If this call follows a call of startTag, the open tag will be + * closed -- meaning that no more attributes can be written until another + * tag is started. If the text value is null, the current tag will still + * be closed, but no other text will be written. + * @param text the text to be written, may be null or zero length. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void write(String text) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + + if (text == null) + return; + + // check to see if there are any special characters + boolean specialChars = false; + for (int i = 0; i < text.length() && !specialChars; i++) { + switch (text.charAt(i)) { + case '<': case '>': case '&': + specialChars = true; + } + } + + // if there are special characters write the string character at a time; + // otherwise, write it out as is + if (specialChars) { + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + switch (c) { + case '<': out.write("<"); break; + case '>': out.write(">"); break; + case '&': out.write("&"); break; + default: out.write(c); + } + } + } + else + out.write(text); + } + + /** + * Write a basic HTML entity, such as   or { . + * @param entity the entity to write + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeEntity(String entity) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + out.write(entity); + } + + /** + * Write an image tag, using a specified path for the image source attribute. + * @param imagePath the path for the image source + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeImage(String imagePath) throws IOException { + startTag(IMAGE); + writeAttr(SRC, imagePath); + } + + /** + * Write an image tag, using a specified path for the image source attribute. + * @param imageURL the url for the image source + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeImage(URL imageURL) throws IOException { + writeImage(imageURL.toString()); + } + + /** + * Write a hypertext link. + * @param anchor the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(String anchor, String body) throws IOException { + startTag(A); + writeAttr(HREF, anchor); + write(body); + endTag(A); + } + + /** + * Write a hypertext link. + * @param file the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(File file, String body) throws IOException { + startTag(A); + StringBuffer sb = new StringBuffer(); + String path = file.getPath().replace(File.separatorChar, '/'); + if (file.isAbsolute() && !path.startsWith("/")) + sb.append('/'); + sb.append(path); + writeAttr(HREF, sb.toString()); + write(body); + endTag(A); + } + + /** + * Write a hypertext link. + * @param file the target and body for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(File file) throws IOException { + writeLink(file, file.getPath()); + } + + /** + * Write a hypertext link. + * @param url the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(URL url, String body) throws IOException { + startTag(A); + writeAttr(HREF, url.toString()); + write(body); + endTag(A); + } + + /** + * Write the destination marker for a hypertext link. + * @param anchor the destination marker for hypertext links + * @param body the body text for the marker + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLinkDestination(String anchor, String body) throws IOException { + startTag(A); + writeAttr(NAME, anchor); + write(body); + endTag(A); + } + + /** + * Write a parameter tag. + * @param name the name of the parameter + * @param value the value of the parameter + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeParam(String name, String value) throws IOException { + startTag(PARAM); + writeAttr(NAME, name); + writeAttr(VALUE, value); + } + + /** + * Write a style attribute. + * @param value the value for the style atrtribute + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeStyleAttr(String value) throws IOException { + writeAttr(STYLE, value); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(ResourceBundle i18n, String key) throws IOException { + write(getString(i18n, key)); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @param arg an argument to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(ResourceBundle i18n, String key, Object arg) throws IOException { + write(getString(i18n, key, arg)); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @param args arguments to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(ResourceBundle i18n, String key, Object[] args) throws IOException { + write(getString(i18n, key, args)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key) throws IOException { + write(getString(i18n, key)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @param arg an argument to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key, Object arg) throws IOException { + write(getString(i18n, key, arg)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @param args arguments to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key, Object[] args) throws IOException { + write(getString(i18n, key, args)); + } + + private String getString(ResourceBundle rb, String key, Object... args) { + String s = rb.getString(key); + return MessageFormat.format(s, args); + } + + /** The HTML "a" tag. */ + public static final String A = "a"; + /** The HTML "align" attribute. */ + public static final String ALIGN = "align"; + /** The HTML "b" tag. */ + public static final String B = "b"; + /** The HTML "body" tag. */ + public static final String BODY = "body"; + /** The HTML "border" attribute. */ + public static final String BORDER = "border"; + /** The HTML "br" tag. */ + public static final String BR = "br"; + /** The HTML "class" attribute. */ + public static final String CLASS = "class"; + /** The HTML "classid" attribute. */ + public static final String CLASSID = "classid"; + /** The HTML "code" tag. */ + public static final String CODE = "code"; + /** The HTML "color" attribte. */ + public static final String COLOR = "color"; + /** The HTML "col" attribute value. */ + public static final String COL = "col"; + /** The HTML "dd" tag. */ + public static final String DD = "dd"; + /** The HTML "div" tag. */ + public static final String DIV = "div"; + /** The HTML "dl" tag. */ + public static final String DL = "dl"; + /** The HTML "dt" tag. */ + public static final String DT = "dt"; + /** The HTML "font" tag. */ + public static final String FONT = "font"; + /** The HTML "h1" tag. */ + public static final String H1 = "h1"; + /** The HTML "h2" tag. */ + public static final String H2 = "h2"; + /** The HTML "h3" tag. */ + public static final String H3 = "h3"; + /** The HTML "h4" tag. */ + public static final String H4 = "h4"; + /** The HTML "h5" tag. */ + public static final String H5 = "h5"; + /** The HTML "head" tag. */ + public static final String HEAD = "head"; + /** The HTML "href" attribute. */ + public static final String HREF = "href"; + /** The HTML "html" tag. */ + public static final String HTML = "html"; + /** The HTML "hr" tag. */ + public static final String HR = "hr"; + /** The HTML "i" tag. */ + public static final String I = "i"; + /** The HTML "id" tag. */ + public static final String ID = "id"; + /** The HTML "image" tag. */ + public static final String IMAGE = "image"; + /** The HTML "left" attribute value. */ + public static final String LEFT = "left"; + /** The HTML "li" tag. */ + public static final String LI = "li"; + /** The HTML "link" tag. */ + public static final String LINK = "link"; + /** The HTML "name" attribute. */ + public static final String NAME = "name"; + /** The HTML "object" tag. */ + public static final String OBJECT = "object"; + /** The HTML "p" tag. */ + public static final String PARAM = "param"; + /** The HTML "param" tag. */ + public static final String P = "p"; + /** The HTML "rel" attribute value. */ + public static final String REL = "rel"; + /** The HTML "right" attribute value. */ + public static final String RIGHT = "right"; + /** The HTML "row" attribute value. */ + public static final String ROW = "row"; + /** The HTML "script" tag. */ + public static final String SCRIPT = "script"; + /** The HTML "small" tag. */ + public static final String SMALL = "small"; + /** The HTML "span" tag. */ + public static final String SPAN = "span"; + /** The HTML "src" attribute. */ + public static final String SRC = "src"; + /** The HTML "scope" attribute. */ + public static final String SCOPE = "scope"; + /** The HTML "style" attribute. */ + public static final String STYLE = "style"; + /** The HTML "table" tag. */ + public static final String TABLE = "table"; + /** The HTML "td" tag. */ + public static final String TD = "td"; + /** The HTML type for JavaScript. */ + public static final String TEXT_JAVASCRIPT = "text/javascript"; + /** The HTML "title"attribute. */ + public static final String TITLE = "title"; + /** The HTML "th" tag. */ + public static final String TH = "th"; + /** The HTML "top" attribute value. */ + public static final String TOP = "top"; + /** The HTML "tr" tag. */ + public static final String TR = "tr"; + /** The HTML "type" attribute. */ + public static final String TYPE = "type"; + /** The HTML "ul" tag. */ + public static final String UL = "ul"; + /** The HTML "valign" attribute. */ + public static final String VALIGN = "valign"; + /** The HTML "value" attribute. */ + public static final String VALUE = "value"; + + + private BufferedWriter out; + private int state; + private ResourceBundle i18n; + private static final int IN_TAG = 1; + private static final int IN_BODY = 2; +}