169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage test.javassist.proxy;
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.util.proxy.*;
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport junit.framework.TestCase;
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.*;
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.Constructor;
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.InvocationTargetException;
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.Method;
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Test to ensure that serialization and deserialization of javassist proxies via
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * {@link javassist.util.proxy.ProxyObjectOutputStream} and  @link javassist.util.proxy.ProxyObjectInputStream}
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * reuses classes located in the proxy cache. This tests the fixes provided for JASSIST-42 and JASSIST-97.
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class ProxySerializationTest extends TestCase
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal{
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void testSerialization()
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ProxyFactory factory = new ProxyFactory();
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        factory.setSuperclass(TestClass.class);
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        factory.setInterfaces(new Class[] {TestInterface.class});
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        factory.setUseWriteReplace(true);
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Class proxyClass = factory.createClass(new TestFilter());
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        MethodHandler handler = new TestHandler();
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // first try serialization using writeReplace
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String name = "proxytest_1";
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Constructor constructor = proxyClass.getConstructor(new Class[] {String.class});
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TestClass proxy = (TestClass)constructor.newInstance(new Object[] {name});
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ((ProxyObject)proxy).setHandler(handler);
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArrayOutputStream bos = new ByteArrayOutputStream();
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ObjectOutputStream out = new ObjectOutputStream(bos);
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.writeObject(proxy);
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.close();
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] bytes = bos.toByteArray();
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ObjectInputStream in = new ObjectInputStream(bis);
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TestClass newProxy = (TestClass)in.readObject();
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // inherited fields should not have been deserialized
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            assertTrue("new name should be null", newProxy.getName() == null);
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // since we are reading into the same JVM the new proxy should have the same class as the old proxy
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            assertTrue("classes should be equal", newProxy.getClass() == proxy.getClass());
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        } catch (Exception e) {
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            e.printStackTrace();
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            fail();
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        // second try serialization using proxy object output/input streams
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        factory.setUseWriteReplace(false);
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        proxyClass = factory.createClass(new TestFilter());
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String name = "proxytest_2";
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Constructor constructor = proxyClass.getConstructor(new Class[] {String.class});
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TestClass proxy = (TestClass)constructor.newInstance(new Object[] {name});
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ((ProxyObject)proxy).setHandler(handler);
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArrayOutputStream bos = new ByteArrayOutputStream();
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ProxyObjectOutputStream out = new ProxyObjectOutputStream(bos);
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.writeObject(proxy);
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            out.close();
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            byte[] bytes = bos.toByteArray();
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ProxyObjectInputStream in = new ProxyObjectInputStream(bis);
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TestClass newProxy = (TestClass)in.readObject();
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // inherited fields should have been deserialized
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            assertTrue("names should be equal", proxy.getName().equals(newProxy.getName()));
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // since we are reading into the same JVM the new proxy should have the same class as the old proxy
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            assertTrue("classes should still be equal", newProxy.getClass() == proxy.getClass());
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        } catch (Exception e) {
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            e.printStackTrace();
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            fail();
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class TestFilter implements MethodFilter, Serializable
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public boolean isHandled(Method m) {
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (m.getName().equals("getName")) {
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return true;
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public boolean equals(Object o)
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (o instanceof TestFilter) {
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                // all test filters are equal
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return true;
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public int hashCode()
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return TestFilter.class.hashCode();
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class TestHandler implements MethodHandler, Serializable
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return proceed.invoke(self, args);
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public boolean equals(Object o)
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (o instanceof TestHandler) {
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                // all test handlers are equal
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return true;
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public int hashCode()
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return TestHandler.class.hashCode();
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class TestClass implements Serializable
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String name;
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public TestClass()
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public TestClass(String name)
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            this.name = name;
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String getName()
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return name;
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static interface TestInterface
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String getName();
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
152