/**********************************************************\
| |
| The implementation of PHPRPC Protocol 3.0 |
| |
| PHPSerializer.java |
| |
| Release 3.0.0 beta 3 |
| Copyright (c) 2005-2007 by Team-PHPRPC |
| |
| WebSite: http://www.phprpc.org/ |
| http://www.phprpc.net/ |
| http://www.phprpc.com/ |
| http://sourceforge.net/projects/php-rpc/ |
| |
| Authors: Ma Bingyao <andot@ujn.edu.cn> |
| |
| This file may be distributed and/or modified under the |
| terms of the GNU Lesser General Public License (LGPL) |
| version 2.1 as published by the Free Software Foundation |
| and appearing in the included file LICENSE. |
| |
\**********************************************************/
/* PHP serialize/unserialize library.
*
* Copyright (C) 2006-2007 Ma Bingyao <andot@ujn.edu.cn>
* Version: 3.0.0 beta 3
* LastModified: Apr 21, 2007
* This library is free. You can redistribute it and/or modify it.
*/
package org.phprpc.util;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectStreamClass;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
final class UnSerializeResult {
public Object value;
public int hv;
public UnSerializeResult() {}
public UnSerializeResult(Object value, int hv) {
this.value = value;
this.hv = hv;
}
}
final public class PHPSerializer {
private static final byte __Quote = 34;
private static final byte __0 = 48;
private static final byte __1 = 49;
private static final byte __Colon = 58;
private static final byte __Semicolon = 59;
private static final byte __C = 67;
private static final byte __N = 78;
private static final byte __O = 79;
private static final byte __R = 82;
private static final byte __U = 85;
private static final byte __Slash = 92;
private static final byte __a = 97;
private static final byte __b = 98;
private static final byte __d = 100;
private static final byte __i = 105;
private static final byte __r = 114;
private static final byte __s = 115;
private static final byte __LeftB = 123;
private static final byte __RightB = 125;
private static final String __NAN = "NAN";
private static final String __INF = "INF";
private static final String __NINF = "-INF";
private String charset = "UTF-8";
public PHPSerializer() {}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
synchronized public byte[] serialize(Object obj) {
HashMap ht = new HashMap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
int hv = serialize(stream, obj, ht, 1);
byte[] result = stream.toByteArray();
return result;
}
synchronized private int serialize(ByteArrayOutputStream stream, Object obj, HashMap ht, int hv) {
if (obj == null) {
hv++;
writeNull(stream);
}
else if (obj instanceof Boolean) {
hv++;
writeBoolean(stream, ((Boolean) obj).booleanValue() ? __1 : __0);
}
else if ((obj instanceof Byte) ||
(obj instanceof Short) ||
(obj instanceof Integer)) {
hv++;
writeInteger(stream, getAsciiBytes(obj));
}
else if (obj instanceof Long) {
hv++;
writeDouble(stream, getAsciiBytes(obj));
}
else if (obj instanceof Float) {
hv++;
Float f = (Float) obj;
obj = f.isNaN() ? __NAN :
(!f.isInfinite() ? obj :
(f.floatValue() > 0 ? __INF : __NINF));
writeDouble(stream, getAsciiBytes(obj));
}
else if (obj instanceof Double) {
hv++;
Double d = (Double) obj;
obj = d.isNaN() ? __NAN :
(!d.isInfinite() ? obj :
(d.doubleValue() > 0 ? __INF : __NINF));
writeDouble(stream, getAsciiBytes(obj));
}
else if (obj instanceof byte[]) {
hv++;
writeString(stream, (byte[])obj);
}
else if (obj instanceof char[]) {
hv++;
writeString(stream, getBytes(new String((char[]) obj)));
}
else if ((obj instanceof Character) ||
(obj instanceof String) ||
(obj instanceof StringBuffer)) {
hv++;
writeString(stream, getBytes(obj));
}
else {
Integer h = new Integer(obj.hashCode());
if (obj.getClass().isArray()) {
if (ht.containsKey(h)) {
writePointRef(stream, getAsciiBytes(ht.get(h)));
}
else {
ht.put(h, new Integer(hv++));
hv = writeArray(stream, obj, ht, hv);
}
}
else if (obj instanceof ArrayList) {
if (ht.containsKey(h)) {
writePointRef(stream, getAsciiBytes(ht.get(h)));
}
else {
ht.put(h, new Integer(hv++));
hv = writeArrayList(stream, (ArrayList) obj, ht, hv);
}
}
else if (obj instanceof HashMap) {
if (ht.containsKey(h)) {
writePointRef(stream, getAsciiBytes(ht.get(h)));
}
else {
ht.put(h, new Integer(hv++));
hv = writeHashMap(stream, (HashMap) obj, ht, hv);
}
}
else {
if (ht.containsKey(h)) {
hv++;
writeRef(stream, getAsciiBytes(ht.get(h)));
}
else {
ht.put(h, new Integer(hv++));
hv = writeObject(stream, obj, ht, hv);
}
}
}
return hv;
}
synchronized private void writeNull(ByteArrayOutputStream stream) {
stream.write(__N);
stream.write(__Semicolon);
}
synchronized private void writeRef(ByteArrayOutputStream stream, byte[] r) {
stream.write(__r);
stream.write(__Colon);
stream.write(r, 0, r.length);
stream.write(__Semicolon);
}
synchronized private void writePointRef(ByteArrayOutputStream stream, byte[] p) {
stream.write(__R);
stream.write(__Colon);
stream.write(p, 0, p.length);
stream.write(__Semicolon);
}
synchronized private void writeBoolean(ByteArrayOutputStream stream, byte b) {
stream.write(__b);
stream.write(__Colon);
stream.write(b);
stream.write(__Semicolon);
}
synchronized private void writeInteger(ByteArrayOutputStream stream, byte[] i) {
stream.write(__i);
stream.write(__Colon);
stream.write(i, 0, i.length);
stream.write(__Semicolon);
}
synchronized private void writeDouble(ByteArrayOutputStream stream, byte[] d) {
stream.write(__d);
stream.write(__Colon);
stream.write(d, 0, d.length);
stream.write(__Semicolon);
}
synchronized private void writeString(ByteArrayOutputStream stream, byte[] s) {
byte[] slen = getAsciiBytes(new Integer(s.length));
stream.write(__s);
stream.write(__Colon);
stream.write(slen, 0, slen.length);
stream.write(__Colon);
stream.write(__Quote);
stream.write(s, 0, s.length);
stream.write(__Quote);
stream.write(__Semicolon);
}
synchronized private int writeArray(ByteArrayOutputStream stream, Object a, HashMap ht, int hv) {
int len = Array.getLength(a);
byte[] alen = getAsciiBytes(new Integer(len));
stream.write(__a);
stream.write(__Colon);
stream.write(alen, 0, alen.length);
stream.write(__Colon);
stream.write(__LeftB);
for (int i = 0; i < len; i++) {
writeInteger(stream, getAsciiBytes(new Integer(i)));
hv = serialize(stream, Array.get(a, i), ht, hv);
}
stream.write(__RightB);
return hv;
}
synchronized private int writeArrayList(ByteArrayOutputStream stream, ArrayList a, HashMap ht, int hv) {
int len = a.size();
byte[] alen = getAsciiBytes(new Integer(len));
stream.write(__a);
stream.write(__Colon);
stream.write(alen, 0, alen.length);
stream.write(__Colon);
stream.write(__LeftB);
for (int i = 0; i < len; i++) {
writeInteger(stream, getAsciiBytes(new Integer(i)));
hv = serialize(stream, a.get(i), ht, hv);
}
stream.write(__RightB);
return hv;
}
synchronized private int writeHashMap(ByteArrayOutputStream stream, HashMap h, HashMap ht, int hv) {
int len = h.size();
byte[] hlen = getAsciiBytes(new Integer(len));
stream.write(__a);
stream.write(__Colon);
stream.write(hlen, 0, hlen.length);
stream.write(__Colon);
stream.write(__LeftB);
for (Iterator keys = h.keySet().iterator(); keys.hasNext();) {
Object key = keys.next();
if ((key instanceof Byte) ||
(key instanceof Short) ||
(key instanceof Integer)) {
writeInteger(stream, getAsciiBytes(key));
}
else if (key instanceof Boolean) {
writeInteger(stream, new byte[] { ((Boolean) key).booleanValue() ? __1 : __0 });
}
else {
writeString(stream, getBytes(key));
}
hv = serialize(stream, h.get(key), ht, hv);
}
stream.write(__RightB);
return hv;
}
synchronized private int writeObject(ByteArrayOutputStream stream, Object obj, HashMap ht, int hv) {
if (obj instanceof java.io.Serializable) {
Class cls = obj.getClass();
byte[] className = getBytes(getClassName(cls));
byte[] classNameLen = getAsciiBytes(new Integer(className.length));
if (obj instanceof org.phprpc.util.Serializable) {
byte[] cs = ((org.phprpc.util.Serializable) obj).serialize();
byte[] cslen = getAsciiBytes(new Integer(cs.length));
stream.write(__C);
stream.write(__Colon);
stream.write(classNameLen, 0, classNameLen.length);
stream.write(__Colon);
stream.write(__Quote);
stream.write(className, 0, className.length);
stream.write(__Quote);
stream.write(__Colon);
stream.write(cslen, 0, cslen.length);
stream.write(__Colon);
stream.write(__LeftB);
stream.write(cs, 0, cs.length);
stream.write(__RightB);
}
else {
Method __sleep;
try {
__sleep = cls.getMethod("__sleep", new Class[] {});
}
catch (Exception e) {
__sleep = null;
}
int fl = 0;
Field[] f;
if (__sleep != null) {
String[] fieldNames;
try {
__sleep.setAccessible(true);
fieldNames = (String[]) __sleep.invoke(obj, new Object[] {});
}
catch (Exception e) {
fieldNames = null;
}
f = getFields(obj, fieldNames);
}
else {
f = getFields(obj);
}
AccessibleObject.setAccessible(f, true);
byte[] flen = getAsciiBytes(new Integer(f.length));
stream.write(__O);
stream.write(__Colon);
stream.write(classNameLen, 0, classNameLen.length);
stream.write(__Colon);
stream.write(__Quote);
stream.write(className, 0, className.length);
stream.write(__Quote);
stream.write(__Colon);
stream.write(flen, 0, flen.length);
stream.write(__Colon);
stream.write(__LeftB);
for (int i = 0, len = f.length; i < len; i++) {
int mod = f[i].getModifiers();
String fn = f[i].getName();
if (Modifier.isPublic(mod)) {
writeString(stream, getBytes(fn));
}
else if (Modifier.isProtected(mod)) {
writeString(stream, getBytes("\0*\0" + fn));
}
else {
writeString(stream, getBytes("\0" + getClassName(f[i].getDeclaringClass()) + "\0" + fn));
}
Object o;
try {
o = f[i].get(obj);
}
catch (Exception e) {
o = null;
}
hv = serialize(stream, o, ht, hv);
}
stream.write(__RightB);
}
}
else {
writeNull(stream);
}
return hv;
}
private byte[] getBytes(Object obj) {
try {
return obj.toString().getBytes(charset);
}
catch (Exception e) {
return obj.toString().getBytes();
}
}
private byte[] getAsciiBytes(Object obj) {
try {
return obj.toString().getBytes("US-ASCII");
}
catch (Exception e) {
return null;
}
}
private Class getInnerClass(StringBuffer className, int[] pos, int i, char c) {
if (i < pos.length) {
int p = pos[i];
className.setCharAt(p, c);
Class cls = getInnerClass(className, pos, i + 1, '_');
if (i + 1 < pos.length && cls == null) {
cls = getInnerClass(className, pos, i + 1, '$');
}
return cls;
}
else {
try {
return Class.forName(className.toString());
}
catch (Exception e) {
return null;
}
}
}
private Class getClass(StringBuffer className, int[] pos, int i, char c) {
if (i < pos.length) {
int p = pos[i];
className.setCharAt(p, c);
Class cls = getClass(className, pos, i + 1, '.');
if (i + 1 < pos.length) {
if (cls == null) {
cls = getClass(className, pos, i + 1, '_');
}
if (cls == null) {
cls = getInnerClass(className, pos, i + 1, '$');
}
}
return cls;
}
else {
try {
return Class.forName(className.toString());
}
catch (Exception e) {
return null;
}
}
}
public Class getClass(String className) {
StringBuffer cn = new StringBuffer(className);
ArrayList al = new ArrayList();
int p = cn.indexOf("_");
while (p > -1) {
al.add(new Integer(p));
p = cn.indexOf("_", p + 1);
}
if (al.size() > 0) {
int[] pos;
try {
pos = (int[])toArray(al, Integer.TYPE);
}
catch (Exception e) {
return null;
}
Class cls = getClass(cn, pos, 0, '.');
if (cls == null) {
cls = getClass(cn, pos, 0, '_');
}
if (cls == null) {
cls = getInnerClass(cn, pos, 0, '$');
}
return cls;
}
else {
try {
return Class.forName(className.toString());
}
catch (Exception e) {
return null;
}
}
}
private String getClassName(Class cls) {
return cls.getName().replace('.', '_').replace('$', '_');
}
private Field getField(Object obj, String fieldName) {
Class cls = obj.getClass();
while (cls != null) {
try {
Field result = cls.getDeclaredField(fieldName);
int mod = result.getModifiers();
if (Modifier.isTransient(mod) || Modifier.isStatic(mod)) {
return null;
}
return result;
}
catch (Exception e) {}
cls = cls.getSuperclass();
}
return null;
}
private Field[] getFields(Object obj, String[] fieldNames) {
if (fieldNames == null) {
return getFields(obj);
}
int n = fieldNames.length;
ArrayList fields = new ArrayList(n);
for (int i = 0; i < n; i++) {
Field f = getField(obj, fieldNames[i]);
if (f != null) {
fields.add(f);
}
}
return (Field[]) fields.toArray(new Field[fields.size()]);
}
private Field[] getFields(Object obj) {
ArrayList fields = new ArrayList();
Class cls = obj.getClass();
while (cls != null) {
Field[] fs = cls.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
int mod = fs[i].getModifiers();
if (!Modifier.isTransient(mod) && !Modifier.isStatic(mod)) {
fields.add(fs[i]);
}
}
cls = cls.getSuperclass();
}
return (Field[]) fields.toArray(new Field[fields.size()]);
}
synchronized public static Object newInstance(Class cls) {
return newInstance(cls, true);
}
synchronized private static Object newInstance(Class cls, boolean tryagain) {
try {
ObjectStreamClass desc = ObjectStreamClass.lookup(cls);
Method m = ObjectStreamClass.class.getDeclaredMethod("newInstance", new Class[] {});
m.setAccessible(true);
return m.invoke(desc, new Object[] {});
}
catch (Exception e) {
if (tryagain) {
return newInstance(cls, false);
}
else {
return null;
}
}
}
public Object cast(Number n, Class destClass) {
if (destClass == Byte.class || destClass == Byte.TYPE) {
return new Byte(n.byteValue());
}
if (destClass == Short.class || destClass == Short.TYPE) {
return new Short(n.shortValue());
}
if (destClass == Integer.class || destClass == Integer.TYPE) {
return new Integer(n.intValue());
}
if (destClass == Long.class || destClass == Long.TYPE) {
return new Long(n.longValue());
}
if (destClass == Float.class || destClass == Float.TYPE) {
return new Float(n.floatValue());
}
if (destClass == Double.class || destClass == Double.TYPE) {
return new Double(n.doubleValue());
}
if (destClass == Boolean.class || destClass == Boolean.TYPE) {
return new Boolean(n.byteValue() != 0);
}
return n;
}
public Object cast(String s, Class destClass) throws UnsupportedEncodingException {
if (destClass == char[].class) {
return s.toCharArray();
}
if (destClass == byte[].class) {
return s.getBytes(charset);
}
if (destClass == StringBuffer.class) {
return new StringBuffer(s);
}
if (destClass == Byte.class || destClass == Byte.TYPE) {
return new Byte(s);
}
if (destClass == Short.class || destClass == Short.TYPE) {
return new Short(s);
}
if (destClass == Integer.class || destClass == Integer.TYPE) {
return new Integer(s);
}
if (destClass == Long.class || destClass == Long.TYPE) {
return new Long(s);
}
if (destClass == Float.class || destClass == Float.TYPE) {
return new Float(s);
}
if (destClass == Double.class || destClass == Double.TYPE) {
return new Double(s);
}
if (destClass == Boolean.class || destClass == Boolean.TYPE) {
return new Boolean(!(s.equals("") || s.equals("0")));
}
return s;
}
synchronized public Object cast(Object obj, Class destClass) throws UnsupportedEncodingException {
if (obj == null || destClass == null || obj.getClass() == destClass) {
return obj;
}
if (destClass == Void.class || destClass == Void.TYPE) {
return null;
}
if (obj instanceof byte[]) {
return cast(new String((byte[]) obj, charset), destClass);
}
if (obj instanceof char[]) {
return cast(new String((char[]) obj), destClass);
}
if (obj instanceof StringBuffer) {
return cast(((StringBuffer) obj).toString(), destClass);
}
if (obj instanceof String) {
return cast((String) obj, destClass);
}
if (destClass == Character.class || destClass == Character.TYPE) {
return new Character(obj.toString().charAt(0));
}
if ((obj instanceof ArrayList) && destClass.isArray()) {
return toArray((ArrayList) obj, destClass.getComponentType());
}
if ((obj instanceof ArrayList) && destClass == HashMap.class) {
return toHashMap((ArrayList) obj);
}
if ((obj instanceof Boolean) && destClass.isAssignableFrom(Number.class)) {
return cast(new Integer((((Boolean) obj).booleanValue() == true) ? 1 : 0), destClass);
}
if (destClass == String.class) {
return obj.toString();
}
if (destClass == StringBuffer.class) {
return new StringBuffer(obj.toString());
}
if (!obj.getClass().isArray() && destClass == byte[].class) {
return obj.toString().getBytes(charset);
}
if (!obj.getClass().isArray() && destClass == char[].class) {
return obj.toString().toCharArray();
}
if (obj instanceof Number) {
return cast((Number) obj, destClass);
}
return obj;
}
synchronized private HashMap toHashMap(ArrayList a) {
int n = a.size();
HashMap h = new HashMap(n);
for (int i = 0; i < n; i++) {
h.put(new Integer(i), a.get(i));
}
return h;
}
synchronized private Object toArray(ArrayList obj, Class componentType) throws UnsupportedEncodingException {
int n = obj.size();
Object a = Array.newInstance(componentType, n);
for (int i = 0; i < n; i++) {
Array.set(a, i, cast(obj.get(i), componentType));
}
return a;
}
synchronized private static int getPos(ByteArrayInputStream stream) {
try {
Field pos = stream.getClass().getDeclaredField("pos");
pos.setAccessible(true);
return pos.getInt(stream);
} catch (Exception e) {
return 0;
}
}
synchronized private static void setPos(ByteArrayInputStream stream, int p) {
try {
Field pos = stream.getClass().getDeclaredField("pos");
pos.setAccessible(true);
pos.setInt(stream, p);
} catch (Exception e) {}
}
synchronized public Object unserialize(byte[] ss) throws IllegalAccessException, UnsupportedEncodingException {
return unserialize(ss, null);
}
synchronized public Object unserialize(byte[] ss, Class cls) throws IllegalAccessException, UnsupportedEncodingException {
ByteArrayInputStream stream = new ByteArrayInputStream(ss);
Object result = unserialize(stream, new HashMap(), 1, new HashMap()).value;
return cast(result, cls);
}
synchronized private UnSerializeResult unserialize(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) throws UnsupportedEncodingException, IllegalAccessException {
Object obj;
switch (stream.read()) {
case __N:
obj = readNull(stream);
ht.put(new Integer(hv++), obj);
return new UnSerializeResult(obj, hv);
case __b:
obj = readBoolean(stream);
ht.put(new Integer(hv++), obj);
return new UnSerializeResult(obj, hv);
case __i:
obj = readInteger(stream);
ht.put(new Integer(hv++), obj);
return new UnSerializeResult(obj, hv);
case __d:
obj = readDouble(stream);
ht.put(new Integer(hv++), obj);
return new UnSerializeResult(obj, hv);
case __s:
obj = readString(stream);
ht.put(new Integer(hv++), obj);
return new UnSerializeResult(obj, hv);
case __U:
obj = readUnicodeString(stream);
ht.put(new Integer(hv++), obj);
return new UnSerializeResult(obj, hv);
case __r:
return readRef(stream, ht, hv, rt);
case __R:
return readPointRef(stream, ht, hv, rt);
case __a:
return readArray(stream, ht, hv, rt);
case __O:
return readObject(stream, ht, hv, rt);
case __C:
return readCustomObject(stream, ht, hv);
default:
return null;
}
}
synchronized private String readNumber(ByteArrayInputStream stream) {
StringBuffer sb = new StringBuffer();
int i = stream.read();
while ((i != __Semicolon) && (i != __Colon)) {
sb.append((char) i);
i = stream.read();
}
return sb.toString();
}
synchronized private Object readNull(ByteArrayInputStream stream) {
stream.skip(1);
return null;
}
synchronized private Boolean readBoolean(ByteArrayInputStream stream) {
stream.skip(1);
Boolean b = new Boolean(stream.read() == __1);
stream.skip(1);
return b;
}
synchronized private Number readInteger(ByteArrayInputStream stream) {
stream.skip(1);
String i = readNumber(stream);
try {
return new Byte(i);
}
catch (Exception e1) {
try {
return new Short(i);
}
catch (Exception e2) {
return new Integer(i);
}
}
}
synchronized private Number readDouble(ByteArrayInputStream stream) {
stream.skip(1);
String d = readNumber(stream);
if (d.equals(__NAN)) {
return new Double(Double.NaN);
}
if (d.equals(__INF)) {
return new Double(Double.POSITIVE_INFINITY);
}
if (d.equals(__NINF)) {
return new Double(Double.NEGATIVE_INFINITY);
}
try {
return new Long(d);
}
catch (Exception e1) {
try {
Float f = new Float(d);
if (f.isInfinite()) {
return new Double(d);
}
else {
return f;
}
}
catch (Exception e2) {
return new Float(0);
}
}
}
synchronized private Object readString(ByteArrayInputStream stream) {
stream.skip(1);
int len = Integer.parseInt(readNumber(stream));
stream.skip(1);
byte[] buf = new byte[len];
stream.read(buf, 0, len);
stream.skip(2);
try {
return new String(buf, charset);
}
catch (Exception e) {}
return buf;
}
synchronized private String readUnicodeString(ByteArrayInputStream stream) {
stream.skip(1);
int l = Integer.parseInt(readNumber(stream));
stream.skip(1);
StringBuffer sb = new StringBuffer(l);
int c;
for (int i = 0; i < l; i++) {
if ((c = stream.read()) == __Slash) {
char c1 = (char) stream.read();
char c2 = (char) stream.read();
char c3 = (char) stream.read();
char c4 = (char) stream.read();
sb.append(
(char) (Integer.parseInt(
new String(new char[] { c1, c2, c3, c4 }), 16)));
}
else {
sb.append((char) c);
}
}
stream.skip(2);
return sb.toString();
}
synchronized private UnSerializeResult readRef(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) {
stream.skip(1);
Integer r = new Integer(readNumber(stream));
if (rt.containsKey(r)) {
rt.put(r, new Boolean(true));
}
Object obj = ht.get(r);
ht.put(new Integer(hv++), obj);
return new UnSerializeResult(obj, hv);
}
synchronized private UnSerializeResult readPointRef(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) {
stream.skip(1);
Integer r = new Integer(readNumber(stream));
if (rt.containsKey(r)) {
rt.put(r, new Boolean(true));
}
Object obj = ht.get(r);
return new UnSerializeResult(obj, hv);
}
synchronized private UnSerializeResult readArray(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) throws UnsupportedEncodingException, IllegalAccessException {
stream.skip(1);
int n = Integer.parseInt(readNumber(stream));
stream.skip(1);
int p = getPos(stream);
HashMap h = new HashMap(n);
ArrayList al = new ArrayList(n);
Integer r = new Integer(hv);
rt.put(r, new Boolean(false));
ht.put(new Integer(hv++), h);
for (int i = 0; i < n; i++) {
Object key;
switch (stream.read()) {
case __i:
key = cast(readInteger(stream), Integer.class);
break;
case __s:
key = readString(stream);
break;
case __U:
key = readUnicodeString(stream);
break;
default:
return null;
}
UnSerializeResult result = unserialize(stream, ht, hv, rt);
hv = result.hv;
if (al != null) {
if ((key instanceof Integer) && (((Integer) key).intValue() == i)) {
al.add(result.value);
}
else {
al = null;
}
}
h.put(key, result.value);
}
if (al != null) {
ht.put(r, al);
if (((Boolean) (rt.get(r))).booleanValue()) {
hv = r.intValue() + 1;
setPos(stream, p);
for (int i = 0; i < n; i++) {
int key;
switch (stream.read()) {
case __i:
key = ((Integer) cast(readInteger(stream), Integer.class)).intValue();
break;
default:
return null;
}
UnSerializeResult result = unserialize(stream, ht, hv, rt);
hv = result.hv;
al.set(key, result.value);
}
}
}
rt.remove(r);
stream.skip(1);
return new UnSerializeResult(ht.get(r), hv);
}
synchronized private UnSerializeResult readObject(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) throws UnsupportedEncodingException, IllegalAccessException {
stream.skip(1);
int len = Integer.parseInt(readNumber(stream));
stream.skip(1);
byte[] buf = new byte[len];
stream.read(buf, 0, len);
String cn = new String(buf, charset);
stream.skip(2);
int n = Integer.parseInt(readNumber(stream));
stream.skip(1);
Class cls = getClass(cn);
Object o;
if (cls != null) {
if ((o = newInstance(cls)) == null) {
o = new HashMap(n);
}
}
else {
o = new HashMap(n);
}
ht.put(new Integer(hv++), o);
for (int i = 0; i < n; i++) {
String key;
switch (stream.read()) {
case __s:
key = (String)readString(stream);
break;
case __U:
key = readUnicodeString(stream);
break;
default:
return null;
}
if (key.charAt(0) == (char) 0) {
key = key.substring(key.indexOf("\0", 1) + 1);
}
UnSerializeResult result = unserialize(stream, ht, hv, rt);
hv = result.hv;
if (o instanceof HashMap) {
((HashMap) o).put(key, result.value);
}
else {
Field f = getField(o, key);
f.setAccessible(true);
f.set(o, cast(result.value, f.getType()));
}
}
stream.skip(1);
Method __wakeup = null;
try {
__wakeup = o.getClass().getMethod("__wakeup", new Class[] {});
__wakeup.invoke(o, new Object[] {});
}
catch (Exception e) {}
return new UnSerializeResult(o, hv);
}
synchronized private UnSerializeResult readCustomObject(ByteArrayInputStream stream, HashMap ht, int hv) throws UnsupportedEncodingException {
stream.skip(1);
int len = Integer.parseInt(readNumber(stream));
stream.skip(1);
byte[] buf = new byte[len];
stream.read(buf, 0, len);
String cn = new String(buf, charset);
stream.skip(2);
int n = Integer.parseInt(readNumber(stream));
stream.skip(1);
Class cls = getClass(cn);
Object o;
if (cls != null) {
o = newInstance(cls);
}
else {
o = null;
}
ht.put(new Integer(hv++), o);
if (o == null) {
stream.skip(n);
}
else if (o instanceof org.phprpc.util.Serializable) {
byte[] b = new byte[n];
stream.read(b, 0, n);
((org.phprpc.util.Serializable) o).unserialize(b);
}
else {
stream.skip(n);
}
stream.skip(1);
return new UnSerializeResult(o, hv);
}
}