/**********************************************************\
| |
| The implementation of PHPRPC Protocol 3.0 |
| |
| PHPSerializer.java |
| |
| Release 3.0.1 |
| Copyright (c) 2005-2008 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 3.0 as published by the Free Software Foundation |
| and appearing in the included file LICENSE. |
| |
\**********************************************************/
/* PHP serialize/unserialize library.
*
* Copyright (C) 2005-2008 Ma Bingyao <andot@ujn.edu.cn>
* Version: 3.0.1
* LastModified: Feb 8, 2008
* 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.Arrays;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
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 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 __S = 83;
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";
final private class UnSerializeResult {
Object value;
int hv;
UnSerializeResult() {}
UnSerializeResult(Object value, int hv) {
this.value = value;
this.hv = hv;
}
}
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;
}
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 if (obj instanceof Date) {
hv += 8;
writeDate(stream, (Date)obj);
}
else if (!(obj instanceof java.io.Serializable)) {
writeNull(stream);
}
else if (obj instanceof AssocArray) {
obj = ((AssocArray)obj).toHashMap();
if (ht.containsKey(obj)) {
writePointRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv++));
hv = writeMap(stream, (Map) obj, ht, hv);
}
}
else if (obj.getClass().isArray()) {
if (ht.containsKey(obj)) {
writePointRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv++));
hv = writeArray(stream, obj, ht, hv);
}
}
else if (obj instanceof List) {
if (ht.containsKey(obj)) {
writePointRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
try {
obj.getClass().getConstructor(new Class[] { Collection.class });
ht.put(obj, new Integer(hv++));
hv = writeList(stream, (List) obj, ht, hv);
}
catch (NoSuchMethodException e) {
ht.put(obj, new Integer(hv++));
hv = writeObject(stream, obj, ht, hv);
}
}
}
else if (obj instanceof Collection) {
if (ht.containsKey(obj)) {
writePointRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
try {
obj.getClass().getConstructor(new Class[] { Collection.class });
ht.put(obj, new Integer(hv++));
hv = writeCollection(stream, (Collection) obj, ht, hv);
}
catch (NoSuchMethodException e) {
ht.put(obj, new Integer(hv++));
hv = writeObject(stream, obj, ht, hv);
}
}
}
else if (obj instanceof Map) {
if (ht.containsKey(obj)) {
writePointRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
try {
obj.getClass().getConstructor(new Class[] { Map.class });
ht.put(obj, new Integer(hv++));
hv = writeMap(stream, (Map) obj, ht, hv);
}
catch (NoSuchMethodException e) {
ht.put(obj, new Integer(hv++));
hv = writeObject(stream, obj, ht, hv);
}
}
}
else {
if (ht.containsKey(obj)) {
hv++;
writeRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv++));
hv = writeObject(stream, obj, ht, hv);
}
}
return hv;
}
private void writeNull(ByteArrayOutputStream stream) {
stream.write(__N);
stream.write(__Semicolon);
}
private void writeRef(ByteArrayOutputStream stream, byte[] r) {
stream.write(__r);
stream.write(__Colon);
stream.write(r, 0, r.length);
stream.write(__Semicolon);
}
private void writePointRef(ByteArrayOutputStream stream, byte[] p) {
stream.write(__R);
stream.write(__Colon);
stream.write(p, 0, p.length);
stream.write(__Semicolon);
}
private void writeBoolean(ByteArrayOutputStream stream, byte b) {
stream.write(__b);
stream.write(__Colon);
stream.write(b);
stream.write(__Semicolon);
}
private void writeInteger(ByteArrayOutputStream stream, byte[] i) {
stream.write(__i);
stream.write(__Colon);
stream.write(i, 0, i.length);
stream.write(__Semicolon);
}
private void writeDouble(ByteArrayOutputStream stream, byte[] d) {
stream.write(__d);
stream.write(__Colon);
stream.write(d, 0, d.length);
stream.write(__Semicolon);
}
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);
}
private void writeDate(ByteArrayOutputStream stream, Date date) {
byte[] typeName = getBytes("PHPRPC_Date");
byte[] classNameLen = getAsciiBytes(new Integer(typeName.length));
stream.write(__O);
stream.write(__Colon);
stream.write(classNameLen, 0, classNameLen.length);
stream.write(__Colon);
stream.write(__Quote);
stream.write(typeName, 0, typeName.length);
stream.write(__Quote);
stream.write(__Colon);
stream.write(0x37);
stream.write(__Colon);
stream.write(__LeftB);
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(date);
writeString(stream, getBytes("year"));
writeInteger(stream, getAsciiBytes(new Integer(calendar.get(Calendar.YEAR))));
writeString(stream, getBytes("month"));
writeInteger(stream, getAsciiBytes(new Integer(calendar.get(Calendar.MONTH) + 1)));
writeString(stream, getBytes("day"));
writeInteger(stream, getAsciiBytes(new Integer(calendar.get(Calendar.DATE))));
writeString(stream, getBytes("hour"));
writeInteger(stream, getAsciiBytes(new Integer(calendar.get(Calendar.HOUR_OF_DAY))));
writeString(stream, getBytes("minute"));
writeInteger(stream, getAsciiBytes(new Integer(calendar.get(Calendar.MINUTE))));
writeString(stream, getBytes("second"));
writeInteger(stream, getAsciiBytes(new Integer(calendar.get(Calendar.SECOND))));
writeString(stream, getBytes("millisecond"));
writeInteger(stream, getAsciiBytes(new Integer(0)));
stream.write(__RightB);
}
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;
}
private int writeCollection(ByteArrayOutputStream stream, Collection c, HashMap ht, int hv) {
int len = c.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);
int i = 0;
for (Iterator values = c.iterator(); values.hasNext();) {
writeInteger(stream, getAsciiBytes(new Integer(i++)));
Object value = values.next();
hv = serialize(stream, value, ht, hv);
}
stream.write(__RightB);
return hv;
}
private int writeList(ByteArrayOutputStream stream, List 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;
}
private int writeMap(ByteArrayOutputStream stream, Map 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;
}
private int writeObject(ByteArrayOutputStream stream, Object obj, HashMap ht, int hv) {
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);
}
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 String getString(byte[] b) {
try {
return new String(b, charset);
}
catch (Exception e) {
return new String(b);
}
}
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[])Cast.toArray(al, Integer.TYPE, charset);
}
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()]);
}
public static Object newInstance(Class cls) {
return newInstance(cls, true);
}
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 unserialize(byte[] ss) throws IllegalAccessException {
return unserialize(ss, Object.class);
}
synchronized public Object unserialize(byte[] ss, Class cls) throws IllegalAccessException {
ByteArrayInputStream stream = new ByteArrayInputStream(ss);
Object result = unserialize(stream, new HashMap(), 1).value;
return Cast.cast(result, cls, charset);
}
private UnSerializeResult unserialize(ByteArrayInputStream stream, HashMap ht, int hv) throws 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 __S:
obj = readEscapedString(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);
case __R:
return readPointRef(stream, ht, hv);
case __a:
return readAssocArray(stream, ht, hv);
case __O:
return readObject(stream, ht, hv);
case __C:
return readCustomObject(stream, ht, hv);
default:
assert false;
return null;
}
}
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();
}
private Object readNull(ByteArrayInputStream stream) {
stream.skip(1);
return null;
}
private Boolean readBoolean(ByteArrayInputStream stream) {
stream.skip(1);
Boolean b = new Boolean(stream.read() == __1);
stream.skip(1);
return b;
}
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);
}
}
}
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);
}
}
}
private byte[] 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);
return buf;
}
private byte[] readEscapedString(ByteArrayInputStream stream) {
stream.skip(1);
int len = Integer.parseInt(readNumber(stream));
stream.skip(1);
byte[] buf = new byte[len];
int c;
for (int i = 0; i < len; i++) {
if ((c = stream.read()) == __Slash) {
char c1 = (char) stream.read();
char c2 = (char) stream.read();
buf[i] = (byte) (Integer.parseInt(new String(new char[] { c1, c2 }), 16) & 0xff);
}
else {
buf[i] = (byte) (c & 0xff);
}
}
stream.skip(2);
return buf;
}
private String readUnicodeString(ByteArrayInputStream stream) {
stream.skip(1);
int len = Integer.parseInt(readNumber(stream));
stream.skip(1);
StringBuffer sb = new StringBuffer(len);
int c;
for (int i = 0; i < len; 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();
}
private UnSerializeResult readRef(ByteArrayInputStream stream, HashMap ht, int hv) {
stream.skip(1);
Object obj = ht.get(new Integer(readNumber(stream)));
ht.put(new Integer(hv++), obj);
return new UnSerializeResult(obj, hv);
}
private UnSerializeResult readPointRef(ByteArrayInputStream stream, HashMap ht, int hv) {
stream.skip(1);
Object obj = ht.get(new Integer(readNumber(stream)));
return new UnSerializeResult(obj, hv);
}
private UnSerializeResult readAssocArray(ByteArrayInputStream stream, HashMap ht, int hv) throws IllegalAccessException {
stream.skip(1);
int n = Integer.parseInt(readNumber(stream));
stream.skip(1);
AssocArray a = new AssocArray(n);
ht.put(new Integer(hv++), a);
for (int i = 0; i < n; i++) {
Object key;
switch (stream.read()) {
case __i:
key = Cast.cast(readInteger(stream), Integer.class);
break;
case __s:
key = Cast.cast(readString(stream), String.class, charset);
break;
case __S:
key = Cast.cast(readEscapedString(stream), String.class, charset);
break;
case __U:
key = readUnicodeString(stream);
break;
default:
assert false;
return null;
}
UnSerializeResult result = unserialize(stream, ht, hv);
hv = result.hv;
if (key instanceof Integer) {
a.set((Integer)key, result.value);
}
else {
a.set((String)key, result.value);
}
}
stream.skip(1);
return new UnSerializeResult(a, hv);
}
private UnSerializeResult readDate(ByteArrayInputStream stream, HashMap ht, int hv, int n) {
HashMap dt = new HashMap(n);
String key;
for (int i = 0; i < n; i++)
{
switch (stream.read()) {
case __s:
key = getString(readString(stream));
break;
case __S:
key = getString(readEscapedString(stream));
break;
case __U:
key = readUnicodeString(stream);
break;
default:
assert false;
return null;
}
if (stream.read() == __i) {
dt.put(key, Cast.cast(readInteger(stream), Integer.class));
}
else {
return null;
}
}
stream.skip(1);
GregorianCalendar calendar = new GregorianCalendar(
((Integer) dt.get("year")).intValue(),
((Integer) dt.get("month")).intValue() - 1,
((Integer) dt.get("day")).intValue(),
((Integer) dt.get("hour")).intValue(),
((Integer) dt.get("minute")).intValue(),
((Integer) dt.get("second")).intValue()
);
Date date = new Date(calendar.getTimeInMillis());
ht.put(new Integer(hv++), date);
ht.put(new Integer(hv++), dt.get("year"));
ht.put(new Integer(hv++), dt.get("month"));
ht.put(new Integer(hv++), dt.get("day"));
ht.put(new Integer(hv++), dt.get("hour"));
ht.put(new Integer(hv++), dt.get("minute"));
ht.put(new Integer(hv++), dt.get("second"));
ht.put(new Integer(hv++), dt.get("millisecond"));
return new UnSerializeResult(date, hv);
}
private UnSerializeResult readObject(ByteArrayInputStream stream, HashMap ht, int hv) throws 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 = getString(buf);
stream.skip(2);
int n = Integer.parseInt(readNumber(stream));
stream.skip(1);
if (cn.equals("PHPRPC_Date")) {
return readDate(stream, ht, hv, n);
}
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 = getString(readString(stream));
break;
case __S:
key = getString(readEscapedString(stream));
break;
case __U:
key = readUnicodeString(stream);
break;
default:
assert false;
return null;
}
if (key.charAt(0) == (char) 0) {
key = key.substring(key.indexOf("\0", 1) + 1);
}
UnSerializeResult result = unserialize(stream, ht, hv);
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.cast(result.value, f.getType(), charset));
}
}
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);
}
private UnSerializeResult readCustomObject(ByteArrayInputStream stream, HashMap ht, int hv) {
stream.skip(1);
int len = Integer.parseInt(readNumber(stream));
stream.skip(1);
byte[] buf = new byte[len];
stream.read(buf, 0, len);
String cn = getString(buf);
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);
}
}