jdk/make/src/classes/build/tools/dtdbuilder/DTDBuilder.java
changeset 21805 c7d7946239de
parent 10110 75674d930b1f
child 23010 6dadb192ad81
equal deleted inserted replaced
21804:07b686da11c4 21805:c7d7946239de
       
     1 /*
       
     2  * Copyright (c) 1998, 2011, 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 
       
    26 package build.tools.dtdbuilder;
       
    27 
       
    28 import javax.swing.text.html.parser.*;
       
    29 import java.io.DataOutputStream;
       
    30 import java.io.File;
       
    31 import java.io.FileInputStream;
       
    32 import java.io.IOException;
       
    33 import java.io.FileNotFoundException;
       
    34 import java.io.BufferedInputStream;
       
    35 import java.io.OutputStream;
       
    36 import java.util.Hashtable;
       
    37 import java.util.Vector;
       
    38 import java.util.BitSet;
       
    39 import java.util.StringTokenizer;
       
    40 import java.util.Enumeration;
       
    41 import java.util.Properties;
       
    42 import java.util.zip.DeflaterOutputStream;
       
    43 import java.util.zip.Deflater;
       
    44 import java.net.URL;
       
    45 
       
    46 /**
       
    47  * The representation of an SGML DTD. This is produced by the DTDParser.
       
    48  * The resulting DTD object describes a document syntax and is needed
       
    49  * to parse HTML documents using the Parser. It contains a list of
       
    50  * elements and their attributes as well as a list of entities defined
       
    51  * in the DTD.
       
    52  *
       
    53  * @see Element
       
    54  * @see AttributeList
       
    55  * @see ContentModel
       
    56  * @see DTDParser
       
    57  * @see Parser
       
    58  * @author Arthur van Hoff
       
    59  */
       
    60 public
       
    61 class DTDBuilder extends DTD {
       
    62 
       
    63     static PublicMapping mapping = null;
       
    64 
       
    65     // Hash from name to Integer
       
    66     private Hashtable<String, Integer> namesHash = new Hashtable<>();
       
    67     // Vector of all names
       
    68     private Vector<String> namesVector = new Vector<>();
       
    69 
       
    70     /**
       
    71      * Create a new DTD.
       
    72      */
       
    73     protected DTDBuilder(String name) {
       
    74         super(name);
       
    75     }
       
    76 
       
    77 
       
    78     /**
       
    79      * Save to a stream as a Java class. Instantiating this class will
       
    80      * reproduce a (virtually) identical DTD.
       
    81      */
       
    82     void save(DataOutputStream out, String className) throws IOException {
       
    83 
       
    84         out.writeInt(DTD.FILE_VERSION);
       
    85 
       
    86         buildNamesTable();
       
    87         int numNames = namesVector.size();
       
    88         out.writeShort((short) (namesVector.size()));
       
    89         for (int i = 0; i < namesVector.size(); i++) {
       
    90             String nm = namesVector.elementAt(i);
       
    91             out.writeUTF(nm);
       
    92         }
       
    93 
       
    94         saveEntities(out);
       
    95 
       
    96         out.writeShort((short) (elements.size()));
       
    97         for (Enumeration<Element> e = elements.elements() ; e.hasMoreElements() ; ) {
       
    98             saveElement(out, e.nextElement());
       
    99         }
       
   100 
       
   101         if (namesVector.size() != numNames) {
       
   102             System.err.println("!!! ERROR!  Names were added to the list!");
       
   103             Thread.dumpStack();
       
   104             System.exit(1);
       
   105         }
       
   106     }
       
   107 
       
   108     private void buildNamesTable() {
       
   109         for (Enumeration<Entity> e = entityHash.elements() ; e.hasMoreElements() ; ) {
       
   110             Entity ent = e.nextElement();
       
   111             // Do even if not isGeneral().  That way, exclusions and inclusions
       
   112             // will definitely have their element.
       
   113             getNameId(ent.getName());
       
   114         }
       
   115         for (Enumeration<Element> e = elements.elements() ; e.hasMoreElements() ; ) {
       
   116             Element el = e.nextElement();
       
   117             getNameId(el.getName());
       
   118             for (AttributeList atts = el.getAttributes() ; atts != null ; atts = atts.getNext()) {
       
   119                 getNameId(atts.getName());
       
   120                 if (atts.getValue() != null) {
       
   121                     getNameId(atts.getValue());
       
   122                 }
       
   123                 Enumeration<?> vals = atts.getValues();
       
   124                 while (vals != null && vals.hasMoreElements()) {
       
   125                     String s = (String) vals.nextElement();
       
   126                     getNameId(s);
       
   127                 }
       
   128             }
       
   129         }
       
   130     }
       
   131 
       
   132     //
       
   133     // The the id of a name from the list of names
       
   134     //
       
   135     private short getNameId(String name)  {
       
   136         Integer o = namesHash.get(name);
       
   137         if (o != null) {
       
   138             return (short) o.intValue();
       
   139         }
       
   140         int i = namesVector.size();
       
   141         namesVector.addElement(name);
       
   142         namesHash.put(name, new Integer(i));
       
   143         return (short) i;
       
   144     }
       
   145 
       
   146 
       
   147     /**
       
   148      * Save an entity to a stream.
       
   149      */
       
   150     void saveEntities(DataOutputStream out) throws IOException {
       
   151         int num = 0;
       
   152         for (Enumeration<Entity> e = entityHash.elements() ; e.hasMoreElements() ; ) {
       
   153             Entity ent = e.nextElement();
       
   154             if (ent.isGeneral()) {
       
   155                 num++;
       
   156             }
       
   157         }
       
   158 
       
   159         out.writeShort((short) num);
       
   160         for (Enumeration<Entity> e = entityHash.elements() ; e.hasMoreElements() ; ) {
       
   161             Entity ent = e.nextElement();
       
   162             if (ent.isGeneral()) {
       
   163                 out.writeShort(getNameId(ent.getName()));
       
   164                 out.writeByte(ent.getType() & ~GENERAL);
       
   165                 out.writeUTF(ent.getString());
       
   166             }
       
   167         }
       
   168     }
       
   169 
       
   170 
       
   171     /**
       
   172      * Save an element to a stream.
       
   173      */
       
   174 
       
   175     public void saveElement(DataOutputStream out, Element elem) throws IOException {
       
   176 
       
   177         out.writeShort(getNameId(elem.getName()));
       
   178         out.writeByte(elem.getType());
       
   179 
       
   180         byte flags = 0;
       
   181         if (elem.omitStart()) {
       
   182             flags |= 0x01;
       
   183         }
       
   184         if (elem.omitEnd()) {
       
   185             flags |= 0x02;
       
   186         }
       
   187         out.writeByte(flags);
       
   188         saveContentModel(out, elem.getContent());
       
   189 
       
   190         // Exclusions
       
   191         if (elem.exclusions == null) {
       
   192             out.writeShort(0);
       
   193         } else {
       
   194             short num = 0;
       
   195             for (int i = 0 ; i < elem.exclusions.size() ; i++) {
       
   196                 if (elem.exclusions.get(i)) {
       
   197                     num++;
       
   198                 }
       
   199             }
       
   200             out.writeShort(num);
       
   201             for (int i = 0 ; i < elem.exclusions.size() ; i++) {
       
   202                 if (elem.exclusions.get(i)) {
       
   203                     out.writeShort(getNameId(getElement(i).getName()));
       
   204                 }
       
   205             }
       
   206         }
       
   207 
       
   208         // Inclusions
       
   209         if (elem.inclusions == null) {
       
   210             out.writeShort(0);
       
   211         } else {
       
   212             short num = 0;
       
   213             for (int i = 0 ; i < elem.inclusions.size() ; i++) {
       
   214                 if (elem.inclusions.get(i)) {
       
   215                     num++;
       
   216                 }
       
   217             }
       
   218             out.writeShort(num);
       
   219             for (int i = 0 ; i < elem.inclusions.size() ; i++) {
       
   220                 if (elem.inclusions.get(i)) {
       
   221                     out.writeShort(getNameId(getElement(i).getName()));
       
   222                 }
       
   223             }
       
   224         }
       
   225 
       
   226         // Attributes
       
   227         {
       
   228             short numAtts = 0;
       
   229             for (AttributeList atts = elem.getAttributes() ; atts != null ; atts = atts.getNext()) {
       
   230                 numAtts++;
       
   231             }
       
   232             out.writeByte(numAtts);
       
   233             for (AttributeList atts = elem.getAttributes() ; atts != null ; atts = atts.getNext()) {
       
   234                 out.writeShort(getNameId(atts.getName()));
       
   235                 out.writeByte(atts.getType());
       
   236                 out.writeByte(atts.getModifier());
       
   237                 if (atts.getValue() == null) {
       
   238                     out.writeShort(-1);
       
   239                 } else {
       
   240                     out.writeShort(getNameId(atts.getValue()));
       
   241                 }
       
   242                 if (atts.values == null) {
       
   243                     out.writeShort(0);
       
   244                 } else {
       
   245                     out.writeShort((short) atts.values.size());
       
   246                     for (int i = 0; i < atts.values.size(); i++) {
       
   247                         String s = (String) atts.values.elementAt(i);
       
   248                         out.writeShort(getNameId(s));
       
   249                     }
       
   250                 }
       
   251             }
       
   252         }
       
   253     }
       
   254 
       
   255 
       
   256     /**
       
   257      * Save a content model to a stream. This does a
       
   258      * recursive decent of the entire model.
       
   259      */
       
   260     public void saveContentModel(DataOutputStream out, ContentModel model) throws IOException {
       
   261         if (model == null) {
       
   262             out.writeByte(0);
       
   263         } else if (model.content instanceof ContentModel) {
       
   264             out.writeByte(1);
       
   265             out.writeByte(model.type);
       
   266             saveContentModel(out, (ContentModel)model.content);
       
   267 
       
   268             saveContentModel(out, model.next);
       
   269         } else if (model.content instanceof Element) {
       
   270             out.writeByte(2);
       
   271             out.writeByte(model.type);
       
   272             out.writeShort(getNameId(((Element) model.content).getName()));
       
   273 
       
   274             saveContentModel(out, model.next);
       
   275         }
       
   276     }
       
   277 
       
   278 
       
   279     /**
       
   280      * Generate a class representing this DTD.
       
   281      */
       
   282 
       
   283     public static void main(String argv[]) {
       
   284 
       
   285         String dtd_home = System.getProperty("dtd_home") + File.separator;
       
   286         if (dtd_home == null) {
       
   287             System.err.println("Must set property 'dtd_home'");
       
   288             return;
       
   289         }
       
   290 
       
   291         DTDBuilder dtd = null;
       
   292         try {
       
   293             dtd = new DTDBuilder(argv[0]);
       
   294             mapping = new PublicMapping(dtd_home, "public.map");
       
   295             String path = mapping.get(argv[0]);
       
   296             new DTDParser().parse(new FileInputStream(path), dtd);
       
   297 
       
   298         } catch (IOException e) {
       
   299             System.err.println("Could not open DTD file "+argv[0]);
       
   300             e.printStackTrace(System.err);
       
   301             System.exit(1);
       
   302         }
       
   303         try {
       
   304             DataOutputStream str = new DataOutputStream(System.out);
       
   305             dtd.save(str, argv[0]);
       
   306             str.close();
       
   307         } catch (IOException ex) {
       
   308             ex.printStackTrace();
       
   309             System.exit(1);
       
   310         }
       
   311     }
       
   312 
       
   313 }