⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wbxmldecoder.java

📁 WAP Stack implementation jwap.sourceforge.net
💻 JAVA
字号:
/** * JWAP - A Java Implementation of the WAP Protocols * Copyright (C) 2001-2004 Niko Bender * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package net.sourceforge.jwap.util.wbxml;import java.io.DataInputStream;import java.io.IOException;import java.io.InputStream;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import net.sourceforge.jwap.util.TransTable;import org.w3c.dom.Attr;import org.w3c.dom.Document;import org.w3c.dom.DocumentType;import org.w3c.dom.Element;import org.w3c.dom.Text;/** * to do's :- string table length is in multiple byte format, currently it is assumed to be single byte * index in string table should also be read as multiple byte format * character encoding supported is only utf-8,  * for other encodings the termination character in string table can be different... *  *   * @author <a href="mailto:suvarna@witscale.com">Suvarna Kadam</a> */public class WBXMLDecoder {	private static WBXMLDecoder instance;	private DataInputStream wbxmlStream;	private Document xmlDocument;	private String publicId = "UNKNOWN";	private byte publicIdIndex = -1;	private String encoding;	private StringBuffer stringTable;	private byte parentBitMask = (byte) 0x40;	// The bit representation 10000000	private byte attributeBitMask = (byte) 0x80;	// The bit representation 01000000	private TokenRepository tokenRepository;	public static WBXMLDecoder getInstance() {		if (instance == null)			instance = new WBXMLDecoder();		return instance;	}	private WBXMLDecoder() {		initialize();	}	private void initialize() {	}	public Document decode(InputStream wbxmlStream) {		this.wbxmlStream = new DataInputStream(wbxmlStream);		try {			xmlDocument =				DocumentBuilderFactory					.newInstance()					.newDocumentBuilder()					.newDocument();			decodeProlog();			decodeBody();		} catch (Exception exp) {			exp.printStackTrace();		}		return xmlDocument;	}	/**	 *  currently encoding cannot be specifies as DOM does not have any API to access the XML declaration. 	 * by default utf-16 is used.. If encoding is to be used ...	 * xmlDocument.getImplementation().String piData = "version=\"1.0\" encoding=\"" + encoding + "\"";	 * ProcessingInstruction xmlDeclaration = xmlDocument.createProcessingInstruction("xml", piData);	 * xmlDocument.insertBefore(xmlDeclaration, xmlDocument.getDocumentElement());	 **/	private void decodeProlog() throws IOException {		byte version = wbxmlStream.readByte();		readPublicID();		byte charset = wbxmlStream.readByte(); // to do for mutiple byte		encoding =  TransTable.getTable("charsets").code2str(charset);		byte strtblSize = wbxmlStream.readByte();		// TODO for multi-byte and negative size		stringTable = new StringBuffer(strtblSize);		for (int i = 0; i < strtblSize; i++)			stringTable.append((char) wbxmlStream.readByte());		if (publicIdIndex != -1)			readPublicIDFromStringTable();		// Now initialze the token repository as per the public identifier specified		String publicIDInHex =			PublicIdentifiers.getInstance().getPublicIdentifierValueHex(				publicId);		tokenRepository = TokenRepository.getInstance(publicIDInHex);	}	private void readPublicIDFromStringTable() {		char c = 0x0;		int endIndex =			stringTable.toString().indexOf(new String(new char[] { c }), publicIdIndex);		if (endIndex == -1)			publicId = stringTable.substring(publicIdIndex);		else			publicId = stringTable.substring(publicIdIndex, endIndex);	}	private void readPublicID() throws IOException {		byte[] multipleBytes = new byte[4];		byte nextByte = wbxmlStream.readByte();		if (nextByte == 0) {			// public id is encoded as string in form:-  0 indexInstringtable			publicIdIndex = wbxmlStream.readByte();		} else { // public id is encoded in multi-byte integer format(mb_u_int32)			int i = 0;			StringBuffer strBuf = new StringBuffer();			while ((nextByte & 0x80) == 0x80) { //msb IS 1				String str = Integer.toBinaryString(nextByte & 0x7F);				if (str.length() < 7) {					int zerosToPumpIn = 7 - str.length();					for (int j = 0; j < zerosToPumpIn; j++)						strBuf.append('0');				}				strBuf.append(str);				nextByte = wbxmlStream.readByte();			}			String str = Integer.toBinaryString(nextByte & 0x7F);			if (str.length() < 7) {				int zerosToPumpIn = 7 - str.length();				for (int j = 0; j < zerosToPumpIn; j++)					strBuf.append('0');			}			strBuf.append(str);			int publicIdValue =				Integer.valueOf(strBuf.toString(), 2).intValue();			publicId =				PublicIdentifiers.getInstance().getPublicIdentifier(					publicIdValue);		}	}	private void decodeBody() throws IOException {		writeRootElement();	}	private void writeRootElement() throws IOException {		byte maskedTokenValue = wbxmlStream.readByte();		byte actualTokenValue = getTokenValue(maskedTokenValue);		String rootElementName = tokenRepository.getTagName(actualTokenValue);		try {			DocumentBuilder builder =				DocumentBuilderFactory.newInstance().newDocumentBuilder();			String systemId =				PublicIdentifiers.getInstance().getSystemIdentifier(publicId);			DocumentType docType =				builder.getDOMImplementation().createDocumentType(					rootElementName,					publicId,					systemId);			xmlDocument =				builder.getDOMImplementation().createDocument(					"",					rootElementName,					docType);			if (hasAttributes(maskedTokenValue))				setAttributes(xmlDocument.getDocumentElement());			if (hasContent(maskedTokenValue))				writeChildElement(xmlDocument.getDocumentElement());		} catch (Exception exp) {			exp.printStackTrace();		}	}	private void writeChildElement(Element parent) throws IOException {		byte maskedTokenValue = wbxmlStream.readByte();		while (maskedTokenValue != 01) { // END (of parent element)			byte actualTokenValue = getTokenValue(maskedTokenValue);			if (isInlineStrToken(maskedTokenValue)) // element has text content				writeContentAsInlineStr(parent);			else {				if (isEntityToken(actualTokenValue)) // element has entity					writeEntityContent(parent);				else if (maskedTokenValue == GlobalTokens.OPAQUE)					// element contains opaque data					writeOpaqueContent(parent);				else if (isStringTableReferenceToken(maskedTokenValue)) {					byte indexInStringTable = wbxmlStream.readByte();					writeContentFromStrTable(parent, indexInStringTable);				} else if (actualTokenValue == GlobalTokens.SWITCH_PAGE) {					byte codepageNo = wbxmlStream.readByte();					TokenRepository.setCurrentCodepage(codepageNo);					// TODO specify namespace with xmlns attribute				} else {					String elementName =						tokenRepository.getTagName(actualTokenValue);					Element childElement =						xmlDocument.createElement(elementName);					//childElement.setPrefix(tokenRepository.getCurrentNamespace());					parent.appendChild(childElement);					if (hasAttributes(maskedTokenValue))						setAttributes(childElement);					if (hasContent(maskedTokenValue)) {						writeChildElement(childElement);						maskedTokenValue = wbxmlStream.readByte();						continue;					}				}			}			maskedTokenValue = wbxmlStream.readByte();		}	}	private void writeContentFromStrTable(		Element parent,		int indexInStringTable) {		char c = 0x0;		int endIndex =			stringTable.toString().indexOf(				new String(new char[] { c }),				indexInStringTable);		String content = stringTable.substring(indexInStringTable, endIndex);		Text txtContent = xmlDocument.createTextNode(content);		parent.appendChild(txtContent);	}	private boolean hasAttributes(byte tokenValue) {		return ((tokenValue & attributeBitMask) == attributeBitMask);	}	private boolean hasContent(byte tokenValue) {		return (tokenValue & parentBitMask) == parentBitMask;	}	private void setAttributes(Element element) throws IOException {		byte attrTokenValue = wbxmlStream.readByte();		String currentAttrName = "";		while (attrTokenValue != 01) { // END (of attribue list)			if (isInlineStrToken(attrTokenValue))				writeAttrValueAsInlineStr(element, currentAttrName);			else {				if (isEntityToken(attrTokenValue))					writeEntityAsAttribute(element, currentAttrName);				else if (isStringTableReferenceToken(attrTokenValue)) {					byte indexInStringTable = wbxmlStream.readByte();					writeAttributeFromStrTable(						element,						currentAttrName,						indexInStringTable);				} else {					if (isAttrNameToken(attrTokenValue))						currentAttrName =							writeAttribute(element, attrTokenValue);					else {						if (isAttrValueToken(attrTokenValue))							writeAttrValue(								element,								currentAttrName,								attrTokenValue);					}				}			}			attrTokenValue = wbxmlStream.readByte();		}	}	private String writeAttribute(Element element, byte attrTokenValue) {		String[] attributeNameAndPrefix =			tokenRepository.getAttributeNameAndPrefix(attrTokenValue);		String attributeValue = "";		String attributeName = attributeNameAndPrefix[0].toString();		boolean hasPrefix = attributeNameAndPrefix[1] != null;		if (hasPrefix)			attributeValue = attributeNameAndPrefix[1].trim();		Attr attrNode = xmlDocument.createAttribute(attributeName);		attrNode.setValue(attributeValue);		element.setAttributeNode(attrNode);		return attributeName;	}	private void writeAttrValue(		Element element,		String attrName,		byte attrTokenValue)		throws IOException {		String partialAttrValue = element.getAttribute(attrName);		String attrValue =			partialAttrValue				+ tokenRepository.getAttributeValue(attrTokenValue);		element.setAttribute(attrName, attrValue);	}	private void writeAttributeFromStrTable(		Element element,		String attrName,		byte indexInStringTable) {		String partialAttrValue = element.getAttribute(attrName);		char c = 0x0;		int endIndex =			stringTable.toString().indexOf(				new String(new char[] { c }),				indexInStringTable);		String attrValue =			partialAttrValue				+ stringTable.substring(indexInStringTable, endIndex);		element.setAttribute(attrName, attrValue);	}	private void writeAttrValueAsInlineStr(Element element, String attrName)		throws IOException {		byte aChar = wbxmlStream.readByte();		byte[] content = new byte[1024];		int count = 0;		while (aChar != 0x0) {			content[count++] = aChar;			aChar = wbxmlStream.readByte();		}		String previous_value = element.getAttribute(attrName);		StringBuffer attrValue =			new StringBuffer(				previous_value.equals("null") ? "" : previous_value);		attrValue =			attrValue.append(new String(content, 0, count, this.encoding));		element.setAttribute(attrName, attrValue.toString());	}	private void writeEntityAsAttribute(Element element, String attrName)		throws IOException {		String previous_value = element.getAttribute(attrName);		StringBuffer attrValue =			new StringBuffer(				previous_value.equals("null") ? "" : previous_value);		byte aChar = wbxmlStream.readByte();		while ((aChar & (byte) 0x80) == 0x80) {			// is aChar's continuation flag(MSB) is on)			aChar = (byte) (aChar & 0x7f); //extract remaining 7 bits;			String str1 = Integer.toString(aChar, 2);			attrValue.append(str1);			aChar = wbxmlStream.readByte();		}		String str2 = Integer.toString(aChar, 2);		// last byte in multiple byte format		while (str2.length() < 7)			str2 = "0" + str2;		attrValue.append(str2);		int multipleByteValue = Integer.parseInt(attrValue.toString(), 2);		element.setAttribute(attrName, "&#" + multipleByteValue + ";");	}	private void writeContentAsInlineStr(Element element) throws IOException {		byte aChar = wbxmlStream.readByte();		byte[] content = new byte[1024];		int count = 0;		while (aChar != 0x0) {			content[count++] = aChar;			aChar = wbxmlStream.readByte();		}		String attrValue = new String(content, 0, count, this.encoding);		Text txtContent = xmlDocument.createTextNode(attrValue);		element.appendChild(txtContent);	}	private boolean isEntityToken(byte tokenValue) {		return tokenValue == GlobalTokens.ENTITY;		// todo for other global tokens	}	private boolean isStringTableReferenceToken(byte tokenValue) {		return tokenValue == GlobalTokens.STR_T;	}	private void writeEntityContent(Element element) throws IOException {		StringBuffer attrValue = new StringBuffer();		byte aChar = wbxmlStream.readByte();		while ((aChar & (byte) 0x80) == 0x80) {			// is aChar's continuation flag(MSB) is on)			aChar = (byte) (aChar & 0x7f); //extract remaining 7 bits;			String str1 = Integer.toString(aChar, 2);			attrValue.append(str1);			aChar = wbxmlStream.readByte();		}		String str2 = Integer.toString(aChar, 2);		// last byte in multiple byte format		while (str2.length() < 7)			str2 = "0" + str2;		attrValue.append(str2);		int multipleByteValue = Integer.parseInt(attrValue.toString(), 2);		Text txtContent =			xmlDocument.createTextNode(Integer.toString(multipleByteValue));		element.appendChild(txtContent);	}	private void writeOpaqueContent(Element element) throws IOException {		//	StringBuffer opaqueData = new StringBuffer();		byte lengthOfOpaqueData = wbxmlStream.readByte();		// TODO for multi-byte length		byte[] opaqueDataBuf = new byte[lengthOfOpaqueData];		for (int i = 0; i < lengthOfOpaqueData; i++) {			opaqueDataBuf[i] = wbxmlStream.readByte();		}		byte b = wbxmlStream.readByte();		while (b != 1) {			b = wbxmlStream.readByte();		}		String opaqueDataStr = new String(opaqueDataBuf, this.encoding);		Text txtContent = xmlDocument.createTextNode("");		//System.out.println("Opaque____" + opaqueDataStr);		element.appendChild(txtContent);	}	private boolean isInlineStrToken(byte tokenValue) {		return tokenValue == GlobalTokens.STR_ISTR_I;	}	private boolean isAttrNameToken(byte tokenValue) {		return (tokenValue >= 0); // tokenValue is positive implies MSB is 0	}	private boolean isAttrValueToken(byte tokenValue) {		return (tokenValue < 0);		// tokenValue is negative that implies MSB is 1	}	private byte getTokenValue(byte maskedTokenValue) {		byte unmaskedTokenValue = (byte) (maskedTokenValue & ((byte) 0x3f));		// 3f =~ 0011 1111		return unmaskedTokenValue;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -