
com.caucho.burlap.io.BurlapInput Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hessian Show documentation
Show all versions of hessian Show documentation
Hessian is a compact binary protocol for connecting web services.
The newest version!
/*
* Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved.
*
* The Apache Software License, Version 1.1
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Caucho Technology (http://www.caucho.com/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "Hessian", "Resin", and "Caucho" must not be used to
* endorse or promote products derived from this software without prior
* written permission. For written permission, please contact
* [email protected].
*
* 5. Products derived from this software may not be called "Resin"
* nor may "Resin" appear in their names without prior written
* permission of Caucho Technology.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Scott Ferguson
*/
package com.caucho.burlap.io;
import com.caucho.hessian.io.Deserializer;
import com.caucho.hessian.io.HessianRemoteResolver;
import com.caucho.hessian.io.SerializerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.TimeZone;
/**
* Input stream for Burlap requests.
*
* BurlapInput is unbuffered, so any client needs to provide
* its own buffering.
*
*
* InputStream is = ...; // from http connection
* BurlapInput in = new BurlapInput(is);
* String value;
*
* in.startReply(); // read reply header
* value = in.readString(); // read string value
* in.completeReply(); // read reply footer
*
*/
public class BurlapInput extends AbstractBurlapInput {
private static int []base64Decode;
public final static int TAG_EOF = -1;
public final static int TAG_NULL = 0;
public final static int TAG_BOOLEAN = 1;
public final static int TAG_INT = 2;
public final static int TAG_LONG = 3;
public final static int TAG_DOUBLE = 4;
public final static int TAG_DATE = 5;
public final static int TAG_STRING = 6;
public final static int TAG_XML = 7;
public final static int TAG_BASE64 = 8;
public final static int TAG_MAP = 9;
public final static int TAG_LIST = 10;
public final static int TAG_TYPE = 11;
public final static int TAG_LENGTH = 12;
public final static int TAG_REF = 13;
public final static int TAG_REMOTE = 14;
public final static int TAG_CALL = 15;
public final static int TAG_REPLY = 16;
public final static int TAG_FAULT = 17;
public final static int TAG_METHOD = 18;
public final static int TAG_HEADER = 19;
public final static int TAG_NULL_END = TAG_NULL + 100;
public final static int TAG_BOOLEAN_END = TAG_BOOLEAN + 100;
public final static int TAG_INT_END = TAG_INT + 100;
public final static int TAG_LONG_END = TAG_LONG + 100;
public final static int TAG_DOUBLE_END = TAG_DOUBLE + 100;
public final static int TAG_DATE_END = TAG_DATE + 100;
public final static int TAG_STRING_END = TAG_STRING + 100;
public final static int TAG_XML_END = TAG_XML + 100;
public final static int TAG_BASE64_END = TAG_BASE64 + 100;
public final static int TAG_MAP_END = TAG_MAP + 100;
public final static int TAG_LIST_END = TAG_LIST + 100;
public final static int TAG_TYPE_END = TAG_TYPE + 100;
public final static int TAG_LENGTH_END = TAG_LENGTH + 100;
public final static int TAG_REF_END = TAG_REF + 100;
public final static int TAG_REMOTE_END = TAG_REMOTE + 100;
public final static int TAG_CALL_END = TAG_CALL + 100;
public final static int TAG_REPLY_END = TAG_REPLY + 100;
public final static int TAG_FAULT_END = TAG_FAULT + 100;
public final static int TAG_METHOD_END = TAG_METHOD + 100;
public final static int TAG_HEADER_END = TAG_HEADER + 100;
private static HashMap _tagMap;
private static Field _detailMessageField;
protected SerializerFactory _serializerFactory;
protected ArrayList _refs;
// the underlying input stream
private InputStream _is;
// a peek character
protected int _peek = -1;
// the method for a call
private String _method;
private int _peekTag;
private Throwable _replyFault;
protected StringBuffer _sbuf = new StringBuffer();
protected StringBuffer _entityBuffer = new StringBuffer();
protected Calendar _utcCalendar;
protected Calendar _localCalendar;
/**
* Creates an uninitialized Burlap input stream.
*/
public BurlapInput()
{
}
/**
* Creates a new Burlap input stream, initialized with an
* underlying input stream.
*
* @param is the underlying input stream.
*/
public BurlapInput(InputStream is)
{
init(is);
}
/**
* Sets the serializer factory.
*/
public void setSerializerFactory(SerializerFactory factory)
{
_serializerFactory = factory;
}
/**
* Gets the serializer factory.
*/
public SerializerFactory getSerializerFactory()
{
return _serializerFactory;
}
/**
* Initialize the burlap stream with the underlying input stream.
*/
public void init(InputStream is)
{
_is = is;
_method = null;
_peek = -1;
_peekTag = -1;
_refs = null;
_replyFault = null;
if (_serializerFactory == null)
_serializerFactory = new SerializerFactory();
}
/**
* Returns the calls method
*/
public String getMethod()
{
return _method;
}
/**
* Returns any reply fault.
*/
public Throwable getReplyFault()
{
return _replyFault;
}
/**
* Starts reading the call
*
*
* <burlap:call>
* <method>method</method>
*
*/
public void startCall()
throws IOException
{
readCall();
while ((readHeader() != null))
readObject();
readMethod();
}
/**
* Starts reading the call
*
* A successful completion will have a single value:
*
*
* <burlap:call>
*
*/
public int readCall()
throws IOException
{
expectTag(TAG_CALL);
int major = 1;
int minor = 0;
return (major << 16) + minor;
}
/**
* Reads the method
*
*
* <method>method</method>
*
*/
public String readMethod()
throws IOException
{
expectTag(TAG_METHOD);
_method = parseString();
expectTag(TAG_METHOD_END);
return _method;
}
/**
* Completes reading the call
*
* A successful completion will have a single value:
*
*
* </burlap:call>
*
*/
public void completeCall()
throws IOException
{
expectTag(TAG_CALL_END);
}
/**
* Reads a reply as an object.
* If the reply has a fault, throws the exception.
*/
public Object readReply(Class expectedClass)
throws Throwable
{
expectTag(TAG_REPLY);
int tag = parseTag();
if (tag == TAG_FAULT)
throw prepareFault();
else {
_peekTag = tag;
Object value = readObject(expectedClass);
expectTag(TAG_REPLY_END);
return value;
}
}
/**
* Starts reading the reply
*
* A successful completion will have a single value:
*
*
* <burlap:reply>
* <value>
*
*/
public void startReply()
throws Throwable
{
expectTag(TAG_REPLY);
int tag = parseTag();
if (tag == TAG_FAULT)
throw prepareFault();
else
_peekTag = tag;
}
/**
* Prepares the fault.
*/
private Throwable prepareFault()
throws IOException
{
HashMap fault = readFault();
Object detail = fault.get("detail");
String message = (String) fault.get("message");
if (detail instanceof Throwable) {
_replyFault = (Throwable) detail;
Field detailMessageField = getDetailMessageField();
if (message != null && detailMessageField != null) {
try {
detailMessageField.set(_replyFault, message);
} catch (Throwable e) {
}
}
return _replyFault;
}
else {
String code = (String) fault.get("code");
_replyFault = new BurlapServiceException(message, code, detail);
return _replyFault;
}
}
/**
* Completes reading the call
*
* A successful completion will have a single value:
*
*
* </burlap:reply>
*
*/
public void completeReply()
throws IOException
{
expectTag(TAG_REPLY_END);
}
/**
* Reads a header, returning null if there are no headers.
*
*
* <header>value</header>
*
*/
public String readHeader()
throws IOException
{
int tag = parseTag();
if (tag == TAG_HEADER) {
_sbuf.setLength(0);
String value = parseString(_sbuf).toString();
expectTag(TAG_HEADER_END);
return value;
}
_peekTag = tag;
return null;
}
/**
* Reads a null
*
*
* <null></null>
*
*/
public void readNull()
throws IOException
{
int tag = parseTag();
switch (tag) {
case TAG_NULL:
expectTag(TAG_NULL_END);
return;
default:
throw expectedTag("null", tag);
}
}
/**
* Reads a boolean
*
*
* <boolean>0</boolean>
* <boolean>1</boolean>
*
*/
public boolean readBoolean()
throws IOException
{
int tag = parseTag();
boolean value;
switch (tag) {
case TAG_NULL:
value = false;
expectTag(TAG_NULL_END);
return value;
case TAG_BOOLEAN:
value = parseInt() != 0;
expectTag(TAG_BOOLEAN_END);
return value;
case TAG_INT:
value = parseInt() != 0;
expectTag(TAG_INT_END);
return value;
case TAG_LONG:
value = parseLong() != 0;
expectTag(TAG_LONG_END);
return value;
case TAG_DOUBLE:
value = parseDouble() != 0;
expectTag(TAG_DOUBLE_END);
return value;
default:
throw expectedTag("boolean", tag);
}
}
/**
* Reads a byte
*
*
* <int>value</int>
*
*/
public byte readByte()
throws IOException
{
return (byte) readInt();
}
/**
* Reads a short
*
*
* <int>value</int>
*
*/
public short readShort()
throws IOException
{
return (short) readInt();
}
/**
* Reads an integer
*
*
* <int>value</int>
*
*/
public int readInt()
throws IOException
{
int tag = parseTag();
int value;
switch (tag) {
case TAG_NULL:
value = 0;
expectTag(TAG_NULL_END);
return value;
case TAG_BOOLEAN:
value = parseInt();
expectTag(TAG_BOOLEAN_END);
return value;
case TAG_INT:
value = parseInt();
expectTag(TAG_INT_END);
return value;
case TAG_LONG:
value = (int) parseLong();
expectTag(TAG_LONG_END);
return value;
case TAG_DOUBLE:
value = (int) parseDouble();
expectTag(TAG_DOUBLE_END);
return value;
default:
throw expectedTag("int", tag);
}
}
/**
* Reads a long
*
*
* <long>value</long>
*
*/
public long readLong()
throws IOException
{
int tag = parseTag();
long value;
switch (tag) {
case TAG_NULL:
value = 0;
expectTag(TAG_NULL_END);
return value;
case TAG_BOOLEAN:
value = parseInt();
expectTag(TAG_BOOLEAN_END);
return value;
case TAG_INT:
value = parseInt();
expectTag(TAG_INT_END);
return value;
case TAG_LONG:
value = parseLong();
expectTag(TAG_LONG_END);
return value;
case TAG_DOUBLE:
value = (long) parseDouble();
expectTag(TAG_DOUBLE_END);
return value;
default:
throw expectedTag("long", tag);
}
}
/**
* Reads a float
*
*
* <double>value</double>
*
*/
public float readFloat()
throws IOException
{
return (float) readDouble();
}
/**
* Reads a double
*
*
* <double>value</double>
*
*/
public double readDouble()
throws IOException
{
int tag = parseTag();
double value;
switch (tag) {
case TAG_NULL:
value = 0;
expectTag(TAG_NULL_END);
return value;
case TAG_BOOLEAN:
value = parseInt();
expectTag(TAG_BOOLEAN_END);
return value;
case TAG_INT:
value = parseInt();
expectTag(TAG_INT_END);
return value;
case TAG_LONG:
value = parseLong();
expectTag(TAG_LONG_END);
return value;
case TAG_DOUBLE:
value = parseDouble();
expectTag(TAG_DOUBLE_END);
return value;
default:
throw expectedTag("double", tag);
}
}
/**
* Reads a date.
*
*
* <date>ISO-8609 date</date>
*
*/
public long readUTCDate()
throws IOException
{
int tag = parseTag();
if (tag != TAG_DATE)
throw error("expected date");
if (_utcCalendar == null)
_utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
long value = parseDate(_utcCalendar);
expectTag(TAG_DATE_END);
return value;
}
/**
* Reads a date.
*
*
* <date>ISO-8609 date</date>
*
*/
public long readLocalDate()
throws IOException
{
int tag = parseTag();
if (tag != TAG_DATE)
throw error("expected date");
if (_localCalendar == null)
_localCalendar = Calendar.getInstance();
long value = parseDate(_localCalendar);
expectTag(TAG_DATE_END);
return value;
}
/**
* Reads a string
*
*
* <string>value</string>
*
*/
public String readString()
throws IOException
{
int tag = parseTag();
String value;
switch (tag) {
case TAG_NULL:
expectTag(TAG_NULL_END);
return null;
case TAG_STRING:
_sbuf.setLength(0);
value = parseString(_sbuf).toString();
expectTag(TAG_STRING_END);
return value;
case TAG_XML:
_sbuf.setLength(0);
value = parseString(_sbuf).toString();
expectTag(TAG_XML_END);
return value;
default:
throw expectedTag("string", tag);
}
}
/**
* Reads an XML node.
*
*
* &xml;xml string</xml>
*
*/
public org.w3c.dom.Node readNode()
throws IOException
{
int tag = read();
switch (tag) {
case 'N':
return null;
case 'S':
case 's':
case 'X':
case 'x':
throw error("can't cope");
default:
throw expectedTag("string", tag);
}
}
/**
* Reads a byte array
*
*
* <base64>...</base64>
*
*/
public byte []readBytes()
throws IOException
{
int tag = parseTag();
switch (tag) {
case TAG_NULL:
expectTag(TAG_NULL_END);
return null;
case TAG_BASE64:
byte []data = parseBytes();
expectTag(TAG_BASE64_END);
return data;
default:
throw expectedTag("bytes", tag);
}
}
/**
* Reads a length
*
*
* <length>value</length>
*
*/
public int readLength()
throws IOException
{
int tag = parseTag();
if (tag != TAG_LENGTH) {
_peekTag = tag;
return -1;
}
int value = parseInt();
expectTag(TAG_LENGTH_END);
return value;
}
/**
* Reads a fault.
*/
private HashMap readFault()
throws IOException
{
HashMap map = new HashMap();
int code = parseTag();
for (; code >= 0 && code != TAG_FAULT_END; code = parseTag()) {
_peekTag = code;
Object key = readObject();
Object value = readObject();
if (key != null && value != null)
map.put(key, value);
}
if (code != TAG_FAULT_END)
throw expectedTag("fault", code);
return map;
}
/**
* Reads an object from the input stream with an expected type.
*/
public Object readObject(Class cl)
throws IOException
{
if (cl == null || cl.equals(Object.class))
return readObject();
int tag = parseTag();
switch (tag) {
case TAG_NULL:
expectTag(TAG_NULL_END);
return null;
case TAG_MAP:
{
String type = readType();
Deserializer reader;
reader = _serializerFactory.getObjectDeserializer(type, cl);
return reader.readMap(this);
}
case TAG_LIST:
{
String type = readType();
int length = readLength();
Deserializer reader;
reader = _serializerFactory.getObjectDeserializer(type, cl);
return reader.readList(this, length);
}
case TAG_REF:
{
int ref = parseInt();
expectTag(TAG_REF_END);
return _refs.get(ref);
}
case TAG_REMOTE:
{
String type = readType();
String url = readString();
expectTag(TAG_REMOTE_END);
Object remote = resolveRemote(type, url);
return remote;
}
}
_peekTag = tag;
Object value = _serializerFactory.getDeserializer(cl).readObject(this);
return value;
}
/**
* Reads an arbitrary object from the input stream when the type
* is unknown.
*/
public Object readObject()
throws IOException
{
int tag = parseTag();
switch (tag) {
case TAG_NULL:
expectTag(TAG_NULL_END);
return null;
case TAG_BOOLEAN:
{
int value = parseInt();
expectTag(TAG_BOOLEAN_END);
return new Boolean(value != 0);
}
case TAG_INT:
{
int value = parseInt();
expectTag(TAG_INT_END);
return new Integer(value);
}
case TAG_LONG:
{
long value = parseLong();
expectTag(TAG_LONG_END);
return new Long(value);
}
case TAG_DOUBLE:
{
double value = parseDouble();
expectTag(TAG_DOUBLE_END);
return new Double(value);
}
case TAG_DATE:
{
long value = parseDate();
expectTag(TAG_DATE_END);
return new Date(value);
}
case TAG_XML:
{
return parseXML();
}
case TAG_STRING:
{
_sbuf.setLength(0);
String value = parseString(_sbuf).toString();
expectTag(TAG_STRING_END);
return value;
}
case TAG_BASE64:
{
byte []data = parseBytes();
expectTag(TAG_BASE64_END);
return data;
}
case TAG_LIST:
{
String type = readType();
int length = readLength();
return _serializerFactory.readList(this, length, type);
}
case TAG_MAP:
{
String type = readType();
Deserializer deserializer;
deserializer = _serializerFactory.getObjectDeserializer(type);
return deserializer.readMap(this);
}
case TAG_REF:
{
int ref = parseInt();
expectTag(TAG_REF_END);
return _refs.get(ref);
}
case TAG_REMOTE:
{
String type = readType();
String url = readString();
expectTag(TAG_REMOTE_END);
return resolveRemote(type, url);
}
default:
throw error("unknown code:" + tagName(tag));
}
}
/**
* Reads a remote object.
*/
public Object readRemote()
throws IOException
{
String type = readType();
String url = readString();
return resolveRemote(type, url);
}
/**
* Reads a reference.
*/
public Object readRef()
throws IOException
{
return _refs.get(parseInt());
}
/**
* Reads the start of a list.
*/
public int readListStart()
throws IOException
{
return parseTag();
}
/**
* Reads the start of a map.
*/
public int readMapStart()
throws IOException
{
return parseTag();
}
/**
* Returns true if this is the end of a list or a map.
*/
public boolean isEnd()
throws IOException
{
int code = parseTag();
_peekTag = code;
return (code < 0 || code >= 100);
}
/**
* Reads the end byte.
*/
public void readEnd()
throws IOException
{
int code = parseTag();
if (code < 100)
throw error("unknown code:" + (char) code);
}
/**
* Reads the end of the map
*/
public void readMapEnd()
throws IOException
{
expectTag(TAG_MAP_END);
}
/**
* Reads the end of the map
*/
public void readListEnd()
throws IOException
{
expectTag(TAG_LIST_END);
}
/**
* Adds a list/map reference.
*/
public int addRef(Object ref)
{
if (_refs == null)
_refs = new ArrayList();
_refs.add(ref);
return _refs.size() - 1;
}
/**
* Adds a list/map reference.
*/
public void setRef(int i, Object ref)
{
_refs.set(i, ref);
}
/**
* Resolves a remote object.
*/
public Object resolveRemote(String type, String url)
throws IOException
{
HessianRemoteResolver resolver = getRemoteResolver();
if (resolver != null)
return resolver.lookup(type, url);
else
return new BurlapRemote(type, url);
}
/**
* Parses a type from the stream.
*
*
* <type>type</type>
*
*/
public String readType()
throws IOException
{
int code = parseTag();
if (code != TAG_TYPE) {
_peekTag = code;
return "";
}
_sbuf.setLength(0);
int ch;
while ((ch = readChar()) >= 0)
_sbuf.append((char) ch);
String type = _sbuf.toString();
expectTag(TAG_TYPE_END);
return type;
}
/**
* Parses a 32-bit integer value from the stream.
*/
private int parseInt()
throws IOException
{
int sign = 1;
int ch = read();
if (ch == '-') {
sign = -1;
ch = read();
}
int value = 0;
for (; ch >= '0' && ch <= '9'; ch = read())
value = 10 * value + ch - '0';
_peek = ch;
return sign * value;
}
/**
* Parses a 64-bit long value from the stream.
*/
private long parseLong()
throws IOException
{
int sign = 1;
int ch = read();
if (ch == '-') {
sign = -1;
ch = read();
}
long value = 0;
for (; ch >= '0' && ch <= '9'; ch = read())
value = 10 * value + ch - '0';
_peek = ch;
return sign * value;
}
/**
* Parses a 64-bit double value from the stream.
*
*
* b64 b56 b48 b40 b32 b24 b16 b8
*
*/
private double parseDouble()
throws IOException
{
int ch = skipWhitespace();
_sbuf.setLength(0);
for (; ! isWhitespace(ch) && ch != '<'; ch = read())
_sbuf.append((char) ch);
_peek = ch;
return new Double(_sbuf.toString()).doubleValue();
}
/**
* Parses a date value from the stream.
*/
protected long parseDate()
throws IOException
{
if (_utcCalendar == null)
_utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
return parseDate(_utcCalendar);
}
/**
* Parses a date value from the stream.
*/
protected long parseDate(Calendar calendar)
throws IOException
{
int ch = skipWhitespace();
int year = 0;
for (int i = 0; i < 4; i++) {
if (ch >= '0' && ch <= '9')
year = 10 * year + ch - '0';
else
throw expectedChar("year", ch);
ch = read();
}
int month = 0;
for (int i = 0; i < 2; i++) {
if (ch >= '0' && ch <= '9')
month = 10 * month + ch - '0';
else
throw expectedChar("month", ch);
ch = read();
}
int day = 0;
for (int i = 0; i < 2; i++) {
if (ch >= '0' && ch <= '9')
day = 10 * day + ch - '0';
else
throw expectedChar("day", ch);
ch = read();
}
if (ch != 'T')
throw expectedChar("`T'", ch);
ch = read();
int hour = 0;
for (int i = 0; i < 2; i++) {
if (ch >= '0' && ch <= '9')
hour = 10 * hour + ch - '0';
else
throw expectedChar("hour", ch);
ch = read();
}
int minute = 0;
for (int i = 0; i < 2; i++) {
if (ch >= '0' && ch <= '9')
minute = 10 * minute + ch - '0';
else
throw expectedChar("minute", ch);
ch = read();
}
int second = 0;
for (int i = 0; i < 2; i++) {
if (ch >= '0' && ch <= '9')
second = 10 * second + ch - '0';
else
throw expectedChar("second", ch);
ch = read();
}
int ms = 0;
if (ch == '.') {
ch = read();
while (ch >= '0' && ch <= '9') {
ms = 10 * ms + ch - '0';
ch = read();
}
}
for (; ch > 0 && ch != '<'; ch = read()) {
}
_peek = ch;
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, ms);
return calendar.getTime().getTime();
}
protected String parseString()
throws IOException
{
_sbuf.setLength(0);
return parseString(_sbuf).toString();
}
/**
* Parses a string value from the stream. The burlap object's
* string buffer is used for the result.
*/
protected StringBuffer parseString(StringBuffer sbuf)
throws IOException
{
int ch;
while ((ch = readChar()) >= 0)
sbuf.append((char) ch);
return sbuf;
}
org.w3c.dom.Node parseXML()
throws IOException
{
throw error("help!");
}
/**
* Reads a character from the underlying stream.
*/
int readChar()
throws IOException
{
int ch = read();
if (ch == '<' || ch < 0) {
_peek = ch;
return -1;
}
if (ch == '&') {
ch = read();
if (ch == '#') {
ch = read();
if (ch >= '0' && ch <= '9') {
int v = 0;
for (; ch >= '0' && ch <= '9'; ch = read()) {
v = 10 * v + ch - '0';
}
if (ch != ';')
throw error("expected ';' at " + (char) ch);
return (char) v;
}
else
throw error("expected digit at " + (char) ch);
}
else {
_entityBuffer.setLength(0);
for (; ch >= 'a' && ch <= 'z'; ch = read())
_entityBuffer.append((char) ch);
String entity = _entityBuffer.toString();
if (ch != ';')
throw expectedChar("';'", ch);
if (entity.equals("amp"))
return '&';
else if (entity.equals("apos"))
return '\'';
else if (entity.equals("quot"))
return '"';
else if (entity.equals("lt"))
return '<';
else if (entity.equals("gt"))
return '>';
else
throw new BurlapProtocolException("unknown XML entity &" + entity + "; at `" + (char) ch + "'");
}
}
else if (ch < 0x80)
return (char) ch;
else if ((ch & 0xe0) == 0xc0) {
int ch1 = read();
int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f);
return (char) v;
}
else if ((ch & 0xf0) == 0xe0) {
int ch1 = read();
int ch2 = read();
int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f);
return (char) v;
}
else
throw new BurlapProtocolException("bad utf-8 encoding");
}
/**
* Parses a byte array.
*/
protected byte []parseBytes()
throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
parseBytes(bos);
return bos.toByteArray();
}
/**
* Parses a byte array.
*/
protected ByteArrayOutputStream parseBytes(ByteArrayOutputStream bos)
throws IOException
{
int ch;
for (ch = skipWhitespace(); ch >= 0 && ch != '<'; ch = skipWhitespace()) {
int b1 = ch;
int b2 = read();
int b3 = read();
int b4 = read();
if (b4 != '=') {
int chunk = ((base64Decode[b1] << 18) +
(base64Decode[b2] << 12) +
(base64Decode[b3] << 6) +
(base64Decode[b4]));
bos.write(chunk >> 16);
bos.write(chunk >> 8);
bos.write(chunk);
}
else if (b3 != '=') {
int chunk = ((base64Decode[b1] << 10) +
(base64Decode[b2] << 4) +
(base64Decode[b3] >> 2));
bos.write(chunk >> 8);
bos.write(chunk);
}
else {
int chunk = ((base64Decode[b1] << 2) +
(base64Decode[b2] >> 4));
bos.write(chunk);
}
}
if (ch == '<')
_peek = ch;
return bos;
}
public void expectTag(int expectTag)
throws IOException
{
int tag = parseTag();
if (tag != expectTag)
throw error("expected " + tagName(expectTag) + " at " + tagName(tag));
}
/**
* Parses a tag. Returns true if it's a start tag.
*/
protected int parseTag()
throws IOException
{
if (_peekTag >= 0) {
int tag = _peekTag;
_peekTag = -1;
return tag;
}
int ch = skipWhitespace();
int endTagDelta = 0;
if (ch != '<')
throw expectedChar("'<'", ch);
ch = read();
if (ch == '/') {
endTagDelta = 100;
ch = _is.read();
}
if (! isTagChar(ch))
throw expectedChar("tag", ch);
_sbuf.setLength(0);
for (; isTagChar(ch); ch = read())
_sbuf.append((char) ch);
if (ch != '>')
throw expectedChar("'>'", ch);
Integer value = (Integer) _tagMap.get(_sbuf.toString());
if (value == null)
throw error("Unknown tag <" + _sbuf + ">");
return value.intValue() + endTagDelta;
}
/**
* Returns true if the character is a valid tag character.
*/
private boolean isTagChar(int ch)
{
return (ch >= 'a' && ch <= 'z' ||
ch >= 'A' && ch <= 'Z' ||
ch >= '0' && ch <= '9' ||
ch == ':' || ch == '-');
}
protected int skipWhitespace()
throws IOException
{
int ch = read();
for (;
ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
ch = read()) {
}
return ch;
}
protected boolean isWhitespace(int ch)
throws IOException
{
return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
}
/**
* Reads bytes from the underlying stream.
*/
int read(byte []buffer, int offset, int length)
throws IOException
{
throw new UnsupportedOperationException();
}
int read()
throws IOException
{
if (_peek >= 0) {
int value = _peek;
_peek = -1;
return value;
}
int ch = _is.read();
return ch;
}
public Reader getReader()
{
return null;
}
public InputStream readInputStream()
{
return null;
}
public InputStream getInputStream()
{
return null;
}
protected IOException expectBeginTag(String expect, String tag)
{
return new BurlapProtocolException("expected <" + expect + "> at <" + tag + ">");
}
protected IOException expectedChar(String expect, int ch)
{
if (ch < 0)
return error("expected " + expect + " at end of file");
else
return error("expected " + expect + " at " + (char) ch);
}
protected IOException expectedTag(String expect, int tag)
{
return error("expected " + expect + " at " + tagName(tag));
}
protected IOException error(String message)
{
return new BurlapProtocolException(message);
}
protected static String tagName(int tag)
{
switch (tag) {
case TAG_NULL:
return "";
case TAG_NULL_END:
return " ";
case TAG_BOOLEAN:
return "";
case TAG_BOOLEAN_END:
return " ";
case TAG_INT:
return "";
case TAG_INT_END:
return " ";
case TAG_LONG:
return "";
case TAG_LONG_END:
return " ";
case TAG_DOUBLE:
return "";
case TAG_DOUBLE_END:
return " ";
case TAG_STRING:
return "";
case TAG_STRING_END:
return " ";
case TAG_XML:
return "";
case TAG_XML_END:
return " ";
case TAG_BASE64:
return "";
case TAG_BASE64_END:
return " ";
case TAG_MAP:
return "";
case TAG_LIST:
return "";
case TAG_LIST_END:
return "
";
case TAG_TYPE:
return "";
case TAG_TYPE_END:
return " ";
case TAG_LENGTH:
return "";
case TAG_LENGTH_END:
return " ";
case TAG_REF:
return "";
case TAG_REF_END:
return "";
case TAG_REMOTE:
return "";
case TAG_REMOTE_END:
return " ";
case TAG_CALL:
return "";
case TAG_CALL_END:
return " ";
case TAG_REPLY:
return "";
case TAG_REPLY_END:
return " ";
case TAG_HEADER:
return "";
case TAG_HEADER_END:
return " ";
case TAG_FAULT:
return "";
case TAG_FAULT_END:
return " ";
case -1:
return "end of file";
default:
return "unknown " + tag;
}
}
static {
_tagMap = new HashMap();
_tagMap.put("null", new Integer(TAG_NULL));
_tagMap.put("boolean", new Integer(TAG_BOOLEAN));
_tagMap.put("int", new Integer(TAG_INT));
_tagMap.put("long", new Integer(TAG_LONG));
_tagMap.put("double", new Integer(TAG_DOUBLE));
_tagMap.put("date", new Integer(TAG_DATE));
_tagMap.put("string", new Integer(TAG_STRING));
_tagMap.put("xml", new Integer(TAG_XML));
_tagMap.put("base64", new Integer(TAG_BASE64));
_tagMap.put("map", new Integer(TAG_MAP));
_tagMap.put("list", new Integer(TAG_LIST));
_tagMap.put("type", new Integer(TAG_TYPE));
_tagMap.put("length", new Integer(TAG_LENGTH));
_tagMap.put("ref", new Integer(TAG_REF));
_tagMap.put("remote", new Integer(TAG_REMOTE));
_tagMap.put("burlap:call", new Integer(TAG_CALL));
_tagMap.put("burlap:reply", new Integer(TAG_REPLY));
_tagMap.put("fault", new Integer(TAG_FAULT));
_tagMap.put("method", new Integer(TAG_METHOD));
_tagMap.put("header", new Integer(TAG_HEADER));
}
static {
base64Decode = new int[256];
for (int i = 'A'; i <= 'Z'; i++)
base64Decode[i] = i - 'A';
for (int i = 'a'; i <= 'z'; i++)
base64Decode[i] = i - 'a' + 26;
for (int i = '0'; i <= '9'; i++)
base64Decode[i] = i - '0' + 52;
base64Decode['+'] = 62;
base64Decode['/'] = 63;
}
private static Field getDetailMessageField()
{
if (_detailMessageField == null) {
try {
_detailMessageField = Throwable.class.getDeclaredField("detailMessage");
_detailMessageField.setAccessible(true);
} catch (Throwable e) {
}
}
return _detailMessageField;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy