/*******************************************************************************
* Copyright 2010 Cees De Groot, Alex Boisvert, Jan Kotek
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package jdbm.helper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Properties;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import jdbm.recman.BlockIo;
/**
* Serialization util. It reduces serialized data size for most common java types.
* <p>
* Common pattern is one byte header which identifies data type, then size is written (if required) and
* data.
* <p>
* On unknown types normal java serialization is used
*
* <p>
* Header byte values bellow 180 are reserved by author for future use. If you want to customize
* this class, use values over 180, to be compatible with future updates.
*
*
* @author Jan Kotek
*/
@SuppressWarnings("unchecked")
public final class Serialization
{
public static final byte END_OF_NORMAL_SERIALIZATION = 111;
/** print statistics to STDOUT */
public static final boolean DEBUG = false;
/** if set to true, debug informations will be saved to store to make it more robust */
public static final boolean DEBUGSTORE = false;
private static final int DEBUGSTORE_DUMMY_START = 456456567;
private static final int DEBUGSTORE_DUMMY_END = 1234456;
public final static int NULL = 0;
public final static int NORMAL = 1;
public final static int BOOLEAN_TRUE = 2;
public final static int BOOLEAN_FALSE = 3;
public final static int INTEGER_MINUS_1 = 4;
public final static int INTEGER_0 = 5;
public final static int INTEGER_1 = 6;
public final static int INTEGER_2 = 7;
public final static int INTEGER_3 = 8;
public final static int INTEGER_4 = 9;
public final static int INTEGER_5 = 10;
public final static int INTEGER_6 = 11;
public final static int INTEGER_7 = 12;
public final static int INTEGER_8 = 13;
public final static int INTEGER_255 = 14;
public final static int INTEGER_PACK_NEG= 15;
public final static int INTEGER_PACK = 16;
public final static int LONG_MINUS_1 = 17;
public final static int LONG_0 = 18;
public final static int LONG_1 = 19;
public final static int LONG_2 = 20;
public final static int LONG_3 = 21;
public final static int LONG_4 = 22;
public final static int LONG_5 = 23;
public final static int LONG_6 = 24;
public final static int LONG_7 = 25;
public final static int LONG_8 = 26;
public final static int LONG_PACK_NEG = 27;
public final static int LONG_PACK = 28;
public final static int LONG_255 = 29;
public final static int LONG_MINUS_MAX = 30;
public final static int SHORT_MINUS_1 = 31;
public final static int SHORT_0 = 32;
public final static int SHORT_1 = 33;
public final static int SHORT_255 = 34;
public final static int SHORT_FULL = 35;
public final static int BYTE_MINUS_1 = 36;
public final static int BYTE_0 = 37;
public final static int BYTE_1 = 38;
public final static int BYTE_FULL = 39;
public final static int CHAR = 40;
public final static int FLOAT_MINUS_1 = 41;
public final static int FLOAT_0 = 42;
public final static int FLOAT_1 = 43;
public final static int FLOAT_255 = 44;
public final static int FLOAT_SHORT = 45;
public final static int FLOAT_FULL = 46;
public final static int DOUBLE_MINUS_1 = 47;
public final static int DOUBLE_0 = 48;
public final static int DOUBLE_1 = 49;
public final static int DOUBLE_255 = 50;
public final static int DOUBLE_SHORT = 51;
public final static int DOUBLE_FULL = 52;
//TODO serialization for bigdecimal and biginteger
public final static int BIGDECIMAL_255 = 53;
public final static int BIGDECIMAL = 54;
public final static int BIGINTEGER_255 = 55;
public final static int BIGINTEGER = 56;
public final static int INTEGER_MINUS_MAX= 57;
public final static int ARRAY_INT_B_255 = 60;
public final static int ARRAY_INT_B_INT = 61;
public final static int ARRAY_INT_S = 62;
public final static int ARRAY_INT_I = 63;
public final static int ARRAY_INT_PACKED = 64;
public final static int ARRAY_LONG_B = 65;
public final static int ARRAY_LONG_S = 66;
public final static int ARRAY_LONG_I = 67;
public final static int ARRAY_LONG_L = 68;
public final static int ARRAY_LONG_PACKED = 69;
public final static int ARRAY_BYTE_255 = 70;
public final static int ARRAY_BYTE_INT = 71;
public final static int ARRAY_OBJECT_255 = 72;
public final static int ARRAY_OBJECT = 73;
//special cases for BTree values which stores references
public final static int ARRAY_OBJECT_PACKED_LONG = 74;
public final static int ARRAYLIST_PACKED_LONG = 75;
public final static int STRING_EMPTY = 101;
public final static int STRING_255 = 102;
public final static int STRING = 103;
public final static int ARRAYLIST_255 = 104;
public final static int ARRAYLIST = 105;
public final static int TREEMAP_255 = 106;
public final static int TREEMAP = 107;
public final static int HASHMAP_255 = 108;
public final static int HASHMAP = 109;
public final static int LINKEDHASHMAP_255 = 110;
public final static int LINKEDHASHMAP = 111;
public final static int TREESET_255 = 112;
public final static int TREESET = 113;
public final static int HASHSET_255 = 114;
public final static int HASHSET = 115;
public final static int LINKEDHASHSET_255 = 116;
public final static int LINKEDHASHSET = 117;
public final static int LINKEDLIST_255 = 118;
public final static int LINKEDLIST = 119;
public final static int VECTOR_255 = 120;
public final static int VECTOR = 121;
public final static int HASHTABLE_255 = 122;
public final static int HASHTABLE = 123;
public final static int PROPERTIES_255 = 124;
public final static int PROPERTIES = 125;
public final static int CLASS = 126;
public final static int STOREREFERENCE = 160;
public final static int BLOCKIO = 161;
public static final int BPAGE_LEAF = 162;
public static final int BPAGE_NONLEAF = 163;
public static final int HTREE_BUCKET = 164;
public static final int HTREE_DIRECTORY = 165;
public static final int JAVA_SERIALIZATION = 172;
/**
* Serialize the object into a byte array.
*/
public static byte[] serialize( Object obj )
throws IOException
{
ByteArrayOutputStream ba = new ByteArrayOutputStream();
DataOutputStream da = new DataOutputStream(ba);
writeObject(da,obj);
da.close();
return ba.toByteArray();
}
public static void writeObject(final DataOutputStream out, final Object obj) throws IOException {
final int written = DEBUG?out.size():0;
final Class clazz = obj!=null?obj.getClass():null;
if(DEBUGSTORE){
out.writeInt(DEBUGSTORE_DUMMY_START);
}
if(obj == null){
out.write(NULL);
}else if (clazz == Boolean.class){
if(((Boolean)obj).booleanValue())
out.write(BOOLEAN_TRUE);
else
out.write(BOOLEAN_FALSE);
}else if (clazz == Integer.class){
final int val = (Integer) obj;
writeInteger(out, val);
}else if (clazz == Double.class){
double v = (Double) obj;
if(v == -1d)
out.write(DOUBLE_MINUS_1);
else if(v == 0d)
out.write(DOUBLE_0);
else if(v == 1d)
out.write(DOUBLE_1);
else if(v >= 0&& v<=255 && (int)v == v){
out.write(DOUBLE_255);
out.write((int) v);
}else if(v >= Short.MIN_VALUE&& v<=Short.MAX_VALUE && (short)v == v){
out.write(DOUBLE_SHORT);
out.writeShort((int) v);
}else{
out.write(DOUBLE_FULL);
out.writeDouble(v);
}
}else if (clazz == Float.class){
float v = (Float) obj;
if(v == -1f)
out.write(FLOAT_MINUS_1);
else if(v == 0f)
out.write(FLOAT_0);
else if(v == 1f)
out.write(FLOAT_1);
else if(v >= 0&& v<=255 && (int)v == v){
out.write(FLOAT_255);
out.write((int) v);
}else if(v >= Short.MIN_VALUE&& v<=Short.MAX_VALUE && (short)v == v){
out.write(FLOAT_SHORT);
out.writeShort((int) v);
}else{
out.write(FLOAT_FULL);
out.writeFloat(v);
}
}else if (clazz == Long.class){
final long val = (Long) obj;
writeLong(out, val);
}else if (clazz == Short.class){
short val = (Short)obj;
if(val == -1)
out.write(SHORT_MINUS_1);
else if(val == 0)
out.write(SHORT_0);
else if(val == 1)
out.write(SHORT_1);
else if(val > 0 && val<255){
out.write(SHORT_255);
out.write(val);
}else{
out.write(SHORT_FULL);
out.writeShort(val);
}
}else if (clazz == Byte.class){
byte val = (Byte)obj;
if(val == -1)
out.write(BYTE_MINUS_1);
else if(val == 0)
out.write(BYTE_0);
else if(val == 1)
out.write(BYTE_1);
else{
out.write(SHORT_FULL);
out.writeByte(val);
}
}else if (clazz == Character.class){
out.write(CHAR);
out.writeChar((Character)obj);
}else if (clazz == BlockIo.class){
out.write(BLOCKIO);
((BlockIo)obj).writeExternal(out);
}else if (clazz == StoreReference.class){
out.write(STOREREFERENCE);
((StoreReference)obj).writeExternal(out);
}else if(clazz == String.class){
byte[] s = ((String)obj).getBytes();
if(s.length==0){
out.write(STRING_EMPTY);
}else if(s.length<255){
out.write(STRING_255);
out.write(s.length);
}else{
out.write(STRING);
LongPacker.packInt(out, s.length);
}
out.write(s);
}else if(obj instanceof Class){
out.write(CLASS);
writeObject(out, ((Class)obj).getName());
}else if(obj instanceof int[]){
writeIntArray(out,(int[])obj);
}else if(obj instanceof long[]){
writeLongArray(out,(long[])obj);
}else if(obj instanceof byte[]){
byte[] b = (byte[]) obj;
if(b.length<=255){
out.write(ARRAY_BYTE_255);
out.write(b.length);
}else{
out.write(ARRAY_BYTE_INT);
LongPacker.packInt(out,b.length);
}
out.write(b);
}else if(obj instanceof Object[]){
Object[] b = (Object[]) obj;
if(b.length<=255){
//check if it contains packable longs
boolean packableLongs = true;
for(Object o:b){
if(o!=null && (o.getClass() != Long.class || (((Long)o).longValue()<0 && ((Long)o).longValue()!=Long.MAX_VALUE))){
packableLongs = false;
break;
}
}
if(packableLongs){
out.write(ARRAY_OBJECT_PACKED_LONG);
out.write(b.length);
for(Object o : b){
if(o == null)
LongPacker.packLong(out,0);
else
LongPacker.packLong(out,((Long)o).longValue()+1);
}
}else{
out.write(ARRAY_OBJECT_255);
out.write(b.length);
for(Object o : b)
writeObject(out,o);
}
}else{
out.write(ARRAY_OBJECT);
LongPacker.packInt(out,b.length);
for(Object o : b)
writeObject(out,o);
}
}else if(clazz == ArrayList.class){
ArrayList l = (ArrayList) obj;
if(l.size()<255){
//check if it contains packable longs
boolean packableLongs = true;
for(Object o:l){
if(o!=null && (o.getClass() != Long.class || (((Long)o).longValue()<0 && ((Long)o).longValue()!=Long.MAX_VALUE))){
packableLongs = false;
break;
}
}
if(packableLongs){
out.write(ARRAYLIST_PACKED_LONG);
out.write(l.size());
for(Object o : l){
if(o == null)
LongPacker.packLong(out,0);
else
LongPacker.packLong(out,((Long)o).longValue()+1);
}
}else{
out.write(ARRAYLIST_255);
out.write(l.size());
for(Object o:l)
writeObject(out, o);
}
}else{
out.write(ARRAYLIST);
LongPacker.packInt(out,l.size());
for(Object o:l)
writeObject(out, o);
}
}else if(clazz == LinkedList.class){
LinkedList l = (LinkedList) obj;
if(l.size()<255){
out.write(LINKEDLIST_255);
out.write(l.size());
}else{
out.write(LINKEDLIST);
LongPacker.packInt(out,l.size());
}
for(Object o:l)
writeObject(out, o);
}else if(clazz == Vector.class){
Vector l = (Vector) obj;
if(l.size()<255){
out.write(VECTOR_255);
out.write(l.size());
}else{
out.write(VECTOR);
LongPacker.packInt(out,l.size());
}
for(Object o:l)
writeObject(out, o);
}else if(clazz == TreeSet.class){
TreeSet l = (TreeSet) obj;
if(l.size()<255){
out.write(TREESET_255);
out.write(l.size());
}else{
out.write(TREESET);
LongPacker.packInt(out,l.size());
}
writeObject(out,l.comparator());
for(Object o:l)
writeObject(out, o);
}else if(clazz == HashSet.class){
HashSet l = (HashSet) obj;
if(l.size()<255){
out.write(HASHSET_255);
out.write(l.size());
}else{
out.write(HASHSET);
LongPacker.packInt(out,l.size());
}
for(Object o:l)
writeObject(out, o);
}else if(clazz == LinkedHashSet.class){
LinkedHashSet l = (LinkedHashSet) obj;
if(l.size()<255){
out.write(LINKEDHASHSET_255);
out.write(l.size());
}else{
out.write(LINKEDHASHSET);
LongPacker.packInt(out,l.size());
}
for(Object o:l)
writeObject(out, o);
}else if(clazz == TreeMap.class){
TreeMap l = (TreeMap) obj;
if(l.size()<255){
out.write(TREEMAP_255);
out.write(l.size());
}else{
out.write(TREEMAP);
LongPacker.packInt(out,l.size());
}
writeObject(out, l.comparator());
for(Object o:l.keySet()){
writeObject(out, o);
writeObject(out, l.get(o));
}
}else if(clazz == HashMap.class){
HashMap l = (HashMap) obj;
if(l.size()<255){
out.write(HASHMAP_255);
out.write(l.size());
}else{
out.write(HASHMAP);
LongPacker.packInt(out,l.size());
}
for(Object o:l.keySet()){
writeObject(out, o);
writeObject(out, l.get(o));
}
}else if(clazz == LinkedHashMap.class){
LinkedHashMap l = (LinkedHashMap) obj;
if(l.size()<255){
out.write(LINKEDHASHMAP_255);
out.write(l.size());
}else{
out.write(LINKEDHASHMAP);
LongPacker.packInt(out,l.size());
}
for(Object o:l.keySet()){
writeObject(out, o);
writeObject(out, l.get(o));
}
}else if(clazz == Hashtable.class){
Hashtable l = (Hashtable) obj;
if(l.size()<255){
out.write(HASHTABLE_255);
out.write(l.size());
}else{
out.write(HASHTABLE);
LongPacker.packInt(out,l.size());
}
for(Object o:l.keySet()){
writeObject(out, o);
writeObject(out, l.get(o));
}
}else if(clazz == Properties.class){
Properties l = (Properties) obj;
if(l.size()<255){
out.write(PROPERTIES_255);
out.write(l.size());
}else{
out.write(PROPERTIES);
LongPacker.packInt(out,l.size());
}
for(Object o:l.keySet()){
writeObject(out, o);
writeObject(out, l.get(o));
}
}else{
out.write(serializeNormal(obj));
out.writeByte(END_OF_NORMAL_SERIALIZATION);
}
if(DEBUGSTORE){
out.writeInt(DEBUGSTORE_DUMMY_END);
}
if(DEBUG){
System.out.println("SERIAL write object: "+(clazz!=null?clazz.getSimpleName():"null")+ " - " +(out.size() - written)+"B - "+obj);
}
}
private static void writeLongArray(DataOutputStream da, long[] obj) throws IOException {
long max = Long.MIN_VALUE;
long min = Long.MAX_VALUE;
for(long i:obj){
max = Math.max(max, i);
min = Math.min(min, i);
}
if(0<=min && max<=255){
da.write(ARRAY_LONG_B);
LongPacker.packInt(da,obj.length);
for(long l : obj)
da.write((int) l);
}else if(0<=min && max<=Long.MAX_VALUE){
da.write(ARRAY_LONG_PACKED);
LongPacker.packInt(da,obj.length);
for(long l : obj)
LongPacker.packLong(da, l);
}else if(Short.MIN_VALUE<=min && max<=Short.MAX_VALUE){
da.write(ARRAY_LONG_S);
LongPacker.packInt(da,obj.length);
for(long l : obj)
da.writeShort((short) l);
}else if(Integer.MIN_VALUE<=min && max<=Integer.MAX_VALUE){
da.write(ARRAY_LONG_I);
LongPacker.packInt(da,obj.length);
for(long l : obj)
da.writeInt((int) l);
}else{
da.write(ARRAY_LONG_L);
LongPacker.packInt(da,obj.length);
for(long l : obj)
da.writeLong(l);
}
}
private static void writeIntArray(DataOutputStream da, int[] obj) throws IOException {
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(int i:obj){
max = Math.max(max, i);
min = Math.min(min, i);
}
boolean fitsInByte = 0<=min && max<=255;
boolean fitsInShort = Short.MIN_VALUE>=min && max<=Short.MAX_VALUE;
if(obj.length<=255 && fitsInByte){
da.write(ARRAY_INT_B_255);
da.write(obj.length);
for(int i:obj)
da.write(i);
}else if(fitsInByte){
da.write(ARRAY_INT_B_INT);
LongPacker.packInt(da,obj.length);
for(int i:obj)
da.write(i);
}else if(0<=min && max<=Integer.MAX_VALUE){
da.write(ARRAY_INT_PACKED);
LongPacker.packInt(da,obj.length);
for(int l : obj)
LongPacker.packInt(da, l);
} else if(fitsInShort){
da.write(ARRAY_INT_S);
LongPacker.packInt(da,obj.length);
for(int i:obj)
da.writeShort(i);
}else{
da.write(ARRAY_INT_I);
LongPacker.packInt(da,obj.length);
for(int i:obj)
da.writeInt(i);
}
}
private static void writeInteger(DataOutputStream da, final int val) throws IOException {
if(val == -1)
da.write(INTEGER_MINUS_1);
else if (val == 0)
da.write(INTEGER_0);
else if (val == 1)
da.write(INTEGER_1);
else if (val == 2)
da.write(INTEGER_2);
else if (val == 3)
da.write(INTEGER_3);
else if (val == 4)
da.write(INTEGER_4);
else if (val == 5)
da.write(INTEGER_5);
else if (val == 6)
da.write(INTEGER_6);
else if (val == 7)
da.write(INTEGER_7);
else if (val == 8)
da.write(INTEGER_8);
else if (val == Integer.MIN_VALUE)
da.write(INTEGER_MINUS_MAX);
else if(val >0 && val<255){
da.write(INTEGER_255);
da.write(val);
}else if(val <0){
da.write(INTEGER_PACK_NEG);
LongPacker.packInt(da, -val);
}else{
da.write(INTEGER_PACK);
LongPacker.packInt(da, val);
}
}
private static void writeLong(DataOutputStream da, final long val) throws IOException {
if(val == -1)
da.write(LONG_MINUS_1);
else if (val == 0)
da.write(LONG_0);
else if (val == 1)
da.write(LONG_1);
else if (val == 2)
da.write(LONG_2);
else if (val == 3)
da.write(LONG_3);
else if (val == 4)
da.write(LONG_4);
else if (val == 5)
da.write(LONG_5);
else if (val == 6)
da.write(LONG_6);
else if (val == 7)
da.write(LONG_7);
else if (val == 8)
da.write(LONG_8);
else if (val == Long.MIN_VALUE)
da.write(LONG_MINUS_MAX);
else if(val >0 && val<255){
da.write(LONG_255);
da.write((int) val);
}else if(val <0){
da.write(LONG_PACK_NEG);
LongPacker.packLong(da, -val);
}else{
da.write(LONG_PACK);
LongPacker.packLong(da, val);
}
}
/**
* Deserialize an object from a byte array
* @throws IOException
* @throws ClassNotFoundException
*/
public static Object deserialize( byte[] buf ) throws ClassNotFoundException, IOException{
ByteArrayInputStream bs = new ByteArrayInputStream(buf);
DataInputStream das = new DataInputStream(bs);
Object ret = readObject(das);
if(bs.available()!=0)
throw new InternalError("bytes left: "+bs.available());
return ret;
}
private static String deserializeString(DataInputStream buf) throws IOException {
int len = LongPacker.unpackInt(buf);
byte[] b= new byte[len];
buf.readFully(b);
return new String(b);
}
private static String deserializeString256Smaller(DataInputStream buf) throws IOException {
int len = buf.read();
if (len < 0)
throw new EOFException();
byte[] b= new byte[len];
buf.readFully(b);
return new String(b);
}
/**
* Serialize the object into a byte array.
*/
protected static byte[] serializeNormal( Object obj )
throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(NORMAL);
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject( obj );
oos.close();
return baos.toByteArray();
}
/**
* Deserialize an object from a byte array
*/
protected static Object deserializeNormal(DataInputStream buf )
throws ClassNotFoundException, IOException
{
ObjectInputStream ois = new ObjectInputStream( buf );
Object ret = ois.readObject();
if(buf.readByte()!=END_OF_NORMAL_SERIALIZATION)
throw new IOException("Wrong magic after serialization, maybe is Externalizable and wrong amount of bytes was read?");
return ret;
}
public static Object readObject(DataInputStream is) throws IOException, ClassNotFoundException{
final int available = DEBUG?is.available():0;
Object ret = null;
if(DEBUGSTORE && is.readInt()!=DEBUGSTORE_DUMMY_START){
throw new InternalError("Wrong offset");
}
int head = is.read();
switch(head){
case NULL:ret= null;break;
case NORMAL:ret= deserializeNormal(is);break;
case BOOLEAN_TRUE:ret= true;break;
case BOOLEAN_FALSE:ret= false;break;
case INTEGER_MINUS_1:ret= Integer.valueOf(-1);break;
case INTEGER_0:ret= Integer.valueOf(0);break;
case INTEGER_1:ret= Integer.valueOf(1);break;
case INTEGER_2:ret= Integer.valueOf(2);break;
case INTEGER_3:ret= Integer.valueOf(3);break;
case INTEGER_4:ret= Integer.valueOf(4);break;
case INTEGER_5:ret= Integer.valueOf(5);break;
case INTEGER_6:ret= Integer.valueOf(6);break;
case INTEGER_7:ret= Integer.valueOf(7);break;
case INTEGER_8:ret= Integer.valueOf(8);break;
case INTEGER_MINUS_MAX:ret= Integer.valueOf(Integer.MIN_VALUE);break;
case INTEGER_255:ret= Integer.valueOf(is.read());break;
case INTEGER_PACK_NEG:ret= Integer.valueOf(-LongPacker.unpackInt(is));break;
case INTEGER_PACK:ret= Integer.valueOf(LongPacker.unpackInt(is));break;
case LONG_MINUS_1:ret= Long.valueOf(-1);break;
case LONG_0:ret= Long.valueOf(0);break;
case LONG_1:ret= Long.valueOf(1);break;
case LONG_2:ret= Long.valueOf(2);break;
case LONG_3:ret= Long.valueOf(3);break;
case LONG_4:ret= Long.valueOf(4);break;
case LONG_5:ret= Long.valueOf(5);break;
case LONG_6:ret= Long.valueOf(6);break;
case LONG_7:ret= Long.valueOf(7);break;
case LONG_8:ret= Long.valueOf(8);break;
case LONG_255:ret= Long.valueOf(is.read());break;
case LONG_PACK_NEG:ret= Long.valueOf(-LongPacker.unpackLong(is));break;
case LONG_PACK:ret= Long.valueOf(LongPacker.unpackLong(is));break;
case LONG_MINUS_MAX:ret= Long.valueOf(Long.MIN_VALUE);break;
case SHORT_MINUS_1:ret= Short.valueOf((short)-1);break;
case SHORT_0:ret= Short.valueOf((short)0);break;
case SHORT_1:ret= Short.valueOf((short)1);break;
case SHORT_255:ret= Short.valueOf((short)is.read());break;
case SHORT_FULL:ret= Short.valueOf(is.readShort());break;
case BYTE_MINUS_1:ret= Byte.valueOf((byte)-1);break;
case BYTE_0:ret= Byte.valueOf((byte)0);break;
case BYTE_1:ret= Byte.valueOf((byte)1);break;
case BYTE_FULL:ret= Byte.valueOf(is.readByte());break;
case CHAR:ret= Character.valueOf(is.readChar());break;
case FLOAT_MINUS_1:ret= Float.valueOf(-1);break;
case FLOAT_0:ret= Float.valueOf(0);break;
case FLOAT_1:ret= Float.valueOf(1);break;
case FLOAT_255:ret= Float.valueOf(is.read());break;
case FLOAT_SHORT:ret= Float.valueOf(is.readShort());break;
case FLOAT_FULL:ret= Float.valueOf(is.readFloat());break;
case DOUBLE_MINUS_1:ret= Double.valueOf(-1);break;
case DOUBLE_0:ret= Double.valueOf(0);break;
case DOUBLE_1:ret= Double.valueOf(1);break;
case DOUBLE_255:ret= Double.valueOf(is.read());break;
case DOUBLE_SHORT:ret= Double.valueOf(is.readShort());break;
case DOUBLE_FULL:ret= Double.valueOf(is.readDouble());break;
case BLOCKIO:ret= deserializeBlockIo(is);break;
case STOREREFERENCE:ret= deserializeStoreReference(is);break;
case STRING_255:ret= deserializeString256Smaller(is);break;
case STRING:ret= deserializeString(is);break;
case STRING_EMPTY:ret= "";break;
case ARRAYLIST_255:ret= deserializeArrayList256Smaller(is);break;
case ARRAYLIST:ret= deserializeArrayList(is);break;
case ARRAYLIST_PACKED_LONG:ret= deserializeArrayListPackedLong(is);break;
case ARRAY_OBJECT_255:ret= deserializeArrayObject256Smaller(is);break;
case ARRAY_OBJECT:ret= deserializeArrayObject(is);break;
case ARRAY_OBJECT_PACKED_LONG:ret= deserializeArrayObjectPackedLong(is);break;
case LINKEDLIST_255:ret= deserializeLinkedList256Smaller(is);break;
case LINKEDLIST:ret= deserializeLinkedList(is);break;
case TREESET_255:ret= deserializeTreeSet256Smaller(is);break;
case TREESET:ret= deserializeTreeSet(is);break;
case HASHSET_255:ret= deserializeHashSet256Smaller(is);break;
case HASHSET:ret= deserializeHashSet(is);break;
case LINKEDHASHSET_255:ret= deserializeLinkedHashSet256Smaller(is);break;
case LINKEDHASHSET:ret= deserializeLinkedHashSet(is);break;
case VECTOR_255:ret= deserializeVector256Smaller(is);break;
case VECTOR:ret= deserializeVector(is);break;
case TREEMAP_255:ret= deserializeTreeMap256Smaller(is);break;
case TREEMAP:ret= deserializeTreeMap(is);break;
case HASHMAP_255:ret= deserializeHashMap256Smaller(is);break;
case HASHMAP:ret= deserializeHashMap(is);break;
case LINKEDHASHMAP_255:ret= deserializeLinkedHashMap256Smaller(is);break;
case LINKEDHASHMAP:ret= deserializeLinkedHashMap(is);break;
case HASHTABLE_255:ret= deserializeHashtable256Smaller(is);break;
case HASHTABLE:ret= deserializeHashtable(is);break;
case PROPERTIES_255:ret= deserializeProperties256Smaller(is);break;
case PROPERTIES:ret= deserializeProperties(is);break;
case CLASS:ret= deserializeClass(is);break;
case ARRAY_INT_B_255: ret= deserializeArrayIntB255(is);break;
case ARRAY_INT_B_INT: ret= deserializeArrayIntBInt(is);break;
case ARRAY_INT_S: ret= deserializeArrayIntSInt(is);break;
case ARRAY_INT_I: ret= deserializeArrayIntIInt(is);break;
case ARRAY_INT_PACKED: ret= deserializeArrayIntPack(is);break;
case ARRAY_LONG_B: ret= deserializeArrayLongB(is);break;
case ARRAY_LONG_S: ret= deserializeArrayLongS(is);break;
case ARRAY_LONG_I: ret= deserializeArrayLongI(is);break;
case ARRAY_LONG_L: ret= deserializeArrayLongL(is);break;
case ARRAY_LONG_PACKED: ret= deserializeArrayLongPack(is);break;
case ARRAY_BYTE_255: ret= deserializeArrayByte255(is);break;
case ARRAY_BYTE_INT: ret= deserializeArrayByteInt(is);break;
case BPAGE_LEAF: throw new InternalError("BPage header, wrong serializer used");
case BPAGE_NONLEAF: throw new InternalError("BPage header, wrong serializer used");
case JAVA_SERIALIZATION: throw new InternalError("Wrong header, data were propably serialized with OutputStream, not with JDBM serialization");
case -1: throw new EOFException();
default: throw new InternalError("Unknown serialization header: "+head);
}
if(DEBUG){
System.out.println("SERIAL read object: "+ret.getClass().getSimpleName()+" - "+(available-is.available())+"B - "+ ret);
}
if(DEBUGSTORE && is.readInt()!=DEBUGSTORE_DUMMY_END){
throw new InternalError("Wrong offset '"+ret+ "' - "+ret.getClass());
}
return ret;
}
private static Class deserializeClass(DataInputStream is) throws IOException, ClassNotFoundException {
String className = (String) readObject(is);
Class cls = Class.forName(className);
return cls;
}
private static StoreReference deserializeStoreReference(DataInputStream is) throws IOException {
StoreReference r = new StoreReference();
r.readExternal(is);
return r;
}
private static byte[] deserializeArrayByteInt(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
byte[] b = new byte[size];
is.readFully(b);
return b;
}
private static byte[] deserializeArrayByte255(DataInputStream is) throws IOException {
int size = is.read();
if (size < 0)
throw new EOFException();
byte[] b = new byte[size];
is.readFully(b);
return b;
}
private static long[] deserializeArrayLongL(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
long[] ret = new long[size];
for(int i=0;i<size;i++)
ret[i] = is.readLong();
return ret;
}
private static long[] deserializeArrayLongI(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
long[] ret = new long[size];
for(int i=0;i<size;i++)
ret[i] = is.readInt();
return ret;
}
private static long[] deserializeArrayLongS(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
long[] ret = new long[size];
for(int i=0;i<size;i++)
ret[i] = is.readShort();
return ret;
}
private static long[] deserializeArrayLongB(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
long[] ret = new long[size];
for(int i=0;i<size;i++){
ret[i] = is.read();
if(ret[i] <0)
throw new EOFException();
}
return ret;
}
private static int[] deserializeArrayIntIInt(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
int[] ret = new int[size];
for(int i=0;i<size;i++)
ret[i] = is.readInt();
return ret;
}
private static int[] deserializeArrayIntSInt(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
int[] ret = new int[size];
for(int i=0;i<size;i++)
ret[i] = is.readShort();
return ret;
}
private static int[] deserializeArrayIntBInt(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
int[] ret = new int[size];
for(int i=0;i<size;i++){
ret[i] = is.read();
if(ret[i] <0)
throw new EOFException();
}
return ret; }
private static int[] deserializeArrayIntPack(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
if (size < 0)
throw new EOFException();
int[] ret = new int[size];
for(int i=0;i<size;i++){
ret[i] = LongPacker.unpackInt(is);
}
return ret;
}
private static long[] deserializeArrayLongPack(DataInputStream is) throws IOException {
int size = LongPacker.unpackInt(is);
if (size < 0)
throw new EOFException();
long[] ret = new long[size];
for(int i=0;i<size;i++){
ret[i] = LongPacker.unpackLong(is);
}
return ret;
}
private static int[] deserializeArrayIntB255(DataInputStream is) throws IOException {
int size = is.read();
if (size < 0)
throw new EOFException();
int[] ret = new int[size];
for(int i=0;i<size;i++){
ret[i] = is.read();
if(ret[i] <0)
throw new EOFException();
}
return ret; }
private static BlockIo deserializeBlockIo(DataInputStream is) throws IOException, ClassNotFoundException {
BlockIo b = new BlockIo();
b.readExternal(is);
return b;
}
private static Object[] deserializeArrayObject(DataInputStream is) throws IOException, ClassNotFoundException {
int size =LongPacker.unpackInt(is);
Object[] s = new Object[size];
for(int i = 0; i<size;i++)
s[i] = readObject(is);
return s;
}
private static Object[] deserializeArrayObjectPackedLong(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
Object[] s = new Object[size];
for(int i = 0; i<size;i++){
long l = LongPacker.unpackLong(is);
if(l == 0)
s[i] = null;
else
s[i] = Long.valueOf(l-1);
}
return s;
}
private static Object[] deserializeArrayObject256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
Object[] s = new Object[size];
for(int i = 0; i<size;i++)
s[i] = readObject(is);
return s;
}
private static ArrayList<Object> deserializeArrayList(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
ArrayList<Object> s = new ArrayList<Object>(size);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static ArrayList<Object> deserializeArrayListPackedLong(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
ArrayList<Object> s = new ArrayList<Object>(size);
for(int i = 0; i<size;i++){
long l = LongPacker.unpackLong(is);
if(l == 0)
s.add(null);
else
s.add( Long.valueOf(l-1));
}
return s;
}
private static ArrayList<Object> deserializeArrayList256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
ArrayList<Object> s = new ArrayList<Object>(size);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static LinkedList<Object> deserializeLinkedList(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
LinkedList<Object> s = new LinkedList<Object>();
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static LinkedList<Object> deserializeLinkedList256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
LinkedList<Object> s = new LinkedList<Object>();
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static Vector<Object> deserializeVector(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
Vector<Object> s = new Vector<Object>(size);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static Vector<Object> deserializeVector256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
Vector<Object> s = new Vector<Object>(size);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static HashSet<Object> deserializeHashSet(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
HashSet<Object> s = new HashSet<Object>(size);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static HashSet<Object> deserializeHashSet256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
HashSet<Object> s = new HashSet<Object>(size);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static LinkedHashSet<Object> deserializeLinkedHashSet(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
LinkedHashSet<Object> s = new LinkedHashSet<Object>(size);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static LinkedHashSet<Object> deserializeLinkedHashSet256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
LinkedHashSet<Object> s = new LinkedHashSet<Object>(size);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static TreeSet<Object> deserializeTreeSet(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
TreeSet<Object> s = new TreeSet<Object>();
Comparator comparator = (Comparator) readObject(is);
if(comparator!=null)
s = new TreeSet<Object>(comparator);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static TreeSet<Object> deserializeTreeSet256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
TreeSet<Object> s = new TreeSet<Object>();
Object obj = readObject(is);
Comparator comparator = (Comparator) obj;
if(comparator!=null)
s = new TreeSet<Object>(comparator);
for(int i = 0; i<size;i++)
s.add(readObject(is));
return s;
}
private static TreeMap<Object,Object> deserializeTreeMap(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
TreeMap<Object,Object> s = new TreeMap<Object,Object>();
Comparator comparator = (Comparator) readObject(is);
if(comparator!=null)
s = new TreeMap<Object,Object>(comparator);
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static TreeMap<Object,Object> deserializeTreeMap256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
TreeMap<Object,Object> s = new TreeMap<Object,Object>();
Comparator comparator = (Comparator) readObject(is);
if(comparator!=null)
s = new TreeMap<Object,Object>(comparator);
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static HashMap<Object,Object> deserializeHashMap(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
HashMap<Object,Object> s = new HashMap<Object,Object>(size);
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static HashMap<Object,Object> deserializeHashMap256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
HashMap<Object,Object> s = new HashMap<Object,Object>(size);
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static LinkedHashMap<Object,Object> deserializeLinkedHashMap(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
LinkedHashMap<Object,Object> s = new LinkedHashMap<Object,Object>(size);
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static LinkedHashMap<Object,Object> deserializeLinkedHashMap256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
LinkedHashMap<Object,Object> s = new LinkedHashMap<Object,Object>(size);
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static Hashtable<Object,Object> deserializeHashtable(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
Hashtable<Object,Object> s = new Hashtable<Object,Object>(size);
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static Hashtable<Object,Object> deserializeHashtable256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
Hashtable<Object,Object> s = new Hashtable<Object,Object>(size);
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static Properties deserializeProperties(DataInputStream is) throws IOException, ClassNotFoundException {
int size = LongPacker.unpackInt(is);
Properties s = new Properties();
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
private static Properties deserializeProperties256Smaller(DataInputStream is) throws IOException, ClassNotFoundException {
int size = is.read();
if(size <0)
throw new EOFException();
Properties s = new Properties();
for(int i = 0; i<size;i++)
s.put(readObject(is),readObject(is));
return s;
}
}