/*
 * Copyright (c) 2001-2004 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
 *    info@caucho.com.
 *
 * 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.hessian.io;

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.Date;
import java.util.HashMap;

Input stream for Hessian requests.

HessianInput is unbuffered, so any client needs to provide its own buffering.

InputStream is = ...; // from http connection
HessianInput in = new HessianInput(is);
String value;
in.startReply();         // read reply header
value = in.readString(); // read string value
in.completeReply();      // read reply footer
/** * Input stream for Hessian requests. * * <p>HessianInput is unbuffered, so any client needs to provide * its own buffering. * * <pre> * InputStream is = ...; // from http connection * HessianInput in = new HessianInput(is); * String value; * * in.startReply(); // read reply header * value = in.readString(); // read string value * in.completeReply(); // read reply footer * </pre> */
public class HessianInput extends AbstractHessianInput { private static int END_OF_DATA = -2; private static Field _detailMessageField; // factory for deserializing objects in the input stream 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 Reader _chunkReader; private InputStream _chunkInputStream; private Throwable _replyFault; private StringBuffer _sbuf = new StringBuffer(); // true if this is the last chunk private boolean _isLastChunk; // the chunk length private int _chunkLength;
Creates an uninitialized Hessian input stream.
/** * Creates an uninitialized Hessian input stream. */
public HessianInput() { }
Creates a new Hessian input stream, initialized with an underlying input stream.
Params:
  • is – the underlying input stream.
/** * Creates a new Hessian input stream, initialized with an * underlying input stream. * * @param is the underlying input stream. */
public HessianInput(InputStream is) { init(is); }
Sets the serializer factory.
/** * Sets the serializer factory. */
public void setSerializerFactory(SerializerFactory factory) { _serializerFactory = factory; }
Gets the serializer factory.
/** * Gets the serializer factory. */
public SerializerFactory getSerializerFactory() { return _serializerFactory; }
Initialize the hessian stream with the underlying input stream.
/** * Initialize the hessian stream with the underlying input stream. */
public void init(InputStream is) { _is = is; _method = null; _isLastChunk = true; _chunkLength = 0; _peek = -1; _refs = null; _replyFault = null; if (_serializerFactory == null) _serializerFactory = new SerializerFactory(); }
Returns the calls method
/** * Returns the calls method */
public String getMethod() { return _method; }
Returns any reply fault.
/** * Returns any reply fault. */
public Throwable getReplyFault() { return _replyFault; }
Starts reading the call
c major minor
/** * Starts reading the call * * <pre> * c major minor * </pre> */
public int readCall() throws IOException { int tag = read(); if (tag != 'c') throw error("expected hessian call ('c') at " + codeName(tag)); int major = read(); int minor = read(); return (major << 16) + minor; }
For backward compatibility with HessianSkeleton
/** * For backward compatibility with HessianSkeleton */
public void skipOptionalCall() throws IOException { int tag = read(); if (tag == 'c') { read(); read(); } else _peek = tag; }
Starts reading the call

A successful completion will have a single value:

m b16 b8 method
/** * Starts reading the call * * <p>A successful completion will have a single value: * * <pre> * m b16 b8 method * </pre> */
public String readMethod() throws IOException { int tag = read(); if (tag != 'm') throw error("expected hessian method ('m') at " + codeName(tag)); int d1 = read(); int d2 = read(); _isLastChunk = true; _chunkLength = d1 * 256 + d2; _sbuf.setLength(0); int ch; while ((ch = parseChar()) >= 0) _sbuf.append((char) ch); _method = _sbuf.toString(); return _method; }
Starts reading the call, including the headers.

The call expects the following protocol data

c major minor
m b16 b8 method
/** * Starts reading the call, including the headers. * * <p>The call expects the following protocol data * * <pre> * c major minor * m b16 b8 method * </pre> */
public void startCall() throws IOException { readCall(); while (readHeader() != null) { readObject(); } readMethod(); }
Completes reading the call

A successful completion will have a single value:

z
/** * Completes reading the call * * <p>A successful completion will have a single value: * * <pre> * z * </pre> */
public void completeCall() throws IOException { int tag = read(); if (tag == 'z') { } else throw error("expected end of call ('z') at " + codeName(tag) + ". Check method arguments and ensure method overloading is enabled if necessary"); }
Reads a reply as an object. If the reply has a fault, throws the exception.
/** * Reads a reply as an object. * If the reply has a fault, throws the exception. */
public Object readReply(Class expectedClass) throws Throwable { int tag = read(); if (tag != 'r') error("expected hessian reply at " + codeName(tag)); int major = read(); int minor = read(); tag = read(); if (tag == 'f') throw prepareFault(); else { _peek = tag; Object value = readObject(expectedClass); completeValueReply(); return value; } }
Starts reading the reply

A successful completion will have a single value:

r
/** * Starts reading the reply * * <p>A successful completion will have a single value: * * <pre> * r * </pre> */
public void startReply() throws Throwable { int tag = read(); if (tag != 'r') error("expected hessian reply at " + codeName(tag)); int major = read(); int minor = read(); startReplyBody(); } public void startReplyBody() throws Throwable { int tag = read(); if (tag == 'f') throw prepareFault(); else _peek = tag; }
Prepares the fault.
/** * 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; if (message != null && _detailMessageField != null) { try { _detailMessageField.set(_replyFault, message); } catch (Throwable e) { } } return _replyFault; } else { String code = (String) fault.get("code"); _replyFault = new HessianServiceException(message, code, detail); return _replyFault; } }
Completes reading the call

A successful completion will have a single value:

z
/** * Completes reading the call * * <p>A successful completion will have a single value: * * <pre> * z * </pre> */
public void completeReply() throws IOException { int tag = read(); if (tag != 'z') error("expected end of reply at " + codeName(tag)); }
Completes reading the call

A successful completion will have a single value:

z
/** * Completes reading the call * * <p>A successful completion will have a single value: * * <pre> * z * </pre> */
public void completeValueReply() throws IOException { int tag = read(); if (tag != 'z') error("expected end of reply at " + codeName(tag)); }
Reads a header, returning null if there are no headers.
H b16 b8 value
/** * Reads a header, returning null if there are no headers. * * <pre> * H b16 b8 value * </pre> */
public String readHeader() throws IOException { int tag = read(); if (tag == 'H') { _isLastChunk = true; _chunkLength = (read() << 8) + read(); _sbuf.setLength(0); int ch; while ((ch = parseChar()) >= 0) _sbuf.append((char) ch); return _sbuf.toString(); } _peek = tag; return null; }
Reads a null
N
/** * Reads a null * * <pre> * N * </pre> */
public void readNull() throws IOException { int tag = read(); switch (tag) { case 'N': return; default: throw expect("null", tag); } }
Reads a boolean
T
F
/** * Reads a boolean * * <pre> * T * F * </pre> */
public boolean readBoolean() throws IOException { int tag = read(); switch (tag) { case 'T': return true; case 'F': return false; case 'I': return parseInt() == 0; case 'L': return parseLong() == 0; case 'D': return parseDouble() == 0.0; case 'N': return false; default: throw expect("boolean", tag); } } /** * Reads a byte * * <pre> * I b32 b24 b16 b8 * </pre> */ /* public byte readByte() throws IOException { return (byte) readInt(); } */
Reads a short
I b32 b24 b16 b8
/** * Reads a short * * <pre> * I b32 b24 b16 b8 * </pre> */
public short readShort() throws IOException { return (short) readInt(); }
Reads an integer
I b32 b24 b16 b8
/** * Reads an integer * * <pre> * I b32 b24 b16 b8 * </pre> */
public int readInt() throws IOException { int tag = read(); switch (tag) { case 'T': return 1; case 'F': return 0; case 'I': return parseInt(); case 'L': return (int) parseLong(); case 'D': return (int) parseDouble(); default: throw expect("int", tag); } }
Reads a long
L b64 b56 b48 b40 b32 b24 b16 b8
/** * Reads a long * * <pre> * L b64 b56 b48 b40 b32 b24 b16 b8 * </pre> */
public long readLong() throws IOException { int tag = read(); switch (tag) { case 'T': return 1; case 'F': return 0; case 'I': return parseInt(); case 'L': return parseLong(); case 'D': return (long) parseDouble(); default: throw expect("long", tag); } }
Reads a float
D b64 b56 b48 b40 b32 b24 b16 b8
/** * Reads a float * * <pre> * D b64 b56 b48 b40 b32 b24 b16 b8 * </pre> */
public float readFloat() throws IOException { return (float) readDouble(); }
Reads a double
D b64 b56 b48 b40 b32 b24 b16 b8
/** * Reads a double * * <pre> * D b64 b56 b48 b40 b32 b24 b16 b8 * </pre> */
public double readDouble() throws IOException { int tag = read(); switch (tag) { case 'T': return 1; case 'F': return 0; case 'I': return parseInt(); case 'L': return (double) parseLong(); case 'D': return parseDouble(); default: throw expect("long", tag); } }
Reads a date.
T b64 b56 b48 b40 b32 b24 b16 b8
/** * Reads a date. * * <pre> * T b64 b56 b48 b40 b32 b24 b16 b8 * </pre> */
public long readUTCDate() throws IOException { int tag = read(); if (tag != 'd') throw error("expected date at " + codeName(tag)); long b64 = read(); long b56 = read(); long b48 = read(); long b40 = read(); long b32 = read(); long b24 = read(); long b16 = read(); long b8 = read(); return ((b64 << 56) + (b56 << 48) + (b48 << 40) + (b40 << 32) + (b32 << 24) + (b24 << 16) + (b16 << 8) + b8); }
Reads a byte from the stream.
/** * Reads a byte from the stream. */
public int readChar() throws IOException { if (_chunkLength > 0) { _chunkLength--; if (_chunkLength == 0 && _isLastChunk) _chunkLength = END_OF_DATA; int ch = parseUTF8Char(); return ch; } else if (_chunkLength == END_OF_DATA) { _chunkLength = 0; return -1; } int tag = read(); switch (tag) { case 'N': return -1; case 'S': case 's': case 'X': case 'x': _isLastChunk = tag == 'S' || tag == 'X'; _chunkLength = (read() << 8) + read(); _chunkLength--; int value = parseUTF8Char(); // special code so successive read byte won't // be read as a single object. if (_chunkLength == 0 && _isLastChunk) _chunkLength = END_OF_DATA; return value; default: throw new IOException("expected 'S' at " + (char) tag); } }
Reads a byte array from the stream.
/** * Reads a byte array from the stream. */
public int readString(char []buffer, int offset, int length) throws IOException { int readLength = 0; if (_chunkLength == END_OF_DATA) { _chunkLength = 0; return -1; } else if (_chunkLength == 0) { int tag = read(); switch (tag) { case 'N': return -1; case 'S': case 's': case 'X': case 'x': _isLastChunk = tag == 'S' || tag == 'X'; _chunkLength = (read() << 8) + read(); break; default: throw new IOException("expected 'S' at " + (char) tag); } } while (length > 0) { if (_chunkLength > 0) { buffer[offset++] = (char) parseUTF8Char(); _chunkLength--; length--; readLength++; } else if (_isLastChunk) { if (readLength == 0) return -1; else { _chunkLength = END_OF_DATA; return readLength; } } else { int tag = read(); switch (tag) { case 'S': case 's': case 'X': case 'x': _isLastChunk = tag == 'S' || tag == 'X'; _chunkLength = (read() << 8) + read(); break; default: throw new IOException("expected 'S' at " + (char) tag); } } } if (readLength == 0) return -1; else if (_chunkLength > 0 || ! _isLastChunk) return readLength; else { _chunkLength = END_OF_DATA; return readLength; } }
Reads a string
S b16 b8 string value
/** * Reads a string * * <pre> * S b16 b8 string value * </pre> */
public String readString() throws IOException { int tag = read(); switch (tag) { case 'N': return null; case 'I': return String.valueOf(parseInt()); case 'L': return String.valueOf(parseLong()); case 'D': return String.valueOf(parseDouble()); case 'S': case 's': case 'X': case 'x': _isLastChunk = tag == 'S' || tag == 'X'; _chunkLength = (read() << 8) + read(); _sbuf.setLength(0); int ch; while ((ch = parseChar()) >= 0) _sbuf.append((char) ch); return _sbuf.toString(); default: throw expect("string", tag); } }
Reads an XML node.
S b16 b8 string value
/** * Reads an XML node. * * <pre> * S b16 b8 string value * </pre> */
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': _isLastChunk = tag == 'S' || tag == 'X'; _chunkLength = (read() << 8) + read(); throw error("Can't handle string in this context"); default: throw expect("string", tag); } }
Reads a byte array
B b16 b8 data value
/** * Reads a byte array * * <pre> * B b16 b8 data value * </pre> */
public byte []readBytes() throws IOException { int tag = read(); switch (tag) { case 'N': return null; case 'B': case 'b': _isLastChunk = tag == 'B'; _chunkLength = (read() << 8) + read(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int data; while ((data = parseByte()) >= 0) bos.write(data); return bos.toByteArray(); default: throw expect("bytes", tag); } }
Reads a byte from the stream.
/** * Reads a byte from the stream. */
public int readByte() throws IOException { if (_chunkLength > 0) { _chunkLength--; if (_chunkLength == 0 && _isLastChunk) _chunkLength = END_OF_DATA; return read(); } else if (_chunkLength == END_OF_DATA) { _chunkLength = 0; return -1; } int tag = read(); switch (tag) { case 'N': return -1; case 'B': case 'b': _isLastChunk = tag == 'B'; _chunkLength = (read() << 8) + read(); int value = parseByte(); // special code so successive read byte won't // be read as a single object. if (_chunkLength == 0 && _isLastChunk) _chunkLength = END_OF_DATA; return value; default: throw new IOException("expected 'B' at " + (char) tag); } }
Reads a byte array from the stream.
/** * Reads a byte array from the stream. */
public int readBytes(byte []buffer, int offset, int length) throws IOException { int readLength = 0; if (_chunkLength == END_OF_DATA) { _chunkLength = 0; return -1; } else if (_chunkLength == 0) { int tag = read(); switch (tag) { case 'N': return -1; case 'B': case 'b': _isLastChunk = tag == 'B'; _chunkLength = (read() << 8) + read(); break; default: throw new IOException("expected 'B' at " + (char) tag); } } while (length > 0) { if (_chunkLength > 0) { buffer[offset++] = (byte) read(); _chunkLength--; length--; readLength++; } else if (_isLastChunk) { if (readLength == 0) return -1; else { _chunkLength = END_OF_DATA; return readLength; } } else { int tag = read(); switch (tag) { case 'B': case 'b': _isLastChunk = tag == 'B'; _chunkLength = (read() << 8) + read(); break; default: throw new IOException("expected 'B' at " + (char) tag); } } } if (readLength == 0) return -1; else if (_chunkLength > 0 || ! _isLastChunk) return readLength; else { _chunkLength = END_OF_DATA; return readLength; } }
Reads a fault.
/** * Reads a fault. */
private HashMap readFault() throws IOException { HashMap map = new HashMap(); int code = read(); for (; code > 0 && code != 'z'; code = read()) { _peek = code; Object key = readObject(); Object value = readObject(); if (key != null && value != null) map.put(key, value); } if (code != 'z') throw expect("fault", code); return map; }
Reads an object from the input stream with an expected type.
/** * Reads an object from the input stream with an expected type. */
public Object readObject(Class cl) throws IOException { if (cl == null || cl == Object.class) return readObject(); int tag = read(); switch (tag) { case 'N': return null; case 'M': { String type = readType(); // hessian/3386 if ("".equals(type)) { Deserializer reader; reader = _serializerFactory.getDeserializer(cl); return reader.readMap(this); } else { Deserializer reader; reader = _serializerFactory.getObjectDeserializer(type); return reader.readMap(this); } } case 'V': { String type = readType(); int length = readLength(); Deserializer reader; reader = _serializerFactory.getObjectDeserializer(type); if (cl != reader.getType() && cl.isAssignableFrom(reader.getType())) return reader.readList(this, length); reader = _serializerFactory.getDeserializer(cl); Object v = reader.readList(this, length); return v; } case 'R': { int ref = parseInt(); return _refs.get(ref); } case 'r': { String type = readType(); String url = readString(); return resolveRemote(type, url); } } _peek = tag; // hessian/332i vs hessian/3406 //return readObject(); Object value = _serializerFactory.getDeserializer(cl).readObject(this); return value; }
Reads an arbitrary object from the input stream when the type is unknown.
/** * Reads an arbitrary object from the input stream when the type * is unknown. */
public Object readObject() throws IOException { int tag = read(); switch (tag) { case 'N': return null; case 'T': return Boolean.valueOf(true); case 'F': return Boolean.valueOf(false); case 'I': return Integer.valueOf(parseInt()); case 'L': return Long.valueOf(parseLong()); case 'D': return Double.valueOf(parseDouble()); case 'd': return new Date(parseLong()); case 'x': case 'X': { _isLastChunk = tag == 'X'; _chunkLength = (read() << 8) + read(); return parseXML(); } case 's': case 'S': { _isLastChunk = tag == 'S'; _chunkLength = (read() << 8) + read(); int data; _sbuf.setLength(0); while ((data = parseChar()) >= 0) _sbuf.append((char) data); return _sbuf.toString(); } case 'b': case 'B': { _isLastChunk = tag == 'B'; _chunkLength = (read() << 8) + read(); int data; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while ((data = parseByte()) >= 0) bos.write(data); return bos.toByteArray(); } case 'V': { String type = readType(); int length = readLength(); return _serializerFactory.readList(this, length, type); } case 'M': { String type = readType(); return _serializerFactory.readMap(this, type); } case 'R': { int ref = parseInt(); return _refs.get(ref); } case 'r': { String type = readType(); String url = readString(); return resolveRemote(type, url); } default: throw error("unknown code for readObject at " + codeName(tag)); } }
Reads a remote object.
/** * Reads a remote object. */
public Object readRemote() throws IOException { String type = readType(); String url = readString(); return resolveRemote(type, url); }
Reads a reference.
/** * Reads a reference. */
public Object readRef() throws IOException { return _refs.get(parseInt()); }
Reads the start of a list.
/** * Reads the start of a list. */
public int readListStart() throws IOException { return read(); }
Reads the start of a list.
/** * Reads the start of a list. */
public int readMapStart() throws IOException { return read(); }
Returns true if this is the end of a list or a map.
/** * Returns true if this is the end of a list or a map. */
public boolean isEnd() throws IOException { int code = read(); _peek = code; return (code < 0 || code == 'z'); }
Reads the end byte.
/** * Reads the end byte. */
public void readEnd() throws IOException { int code = read(); if (code != 'z') throw error("unknown code at " + codeName(code)); }
Reads the end byte.
/** * Reads the end byte. */
public void readMapEnd() throws IOException { int code = read(); if (code != 'z') throw error("expected end of map ('z') at " + codeName(code)); }
Reads the end byte.
/** * Reads the end byte. */
public void readListEnd() throws IOException { int code = read(); if (code != 'z') throw error("expected end of list ('z') at " + codeName(code)); }
Adds a list/map reference.
/** * 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.
/** * Adds a list/map reference. */
public void setRef(int i, Object ref) { _refs.set(i, ref); }
Resets the references for streaming.
/** * Resets the references for streaming. */
public void resetReferences() { if (_refs != null) _refs.clear(); }
Resolves a remote object.
/** * 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 HessianRemote(type, url); }
Parses a type from the stream.
t b16 b8
/** * Parses a type from the stream. * * <pre> * t b16 b8 * </pre> */
public String readType() throws IOException { int code = read(); if (code != 't') { _peek = code; return ""; } _isLastChunk = true; _chunkLength = (read() << 8) + read(); _sbuf.setLength(0); int ch; while ((ch = parseChar()) >= 0) _sbuf.append((char) ch); return _sbuf.toString(); }
Parses the length for an array
l b32 b24 b16 b8
/** * Parses the length for an array * * <pre> * l b32 b24 b16 b8 * </pre> */
public int readLength() throws IOException { int code = read(); if (code != 'l') { _peek = code; return -1; } return parseInt(); }
Parses a 32-bit integer value from the stream.
b32 b24 b16 b8
/** * Parses a 32-bit integer value from the stream. * * <pre> * b32 b24 b16 b8 * </pre> */
private int parseInt() throws IOException { int b32 = read(); int b24 = read(); int b16 = read(); int b8 = read(); return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8; }
Parses a 64-bit long value from the stream.
b64 b56 b48 b40 b32 b24 b16 b8
/** * Parses a 64-bit long value from the stream. * * <pre> * b64 b56 b48 b40 b32 b24 b16 b8 * </pre> */
private long parseLong() throws IOException { long b64 = read(); long b56 = read(); long b48 = read(); long b40 = read(); long b32 = read(); long b24 = read(); long b16 = read(); long b8 = read(); return ((b64 << 56) + (b56 << 48) + (b48 << 40) + (b40 << 32) + (b32 << 24) + (b24 << 16) + (b16 << 8) + b8); }
Parses a 64-bit double value from the stream.
b64 b56 b48 b40 b32 b24 b16 b8
/** * Parses a 64-bit double value from the stream. * * <pre> * b64 b56 b48 b40 b32 b24 b16 b8 * </pre> */
private double parseDouble() throws IOException { long b64 = read(); long b56 = read(); long b48 = read(); long b40 = read(); long b32 = read(); long b24 = read(); long b16 = read(); long b8 = read(); long bits = ((b64 << 56) + (b56 << 48) + (b48 << 40) + (b40 << 32) + (b32 << 24) + (b24 << 16) + (b16 << 8) + b8); return Double.longBitsToDouble(bits); } org.w3c.dom.Node parseXML() throws IOException { throw new UnsupportedOperationException(); }
Reads a character from the underlying stream.
/** * Reads a character from the underlying stream. */
private int parseChar() throws IOException { while (_chunkLength <= 0) { if (_isLastChunk) return -1; int code = read(); switch (code) { case 's': case 'x': _isLastChunk = false; _chunkLength = (read() << 8) + read(); break; case 'S': case 'X': _isLastChunk = true; _chunkLength = (read() << 8) + read(); break; default: throw expect("string", code); } } _chunkLength--; return parseUTF8Char(); }
Parses a single UTF8 character.
/** * Parses a single UTF8 character. */
private int parseUTF8Char() throws IOException { int ch = read(); if (ch < 0x80) return ch; else if ((ch & 0xe0) == 0xc0) { int ch1 = read(); int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f); return v; } else if ((ch & 0xf0) == 0xe0) { int ch1 = read(); int ch2 = read(); int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f); return v; } else throw error("bad utf-8 encoding at " + codeName(ch)); }
Reads a byte from the underlying stream.
/** * Reads a byte from the underlying stream. */
private int parseByte() throws IOException { while (_chunkLength <= 0) { if (_isLastChunk) { return -1; } int code = read(); switch (code) { case 'b': _isLastChunk = false; _chunkLength = (read() << 8) + read(); break; case 'B': _isLastChunk = true; _chunkLength = (read() << 8) + read(); break; default: throw expect("byte[]", code); } } _chunkLength--; return read(); }
Reads bytes based on an input stream.
/** * Reads bytes based on an input stream. */
public InputStream readInputStream() throws IOException { int tag = read(); switch (tag) { case 'N': return null; case 'B': case 'b': _isLastChunk = tag == 'B'; _chunkLength = (read() << 8) + read(); break; default: throw expect("inputStream", tag); } return new InputStream() { boolean _isClosed = false; public int read() throws IOException { if (_isClosed || _is == null) return -1; int ch = parseByte(); if (ch < 0) _isClosed = true; return ch; } public int read(byte []buffer, int offset, int length) throws IOException { if (_isClosed || _is == null) return -1; int len = HessianInput.this.read(buffer, offset, length); if (len < 0) _isClosed = true; return len; } public void close() throws IOException { while (read() >= 0) { } _isClosed = true; } }; }
Reads bytes from the underlying stream.
/** * Reads bytes from the underlying stream. */
int read(byte []buffer, int offset, int length) throws IOException { int readLength = 0; while (length > 0) { while (_chunkLength <= 0) { if (_isLastChunk) return readLength == 0 ? -1 : readLength; int code = read(); switch (code) { case 'b': _isLastChunk = false; _chunkLength = (read() << 8) + read(); break; case 'B': _isLastChunk = true; _chunkLength = (read() << 8) + read(); break; default: throw expect("byte[]", code); } } int sublen = _chunkLength; if (length < sublen) sublen = length; sublen = _is.read(buffer, offset, sublen); offset += sublen; readLength += sublen; length -= sublen; _chunkLength -= sublen; } return readLength; } final int read() throws IOException { if (_peek >= 0) { int value = _peek; _peek = -1; return value; } int ch = _is.read(); return ch; } public void close() { _is = null; } public Reader getReader() { return null; } protected IOException expect(String expect, int ch) { return error("expected " + expect + " at " + codeName(ch)); } protected String codeName(int ch) { if (ch < 0) return "end of file"; else return "0x" + Integer.toHexString(ch & 0xff) + " (" + (char) + ch + ")"; } protected IOException error(String message) { if (_method != null) return new HessianProtocolException(_method + ": " + message); else return new HessianProtocolException(message); } static { try { _detailMessageField = Throwable.class.getDeclaredField("detailMessage"); _detailMessageField.setAccessible(true); } catch (Throwable e) { } } }