blob: 7c4f7b589061406eba8c192703fd5dcf7d761722 [file] [log] [blame]
/*
* 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.alibaba.com.caucho.hessian3.io;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Debugging input stream for Hessian requests.
*/
public class HessianDebugState implements Hessian2Constants {
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;
/**
* Creates an uninitialized Hessian input stream.
*/
public HessianDebugState(PrintWriter dbg) {
_dbg = dbg;
_state = new InitialState();
}
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;
}
}
public void startTop2() {
_state = new Top2State();
}
/**
* 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);
}
void println() {
if (!_isNewline) {
_dbg.println();
_dbg.flush();
}
_isNewline = true;
_column = 0;
}
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;
}
}
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 0;
}
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;
}
}
}
class InitialState extends State {
@Override
State next(int ch) {
println();
if (ch == 'r') {
return new ReplyState(this);
} else if (ch == 'c') {
return new CallState(this);
} else
return nextObject(ch);
}
}
class Top2State extends State {
@Override
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 ReplyState(this);
} else if (ch == 'c') {
return new CallState(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;
}
@Override
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;
}
@Override
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;
}
@Override
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 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;
}
@Override
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);
}
@Override
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);
}
@Override
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;
}
@Override
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(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') {
_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(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
throw new IllegalStateException();
}
@Override
int depth() {
if (_state == TYPE)
return _next.depth();
else if (_state == KEY)
return _next.depth() + 2;
else
return _valueDepth;
}
@Override
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 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 _refId;
private int _state;
private boolean _hasData;
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;
}
@Override
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) {
throw new IllegalStateException(def + " is an unknown object type");
}
_def = _objectDefList.get(def);
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;
}
@Override
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 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 boolean _hasData;
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;
}
@Override
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 boolean _hasData;
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;
}
@Override
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);
}
@Override
int depth() {
return _next.depth() + 2;
}
@Override
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 CallState extends State {
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;
CallState(State next) {
super(next);
}
@Override
int depth() {
return _next.depth() + 2;
}
@Override
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')
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);
}
@Override
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)
return _next.next(ch);
else {
println();
print(-3, _i++ + ": ");
return nextObject(ch);
}
default:
throw new IllegalStateException();
}
}
}
class ReplyState extends State {
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;
ReplyState(State next) {
_next = next;
}
@Override
int depth() {
return _next.depth() + 2;
}
@Override
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");
}
@Override
int depth() {
return _next.depth() + 2;
}
@Override
State next(int ch) {
return nextObject(ch);
}
}
class Fault2State extends State {
Fault2State(State next) {
super(next);
println(-2, "Fault");
}
@Override
int depth() {
return _next.depth() + 2;
}
@Override
State next(int ch) {
return nextObject(ch);
}
}
class IndirectState extends State {
IndirectState(State next) {
super(next);
}
@Override
boolean isShift(Object object) {
return _next.isShift(object);
}
@Override
State shift(Object object) {
return _next.shift(object);
}
@Override
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 int _digit;
private int _length;
private boolean _isLast;
private boolean _isFirst = true;
private State _childState;
StreamingState(State next, boolean isLast) {
super(next);
_isLast = isLast;
_childState = new InitialState();
}
@Override
State next(int ch) {
if (_digit < 2) {
_length = 256 * _length + ch;
_digit++;
if (_digit == 2 && _length == 0 && _isLast) {
_refId = 0;
return _next;
} else {
if (_digit == 2)
println(-1, "packet-start(" + _length + ")");
return this;
}
} else if (_length == 0) {
_isLast = (ch == 'P');
_digit = 0;
return this;
}
_childState = _childState.next(ch);
_length--;
if (_length == 0 && _isLast) {
println(-1, "");
println(-1, "packet-end");
_refId = 0;
return _next;
} else
return this;
}
}
}