package test.javassist.proxy;
import javassist.util.proxy.*;
import junit.framework.TestCase;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Test to ensure that serialization and deserialization of javassist proxies via
* {@link javassist.util.proxy.ProxyObjectOutputStream} and @link javassist.util.proxy.ProxyObjectInputStream}
* reuses classes located in the proxy cache. This tests the fixes provided for JASSIST-42 and JASSIST-97.
*/
public class ProxySerializationTest extends TestCase
{
public void testSerialization()
{
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(TestClass.class);
factory.setInterfaces(new Class[] {TestInterface.class});
factory.setUseWriteReplace(true);
Class proxyClass = factory.createClass(new TestFilter());
MethodHandler handler = new TestHandler();
// first try serialization using writeReplace
try {
String name = "proxytest_1";
Constructor constructor = proxyClass.getConstructor(new Class[] {String.class});
TestClass proxy = (TestClass)constructor.newInstance(new Object[] {name});
((ProxyObject)proxy).setHandler(handler);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(proxy);
out.close();
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream in = new ObjectInputStream(bis);
TestClass newProxy = (TestClass)in.readObject();
// inherited fields should not have been deserialized
assertTrue("new name should be null", newProxy.getName() == null);
// since we are reading into the same JVM the new proxy should have the same class as the old proxy
assertTrue("classes should be equal", newProxy.getClass() == proxy.getClass());
} catch (Exception e) {
e.printStackTrace();
fail();
}
// second try serialization using proxy object output/input streams
factory.setUseWriteReplace(false);
proxyClass = factory.createClass(new TestFilter());
try {
String name = "proxytest_2";
Constructor constructor = proxyClass.getConstructor(new Class[] {String.class});
TestClass proxy = (TestClass)constructor.newInstance(new Object[] {name});
((ProxyObject)proxy).setHandler(handler);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ProxyObjectOutputStream out = new ProxyObjectOutputStream(bos);
out.writeObject(proxy);
out.close();
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ProxyObjectInputStream in = new ProxyObjectInputStream(bis);
TestClass newProxy = (TestClass)in.readObject();
// inherited fields should have been deserialized
assertTrue("names should be equal", proxy.getName().equals(newProxy.getName()));
// since we are reading into the same JVM the new proxy should have the same class as the old proxy
assertTrue("classes should still be equal", newProxy.getClass() == proxy.getClass());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
public static class TestFilter implements MethodFilter, Serializable
{
public boolean isHandled(Method m) {
if (m.getName().equals("getName")) {
return true;
}
return false;
}
public boolean equals(Object o)
{
if (o instanceof TestFilter) {
// all test filters are equal
return true;
}
return false;
}
public int hashCode()
{
return TestFilter.class.hashCode();
}
}
public static class TestHandler implements MethodHandler, Serializable
{
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable
{
return proceed.invoke(self, args);
}
public boolean equals(Object o)
{
if (o instanceof TestHandler) {
// all test handlers are equal
return true;
}
return false;
}
public int hashCode()
{
return TestHandler.class.hashCode();
}
}
public static class TestClass implements Serializable
{
public String name;
public TestClass()
{
}
public TestClass(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
public static interface TestInterface
{
public String getName();
}
}