gt:         if (text == null)
context: /*
   * Copyright (c) 1996, 2008, 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 com.sun.javatest.diff;
  
  import java.io.BufferedWriter;
  import java.io.File;
  import java.io.IOException;
  import java.io.Writer;
  import java.net.URL;
  
  import com.sun.javatest.util.I18NResourceBundle;
  
  /**
   * 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, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">");
      }
  
      /**
       * 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 l0calizing 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, I18NResourceBundle 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, I18NResourceBundle 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 setI18NResourceBundle(I18NResourceBundle 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.write(tag);
          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;
          }
  
  