1 /*
   2  * Copyright (c) 1998, 2014, 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 package javax.swing.text.html;
  26 
  27 import java.io.*;
  28 import java.util.Hashtable;
  29 import javax.swing.text.AttributeSet;
  30 import javax.swing.text.StyleConstants;
  31 import javax.swing.text.StyleContext;
  32 
  33 /**
  34  * Constants used in the <code>HTMLDocument</code>.  These
  35  * are basically tag and attribute definitions.
  36  *
  37  * @author  Timothy Prinzing
  38  * @author  Sunita Mani
  39  *
  40  */
  41 public class HTML {
  42 
  43     /**
  44      * Typesafe enumeration for an HTML tag.  Although the
  45      * set of HTML tags is a closed set, we have left the
  46      * set open so that people can add their own tag types
  47      * to their custom parser and still communicate to the
  48      * reader.
  49      */
  50     public static class Tag {
  51 
  52         /** @since 1.3 */
  53         public Tag() {}
  54 
  55         /**
  56          * Creates a new <code>Tag</code> with the specified <code>id</code>,
  57          * and with <code>causesBreak</code> and <code>isBlock</code>
  58          * set to <code>false</code>.
  59          *
  60          * @param id  the id of the new tag
  61          */
  62         protected Tag(String id) {
  63             this(id, false, false);
  64         }
  65 
  66         /**
  67          * Creates a new <code>Tag</code> with the specified <code>id</code>;
  68          * <code>causesBreak</code> and <code>isBlock</code> are defined
  69          * by the user.
  70          *
  71          * @param id the id of the new tag
  72          * @param causesBreak  <code>true</code> if this tag
  73          *    causes a break to the flow of data
  74          * @param isBlock <code>true</code> if the tag is used
  75          *    to add structure to a document
  76          */
  77         protected Tag(String id, boolean causesBreak, boolean isBlock) {
  78             name = id;
  79             this.breakTag = causesBreak;
  80             this.blockTag = isBlock;
  81         }
  82 
  83         /**
  84          * Returns <code>true</code> if this tag is a block
  85          * tag, which is a tag used to add structure to a
  86          * document.
  87          *
  88          * @return <code>true</code> if this tag is a block
  89          *   tag, otherwise returns <code>false</code>
  90          */
  91         public boolean isBlock() {
  92             return blockTag;
  93         }
  94 
  95         /**
  96          * Returns <code>true</code> if this tag causes a
  97          * line break to the flow of data, otherwise returns
  98          * <code>false</code>.
  99          *
 100          * @return <code>true</code> if this tag causes a
 101          *   line break to the flow of data, otherwise returns
 102          *   <code>false</code>
 103          */
 104         public boolean breaksFlow() {
 105             return breakTag;
 106         }
 107 
 108         /**
 109          * Returns <code>true</code> if this tag is pre-formatted,
 110          * which is true if the tag is either <code>PRE</code> or
 111          * <code>TEXTAREA</code>.
 112          *
 113          * @return <code>true</code> if this tag is pre-formatted,
 114          *   otherwise returns <code>false</code>
 115          */
 116         public boolean isPreformatted() {
 117             return (this == PRE || this == TEXTAREA);
 118         }
 119 
 120         /**
 121          * Returns the string representation of the
 122          * tag.
 123          *
 124          * @return the <code>String</code> representation of the tag
 125          */
 126         public String toString() {
 127             return name;
 128         }
 129 
 130         /**
 131          * Returns <code>true</code> if this tag is considered to be a paragraph
 132          * in the internal HTML model. <code>false</code> - otherwise.
 133          *
 134          * @return <code>true</code> if this tag is considered to be a paragraph
 135          *         in the internal HTML model. <code>false</code> - otherwise.
 136          * @see HTMLDocument.HTMLReader.ParagraphAction
 137          */
 138         boolean isParagraph() {
 139             return (
 140                 this == P
 141                    || this == IMPLIED
 142                    || this == DT
 143                    || this == H1
 144                    || this == H2
 145                    || this == H3
 146                    || this == H4
 147                    || this == H5
 148                    || this == H6
 149             );
 150         }
 151 
 152         boolean blockTag;
 153         boolean breakTag;
 154         String name;
 155         boolean unknown;
 156 
 157         // --- Tag Names -----------------------------------
 158 
 159         public static final Tag A = new Tag("a");
 160         public static final Tag ADDRESS = new Tag("address");
 161         public static final Tag APPLET = new Tag("applet");
 162         public static final Tag AREA = new Tag("area");
 163         public static final Tag B = new Tag("b");
 164         public static final Tag BASE = new Tag("base");
 165         public static final Tag BASEFONT = new Tag("basefont");
 166         public static final Tag BIG = new Tag("big");
 167         public static final Tag BLOCKQUOTE = new Tag("blockquote", true, true);
 168         public static final Tag BODY = new Tag("body", true, true);
 169         public static final Tag BR = new Tag("br", true, false);
 170         public static final Tag CAPTION = new Tag("caption");
 171         public static final Tag CENTER = new Tag("center", true, false);
 172         public static final Tag CITE = new Tag("cite");
 173         public static final Tag CODE = new Tag("code");
 174         public static final Tag DD = new Tag("dd", true, true);
 175         public static final Tag DFN = new Tag("dfn");
 176         public static final Tag DIR = new Tag("dir", true, true);
 177         public static final Tag DIV = new Tag("div", true, true);
 178         public static final Tag DL = new Tag("dl", true, true);
 179         public static final Tag DT = new Tag("dt", true, true);
 180         public static final Tag EM = new Tag("em");
 181         public static final Tag FONT = new Tag("font");
 182         public static final Tag FORM = new Tag("form", true, false);
 183         public static final Tag FRAME = new Tag("frame");
 184         public static final Tag FRAMESET = new Tag("frameset");
 185         public static final Tag H1 = new Tag("h1", true, true);
 186         public static final Tag H2 = new Tag("h2", true, true);
 187         public static final Tag H3 = new Tag("h3", true, true);
 188         public static final Tag H4 = new Tag("h4", true, true);
 189         public static final Tag H5 = new Tag("h5", true, true);
 190         public static final Tag H6 = new Tag("h6", true, true);
 191         public static final Tag HEAD = new Tag("head", true, true);
 192         public static final Tag HR = new Tag("hr", true, false);
 193         public static final Tag HTML = new Tag("html", true, false);
 194         public static final Tag I = new Tag("i");
 195         public static final Tag IMG = new Tag("img");
 196         public static final Tag INPUT = new Tag("input");
 197         public static final Tag ISINDEX = new Tag("isindex", true, false);
 198         public static final Tag KBD = new Tag("kbd");
 199         public static final Tag LI = new Tag("li", true, true);
 200         public static final Tag LINK = new Tag("link");
 201         public static final Tag MAP = new Tag("map");
 202         public static final Tag MENU = new Tag("menu", true, true);
 203         public static final Tag META = new Tag("meta");
 204         /*public*/ static final Tag NOBR = new Tag("nobr");
 205         public static final Tag NOFRAMES = new Tag("noframes", true, true);
 206         public static final Tag OBJECT = new Tag("object");
 207         public static final Tag OL = new Tag("ol", true, true);
 208         public static final Tag OPTION = new Tag("option");
 209         public static final Tag P = new Tag("p", true, true);
 210         public static final Tag PARAM = new Tag("param");
 211         public static final Tag PRE = new Tag("pre", true, true);
 212         public static final Tag SAMP = new Tag("samp");
 213         public static final Tag SCRIPT = new Tag("script");
 214         public static final Tag SELECT = new Tag("select");
 215         public static final Tag SMALL = new Tag("small");
 216         public static final Tag SPAN = new Tag("span");
 217         public static final Tag STRIKE = new Tag("strike");
 218         public static final Tag S = new Tag("s");
 219         public static final Tag STRONG = new Tag("strong");
 220         public static final Tag STYLE = new Tag("style");
 221         public static final Tag SUB = new Tag("sub");
 222         public static final Tag SUP = new Tag("sup");
 223         public static final Tag TABLE = new Tag("table", false, true);
 224         public static final Tag TD = new Tag("td", true, true);
 225         public static final Tag TEXTAREA = new Tag("textarea");
 226         public static final Tag TH = new Tag("th", true, true);
 227         public static final Tag TITLE = new Tag("title", true, true);
 228         public static final Tag TR = new Tag("tr", false, true);
 229         public static final Tag TT = new Tag("tt");
 230         public static final Tag U = new Tag("u");
 231         public static final Tag UL = new Tag("ul", true, true);
 232         public static final Tag VAR = new Tag("var");
 233 
 234         /**
 235          * All text content must be in a paragraph element.
 236          * If a paragraph didn't exist when content was
 237          * encountered, a paragraph is manufactured.
 238          * <p>
 239          * This is a tag synthesized by the HTML reader.
 240          * Since elements are identified by their tag type,
 241          * we create a some fake tag types to mark the elements
 242          * that were manufactured.
 243          */
 244         public static final Tag IMPLIED = new Tag("p-implied");
 245 
 246         /**
 247          * All text content is labeled with this tag.
 248          * <p>
 249          * This is a tag synthesized by the HTML reader.
 250          * Since elements are identified by their tag type,
 251          * we create a some fake tag types to mark the elements
 252          * that were manufactured.
 253          */
 254         public static final Tag CONTENT = new Tag("content");
 255 
 256         /**
 257          * All comments are labeled with this tag.
 258          * <p>
 259          * This is a tag synthesized by the HTML reader.
 260          * Since elements are identified by their tag type,
 261          * we create a some fake tag types to mark the elements
 262          * that were manufactured.
 263          */
 264         public static final Tag COMMENT = new Tag("comment");
 265 
 266         static final Tag allTags[]  = {
 267             A, ADDRESS, APPLET, AREA, B, BASE, BASEFONT, BIG,
 268             BLOCKQUOTE, BODY, BR, CAPTION, CENTER, CITE, CODE,
 269             DD, DFN, DIR, DIV, DL, DT, EM, FONT, FORM, FRAME,
 270             FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR, HTML,
 271             I, IMG, INPUT, ISINDEX, KBD, LI, LINK, MAP, MENU,
 272             META, NOBR, NOFRAMES, OBJECT, OL, OPTION, P, PARAM,
 273             PRE, SAMP, SCRIPT, SELECT, SMALL, SPAN, STRIKE, S,
 274             STRONG, STYLE, SUB, SUP, TABLE, TD, TEXTAREA,
 275             TH, TITLE, TR, TT, U, UL, VAR
 276         };
 277 
 278         static {
 279             // Force HTMLs static initialize to be loaded.
 280             getTag("html");
 281         }
 282     }
 283 
 284     // There is no unique instance of UnknownTag, so we allow it to be
 285     // Serializable.
 286     public static class UnknownTag extends Tag implements Serializable {
 287         private static final long serialVersionUID = -1534369342247250625L;
 288 
 289         /**
 290          * Creates a new <code>UnknownTag</code> with the specified
 291          * <code>id</code>.
 292          * @param id the id of the new tag
 293          */
 294         public UnknownTag(String id) {
 295             super(id);
 296         }
 297 
 298         /**
 299          * Returns the hash code which corresponds to the string
 300          * for this tag.
 301          */
 302         public int hashCode() {
 303             return toString().hashCode();
 304         }
 305 
 306         /**
 307          * Compares this object to the specified object.
 308          * The result is <code>true</code> if and only if the argument is not
 309          * <code>null</code> and is an <code>UnknownTag</code> object
 310          * with the same name.
 311          *
 312          * @param     obj   the object to compare this tag with
 313          * @return    <code>true</code> if the objects are equal;
 314          *            <code>false</code> otherwise
 315          */
 316         public boolean equals(Object obj) {
 317             if (obj instanceof UnknownTag) {
 318                 return toString().equals(obj.toString());
 319             }
 320             return false;
 321         }
 322 
 323         private void writeObject(java.io.ObjectOutputStream s)
 324                      throws IOException {
 325             s.defaultWriteObject();
 326             s.writeBoolean(blockTag);
 327             s.writeBoolean(breakTag);
 328             s.writeBoolean(unknown);
 329             s.writeObject(name);
 330         }
 331 
 332         private void readObject(ObjectInputStream s)
 333             throws ClassNotFoundException, IOException {
 334             s.defaultReadObject();
 335             blockTag = s.readBoolean();
 336             breakTag = s.readBoolean();
 337             unknown = s.readBoolean();
 338             name = (String)s.readObject();
 339         }
 340     }
 341 
 342     /**
 343      * Typesafe enumeration representing an HTML
 344      * attribute.
 345      */
 346     public static final class Attribute {
 347 
 348         /**
 349          * Creates a new <code>Attribute</code> with the specified
 350          * <code>id</code>.
 351          *
 352          * @param id the id of the new <code>Attribute</code>
 353          */
 354         Attribute(String id) {
 355             name = id;
 356         }
 357 
 358         /**
 359          * Returns the string representation of this attribute.
 360          * @return the string representation of this attribute
 361          */
 362         public String toString() {
 363             return name;
 364         }
 365 
 366         private String name;
 367 
 368         public static final Attribute SIZE = new Attribute("size");
 369         public static final Attribute COLOR = new Attribute("color");
 370         public static final Attribute CLEAR = new Attribute("clear");
 371         public static final Attribute BACKGROUND = new Attribute("background");
 372         public static final Attribute BGCOLOR = new Attribute("bgcolor");
 373         public static final Attribute TEXT = new Attribute("text");
 374         public static final Attribute LINK = new Attribute("link");
 375         public static final Attribute VLINK = new Attribute("vlink");
 376         public static final Attribute ALINK = new Attribute("alink");
 377         public static final Attribute WIDTH = new Attribute("width");
 378         public static final Attribute HEIGHT = new Attribute("height");
 379         public static final Attribute ALIGN = new Attribute("align");
 380         public static final Attribute NAME = new Attribute("name");
 381         public static final Attribute HREF = new Attribute("href");
 382         public static final Attribute REL = new Attribute("rel");
 383         public static final Attribute REV = new Attribute("rev");
 384         public static final Attribute TITLE = new Attribute("title");
 385         public static final Attribute TARGET = new Attribute("target");
 386         public static final Attribute SHAPE = new Attribute("shape");
 387         public static final Attribute COORDS = new Attribute("coords");
 388         public static final Attribute ISMAP = new Attribute("ismap");
 389         public static final Attribute NOHREF = new Attribute("nohref");
 390         public static final Attribute ALT = new Attribute("alt");
 391         public static final Attribute ID = new Attribute("id");
 392         public static final Attribute SRC = new Attribute("src");
 393         public static final Attribute HSPACE = new Attribute("hspace");
 394         public static final Attribute VSPACE = new Attribute("vspace");
 395         public static final Attribute USEMAP = new Attribute("usemap");
 396         public static final Attribute LOWSRC = new Attribute("lowsrc");
 397         public static final Attribute CODEBASE = new Attribute("codebase");
 398         public static final Attribute CODE = new Attribute("code");
 399         public static final Attribute ARCHIVE = new Attribute("archive");
 400         public static final Attribute VALUE = new Attribute("value");
 401         public static final Attribute VALUETYPE = new Attribute("valuetype");
 402         public static final Attribute TYPE = new Attribute("type");
 403         public static final Attribute CLASS = new Attribute("class");
 404         public static final Attribute STYLE = new Attribute("style");
 405         public static final Attribute LANG = new Attribute("lang");
 406         public static final Attribute FACE = new Attribute("face");
 407         public static final Attribute DIR = new Attribute("dir");
 408         public static final Attribute DECLARE = new Attribute("declare");
 409         public static final Attribute CLASSID = new Attribute("classid");
 410         public static final Attribute DATA = new Attribute("data");
 411         public static final Attribute CODETYPE = new Attribute("codetype");
 412         public static final Attribute STANDBY = new Attribute("standby");
 413         public static final Attribute BORDER = new Attribute("border");
 414         public static final Attribute SHAPES = new Attribute("shapes");
 415         public static final Attribute NOSHADE = new Attribute("noshade");
 416         public static final Attribute COMPACT = new Attribute("compact");
 417         public static final Attribute START = new Attribute("start");
 418         public static final Attribute ACTION = new Attribute("action");
 419         public static final Attribute METHOD = new Attribute("method");
 420         public static final Attribute ENCTYPE = new Attribute("enctype");
 421         public static final Attribute CHECKED = new Attribute("checked");
 422         public static final Attribute MAXLENGTH = new Attribute("maxlength");
 423         public static final Attribute MULTIPLE = new Attribute("multiple");
 424         public static final Attribute SELECTED = new Attribute("selected");
 425         public static final Attribute ROWS = new Attribute("rows");
 426         public static final Attribute COLS = new Attribute("cols");
 427         public static final Attribute DUMMY = new Attribute("dummy");
 428         public static final Attribute CELLSPACING = new Attribute("cellspacing");
 429         public static final Attribute CELLPADDING = new Attribute("cellpadding");
 430         public static final Attribute VALIGN = new Attribute("valign");
 431         public static final Attribute HALIGN = new Attribute("halign");
 432         public static final Attribute NOWRAP = new Attribute("nowrap");
 433         public static final Attribute ROWSPAN = new Attribute("rowspan");
 434         public static final Attribute COLSPAN = new Attribute("colspan");
 435         public static final Attribute PROMPT = new Attribute("prompt");
 436         public static final Attribute HTTPEQUIV = new Attribute("http-equiv");
 437         public static final Attribute CONTENT = new Attribute("content");
 438         public static final Attribute LANGUAGE = new Attribute("language");
 439         public static final Attribute VERSION = new Attribute("version");
 440         public static final Attribute N = new Attribute("n");
 441         public static final Attribute FRAMEBORDER = new Attribute("frameborder");
 442         public static final Attribute MARGINWIDTH = new Attribute("marginwidth");
 443         public static final Attribute MARGINHEIGHT = new Attribute("marginheight");
 444         public static final Attribute SCROLLING = new Attribute("scrolling");
 445         public static final Attribute NORESIZE = new Attribute("noresize");
 446         public static final Attribute ENDTAG = new Attribute("endtag");
 447         public static final Attribute COMMENT = new Attribute("comment");
 448         static final Attribute MEDIA = new Attribute("media");
 449 
 450         static final Attribute allAttributes[] = {
 451             FACE,
 452             COMMENT,
 453             SIZE,
 454             COLOR,
 455             CLEAR,
 456             BACKGROUND,
 457             BGCOLOR,
 458             TEXT,
 459             LINK,
 460             VLINK,
 461             ALINK,
 462             WIDTH,
 463             HEIGHT,
 464             ALIGN,
 465             NAME,
 466             HREF,
 467             REL,
 468             REV,
 469             TITLE,
 470             TARGET,
 471             SHAPE,
 472             COORDS,
 473             ISMAP,
 474             NOHREF,
 475             ALT,
 476             ID,
 477             SRC,
 478             HSPACE,
 479             VSPACE,
 480             USEMAP,
 481             LOWSRC,
 482             CODEBASE,
 483             CODE,
 484             ARCHIVE,
 485             VALUE,
 486             VALUETYPE,
 487             TYPE,
 488             CLASS,
 489             STYLE,
 490             LANG,
 491             DIR,
 492             DECLARE,
 493             CLASSID,
 494             DATA,
 495             CODETYPE,
 496             STANDBY,
 497             BORDER,
 498             SHAPES,
 499             NOSHADE,
 500             COMPACT,
 501             START,
 502             ACTION,
 503             METHOD,
 504             ENCTYPE,
 505             CHECKED,
 506             MAXLENGTH,
 507             MULTIPLE,
 508             SELECTED,
 509             ROWS,
 510             COLS,
 511             DUMMY,
 512             CELLSPACING,
 513             CELLPADDING,
 514             VALIGN,
 515             HALIGN,
 516             NOWRAP,
 517             ROWSPAN,
 518             COLSPAN,
 519             PROMPT,
 520             HTTPEQUIV,
 521             CONTENT,
 522             LANGUAGE,
 523             VERSION,
 524             N,
 525             FRAMEBORDER,
 526             MARGINWIDTH,
 527             MARGINHEIGHT,
 528             SCROLLING,
 529             NORESIZE,
 530             MEDIA,
 531             ENDTAG
 532         };
 533     }
 534 
 535     // The secret to 73, is that, given that the Hashtable contents
 536     // never change once the static initialization happens, the initial size
 537     // that the hashtable grew to was determined, and then that very size
 538     // is used.
 539     //
 540     private static final Hashtable<String, Tag> tagHashtable = new Hashtable<String, Tag>(73);
 541 
 542     /** Maps from StyleConstant key to HTML.Tag. */
 543     private static final Hashtable<Object, Tag> scMapping = new Hashtable<Object, Tag>(8);
 544 
 545     static {
 546 
 547         for (int i = 0; i < Tag.allTags.length; i++ ) {
 548             tagHashtable.put(Tag.allTags[i].toString(), Tag.allTags[i]);
 549             StyleContext.registerStaticAttributeKey(Tag.allTags[i]);
 550         }
 551         StyleContext.registerStaticAttributeKey(Tag.IMPLIED);
 552         StyleContext.registerStaticAttributeKey(Tag.CONTENT);
 553         StyleContext.registerStaticAttributeKey(Tag.COMMENT);
 554         for (int i = 0; i < Attribute.allAttributes.length; i++) {
 555             StyleContext.registerStaticAttributeKey(Attribute.
 556                                                     allAttributes[i]);
 557         }
 558         StyleContext.registerStaticAttributeKey(HTML.NULL_ATTRIBUTE_VALUE);
 559         scMapping.put(StyleConstants.Bold, Tag.B);
 560         scMapping.put(StyleConstants.Italic, Tag.I);
 561         scMapping.put(StyleConstants.Underline, Tag.U);
 562         scMapping.put(StyleConstants.StrikeThrough, Tag.STRIKE);
 563         scMapping.put(StyleConstants.Superscript, Tag.SUP);
 564         scMapping.put(StyleConstants.Subscript, Tag.SUB);
 565         scMapping.put(StyleConstants.FontFamily, Tag.FONT);
 566         scMapping.put(StyleConstants.FontSize, Tag.FONT);
 567     }
 568 
 569     /**
 570      * Returns the set of actual HTML tags that
 571      * are recognized by the default HTML reader.
 572      * This set does not include tags that are
 573      * manufactured by the reader.
 574      */
 575     public static Tag[] getAllTags() {
 576         Tag[] tags = new Tag[Tag.allTags.length];
 577         System.arraycopy(Tag.allTags, 0, tags, 0, Tag.allTags.length);
 578         return tags;
 579     }
 580 
 581     /**
 582      * Fetches a tag constant for a well-known tag name (i.e. one of
 583      * the tags in the set {A, ADDRESS, APPLET, AREA, B,
 584      * BASE, BASEFONT, BIG,
 585      * BLOCKQUOTE, BODY, BR, CAPTION, CENTER, CITE, CODE,
 586      * DD, DFN, DIR, DIV, DL, DT, EM, FONT, FORM, FRAME,
 587      * FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR, HTML,
 588      * I, IMG, INPUT, ISINDEX, KBD, LI, LINK, MAP, MENU,
 589      * META, NOBR, NOFRAMES, OBJECT, OL, OPTION, P, PARAM,
 590      * PRE, SAMP, SCRIPT, SELECT, SMALL, SPAN, STRIKE, S,
 591      * STRONG, STYLE, SUB, SUP, TABLE, TD, TEXTAREA,
 592      * TH, TITLE, TR, TT, U, UL, VAR}.  If the given
 593      * name does not represent one of the well-known tags, then
 594      * <code>null</code> will be returned.
 595      *
 596      * @param tagName the <code>String</code> name requested
 597      * @return a tag constant corresponding to the <code>tagName</code>,
 598      *    or <code>null</code> if not found
 599      */
 600     public static Tag getTag(String tagName) {
 601 
 602         Tag t =  tagHashtable.get(tagName);
 603         return (t == null ? null : t);
 604     }
 605 
 606     /**
 607      * Returns the HTML <code>Tag</code> associated with the
 608      * <code>StyleConstants</code> key <code>sc</code>.
 609      * If no matching <code>Tag</code> is found, returns
 610      * <code>null</code>.
 611      *
 612      * @param sc the <code>StyleConstants</code> key
 613      * @return tag which corresponds to <code>sc</code>, or
 614      *   <code>null</code> if not found
 615      */
 616     static Tag getTagForStyleConstantsKey(StyleConstants sc) {
 617         return scMapping.get(sc);
 618     }
 619 
 620     /**
 621      * Fetches an integer attribute value.  Attribute values
 622      * are stored as a string, and this is a convenience method
 623      * to convert to an actual integer.
 624      *
 625      * @param attr the set of attributes to use to try to fetch a value
 626      * @param key the key to use to fetch the value
 627      * @param def the default value to use if the attribute isn't
 628      *  defined or there is an error converting to an integer
 629      */
 630     public static int getIntegerAttributeValue(AttributeSet attr,
 631                                                Attribute key, int def) {
 632         int value = def;
 633         String istr = (String) attr.getAttribute(key);
 634         if (istr != null) {
 635             try {
 636                 value = Integer.valueOf(istr).intValue();
 637             } catch (NumberFormatException e) {
 638                 value = def;
 639             }
 640         }
 641         return value;
 642     }
 643 
 644     //  This is used in cases where the value for the attribute has not
 645     //  been specified.
 646     //
 647     public static final String NULL_ATTRIBUTE_VALUE = "#DEFAULT";
 648 
 649     // size determined similar to size of tagHashtable
 650     private static final Hashtable<String, Attribute> attHashtable = new Hashtable<String, Attribute>(77);
 651 
 652     static {
 653 
 654         for (int i = 0; i < Attribute.allAttributes.length; i++ ) {
 655             attHashtable.put(Attribute.allAttributes[i].toString(), Attribute.allAttributes[i]);
 656         }
 657     }
 658 
 659     /**
 660      * Returns the set of HTML attributes recognized.
 661      * @return the set of HTML attributes recognized
 662      */
 663     public static Attribute[] getAllAttributeKeys() {
 664         Attribute[] attributes = new Attribute[Attribute.allAttributes.length];
 665         System.arraycopy(Attribute.allAttributes, 0,
 666                          attributes, 0, Attribute.allAttributes.length);
 667         return attributes;
 668     }
 669 
 670     /**
 671      * Fetches an attribute constant for a well-known attribute name
 672      * (i.e. one of the attributes in the set {FACE, COMMENT, SIZE,
 673      * COLOR, CLEAR, BACKGROUND, BGCOLOR, TEXT, LINK, VLINK, ALINK,
 674      * WIDTH, HEIGHT, ALIGN, NAME, HREF, REL, REV, TITLE, TARGET,
 675      * SHAPE, COORDS, ISMAP, NOHREF, ALT, ID, SRC, HSPACE, VSPACE,
 676      * USEMAP, LOWSRC, CODEBASE, CODE, ARCHIVE, VALUE, VALUETYPE,
 677      * TYPE, CLASS, STYLE, LANG, DIR, DECLARE, CLASSID, DATA, CODETYPE,
 678      * STANDBY, BORDER, SHAPES, NOSHADE, COMPACT, START, ACTION, METHOD,
 679      * ENCTYPE, CHECKED, MAXLENGTH, MULTIPLE, SELECTED, ROWS, COLS,
 680      * DUMMY, CELLSPACING, CELLPADDING, VALIGN, HALIGN, NOWRAP, ROWSPAN,
 681      * COLSPAN, PROMPT, HTTPEQUIV, CONTENT, LANGUAGE, VERSION, N,
 682      * FRAMEBORDER, MARGINWIDTH, MARGINHEIGHT, SCROLLING, NORESIZE,
 683      * MEDIA, ENDTAG}).
 684      * If the given name does not represent one of the well-known attributes,
 685      * then <code>null</code> will be returned.
 686      *
 687      * @param attName the <code>String</code> requested
 688      * @return the <code>Attribute</code> corresponding to <code>attName</code>
 689      */
 690     public static Attribute getAttributeKey(String attName) {
 691         Attribute a = attHashtable.get(attName);
 692         if (a == null) {
 693           return null;
 694         }
 695         return a;
 696     }
 697 
 698 }