1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/tools/javac/diags/HTMLWriter.java Thu Jul 22 11:02:54 2010 -0700 1.3 @@ -0,0 +1,582 @@ 1.4 +/* 1.5 + * Copyright (c) 1996,2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + */ 1.26 + 1.27 + 1.28 + 1.29 +import java.io.BufferedWriter; 1.30 +import java.io.File; 1.31 +import java.io.IOException; 1.32 +import java.io.Writer; 1.33 +import java.net.URL; 1.34 +import java.text.MessageFormat; 1.35 +import java.util.ResourceBundle; 1.36 + 1.37 +/** 1.38 + * A class to facilitate writing HTML via a stream. 1.39 + */ 1.40 +public class HTMLWriter 1.41 +{ 1.42 + /** 1.43 + * Create an HTMLWriter object, using a default doctype for HTML 3.2. 1.44 + * @param out a Writer to which to write the generated HTML 1.45 + * @throws IOException if there is a problem writing to the underlying stream 1.46 + */ 1.47 + public HTMLWriter(Writer out) throws IOException { 1.48 + this(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"); 1.49 + } 1.50 + 1.51 + /** 1.52 + * Create an HTMLWriter object, using a specifed doctype header. 1.53 + * @param out a Writer to which to write the generated HTML 1.54 + * @param docType a string containing a doctype header for the HTML to be generetaed 1.55 + * @throws IOException if there is a problem writing to the underlying stream 1.56 + */ 1.57 + public HTMLWriter(Writer out, String docType) throws IOException { 1.58 + if (out instanceof BufferedWriter) 1.59 + this.out = (BufferedWriter) out; 1.60 + else 1.61 + this.out = new BufferedWriter(out); 1.62 + this.out.write(docType); 1.63 + this.out.newLine(); 1.64 + } 1.65 + 1.66 + /** 1.67 + * Create an HTMLWriter object, using a specified bundle for localizing messages. 1.68 + * @param out a Writer to which to write the generated HTML 1.69 + * @param i18n a resource bundle to use to localize messages 1.70 + * @throws IOException if there is a problem writing to the underlying stream 1.71 + */ 1.72 + public HTMLWriter(Writer out, ResourceBundle i18n) throws IOException { 1.73 + this(out); 1.74 + this.i18n = i18n; 1.75 + } 1.76 + 1.77 + 1.78 + /** 1.79 + * Create an HTMLWriter object, using a specifed doctype header and 1.80 + * using a specified bundle for l0calizing messages. 1.81 + * @param out a Writer to which to write the generated HTML 1.82 + * @param docType a string containing a doctype header for the HTML to be generetaed 1.83 + * @param i18n a resource bundle to use to localize messages 1.84 + * @throws IOException if there is a problem writing to the underlying stream 1.85 + */ 1.86 + public HTMLWriter(Writer out, String docType, ResourceBundle i18n) throws IOException { 1.87 + this(out, docType); 1.88 + this.i18n = i18n; 1.89 + } 1.90 + 1.91 + /** 1.92 + * Set the reource bundle to be used for localizing messages. 1.93 + * @param i18n the resource bundle to be used for localizing messages 1.94 + */ 1.95 + public void setResourceBundle(ResourceBundle i18n) { 1.96 + this.i18n = i18n; 1.97 + } 1.98 + 1.99 + /** 1.100 + * Flush the stream, and the underlying output stream. 1.101 + * @throws IOException if there is a problem writing to the underlying stream 1.102 + */ 1.103 + public void flush() throws IOException { 1.104 + out.flush(); 1.105 + } 1.106 + 1.107 + /** 1.108 + * Close the stream, and the underlying output stream. 1.109 + * @throws IOException if there is a problem closing the underlying stream 1.110 + */ 1.111 + public void close() throws IOException { 1.112 + out.close(); 1.113 + } 1.114 + 1.115 + /** 1.116 + * Write a newline to the underlying output stream. 1.117 + * @throws IOException if there is a problem writing to the underlying stream 1.118 + */ 1.119 + public void newLine() throws IOException { 1.120 + out.newLine(); 1.121 + } 1.122 + 1.123 + /** 1.124 + * Start an HTML tag. If a prior tag has been started, it will 1.125 + * be closed first. Once a tag has been opened, attributes for the 1.126 + * tag may be written out, followed by body content before finally 1.127 + * ending the tag. 1.128 + * @param tag the tag to be started 1.129 + * @throws IOException if there is a problem writing to the underlying stream 1.130 + * @see #writeAttr 1.131 + * @see #write 1.132 + * @see #endTag 1.133 + */ 1.134 + public void startTag(String tag) throws IOException { 1.135 + if (state == IN_TAG) { 1.136 + out.write(">"); 1.137 + state = IN_BODY; 1.138 + } 1.139 + //newLine(); 1.140 + out.write("<"); 1.141 + out.write(tag); 1.142 + state = IN_TAG; 1.143 + } 1.144 + 1.145 + /** 1.146 + * Finish an HTML tag. It is expected that a call to endTag will match 1.147 + * a corresponding earlier call to startTag, but there is no formal check 1.148 + * for this. 1.149 + * @param tag the tag to be closed. 1.150 + * @throws IOException if there is a problem writing to the underlying stream 1.151 + */ 1.152 + public void endTag(String tag) throws IOException { 1.153 + if (state == IN_TAG) { 1.154 + out.write(">"); 1.155 + state = IN_BODY; 1.156 + out.newLine(); 1.157 + } 1.158 + out.write("</"); 1.159 + out.write(tag); 1.160 + out.write(">"); 1.161 + //out.newLine(); // PATCHED, jjg 1.162 + state = IN_BODY; 1.163 + } 1.164 + 1.165 + /** 1.166 + * Finish an empty element tag, such as a META, BASE or LINK tag. 1.167 + * This is expected to correspond with a startTag. 1.168 + * @param tag the tag which is being closed. this is only useful for 1.169 + * validation, it is not written out 1.170 + * @throws IllegalStateException if this call does not follow startTag 1.171 + * (stream is not currently inside a tag) 1.172 + * @throws IOException if there is a problem writing to the underlying stream 1.173 + */ 1.174 + public void endEmptyTag(String tag) throws IOException { 1.175 + if (state != IN_TAG) 1.176 + throw new IllegalStateException(); 1.177 + 1.178 + out.write(">"); 1.179 + state = IN_BODY; 1.180 + out.newLine(); 1.181 + } 1.182 + 1.183 + /** 1.184 + * Write an attribute for a tag. A tag must previously have been started. 1.185 + * All tag attributes must be written before any body text is written. 1.186 + * The value will be quoted if necessary when writing it to the underlying 1.187 + * stream. No check is made that the attribute is valid for the current tag. 1.188 + * @param name the name of the attribute to be written 1.189 + * @param value the value of the attribute to be written 1.190 + * @throws IllegalStateException if the stream is not in a state to 1.191 + * write attributes -- e.g. if this call does not follow startTag or other 1.192 + * calls of writteAttr 1.193 + * @throws IOException if there is a problem writing to the underlying stream 1.194 + */ 1.195 + public void writeAttr(String name, String value) throws IOException { 1.196 + if (state != IN_TAG) 1.197 + throw new IllegalStateException(); 1.198 + 1.199 + out.write(" "); 1.200 + out.write(name); 1.201 + out.write("="); 1.202 + boolean alpha = true; 1.203 + for (int i = 0; i < value.length() && alpha; i++) 1.204 + alpha = Character.isLetter(value.charAt(i)); 1.205 + if (!alpha) 1.206 + out.write("\""); 1.207 + out.write(value); 1.208 + if (!alpha) 1.209 + out.write("\""); 1.210 + } 1.211 + 1.212 + /** 1.213 + * Write an attribute for a tag. A tag must previously have been started. 1.214 + * All tag attributes must be written before any body text is written. 1.215 + * The value will be quoted if necessary when writing it to the underlying 1.216 + * stream. No check is made that the attribute is valid for the current tag. 1.217 + * @param name the name of the attribute to be written 1.218 + * @param value the value of the attribute to be written 1.219 + * @throws IllegalStateException if the stream is not in a state to 1.220 + * write attributes -- e.g. if this call does not follow startTag or other 1.221 + * calls of writteAttr 1.222 + * @throws IOException if there is a problem writing to the underlying stream 1.223 + */ 1.224 + public void writeAttr(String name, int value) throws IOException { 1.225 + writeAttr(name, Integer.toString(value)); 1.226 + } 1.227 + 1.228 + /** 1.229 + * Write a line of text, followed by a newline. 1.230 + * The text will be escaped as necessary. 1.231 + * @param text the text to be written. 1.232 + * @throws IOException if there is a problem closing the underlying stream 1.233 + */ 1.234 + public void writeLine(String text) throws IOException { 1.235 + write(text); 1.236 + out.newLine(); 1.237 + } 1.238 + 1.239 + /** 1.240 + * Write body text, escaping it as necessary. 1.241 + * If this call follows a call of startTag, the open tag will be 1.242 + * closed -- meaning that no more attributes can be written until another 1.243 + * tag is started. If the text value is null, the current tag will still 1.244 + * be closed, but no other text will be written. 1.245 + * @param text the text to be written, may be null or zero length. 1.246 + * @throws IOException if there is a problem writing to the underlying stream 1.247 + */ 1.248 + public void write(String text) throws IOException { 1.249 + if (state == IN_TAG) { 1.250 + out.write(">"); 1.251 + state = IN_BODY; 1.252 + } 1.253 + 1.254 + if (text == null) 1.255 + return; 1.256 + 1.257 + // check to see if there are any special characters 1.258 + boolean specialChars = false; 1.259 + for (int i = 0; i < text.length() && !specialChars; i++) { 1.260 + switch (text.charAt(i)) { 1.261 + case '<': case '>': case '&': 1.262 + specialChars = true; 1.263 + } 1.264 + } 1.265 + 1.266 + // if there are special characters write the string character at a time; 1.267 + // otherwise, write it out as is 1.268 + if (specialChars) { 1.269 + for (int i = 0; i < text.length(); i++) { 1.270 + char c = text.charAt(i); 1.271 + switch (c) { 1.272 + case '<': out.write("<"); break; 1.273 + case '>': out.write(">"); break; 1.274 + case '&': out.write("&"); break; 1.275 + default: out.write(c); 1.276 + } 1.277 + } 1.278 + } 1.279 + else 1.280 + out.write(text); 1.281 + } 1.282 + 1.283 + /** 1.284 + * Write a basic HTML entity, such as or { . 1.285 + * @param entity the entity to write 1.286 + * @throws IOException if there is a problem writing to the underlying stream 1.287 + */ 1.288 + public void writeEntity(String entity) throws IOException { 1.289 + if (state == IN_TAG) { 1.290 + out.write(">"); 1.291 + state = IN_BODY; 1.292 + } 1.293 + out.write(entity); 1.294 + } 1.295 + 1.296 + /** 1.297 + * Write an image tag, using a specified path for the image source attribute. 1.298 + * @param imagePath the path for the image source 1.299 + * @throws IOException if there is a problem closing the underlying stream 1.300 + */ 1.301 + public void writeImage(String imagePath) throws IOException { 1.302 + startTag(IMAGE); 1.303 + writeAttr(SRC, imagePath); 1.304 + } 1.305 + 1.306 + /** 1.307 + * Write an image tag, using a specified path for the image source attribute. 1.308 + * @param imageURL the url for the image source 1.309 + * @throws IOException if there is a problem closing the underlying stream 1.310 + */ 1.311 + public void writeImage(URL imageURL) throws IOException { 1.312 + writeImage(imageURL.toString()); 1.313 + } 1.314 + 1.315 + /** 1.316 + * Write a hypertext link. 1.317 + * @param anchor the target for the link 1.318 + * @param body the body text for the link 1.319 + * @throws IOException if there is a problem closing the underlying stream 1.320 + */ 1.321 + public void writeLink(String anchor, String body) throws IOException { 1.322 + startTag(A); 1.323 + writeAttr(HREF, anchor); 1.324 + write(body); 1.325 + endTag(A); 1.326 + } 1.327 + 1.328 + /** 1.329 + * Write a hypertext link. 1.330 + * @param file the target for the link 1.331 + * @param body the body text for the link 1.332 + * @throws IOException if there is a problem closing the underlying stream 1.333 + */ 1.334 + public void writeLink(File file, String body) throws IOException { 1.335 + startTag(A); 1.336 + StringBuffer sb = new StringBuffer(); 1.337 + String path = file.getPath().replace(File.separatorChar, '/'); 1.338 + if (file.isAbsolute() && !path.startsWith("/")) 1.339 + sb.append('/'); 1.340 + sb.append(path); 1.341 + writeAttr(HREF, sb.toString()); 1.342 + write(body); 1.343 + endTag(A); 1.344 + } 1.345 + 1.346 + /** 1.347 + * Write a hypertext link. 1.348 + * @param file the target and body for the link 1.349 + * @throws IOException if there is a problem closing the underlying stream 1.350 + */ 1.351 + public void writeLink(File file) throws IOException { 1.352 + writeLink(file, file.getPath()); 1.353 + } 1.354 + 1.355 + /** 1.356 + * Write a hypertext link. 1.357 + * @param url the target for the link 1.358 + * @param body the body text for the link 1.359 + * @throws IOException if there is a problem closing the underlying stream 1.360 + */ 1.361 + public void writeLink(URL url, String body) throws IOException { 1.362 + startTag(A); 1.363 + writeAttr(HREF, url.toString()); 1.364 + write(body); 1.365 + endTag(A); 1.366 + } 1.367 + 1.368 + /** 1.369 + * Write the destination marker for a hypertext link. 1.370 + * @param anchor the destination marker for hypertext links 1.371 + * @param body the body text for the marker 1.372 + * @throws IOException if there is a problem closing the underlying stream 1.373 + */ 1.374 + public void writeLinkDestination(String anchor, String body) throws IOException { 1.375 + startTag(A); 1.376 + writeAttr(NAME, anchor); 1.377 + write(body); 1.378 + endTag(A); 1.379 + } 1.380 + 1.381 + /** 1.382 + * Write a parameter tag. 1.383 + * @param name the name of the parameter 1.384 + * @param value the value of the parameter 1.385 + * @throws IOException if there is a problem closing the underlying stream 1.386 + */ 1.387 + public void writeParam(String name, String value) throws IOException { 1.388 + startTag(PARAM); 1.389 + writeAttr(NAME, name); 1.390 + writeAttr(VALUE, value); 1.391 + } 1.392 + 1.393 + /** 1.394 + * Write a style attribute. 1.395 + * @param value the value for the style atrtribute 1.396 + * @throws IOException if there is a problem closing the underlying stream 1.397 + */ 1.398 + public void writeStyleAttr(String value) throws IOException { 1.399 + writeAttr(STYLE, value); 1.400 + } 1.401 + 1.402 + /** 1.403 + * Write a localized message, using a specified resource bundle. 1.404 + * @param i18n the resource bundle used to localize the message 1.405 + * @param key the key for the message to be localized 1.406 + * @throws IOException if there is a problem closing the underlying stream 1.407 + */ 1.408 + public void write(ResourceBundle i18n, String key) throws IOException { 1.409 + write(getString(i18n, key)); 1.410 + } 1.411 + 1.412 + /** 1.413 + * Write a localized message, using a specified resource bundle. 1.414 + * @param i18n the resource bundle used to localize the message 1.415 + * @param key the key for the message to be localized 1.416 + * @param arg an argument to be formatted into the localized message 1.417 + * @throws IOException if there is a problem closing the underlying stream 1.418 + */ 1.419 + public void write(ResourceBundle i18n, String key, Object arg) throws IOException { 1.420 + write(getString(i18n, key, arg)); 1.421 + } 1.422 + 1.423 + /** 1.424 + * Write a localized message, using a specified resource bundle. 1.425 + * @param i18n the resource bundle used to localize the message 1.426 + * @param key the key for the message to be localized 1.427 + * @param args arguments to be formatted into the localized message 1.428 + * @throws IOException if there is a problem closing the underlying stream 1.429 + */ 1.430 + public void write(ResourceBundle i18n, String key, Object[] args) throws IOException { 1.431 + write(getString(i18n, key, args)); 1.432 + } 1.433 + 1.434 + /** 1.435 + * Write a localized message, using the default resource bundle. 1.436 + * @param key the key for the message to be localized 1.437 + * @throws IOException if there is a problem closing the underlying stream 1.438 + */ 1.439 + public void writeI18N(String key) throws IOException { 1.440 + write(getString(i18n, key)); 1.441 + } 1.442 + 1.443 + /** 1.444 + * Write a localized message, using the default resource bundle. 1.445 + * @param key the key for the message to be localized 1.446 + * @param arg an argument to be formatted into the localized message 1.447 + * @throws IOException if there is a problem closing the underlying stream 1.448 + */ 1.449 + public void writeI18N(String key, Object arg) throws IOException { 1.450 + write(getString(i18n, key, arg)); 1.451 + } 1.452 + 1.453 + /** 1.454 + * Write a localized message, using the default resource bundle. 1.455 + * @param key the key for the message to be localized 1.456 + * @param args arguments to be formatted into the localized message 1.457 + * @throws IOException if there is a problem closing the underlying stream 1.458 + */ 1.459 + public void writeI18N(String key, Object[] args) throws IOException { 1.460 + write(getString(i18n, key, args)); 1.461 + } 1.462 + 1.463 + private String getString(ResourceBundle rb, String key, Object... args) { 1.464 + String s = rb.getString(key); 1.465 + return MessageFormat.format(s, args); 1.466 + } 1.467 + 1.468 + /** The HTML "a" tag. */ 1.469 + public static final String A = "a"; 1.470 + /** The HTML "align" attribute. */ 1.471 + public static final String ALIGN = "align"; 1.472 + /** The HTML "b" tag. */ 1.473 + public static final String B = "b"; 1.474 + /** The HTML "body" tag. */ 1.475 + public static final String BODY = "body"; 1.476 + /** The HTML "border" attribute. */ 1.477 + public static final String BORDER = "border"; 1.478 + /** The HTML "br" tag. */ 1.479 + public static final String BR = "br"; 1.480 + /** The HTML "class" attribute. */ 1.481 + public static final String CLASS = "class"; 1.482 + /** The HTML "classid" attribute. */ 1.483 + public static final String CLASSID = "classid"; 1.484 + /** The HTML "code" tag. */ 1.485 + public static final String CODE = "code"; 1.486 + /** The HTML "color" attribte. */ 1.487 + public static final String COLOR = "color"; 1.488 + /** The HTML "col" attribute value. */ 1.489 + public static final String COL = "col"; 1.490 + /** The HTML "dd" tag. */ 1.491 + public static final String DD = "dd"; 1.492 + /** The HTML "div" tag. */ 1.493 + public static final String DIV = "div"; 1.494 + /** The HTML "dl" tag. */ 1.495 + public static final String DL = "dl"; 1.496 + /** The HTML "dt" tag. */ 1.497 + public static final String DT = "dt"; 1.498 + /** The HTML "font" tag. */ 1.499 + public static final String FONT = "font"; 1.500 + /** The HTML "h1" tag. */ 1.501 + public static final String H1 = "h1"; 1.502 + /** The HTML "h2" tag. */ 1.503 + public static final String H2 = "h2"; 1.504 + /** The HTML "h3" tag. */ 1.505 + public static final String H3 = "h3"; 1.506 + /** The HTML "h4" tag. */ 1.507 + public static final String H4 = "h4"; 1.508 + /** The HTML "h5" tag. */ 1.509 + public static final String H5 = "h5"; 1.510 + /** The HTML "head" tag. */ 1.511 + public static final String HEAD = "head"; 1.512 + /** The HTML "href" attribute. */ 1.513 + public static final String HREF = "href"; 1.514 + /** The HTML "html" tag. */ 1.515 + public static final String HTML = "html"; 1.516 + /** The HTML "hr" tag. */ 1.517 + public static final String HR = "hr"; 1.518 + /** The HTML "i" tag. */ 1.519 + public static final String I = "i"; 1.520 + /** The HTML "id" tag. */ 1.521 + public static final String ID = "id"; 1.522 + /** The HTML "image" tag. */ 1.523 + public static final String IMAGE = "image"; 1.524 + /** The HTML "left" attribute value. */ 1.525 + public static final String LEFT = "left"; 1.526 + /** The HTML "li" tag. */ 1.527 + public static final String LI = "li"; 1.528 + /** The HTML "link" tag. */ 1.529 + public static final String LINK = "link"; 1.530 + /** The HTML "name" attribute. */ 1.531 + public static final String NAME = "name"; 1.532 + /** The HTML "object" tag. */ 1.533 + public static final String OBJECT = "object"; 1.534 + /** The HTML "p" tag. */ 1.535 + public static final String PARAM = "param"; 1.536 + /** The HTML "param" tag. */ 1.537 + public static final String P = "p"; 1.538 + /** The HTML "rel" attribute value. */ 1.539 + public static final String REL = "rel"; 1.540 + /** The HTML "right" attribute value. */ 1.541 + public static final String RIGHT = "right"; 1.542 + /** The HTML "row" attribute value. */ 1.543 + public static final String ROW = "row"; 1.544 + /** The HTML "script" tag. */ 1.545 + public static final String SCRIPT = "script"; 1.546 + /** The HTML "small" tag. */ 1.547 + public static final String SMALL = "small"; 1.548 + /** The HTML "span" tag. */ 1.549 + public static final String SPAN = "span"; 1.550 + /** The HTML "src" attribute. */ 1.551 + public static final String SRC = "src"; 1.552 + /** The HTML "scope" attribute. */ 1.553 + public static final String SCOPE = "scope"; 1.554 + /** The HTML "style" attribute. */ 1.555 + public static final String STYLE = "style"; 1.556 + /** The HTML "table" tag. */ 1.557 + public static final String TABLE = "table"; 1.558 + /** The HTML "td" tag. */ 1.559 + public static final String TD = "td"; 1.560 + /** The HTML type for JavaScript. */ 1.561 + public static final String TEXT_JAVASCRIPT = "text/javascript"; 1.562 + /** The HTML "title"attribute. */ 1.563 + public static final String TITLE = "title"; 1.564 + /** The HTML "th" tag. */ 1.565 + public static final String TH = "th"; 1.566 + /** The HTML "top" attribute value. */ 1.567 + public static final String TOP = "top"; 1.568 + /** The HTML "tr" tag. */ 1.569 + public static final String TR = "tr"; 1.570 + /** The HTML "type" attribute. */ 1.571 + public static final String TYPE = "type"; 1.572 + /** The HTML "ul" tag. */ 1.573 + public static final String UL = "ul"; 1.574 + /** The HTML "valign" attribute. */ 1.575 + public static final String VALIGN = "valign"; 1.576 + /** The HTML "value" attribute. */ 1.577 + public static final String VALUE = "value"; 1.578 + 1.579 + 1.580 + private BufferedWriter out; 1.581 + private int state; 1.582 + private ResourceBundle i18n; 1.583 + private static final int IN_TAG = 1; 1.584 + private static final int IN_BODY = 2; 1.585 +}