0001: /*
0002: * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved.
0003: *
0004: * The Apache Software License, Version 1.1
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: *
0010: * 1. Redistributions of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * 2. Redistributions in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in
0015: * the documentation and/or other materials provided with the
0016: * distribution.
0017: *
0018: * 3. The end-user documentation included with the redistribution, if
0019: * any, must include the following acknowlegement:
0020: * "This product includes software developed by the
0021: * Caucho Technology (http://www.caucho.com/)."
0022: * Alternately, this acknowlegement may appear in the software itself,
0023: * if and wherever such third-party acknowlegements normally appear.
0024: *
0025: * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
0026: * endorse or promote products derived from this software without prior
0027: * written permission. For written permission, please contact
0028: * info@caucho.com.
0029: *
0030: * 5. Products derived from this software may not be called "Resin"
0031: * nor may "Resin" appear in their names without prior written
0032: * permission of Caucho Technology.
0033: *
0034: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0035: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0036: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0037: * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
0038: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
0039: * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0040: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
0041: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
0042: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
0043: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
0044: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0045: *
0046: * @author Scott Ferguson
0047: */
0048:
0049: package com.caucho.hessian.io;
0050:
0051: import java.io.ByteArrayOutputStream;
0052: import java.io.IOException;
0053: import java.io.InputStream;
0054: import java.io.Reader;
0055: import java.lang.reflect.Field;
0056: import java.util.ArrayList;
0057: import java.util.Date;
0058: import java.util.HashMap;
0059: import java.util.logging.*;
0060:
0061: /**
0062: * Input stream for Hessian requests.
0063: *
0064: * <p>HessianInput is unbuffered, so any client needs to provide
0065: * its own buffering.
0066: *
0067: * <pre>
0068: * InputStream is = ...; // from http connection
0069: * HessianInput in = new HessianInput(is);
0070: * String value;
0071: *
0072: * in.startReply(); // read reply header
0073: * value = in.readString(); // read string value
0074: * in.completeReply(); // read reply footer
0075: * </pre>
0076: */
0077: public class Hessian2Input extends AbstractHessianInput implements
0078: Hessian2Constants {
0079: private static final Logger log = Logger
0080: .getLogger(Hessian2Input.class.getName());
0081:
0082: private static final double D_256 = 1.0 / 256.0;
0083: private static final int END_OF_DATA = -2;
0084:
0085: private static Field _detailMessageField;
0086:
0087: private static final int SIZE = 256;
0088: private static final int GAP = 16;
0089:
0090: // factory for deserializing objects in the input stream
0091: protected SerializerFactory _serializerFactory;
0092:
0093: private static boolean _isCloseStreamOnClose;
0094:
0095: protected ArrayList _refs;
0096: protected ArrayList _classDefs;
0097: protected ArrayList _types;
0098:
0099: // the underlying input stream
0100: private InputStream _is;
0101: private final byte[] _buffer = new byte[SIZE];
0102:
0103: // a peek character
0104: private int _offset;
0105: private int _length;
0106:
0107: // true for streaming data
0108: private boolean _isStreaming;
0109:
0110: // the method for a call
0111: private String _method;
0112:
0113: private Reader _chunkReader;
0114: private InputStream _chunkInputStream;
0115:
0116: private Throwable _replyFault;
0117:
0118: private StringBuffer _sbuf = new StringBuffer();
0119:
0120: // true if this is the last chunk
0121: private boolean _isLastChunk;
0122: // the chunk length
0123: private int _chunkLength;
0124:
0125: /**
0126: * Creates a new Hessian input stream, initialized with an
0127: * underlying input stream.
0128: *
0129: * @param is the underlying input stream.
0130: */
0131: public Hessian2Input(InputStream is) {
0132: _is = is;
0133: }
0134:
0135: /**
0136: * Sets the serializer factory.
0137: */
0138: public void setSerializerFactory(SerializerFactory factory) {
0139: _serializerFactory = factory;
0140: }
0141:
0142: /**
0143: * Gets the serializer factory.
0144: */
0145: public SerializerFactory getSerializerFactory() {
0146: return _serializerFactory;
0147: }
0148:
0149: /**
0150: * Gets the serializer factory, creating a default if necessary.
0151: */
0152: public final SerializerFactory findSerializerFactory() {
0153: SerializerFactory factory = _serializerFactory;
0154:
0155: if (factory == null)
0156: _serializerFactory = factory = new SerializerFactory();
0157:
0158: return factory;
0159: }
0160:
0161: public void setCloseStreamOnClose(boolean isClose) {
0162: _isCloseStreamOnClose = isClose;
0163: }
0164:
0165: public boolean isCloseStreamOnClose() {
0166: return _isCloseStreamOnClose;
0167: }
0168:
0169: /**
0170: * Returns the calls method
0171: */
0172: public String getMethod() {
0173: return _method;
0174: }
0175:
0176: /**
0177: * Returns any reply fault.
0178: */
0179: public Throwable getReplyFault() {
0180: return _replyFault;
0181: }
0182:
0183: /**
0184: * Starts reading the call
0185: *
0186: * <pre>
0187: * c major minor
0188: * </pre>
0189: */
0190: public int readCall() throws IOException {
0191: int tag = read();
0192:
0193: if (tag != 'c')
0194: throw error("expected hessian call ('c') at "
0195: + codeName(tag));
0196:
0197: int major = read();
0198: int minor = read();
0199:
0200: return (major << 16) + minor;
0201: }
0202:
0203: /**
0204: * Starts reading the envelope
0205: *
0206: * <pre>
0207: * E major minor
0208: * </pre>
0209: */
0210: public int readEnvelope() throws IOException {
0211: int tag = read();
0212:
0213: if (tag != 'E')
0214: throw error("expected hessian Envelope ('E') at "
0215: + codeName(tag));
0216:
0217: int major = read();
0218: int minor = read();
0219:
0220: return (major << 16) + minor;
0221: }
0222:
0223: /**
0224: * Completes reading the envelope
0225: *
0226: * <p>A successful completion will have a single value:
0227: *
0228: * <pre>
0229: * z
0230: * </pre>
0231: */
0232: public void completeEnvelope() throws IOException {
0233: int tag = read();
0234:
0235: if (tag != 'z')
0236: error("expected end of envelope at " + codeName(tag));
0237: }
0238:
0239: /**
0240: * Starts reading the call
0241: *
0242: * <p>A successful completion will have a single value:
0243: *
0244: * <pre>
0245: * m b16 b8 method
0246: * </pre>
0247: */
0248: public String readMethod() throws IOException {
0249: int tag = read();
0250:
0251: if (tag != 'm')
0252: throw error("expected hessian method ('m') at "
0253: + codeName(tag));
0254:
0255: int d1 = read();
0256: int d2 = read();
0257:
0258: _isLastChunk = true;
0259: _chunkLength = d1 * 256 + d2;
0260: _sbuf.setLength(0);
0261: int ch;
0262: while ((ch = parseChar()) >= 0)
0263: _sbuf.append((char) ch);
0264:
0265: _method = _sbuf.toString();
0266:
0267: return _method;
0268: }
0269:
0270: /**
0271: * Starts reading the call, including the headers.
0272: *
0273: * <p>The call expects the following protocol data
0274: *
0275: * <pre>
0276: * c major minor
0277: * m b16 b8 method
0278: * </pre>
0279: */
0280: public void startCall() throws IOException {
0281: readCall();
0282:
0283: while (readHeader() != null) {
0284: readObject();
0285: }
0286:
0287: readMethod();
0288: }
0289:
0290: /**
0291: * Completes reading the call
0292: *
0293: * <p>A successful completion will have a single value:
0294: *
0295: * <pre>
0296: * z
0297: * </pre>
0298: */
0299: public void completeCall() throws IOException {
0300: int tag = read();
0301:
0302: if (tag == 'z') {
0303: } else if (tag < 0)
0304: throw error("expected end of call ('z') at end of stream.");
0305: else
0306: throw error("expected end of call ('z') at "
0307: + codeName(tag)
0308: + ". Check method arguments and ensure method overloading is enabled if necessary");
0309: }
0310:
0311: /**
0312: * Reads a reply as an object.
0313: * If the reply has a fault, throws the exception.
0314: */
0315: @Override
0316: public Object readReply(Class expectedClass) throws Throwable {
0317: int tag = read();
0318:
0319: if (tag != 'r') {
0320: StringBuilder sb = new StringBuilder();
0321: sb.append((char) tag);
0322:
0323: try {
0324: int ch;
0325:
0326: while ((ch = read()) >= 0) {
0327: sb.append((char) ch);
0328: }
0329: } catch (IOException e) {
0330: log.log(Level.FINE, e.toString(), e);
0331: }
0332:
0333: throw error("expected hessian reply at " + codeName(tag)
0334: + "\n" + sb);
0335: }
0336:
0337: int major = read();
0338: int minor = read();
0339:
0340: if (major > 2 || major == 2 && minor > 0)
0341: throw error("Cannot understand Hessian " + major + "."
0342: + minor + " response");
0343: tag = read();
0344: if (tag == 'f')
0345: throw prepareFault();
0346: else {
0347: if (tag >= 0)
0348: _offset--;
0349:
0350: Object value = readObject(expectedClass);
0351:
0352: completeValueReply();
0353:
0354: return value;
0355: }
0356: }
0357:
0358: /**
0359: * Starts reading the reply
0360: *
0361: * <p>A successful completion will have a single value:
0362: *
0363: * <pre>
0364: * r
0365: * </pre>
0366: */
0367: public void startReply() throws Throwable {
0368: int tag = read();
0369:
0370: if (tag != 'r') {
0371: StringBuilder sb = new StringBuilder();
0372: sb.append((char) tag);
0373:
0374: try {
0375: int ch;
0376:
0377: while ((ch = read()) >= 0) {
0378: sb.append((char) ch);
0379: }
0380: } catch (IOException e) {
0381: log.log(Level.FINE, e.toString(), e);
0382: }
0383:
0384: throw error("expected hessian reply at " + codeName(tag)
0385: + "\n" + sb);
0386: }
0387:
0388: int major = read();
0389: int minor = read();
0390:
0391: if (major > 2 || major == 2 && minor > 0)
0392: throw error("Cannot understand Hessian " + major + "."
0393: + minor + " response");
0394:
0395: tag = read();
0396: if (tag == 'f')
0397: throw prepareFault();
0398: else if (tag >= 0)
0399: _offset--;
0400: }
0401:
0402: /**
0403: * Prepares the fault.
0404: */
0405: private Throwable prepareFault() throws IOException {
0406: HashMap fault = readFault();
0407:
0408: Object detail = fault.get("detail");
0409: String message = (String) fault.get("message");
0410:
0411: if (detail instanceof Throwable) {
0412: _replyFault = (Throwable) detail;
0413:
0414: if (message != null && _detailMessageField != null) {
0415: try {
0416: _detailMessageField.set(_replyFault, message);
0417: } catch (Throwable e) {
0418: }
0419: }
0420:
0421: return _replyFault;
0422: }
0423:
0424: else {
0425: String code = (String) fault.get("code");
0426:
0427: _replyFault = new HessianServiceException(message, code,
0428: detail);
0429:
0430: return _replyFault;
0431: }
0432: }
0433:
0434: /**
0435: * Completes reading the call
0436: *
0437: * <p>A successful completion will have a single value:
0438: *
0439: * <pre>
0440: * z
0441: * </pre>
0442: */
0443: public void completeReply() throws IOException {
0444: int tag = read();
0445:
0446: if (tag != 'z')
0447: error("expected end of reply at " + codeName(tag));
0448: }
0449:
0450: /**
0451: * Completes reading the call
0452: *
0453: * <p>A successful completion will have a single value:
0454: *
0455: * <pre>
0456: * z
0457: * </pre>
0458: */
0459: public void completeValueReply() throws IOException {
0460: int tag = read();
0461:
0462: if (tag != 'z')
0463: error("expected end of reply at " + codeName(tag));
0464: }
0465:
0466: /**
0467: * Reads a header, returning null if there are no headers.
0468: *
0469: * <pre>
0470: * H b16 b8 value
0471: * </pre>
0472: */
0473: public String readHeader() throws IOException {
0474: int tag = read();
0475:
0476: if (tag == 'H') {
0477: _isLastChunk = true;
0478: _chunkLength = (read() << 8) + read();
0479:
0480: _sbuf.setLength(0);
0481: int ch;
0482: while ((ch = parseChar()) >= 0)
0483: _sbuf.append((char) ch);
0484:
0485: return _sbuf.toString();
0486: }
0487:
0488: if (tag >= 0)
0489: _offset--;
0490:
0491: return null;
0492: }
0493:
0494: /**
0495: * Starts reading the message
0496: *
0497: * <pre>
0498: * p major minor
0499: * </pre>
0500: */
0501: public int startMessage() throws IOException {
0502: int tag = read();
0503:
0504: if (tag == 'p')
0505: _isStreaming = false;
0506: else if (tag == 'P')
0507: _isStreaming = true;
0508: else
0509: throw error("expected Hessian message ('p') at "
0510: + codeName(tag));
0511:
0512: int major = read();
0513: int minor = read();
0514:
0515: return (major << 16) + minor;
0516: }
0517:
0518: /**
0519: * Completes reading the message
0520: *
0521: * <p>A successful completion will have a single value:
0522: *
0523: * <pre>
0524: * z
0525: * </pre>
0526: */
0527: public void completeMessage() throws IOException {
0528: int tag = read();
0529:
0530: if (tag != 'z')
0531: error("expected end of message at " + codeName(tag));
0532: }
0533:
0534: /**
0535: * Reads a null
0536: *
0537: * <pre>
0538: * N
0539: * </pre>
0540: */
0541: public void readNull() throws IOException {
0542: int tag = read();
0543:
0544: switch (tag) {
0545: case 'N':
0546: return;
0547:
0548: default:
0549: throw expect("null", tag);
0550: }
0551: }
0552:
0553: /**
0554: * Reads a boolean
0555: *
0556: * <pre>
0557: * T
0558: * F
0559: * </pre>
0560: */
0561: public boolean readBoolean() throws IOException {
0562: int tag = _offset < _length ? (_buffer[_offset++] & 0xff)
0563: : read();
0564:
0565: switch (tag) {
0566: case 'T':
0567: return true;
0568: case 'F':
0569: return false;
0570:
0571: // direct integer
0572: case 0x80:
0573: case 0x81:
0574: case 0x82:
0575: case 0x83:
0576: case 0x84:
0577: case 0x85:
0578: case 0x86:
0579: case 0x87:
0580: case 0x88:
0581: case 0x89:
0582: case 0x8a:
0583: case 0x8b:
0584: case 0x8c:
0585: case 0x8d:
0586: case 0x8e:
0587: case 0x8f:
0588:
0589: case 0x90:
0590: case 0x91:
0591: case 0x92:
0592: case 0x93:
0593: case 0x94:
0594: case 0x95:
0595: case 0x96:
0596: case 0x97:
0597: case 0x98:
0598: case 0x99:
0599: case 0x9a:
0600: case 0x9b:
0601: case 0x9c:
0602: case 0x9d:
0603: case 0x9e:
0604: case 0x9f:
0605:
0606: case 0xa0:
0607: case 0xa1:
0608: case 0xa2:
0609: case 0xa3:
0610: case 0xa4:
0611: case 0xa5:
0612: case 0xa6:
0613: case 0xa7:
0614: case 0xa8:
0615: case 0xa9:
0616: case 0xaa:
0617: case 0xab:
0618: case 0xac:
0619: case 0xad:
0620: case 0xae:
0621: case 0xaf:
0622:
0623: case 0xb0:
0624: case 0xb1:
0625: case 0xb2:
0626: case 0xb3:
0627: case 0xb4:
0628: case 0xb5:
0629: case 0xb6:
0630: case 0xb7:
0631: case 0xb8:
0632: case 0xb9:
0633: case 0xba:
0634: case 0xbb:
0635: case 0xbc:
0636: case 0xbd:
0637: case 0xbe:
0638: case 0xbf:
0639: return tag != INT_ZERO;
0640:
0641: // INT_BYTE = 0
0642: case 0xc8:
0643: return read() != 0;
0644:
0645: // INT_BYTE != 0
0646: case 0xc0:
0647: case 0xc1:
0648: case 0xc2:
0649: case 0xc3:
0650: case 0xc4:
0651: case 0xc5:
0652: case 0xc6:
0653: case 0xc7:
0654: case 0xc9:
0655: case 0xca:
0656: case 0xcb:
0657: case 0xcc:
0658: case 0xcd:
0659: case 0xce:
0660: case 0xcf:
0661: read();
0662: return true;
0663:
0664: // INT_SHORT = 0
0665: case 0xd4:
0666: return (256 * read() + read()) != 0;
0667:
0668: // INT_SHORT != 0
0669: case 0xd0:
0670: case 0xd1:
0671: case 0xd2:
0672: case 0xd3:
0673: case 0xd5:
0674: case 0xd6:
0675: case 0xd7:
0676: read();
0677: read();
0678: return true;
0679:
0680: case 'I':
0681: return parseInt() != 0;
0682:
0683: case 0xd8:
0684: case 0xd9:
0685: case 0xda:
0686: case 0xdb:
0687: case 0xdc:
0688: case 0xdd:
0689: case 0xde:
0690: case 0xdf:
0691:
0692: case 0xe0:
0693: case 0xe1:
0694: case 0xe2:
0695: case 0xe3:
0696: case 0xe4:
0697: case 0xe5:
0698: case 0xe6:
0699: case 0xe7:
0700: case 0xe8:
0701: case 0xe9:
0702: case 0xea:
0703: case 0xeb:
0704: case 0xec:
0705: case 0xed:
0706: case 0xee:
0707: case 0xef:
0708: return tag != LONG_ZERO;
0709:
0710: // LONG_BYTE = 0
0711: case 0xf8:
0712: return read() != 0;
0713:
0714: // LONG_BYTE != 0
0715: case 0xf0:
0716: case 0xf1:
0717: case 0xf2:
0718: case 0xf3:
0719: case 0xf4:
0720: case 0xf5:
0721: case 0xf6:
0722: case 0xf7:
0723: case 0xf9:
0724: case 0xfa:
0725: case 0xfb:
0726: case 0xfc:
0727: case 0xfd:
0728: case 0xfe:
0729: case 0xff:
0730: read();
0731: return true;
0732:
0733: // INT_SHORT = 0
0734: case 0x3c:
0735: return (256 * read() + read()) != 0;
0736:
0737: // INT_SHORT != 0
0738: case 0x38:
0739: case 0x39:
0740: case 0x3a:
0741: case 0x3b:
0742: case 0x3d:
0743: case 0x3e:
0744: case 0x3f:
0745: read();
0746: read();
0747: return true;
0748:
0749: case LONG_INT:
0750: return (0x1000000L * read() + 0x10000L * read() + 0x100
0751: * read() + read()) != 0;
0752:
0753: case 'L':
0754: return parseLong() != 0;
0755:
0756: case DOUBLE_ZERO:
0757: return false;
0758:
0759: case DOUBLE_ONE:
0760: return true;
0761:
0762: case DOUBLE_BYTE:
0763: return read() != 0;
0764:
0765: case DOUBLE_SHORT:
0766: return (0x100 * read() + read()) != 0;
0767:
0768: case DOUBLE_FLOAT: {
0769: int f = parseInt();
0770:
0771: return Float.intBitsToFloat(f) != 0;
0772: }
0773:
0774: case 'D':
0775: return parseDouble() != 0.0;
0776:
0777: case 'N':
0778: return false;
0779:
0780: default:
0781: throw expect("boolean", tag);
0782: }
0783: }
0784:
0785: /**
0786: * Reads a short
0787: *
0788: * <pre>
0789: * I b32 b24 b16 b8
0790: * </pre>
0791: */
0792: public short readShort() throws IOException {
0793: return (short) readInt();
0794: }
0795:
0796: /**
0797: * Reads an integer
0798: *
0799: * <pre>
0800: * I b32 b24 b16 b8
0801: * </pre>
0802: */
0803: public final int readInt() throws IOException {
0804: //int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
0805: int tag = read();
0806:
0807: switch (tag) {
0808: case 'N':
0809: return 0;
0810:
0811: case 'F':
0812: return 0;
0813:
0814: case 'T':
0815: return 1;
0816:
0817: // direct integer
0818: case 0x80:
0819: case 0x81:
0820: case 0x82:
0821: case 0x83:
0822: case 0x84:
0823: case 0x85:
0824: case 0x86:
0825: case 0x87:
0826: case 0x88:
0827: case 0x89:
0828: case 0x8a:
0829: case 0x8b:
0830: case 0x8c:
0831: case 0x8d:
0832: case 0x8e:
0833: case 0x8f:
0834:
0835: case 0x90:
0836: case 0x91:
0837: case 0x92:
0838: case 0x93:
0839: case 0x94:
0840: case 0x95:
0841: case 0x96:
0842: case 0x97:
0843: case 0x98:
0844: case 0x99:
0845: case 0x9a:
0846: case 0x9b:
0847: case 0x9c:
0848: case 0x9d:
0849: case 0x9e:
0850: case 0x9f:
0851:
0852: case 0xa0:
0853: case 0xa1:
0854: case 0xa2:
0855: case 0xa3:
0856: case 0xa4:
0857: case 0xa5:
0858: case 0xa6:
0859: case 0xa7:
0860: case 0xa8:
0861: case 0xa9:
0862: case 0xaa:
0863: case 0xab:
0864: case 0xac:
0865: case 0xad:
0866: case 0xae:
0867: case 0xaf:
0868:
0869: case 0xb0:
0870: case 0xb1:
0871: case 0xb2:
0872: case 0xb3:
0873: case 0xb4:
0874: case 0xb5:
0875: case 0xb6:
0876: case 0xb7:
0877: case 0xb8:
0878: case 0xb9:
0879: case 0xba:
0880: case 0xbb:
0881: case 0xbc:
0882: case 0xbd:
0883: case 0xbe:
0884: case 0xbf:
0885: return tag - INT_ZERO;
0886:
0887: /* byte int */
0888: case 0xc0:
0889: case 0xc1:
0890: case 0xc2:
0891: case 0xc3:
0892: case 0xc4:
0893: case 0xc5:
0894: case 0xc6:
0895: case 0xc7:
0896: case 0xc8:
0897: case 0xc9:
0898: case 0xca:
0899: case 0xcb:
0900: case 0xcc:
0901: case 0xcd:
0902: case 0xce:
0903: case 0xcf:
0904: return ((tag - INT_BYTE_ZERO) << 8) + read();
0905:
0906: /* short int */
0907: case 0xd0:
0908: case 0xd1:
0909: case 0xd2:
0910: case 0xd3:
0911: case 0xd4:
0912: case 0xd5:
0913: case 0xd6:
0914: case 0xd7:
0915: return ((tag - INT_SHORT_ZERO) << 16) + 256 * read()
0916: + read();
0917:
0918: case 'I':
0919: case LONG_INT:
0920: return ((read() << 24) + (read() << 16) + (read() << 8) + read());
0921:
0922: // direct long
0923: case 0xd8:
0924: case 0xd9:
0925: case 0xda:
0926: case 0xdb:
0927: case 0xdc:
0928: case 0xdd:
0929: case 0xde:
0930: case 0xdf:
0931:
0932: case 0xe0:
0933: case 0xe1:
0934: case 0xe2:
0935: case 0xe3:
0936: case 0xe4:
0937: case 0xe5:
0938: case 0xe6:
0939: case 0xe7:
0940: case 0xe8:
0941: case 0xe9:
0942: case 0xea:
0943: case 0xeb:
0944: case 0xec:
0945: case 0xed:
0946: case 0xee:
0947: case 0xef:
0948: return tag - LONG_ZERO;
0949:
0950: /* byte long */
0951: case 0xf0:
0952: case 0xf1:
0953: case 0xf2:
0954: case 0xf3:
0955: case 0xf4:
0956: case 0xf5:
0957: case 0xf6:
0958: case 0xf7:
0959: case 0xf8:
0960: case 0xf9:
0961: case 0xfa:
0962: case 0xfb:
0963: case 0xfc:
0964: case 0xfd:
0965: case 0xfe:
0966: case 0xff:
0967: return ((tag - LONG_BYTE_ZERO) << 8) + read();
0968:
0969: /* short long */
0970: case 0x38:
0971: case 0x39:
0972: case 0x3a:
0973: case 0x3b:
0974: case 0x3c:
0975: case 0x3d:
0976: case 0x3e:
0977: case 0x3f:
0978: return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read()
0979: + read();
0980:
0981: case 'L':
0982: return (int) parseLong();
0983:
0984: case DOUBLE_ZERO:
0985: return 0;
0986:
0987: case DOUBLE_ONE:
0988: return 1;
0989:
0990: //case LONG_BYTE:
0991: case DOUBLE_BYTE:
0992: return (byte) (_offset < _length ? _buffer[_offset++]
0993: : read());
0994:
0995: //case INT_SHORT:
0996: //case LONG_SHORT:
0997: case DOUBLE_SHORT:
0998: return (short) (256 * read() + read());
0999:
1000: case DOUBLE_FLOAT: {
1001: int f = parseInt();
1002:
1003: return (int) Float.intBitsToFloat(f);
1004: }
1005:
1006: case 'D':
1007: return (int) parseDouble();
1008:
1009: default:
1010: throw expect("integer", tag);
1011: }
1012: }
1013:
1014: /**
1015: * Reads a long
1016: *
1017: * <pre>
1018: * L b64 b56 b48 b40 b32 b24 b16 b8
1019: * </pre>
1020: */
1021: public long readLong() throws IOException {
1022: int tag = read();
1023:
1024: switch (tag) {
1025: case 'N':
1026: return 0;
1027:
1028: case 'F':
1029: return 0;
1030:
1031: case 'T':
1032: return 1;
1033:
1034: // direct integer
1035: case 0x80:
1036: case 0x81:
1037: case 0x82:
1038: case 0x83:
1039: case 0x84:
1040: case 0x85:
1041: case 0x86:
1042: case 0x87:
1043: case 0x88:
1044: case 0x89:
1045: case 0x8a:
1046: case 0x8b:
1047: case 0x8c:
1048: case 0x8d:
1049: case 0x8e:
1050: case 0x8f:
1051:
1052: case 0x90:
1053: case 0x91:
1054: case 0x92:
1055: case 0x93:
1056: case 0x94:
1057: case 0x95:
1058: case 0x96:
1059: case 0x97:
1060: case 0x98:
1061: case 0x99:
1062: case 0x9a:
1063: case 0x9b:
1064: case 0x9c:
1065: case 0x9d:
1066: case 0x9e:
1067: case 0x9f:
1068:
1069: case 0xa0:
1070: case 0xa1:
1071: case 0xa2:
1072: case 0xa3:
1073: case 0xa4:
1074: case 0xa5:
1075: case 0xa6:
1076: case 0xa7:
1077: case 0xa8:
1078: case 0xa9:
1079: case 0xaa:
1080: case 0xab:
1081: case 0xac:
1082: case 0xad:
1083: case 0xae:
1084: case 0xaf:
1085:
1086: case 0xb0:
1087: case 0xb1:
1088: case 0xb2:
1089: case 0xb3:
1090: case 0xb4:
1091: case 0xb5:
1092: case 0xb6:
1093: case 0xb7:
1094: case 0xb8:
1095: case 0xb9:
1096: case 0xba:
1097: case 0xbb:
1098: case 0xbc:
1099: case 0xbd:
1100: case 0xbe:
1101: case 0xbf:
1102: return tag - INT_ZERO;
1103:
1104: /* byte int */
1105: case 0xc0:
1106: case 0xc1:
1107: case 0xc2:
1108: case 0xc3:
1109: case 0xc4:
1110: case 0xc5:
1111: case 0xc6:
1112: case 0xc7:
1113: case 0xc8:
1114: case 0xc9:
1115: case 0xca:
1116: case 0xcb:
1117: case 0xcc:
1118: case 0xcd:
1119: case 0xce:
1120: case 0xcf:
1121: return ((tag - INT_BYTE_ZERO) << 8) + read();
1122:
1123: /* short int */
1124: case 0xd0:
1125: case 0xd1:
1126: case 0xd2:
1127: case 0xd3:
1128: case 0xd4:
1129: case 0xd5:
1130: case 0xd6:
1131: case 0xd7:
1132: return ((tag - INT_SHORT_ZERO) << 16) + 256 * read()
1133: + read();
1134:
1135: //case LONG_BYTE:
1136: case DOUBLE_BYTE:
1137: return (byte) (_offset < _length ? _buffer[_offset++]
1138: : read());
1139:
1140: //case INT_SHORT:
1141: //case LONG_SHORT:
1142: case DOUBLE_SHORT:
1143: return (short) (256 * read() + read());
1144:
1145: case 'I':
1146: case LONG_INT:
1147: return parseInt();
1148:
1149: // direct long
1150: case 0xd8:
1151: case 0xd9:
1152: case 0xda:
1153: case 0xdb:
1154: case 0xdc:
1155: case 0xdd:
1156: case 0xde:
1157: case 0xdf:
1158:
1159: case 0xe0:
1160: case 0xe1:
1161: case 0xe2:
1162: case 0xe3:
1163: case 0xe4:
1164: case 0xe5:
1165: case 0xe6:
1166: case 0xe7:
1167: case 0xe8:
1168: case 0xe9:
1169: case 0xea:
1170: case 0xeb:
1171: case 0xec:
1172: case 0xed:
1173: case 0xee:
1174: case 0xef:
1175: return tag - LONG_ZERO;
1176:
1177: /* byte long */
1178: case 0xf0:
1179: case 0xf1:
1180: case 0xf2:
1181: case 0xf3:
1182: case 0xf4:
1183: case 0xf5:
1184: case 0xf6:
1185: case 0xf7:
1186: case 0xf8:
1187: case 0xf9:
1188: case 0xfa:
1189: case 0xfb:
1190: case 0xfc:
1191: case 0xfd:
1192: case 0xfe:
1193: case 0xff:
1194: return ((tag - LONG_BYTE_ZERO) << 8) + read();
1195:
1196: /* short long */
1197: case 0x38:
1198: case 0x39:
1199: case 0x3a:
1200: case 0x3b:
1201: case 0x3c:
1202: case 0x3d:
1203: case 0x3e:
1204: case 0x3f:
1205: return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read()
1206: + read();
1207:
1208: case 'L':
1209: return parseLong();
1210:
1211: case DOUBLE_ZERO:
1212: return 0;
1213:
1214: case DOUBLE_ONE:
1215: return 1;
1216:
1217: case DOUBLE_FLOAT: {
1218: int f = parseInt();
1219:
1220: return (long) Float.intBitsToFloat(f);
1221: }
1222:
1223: case 'D':
1224: return (long) parseDouble();
1225:
1226: default:
1227: throw expect("long", tag);
1228: }
1229: }
1230:
1231: /**
1232: * Reads a float
1233: *
1234: * <pre>
1235: * D b64 b56 b48 b40 b32 b24 b16 b8
1236: * </pre>
1237: */
1238: public float readFloat() throws IOException {
1239: return (float) readDouble();
1240: }
1241:
1242: /**
1243: * Reads a double
1244: *
1245: * <pre>
1246: * D b64 b56 b48 b40 b32 b24 b16 b8
1247: * </pre>
1248: */
1249: public double readDouble() throws IOException {
1250: int tag = read();
1251:
1252: switch (tag) {
1253: case 'N':
1254: return 0;
1255:
1256: case 'F':
1257: return 0;
1258:
1259: case 'T':
1260: return 1;
1261:
1262: // direct integer
1263: case 0x80:
1264: case 0x81:
1265: case 0x82:
1266: case 0x83:
1267: case 0x84:
1268: case 0x85:
1269: case 0x86:
1270: case 0x87:
1271: case 0x88:
1272: case 0x89:
1273: case 0x8a:
1274: case 0x8b:
1275: case 0x8c:
1276: case 0x8d:
1277: case 0x8e:
1278: case 0x8f:
1279:
1280: case 0x90:
1281: case 0x91:
1282: case 0x92:
1283: case 0x93:
1284: case 0x94:
1285: case 0x95:
1286: case 0x96:
1287: case 0x97:
1288: case 0x98:
1289: case 0x99:
1290: case 0x9a:
1291: case 0x9b:
1292: case 0x9c:
1293: case 0x9d:
1294: case 0x9e:
1295: case 0x9f:
1296:
1297: case 0xa0:
1298: case 0xa1:
1299: case 0xa2:
1300: case 0xa3:
1301: case 0xa4:
1302: case 0xa5:
1303: case 0xa6:
1304: case 0xa7:
1305: case 0xa8:
1306: case 0xa9:
1307: case 0xaa:
1308: case 0xab:
1309: case 0xac:
1310: case 0xad:
1311: case 0xae:
1312: case 0xaf:
1313:
1314: case 0xb0:
1315: case 0xb1:
1316: case 0xb2:
1317: case 0xb3:
1318: case 0xb4:
1319: case 0xb5:
1320: case 0xb6:
1321: case 0xb7:
1322: case 0xb8:
1323: case 0xb9:
1324: case 0xba:
1325: case 0xbb:
1326: case 0xbc:
1327: case 0xbd:
1328: case 0xbe:
1329: case 0xbf:
1330: return tag - 0x90;
1331:
1332: /* byte int */
1333: case 0xc0:
1334: case 0xc1:
1335: case 0xc2:
1336: case 0xc3:
1337: case 0xc4:
1338: case 0xc5:
1339: case 0xc6:
1340: case 0xc7:
1341: case 0xc8:
1342: case 0xc9:
1343: case 0xca:
1344: case 0xcb:
1345: case 0xcc:
1346: case 0xcd:
1347: case 0xce:
1348: case 0xcf:
1349: return ((tag - INT_BYTE_ZERO) << 8) + read();
1350:
1351: /* short int */
1352: case 0xd0:
1353: case 0xd1:
1354: case 0xd2:
1355: case 0xd3:
1356: case 0xd4:
1357: case 0xd5:
1358: case 0xd6:
1359: case 0xd7:
1360: return ((tag - INT_SHORT_ZERO) << 16) + 256 * read()
1361: + read();
1362:
1363: case 'I':
1364: case LONG_INT:
1365: return parseInt();
1366:
1367: // direct long
1368: case 0xd8:
1369: case 0xd9:
1370: case 0xda:
1371: case 0xdb:
1372: case 0xdc:
1373: case 0xdd:
1374: case 0xde:
1375: case 0xdf:
1376:
1377: case 0xe0:
1378: case 0xe1:
1379: case 0xe2:
1380: case 0xe3:
1381: case 0xe4:
1382: case 0xe5:
1383: case 0xe6:
1384: case 0xe7:
1385: case 0xe8:
1386: case 0xe9:
1387: case 0xea:
1388: case 0xeb:
1389: case 0xec:
1390: case 0xed:
1391: case 0xee:
1392: case 0xef:
1393: return tag - LONG_ZERO;
1394:
1395: /* byte long */
1396: case 0xf0:
1397: case 0xf1:
1398: case 0xf2:
1399: case 0xf3:
1400: case 0xf4:
1401: case 0xf5:
1402: case 0xf6:
1403: case 0xf7:
1404: case 0xf8:
1405: case 0xf9:
1406: case 0xfa:
1407: case 0xfb:
1408: case 0xfc:
1409: case 0xfd:
1410: case 0xfe:
1411: case 0xff:
1412: return ((tag - LONG_BYTE_ZERO) << 8) + read();
1413:
1414: /* short long */
1415: case 0x38:
1416: case 0x39:
1417: case 0x3a:
1418: case 0x3b:
1419: case 0x3c:
1420: case 0x3d:
1421: case 0x3e:
1422: case 0x3f:
1423: return ((tag - LONG_SHORT_ZERO) << 16) + 256 * read()
1424: + read();
1425:
1426: case 'L':
1427: return (double) parseLong();
1428:
1429: case DOUBLE_ZERO:
1430: return 0;
1431:
1432: case DOUBLE_ONE:
1433: return 1;
1434:
1435: case DOUBLE_BYTE:
1436: return (byte) (_offset < _length ? _buffer[_offset++]
1437: : read());
1438:
1439: case DOUBLE_SHORT:
1440: return (short) (256 * read() + read());
1441:
1442: case DOUBLE_FLOAT: {
1443: int f = parseInt();
1444:
1445: return Float.intBitsToFloat(f);
1446: }
1447:
1448: case 'D':
1449: return parseDouble();
1450:
1451: default:
1452: throw expect("double", tag);
1453: }
1454: }
1455:
1456: /**
1457: * Reads a date.
1458: *
1459: * <pre>
1460: * T b64 b56 b48 b40 b32 b24 b16 b8
1461: * </pre>
1462: */
1463: public long readUTCDate() throws IOException {
1464: int tag = read();
1465:
1466: if (tag != 'd')
1467: throw expect("date", tag);
1468:
1469: long b64 = read();
1470: long b56 = read();
1471: long b48 = read();
1472: long b40 = read();
1473: long b32 = read();
1474: long b24 = read();
1475: long b16 = read();
1476: long b8 = read();
1477:
1478: return ((b64 << 56) + (b56 << 48) + (b48 << 40) + (b40 << 32)
1479: + (b32 << 24) + (b24 << 16) + (b16 << 8) + b8);
1480: }
1481:
1482: /**
1483: * Reads a byte from the stream.
1484: */
1485: public int readChar() throws IOException {
1486: if (_chunkLength > 0) {
1487: _chunkLength--;
1488: if (_chunkLength == 0 && _isLastChunk)
1489: _chunkLength = END_OF_DATA;
1490:
1491: int ch = parseUTF8Char();
1492: return ch;
1493: } else if (_chunkLength == END_OF_DATA) {
1494: _chunkLength = 0;
1495: return -1;
1496: }
1497:
1498: int tag = read();
1499:
1500: switch (tag) {
1501: case 'N':
1502: return -1;
1503:
1504: case 'S':
1505: case 's':
1506: case 'X':
1507: case 'x':
1508: _isLastChunk = tag == 'S' || tag == 'X';
1509: _chunkLength = (read() << 8) + read();
1510:
1511: _chunkLength--;
1512: int value = parseUTF8Char();
1513:
1514: // special code so successive read byte won't
1515: // be read as a single object.
1516: if (_chunkLength == 0 && _isLastChunk)
1517: _chunkLength = END_OF_DATA;
1518:
1519: return value;
1520:
1521: default:
1522: throw expect("char", tag);
1523: }
1524: }
1525:
1526: /**
1527: * Reads a byte array from the stream.
1528: */
1529: public int readString(char[] buffer, int offset, int length)
1530: throws IOException {
1531: int readLength = 0;
1532:
1533: if (_chunkLength == END_OF_DATA) {
1534: _chunkLength = 0;
1535: return -1;
1536: } else if (_chunkLength == 0) {
1537: int tag = read();
1538:
1539: switch (tag) {
1540: case 'N':
1541: return -1;
1542:
1543: case 'S':
1544: case 's':
1545: case 'X':
1546: case 'x':
1547: _isLastChunk = tag == 'S' || tag == 'X';
1548: _chunkLength = (read() << 8) + read();
1549: break;
1550:
1551: case 0x00:
1552: case 0x01:
1553: case 0x02:
1554: case 0x03:
1555: case 0x04:
1556: case 0x05:
1557: case 0x06:
1558: case 0x07:
1559: case 0x08:
1560: case 0x09:
1561: case 0x0a:
1562: case 0x0b:
1563: case 0x0c:
1564: case 0x0d:
1565: case 0x0e:
1566: case 0x0f:
1567:
1568: case 0x10:
1569: case 0x11:
1570: case 0x12:
1571: case 0x13:
1572: case 0x14:
1573: case 0x15:
1574: case 0x16:
1575: case 0x17:
1576: case 0x18:
1577: case 0x19:
1578: case 0x1a:
1579: case 0x1b:
1580: case 0x1c:
1581: case 0x1d:
1582: case 0x1e:
1583: case 0x1f:
1584: _isLastChunk = true;
1585: _chunkLength = tag - 0x00;
1586: break;
1587:
1588: default:
1589: throw expect("string", tag);
1590: }
1591: }
1592:
1593: while (length > 0) {
1594: if (_chunkLength > 0) {
1595: buffer[offset++] = (char) parseUTF8Char();
1596: _chunkLength--;
1597: length--;
1598: readLength++;
1599: } else if (_isLastChunk) {
1600: if (readLength == 0)
1601: return -1;
1602: else {
1603: _chunkLength = END_OF_DATA;
1604: return readLength;
1605: }
1606: } else {
1607: int tag = read();
1608:
1609: switch (tag) {
1610: case 'S':
1611: case 's':
1612: case 'X':
1613: case 'x':
1614: _isLastChunk = tag == 'S' || tag == 'X';
1615: _chunkLength = (read() << 8) + read();
1616: break;
1617:
1618: default:
1619: throw expect("string", tag);
1620: }
1621: }
1622: }
1623:
1624: if (readLength == 0)
1625: return -1;
1626: else if (_chunkLength > 0 || !_isLastChunk)
1627: return readLength;
1628: else {
1629: _chunkLength = END_OF_DATA;
1630: return readLength;
1631: }
1632: }
1633:
1634: /**
1635: * Reads a string
1636: *
1637: * <pre>
1638: * S b16 b8 string value
1639: * </pre>
1640: */
1641: public String readString() throws IOException {
1642: int tag = read();
1643:
1644: switch (tag) {
1645: case 'N':
1646: return null;
1647: case 'T':
1648: return "true";
1649: case 'F':
1650: return "false";
1651:
1652: // direct integer
1653: case 0x80:
1654: case 0x81:
1655: case 0x82:
1656: case 0x83:
1657: case 0x84:
1658: case 0x85:
1659: case 0x86:
1660: case 0x87:
1661: case 0x88:
1662: case 0x89:
1663: case 0x8a:
1664: case 0x8b:
1665: case 0x8c:
1666: case 0x8d:
1667: case 0x8e:
1668: case 0x8f:
1669:
1670: case 0x90:
1671: case 0x91:
1672: case 0x92:
1673: case 0x93:
1674: case 0x94:
1675: case 0x95:
1676: case 0x96:
1677: case 0x97:
1678: case 0x98:
1679: case 0x99:
1680: case 0x9a:
1681: case 0x9b:
1682: case 0x9c:
1683: case 0x9d:
1684: case 0x9e:
1685: case 0x9f:
1686:
1687: case 0xa0:
1688: case 0xa1:
1689: case 0xa2:
1690: case 0xa3:
1691: case 0xa4:
1692: case 0xa5:
1693: case 0xa6:
1694: case 0xa7:
1695: case 0xa8:
1696: case 0xa9:
1697: case 0xaa:
1698: case 0xab:
1699: case 0xac:
1700: case 0xad:
1701: case 0xae:
1702: case 0xaf:
1703:
1704: case 0xb0:
1705: case 0xb1:
1706: case 0xb2:
1707: case 0xb3:
1708: case 0xb4:
1709: case 0xb5:
1710: case 0xb6:
1711: case 0xb7:
1712: case 0xb8:
1713: case 0xb9:
1714: case 0xba:
1715: case 0xbb:
1716: case 0xbc:
1717: case 0xbd:
1718: case 0xbe:
1719: case 0xbf:
1720: return String.valueOf((tag - 0x90));
1721:
1722: /* byte int */
1723: case 0xc0:
1724: case 0xc1:
1725: case 0xc2:
1726: case 0xc3:
1727: case 0xc4:
1728: case 0xc5:
1729: case 0xc6:
1730: case 0xc7:
1731: case 0xc8:
1732: case 0xc9:
1733: case 0xca:
1734: case 0xcb:
1735: case 0xcc:
1736: case 0xcd:
1737: case 0xce:
1738: case 0xcf:
1739: return String
1740: .valueOf(((tag - INT_BYTE_ZERO) << 8) + read());
1741:
1742: /* short int */
1743: case 0xd0:
1744: case 0xd1:
1745: case 0xd2:
1746: case 0xd3:
1747: case 0xd4:
1748: case 0xd5:
1749: case 0xd6:
1750: case 0xd7:
1751: return String.valueOf(((tag - INT_SHORT_ZERO) << 16) + 256
1752: * read() + read());
1753:
1754: case 'I':
1755: case LONG_INT:
1756: return String.valueOf(parseInt());
1757:
1758: // direct long
1759: case 0xd8:
1760: case 0xd9:
1761: case 0xda:
1762: case 0xdb:
1763: case 0xdc:
1764: case 0xdd:
1765: case 0xde:
1766: case 0xdf:
1767:
1768: case 0xe0:
1769: case 0xe1:
1770: case 0xe2:
1771: case 0xe3:
1772: case 0xe4:
1773: case 0xe5:
1774: case 0xe6:
1775: case 0xe7:
1776: case 0xe8:
1777: case 0xe9:
1778: case 0xea:
1779: case 0xeb:
1780: case 0xec:
1781: case 0xed:
1782: case 0xee:
1783: case 0xef:
1784: return String.valueOf(tag - LONG_ZERO);
1785:
1786: /* byte long */
1787: case 0xf0:
1788: case 0xf1:
1789: case 0xf2:
1790: case 0xf3:
1791: case 0xf4:
1792: case 0xf5:
1793: case 0xf6:
1794: case 0xf7:
1795: case 0xf8:
1796: case 0xf9:
1797: case 0xfa:
1798: case 0xfb:
1799: case 0xfc:
1800: case 0xfd:
1801: case 0xfe:
1802: case 0xff:
1803: return String.valueOf(((tag - LONG_BYTE_ZERO) << 8)
1804: + read());
1805:
1806: /* short long */
1807: case 0x38:
1808: case 0x39:
1809: case 0x3a:
1810: case 0x3b:
1811: case 0x3c:
1812: case 0x3d:
1813: case 0x3e:
1814: case 0x3f:
1815: return String.valueOf(((tag - LONG_SHORT_ZERO) << 16) + 256
1816: * read() + read());
1817:
1818: case 'L':
1819: return String.valueOf(parseLong());
1820:
1821: case DOUBLE_ZERO:
1822: return "0.0";
1823:
1824: case DOUBLE_ONE:
1825: return "1.0";
1826:
1827: case DOUBLE_BYTE:
1828: return String
1829: .valueOf((byte) (_offset < _length ? _buffer[_offset++]
1830: : read()));
1831:
1832: case DOUBLE_SHORT:
1833: return String.valueOf(((short) (256 * read() + read())));
1834:
1835: case DOUBLE_FLOAT: {
1836: int f = parseInt();
1837:
1838: return String.valueOf(Float.intBitsToFloat(f));
1839: }
1840:
1841: case 'D':
1842: return String.valueOf(parseDouble());
1843:
1844: case 'S':
1845: case 's':
1846: case 'X':
1847: case 'x':
1848: _isLastChunk = tag == 'S' || tag == 'X';
1849: _chunkLength = (read() << 8) + read();
1850:
1851: _sbuf.setLength(0);
1852: int ch;
1853:
1854: while ((ch = parseChar()) >= 0)
1855: _sbuf.append((char) ch);
1856:
1857: return _sbuf.toString();
1858:
1859: // 0-byte string
1860: case 0x00:
1861: case 0x01:
1862: case 0x02:
1863: case 0x03:
1864: case 0x04:
1865: case 0x05:
1866: case 0x06:
1867: case 0x07:
1868: case 0x08:
1869: case 0x09:
1870: case 0x0a:
1871: case 0x0b:
1872: case 0x0c:
1873: case 0x0d:
1874: case 0x0e:
1875: case 0x0f:
1876:
1877: case 0x10:
1878: case 0x11:
1879: case 0x12:
1880: case 0x13:
1881: case 0x14:
1882: case 0x15:
1883: case 0x16:
1884: case 0x17:
1885: case 0x18:
1886: case 0x19:
1887: case 0x1a:
1888: case 0x1b:
1889: case 0x1c:
1890: case 0x1d:
1891: case 0x1e:
1892: case 0x1f:
1893: _isLastChunk = true;
1894: _chunkLength = tag - 0x00;
1895:
1896: _sbuf.setLength(0);
1897:
1898: while ((ch = parseChar()) >= 0)
1899: _sbuf.append((char) ch);
1900:
1901: return _sbuf.toString();
1902:
1903: default:
1904: throw expect("string", tag);
1905: }
1906: }
1907:
1908: /**
1909: * Reads an XML node.
1910: *
1911: * <pre>
1912: * S b16 b8 string value
1913: * </pre>
1914: */
1915: public org.w3c.dom.Node readNode() throws IOException {
1916: int tag = read();
1917:
1918: switch (tag) {
1919: case 'N':
1920: return null;
1921:
1922: case 'S':
1923: case 's':
1924: case 'X':
1925: case 'x':
1926: _isLastChunk = tag == 'S' || tag == 'X';
1927: _chunkLength = (read() << 8) + read();
1928:
1929: throw error("XML is not supported");
1930:
1931: case 0x00:
1932: case 0x01:
1933: case 0x02:
1934: case 0x03:
1935: case 0x04:
1936: case 0x05:
1937: case 0x06:
1938: case 0x07:
1939: case 0x08:
1940: case 0x09:
1941: case 0x0a:
1942: case 0x0b:
1943: case 0x0c:
1944: case 0x0d:
1945: case 0x0e:
1946: case 0x0f:
1947:
1948: case 0x10:
1949: case 0x11:
1950: case 0x12:
1951: case 0x13:
1952: case 0x14:
1953: case 0x15:
1954: case 0x16:
1955: case 0x17:
1956: case 0x18:
1957: case 0x19:
1958: case 0x1a:
1959: case 0x1b:
1960: case 0x1c:
1961: case 0x1d:
1962: case 0x1e:
1963: case 0x1f:
1964: _isLastChunk = true;
1965: _chunkLength = tag - 0x00;
1966:
1967: throw error("XML is not supported");
1968:
1969: default:
1970: throw expect("string", tag);
1971: }
1972: }
1973:
1974: /**
1975: * Reads a byte array
1976: *
1977: * <pre>
1978: * B b16 b8 data value
1979: * </pre>
1980: */
1981: public byte[] readBytes() throws IOException {
1982: int tag = read();
1983:
1984: switch (tag) {
1985: case 'N':
1986: return null;
1987:
1988: case 'B':
1989: case 'b':
1990: _isLastChunk = tag == 'B';
1991: _chunkLength = (read() << 8) + read();
1992:
1993: ByteArrayOutputStream bos = new ByteArrayOutputStream();
1994:
1995: int data;
1996: while ((data = parseByte()) >= 0)
1997: bos.write(data);
1998:
1999: return bos.toByteArray();
2000:
2001: case 0x20:
2002: case 0x21:
2003: case 0x22:
2004: case 0x23:
2005: case 0x24:
2006: case 0x25:
2007: case 0x26:
2008: case 0x27:
2009: case 0x28:
2010: case 0x29:
2011: case 0x2a:
2012: case 0x2b:
2013: case 0x2c:
2014: case 0x2d:
2015: case 0x2e:
2016: case 0x2f:
2017: _isLastChunk = true;
2018: _chunkLength = tag - 0x20;
2019:
2020: bos = new ByteArrayOutputStream();
2021:
2022: while ((data = parseByte()) >= 0)
2023: bos.write(data);
2024:
2025: return bos.toByteArray();
2026:
2027: default:
2028: throw expect("bytes", tag);
2029: }
2030: }
2031:
2032: /**
2033: * Reads a byte from the stream.
2034: */
2035: public int readByte() throws IOException {
2036: if (_chunkLength > 0) {
2037: _chunkLength--;
2038: if (_chunkLength == 0 && _isLastChunk)
2039: _chunkLength = END_OF_DATA;
2040:
2041: return read();
2042: } else if (_chunkLength == END_OF_DATA) {
2043: _chunkLength = 0;
2044: return -1;
2045: }
2046:
2047: int tag = read();
2048:
2049: switch (tag) {
2050: case 'N':
2051: return -1;
2052:
2053: case 'B':
2054: case 'b':
2055: _isLastChunk = tag == 'B';
2056: _chunkLength = (read() << 8) + read();
2057:
2058: int value = parseByte();
2059:
2060: // special code so successive read byte won't
2061: // be read as a single object.
2062: if (_chunkLength == 0 && _isLastChunk)
2063: _chunkLength = END_OF_DATA;
2064:
2065: return value;
2066:
2067: default:
2068: throw expect("binary", tag);
2069: }
2070: }
2071:
2072: /**
2073: * Reads a byte array from the stream.
2074: */
2075: public int readBytes(byte[] buffer, int offset, int length)
2076: throws IOException {
2077: int readLength = 0;
2078:
2079: if (_chunkLength == END_OF_DATA) {
2080: _chunkLength = 0;
2081: return -1;
2082: } else if (_chunkLength == 0) {
2083: int tag = read();
2084:
2085: switch (tag) {
2086: case 'N':
2087: return -1;
2088:
2089: case 'B':
2090: case 'b':
2091: _isLastChunk = tag == 'B';
2092: _chunkLength = (read() << 8) + read();
2093: break;
2094:
2095: default:
2096: throw expect("binary", tag);
2097: }
2098: }
2099:
2100: while (length > 0) {
2101: if (_chunkLength > 0) {
2102: buffer[offset++] = (byte) read();
2103: _chunkLength--;
2104: length--;
2105: readLength++;
2106: } else if (_isLastChunk) {
2107: if (readLength == 0)
2108: return -1;
2109: else {
2110: _chunkLength = END_OF_DATA;
2111: return readLength;
2112: }
2113: } else {
2114: int tag = read();
2115:
2116: switch (tag) {
2117: case 'B':
2118: case 'b':
2119: _isLastChunk = tag == 'B';
2120: _chunkLength = (read() << 8) + read();
2121: break;
2122:
2123: default:
2124: throw expect("binary", tag);
2125: }
2126: }
2127: }
2128:
2129: if (readLength == 0)
2130: return -1;
2131: else if (_chunkLength > 0 || !_isLastChunk)
2132: return readLength;
2133: else {
2134: _chunkLength = END_OF_DATA;
2135: return readLength;
2136: }
2137: }
2138:
2139: /**
2140: * Reads a fault.
2141: */
2142: private HashMap readFault() throws IOException {
2143: HashMap map = new HashMap();
2144:
2145: int code = read();
2146: for (; code > 0 && code != 'z'; code = read()) {
2147: _offset--;
2148:
2149: Object key = readObject();
2150: Object value = readObject();
2151:
2152: if (key != null && value != null)
2153: map.put(key, value);
2154: }
2155:
2156: if (code != 'z')
2157: throw expect("fault", code);
2158:
2159: return map;
2160: }
2161:
2162: /**
2163: * Reads an object from the input stream with an expected type.
2164: */
2165: public Object readObject(Class cl) throws IOException {
2166: if (cl == null || cl == Object.class)
2167: return readObject();
2168:
2169: int tag = _offset < _length ? (_buffer[_offset++] & 0xff)
2170: : read();
2171:
2172: switch (tag) {
2173: case 'N':
2174: return null;
2175:
2176: case 'M': {
2177: String type = readType();
2178:
2179: // hessian/3bb3
2180: if ("".equals(type)) {
2181: Deserializer reader;
2182: reader = findSerializerFactory().getDeserializer(cl);
2183:
2184: return reader.readMap(this );
2185: } else {
2186: Deserializer reader;
2187: reader = findSerializerFactory().getObjectDeserializer(
2188: type, cl);
2189:
2190: return reader.readMap(this );
2191: }
2192: }
2193:
2194: case 'O': {
2195: readObjectDefinition(cl);
2196:
2197: return readObject(cl);
2198: }
2199:
2200: case 'o': {
2201: int ref = readInt();
2202: int size = _classDefs.size();
2203:
2204: if (ref < 0 || size <= ref)
2205: throw new HessianProtocolException("'" + ref
2206: + "' is an unknown class definition");
2207:
2208: ObjectDefinition def = (ObjectDefinition) _classDefs
2209: .get(ref);
2210:
2211: return readObjectInstance(cl, def);
2212: }
2213:
2214: case 'V': {
2215: String type = readType();
2216: int length = readLength();
2217:
2218: Deserializer reader;
2219: reader = findSerializerFactory().getObjectDeserializer(
2220: type, cl);
2221:
2222: Object v = reader.readList(this , length);
2223:
2224: return v;
2225: }
2226:
2227: case 'v': {
2228: int ref = readInt();
2229: String type = (String) _types.get(ref);
2230: int length = readInt();
2231:
2232: Deserializer reader;
2233: reader = findSerializerFactory().getObjectDeserializer(
2234: type, cl);
2235:
2236: Object v = reader.readLengthList(this , length);
2237:
2238: return v;
2239: }
2240:
2241: case 'R': {
2242: int ref = parseInt();
2243:
2244: return _refs.get(ref);
2245: }
2246:
2247: case 'r': {
2248: String type = readType();
2249: String url = readString();
2250:
2251: return resolveRemote(type, url);
2252: }
2253:
2254: case REF_BYTE: {
2255: int ref = read();
2256:
2257: return _refs.get(ref);
2258: }
2259:
2260: case REF_SHORT: {
2261: int ref = 256 * read() + read();
2262:
2263: return _refs.get(ref);
2264: }
2265: }
2266:
2267: if (tag >= 0)
2268: _offset--;
2269:
2270: // hessian/3b2i vs hessian/3406
2271: // return readObject();
2272:
2273: Object value = findSerializerFactory().getDeserializer(cl)
2274: .readObject(this );
2275: return value;
2276: }
2277:
2278: /**
2279: * Reads an arbitrary object from the input stream when the type
2280: * is unknown.
2281: */
2282: public Object readObject() throws IOException {
2283: int tag = _offset < _length ? (_buffer[_offset++] & 0xff)
2284: : read();
2285:
2286: switch (tag) {
2287: case 'N':
2288: return null;
2289:
2290: case 'T':
2291: return Boolean.valueOf(true);
2292:
2293: case 'F':
2294: return Boolean.valueOf(false);
2295:
2296: // direct integer
2297: case 0x80:
2298: case 0x81:
2299: case 0x82:
2300: case 0x83:
2301: case 0x84:
2302: case 0x85:
2303: case 0x86:
2304: case 0x87:
2305: case 0x88:
2306: case 0x89:
2307: case 0x8a:
2308: case 0x8b:
2309: case 0x8c:
2310: case 0x8d:
2311: case 0x8e:
2312: case 0x8f:
2313:
2314: case 0x90:
2315: case 0x91:
2316: case 0x92:
2317: case 0x93:
2318: case 0x94:
2319: case 0x95:
2320: case 0x96:
2321: case 0x97:
2322: case 0x98:
2323: case 0x99:
2324: case 0x9a:
2325: case 0x9b:
2326: case 0x9c:
2327: case 0x9d:
2328: case 0x9e:
2329: case 0x9f:
2330:
2331: case 0xa0:
2332: case 0xa1:
2333: case 0xa2:
2334: case 0xa3:
2335: case 0xa4:
2336: case 0xa5:
2337: case 0xa6:
2338: case 0xa7:
2339: case 0xa8:
2340: case 0xa9:
2341: case 0xaa:
2342: case 0xab:
2343: case 0xac:
2344: case 0xad:
2345: case 0xae:
2346: case 0xaf:
2347:
2348: case 0xb0:
2349: case 0xb1:
2350: case 0xb2:
2351: case 0xb3:
2352: case 0xb4:
2353: case 0xb5:
2354: case 0xb6:
2355: case 0xb7:
2356: case 0xb8:
2357: case 0xb9:
2358: case 0xba:
2359: case 0xbb:
2360: case 0xbc:
2361: case 0xbd:
2362: case 0xbe:
2363: case 0xbf:
2364: return Integer.valueOf(tag - INT_ZERO);
2365:
2366: /* byte int */
2367: case 0xc0:
2368: case 0xc1:
2369: case 0xc2:
2370: case 0xc3:
2371: case 0xc4:
2372: case 0xc5:
2373: case 0xc6:
2374: case 0xc7:
2375: case 0xc8:
2376: case 0xc9:
2377: case 0xca:
2378: case 0xcb:
2379: case 0xcc:
2380: case 0xcd:
2381: case 0xce:
2382: case 0xcf:
2383: return Integer.valueOf(((tag - INT_BYTE_ZERO) << 8)
2384: + read());
2385:
2386: /* short int */
2387: case 0xd0:
2388: case 0xd1:
2389: case 0xd2:
2390: case 0xd3:
2391: case 0xd4:
2392: case 0xd5:
2393: case 0xd6:
2394: case 0xd7:
2395: return Integer.valueOf(((tag - INT_SHORT_ZERO) << 16) + 256
2396: * read() + read());
2397:
2398: case 'I':
2399: return Integer.valueOf(parseInt());
2400:
2401: // direct long
2402: case 0xd8:
2403: case 0xd9:
2404: case 0xda:
2405: case 0xdb:
2406: case 0xdc:
2407: case 0xdd:
2408: case 0xde:
2409: case 0xdf:
2410:
2411: case 0xe0:
2412: case 0xe1:
2413: case 0xe2:
2414: case 0xe3:
2415: case 0xe4:
2416: case 0xe5:
2417: case 0xe6:
2418: case 0xe7:
2419: case 0xe8:
2420: case 0xe9:
2421: case 0xea:
2422: case 0xeb:
2423: case 0xec:
2424: case 0xed:
2425: case 0xee:
2426: case 0xef:
2427: return Long.valueOf(tag - LONG_ZERO);
2428:
2429: /* byte long */
2430: case 0xf0:
2431: case 0xf1:
2432: case 0xf2:
2433: case 0xf3:
2434: case 0xf4:
2435: case 0xf5:
2436: case 0xf6:
2437: case 0xf7:
2438: case 0xf8:
2439: case 0xf9:
2440: case 0xfa:
2441: case 0xfb:
2442: case 0xfc:
2443: case 0xfd:
2444: case 0xfe:
2445: case 0xff:
2446: return Long.valueOf(((tag - LONG_BYTE_ZERO) << 8) + read());
2447:
2448: /* short long */
2449: case 0x38:
2450: case 0x39:
2451: case 0x3a:
2452: case 0x3b:
2453: case 0x3c:
2454: case 0x3d:
2455: case 0x3e:
2456: case 0x3f:
2457: return Long.valueOf(((tag - LONG_SHORT_ZERO) << 16) + 256
2458: * read() + read());
2459:
2460: case LONG_INT:
2461: return Long.valueOf(parseInt());
2462:
2463: case 'L':
2464: return Long.valueOf(parseLong());
2465:
2466: case DOUBLE_ZERO:
2467: return Double.valueOf(0);
2468:
2469: case DOUBLE_ONE:
2470: return Double.valueOf(1);
2471:
2472: case DOUBLE_BYTE:
2473: return Double.valueOf((byte) read());
2474:
2475: case DOUBLE_SHORT:
2476: return Double.valueOf((short) (256 * read() + read()));
2477:
2478: case DOUBLE_FLOAT: {
2479: int f = parseInt();
2480:
2481: return Double.valueOf(Float.intBitsToFloat(f));
2482: }
2483:
2484: case 'D':
2485: return Double.valueOf(parseDouble());
2486:
2487: case 'd':
2488: return new Date(parseLong());
2489:
2490: case 'x':
2491: case 'X': {
2492: _isLastChunk = tag == 'X';
2493: _chunkLength = (read() << 8) + read();
2494:
2495: return parseXML();
2496: }
2497:
2498: case 's':
2499: case 'S': {
2500: _isLastChunk = tag == 'S';
2501: _chunkLength = (read() << 8) + read();
2502:
2503: int data;
2504: _sbuf.setLength(0);
2505:
2506: while ((data = parseChar()) >= 0)
2507: _sbuf.append((char) data);
2508:
2509: return _sbuf.toString();
2510: }
2511:
2512: case 0x00:
2513: case 0x01:
2514: case 0x02:
2515: case 0x03:
2516: case 0x04:
2517: case 0x05:
2518: case 0x06:
2519: case 0x07:
2520: case 0x08:
2521: case 0x09:
2522: case 0x0a:
2523: case 0x0b:
2524: case 0x0c:
2525: case 0x0d:
2526: case 0x0e:
2527: case 0x0f:
2528:
2529: case 0x10:
2530: case 0x11:
2531: case 0x12:
2532: case 0x13:
2533: case 0x14:
2534: case 0x15:
2535: case 0x16:
2536: case 0x17:
2537: case 0x18:
2538: case 0x19:
2539: case 0x1a:
2540: case 0x1b:
2541: case 0x1c:
2542: case 0x1d:
2543: case 0x1e:
2544: case 0x1f: {
2545: _isLastChunk = true;
2546: _chunkLength = tag - 0x00;
2547:
2548: int data;
2549: _sbuf.setLength(0);
2550:
2551: while ((data = parseChar()) >= 0)
2552: _sbuf.append((char) data);
2553:
2554: return _sbuf.toString();
2555: }
2556:
2557: case 'b':
2558: case 'B': {
2559: _isLastChunk = tag == 'B';
2560: _chunkLength = (read() << 8) + read();
2561:
2562: int data;
2563: ByteArrayOutputStream bos = new ByteArrayOutputStream();
2564:
2565: while ((data = parseByte()) >= 0)
2566: bos.write(data);
2567:
2568: return bos.toByteArray();
2569: }
2570:
2571: case 0x20:
2572: case 0x21:
2573: case 0x22:
2574: case 0x23:
2575: case 0x24:
2576: case 0x25:
2577: case 0x26:
2578: case 0x27:
2579: case 0x28:
2580: case 0x29:
2581: case 0x2a:
2582: case 0x2b:
2583: case 0x2c:
2584: case 0x2d:
2585: case 0x2e:
2586: case 0x2f: {
2587: _isLastChunk = true;
2588: int len = tag - 0x20;
2589: _chunkLength = 0;
2590:
2591: byte[] data = new byte[len];
2592:
2593: for (int i = 0; i < len; i++)
2594: data[i] = (byte) read();
2595:
2596: return data;
2597: }
2598:
2599: case 'V': {
2600: String type = readType();
2601: int length = readLength();
2602:
2603: return findSerializerFactory().readList(this , length, type);
2604: }
2605:
2606: // direct lists
2607: case 'v': {
2608: int ref = readInt();
2609: String type = (String) _types.get(ref);
2610: int length = readInt();
2611:
2612: Deserializer reader;
2613: reader = findSerializerFactory().getObjectDeserializer(
2614: type, null);
2615:
2616: return reader.readLengthList(this , length);
2617: }
2618:
2619: case 'M': {
2620: String type = readType();
2621:
2622: return findSerializerFactory().readMap(this , type);
2623: }
2624:
2625: case 'O': {
2626: readObjectDefinition(null);
2627:
2628: return readObject();
2629: }
2630:
2631: case 'o': {
2632: int ref = readInt();
2633:
2634: ObjectDefinition def = (ObjectDefinition) _classDefs
2635: .get(ref);
2636:
2637: return readObjectInstance(null, def);
2638: }
2639:
2640: case 'R': {
2641: int ref = parseInt();
2642:
2643: return _refs.get(ref);
2644: }
2645:
2646: case REF_BYTE: {
2647: int ref = read();
2648:
2649: return _refs.get(ref);
2650: }
2651:
2652: case REF_SHORT: {
2653: int ref = 256 * read() + read();
2654:
2655: return _refs.get(ref);
2656: }
2657:
2658: case 'r': {
2659: String type = readType();
2660: String url = readString();
2661:
2662: return resolveRemote(type, url);
2663: }
2664:
2665: default:
2666: if (tag < 0)
2667: throw error("readObject: unexpected end of file");
2668: else
2669: throw error("readObject: unknown code " + codeName(tag));
2670: }
2671: }
2672:
2673: /**
2674: * Reads an object definition:
2675: *
2676: * <pre>
2677: * O string <int> (string)* <value>*
2678: * </pre>
2679: */
2680: private void readObjectDefinition(Class cl) throws IOException {
2681: String type = readString();
2682: int len = readInt();
2683:
2684: String[] fieldNames = new String[len];
2685: for (int i = 0; i < len; i++)
2686: fieldNames[i] = readString();
2687:
2688: ObjectDefinition def = new ObjectDefinition(type, fieldNames);
2689:
2690: if (_classDefs == null)
2691: _classDefs = new ArrayList();
2692:
2693: _classDefs.add(def);
2694: }
2695:
2696: private Object readObjectInstance(Class cl, ObjectDefinition def)
2697: throws IOException {
2698: String type = def.getType();
2699: String[] fieldNames = def.getFieldNames();
2700:
2701: if (cl != null) {
2702: Deserializer reader;
2703: reader = findSerializerFactory().getObjectDeserializer(
2704: type, cl);
2705:
2706: return reader.readObject(this , fieldNames);
2707: } else {
2708: return findSerializerFactory().readObject(this , type,
2709: fieldNames);
2710: }
2711: }
2712:
2713: private String readLenString() throws IOException {
2714: int len = readInt();
2715:
2716: _isLastChunk = true;
2717: _chunkLength = len;
2718:
2719: _sbuf.setLength(0);
2720: int ch;
2721: while ((ch = parseChar()) >= 0)
2722: _sbuf.append((char) ch);
2723:
2724: return _sbuf.toString();
2725: }
2726:
2727: private String readLenString(int len) throws IOException {
2728: _isLastChunk = true;
2729: _chunkLength = len;
2730:
2731: _sbuf.setLength(0);
2732: int ch;
2733: while ((ch = parseChar()) >= 0)
2734: _sbuf.append((char) ch);
2735:
2736: return _sbuf.toString();
2737: }
2738:
2739: /**
2740: * Reads a remote object.
2741: */
2742: public Object readRemote() throws IOException {
2743: String type = readType();
2744: String url = readString();
2745:
2746: return resolveRemote(type, url);
2747: }
2748:
2749: /**
2750: * Reads a reference.
2751: */
2752: public Object readRef() throws IOException {
2753: return _refs.get(parseInt());
2754: }
2755:
2756: /**
2757: * Reads the start of a list.
2758: */
2759: public int readListStart() throws IOException {
2760: return read();
2761: }
2762:
2763: /**
2764: * Reads the start of a list.
2765: */
2766: public int readMapStart() throws IOException {
2767: return read();
2768: }
2769:
2770: /**
2771: * Returns true if this is the end of a list or a map.
2772: */
2773: public boolean isEnd() throws IOException {
2774: int code;
2775:
2776: if (_offset < _length)
2777: code = (_buffer[_offset] & 0xff);
2778: else {
2779: code = read();
2780:
2781: if (code >= 0)
2782: _offset--;
2783: }
2784:
2785: return (code < 0 || code == 'z');
2786: }
2787:
2788: /**
2789: * Reads the end byte.
2790: */
2791: public void readEnd() throws IOException {
2792: int code = _offset < _length ? (_buffer[_offset++] & 0xff)
2793: : read();
2794:
2795: if (code == 'z')
2796: return;
2797: else if (code < 0)
2798: throw error("unexpected end of file");
2799: else
2800: throw error("unknown code:" + codeName(code));
2801: }
2802:
2803: /**
2804: * Reads the end byte.
2805: */
2806: public void readMapEnd() throws IOException {
2807: int code = _offset < _length ? (_buffer[_offset++] & 0xff)
2808: : read();
2809:
2810: if (code != 'z')
2811: throw error("expected end of map ('z') at '"
2812: + codeName(code) + "'");
2813: }
2814:
2815: /**
2816: * Reads the end byte.
2817: */
2818: public void readListEnd() throws IOException {
2819: int code = _offset < _length ? (_buffer[_offset++] & 0xff)
2820: : read();
2821:
2822: if (code != 'z')
2823: throw error("expected end of list ('z') at '"
2824: + codeName(code) + "'");
2825: }
2826:
2827: /**
2828: * Adds a list/map reference.
2829: */
2830: public int addRef(Object ref) {
2831: if (_refs == null)
2832: _refs = new ArrayList();
2833:
2834: _refs.add(ref);
2835:
2836: return _refs.size() - 1;
2837: }
2838:
2839: /**
2840: * Adds a list/map reference.
2841: */
2842: public void setRef(int i, Object ref) {
2843: _refs.set(i, ref);
2844: }
2845:
2846: /**
2847: * Resets the references for streaming.
2848: */
2849: public void resetReferences() {
2850: if (_refs != null)
2851: _refs.clear();
2852: }
2853:
2854: public Object readStreamingObject() throws IOException {
2855: if (_refs != null)
2856: _refs.clear();
2857:
2858: return readObject();
2859: }
2860:
2861: /**
2862: * Resolves a remote object.
2863: */
2864: public Object resolveRemote(String type, String url)
2865: throws IOException {
2866: HessianRemoteResolver resolver = getRemoteResolver();
2867:
2868: if (resolver != null)
2869: return resolver.lookup(type, url);
2870: else
2871: return new HessianRemote(type, url);
2872: }
2873:
2874: /**
2875: * Parses a type from the stream.
2876: *
2877: * <pre>
2878: * t b16 b8
2879: * </pre>
2880: */
2881: public String readType() throws IOException {
2882: int code = _offset < _length ? (_buffer[_offset++] & 0xff)
2883: : read();
2884:
2885: switch (code) {
2886: case 't': {
2887: int len = 256 * read() + read();
2888: String type = readLenString(len);
2889:
2890: if (_types == null)
2891: _types = new ArrayList();
2892:
2893: _types.add(type);
2894:
2895: return type;
2896: }
2897:
2898: case 'T': {
2899: int ref = readInt();
2900:
2901: return (String) _types.get(ref);
2902: }
2903:
2904: case TYPE_REF: {
2905: int ref = readInt();
2906:
2907: return (String) _types.get(ref);
2908: }
2909:
2910: default: {
2911: if (code >= 0)
2912: _offset--;
2913:
2914: return "";
2915: }
2916: }
2917: }
2918:
2919: /**
2920: * Parses the length for an array
2921: *
2922: * <pre>
2923: * l b32 b24 b16 b8
2924: * </pre>
2925: */
2926: public int readLength() throws IOException {
2927: int code = read();
2928:
2929: if (code == LENGTH_BYTE)
2930: return read();
2931:
2932: else if (code == 'l')
2933: return parseInt();
2934:
2935: else {
2936: if (code >= 0)
2937: _offset--;
2938:
2939: return -1;
2940: }
2941: }
2942:
2943: /**
2944: * Parses a 32-bit integer value from the stream.
2945: *
2946: * <pre>
2947: * b32 b24 b16 b8
2948: * </pre>
2949: */
2950: private int parseInt() throws IOException {
2951: int offset = _offset;
2952:
2953: if (offset + 3 < _length) {
2954: byte[] buffer = _buffer;
2955:
2956: int b32 = buffer[offset + 0] & 0xff;
2957: int b24 = buffer[offset + 1] & 0xff;
2958: int b16 = buffer[offset + 2] & 0xff;
2959: int b8 = buffer[offset + 3] & 0xff;
2960:
2961: _offset = offset + 4;
2962:
2963: return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8;
2964: } else {
2965: int b32 = read();
2966: int b24 = read();
2967: int b16 = read();
2968: int b8 = read();
2969:
2970: return (b32 << 24) + (b24 << 16) + (b16 << 8) + b8;
2971: }
2972: }
2973:
2974: /**
2975: * Parses a 64-bit long value from the stream.
2976: *
2977: * <pre>
2978: * b64 b56 b48 b40 b32 b24 b16 b8
2979: * </pre>
2980: */
2981: private long parseLong() throws IOException {
2982: long b64 = read();
2983: long b56 = read();
2984: long b48 = read();
2985: long b40 = read();
2986: long b32 = read();
2987: long b24 = read();
2988: long b16 = read();
2989: long b8 = read();
2990:
2991: return ((b64 << 56) + (b56 << 48) + (b48 << 40) + (b40 << 32)
2992: + (b32 << 24) + (b24 << 16) + (b16 << 8) + b8);
2993: }
2994:
2995: /**
2996: * Parses a 64-bit double value from the stream.
2997: *
2998: * <pre>
2999: * b64 b56 b48 b40 b32 b24 b16 b8
3000: * </pre>
3001: */
3002: private double parseDouble() throws IOException {
3003: long bits = parseLong();
3004:
3005: return Double.longBitsToDouble(bits);
3006: }
3007:
3008: org.w3c.dom.Node parseXML() throws IOException {
3009: throw new UnsupportedOperationException();
3010: }
3011:
3012: /**
3013: * Reads a character from the underlying stream.
3014: */
3015: private int parseChar() throws IOException {
3016: while (_chunkLength <= 0) {
3017: if (_isLastChunk)
3018: return -1;
3019:
3020: int code = _offset < _length ? (_buffer[_offset++] & 0xff)
3021: : read();
3022:
3023: switch (code) {
3024: case 's':
3025: case 'x':
3026: _isLastChunk = false;
3027:
3028: _chunkLength = (read() << 8) + read();
3029: break;
3030:
3031: case 'S':
3032: case 'X':
3033: _isLastChunk = true;
3034:
3035: _chunkLength = (read() << 8) + read();
3036: break;
3037:
3038: case 0x00:
3039: case 0x01:
3040: case 0x02:
3041: case 0x03:
3042: case 0x04:
3043: case 0x05:
3044: case 0x06:
3045: case 0x07:
3046: case 0x08:
3047: case 0x09:
3048: case 0x0a:
3049: case 0x0b:
3050: case 0x0c:
3051: case 0x0d:
3052: case 0x0e:
3053: case 0x0f:
3054:
3055: case 0x10:
3056: case 0x11:
3057: case 0x12:
3058: case 0x13:
3059: case 0x14:
3060: case 0x15:
3061: case 0x16:
3062: case 0x17:
3063: case 0x18:
3064: case 0x19:
3065: case 0x1a:
3066: case 0x1b:
3067: case 0x1c:
3068: case 0x1d:
3069: case 0x1e:
3070: case 0x1f:
3071: _isLastChunk = true;
3072: _chunkLength = code - 0x00;
3073: break;
3074:
3075: default:
3076: throw expect("string", code);
3077: }
3078:
3079: }
3080:
3081: _chunkLength--;
3082:
3083: return parseUTF8Char();
3084: }
3085:
3086: /**
3087: * Parses a single UTF8 character.
3088: */
3089: private int parseUTF8Char() throws IOException {
3090: int ch = _offset < _length ? (_buffer[_offset++] & 0xff)
3091: : read();
3092:
3093: if (ch < 0x80)
3094: return ch;
3095: else if ((ch & 0xe0) == 0xc0) {
3096: int ch1 = read();
3097: int v = ((ch & 0x1f) << 6) + (ch1 & 0x3f);
3098:
3099: return v;
3100: } else if ((ch & 0xf0) == 0xe0) {
3101: int ch1 = read();
3102: int ch2 = read();
3103: int v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6)
3104: + (ch2 & 0x3f);
3105:
3106: return v;
3107: } else
3108: throw error("bad utf-8 encoding at " + codeName(ch));
3109: }
3110:
3111: /**
3112: * Reads a byte from the underlying stream.
3113: */
3114: private int parseByte() throws IOException {
3115: while (_chunkLength <= 0) {
3116: if (_isLastChunk) {
3117: return -1;
3118: }
3119:
3120: int code = read();
3121:
3122: switch (code) {
3123: case 'b':
3124: _isLastChunk = false;
3125:
3126: _chunkLength = (read() << 8) + read();
3127: break;
3128:
3129: case 'B':
3130: _isLastChunk = true;
3131:
3132: _chunkLength = (read() << 8) + read();
3133: break;
3134:
3135: case 0x20:
3136: case 0x21:
3137: case 0x22:
3138: case 0x23:
3139: case 0x24:
3140: case 0x25:
3141: case 0x26:
3142: case 0x27:
3143: case 0x28:
3144: case 0x29:
3145: case 0x2a:
3146: case 0x2b:
3147: case 0x2c:
3148: case 0x2d:
3149: case 0x2e:
3150: case 0x2f:
3151: _isLastChunk = true;
3152:
3153: _chunkLength = code - 0x20;
3154: break;
3155:
3156: default:
3157: throw expect("byte[]", code);
3158: }
3159: }
3160:
3161: _chunkLength--;
3162:
3163: return read();
3164: }
3165:
3166: /**
3167: * Reads bytes based on an input stream.
3168: */
3169: public InputStream readInputStream() throws IOException {
3170: int tag = read();
3171:
3172: switch (tag) {
3173: case 'N':
3174: return null;
3175:
3176: case 'B':
3177: case 'b':
3178: _isLastChunk = tag == 'B';
3179: _chunkLength = (read() << 8) + read();
3180: break;
3181:
3182: case 0x20:
3183: case 0x21:
3184: case 0x22:
3185: case 0x23:
3186: case 0x24:
3187: case 0x25:
3188: case 0x26:
3189: case 0x27:
3190: case 0x28:
3191: case 0x29:
3192: case 0x2a:
3193: case 0x2b:
3194: case 0x2c:
3195: case 0x2d:
3196: case 0x2e:
3197: case 0x2f:
3198: _isLastChunk = true;
3199: _chunkLength = tag - 0x20;
3200: break;
3201:
3202: default:
3203: throw expect("binary", tag);
3204: }
3205:
3206: return new ReadInputStream();
3207:
3208: }
3209:
3210: /**
3211: * Reads bytes from the underlying stream.
3212: */
3213: int read(byte[] buffer, int offset, int length) throws IOException {
3214: int readLength = 0;
3215:
3216: while (length > 0) {
3217: while (_chunkLength <= 0) {
3218: if (_isLastChunk)
3219: return readLength == 0 ? -1 : readLength;
3220:
3221: int code = read();
3222:
3223: switch (code) {
3224: case 'b':
3225: _isLastChunk = false;
3226:
3227: _chunkLength = (read() << 8) + read();
3228: break;
3229:
3230: case 'B':
3231: _isLastChunk = true;
3232:
3233: _chunkLength = (read() << 8) + read();
3234: break;
3235:
3236: default:
3237: throw expect("byte[]", code);
3238: }
3239: }
3240:
3241: int sublen = _chunkLength;
3242: if (length < sublen)
3243: sublen = length;
3244:
3245: if (_length <= _offset && !readBuffer())
3246: return -1;
3247:
3248: if (_length - _offset < sublen)
3249: sublen = _length - _offset;
3250:
3251: System.arraycopy(_buffer, _offset, buffer, offset, sublen);
3252:
3253: _offset += sublen;
3254:
3255: offset += sublen;
3256: readLength += sublen;
3257: length -= sublen;
3258: _chunkLength -= sublen;
3259: }
3260:
3261: return readLength;
3262: }
3263:
3264: /**
3265: * Normally, shouldn't be called externally, but needed for QA, e.g.
3266: * ejb/3b01.
3267: */
3268: public final int read() throws IOException {
3269: if (_length <= _offset && !readBuffer())
3270: return -1;
3271:
3272: return _buffer[_offset++] & 0xff;
3273: }
3274:
3275: private final boolean readBuffer() throws IOException {
3276: byte[] buffer = _buffer;
3277: int offset = _offset;
3278: int length = _length;
3279:
3280: if (offset < length) {
3281: System
3282: .arraycopy(buffer, offset, buffer, 0, length
3283: - offset);
3284: offset = length - offset;
3285: } else
3286: offset = 0;
3287:
3288: int len = _is.read(buffer, offset, SIZE - offset);
3289:
3290: if (len <= 0) {
3291: _length = offset;
3292: _offset = 0;
3293:
3294: return offset > 0;
3295: }
3296:
3297: _length = offset + len;
3298: _offset = 0;
3299:
3300: return true;
3301: }
3302:
3303: public Reader getReader() {
3304: return null;
3305: }
3306:
3307: protected IOException expect(String expect, int ch)
3308: throws IOException {
3309: if (ch < 0)
3310: return error("expected " + expect + " at end of file");
3311: else {
3312: _offset--;
3313:
3314: try {
3315: Object obj = readObject();
3316:
3317: if (obj != null) {
3318: return error("expected " + expect + " at 0x"
3319: + Integer.toHexString(ch & 0xff) + " "
3320: + obj.getClass().getName() + " (" + obj
3321: + ")");
3322: } else
3323: return error("expected " + expect + " at 0x"
3324: + Integer.toHexString(ch & 0xff) + " null");
3325: } catch (IOException e) {
3326: log.log(Level.FINE, e.toString(), e);
3327:
3328: return error("expected " + expect + " at 0x"
3329: + Integer.toHexString(ch & 0xff));
3330: }
3331: }
3332: }
3333:
3334: protected String codeName(int ch) {
3335: if (ch < 0)
3336: return "end of file";
3337: else
3338: return "0x" + Integer.toHexString(ch & 0xff) + " ("
3339: + (char) +ch + ")";
3340: }
3341:
3342: protected IOException error(String message) {
3343: if (_method != null)
3344: return new HessianProtocolException(_method + ": "
3345: + message);
3346: else
3347: return new HessianProtocolException(message);
3348: }
3349:
3350: public void close() throws IOException {
3351: InputStream is = _is;
3352: _is = null;
3353:
3354: if (_isCloseStreamOnClose && is != null)
3355: is.close();
3356: }
3357:
3358: class ReadInputStream extends InputStream {
3359: boolean _isClosed = false;
3360:
3361: public int read() throws IOException {
3362: if (_isClosed)
3363: return -1;
3364:
3365: int ch = parseByte();
3366: if (ch < 0)
3367: _isClosed = true;
3368:
3369: return ch;
3370: }
3371:
3372: public int read(byte[] buffer, int offset, int length)
3373: throws IOException {
3374: if (_isClosed)
3375: return -1;
3376:
3377: int len = Hessian2Input.this .read(buffer, offset, length);
3378: if (len < 0)
3379: _isClosed = true;
3380:
3381: return len;
3382: }
3383:
3384: public void close() throws IOException {
3385: while (read() >= 0) {
3386: }
3387: }
3388: };
3389:
3390: final static class ObjectDefinition {
3391: private final String _type;
3392: private final String[] _fields;
3393:
3394: ObjectDefinition(String type, String[] fields) {
3395: _type = type;
3396: _fields = fields;
3397: }
3398:
3399: String getType() {
3400: return _type;
3401: }
3402:
3403: String[] getFieldNames() {
3404: return _fields;
3405: }
3406: }
3407:
3408: static {
3409: try {
3410: _detailMessageField = Throwable.class
3411: .getDeclaredField("detailMessage");
3412: _detailMessageField.setAccessible(true);
3413: } catch (Throwable e) {
3414: }
3415: }
3416: }
|