/*
 * Copyright (c) 2001-2004 Caucho Technology, Inc.  All rights reserved.
 *
 * The Apache Software License, Version 1.1
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Caucho Technology (http://www.caucho.com/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
 *    endorse or promote products derived from this software without prior
 *    written permission. For written permission, please contact
 *    info@caucho.com.
 *
 * 5. Products derived from this software may not be called "Resin"
 *    nor may "Resin" appear in their names without prior written
 *    permission of Caucho Technology.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author Scott Ferguson
 */

package com.caucho.hessian.io;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.logging.Logger;

Debugging input stream for Hessian requests.
/** * Debugging input stream for Hessian requests. */
public class HessianDebugState implements Hessian2Constants { private static final Logger log = Logger.getLogger(HessianDebugState.class.getName()); private PrintWriter _dbg; private State _state; private ArrayList<State> _stateStack = new ArrayList<State>(); private ArrayList<ObjectDef> _objectDefList = new ArrayList<ObjectDef>(); private ArrayList<String> _typeDefList = new ArrayList<String>(); private int _refId; private boolean _isNewline = true; private boolean _isObject = false; private int _column; private int _depth = 0;
Creates an uninitialized Hessian input stream.
/** * Creates an uninitialized Hessian input stream. */
public HessianDebugState(PrintWriter dbg) { _dbg = dbg; _state = new InitialState(); } public void startTop2() { _state = new Top2State(); } public void startData1() { _state = new InitialState1(); } public void startStreaming() { _state = new StreamingState(new InitialState(), false); }
Reads a character.
/** * Reads a character. */
public void next(int ch) throws IOException { _state = _state.next(ch); } void pushStack(State state) { _stateStack.add(state); } State popStack() { return _stateStack.remove(_stateStack.size() - 1); } public void setDepth(int depth) { _depth = depth; } public int getDepth() { return _depth; } void println() { if (! _isNewline) { _dbg.println(); _dbg.flush(); } _isNewline = true; _column = 0; } static boolean isString(int ch) { switch (ch) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: case 0x30: case 0x31: case 0x32: case 0x33: case 'R': case 'S': return true; default: return false; } } static boolean isInteger(int ch) { switch (ch) { case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 'I': return true; default: return false; } } abstract class State { State _next; State() { } State(State next) { _next = next; } abstract State next(int ch); boolean isShift(Object value) { return false; } State shift(Object value) { return this; } int depth() { if (_next != null) return _next.depth(); else return HessianDebugState.this.getDepth(); } void printIndent(int depth) { if (_isNewline) { for (int i = _column; i < depth() + depth; i++) { _dbg.print(" "); _column++; } } } void print(String string) { print(0, string); } void print(int depth, String string) { printIndent(depth); _dbg.print(string); _isNewline = false; _isObject = false; int p = string.lastIndexOf('\n'); if (p > 0) _column = string.length() - p - 1; else _column += string.length(); } void println(String string) { println(0, string); } void println(int depth, String string) { printIndent(depth); _dbg.println(string); _dbg.flush(); _isNewline = true; _isObject = false; _column = 0; } void println() { if (! _isNewline) { _dbg.println(); _dbg.flush(); } _isNewline = true; _isObject = false; _column = 0; } void printObject(String string) { if (_isObject) println(); printIndent(0); _dbg.print(string); _dbg.flush(); _column += string.length(); _isNewline = false; _isObject = true; } protected State nextObject(int ch) { switch (ch) { case -1: println(); return this; case 'N': if (isShift(null)) return shift(null); else { printObject("null"); return this; } case 'T': if (isShift(Boolean.TRUE)) return shift(Boolean.TRUE); else { printObject("true"); return this; } case 'F': if (isShift(Boolean.FALSE)) return shift(Boolean.FALSE); else { printObject("false"); return this; } case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: { Integer value = new Integer(ch - 0x90); if (isShift(value)) return shift(value); else { printObject(value.toString()); return this; } } case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: return new IntegerState(this, "int", ch - 0xc8, 3); case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: return new IntegerState(this, "int", ch - 0xd4, 2); case 'I': return new IntegerState(this, "int"); case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: { Long value = new Long(ch - 0xe0); if (isShift(value)) return shift(value); else { printObject(value.toString() + "L"); return this; } } case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: return new LongState(this, "long", ch - 0xf8, 7); case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: return new LongState(this, "long", ch - 0x3c, 6); case BC_LONG_INT: return new LongState(this, "long", 0, 4); case 'L': return new LongState(this, "long"); case 0x5b: case 0x5c: { Double value = new Double(ch - 0x5b); if (isShift(value)) return shift(value); else { printObject(value.toString()); return this; } } case 0x5d: return new DoubleIntegerState(this, 3); case 0x5e: return new DoubleIntegerState(this, 2); case 0x5f: return new MillsState(this); case 'D': return new DoubleState(this); case 'Q': return new RefState(this); case BC_DATE: return new DateState(this); case BC_DATE_MINUTE: return new DateState(this, true); case 0x00: { String value = "\"\""; if (isShift(value)) return shift(value); else { printObject(value.toString()); return this; } } case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: return new StringState(this, 'S', ch); case 0x30: case 0x31: case 0x32: case 0x33: return new StringState(this, 'S', ch - 0x30, true); case 'R': return new StringState(this, 'S', false); case 'S': return new StringState(this, 'S', true); case 0x20: { String value = "binary(0)"; if (isShift(value)) return shift(value); else { printObject(value.toString()); return this; } } case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: return new BinaryState(this, 'B', ch - 0x20); case 0x34: case 0x35: case 0x36: case 0x37: return new BinaryState(this, 'B', ch - 0x34, true); case 'A': return new BinaryState(this, 'B', false); case 'B': return new BinaryState(this, 'B', true); case 'M': return new MapState(this, _refId++); case 'H': return new MapState(this, _refId++, false); case BC_LIST_VARIABLE: return new ListState(this, _refId++, true); case BC_LIST_VARIABLE_UNTYPED: return new ListState(this, _refId++, false); case BC_LIST_FIXED: return new CompactListState(this, _refId++, true); case BC_LIST_FIXED_UNTYPED: return new CompactListState(this, _refId++, false); case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: return new CompactListState(this, _refId++, true, ch - 0x70); case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: return new CompactListState(this, _refId++, false, ch - 0x78); case 'C': return new ObjectDefState(this); case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: return new ObjectState(this, _refId++, ch - 0x60); case 'O': return new ObjectState(this, _refId++); default: return this; } } } abstract class State1 extends State { State1() { } State1(State next) { super(next); } protected State nextObject(int ch) { switch (ch) { case -1: println(); return this; case 'N': if (isShift(null)) return shift(null); else { printObject("null"); return this; } case 'T': if (isShift(Boolean.TRUE)) return shift(Boolean.TRUE); else { printObject("true"); return this; } case 'F': if (isShift(Boolean.FALSE)) return shift(Boolean.FALSE); else { printObject("false"); return this; } case 'I': return new IntegerState(this, "int"); case 'L': return new LongState(this, "long"); case 'D': return new DoubleState(this); case 'Q': return new RefState(this); case 'd': return new DateState(this); case 's': return new StringState(this, 'S', false); case 'S': return new StringState(this, 'S', true); case 'b': case 'A': return new BinaryState(this, 'B', false); case 'B': return new BinaryState(this, 'B', true); case 'M': return new MapState1(this, _refId++); case 'V': return new ListState1(this, _refId++); case 'R': return new IntegerState(new RefState1(this), "ref"); default: printObject("x" + String.format("%02x", ch)); return this; } } } class InitialState extends State { State next(int ch) { return nextObject(ch); } } class InitialState1 extends State1 { State next(int ch) { return nextObject(ch); } } class Top1State extends State1 { State next(int ch) { println(); if (ch == 'r') { return new ReplyState1(this); } else if (ch == 'c') { return new CallState1(this); } else return nextObject(ch); } } class Top2State extends State { State next(int ch) { println(); if (ch == 'R') { return new Reply2State(this); } else if (ch == 'F') { return new Fault2State(this); } else if (ch == 'C') { return new Call2State(this); } else if (ch == 'H') { return new Hessian2State(this); } else if (ch == 'r') { return new ReplyState1(this); } else if (ch == 'c') { return new CallState1(this); } else return nextObject(ch); } } class IntegerState extends State { String _typeCode; int _length; int _value; IntegerState(State next, String typeCode) { super(next); _typeCode = typeCode; } IntegerState(State next, String typeCode, int value, int length) { super(next); _typeCode = typeCode; _value = value; _length = length; } State next(int ch) { _value = 256 * _value + (ch & 0xff); if (++_length == 4) { Integer value = new Integer(_value); if (_next.isShift(value)) return _next.shift(value); else { printObject(value.toString()); return _next; } } else return this; } } class LongState extends State { String _typeCode; int _length; long _value; LongState(State next, String typeCode) { super(next); _typeCode = typeCode; } LongState(State next, String typeCode, long value, int length) { super(next); _typeCode = typeCode; _value = value; _length = length; } State next(int ch) { _value = 256 * _value + (ch & 0xff); if (++_length == 8) { Long value = new Long(_value); if (_next.isShift(value)) return _next.shift(value); else { printObject(value.toString() + "L"); return _next; } } else return this; } } class DoubleIntegerState extends State { int _length; int _value; boolean _isFirst = true; DoubleIntegerState(State next, int length) { super(next); _length = length; } State next(int ch) { if (_isFirst) _value = (byte) ch; else _value = 256 * _value + (ch & 0xff); _isFirst = false; if (++_length == 4) { Double value = new Double(_value); if (_next.isShift(value)) return _next.shift(value); else { printObject(value.toString()); return _next; } } else return this; } } class RefState extends State { String _typeCode; int _length; int _value; RefState(State next) { super(next); } RefState(State next, String typeCode) { super(next); _typeCode = typeCode; } RefState(State next, String typeCode, int value, int length) { super(next); _typeCode = typeCode; _value = value; _length = length; } @Override boolean isShift(Object o) { return true; } @Override State shift(Object o) { println("ref #" + o); return _next; } @Override State next(int ch) { return nextObject(ch); } } class RefState1 extends State { String _typeCode; RefState1(State next) { super(next); } @Override boolean isShift(Object o) { return true; } @Override State shift(Object o) { println("ref #" + o); return _next; } @Override State next(int ch) { return nextObject(ch); } } class DateState extends State { int _length; long _value; boolean _isMinute; DateState(State next) { super(next); } DateState(State next, boolean isMinute) { super(next); _length = 4; _isMinute = isMinute; } State next(int ch) { _value = 256 * _value + (ch & 0xff); if (++_length == 8) { java.util.Date value; if (_isMinute) value = new java.util.Date(_value * 60000L); else value = new java.util.Date(_value); if (_next.isShift(value)) return _next.shift(value); else { printObject(value.toString()); return _next; } } else return this; } } class DoubleState extends State { int _length; long _value; DoubleState(State next) { super(next); } State next(int ch) { _value = 256 * _value + (ch & 0xff); if (++_length == 8) { Double value = Double.longBitsToDouble(_value); if (_next.isShift(value)) return _next.shift(value); else { printObject(value.toString()); return _next; } } else return this; } } class MillsState extends State { int _length; int _value; MillsState(State next) { super(next); } State next(int ch) { _value = 256 * _value + (ch & 0xff); if (++_length == 4) { Double value = 0.001 * _value; if (_next.isShift(value)) return _next.shift(value); else { printObject(value.toString()); return _next; } } else return this; } } class StringState extends State { private static final int TOP = 0; private static final int UTF_2_1 = 1; private static final int UTF_3_1 = 2; private static final int UTF_3_2 = 3; char _typeCode; StringBuilder _value = new StringBuilder(); int _lengthIndex; int _length; boolean _isLastChunk; int _utfState; char _ch; StringState(State next, char typeCode, boolean isLastChunk) { super(next); _typeCode = typeCode; _isLastChunk = isLastChunk; } StringState(State next, char typeCode, int length) { super(next); _typeCode = typeCode; _isLastChunk = true; _length = length; _lengthIndex = 2; } StringState(State next, char typeCode, int length, boolean isLastChunk) { super(next); _typeCode = typeCode; _isLastChunk = isLastChunk; _length = length; _lengthIndex = 1; } State next(int ch) { if (_lengthIndex < 2) { _length = 256 * _length + (ch & 0xff); if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) { if (_next.isShift(_value.toString())) return _next.shift(_value.toString()); else { printObject("\"" + _value + "\""); return _next; } } else return this; } else if (_length == 0) { if (ch == 's' || ch == 'x') { _isLastChunk = false; _lengthIndex = 0; return this; } else if (ch == 'S' || ch == 'X') { _isLastChunk = true; _lengthIndex = 0; return this; } else if (ch == 0x00) { if (_next.isShift(_value.toString())) return _next.shift(_value.toString()); else { printObject("\"" + _value + "\""); return _next; } } else if (0x00 <= ch && ch < 0x20) { _isLastChunk = true; _lengthIndex = 2; _length = ch & 0xff; return this; } else if (0x30 <= ch && ch < 0x34) { _isLastChunk = true; _lengthIndex = 1; _length = (ch - 0x30); return this; } else { println(this + " " + String.valueOf((char) ch) + ": unexpected character"); return _next; } } switch (_utfState) { case TOP: if (ch < 0x80) { _length--; _value.append((char) ch); } else if (ch < 0xe0) { _ch = (char) ((ch & 0x1f) << 6); _utfState = UTF_2_1; } else { _ch = (char) ((ch & 0xf) << 12); _utfState = UTF_3_1; } break; case UTF_2_1: case UTF_3_2: _ch += ch & 0x3f; _value.append(_ch); _length--; _utfState = TOP; break; case UTF_3_1: _ch += (char) ((ch & 0x3f) << 6); _utfState = UTF_3_2; break; } if (_length == 0 && _isLastChunk) { if (_next.isShift(_value.toString())) return _next.shift(_value.toString()); else { printObject("\"" + _value + "\""); return _next; } } else return this; } } class BinaryState extends State { char _typeCode; int _totalLength; int _lengthIndex; int _length; boolean _isLastChunk; BinaryState(State next, char typeCode, boolean isLastChunk) { super(next); _typeCode = typeCode; _isLastChunk = isLastChunk; } BinaryState(State next, char typeCode, int length) { super(next); _typeCode = typeCode; _isLastChunk = true; _length = length; _lengthIndex = 2; } BinaryState(State next, char typeCode, int length, boolean isLastChunk) { super(next); _typeCode = typeCode; _isLastChunk = isLastChunk; _length = length; _lengthIndex = 1; } @Override State next(int ch) { if (_lengthIndex < 2) { _length = 256 * _length + (ch & 0xff); if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) { String value = "binary(" + _totalLength + ")"; if (_next.isShift(value)) return _next.shift(value); else { printObject(value); return _next; } } else return this; } else if (_length == 0) { if (ch == 'b' || ch == 'A') { _isLastChunk = false; _lengthIndex = 0; return this; } else if (ch == 'B') { _isLastChunk = true; _lengthIndex = 0; return this; } else if (ch == 0x20) { String value = "binary(" + _totalLength + ")"; if (_next.isShift(value)) return _next.shift(value); else { printObject(value); return _next; } } else if (0x20 <= ch && ch < 0x30) { _isLastChunk = true; _lengthIndex = 2; _length = (ch & 0xff) - 0x20; return this; } else { println(this + " 0x" + Integer.toHexString(ch) + " " + String.valueOf((char) ch) + ": unexpected character"); return _next; } } _length--; _totalLength++; if (_length == 0 && _isLastChunk) { String value = "binary(" + _totalLength + ")"; if (_next.isShift(value)) return _next.shift(value); else { printObject(value); return _next; } } else return this; } } class MapState extends State { private static final int TYPE = 0; private static final int KEY = 1; private static final int VALUE = 2; private int _refId; private int _state; private int _valueDepth; private boolean _hasData; MapState(State next, int refId) { super(next); _refId = refId; _state = TYPE; } MapState(State next, int refId, boolean isType) { super(next); _refId = refId; if (isType) _state = TYPE; else { printObject("map (#" + _refId + ")"); _state = VALUE; } } @Override boolean isShift(Object value) { return _state == TYPE; } @Override State shift(Object type) { if (_state == TYPE) { if (type instanceof String) { _typeDefList.add((String) type); } else if (type instanceof Integer) { int iValue = (Integer) type; if (iValue >= 0 && iValue < _typeDefList.size()) type = _typeDefList.get(iValue); } printObject("map " + type + " (#" + _refId + ")"); _state = VALUE; return this; } else { printObject(this + " unknown shift state= " + _state + " type=" + type); return this; } } @Override int depth() { if (_state == TYPE) return _next.depth(); else if (_state == KEY) return _next.depth() + 2; else return _valueDepth; } State next(int ch) { switch (_state) { case TYPE: return nextObject(ch); case VALUE: if (ch == 'Z') { if (_hasData) println(); return _next; } else { if (_hasData) println(); _hasData = true; _state = KEY; return nextObject(ch); } case KEY: print(" => "); _isObject = false; _valueDepth = _column; _state = VALUE; return nextObject(ch); default: throw new IllegalStateException(); } } } class MapState1 extends State1 { private static final int TYPE = 0; private static final int KEY = 1; private static final int VALUE = 2; private int _refId; private int _state; private int _valueDepth; private boolean _hasData; MapState1(State next, int refId) { super(next); _refId = refId; _state = TYPE; } MapState1(State next, int refId, boolean isType) { super(next); _refId = refId; if (isType) _state = TYPE; else { printObject("map (#" + _refId + ")"); _state = VALUE; } } @Override boolean isShift(Object value) { return _state == TYPE; } @Override State shift(Object type) { if (_state == TYPE) { if (type instanceof String) { _typeDefList.add((String) type); } else if (type instanceof Integer) { int iValue = (Integer) type; if (iValue >= 0 && iValue < _typeDefList.size()) type = _typeDefList.get(iValue); } printObject("map " + type + " (#" + _refId + ")"); _state = VALUE; return this; } else throw new IllegalStateException(); } @Override int depth() { if (_state == TYPE) return _next.depth(); else if (_state == KEY) return _next.depth() + 2; else return _valueDepth; } State next(int ch) { switch (_state) { case TYPE: if (ch == 't') { return new StringState(this, 't', true); } else if (ch == 'z') { println("map (#" + _refId + ")"); return _next; } else { println("map (#" + _refId + ")"); _hasData = true; _state = KEY; return nextObject(ch); } case VALUE: if (ch == 'z') { if (_hasData) println(); return _next; } else { if (_hasData) println(); _hasData = true; _state = KEY; return nextObject(ch); } case KEY: print(" => "); _isObject = false; _valueDepth = _column; _state = VALUE; return nextObject(ch); default: throw new IllegalStateException(); } } } class ObjectDefState extends State { private static final int TYPE = 1; private static final int COUNT = 2; private static final int FIELD = 3; private static final int COMPLETE = 4; private int _state; private int _count; private String _type; private ArrayList<String> _fields = new ArrayList<String>(); ObjectDefState(State next) { super(next); _state = TYPE; } @Override boolean isShift(Object value) { return true; } @Override State shift(Object object) { if (_state == TYPE) { _type = (String) object; print("/* defun " + _type + " ["); _objectDefList.add(new ObjectDef(_type, _fields)); _state = COUNT; } else if (_state == COUNT) { _count = (Integer) object; _state = FIELD; } else if (_state == FIELD) { String field = (String) object; _count--; _fields.add(field); if (_fields.size() == 1) print(field); else print(", " + field); } else { throw new UnsupportedOperationException(); } return this; } @Override int depth() { if (_state <= TYPE) return _next.depth(); else return _next.depth() + 2; } State next(int ch) { switch (_state) { case TYPE: return nextObject(ch); case COUNT: return nextObject(ch); case FIELD: if (_count == 0) { println("] */"); _next.printIndent(0); return _next.nextObject(ch); } else return nextObject(ch); default: throw new IllegalStateException(); } } } class ObjectState extends State { private static final int TYPE = 0; private static final int FIELD = 1; private int _refId; private int _state; private ObjectDef _def; private int _count; private int _fieldDepth; ObjectState(State next, int refId) { super(next); _refId = refId; _state = TYPE; } ObjectState(State next, int refId, int def) { super(next); _refId = refId; _state = FIELD; if (def < 0 || _objectDefList.size() <= def) { log.warning(this + " " + def + " is an unknown object type"); println(this + " object unknown (#" + _refId + ")"); } _def = _objectDefList.get(def); if (_isObject) println(); println("object " + _def.getType() + " (#" + _refId + ")"); } @Override boolean isShift(Object value) { if (_state == TYPE) return true; else return false; } @Override State shift(Object object) { if (_state == TYPE) { int def = (Integer) object; _def = _objectDefList.get(def); println("object " + _def.getType() + " (#" + _refId + ")"); _state = FIELD; if (_def.getFields().size() == 0) return _next; } return this; } @Override int depth() { if (_state <= TYPE) return _next.depth(); else return _fieldDepth; } State next(int ch) { switch (_state) { case TYPE: return nextObject(ch); case FIELD: if (_def.getFields().size() <= _count) return _next.next(ch); _fieldDepth = _next.depth() + 2; println(); print(_def.getFields().get(_count++) + ": "); _fieldDepth = _column; _isObject = false; return nextObject(ch); default: throw new IllegalStateException(); } } } class ListState1 extends State1 { private static final int TYPE = 0; private static final int LENGTH = 1; private static final int VALUE = 2; private int _refId; private int _state; private int _count; private int _valueDepth; ListState1(State next, int refId) { super(next); _refId = refId; _state = TYPE; } @Override boolean isShift(Object value) { return _state == TYPE || _state == LENGTH; } @Override State shift(Object object) { if (_state == TYPE) { Object type = object; if (type instanceof String) { _typeDefList.add((String) type); } else if (object instanceof Integer) { int index = (Integer) object; if (index >= 0 && index < _typeDefList.size()) type = _typeDefList.get(index); else type = "type-unknown(" + index + ")"; } printObject("list " + type + "(#" + _refId + ")"); _state = VALUE; return this; } else if (_state == LENGTH) { _state = VALUE; return this; } else return this; } @Override int depth() { if (_state <= LENGTH) return _next.depth(); else if (_state == VALUE) return _valueDepth; else return _next.depth() + 2; } State next(int ch) { switch (_state) { case TYPE: if (ch == 'z') { printObject("list (#" + _refId + ")"); return _next; } else if (ch == 't') { return new StringState(this, 't', true); } else { printObject("list (#" + _refId + ")"); printObject(" " + _count++ + ": "); _valueDepth = _column; _isObject = false; _state = VALUE; return nextObject(ch); } case VALUE: if (ch == 'z') { if (_count > 0) println(); return _next; } else { _valueDepth = _next.depth() + 2; println(); printObject(_count++ + ": "); _valueDepth = _column; _isObject = false; return nextObject(ch); } default: throw new IllegalStateException(); } } } class ListState extends State { private static final int TYPE = 0; private static final int LENGTH = 1; private static final int VALUE = 2; private int _refId; private int _state; private int _count; private int _valueDepth; ListState(State next, int refId, boolean isType) { super(next); _refId = refId; if (isType) _state = TYPE; else { printObject("list (#" + _refId + ")"); _state = VALUE; } } @Override boolean isShift(Object value) { return _state == TYPE || _state == LENGTH; } @Override State shift(Object object) { if (_state == TYPE) { Object type = object; if (type instanceof String) { _typeDefList.add((String) type); } else if (object instanceof Integer) { int index = (Integer) object; if (index >= 0 && index < _typeDefList.size()) type = _typeDefList.get(index); else type = "type-unknown(" + index + ")"; } printObject("list " + type + "(#" + _refId + ")"); _state = VALUE; return this; } else if (_state == LENGTH) { _state = VALUE; return this; } else return this; } @Override int depth() { if (_state <= LENGTH) return _next.depth(); else if (_state == VALUE) return _valueDepth; else return _next.depth() + 2; } State next(int ch) { switch (_state) { case TYPE: return nextObject(ch); case VALUE: if (ch == 'Z') { if (_count > 0) println(); return _next; } else { _valueDepth = _next.depth() + 2; println(); printObject(_count++ + ": "); _valueDepth = _column; _isObject = false; return nextObject(ch); } default: throw new IllegalStateException(); } } } class CompactListState extends State { private static final int TYPE = 0; private static final int LENGTH = 1; private static final int VALUE = 2; private int _refId; private boolean _isTyped; private boolean _isLength; private int _state; private int _length; private int _count; private int _valueDepth; CompactListState(State next, int refId, boolean isTyped) { super(next); _isTyped = isTyped; _refId = refId; if (isTyped) _state = TYPE; else _state = LENGTH; } CompactListState(State next, int refId, boolean isTyped, int length) { super(next); _isTyped = isTyped; _refId = refId; _length = length; _isLength = true; if (isTyped) _state = TYPE; else { printObject("list (#" + _refId + ")"); _state = VALUE; } } @Override boolean isShift(Object value) { return _state == TYPE || _state == LENGTH; } @Override State shift(Object object) { if (_state == TYPE) { Object type = object; if (object instanceof Integer) { int index = (Integer) object; if (index >= 0 && index < _typeDefList.size()) type = _typeDefList.get(index); else type = "type-unknown(" + index + ")"; } else if (object instanceof String) _typeDefList.add((String) object); printObject("list " + type + " (#" + _refId + ")"); if (_isLength) { _state = VALUE; if (_length == 0) return _next; } else _state = LENGTH; return this; } else if (_state == LENGTH) { _length = (Integer) object; if (! _isTyped) printObject("list (#" + _refId + ")"); _state = VALUE; if (_length == 0) return _next; else return this; } else return this; } @Override int depth() { if (_state <= LENGTH) return _next.depth(); else if (_state == VALUE) return _valueDepth; else return _next.depth() + 2; } State next(int ch) { switch (_state) { case TYPE: return nextObject(ch); case LENGTH: return nextObject(ch); case VALUE: if (_length <= _count) return _next.next(ch); else { _valueDepth = _next.depth() + 2; println(); printObject(_count++ + ": "); _valueDepth = _column; _isObject = false; return nextObject(ch); } default: throw new IllegalStateException(); } } } class Hessian2State extends State { private static final int MAJOR = 0; private static final int MINOR = 1; private int _state; private int _major; private int _minor; Hessian2State(State next) { super(next); } int depth() { return _next.depth() + 2; } State next(int ch) { switch (_state) { case MAJOR: _major = ch; _state = MINOR; return this; case MINOR: _minor = ch; println(-2, "Hessian " + _major + "." + _minor); return _next; default: throw new IllegalStateException(); } } } class CallState1 extends State1 { private static final int MAJOR = 0; private static final int MINOR = 1; private static final int HEADER = 2; private static final int METHOD = 3; private static final int VALUE = 4; private static final int ARG = 5; private int _state; private int _major; private int _minor; CallState1(State next) { super(next); } int depth() { return _next.depth() + 2; } State next(int ch) { switch (_state) { case MAJOR: _major = ch; _state = MINOR; return this; case MINOR: _minor = ch; _state = HEADER; println(-2, "call " + _major + "." + _minor); return this; case HEADER: if (ch == 'H') { println(); print("header "); _isObject = false; _state = VALUE; return new StringState(this, 'H', true); } else if (ch == 'm') { println(); print("method "); _isObject = false; _state = ARG; return new StringState(this, 'm', true); } else { println((char) ch + ": unexpected char"); return popStack(); } case VALUE: print(" => "); _isObject = false; _state = HEADER; return nextObject(ch); case ARG: if (ch == 'z') { println(); return _next; } else return nextObject(ch); default: throw new IllegalStateException(); } } } class Call2State extends State { private static final int METHOD = 0; private static final int COUNT = 1; private static final int ARG = 2; private int _state = METHOD; private int _i; private int _count; Call2State(State next) { super(next); } int depth() { return _next.depth() + 5; } @Override boolean isShift(Object value) { return _state != ARG; } @Override State shift(Object object) { if (_state == METHOD) { println(-5, "Call " + object); _state = COUNT; return this; } else if (_state == COUNT) { Integer count = (Integer) object; _count = count; _state = ARG; if (_count == 0) { return _next; } else return this; } else { return this; } } @Override State next(int ch) { switch (_state) { case COUNT: return nextObject(ch); case METHOD: return nextObject(ch); case ARG: if (_count <= _i) { println(); return _next.next(ch); } else { println(); print(-3, _i++ + ": "); return nextObject(ch); } default: throw new IllegalStateException(); } } } class ReplyState1 extends State1 { private static final int MAJOR = 0; private static final int MINOR = 1; private static final int HEADER = 2; private static final int VALUE = 3; private static final int END = 4; private int _state; private int _major; private int _minor; ReplyState1(State next) { _next = next; } int depth() { return _next.depth() + 2; } State next(int ch) { switch (_state) { case MAJOR: if (ch == 't' || ch == 'S') return new RemoteState(this).next(ch); _major = ch; _state = MINOR; return this; case MINOR: _minor = ch; _state = HEADER; println(-2, "reply " + _major + "." + _minor); return this; case HEADER: if (ch == 'H') { _state = VALUE; return new StringState(this, 'H', true); } else if (ch == 'f') { print("fault "); _isObject = false; _state = END; return new MapState(this, 0); } else { _state = END; return nextObject(ch); } case VALUE: _state = HEADER; return nextObject(ch); case END: println(); if (ch == 'z') { return _next; } else return _next.next(ch); default: throw new IllegalStateException(); } } } class Reply2State extends State { Reply2State(State next) { super(next); println(-2, "Reply"); } int depth() { return _next.depth() + 2; } @Override State next(int ch) { if (ch < 0) { println(); return _next; } else { return nextObject(ch); } } } class Fault2State extends State { Fault2State(State next) { super(next); println(-2, "Fault"); } int depth() { return _next.depth() + 2; } @Override State next(int ch) { return nextObject(ch); } } class IndirectState extends State { IndirectState(State next) { super(next); } boolean isShift(Object object) { return _next.isShift(object); } State shift(Object object) { return _next.shift(object); } State next(int ch) { return nextObject(ch); } } class RemoteState extends State { private static final int TYPE = 0; private static final int VALUE = 1; private static final int END = 2; private int _state; private int _major; private int _minor; RemoteState(State next) { super(next); } @Override State next(int ch) { switch (_state) { case TYPE: println(-1, "remote"); if (ch == 't') { _state = VALUE; return new StringState(this, 't', false); } else { _state = END; return nextObject(ch); } case VALUE: _state = END; return _next.nextObject(ch); case END: return _next.next(ch); default: throw new IllegalStateException(); } } } class StreamingState extends State { private long _length; private int _metaLength; private boolean _isLast; private boolean _isFirst = true; private boolean _isLengthState; private State _childState; StreamingState(State next, boolean isLast) { super(next); _isLast = isLast; _childState = new InitialState(); } State next(int ch) { if (_metaLength > 0) { _length = 256 * _length + ch; _metaLength--; if (_metaLength == 0 && _isFirst) { if (_isLast) println(-1, "--- packet-start(" + _length + ")"); else println(-1, "--- packet-start(fragment)"); _isFirst = false; } return this; } if (_length > 0) { _length--; _childState = _childState.next(ch); return this; } if (! _isLengthState) { _isLengthState = true; if (_isLast) { println(-1, ""); println(-1, "--- packet-end"); _refId = 0; _isFirst = true; } _isLast = (ch & 0x80) == 0x00; _isLengthState = true; } else { _isLengthState = false; _length = (ch & 0x7f); if (_length == 0x7e) { _length = 0; _metaLength = 2; } else if (_length == 0x7f) { _length = 0; _metaLength = 8; } else { if (_isFirst) { if (_isLast) println(-1, "--- packet-start(" + _length + ")"); else println(-1, "--- packet-start(fragment)"); _isFirst = false; } } } return this; } } static class ObjectDef { private String _type; private ArrayList<String> _fields; ObjectDef(String type, ArrayList<String> fields) { _type = type; _fields = fields; } String getType() { return _type; } ArrayList<String> getFields() { return _fields; } } }