- /*
 - * @(#)DTD.java 1.10 00/02/02
 - *
 - * Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
 - *
 - * This software is the proprietary information of Sun Microsystems, Inc.
 - * Use is subject to license terms.
 - *
 - */
 - package javax.swing.text.html.parser;
 - import java.io.PrintStream;
 - import java.io.File;
 - import java.io.FileInputStream;
 - import java.io.InputStream;
 - import java.io.IOException;
 - import java.io.FileNotFoundException;
 - import java.io.BufferedInputStream;
 - import java.io.DataInputStream;
 - import java.util.Hashtable;
 - import java.util.Vector;
 - import java.util.BitSet;
 - import java.util.StringTokenizer;
 - import java.util.Enumeration;
 - import java.util.Properties;
 - import java.net.URL;
 - /**
 - * The representation of an SGML DTD. This is produced by the DTDParser.
 - * The resulting DTD object describes a document syntax and is needed
 - * to parser HTML documents using the Parser. It contains a list of
 - * elements and their attributes as well as a list of entities defined
 - * in the DTD.
 - *
 - * @see Element
 - * @see AttributeList
 - * @see ContentModel
 - * @see DTDParser
 - * @see Parser
 - * @author Arthur van Hoff
 - * @version 1.10 02/02/00
 - */
 - public
 - class DTD implements DTDConstants {
 - public String name;
 - public Vector elements = new Vector();
 - public Hashtable elementHash = new Hashtable();
 - public Hashtable entityHash = new Hashtable();
 - public final Element pcdata = getElement("#pcdata");
 - public final Element html = getElement("html");
 - public final Element meta = getElement("meta");
 - public final Element base = getElement("base");
 - public final Element isindex = getElement("isindex");
 - public final Element head = getElement("head");
 - public final Element body = getElement("body");
 - public final Element applet = getElement("applet");
 - public final Element param = getElement("param");
 - public final Element p = getElement("p");
 - public final Element title = getElement("title");
 - final Element style = getElement("style");
 - final Element link = getElement("link");
 - public static int FILE_VERSION = 1;
 - /**
 - * Create a new DTD.
 - */
 - protected DTD(String name) {
 - this.name = name;
 - defEntity("#RE", GENERAL, '\r');
 - defEntity("#RS", GENERAL, '\n');
 - defEntity("#SPACE", GENERAL, ' ');
 - defineElement("unknown", EMPTY, false, true, null, null, null, null);
 - }
 - /**
 - * Get the name of the DTD.
 - */
 - public String getName() {
 - return name;
 - }
 - /**
 - * Get an entity by name.
 - */
 - public Entity getEntity(String name) {
 - return (Entity)entityHash.get(name);
 - }
 - /**
 - * Get a character entity.
 - */
 - public Entity getEntity(int ch) {
 - return (Entity)entityHash.get(new Integer(ch));
 - }
 - /**
 - * Return true if the element is part of the dtd
 - * else false.
 - */
 - boolean elementExists(String name) {
 - Element e = (Element)elementHash.get(name);
 - return ((e == null) ? false : true);
 - }
 - /**
 - * Get an element by name. A new element is
 - * created if the element doesn't exist.
 - */
 - public Element getElement(String name) {
 - Element e = (Element)elementHash.get(name);
 - if (e == null) {
 - e = new Element(name, elements.size());
 - elements.addElement(e);
 - elementHash.put(name, e);
 - }
 - return e;
 - }
 - /**
 - * Get an element by index.
 - */
 - public Element getElement(int index) {
 - return (Element)elements.elementAt(index);
 - }
 - /**
 - * Define an entity.
 - */
 - public Entity defineEntity(String name, int type, char data[]) {
 - Entity ent = (Entity)entityHash.get(name);
 - if (ent == null) {
 - ent = new Entity(name, type, data);
 - entityHash.put(name, ent);
 - if (((type & GENERAL) != 0) && (data.length == 1)) {
 - switch (type & ~GENERAL) {
 - case CDATA:
 - case SDATA:
 - entityHash.put(new Integer(data[0]), ent);
 - break;
 - }
 - }
 - }
 - return ent;
 - }
 - /**
 - * Define an element.
 - */
 - public Element defineElement(String name, int type,
 - boolean omitStart, boolean omitEnd, ContentModel content,
 - BitSet exclusions, BitSet inclusions, AttributeList atts) {
 - Element e = getElement(name);
 - e.type = type;
 - e.oStart = omitStart;
 - e.oEnd = omitEnd;
 - e.content = content;
 - e.exclusions = exclusions;
 - e.inclusions = inclusions;
 - e.atts = atts;
 - return e;
 - }
 - /**
 - * Define the attributes of an element.
 - */
 - public void defineAttributes(String name, AttributeList atts) {
 - Element e = getElement(name);
 - e.atts = atts;
 - }
 - /**
 - * Define a character entity.
 - */
 - public Entity defEntity(String name, int type, int ch) {
 - char data[] = {(char)ch};
 - return defineEntity(name, type, data);
 - }
 - /**
 - * Define an entity.
 - */
 - protected Entity defEntity(String name, int type, String str) {
 - int len = str.length();
 - char data[] = new char[len];
 - str.getChars(0, len, data, 0);
 - return defineEntity(name, type, data);
 - }
 - /**
 - * Define an element.
 - */
 - protected Element defElement(String name, int type,
 - boolean omitStart, boolean omitEnd, ContentModel content,
 - String[] exclusions, String[] inclusions, AttributeList atts) {
 - BitSet excl = null;
 - if (exclusions != null && exclusions.length > 0) {
 - excl = new BitSet();
 - for (int i = 0; i < exclusions.length; i++) {
 - String str = exclusions[i];
 - if (str.length() > 0) {
 - excl.set(getElement(str).getIndex());
 - }
 - }
 - }
 - BitSet incl = null;
 - if (inclusions != null && inclusions.length > 0) {
 - incl = new BitSet();
 - for (int i = 0; i < inclusions.length; i++) {
 - String str = inclusions[i];
 - if (str.length() > 0) {
 - incl.set(getElement(str).getIndex());
 - }
 - }
 - }
 - return defineElement(name, type, omitStart, omitEnd, content, excl, incl, atts);
 - }
 - /**
 - * Define an attribute list
 - */
 - protected AttributeList defAttributeList(String name, int type, int modifier, String value, String values, AttributeList atts) {
 - Vector vals = null;
 - if (values != null) {
 - vals = new Vector();
 - for (StringTokenizer s = new StringTokenizer(values, "|") ; s.hasMoreTokens() ;) {
 - String str = s.nextToken();
 - if (str.length() > 0) {
 - vals.addElement(str);
 - }
 - }
 - }
 - return new AttributeList(name, type, modifier, value, vals, atts);
 - }
 - /**
 - * Define a content model
 - */
 - protected ContentModel defContentModel(int type, Object obj, ContentModel next) {
 - return new ContentModel(type, obj, next);
 - }
 - /**
 - * Return a string representation.
 - */
 - public String toString() {
 - return name;
 - }
 - /**
 - * The hashtable of DTDs.
 - */
 - static Hashtable dtdHash = new Hashtable();
 - public static void putDTDHash(String name, DTD dtd) {
 - dtdHash.put(name, dtd);
 - }
 - /**
 - * Get a DTD.
 - */
 - public static DTD getDTD(String name) throws IOException {
 - name = name.toLowerCase();
 - DTD dtd = (DTD)dtdHash.get(name);
 - if (dtd == null)
 - dtd = new DTD(name);
 - return dtd;
 - }
 - public void read(DataInputStream in) throws IOException {
 - if (in.readInt() != FILE_VERSION) {
 - }
 - //
 - // Read the list of names
 - //
 - String[] names = new String[in.readShort()];
 - for (int i = 0; i < names.length; i++) {
 - names[i] = in.readUTF();
 - }
 - //
 - // Read the entities
 - //
 - int num = in.readShort();
 - for (int i = 0; i < num; i++) {
 - short nameId = in.readShort();
 - int type = in.readByte();
 - String name = in.readUTF();
 - defEntity(names[nameId], type | GENERAL, name);
 - }
 - // Read the elements
 - //
 - num = in.readShort();
 - for (int i = 0; i < num; i++) {
 - short nameId = in.readShort();
 - int type = in.readByte();
 - byte flags = in.readByte();
 - ContentModel m = readContentModel(in, names);
 - String[] exclusions = readNameArray(in, names);
 - String[] inclusions = readNameArray(in, names);
 - AttributeList atts = readAttributeList(in, names);
 - defElement(names[nameId], type,
 - ((flags & 0x01) != 0), ((flags & 0x02) != 0),
 - m, exclusions, inclusions, atts);
 - }
 - }
 - private ContentModel readContentModel(DataInputStream in, String[] names)
 - throws IOException {
 - byte flag = in.readByte();
 - switch(flag) {
 - case 0: // null
 - return null;
 - case 1: { // content_c
 - int type = in.readByte();
 - ContentModel m = readContentModel(in, names);
 - ContentModel next = readContentModel(in, names);
 - return defContentModel(type, m, next);
 - }
 - case 2: { // content_e
 - int type = in.readByte();
 - Element el = getElement(names[in.readShort()]);
 - ContentModel next = readContentModel(in, names);
 - return defContentModel(type, el, next);
 - }
 - default:
 - throw new IOException("bad bdtd");
 - }
 - }
 - private String[] readNameArray(DataInputStream in, String[] names)
 - throws IOException {
 - int num = in.readShort();
 - if (num == 0) {
 - return null;
 - }
 - String[] result = new String[num];
 - for (int i = 0; i < num; i++) {
 - result[i] = names[in.readShort()];
 - }
 - return result;
 - }
 - private AttributeList readAttributeList(DataInputStream in, String[] names)
 - throws IOException {
 - AttributeList result = null;
 - for (int num = in.readByte(); num > 0; --num) {
 - short nameId = in.readShort();
 - int type = in.readByte();
 - int modifier = in.readByte();
 - short valueId = in.readShort();
 - String value = (valueId == -1) ? null : names[valueId];
 - Vector values = null;
 - short numValues = in.readShort();
 - if (numValues > 0) {
 - values = new Vector(numValues);
 - for (int i = 0; i < numValues; i++) {
 - values.addElement(names[in.readShort()]);
 - }
 - }
 - result = new AttributeList(names[nameId], type, modifier, value,
 - values, result);
 - // We reverse the order of the linked list by doing this, but
 - // that order isn't important.
 - }
 - return result;
 - }
 - }