| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package javax.swing.text.html.parser;  | 
 | 
 | 
 | 
import sun.awt.AppContext;  | 
 | 
 | 
 | 
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;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public  | 
 | 
class DTD implements DTDConstants { | 
 | 
    public String name;  | 
 | 
    public Vector<Element> elements = new Vector<Element>();  | 
 | 
    public Hashtable<String,Element> elementHash  | 
 | 
        = new Hashtable<String,Element>();  | 
 | 
    public Hashtable<Object,Entity> entityHash  | 
 | 
        = new Hashtable<Object,Entity>();  | 
 | 
    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"); | 
 | 
    final Element script = getElement("script"); | 
 | 
 | 
 | 
    public static final int FILE_VERSION = 1;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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); | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public String getName() { | 
 | 
        return name;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Entity getEntity(String name) { | 
 | 
        return entityHash.get(name);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Entity getEntity(int ch) { | 
 | 
        return entityHash.get(Integer.valueOf(ch));  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    boolean elementExists(String name) { | 
 | 
        return !"unknown".equals(name) && (elementHash.get(name) != null);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Element getElement(String name) { | 
 | 
        Element e = elementHash.get(name);  | 
 | 
        if (e == null) { | 
 | 
            e = new Element(name, elements.size());  | 
 | 
            elements.addElement(e);  | 
 | 
            elementHash.put(name, e);  | 
 | 
        }  | 
 | 
        return e;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Element getElement(int index) { | 
 | 
        return elements.elementAt(index);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Entity defineEntity(String name, int type, char data[]) { | 
 | 
        Entity ent = 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(Integer.valueOf(data[0]), ent);  | 
 | 
                    break;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return ent;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void defineAttributes(String name, AttributeList atts) { | 
 | 
        Element e = getElement(name);  | 
 | 
        e.atts = atts;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Entity defEntity(String name, int type, int ch) { | 
 | 
        char data[] = {(char)ch}; | 
 | 
        return defineEntity(name, type, data);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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 (String str : exclusions) { | 
 | 
                if (str.length() > 0) { | 
 | 
                    excl.set(getElement(str).getIndex());  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        BitSet incl = null;  | 
 | 
        if (inclusions != null && inclusions.length > 0) { | 
 | 
            incl = new BitSet();  | 
 | 
            for (String str : inclusions) { | 
 | 
                if (str.length() > 0) { | 
 | 
                    incl.set(getElement(str).getIndex());  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return defineElement(name, type, omitStart, omitEnd, content, excl, incl, atts);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected AttributeList defAttributeList(String name, int type, int modifier, String value, String values, AttributeList atts) { | 
 | 
        Vector<String> vals = null;  | 
 | 
        if (values != null) { | 
 | 
            vals = new Vector<String>();  | 
 | 
            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);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected ContentModel defContentModel(int type, Object obj, ContentModel next) { | 
 | 
        return new ContentModel(type, obj, next);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public String toString() { | 
 | 
        return name;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private static final Object DTD_HASH_KEY = new Object();  | 
 | 
 | 
 | 
    public static void putDTDHash(String name, DTD dtd) { | 
 | 
        getDtdHash().put(name, dtd);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public static DTD getDTD(String name) throws IOException { | 
 | 
        name = name.toLowerCase();  | 
 | 
        DTD dtd = getDtdHash().get(name);  | 
 | 
        if (dtd == null)  | 
 | 
          dtd = new DTD(name);  | 
 | 
 | 
 | 
        return dtd;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static Hashtable<String, DTD> getDtdHash() { | 
 | 
        AppContext appContext = AppContext.getAppContext();  | 
 | 
 | 
 | 
        Hashtable<String, DTD> result = (Hashtable<String, DTD>) appContext.get(DTD_HASH_KEY);  | 
 | 
 | 
 | 
        if (result == null) { | 
 | 
            result = new Hashtable<String, DTD>();  | 
 | 
 | 
 | 
            appContext.put(DTD_HASH_KEY, result);  | 
 | 
        }  | 
 | 
 | 
 | 
        return result;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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:               | 
 | 
                return null;  | 
 | 
            case 1: {            | 
 | 
                int type = in.readByte();  | 
 | 
                ContentModel m = readContentModel(in, names);  | 
 | 
                ContentModel next = readContentModel(in, names);  | 
 | 
                return defContentModel(type, m, next);  | 
 | 
            }  | 
 | 
            case 2: {            | 
 | 
                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<String> values = null;  | 
 | 
            short numValues = in.readShort();  | 
 | 
            if (numValues > 0) { | 
 | 
                values = new Vector<String>(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;  | 
 | 
    }  | 
 | 
 | 
 | 
}  |