[sync] Java WBXML encoding...

Anthony Mills amills at gascard.net
Mon Dec 1 19:45:52 PST 2003


Looks like that didn't work either.  This one should.

Anthony
-------------- next part --------------
package com.pyramid6.wbxml.sax.helpers;

import java.io.*;
import java.util.*;
import java.util.logging.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import com.pyramid6.jsync.io.*;
import com.pyramid6.wbxml.dtd.*;
import com.pyramid6.wbxml.sax.*;
import com.pyramid6.wbxml.*;
import com.pyramid6.jsync.syncml.*;

public class WBXMLContentHandler extends DefaultHandler implements OpaqueContentHandler {        
    protected int wbxmlVersion;
    protected String uriString;
    protected String charset;
    protected Vector strings;

    protected Hashtable stringTable;
    
    protected boolean hasWrittenHeader;
  
    protected DTD dtd;
    
    protected OutputStream outputStream;
    
    protected Vector uris;
    
    protected Vector uriNums;
    
    protected int indent; 
    
    protected Logger log;
    
    protected WBXMLContentHandler wbxmlContentHandler; 
    protected int subContentHandlerStack;
    
    //contstructor
    public WBXMLContentHandler() {
        super();
        
        wbxmlVersion = 2;
        charset = "UTF-8";
        
        strings = new Vector();

        stringTable = new Hashtable();
    
        hasWrittenHeader = false;
        uris = new Vector();
        uriNums = new Vector();
    }
    
    public WBXMLContentHandler(OutputStream outputStream) {
        this();
        setOutputStream(outputStream);
    }
    
    
    
    
    //this will write the correct headers
    public void writeHeader(OutputStream out, String uri) throws IOException {
        dtd = DTDManager.getInstanceURI(uri);
        
        String dpiString = dtd.getDPI();
        
        //set Version Number from Section 5.4
        //version = u_int8
        //currently 1,2 or 3
        writeVersionNumber(out, wbxmlVersion);

        //set Document Public Idetifier from Section 5.5
        //publicid = mb_u_int32 | ( zero index )
        //zero = u_int8
        //containing the value zero (0)        
        //The actual DPI is determined after the String Table is read
        writeDocumentPublicIdentifier(outputStream, dpiString, strings);
        
        //set Charset from 5.6
        //charset = mb_u_int32
        writeCharset(out, charset);
        
        //set String Table from 5.7
        //strb1 = length *byte
        writeStringTable(out, strings, charset, stringTable);        

        hasWrittenHeader = true;
    }
    
    public void writeVersionNumber(OutputStream out, int version) throws IOException {
        if (log != null)
            log.info("WBXML Version: " + version);
        out.write(version);
    }

    public void writeDocumentPublicIdentifier(OutputStream out, String dpiString, Vector strings) throws IOException {
        int i = WBXMLUtil.getDPI(dpiString);
        
        if (i == 0) {
            strings.insertElementAt(dpiString, 0);
            out.write(0);
            out.write(0);
        } else {
            WBXMLUtil.setMBUInt32(i, out);
        }                
            
        if (log != null)
            log.info("DPI: " + i);
    }
        
    public void writeCharset(OutputStream out, String charset) throws IOException {
        int cs = WBXMLUtil.getCharset(charset);
        if (cs == 0)
            throw new IOException("Unsupported Charset: " + charset + "!");        
        else
            out.write(cs);
        
        if (log != null)
            log.info("Charset: " + charset);
    }
    
    public void writeStringTable(OutputStream out, Vector strings, String charset, Hashtable stringTable) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();        
        int count = 0;
        for (int i = 0; i < strings.size(); i++) {
            String str = (String)strings.get(i);
            byte[] bytes = str.getBytes(charset);
            baos.write(bytes);
            int nullLength = writeNull(baos, charset);
            stringTable.put(str, new Integer(count));
            count += (bytes.length+nullLength);
        }
        
        byte[] stringBytes = baos.toByteArray();
        
        baos.close();
        
        WBXMLUtil.setMBUInt32(stringBytes.length, out);
        out.write(stringBytes);
                
        String str = "";
        for (int i = 0; i < stringBytes.length; i++) {
            str += stringBytes[i] + " ";
        }
        
        if (log != null) {
            log.info("String Table: " + stringBytes.length + " " + str);
            for (int i = 0; i < strings.size(); i ++) {
                log.info("strings[" + i + "]: |" + strings.get(i) + "|");
            }
        }
    }   
    
    protected void writeString(OutputStream out, String str, String cs) throws IOException {
        byte[] bytes = str.getBytes(cs);
        out.write(bytes);        
        writeNull(out, cs);        
    }       
    
    protected int writeNull(OutputStream baos, String charset) throws IOException {
        baos.write(0);
        return 1;
    }
    
    //has no content, 64        
    public void startEndElementImp(String uri, String name, String lname, org.xml.sax.Attributes attributes) throws org.xml.sax.SAXException {
        try {
            if (!hasWrittenHeader) {
                writeHeader(outputStream, uri);
            }

            switchCodePage(outputStream, uri);

            writeTag(outputStream, name, attributes, false, charset);
        } catch (IOException ioe) {
            if (log != null)
                log.finer("uri=" + uri + " name=" + name);            
            throw new org.xml.sax.SAXException(ioe.toString());
        }
                
    }   
    
    
    //this will store the startElement params to see if we should call startElementImp or startEndElementImp
    protected String storeUri;
    protected String storeName;
    protected String storeLName;
    protected org.xml.sax.Attributes storeAttributes;
    
    public void startElement(String uri, String name, String lname, org.xml.sax.Attributes attributes) throws org.xml.sax.SAXException {
        if (wbxmlContentHandler == null) {
            writeStartElement(false);
            storeUri = uri;
            storeName = name;
            storeLName = lname;
            storeAttributes = attributes;
        } else {
            wbxmlContentHandler.startElement(uri, name, lname, attributes);
            subContentHandlerStack++;            
        }
    }
    
    public void startElementImp(String uri, String name, String lname, org.xml.sax.Attributes attributes) throws org.xml.sax.SAXException {
        try {
            if (!hasWrittenHeader) {
                writeHeader(outputStream, uri);
            }

            switchCodePage(outputStream, uri);

            writeTag(outputStream, name, attributes, true, charset);
        } catch (IOException ioe) {
            if (log != null)
                log.finer("uri=" + uri + " name=" + name);
            else
                System.err.println("uri=" + uri + " name=" + name);
            throw new org.xml.sax.SAXException(ioe.toString());
        }

        pushCurrentURI(uri);        
        indent++;
    }   
    
    
    public void writeStartElement(boolean isEnd) throws org.xml.sax.SAXException {
        if (storeUri != null) {
            if (isEnd) {
                startEndElementImp(storeUri, storeName, storeLName, storeAttributes);
            } else {
                startElementImp(storeUri, storeName, storeLName, storeAttributes);            
            }
        
            storeUri = null;
            storeName = null;
            storeLName = null;
            storeAttributes = null;
        }
    }
    
    public void opaque(byte[] bytes) throws SAXException {
        if (wbxmlContentHandler == null) {
            writeStartElement(false);

            try {
                outputStream.write(WBXMLUtil.GLOBAL_TOKEN_OPAQUE);
                WBXMLUtil.setMBUInt32(bytes.length, outputStream);
                outputStream.write(bytes);
            } catch (IOException ioe) {
                throw new org.xml.sax.SAXException(ioe.toString());
            }
        }                
    }
    
    public void characters(char[] chars, int index, int length) throws org.xml.sax.SAXException {
        if (wbxmlContentHandler == null) {
            writeStartElement(false);
            
            try {
                Integer i = (Integer)stringTable.get((new String(chars, index, length)));
                if (i != null) {
                    outputStream.write(WBXMLUtil.GLOBAL_TOKEN_STR_T);
                    WBXMLUtil.setMBUInt32(i.intValue(), outputStream);
                } else {
                    outputStream.write(WBXMLUtil.GLOBAL_TOKEN_STR_I);
                    writeString(outputStream, (new String(chars, index, length)), charset);        
                }
            } catch (IOException ioe) {
                throw new org.xml.sax.SAXException(ioe.toString());
            }
        } else {
            wbxmlContentHandler.characters(chars, index, length);    
        }        
    }    
    
    protected void writeTag(OutputStream out, String name, Attributes attrs, boolean hasContent, String cs) throws IOException {
        if( attrs != null && attrs.getLength() == 0)
            attrs = null;
        
        int t = 0;
        try {
            t = dtd.toTag(name);
        } catch (Exception e) {
//            System.err.println("dtd: " + dtd);
//            System.err.println("name: " + name);
//            System.err.println("indent: " + indent);
            e.printStackTrace();
        }
        if (t == -1) {
            Integer i = (Integer)stringTable.get(name);
            if (i == null) {
//                System.err.println("dtd=" + dtd);

                throw new IOException(name + " is not found in String Table or DTD!");
            } else {
                if (attrs == null && !hasContent) {
                    out.write(WBXMLUtil.GLOBAL_TOKEN_LITERAL);
                } else if (attrs == null && hasContent) {
                    out.write(WBXMLUtil.GLOBAL_TOKEN_LITERAL_A);                    
                } else if (attrs != null && hasContent) {
                    out.write(WBXMLUtil.GLOBAL_TOKEN_LITERAL_C);                    
                } else if (attrs != null && !hasContent) {
                    out.write(WBXMLUtil.GLOBAL_TOKEN_LITERAL_AC);                    
                }

                WBXMLUtil.setMBUInt32(i.intValue(), out);
            }
        } else {
            if (attrs == null && !hasContent) {
                out.write(t);
            } else if (attrs == null && hasContent) {
                out.write(t | 64);                    
            } else if (attrs != null && hasContent) {
                out.write(t | 128);                    
            } else if (attrs != null && !hasContent) {
                out.write(t | 192);                    
            }
        }
        
        if (attrs != null) {
            writeAttributes(out, attrs, cs);
        }
    }

    protected void writeAttributes(OutputStream out, Attributes attrs, String cs) throws IOException {
	for (int i = 0; i < attrs.getLength(); i++) 
	   writeAttribute(out, attrs.getLocalName(i), attrs.getValue(i), cs);
        
        out.write(WBXMLUtil.GLOBAL_TOKEN_END);
    }
    
    protected void writeAttribute(OutputStream out, String name, String value, String cs) throws IOException {
        int a = dtd.toAttribute(name);
        if (a == -1) {
            Integer i = (Integer)stringTable.get(name);
            if (i == null) {
                throw new IOException(name + " is not found in String Table or DTD!");
            } else {
                out.write(WBXMLUtil.GLOBAL_TOKEN_LITERAL);
                WBXMLUtil.setMBUInt32(i.intValue(), out);
            }
        } else {
            out.write(a);
        }
        
        Integer i = (Integer)stringTable.get(name);
        if (i != null) {
            out.write(WBXMLUtil.GLOBAL_TOKEN_STR_T);
            WBXMLUtil.setMBUInt32(i.intValue(), out);
        } else {
            out.write(WBXMLUtil.GLOBAL_TOKEN_STR_I);
            writeString(out, value, cs);        
        }
    }
       
    protected void switchCodePage(OutputStream out, String uri) throws IOException, org.xml.sax.SAXException {
        if (!isCurrentURI(uri)) {            
            int cp = dtd.toCodePageURI(uri);

            if (cp != -1) {
                dtd = DTDManager.getInstanceURI(uri);            
                
                out.write(0);
                out.write(cp);
            } else {
                out.write(WBXMLUtil.GLOBAL_TOKEN_OPAQUE);
                
                wbxmlContentHandler = new WBXMLContentHandler(outputStream);
                
                wbxmlContentHandler.startDocument();
                
                wbxmlContentHandler.startElement(storeUri, storeName, storeLName, storeAttributes);
                
                storeUri = null;
                storeName = null;
                storeLName = null;
                storeAttributes = null;
            }                
            
//            System.err.println("dtd: " + dtd + " cp: " + cp);
        }
    }
    
    public void endElement(String uri, String name, String lname) throws org.xml.sax.SAXException {
        if (wbxmlContentHandler == null) {
            writeStartElement(false);
            popCurrentURI();        
            indent--;
            
            //end element
            try {
                outputStream.write(WBXMLUtil.GLOBAL_TOKEN_END);
            } catch (IOException ioe) {
                throw new org.xml.sax.SAXException(ioe.toString());
            }
        } else {
            wbxmlContentHandler.endElement(uri, name, lname);
            wbxmlContentHandler.endDocument();
            
            subContentHandlerStack--;
            if (subContentHandlerStack == 0)
                wbxmlContentHandler = null;
        }
    }    
    
    public void pushCurrentURI(String uri) {
        if (uris.size() > 0 && uri.equals(uris.get(uris.size()-1))) {
            int num = ((Integer)uriNums.get(uris.size()-1)).intValue() + 1;
            uriNums.set(uris.size()-1, new Integer(num));
        } else {
            uris.add(uri);
            uriNums.add(new Integer(1));
        }
        
        // for (int i = 0; i < uriNums.size(); i ++ )
            // System.out.println("push uriNums[" + i + "]: " +  uriNums.get(i));
        // for (int i = 0; i < uris.size(); i ++ )
            // System.out.println("push uris[" + i + "]: " +  uris.get(i));
    }
    
    public void popCurrentURI() {
       int num = ((Integer)uriNums.get(uriNums.size()-1)).intValue();
       if (num <= 1) {
            uris.remove(uris.size()-1);
            uriNums.remove(uriNums.size()-1);
  
            if (uris.size() > 0) {
                String uri = (String)uris.get(uris.size()-1);
//                System.err.println("uri: " + uri);
                dtd = DTDManager.getInstanceURI(uri); 
                try {
                    outputStream.write(0);
                    outputStream.write(dtd.toCodePageURI(uri));
                } catch (IOException ioe) {
                    
                }
            }
        } else {
            num--;
            uriNums.set(uriNums.size()-1, new Integer(num));
        }
        
        // for (int i = 0; i < uriNums.size(); i ++ )
            // System.out.println("pop uriNums[" + i + "]: " +  uriNums.get(i));
        // for (int i = 0; i < uris.size(); i ++ )
            // System.out.println("pop uris[" + i + "]: " +  uris.get(i));
    }
    
    public boolean isCurrentURI(String uri) {
        if (uris.size() > 0)            
            return uri.equals(uris.get(uris.size()-1));
        else 
            return false;
    }    
        
    /** Getter for property wbxmlVersion.
     * @return Value of property wbxmlVersion.
     *
     */
    public int getWBXMLVersion() {
        return wbxmlVersion;
    }
    
    /** Setter for property wbxmlVersion.
     * @param wbxmlVersion New value of property wbxmlVersion.
     *
     */
    public void setWBXMLVersion(int wbxmlVersion) {
        this.wbxmlVersion = wbxmlVersion;
    }
    
    /** Getter for property strings.
     * @return Value of property strings.
     *
     */
    public java.util.Vector getStrings() {
        return strings;
    }    

    /** Setter for property strings.
     * @param strings New value of property strings.
     *
     */
    public void setStrings(java.util.Vector strings) {
        this.strings = strings;
    }    
    
    public void addStrings(java.util.Vector addStrings) {
        if (strings != null) {
            for (int i = 0; i < addStrings.size(); i++ ) 
                strings.add(addStrings.get(i));
        }            
    }    
        
    /** Getter for property charset.
     * @return Value of property charset.
     *
     */
    public java.lang.String getCharset() {
        return charset;
    }
    
    /** Setter for property charset.
     * @param charset New value of property charset.
     *
     */
    public void setCharset(java.lang.String charset) {
        this.charset = charset;
    }
    
    /** Getter for property dtd.
     * @return Value of property dtd.
     *
     */
    public com.pyramid6.wbxml.dtd.DTD getDTD() {
        return dtd;
    }
    
    /** Setter for property dtd.
     * @param dtd New value of property dtd.
     *
     */
    public void setDTD(com.pyramid6.wbxml.dtd.DTD dtd) {
        this.dtd = dtd;
    }
    
    /** Getter for property outputStream.
     * @return Value of property outputStream.
     *
     */
    public java.io.OutputStream getOutputStream() {
        return outputStream;
    }
    
    /** Setter for property outputStream.
     * @param outputStream New value of property outputStream.
     *
     */
    public void setOutputStream(java.io.OutputStream outputStream) {
        this.outputStream = outputStream;
    }
    
    public static void main(String[] args) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            WBXMLContentHandler syncOutput = new WBXMLContentHandler();
            
            syncOutput.log = Logger.getLogger("com.pyramid6");
            syncOutput.log.setLevel(Level.ALL);
            
            syncOutput.setOutputStream(baos);
            
            syncOutput.startDocument();            
            
            
            syncOutput.endDocument();            

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());            
            baos.close();

//            int ch = 0;
//            while((ch = bais.read()) != -1)
//                System.err.println( ch + " " + Integer.toHexString(ch));
            
            WBXMLReader reader = new WBXMLReader();
            reader.setContentHandler(new OutputStreamContentHandler(System.err));

            reader.parse(new InputSource(bais));
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (SAXException saxe) {
            saxe.printStackTrace();
        }
        
    }
    
    /** Getter for property log.
     * @return Value of property log.
     *
     */
    public java.util.logging.Logger getLog() {
        return log;
    }
    
    /** Setter for property log.
     * @param log New value of property log.
     *
     */
    public void setLog(java.util.logging.Logger log) {
        this.log = log;
    }
    
    public void ignorableWhitespace(char[] values, int param, int param2) throws org.xml.sax.SAXException {
        writeStartElement(false);
    }
    
    public void processingInstruction(String str, String str1) throws org.xml.sax.SAXException {
        writeStartElement(false);
    }
    
}


More information about the sync mailing list