[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