0001: /*
0002: * Copyright (c) 2001-2004 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.IOException;
0052: import java.io.InputStream;
0053: import java.io.PrintWriter;
0054: import java.util.ArrayList;
0055:
0056: /**
0057: * Debugging input stream for Hessian requests.
0058: */
0059: public class HessianDebugState implements Hessian2Constants {
0060: private PrintWriter _dbg;
0061:
0062: private State _state;
0063: private ArrayList<State> _stateStack = new ArrayList<State>();
0064:
0065: private ArrayList<ObjectDef> _objectDefList = new ArrayList<ObjectDef>();
0066:
0067: private ArrayList<String> _typeDefList = new ArrayList<String>();
0068:
0069: private int _refId;
0070: private boolean _isNewline = true;
0071: private boolean _isObject = false;
0072: private int _column;
0073:
0074: /**
0075: * Creates an uninitialized Hessian input stream.
0076: */
0077: public HessianDebugState(PrintWriter dbg) {
0078: _dbg = dbg;
0079:
0080: _state = new InitialState();
0081: }
0082:
0083: /**
0084: * Reads a character.
0085: */
0086: public void next(int ch) throws IOException {
0087: _state = _state.next(ch);
0088: }
0089:
0090: void pushStack(State state) {
0091: _stateStack.add(state);
0092: }
0093:
0094: State popStack() {
0095: return _stateStack.remove(_stateStack.size() - 1);
0096: }
0097:
0098: void println() {
0099: if (!_isNewline) {
0100: _dbg.println();
0101: _dbg.flush();
0102: }
0103:
0104: _isNewline = true;
0105: _column = 0;
0106: }
0107:
0108: abstract class State {
0109: State _next;
0110:
0111: State() {
0112: }
0113:
0114: State(State next) {
0115: _next = next;
0116: }
0117:
0118: abstract State next(int ch);
0119:
0120: boolean isShift(Object value) {
0121: return false;
0122: }
0123:
0124: State shift(Object value) {
0125: return this ;
0126: }
0127:
0128: int depth() {
0129: if (_next != null)
0130: return _next.depth();
0131: else
0132: return 0;
0133: }
0134:
0135: void printIndent(int depth) {
0136: if (_isNewline) {
0137: for (int i = _column; i < depth() + depth; i++) {
0138: _dbg.print(" ");
0139: _column++;
0140: }
0141: }
0142: }
0143:
0144: void print(String string) {
0145: print(0, string);
0146: }
0147:
0148: void print(int depth, String string) {
0149: printIndent(depth);
0150:
0151: _dbg.print(string);
0152: _isNewline = false;
0153: _isObject = false;
0154:
0155: int p = string.lastIndexOf('\n');
0156: if (p > 0)
0157: _column = string.length() - p - 1;
0158: else
0159: _column += string.length();
0160: }
0161:
0162: void println(String string) {
0163: println(0, string);
0164: }
0165:
0166: void println(int depth, String string) {
0167: printIndent(depth);
0168:
0169: _dbg.println(string);
0170: _dbg.flush();
0171: _isNewline = true;
0172: _isObject = false;
0173: _column = 0;
0174: }
0175:
0176: void println() {
0177: if (!_isNewline) {
0178: _dbg.println();
0179: _dbg.flush();
0180: }
0181:
0182: _isNewline = true;
0183: _isObject = false;
0184: _column = 0;
0185: }
0186:
0187: void printObject(String string) {
0188: if (_isObject)
0189: println();
0190:
0191: printIndent(0);
0192:
0193: _dbg.print(string);
0194: _dbg.flush();
0195:
0196: _column += string.length();
0197:
0198: _isNewline = false;
0199: _isObject = true;
0200: }
0201:
0202: protected State nextObject(int ch) {
0203: switch (ch) {
0204: case -1:
0205: println();
0206: return this ;
0207:
0208: case 'N':
0209: if (isShift(null))
0210: return shift(null);
0211: else {
0212: printObject("null");
0213: return this ;
0214: }
0215:
0216: case 'T':
0217: if (isShift(Boolean.TRUE))
0218: return shift(Boolean.TRUE);
0219: else {
0220: printObject("true");
0221: return this ;
0222: }
0223:
0224: case 'F':
0225: if (isShift(Boolean.FALSE))
0226: return shift(Boolean.FALSE);
0227: else {
0228: printObject("false");
0229: return this ;
0230: }
0231:
0232: case 0x80:
0233: case 0x81:
0234: case 0x82:
0235: case 0x83:
0236: case 0x84:
0237: case 0x85:
0238: case 0x86:
0239: case 0x87:
0240: case 0x88:
0241: case 0x89:
0242: case 0x8a:
0243: case 0x8b:
0244: case 0x8c:
0245: case 0x8d:
0246: case 0x8e:
0247: case 0x8f:
0248:
0249: case 0x90:
0250: case 0x91:
0251: case 0x92:
0252: case 0x93:
0253: case 0x94:
0254: case 0x95:
0255: case 0x96:
0256: case 0x97:
0257: case 0x98:
0258: case 0x99:
0259: case 0x9a:
0260: case 0x9b:
0261: case 0x9c:
0262: case 0x9d:
0263: case 0x9e:
0264: case 0x9f:
0265:
0266: case 0xa0:
0267: case 0xa1:
0268: case 0xa2:
0269: case 0xa3:
0270: case 0xa4:
0271: case 0xa5:
0272: case 0xa6:
0273: case 0xa7:
0274: case 0xa8:
0275: case 0xa9:
0276: case 0xaa:
0277: case 0xab:
0278: case 0xac:
0279: case 0xad:
0280: case 0xae:
0281: case 0xaf:
0282:
0283: case 0xb0:
0284: case 0xb1:
0285: case 0xb2:
0286: case 0xb3:
0287: case 0xb4:
0288: case 0xb5:
0289: case 0xb6:
0290: case 0xb7:
0291: case 0xb8:
0292: case 0xb9:
0293: case 0xba:
0294: case 0xbb:
0295: case 0xbc:
0296: case 0xbd:
0297: case 0xbe:
0298: case 0xbf: {
0299: Integer value = new Integer(ch - 0x90);
0300:
0301: if (isShift(value))
0302: return shift(value);
0303: else {
0304: printObject(value.toString());
0305: return this ;
0306: }
0307: }
0308:
0309: case 0xc0:
0310: case 0xc1:
0311: case 0xc2:
0312: case 0xc3:
0313: case 0xc4:
0314: case 0xc5:
0315: case 0xc6:
0316: case 0xc7:
0317: case 0xc8:
0318: case 0xc9:
0319: case 0xca:
0320: case 0xcb:
0321: case 0xcc:
0322: case 0xcd:
0323: case 0xce:
0324: case 0xcf:
0325: return new IntegerState(this , "int", ch - 0xc8, 3);
0326:
0327: case 0xd0:
0328: case 0xd1:
0329: case 0xd2:
0330: case 0xd3:
0331: case 0xd4:
0332: case 0xd5:
0333: case 0xd6:
0334: case 0xd7:
0335: return new IntegerState(this , "int", ch - 0xd4, 2);
0336:
0337: case 'I':
0338: return new IntegerState(this , "int");
0339:
0340: case 0xd8:
0341: case 0xd9:
0342: case 0xda:
0343: case 0xdb:
0344: case 0xdc:
0345: case 0xdd:
0346: case 0xde:
0347: case 0xdf:
0348: case 0xe0:
0349: case 0xe1:
0350: case 0xe2:
0351: case 0xe3:
0352: case 0xe4:
0353: case 0xe5:
0354: case 0xe6:
0355: case 0xe7:
0356: case 0xe8:
0357: case 0xe9:
0358: case 0xea:
0359: case 0xeb:
0360: case 0xec:
0361: case 0xed:
0362: case 0xee:
0363: case 0xef: {
0364: Long value = new Long(ch - 0xe0);
0365:
0366: if (isShift(value))
0367: return shift(value);
0368: else {
0369: printObject(value.toString() + "L");
0370: return this ;
0371: }
0372: }
0373:
0374: case 0xf0:
0375: case 0xf1:
0376: case 0xf2:
0377: case 0xf3:
0378: case 0xf4:
0379: case 0xf5:
0380: case 0xf6:
0381: case 0xf7:
0382: case 0xf8:
0383: case 0xf9:
0384: case 0xfa:
0385: case 0xfb:
0386: case 0xfc:
0387: case 0xfd:
0388: case 0xfe:
0389: case 0xff:
0390: return new LongState(this , "long", ch - 0xf8, 7);
0391:
0392: case 0x38:
0393: case 0x39:
0394: case 0x3a:
0395: case 0x3b:
0396: case 0x3c:
0397: case 0x3d:
0398: case 0x3e:
0399: case 0x3f:
0400: return new LongState(this , "long", ch - 0x3c, 6);
0401:
0402: case 0x77:
0403: return new LongState(this , "long", 0, 4);
0404:
0405: case 'L':
0406: return new LongState(this , "long");
0407:
0408: case 0x67:
0409: case 0x68: {
0410: Double value = new Double(ch - 0x67);
0411:
0412: if (isShift(value))
0413: return shift(value);
0414: else {
0415: printObject(value.toString());
0416: return this ;
0417: }
0418: }
0419:
0420: case 0x69:
0421: return new DoubleIntegerState(this , 3);
0422:
0423: case 0x6a:
0424: return new DoubleIntegerState(this , 2);
0425:
0426: case 0x6b:
0427: return new FloatState(this );
0428:
0429: case 'D':
0430: return new DoubleState(this );
0431:
0432: case 0x4a:
0433: return new RefState(this , "Ref", 0, 3);
0434:
0435: case 0x4b:
0436: return new RefState(this , "Ref", 0, 2);
0437:
0438: case 'R':
0439: return new RefState(this , "Ref");
0440:
0441: case 'r':
0442: return new RemoteState(this );
0443:
0444: case 'd':
0445: return new DateState(this );
0446:
0447: case 0x00: {
0448: String value = "\"\"";
0449:
0450: if (isShift(value))
0451: return shift(value);
0452: else {
0453: printObject(value.toString());
0454: return this ;
0455: }
0456: }
0457:
0458: case 0x01:
0459: case 0x02:
0460: case 0x03:
0461: case 0x04:
0462: case 0x05:
0463: case 0x06:
0464: case 0x07:
0465: case 0x08:
0466: case 0x09:
0467: case 0x0a:
0468: case 0x0b:
0469: case 0x0c:
0470: case 0x0d:
0471: case 0x0e:
0472: case 0x0f:
0473:
0474: case 0x10:
0475: case 0x11:
0476: case 0x12:
0477: case 0x13:
0478: case 0x14:
0479: case 0x15:
0480: case 0x16:
0481: case 0x17:
0482: case 0x18:
0483: case 0x19:
0484: case 0x1a:
0485: case 0x1b:
0486: case 0x1c:
0487: case 0x1d:
0488: case 0x1e:
0489: case 0x1f:
0490: return new StringState(this , 'S', ch);
0491:
0492: case 'S':
0493: case 'X':
0494: return new StringState(this , 'S', true);
0495:
0496: case 's':
0497: case 'x':
0498: return new StringState(this , 'S', false);
0499:
0500: case 0x20: {
0501: String value = "binary(0)";
0502:
0503: if (isShift(value))
0504: return shift(value);
0505: else {
0506: printObject(value.toString());
0507: return this ;
0508: }
0509: }
0510:
0511: case 0x21:
0512: case 0x22:
0513: case 0x23:
0514: case 0x24:
0515: case 0x25:
0516: case 0x26:
0517: case 0x27:
0518: case 0x28:
0519: case 0x29:
0520: case 0x2a:
0521: case 0x2b:
0522: case 0x2c:
0523: case 0x2d:
0524: case 0x2e:
0525: case 0x2f:
0526: return new BinaryState(this , 'B', ch - 0x20);
0527:
0528: case 'B':
0529: return new BinaryState(this , 'B', true);
0530:
0531: case 'b':
0532: return new BinaryState(this , 'B', false);
0533:
0534: case 'M':
0535: return new MapState(this , _refId++);
0536:
0537: case 'V':
0538: return new ListState(this , _refId++);
0539:
0540: case 'v':
0541: return new CompactListState(this , _refId++);
0542:
0543: case 'O':
0544: return new ObjectDefState(this );
0545:
0546: case 'o':
0547: return new ObjectState(this , _refId++);
0548:
0549: case 'P':
0550: return new StreamingState(this , true);
0551:
0552: case 'p':
0553: return new StreamingState(this , false);
0554:
0555: default:
0556: println(String.valueOf((char) ch)
0557: + ": unexpected character");
0558: return this ;
0559: }
0560: }
0561: }
0562:
0563: class InitialState extends State {
0564: State next(int ch) {
0565: println();
0566:
0567: if (ch == 'r') {
0568: return new ReplyState(this );
0569: } else if (ch == 'c') {
0570: return new CallState(this );
0571: } else
0572: return nextObject(ch);
0573: }
0574: }
0575:
0576: class IntegerState extends State {
0577: String _typeCode;
0578:
0579: int _length;
0580: int _value;
0581:
0582: IntegerState(State next, String typeCode) {
0583: super (next);
0584:
0585: _typeCode = typeCode;
0586: }
0587:
0588: IntegerState(State next, String typeCode, int value, int length) {
0589: super (next);
0590:
0591: _typeCode = typeCode;
0592:
0593: _value = value;
0594: _length = length;
0595: }
0596:
0597: State next(int ch) {
0598: _value = 256 * _value + (ch & 0xff);
0599:
0600: if (++_length == 4) {
0601: Integer value = new Integer(_value);
0602:
0603: if (_next.isShift(value))
0604: return _next.shift(value);
0605: else {
0606: printObject(value.toString());
0607:
0608: return _next;
0609: }
0610: } else
0611: return this ;
0612: }
0613: }
0614:
0615: class LongState extends State {
0616: String _typeCode;
0617:
0618: int _length;
0619: long _value;
0620:
0621: LongState(State next, String typeCode) {
0622: super (next);
0623:
0624: _typeCode = typeCode;
0625: }
0626:
0627: LongState(State next, String typeCode, long value, int length) {
0628: super (next);
0629:
0630: _typeCode = typeCode;
0631:
0632: _value = value;
0633: _length = length;
0634: }
0635:
0636: State next(int ch) {
0637: _value = 256 * _value + (ch & 0xff);
0638:
0639: if (++_length == 8) {
0640: Long value = new Long(_value);
0641:
0642: if (_next.isShift(value))
0643: return _next.shift(value);
0644: else {
0645: printObject(value.toString() + "L");
0646:
0647: return _next;
0648: }
0649: } else
0650: return this ;
0651: }
0652: }
0653:
0654: class DoubleIntegerState extends State {
0655: int _length;
0656: int _value;
0657: boolean _isFirst = true;
0658:
0659: DoubleIntegerState(State next, int length) {
0660: super (next);
0661:
0662: _length = length;
0663: }
0664:
0665: State next(int ch) {
0666: if (_isFirst)
0667: _value = (byte) ch;
0668: else
0669: _value = 256 * _value + (ch & 0xff);
0670:
0671: _isFirst = false;
0672:
0673: if (++_length == 4) {
0674: Double value = new Double(_value);
0675:
0676: if (_next.isShift(value))
0677: return _next.shift(value);
0678: else {
0679: printObject(value.toString());
0680:
0681: return _next;
0682: }
0683: } else
0684: return this ;
0685: }
0686: }
0687:
0688: class RefState extends State {
0689: String _typeCode;
0690:
0691: int _length;
0692: int _value;
0693:
0694: RefState(State next, String typeCode) {
0695: super (next);
0696:
0697: _typeCode = typeCode;
0698: }
0699:
0700: RefState(State next, String typeCode, int value, int length) {
0701: super (next);
0702:
0703: _typeCode = typeCode;
0704:
0705: _value = value;
0706: _length = length;
0707: }
0708:
0709: State next(int ch) {
0710: _value = 256 * _value + (ch & 0xff);
0711:
0712: if (++_length == 4) {
0713: Integer value = new Integer(_value);
0714:
0715: if (_next.isShift(value))
0716: return _next.shift(value);
0717: else {
0718: printObject("ref(#" + value + ")");
0719:
0720: return _next;
0721: }
0722: } else
0723: return this ;
0724: }
0725: }
0726:
0727: class DateState extends State {
0728: int _length;
0729: long _value;
0730:
0731: DateState(State next) {
0732: super (next);
0733: }
0734:
0735: State next(int ch) {
0736: _value = 256 * _value + (ch & 0xff);
0737:
0738: if (++_length == 8) {
0739: java.util.Date value = new java.util.Date(_value);
0740:
0741: if (_next.isShift(value))
0742: return _next.shift(value);
0743: else {
0744: printObject(value.toString());
0745:
0746: return _next;
0747: }
0748: } else
0749: return this ;
0750: }
0751: }
0752:
0753: class DoubleState extends State {
0754: int _length;
0755: long _value;
0756:
0757: DoubleState(State next) {
0758: super (next);
0759: }
0760:
0761: State next(int ch) {
0762: _value = 256 * _value + (ch & 0xff);
0763:
0764: if (++_length == 8) {
0765: Double value = Double.longBitsToDouble(_value);
0766:
0767: if (_next.isShift(value))
0768: return _next.shift(value);
0769: else {
0770: printObject(value.toString());
0771:
0772: return _next;
0773: }
0774: } else
0775: return this ;
0776: }
0777: }
0778:
0779: class FloatState extends State {
0780: int _length;
0781: int _value;
0782:
0783: FloatState(State next) {
0784: super (next);
0785: }
0786:
0787: State next(int ch) {
0788: _value = 256 * _value + (ch & 0xff);
0789:
0790: if (++_length == 4) {
0791: Double value = (double) Float.intBitsToFloat(_value);
0792:
0793: if (_next.isShift(value))
0794: return _next.shift(value);
0795: else {
0796: printObject(value.toString() + "F");
0797:
0798: return _next;
0799: }
0800: } else
0801: return this ;
0802: }
0803: }
0804:
0805: class StringState extends State {
0806: private static final int TOP = 0;
0807: private static final int UTF_2_1 = 1;
0808: private static final int UTF_3_1 = 2;
0809: private static final int UTF_3_2 = 3;
0810:
0811: char _typeCode;
0812:
0813: StringBuilder _value = new StringBuilder();
0814: int _lengthIndex;
0815: int _length;
0816: boolean _isLastChunk;
0817:
0818: int _utfState;
0819: char _ch;
0820:
0821: StringState(State next, char typeCode, boolean isLastChunk) {
0822: super (next);
0823:
0824: _typeCode = typeCode;
0825: _isLastChunk = isLastChunk;
0826: }
0827:
0828: StringState(State next, char typeCode, int length) {
0829: super (next);
0830:
0831: _typeCode = typeCode;
0832: _isLastChunk = true;
0833: _length = length;
0834: _lengthIndex = 2;
0835: }
0836:
0837: State next(int ch) {
0838: if (_lengthIndex < 2) {
0839: _length = 256 * _length + (ch & 0xff);
0840:
0841: if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) {
0842: if (_next.isShift(_value.toString()))
0843: return _next.shift(_value.toString());
0844: else {
0845: printObject("\"" + _value + "\"");
0846: return _next;
0847: }
0848: } else
0849: return this ;
0850: } else if (_length == 0) {
0851: if (ch == 's' || ch == 'x') {
0852: _isLastChunk = false;
0853: _lengthIndex = 0;
0854: return this ;
0855: } else if (ch == 'S' || ch == 'X') {
0856: _isLastChunk = true;
0857: _lengthIndex = 0;
0858: return this ;
0859: } else if (ch == 0x00) {
0860: if (_next.isShift(_value.toString()))
0861: return _next.shift(_value.toString());
0862: else {
0863: printObject("\"" + _value + "\"");
0864: return _next;
0865: }
0866: } else if (0x00 <= ch && ch < 0x20) {
0867: _isLastChunk = true;
0868: _lengthIndex = 2;
0869: _length = ch & 0xff;
0870: return this ;
0871: } else {
0872: println(String.valueOf((char) ch)
0873: + ": unexpected character");
0874: return _next;
0875: }
0876: }
0877:
0878: switch (_utfState) {
0879: case TOP:
0880: if (ch < 0x80) {
0881: _length--;
0882:
0883: _value.append((char) ch);
0884: } else if (ch < 0xe0) {
0885: _ch = (char) ((ch & 0x1f) << 6);
0886: _utfState = UTF_2_1;
0887: } else {
0888: _ch = (char) ((ch & 0xf) << 12);
0889: _utfState = UTF_3_1;
0890: }
0891: break;
0892:
0893: case UTF_2_1:
0894: case UTF_3_2:
0895: _ch += ch & 0x3f;
0896: _value.append(_ch);
0897: _length--;
0898: _utfState = TOP;
0899: break;
0900:
0901: case UTF_3_1:
0902: _ch += (char) ((ch & 0x3f) << 6);
0903: _utfState = UTF_3_2;
0904: break;
0905: }
0906:
0907: if (_length == 0 && _isLastChunk) {
0908: if (_next.isShift(_value.toString()))
0909: return _next.shift(_value.toString());
0910: else {
0911: printObject("\"" + _value + "\"");
0912:
0913: return _next;
0914: }
0915: } else
0916: return this ;
0917: }
0918: }
0919:
0920: class BinaryState extends State {
0921: char _typeCode;
0922:
0923: int _totalLength;
0924:
0925: int _lengthIndex;
0926: int _length;
0927: boolean _isLastChunk;
0928:
0929: BinaryState(State next, char typeCode, boolean isLastChunk) {
0930: super (next);
0931:
0932: _typeCode = typeCode;
0933: _isLastChunk = isLastChunk;
0934: }
0935:
0936: BinaryState(State next, char typeCode, int length) {
0937: super (next);
0938:
0939: _typeCode = typeCode;
0940: _isLastChunk = true;
0941: _length = length;
0942: _lengthIndex = 2;
0943: }
0944:
0945: State next(int ch) {
0946: if (_lengthIndex < 2) {
0947: _length = 256 * _length + (ch & 0xff);
0948:
0949: if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) {
0950: String value = "binary(" + _totalLength + ")";
0951:
0952: if (_next.isShift(value))
0953: return _next.shift(value);
0954: else {
0955: printObject(value);
0956: return _next;
0957: }
0958: } else
0959: return this ;
0960: } else if (_length == 0) {
0961: if (ch == 'b') {
0962: _isLastChunk = false;
0963: _lengthIndex = 0;
0964: return this ;
0965: } else if (ch == 'B') {
0966: _isLastChunk = true;
0967: _lengthIndex = 0;
0968: return this ;
0969: } else if (ch == 0x20) {
0970: String value = "binary(" + _totalLength + ")";
0971:
0972: if (_next.isShift(value))
0973: return _next.shift(value);
0974: else {
0975: printObject(value);
0976: return _next;
0977: }
0978: } else if (0x20 <= ch && ch < 0x30) {
0979: _isLastChunk = true;
0980: _lengthIndex = 2;
0981: _length = (ch & 0xff) - 0x20;
0982: return this ;
0983: } else {
0984: println(String.valueOf((char) ch)
0985: + ": unexpected character");
0986: return _next;
0987: }
0988: }
0989:
0990: _length--;
0991: _totalLength++;
0992:
0993: if (_length == 0 && _isLastChunk) {
0994: String value = "binary(" + _totalLength + ")";
0995:
0996: if (_next.isShift(value))
0997: return _next.shift(value);
0998: else {
0999: printObject(value);
1000:
1001: return _next;
1002: }
1003: } else
1004: return this ;
1005: }
1006: }
1007:
1008: class MapState extends State {
1009: private static final int TYPE = 0;
1010: private static final int KEY = 1;
1011: private static final int VALUE = 2;
1012:
1013: private int _refId;
1014:
1015: private int _state;
1016: private int _valueDepth;
1017: private boolean _hasData;
1018:
1019: MapState(State next, int refId) {
1020: super (next);
1021:
1022: _refId = refId;
1023: _state = TYPE;
1024: }
1025:
1026: @Override
1027: boolean isShift(Object value) {
1028: return _state == TYPE;
1029: }
1030:
1031: @Override
1032: State shift(Object type) {
1033: if (_state == TYPE) {
1034: if (type instanceof String) {
1035: _typeDefList.add((String) type);
1036: } else if (type instanceof Integer) {
1037: int iValue = (Integer) type;
1038:
1039: if (iValue >= 0 && iValue < _typeDefList.size())
1040: type = _typeDefList.get(iValue);
1041: }
1042:
1043: printObject("map " + type + "(#" + _refId + ")");
1044:
1045: _state = VALUE;
1046:
1047: return this ;
1048: } else
1049: throw new IllegalStateException();
1050: }
1051:
1052: @Override
1053: int depth() {
1054: if (_state == TYPE)
1055: return _next.depth();
1056: else if (_state == KEY)
1057: return _next.depth() + 2;
1058: else
1059: return _valueDepth;
1060: }
1061:
1062: State next(int ch) {
1063: switch (_state) {
1064: case TYPE:
1065: if (ch == 't') {
1066: return new StringState(this , 't', true);
1067: } else if (ch == 0x75) {
1068: return new IndirectState(this );
1069: } else if (ch == 'z') {
1070: printObject("map (#" + _refId + ")");
1071: return _next;
1072: } else {
1073: printObject("map (#" + _refId + ")");
1074:
1075: _state = KEY;
1076:
1077: return nextObject(ch);
1078: }
1079:
1080: case VALUE:
1081: if (ch == 'z') {
1082: if (_hasData)
1083: println();
1084:
1085: return _next;
1086: } else {
1087: if (_hasData)
1088: println();
1089:
1090: _hasData = true;
1091: _state = KEY;
1092:
1093: return nextObject(ch);
1094: }
1095:
1096: case KEY:
1097: print(" => ");
1098: _isObject = false;
1099: _valueDepth = _column;
1100:
1101: _state = VALUE;
1102:
1103: return nextObject(ch);
1104:
1105: default:
1106: throw new IllegalStateException();
1107: }
1108: }
1109: }
1110:
1111: class ObjectDefState extends State {
1112: private static final int TYPE = 1;
1113: private static final int COUNT = 2;
1114: private static final int FIELD = 3;
1115: private static final int COMPLETE = 4;
1116:
1117: private int _refId;
1118:
1119: private int _state;
1120: private boolean _hasData;
1121: private int _count;
1122:
1123: private String _type;
1124: private ArrayList<String> _fields = new ArrayList<String>();
1125:
1126: ObjectDefState(State next) {
1127: super (next);
1128:
1129: _state = TYPE;
1130: }
1131:
1132: @Override
1133: boolean isShift(Object value) {
1134: return true;
1135: }
1136:
1137: @Override
1138: State shift(Object object) {
1139: if (_state == TYPE) {
1140: _type = (String) object;
1141:
1142: print("/* defun " + _type + " [");
1143:
1144: _objectDefList.add(new ObjectDef(_type, _fields));
1145:
1146: _state = COUNT;
1147: } else if (_state == COUNT) {
1148: _count = (Integer) object;
1149:
1150: _state = FIELD;
1151: } else if (_state == FIELD) {
1152: String field = (String) object;
1153:
1154: _count--;
1155:
1156: _fields.add(field);
1157:
1158: if (_fields.size() == 1)
1159: print(field);
1160: else
1161: print(", " + field);
1162: } else {
1163: throw new UnsupportedOperationException();
1164: }
1165:
1166: return this ;
1167: }
1168:
1169: @Override
1170: int depth() {
1171: if (_state <= TYPE)
1172: return _next.depth();
1173: else
1174: return _next.depth() + 2;
1175: }
1176:
1177: State next(int ch) {
1178: switch (_state) {
1179: case TYPE:
1180: return nextObject(ch);
1181:
1182: case COUNT:
1183: return nextObject(ch);
1184:
1185: case FIELD:
1186: if (_count == 0) {
1187: println("] */");
1188: _next.printIndent(0);
1189:
1190: return _next.nextObject(ch);
1191: } else
1192: return nextObject(ch);
1193:
1194: default:
1195: throw new IllegalStateException();
1196: }
1197: }
1198: }
1199:
1200: class ObjectState extends State {
1201: private static final int TYPE = 0;
1202: private static final int FIELD = 1;
1203:
1204: private int _refId;
1205:
1206: private int _state;
1207: private ObjectDef _def;
1208: private int _count;
1209: private int _fieldDepth;
1210:
1211: ObjectState(State next, int refId) {
1212: super (next);
1213:
1214: _refId = refId;
1215: _state = TYPE;
1216: }
1217:
1218: @Override
1219: boolean isShift(Object value) {
1220: if (_state == TYPE)
1221: return true;
1222: else
1223: return false;
1224: }
1225:
1226: @Override
1227: State shift(Object object) {
1228: if (_state == TYPE) {
1229: int def = (Integer) object;
1230:
1231: _def = _objectDefList.get(def);
1232:
1233: println("object " + _def.getType() + " (#" + _refId
1234: + ")");
1235:
1236: _state = FIELD;
1237:
1238: if (_def.getFields().size() == 0)
1239: return _next;
1240: }
1241:
1242: return this ;
1243: }
1244:
1245: @Override
1246: int depth() {
1247: if (_state <= TYPE)
1248: return _next.depth();
1249: else
1250: return _fieldDepth;
1251: }
1252:
1253: State next(int ch) {
1254: switch (_state) {
1255: case TYPE:
1256: return nextObject(ch);
1257:
1258: case FIELD:
1259: if (_def.getFields().size() <= _count)
1260: return _next.next(ch);
1261:
1262: _fieldDepth = _next.depth() + 2;
1263: println();
1264: print(_def.getFields().get(_count++) + ": ");
1265:
1266: _fieldDepth = _column;
1267:
1268: _isObject = false;
1269: return nextObject(ch);
1270:
1271: default:
1272: throw new IllegalStateException();
1273: }
1274: }
1275: }
1276:
1277: class ListState extends State {
1278: private static final int TYPE = 0;
1279: private static final int LENGTH = 1;
1280: private static final int VALUE = 2;
1281:
1282: private int _refId;
1283:
1284: private int _state;
1285: private boolean _hasData;
1286: private int _count;
1287: private int _valueDepth;
1288:
1289: ListState(State next, int refId) {
1290: super (next);
1291:
1292: _refId = refId;
1293: _state = TYPE;
1294: }
1295:
1296: @Override
1297: boolean isShift(Object value) {
1298: return _state == TYPE || _state == LENGTH;
1299: }
1300:
1301: @Override
1302: State shift(Object object) {
1303: if (_state == TYPE) {
1304: Object type = object;
1305:
1306: if (type instanceof String) {
1307: _typeDefList.add((String) type);
1308: } else if (object instanceof Integer) {
1309: int index = (Integer) object;
1310:
1311: if (index >= 0 && index < _typeDefList.size())
1312: type = _typeDefList.get(index);
1313: }
1314:
1315: printObject("list " + type + "(#" + _refId + ")");
1316:
1317: _state = LENGTH;
1318:
1319: return this ;
1320: } else if (_state == LENGTH) {
1321: _state = VALUE;
1322:
1323: return this ;
1324: } else
1325: return this ;
1326: }
1327:
1328: @Override
1329: int depth() {
1330: if (_state <= LENGTH)
1331: return _next.depth();
1332: else if (_state == VALUE)
1333: return _valueDepth;
1334: else
1335: return _next.depth() + 2;
1336: }
1337:
1338: State next(int ch) {
1339: switch (_state) {
1340: case TYPE:
1341: if (ch == 't') {
1342: return new StringState(this , 't', true);
1343: } else if (ch == 0x75) {
1344: return new IndirectState(this );
1345: } else if (ch == 'l') {
1346: printObject("list (#" + _refId + ")");
1347: _state = LENGTH;
1348:
1349: return new IntegerState(this , "length");
1350: } else if (ch == 0x6e) {
1351: printObject("list (#" + _refId + ")");
1352: _state = LENGTH;
1353:
1354: return new IndirectState(this );
1355: } else if (ch == 'z') {
1356: printObject("list (#" + _refId + ")");
1357: return _next;
1358: } else {
1359: printObject("list (#" + _refId + ")");
1360:
1361: _state = VALUE;
1362:
1363: _valueDepth = _next.depth() + 2;
1364: println();
1365: printObject(_count++ + ": ");
1366: _valueDepth = _column;
1367: _isObject = false;
1368:
1369: return nextObject(ch);
1370: }
1371:
1372: case LENGTH:
1373: if (ch == 'z') {
1374: return _next;
1375: } else if (ch == 'l') {
1376: return new IntegerState(this , "length");
1377: } else if (ch == 0x6e) {
1378: return new IndirectState(this );
1379: } else {
1380: _state = VALUE;
1381:
1382: _valueDepth = _next.depth() + 2;
1383: println();
1384: printObject(_count++ + ": ");
1385: _valueDepth = _column;
1386: _isObject = false;
1387:
1388: return nextObject(ch);
1389: }
1390:
1391: case VALUE:
1392: if (ch == 'z') {
1393: if (_count > 0)
1394: println();
1395:
1396: return _next;
1397: } else {
1398: _valueDepth = _next.depth() + 2;
1399: println();
1400: printObject(_count++ + ": ");
1401: _valueDepth = _column;
1402: _isObject = false;
1403:
1404: return nextObject(ch);
1405: }
1406:
1407: default:
1408: throw new IllegalStateException();
1409: }
1410: }
1411: }
1412:
1413: class CompactListState extends State {
1414: private static final int TYPE = 0;
1415: private static final int LENGTH = 1;
1416: private static final int VALUE = 2;
1417:
1418: private int _refId;
1419:
1420: private int _state;
1421: private boolean _hasData;
1422: private int _length;
1423: private int _count;
1424: private int _valueDepth;
1425:
1426: CompactListState(State next, int refId) {
1427: super (next);
1428:
1429: _refId = refId;
1430: _state = TYPE;
1431: }
1432:
1433: @Override
1434: boolean isShift(Object value) {
1435: return _state == TYPE || _state == LENGTH;
1436: }
1437:
1438: @Override
1439: State shift(Object object) {
1440: if (_state == TYPE) {
1441: Object type = object;
1442:
1443: if (object instanceof Integer) {
1444: int index = (Integer) object;
1445:
1446: if (index >= 0 && index < _typeDefList.size())
1447: type = _typeDefList.get(index);
1448: }
1449:
1450: printObject("list " + type + "(#" + _refId + ")");
1451:
1452: _state = LENGTH;
1453:
1454: return this ;
1455: } else if (_state == LENGTH) {
1456: _length = (Integer) object;
1457:
1458: _state = VALUE;
1459:
1460: if (_length == 0)
1461: return _next;
1462: else
1463: return this ;
1464: } else
1465: return this ;
1466: }
1467:
1468: @Override
1469: int depth() {
1470: if (_state <= LENGTH)
1471: return _next.depth();
1472: else if (_state == VALUE)
1473: return _valueDepth;
1474: else
1475: return _next.depth() + 2;
1476: }
1477:
1478: State next(int ch) {
1479: switch (_state) {
1480: case TYPE:
1481: return nextObject(ch);
1482:
1483: case LENGTH:
1484: return nextObject(ch);
1485:
1486: case VALUE:
1487: if (_length <= _count)
1488: return _next.next(ch);
1489: else {
1490: _valueDepth = _next.depth() + 2;
1491: println();
1492: printObject(_count++ + ": ");
1493: _valueDepth = _column;
1494: _isObject = false;
1495:
1496: return nextObject(ch);
1497: }
1498:
1499: default:
1500: throw new IllegalStateException();
1501: }
1502: }
1503: }
1504:
1505: class CallState extends State {
1506: private static final int MAJOR = 0;
1507: private static final int MINOR = 1;
1508: private static final int HEADER = 2;
1509: private static final int METHOD = 3;
1510: private static final int VALUE = 4;
1511: private static final int ARG = 5;
1512:
1513: private int _state;
1514: private int _major;
1515: private int _minor;
1516:
1517: CallState(State next) {
1518: super (next);
1519: }
1520:
1521: int depth() {
1522: return _next.depth() + 2;
1523: }
1524:
1525: State next(int ch) {
1526: switch (_state) {
1527: case MAJOR:
1528: _major = ch;
1529: _state = MINOR;
1530: return this ;
1531:
1532: case MINOR:
1533: _minor = ch;
1534: _state = HEADER;
1535: println(-2, "call " + _major + "." + _minor);
1536: return this ;
1537:
1538: case HEADER:
1539: if (ch == 'H') {
1540: println();
1541: print("header ");
1542: _isObject = false;
1543: _state = VALUE;
1544: return new StringState(this , 'H', true);
1545: } else if (ch == 'm') {
1546: println();
1547: print("method ");
1548: _isObject = false;
1549: _state = ARG;
1550: return new StringState(this , 'm', true);
1551: } else {
1552: println((char) ch + ": unexpected char");
1553: return popStack();
1554: }
1555:
1556: case VALUE:
1557: print(" => ");
1558: _isObject = false;
1559: _state = HEADER;
1560: return nextObject(ch);
1561:
1562: case ARG:
1563: if (ch == 'z')
1564: return _next;
1565: else
1566: return nextObject(ch);
1567:
1568: default:
1569: throw new IllegalStateException();
1570: }
1571: }
1572: }
1573:
1574: class ReplyState extends State {
1575: private static final int MAJOR = 0;
1576: private static final int MINOR = 1;
1577: private static final int HEADER = 2;
1578: private static final int VALUE = 3;
1579: private static final int END = 4;
1580:
1581: private int _state;
1582: private int _major;
1583: private int _minor;
1584:
1585: ReplyState(State next) {
1586: _next = next;
1587: }
1588:
1589: int depth() {
1590: return _next.depth() + 2;
1591: }
1592:
1593: State next(int ch) {
1594: switch (_state) {
1595: case MAJOR:
1596: if (ch == 't' || ch == 'S')
1597: return new RemoteState(this ).next(ch);
1598:
1599: _major = ch;
1600: _state = MINOR;
1601: return this ;
1602:
1603: case MINOR:
1604: _minor = ch;
1605: _state = HEADER;
1606: println(-2, "reply " + _major + "." + _minor);
1607: return this ;
1608:
1609: case HEADER:
1610: if (ch == 'H') {
1611: _state = VALUE;
1612: return new StringState(this , 'H', true);
1613: } else if (ch == 'f') {
1614: print("fault ");
1615: _isObject = false;
1616: _state = END;
1617: return new MapState(this , 0);
1618: } else {
1619: _state = END;
1620: return nextObject(ch);
1621: }
1622:
1623: case VALUE:
1624: _state = HEADER;
1625: return nextObject(ch);
1626:
1627: case END:
1628: println();
1629: if (ch == 'z') {
1630: return _next;
1631: } else
1632: return _next.next(ch);
1633:
1634: default:
1635: throw new IllegalStateException();
1636: }
1637: }
1638: }
1639:
1640: class IndirectState extends State {
1641: IndirectState(State next) {
1642: super (next);
1643: }
1644:
1645: boolean isShift(Object object) {
1646: return _next.isShift(object);
1647: }
1648:
1649: State shift(Object object) {
1650: return _next.shift(object);
1651: }
1652:
1653: State next(int ch) {
1654: return nextObject(ch);
1655: }
1656: }
1657:
1658: class RemoteState extends State {
1659: private static final int TYPE = 0;
1660: private static final int VALUE = 1;
1661: private static final int END = 2;
1662:
1663: private int _state;
1664: private int _major;
1665: private int _minor;
1666:
1667: RemoteState(State next) {
1668: super (next);
1669: }
1670:
1671: State next(int ch) {
1672: switch (_state) {
1673: case TYPE:
1674: println(-1, "remote");
1675: if (ch == 't') {
1676: _state = VALUE;
1677: return new StringState(this , 't', false);
1678: } else {
1679: _state = END;
1680: return nextObject(ch);
1681: }
1682:
1683: case VALUE:
1684: _state = END;
1685: return _next.nextObject(ch);
1686:
1687: case END:
1688: return _next.next(ch);
1689:
1690: default:
1691: throw new IllegalStateException();
1692: }
1693: }
1694: }
1695:
1696: class StreamingState extends State {
1697: private int _digit;
1698: private int _length;
1699: private boolean _isLast;
1700: private boolean _isFirst = true;
1701:
1702: private State _childState;
1703:
1704: StreamingState(State next, boolean isLast) {
1705: super (next);
1706:
1707: _isLast = isLast;
1708: _childState = new InitialState();
1709: }
1710:
1711: State next(int ch) {
1712: if (_digit < 2) {
1713: _length = 256 * _length + ch;
1714: _digit++;
1715:
1716: if (_digit == 2 && _length == 0 && _isLast) {
1717: _refId = 0;
1718: return _next;
1719: } else
1720: return this ;
1721: } else if (_length == 0) {
1722: _isLast = (ch == 'P');
1723: _digit = 0;
1724:
1725: return this ;
1726: }
1727:
1728: _childState = _childState.next(ch);
1729:
1730: _length--;
1731:
1732: if (_length == 0 && _isLast) {
1733: _refId = 0;
1734: return _next;
1735: } else
1736: return this ;
1737: }
1738: }
1739:
1740: static class ObjectDef {
1741: private String _type;
1742: private ArrayList<String> _fields;
1743:
1744: ObjectDef(String type, ArrayList<String> fields) {
1745: _type = type;
1746: _fields = fields;
1747: }
1748:
1749: String getType() {
1750: return _type;
1751: }
1752:
1753: ArrayList<String> getFields() {
1754: return _fields;
1755: }
1756: }
1757: }
|