/**********************************************************\
| |
| The implementation of PHPRPC Protocol 3.0 |
| |
| PHPSerializer.java |
| |
| Release 3.0.2 |
| Copyright 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: Ma Bingyao <andot@ujn.edu.cn>
* Version: 3.0.2
* LastModified: Apr 26, 2009
* 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.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
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;
public final class PHPSerializer {
private static final HashMap clscache = new HashMap();
private static final HashMap fieldcache = new HashMap();
private static final HashMap __sleepcache = new HashMap();
private static final HashMap __wakeupcache = new HashMap();
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";
private static Class enumClass;
private static Field enumOrdinal;
static {
try {
enumClass = Class.forName("java.lang.Enum");
enumOrdinal = enumClass.getDeclaredField("ordinal");
enumOrdinal.setAccessible(true);
}
catch (Exception e) {
enumClass = null;
enumOrdinal = null;
}
}
public PHPSerializer() {}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
public byte[] serialize(Object obj) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
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) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
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[]) {
if (ht.containsKey(obj)) {
writeRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv));
writeString(stream, (byte[])obj);
}
hv++;
}
else if (obj instanceof char[]) {
if (ht.containsKey(obj)) {
writeRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv));
writeString(stream, getBytes(new String((char[]) obj)));
}
hv++;
}
else if ((obj instanceof Character) ||
(obj instanceof String) ||
(obj instanceof StringBuffer)) {
if (ht.containsKey(obj)) {
writeRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv));
writeString(stream, getBytes(obj));
}
hv++;
}
else if ((obj instanceof BigInteger) ||
(obj instanceof BigDecimal) ||
(obj instanceof Number)) {
if (ht.containsKey(obj)) {
writeRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv));
writeString(stream, getAsciiBytes(obj));
}
hv++;
}
else if (obj instanceof Date) {
if (ht.containsKey(obj)) {
hv++;
writeRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv));
hv += 8;
writeDate(stream, (Date)obj);
}
}
else if (obj instanceof Calendar) {
if (ht.containsKey(obj)) {
hv++;
writeRef(stream, getAsciiBytes(ht.get(obj)));
}
else {
ht.put(obj, new Integer(hv));