0N/A/*
2362N/A * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage build.tools.dtdbuilder;
0N/A
0N/Aimport javax.swing.text.html.parser.*;
0N/Aimport java.io.DataOutputStream;
0N/Aimport java.io.File;
0N/Aimport java.io.FileInputStream;
0N/Aimport java.io.IOException;
0N/Aimport java.io.FileNotFoundException;
0N/Aimport java.io.BufferedInputStream;
0N/Aimport java.io.OutputStream;
0N/Aimport java.util.Hashtable;
0N/Aimport java.util.Vector;
0N/Aimport java.util.BitSet;
0N/Aimport java.util.StringTokenizer;
0N/Aimport java.util.Enumeration;
0N/Aimport java.util.Properties;
0N/Aimport java.util.zip.DeflaterOutputStream;
0N/Aimport java.util.zip.Deflater;
0N/Aimport java.net.URL;
0N/A
0N/A/**
0N/A * The representation of an SGML DTD. This is produced by the DTDParser.
0N/A * The resulting DTD object describes a document syntax and is needed
0N/A * to parse HTML documents using the Parser. It contains a list of
0N/A * elements and their attributes as well as a list of entities defined
0N/A * in the DTD.
0N/A *
0N/A * @see Element
0N/A * @see AttributeList
0N/A * @see ContentModel
0N/A * @see DTDParser
0N/A * @see Parser
0N/A * @author Arthur van Hoff
0N/A */
0N/Apublic
0N/Aclass DTDBuilder extends DTD {
0N/A
0N/A static PublicMapping mapping = null;
0N/A
0N/A // Hash from name to Integer
0N/A private Hashtable namesHash = new Hashtable();
0N/A // Vector of all names
0N/A private Vector namesVector = new Vector();
0N/A
0N/A /**
0N/A * Create a new DTD.
0N/A */
0N/A protected DTDBuilder(String name) {
0N/A super(name);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Save to a stream as a Java class. Instantiating this class will
0N/A * reproduce a (virtually) identical DTD.
0N/A */
0N/A void save(DataOutputStream out, String className) throws IOException {
0N/A
0N/A out.writeInt(DTD.FILE_VERSION);
0N/A
0N/A buildNamesTable();
0N/A int numNames = namesVector.size();
0N/A out.writeShort((short) (namesVector.size()));
0N/A for (int i = 0; i < namesVector.size(); i++) {
0N/A String nm = (String) namesVector.elementAt(i);
0N/A out.writeUTF(nm);
0N/A }
0N/A
0N/A saveEntities(out);
0N/A
0N/A out.writeShort((short) (elements.size()));
0N/A for (Enumeration e = elements.elements() ; e.hasMoreElements() ; ) {
0N/A saveElement(out, (Element)e.nextElement());
0N/A }
0N/A
0N/A if (namesVector.size() != numNames) {
0N/A System.err.println("!!! ERROR! Names were added to the list!");
0N/A Thread.dumpStack();
0N/A System.exit(1);
0N/A }
0N/A }
0N/A
0N/A private void buildNamesTable() {
0N/A for (Enumeration e = entityHash.elements() ; e.hasMoreElements() ; ) {
0N/A Entity ent = (Entity) e.nextElement();
0N/A // Do even if not isGeneral(). That way, exclusions and inclusions
0N/A // will definitely have their element.
0N/A getNameId(ent.getName());
0N/A }
0N/A for (Enumeration e = elements.elements() ; e.hasMoreElements() ; ) {
0N/A Element el = (Element) e.nextElement();
0N/A getNameId(el.getName());
0N/A for (AttributeList atts = el.getAttributes() ; atts != null ; atts = atts.getNext()) {
0N/A getNameId(atts.getName());
0N/A if (atts.getValue() != null) {
0N/A getNameId(atts.getValue());
0N/A }
0N/A Enumeration vals = atts.getValues();
0N/A while (vals != null && vals.hasMoreElements()) {
0N/A String s = (String) vals.nextElement();
0N/A getNameId(s);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A //
0N/A // The the id of a name from the list of names
0N/A //
0N/A private short getNameId(String name) {
0N/A Object o = namesHash.get(name);
0N/A if (o != null) {
0N/A return (short) ((Integer) o).intValue();
0N/A }
0N/A int i = namesVector.size();
0N/A namesVector.addElement(name);
0N/A namesHash.put(name, new Integer(i));
0N/A return (short) i;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Save an entity to a stream.
0N/A */
0N/A void saveEntities(DataOutputStream out) throws IOException {
0N/A int num = 0;
0N/A for (Enumeration e = entityHash.elements() ; e.hasMoreElements() ; ) {
0N/A Entity ent = (Entity) e.nextElement();
0N/A if (ent.isGeneral()) {
0N/A num++;
0N/A }
0N/A }
0N/A
0N/A out.writeShort((short) num);
0N/A for (Enumeration e = entityHash.elements() ; e.hasMoreElements() ; ) {
0N/A Entity ent = (Entity) e.nextElement();
0N/A if (ent.isGeneral()) {
0N/A out.writeShort(getNameId(ent.getName()));
0N/A out.writeByte(ent.getType() & ~GENERAL);
0N/A out.writeUTF(ent.getString());
0N/A }
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Save an element to a stream.
0N/A */
0N/A
0N/A public void saveElement(DataOutputStream out, Element elem) throws IOException {
0N/A
0N/A out.writeShort(getNameId(elem.getName()));
0N/A out.writeByte(elem.getType());
0N/A
0N/A byte flags = 0;
0N/A if (elem.omitStart()) {
0N/A flags |= 0x01;
0N/A }
0N/A if (elem.omitEnd()) {
0N/A flags |= 0x02;
0N/A }
0N/A out.writeByte(flags);
0N/A saveContentModel(out, elem.getContent());
0N/A
0N/A // Exclusions
0N/A if (elem.exclusions == null) {
0N/A out.writeShort(0);
0N/A } else {
0N/A short num = 0;
0N/A for (int i = 0 ; i < elem.exclusions.size() ; i++) {
0N/A if (elem.exclusions.get(i)) {
0N/A num++;
0N/A }
0N/A }
0N/A out.writeShort(num);
0N/A for (int i = 0 ; i < elem.exclusions.size() ; i++) {
0N/A if (elem.exclusions.get(i)) {
0N/A out.writeShort(getNameId(getElement(i).getName()));
0N/A }
0N/A }
0N/A }
0N/A
0N/A // Inclusions
0N/A if (elem.inclusions == null) {
0N/A out.writeShort(0);
0N/A } else {
0N/A short num = 0;
0N/A for (int i = 0 ; i < elem.inclusions.size() ; i++) {
0N/A if (elem.inclusions.get(i)) {
0N/A num++;
0N/A }
0N/A }
0N/A out.writeShort(num);
0N/A for (int i = 0 ; i < elem.inclusions.size() ; i++) {
0N/A if (elem.inclusions.get(i)) {
0N/A out.writeShort(getNameId(getElement(i).getName()));
0N/A }
0N/A }
0N/A }
0N/A
0N/A // Attributes
0N/A {
0N/A short numAtts = 0;
0N/A for (AttributeList atts = elem.getAttributes() ; atts != null ; atts = atts.getNext()) {
0N/A numAtts++;
0N/A }
0N/A out.writeByte(numAtts);
0N/A for (AttributeList atts = elem.getAttributes() ; atts != null ; atts = atts.getNext()) {
0N/A out.writeShort(getNameId(atts.getName()));
0N/A out.writeByte(atts.getType());
0N/A out.writeByte(atts.getModifier());
0N/A if (atts.getValue() == null) {
0N/A out.writeShort(-1);
0N/A } else {
0N/A out.writeShort(getNameId(atts.getValue()));
0N/A }
0N/A if (atts.values == null) {
0N/A out.writeShort(0);
0N/A } else {
0N/A out.writeShort((short) atts.values.size());
0N/A for (int i = 0; i < atts.values.size(); i++) {
0N/A String s = (String) atts.values.elementAt(i);
0N/A out.writeShort(getNameId(s));
0N/A }
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Save a content model to a stream. This does a
0N/A * recursive decent of the entire model.
0N/A */
0N/A public void saveContentModel(DataOutputStream out, ContentModel model) throws IOException {
0N/A if (model == null) {
0N/A out.writeByte(0);
0N/A } else if (model.content instanceof ContentModel) {
0N/A out.writeByte(1);
0N/A out.writeByte(model.type);
0N/A saveContentModel(out, (ContentModel)model.content);
0N/A
0N/A saveContentModel(out, model.next);
0N/A } else if (model.content instanceof Element) {
0N/A out.writeByte(2);
0N/A out.writeByte(model.type);
0N/A out.writeShort(getNameId(((Element) model.content).getName()));
0N/A
0N/A saveContentModel(out, model.next);
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Generate a class representing this DTD.
0N/A */
0N/A
0N/A public static void main(String argv[]) {
0N/A
0N/A String dtd_home = System.getProperty("dtd_home") + File.separator;
0N/A if (dtd_home == null) {
0N/A System.err.println("Must set property 'dtd_home'");
0N/A return;
0N/A }
0N/A
0N/A DTDBuilder dtd = null;
0N/A try {
0N/A dtd = new DTDBuilder(argv[0]);
0N/A mapping = new PublicMapping(dtd_home, "public.map");
0N/A String path = mapping.get(argv[0]);
0N/A new DTDParser().parse(new FileInputStream(path), dtd);
0N/A
0N/A } catch (IOException e) {
0N/A System.err.println("Could not open DTD file "+argv[0]);
0N/A e.printStackTrace(System.err);
0N/A System.exit(1);
0N/A }
0N/A try {
0N/A DataOutputStream str = new DataOutputStream(System.out);
0N/A dtd.save(str, argv[0]);
0N/A str.close();
0N/A } catch (IOException ex) {
0N/A ex.printStackTrace();
0N/A System.exit(1);
0N/A }
0N/A }
0N/A
0N/A}