package org.ehcache.impl.serialization;
import org.ehcache.core.util.ByteBufferInputStream;
import org.ehcache.spi.serialization.Serializer;
import org.ehcache.spi.serialization.SerializerException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Proxy;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
public class PlainJavaSerializer<T> implements Serializer<T> {
private final ClassLoader classLoader;
public PlainJavaSerializer(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public ByteBuffer serialize(T object) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try(ObjectOutputStream oout = new ObjectOutputStream(bout)) {
oout.writeObject(object);
} catch (IOException e) {
throw new SerializerException(e);
}
return ByteBuffer.wrap(bout.toByteArray());
}
@SuppressWarnings("unchecked")
@Override
public T read(ByteBuffer entry) throws SerializerException, ClassNotFoundException {
ByteBufferInputStream bin = new ByteBufferInputStream(entry);
try {
try (OIS ois = new OIS(bin, classLoader)) {
return (T) ois.readObject();
}
} catch (IOException e) {
throw new SerializerException(e);
} finally {
try {
bin.close();
} catch (IOException e) {
throw new AssertionError(e);
}
}
}
@Override
public boolean equals(T object, ByteBuffer binary) throws SerializerException, ClassNotFoundException {
return object.equals(read(binary));
}
private static class OIS extends ObjectInputStream {
private final ClassLoader classLoader;
public OIS(InputStream in, ClassLoader classLoader) throws IOException {
super(in);
this.classLoader = classLoader;
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws ClassNotFoundException {
try {
return Class.forName(desc.getName(), false, classLoader);
} catch (ClassNotFoundException cnfe) {
Class<?> primitive = primitiveClasses.get(desc.getName());
if (primitive != null) {
return primitive;
}
throw cnfe;
}
}
@Override
protected Class<?> resolveProxyClass(String[] interfaces) throws ClassNotFoundException {
Class<?>[] interfaceClasses = new Class<?>[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
interfaceClasses[i] = Class.forName(interfaces[i], false, classLoader);
}
return Proxy.getProxyClass(classLoader, interfaceClasses);
}
private static final Map<String, Class<?>> primitiveClasses = new HashMap<>();
static {
primitiveClasses.put("boolean", boolean.class);
primitiveClasses.put("byte", byte.class);
primitiveClasses.put("char", char.class);
primitiveClasses.put("double", double.class);
primitiveClasses.put("float", float.class);
primitiveClasses.put("int", int.class);
primitiveClasses.put("long", long.class);
primitiveClasses.put("short", short.class);
primitiveClasses.put("void", void.class);
}
}
}