From 6a3ed31976e54f2523a6e41dfee9001b3cce58c8 Mon Sep 17 00:00:00 2001 From: chibash Date: Tue, 20 Dec 2016 18:07:11 +0900 Subject: [PATCH] updates the test code to run on Java 9 EA+149. Due to the specification change of jigsaw, ClassLoader#defineClass() cannot be invoked through reflection API. As a workaround, --add-opens java.base/java.lang=ALL-UNNAMED must be given to the JVM. The ant target "runtest9" adds this jvm argument. --- build.xml | 12 +- javassist.jar | Bin 725109 -> 722743 bytes src/main/javassist/ClassPoolTail.java | 2 +- src/test/javassist/JvstTest.java | 4 + src/test/javassist/JvstTest2.java | 29 +- .../test/javassist/proxy/ProxySimpleTest.java | 36 +- src/test/testproxy/ProxyTester.java | 914 +++++++++--------- 7 files changed, 523 insertions(+), 474 deletions(-) diff --git a/build.xml b/build.xml index d9c65013..587db2ed 100644 --- a/build.xml +++ b/build.xml @@ -99,7 +99,17 @@ - + + + + + + + + + + + diff --git a/javassist.jar b/javassist.jar index 83712459f2c30305163a9b4ee4e8b288982ba271..5083ca752d31192a1867df36f671489c90252bce 100644 GIT binary patch delta 36345 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 Sho57eW9+`f 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 diff --git a/src/main/javassist/ClassPoolTail.java b/src/main/javassist/ClassPoolTail.java index 13d22d77..681c550e 100644 --- a/src/main/javassist/ClassPoolTail.java +++ b/src/main/javassist/ClassPoolTail.java @@ -241,7 +241,7 @@ final class ClassPoolTail { public ClassPath appendSystemPath() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); - return appendClassPath(new LoaderClassPath(cl, true)); + return appendClassPath(new LoaderClassPath(cl)); } public ClassPath insertClassPath(String pathname) diff --git a/src/test/javassist/JvstTest.java b/src/test/javassist/JvstTest.java index eb57a643..550d4278 100644 --- a/src/test/javassist/JvstTest.java +++ b/src/test/javassist/JvstTest.java @@ -8,8 +8,12 @@ import javassist.expr.*; import javassist.runtime.*; public class JvstTest extends JvstTestRoot { + public static boolean java9; + static { //javassist.bytecode.MethodInfo.doPreverify = true; + java9 = javassist.bytecode.ClassFile.MAJOR_VERSION + >= javassist.bytecode.ClassFile.JAVA_9; } public JvstTest(String name) { super(name); diff --git a/src/test/javassist/JvstTest2.java b/src/test/javassist/JvstTest2.java index 10d5d3e3..443bbb30 100644 --- a/src/test/javassist/JvstTest2.java +++ b/src/test/javassist/JvstTest2.java @@ -295,8 +295,12 @@ public class JvstTest2 extends JvstTestRoot { url = cp.find("java.lang.Object").toString(); System.out.println(url); - assertTrue(url.startsWith("jar:file:")); - assertTrue(url.endsWith(".jar!/java/lang/Object.class")); + if (JvstTest.java9) + assertEquals("jrt:/java.base/java/lang/Object.class", url); + else { + assertTrue(url.startsWith("jar:file:")); + assertTrue(url.endsWith(".jar!/java/lang/Object.class")); + } assertNull(cp.find("class.not.Exist")); @@ -304,7 +308,7 @@ public class JvstTest2 extends JvstTestRoot { cp.insertClassPath("."); url = cp.find("test2.Inner").toString(); - System.out.println(url); + System.out.println("testURL: " + url); assertTrue(url.startsWith("file:/")); assertTrue(url.endsWith("/test2/Inner.class")); @@ -314,7 +318,7 @@ public class JvstTest2 extends JvstTestRoot { cp.insertClassPath(JAR_PATH + "javassist.jar"); url = cp.find("javassist.CtClass").toString(); - System.out.println(url); + System.out.println("testURL: " + url); assertTrue(url.startsWith("jar:file:")); assertTrue(url.endsWith("javassist.jar!/javassist/CtClass.class")); @@ -324,9 +328,9 @@ public class JvstTest2 extends JvstTestRoot { cp.insertClassPath(new LoaderClassPath(cloader)); url = cp.find("javassist.CtMethod").toString(); - System.out.println(url); - // assertTrue(url.startsWith("jar:file:")); - // assertTrue(url.endsWith("javassist.jar!/javassist/CtMethod.class")); + System.out.println("testURL: " + url); + assertTrue(url.startsWith("file:")); + assertTrue(url.endsWith("/javassist/CtMethod.class")); assertNull(cp.find("javassist.TestURL")); @@ -334,7 +338,7 @@ public class JvstTest2 extends JvstTestRoot { cp.insertClassPath(new ByteArrayClassPath("test2.ByteArray", null)); url = cp.find("test2.ByteArray").toString(); - System.out.println(url); + System.out.println("testURL: " + url); assertTrue( url.equals("file:/ByteArrayClassPath/test2/ByteArray.class")); @@ -361,8 +365,13 @@ public class JvstTest2 extends JvstTestRoot { CtClass cc = sloader.get("java.lang.String"); String url = cc.getURL().toString(); System.out.println(url); - assertTrue(url.startsWith("jar:file:")); - assertTrue(url.endsWith(".jar!/java/lang/String.class")); + if (JvstTest.java9) { + assertEquals("jrt:/java.base/java/lang/String.class", url); + } + else { + assertTrue(url.startsWith("jar:file:")); + assertTrue(url.endsWith(".jar!/java/lang/String.class")); + } cc = sloader.get("int"); try { diff --git a/src/test/test/javassist/proxy/ProxySimpleTest.java b/src/test/test/javassist/proxy/ProxySimpleTest.java index 42a4f443..249a2542 100644 --- a/src/test/test/javassist/proxy/ProxySimpleTest.java +++ b/src/test/test/javassist/proxy/ProxySimpleTest.java @@ -1,6 +1,7 @@ package test.javassist.proxy; import junit.framework.TestCase; +import testproxy.ProxyTester.ReadWriteData; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -53,19 +54,28 @@ public class ProxySimpleTest extends TestCase { public void testReadWrite() throws Exception { final String fileName = "read-write.bin"; ProxyFactory.ClassLoaderProvider cp = ProxyFactory.classLoaderProvider; - ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { - public ClassLoader get(ProxyFactory pf) { - return new javassist.Loader(); - } - }; - ProxyFactory pf = new ProxyFactory(); - pf.setSuperclass(ReadWriteData.class); - Object data = pf.createClass().getConstructor().newInstance(); - // Object data = new ReadWriteData(); - ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName)); - oos.writeObject(data); - oos.close(); - ProxyFactory.classLoaderProvider = cp; + try { + ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { + public ClassLoader get(ProxyFactory pf) { + /* If javassist.Loader is returned, the super type of ReadWriteData class, + * which is Serializable, is loaded by javassist.Loader as well as ReadWriteData. + * This breaks the implementation of the object serializer. + */ + // return new javassist.Loader(); + return Thread.currentThread().getContextClassLoader(); + } + }; + ProxyFactory pf = new ProxyFactory(); + pf.setSuperclass(ReadWriteData.class); + Object data = pf.createClass().getConstructor().newInstance(); + // Object data = new ReadWriteData(); + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName)); + oos.writeObject(data); + oos.close(); + } + finally { + ProxyFactory.classLoaderProvider = cp; + } ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName)); Object data2 = ois.readObject(); diff --git a/src/test/testproxy/ProxyTester.java b/src/test/testproxy/ProxyTester.java index 07ae54d2..f325997d 100644 --- a/src/test/testproxy/ProxyTester.java +++ b/src/test/testproxy/ProxyTester.java @@ -1,449 +1,465 @@ -package testproxy; - -import java.lang.reflect.Method; -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; -import java.lang.reflect.InvocationTargetException; -import javassist.util.proxy.ProxyFactory; -import javassist.util.proxy.MethodFilter; -import javassist.util.proxy.MethodHandler; -import javassist.util.proxy.ProxyObject; -import javassist.util.proxy.Proxy; -import junit.framework.Assert; -import junit.framework.TestCase; -import java.io.*; - -public class ProxyTester extends TestCase { - public ProxyTester(String s) { - super(s); - } - - public ProxyTester() { - this("proxy"); - } - - static class Interceptor1 implements MethodHandler { - int counter = 0; - - public Object invoke(Object self, Method m, Method proceed, - Object[] args) throws Exception { - System.out.println("intercept: " + m + ", proceed: " + proceed); - System.out.println(" modifier: " - + Modifier.toString(proceed.getModifiers())); - counter++; - return proceed.invoke(self, args); - } - } - - static class Interceptor2 implements MethodHandler { - int counter = 0; - public Object invoke(Object self, Method m, Method proceed, - Object[] args) throws Exception { - System.out.println("intercept: " + m + ", proceed: " + proceed); - counter++; - if (proceed != null) - return proceed.invoke(self, args); - else - if (m.getReturnType() == int.class) - return Integer.valueOf(3); - else - return "OK"; - } - } - - static MethodFilter finalizeRemover = new MethodFilter() { - public boolean isHandled(Method m) { - return !m.getName().equals("finalize"); - } - }; - - public void testTarget() throws Exception { - ProxyFactory f = new ProxyFactory(); - f.setSuperclass(Target.class); - Interceptor1 interceptor = new Interceptor1(); - // f.setHandler(interceptor); - f.setFilter(finalizeRemover); - f.writeDirectory = "."; - Class c = f.createClass(); - Target obj = (Target)c.getConstructor().newInstance(); - ((Proxy)obj).setHandler(interceptor); - obj.m(); - assertEquals(true, obj.m(true)); - assertEquals((byte)1, obj.m1((byte)1)); - assertEquals('a', obj.m2('a')); - assertEquals((short)2, obj.m3((short)2)); - assertEquals(3, obj.m(3)); - assertEquals(4L, obj.m5(4L)); - assertTrue(5.0F == obj.m6(5.0F)); - assertTrue(6.0 == obj.m7(6.0)); - assertEquals("test", obj.m("test")); - int[] ia = { 1, 2, 3 }; - assertEquals(ia, obj.m7(ia)); - String[] sa = { "1", "2" }; - assertEquals(sa, obj.m8(sa)); - assertEquals(obj, obj.m9(3, obj, null)); - assertEquals(14, interceptor.counter); - } - - public void testTarget1() throws Exception { - ProxyFactory f = new ProxyFactory(); - f.setSuperclass(Target1.class); - Interceptor1 interceptor = new Interceptor1(); - // f.setHandler(interceptor); - f.setFilter(finalizeRemover); - Class c = f.createClass(); - Target1 obj = (Target1)c.getConstructor().newInstance(); - ((Proxy)obj).setHandler(interceptor); - assertEquals(null, obj.m(null)); - assertEquals(1, interceptor.counter); - } - - public void testObject() throws Exception { - ProxyFactory f = new ProxyFactory(); - Interceptor1 interceptor = new Interceptor1(); - // f.setHandler(interceptor); - f.setFilter(finalizeRemover); - Class c = f.createClass(); - Object obj = (Object)c.getConstructor().newInstance(); - ((Proxy)obj).setHandler(interceptor); - System.out.println(obj.toString()); - assertEquals(2, interceptor.counter); - } - - public void testSetter() throws Exception { - ProxyFactory f = new ProxyFactory(); - f.writeDirectory = "."; - Interceptor1 interceptor = new Interceptor1(); - // f.setHandler(interceptor); - f.setFilter(finalizeRemover); - Class c = f.createClass(); - Object obj = (Object)c.getConstructor().newInstance(); - ((Proxy)obj).setHandler(interceptor); - System.out.println("setter1: " + obj.toString()); - ((ProxyObject)obj).setHandler(new MethodHandler() { - public Object invoke(Object self, Method m, Method proceed, - Object[] args) throws Exception { - System.out.print("intercept: " + m); - return "OK"; - } - }); - assertEquals("OK", obj.toString()); - } - - public void testString() throws Exception { - ProxyFactory f = new ProxyFactory(); - Interceptor1 interceptor = new Interceptor1(); - // f.setHandler(interceptor); - f.setFilter(finalizeRemover); - f.setSuperclass(String.class); - try { - Class c = f.createClass(); - Assert.fail("String is final!"); - } - catch (RuntimeException e) { - System.out.println(e); - } - } - - public void testConstructor() throws Exception { - ProxyFactory f = new ProxyFactory(); - Interceptor1 interceptor = new Interceptor1(); - // f.setHandler(interceptor); - f.setFilter(finalizeRemover); - f.setSuperclass(Target2.class); - Class c = f.createClass(); - Constructor[] cons = c.getDeclaredConstructors(); - assertEquals(3, cons.length); - Constructor con1 = c.getDeclaredConstructor(new Class[] { int.class }); - Constructor con2 = c.getDeclaredConstructor(new Class[] { int.class, int.class }); - Method m1 = c.getDeclaredMethod("get", new Class[0]); - Method m2 = c.getDeclaredMethod("foo", new Class[0]); - assertEquals(0, m1.getExceptionTypes().length); - assertEquals("java.io.IOException", m2.getExceptionTypes()[0].getName()); - - Target2 t2 = (Target2)con1.newInstance(new Object[] { Integer.valueOf(1) }); - ((Proxy)t2).setHandler(interceptor); - System.out.println(t2.toString()); - assertEquals(2, interceptor.counter); - - interceptor.counter = 0; - assertEquals(2, t2.foo()); - assertEquals(4, t2._dfoo()); - assertEquals(2, interceptor.counter); - } - - public void testInterface() throws Exception { - ProxyFactory f = new ProxyFactory(); - Interceptor2 interceptor2 = new Interceptor2(); - // f.setHandler(interceptor2); - f.setFilter(finalizeRemover); - f.setInterfaces(new Class[] { Target3.class }); - Class c = f.createClass(); - Target3 obj = (Target3)c.getConstructor().newInstance(); - ((Proxy)obj).setHandler(interceptor2); - assertEquals("OK", obj.m()); - System.out.println(obj.toString()); - assertEquals(3, interceptor2.counter); - } - - public void test2Interfaces() throws Exception { - ProxyFactory f = new ProxyFactory(); - Interceptor2 interceptor2 = new Interceptor2(); - // f.setHandler(interceptor2); - f.setFilter(finalizeRemover); - f.setInterfaces(new Class[] { Target3.class, Target4.class }); - Class c = f.createClass(); - Target3 obj = (Target3)c.getConstructor().newInstance(); - ((Proxy)obj).setHandler(interceptor2); - assertEquals("OK", obj.m()); - System.out.println(obj.toString()); - assertEquals(3, interceptor2.counter); - - interceptor2.counter = 0; - Target4 obj4 = (Target4)c.getConstructor().newInstance(); - ((Proxy)obj4).setHandler(interceptor2); - assertEquals(3, obj4.bar4()); - assertEquals(3, obj4.foo4()); - assertEquals(2, interceptor2.counter); - } - - public void testFilter() throws Exception { - ProxyFactory f = new ProxyFactory(); - Interceptor2 interceptor2 = new Interceptor2(); - // f.setHandler(interceptor2); - f.setFilter(finalizeRemover); - f.setInterfaces(new Class[] { Target3.class }); - f.setFilter(new MethodFilter() { - public boolean isHandled(Method m) { - return m.getDeclaringClass() != Object.class; - } - }); - Class c = f.createClass(); - Target3 obj = (Target3)c.getConstructor().newInstance(); - ((Proxy)obj).setHandler(interceptor2); - assertEquals("OK", obj.m()); - System.out.println(obj.toString()); - assertEquals(1, interceptor2.counter); - } - - public static boolean testInitFlag; - - public void testInit() throws Exception { - ProxyFactory f = new ProxyFactory(); - f.setSuperclass(TargetInit.class); - MethodHandler handler = new MethodHandler() { - public Object invoke(Object self, Method m, - Method proceed, Object[] args) throws Exception { - System.out.println("testInit " + testInitFlag); - return proceed.invoke(self, args); - } - }; - testInitFlag = false; - Class c = f.createClass(); - assertTrue(testInitFlag); // since 3.12. Before then, this line was assertFalse(testInitFlag); - System.out.println("testInit createClass(): " + testInitFlag); - TargetInit obj = (TargetInit)c.getConstructor().newInstance(); - assertTrue(testInitFlag); - System.out.println("testInit newInstance(): " + testInitFlag); - ((ProxyObject)obj).setHandler(handler); - assertEquals("OK", obj.m()); - } - - public void testCreate() throws Exception { - ProxyFactory f = new ProxyFactory(); - f.setSuperclass(Target5.class); - Interceptor1 interceptor = new Interceptor1(); - // f.setHandler(interceptor); - f.setFilter(finalizeRemover); - Class c = f.createClass(); - Target5 obj = (Target5)f.create(new Class[] { int.class }, new Object[] { Integer.valueOf(3) }); - ((Proxy)obj).setHandler(interceptor); - assertEquals(3, obj.get()); - } - - - public void testBridgeMethod() throws Exception { - ProxyFactory f = new ProxyFactory(); - f.writeDirectory = "."; - f.setSuperclass(BridgeMethod.class); - Interceptor1 interceptor = new Interceptor1(); - // f.setHandler(interceptor); - f.setFilter(finalizeRemover); - Class c = f.createClass(); - BridgeMethod obj = (BridgeMethod)c.getConstructor().newInstance(); - ((Proxy)obj).setHandler(interceptor); - Integer value = obj.m1(); - assertEquals(7, value.intValue()); - BridgeMethodInf inf = (BridgeMethodInf)obj; - Number num = inf.m1(); - assertEquals(7, num.intValue()); - BridgeMethodSuper sup = obj; - try { - Object x = sup.id(new Object()); - fail("not cast error"); - } - catch (ClassCastException e) {} - catch (Exception e) { - if (e instanceof InvocationTargetException) - if (e.getCause() instanceof ClassCastException) - return; - - throw e; - } - } - - public void testGetters() throws Exception { - ProxyFactory f = new ProxyFactory(); - Class c = ProxyTester.class; - f.setSuperclass(c); - assertEquals(c, f.getSuperclass()); - Class i = java.io.Serializable.class; - f.setInterfaces(new Class[] { i }); - assertEquals(i, f.getInterfaces()[0]); - } - - static class ProxyFactory2 extends ProxyFactory { - public ClassLoader getClassLoader2() { - return getClassLoader(); - } - } - - public void testProvider() throws Exception { - ProxyFactory.ClassLoaderProvider cp = ProxyFactory.classLoaderProvider; - final ClassLoader cl = Thread.currentThread().getContextClassLoader(); - ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { - public ClassLoader get(ProxyFactory pf) { - return Thread.currentThread().getContextClassLoader(); - } - }; - - ProxyFactory2 pf = new ProxyFactory2(); - assertEquals(cl, pf.getClassLoader2()); - ProxyFactory.classLoaderProvider = cp; - } - - @SuppressWarnings("deprecation") - public void testCache() throws Exception { - boolean prev = ProxyFactory.useCache; - ProxyFactory.useCache = true; - ProxyFactory f = new ProxyFactory(); - f.setSuperclass(Cache1.class); - Class c = f.createClass(); - ProxyFactory f2 = new ProxyFactory(); - f2.setSuperclass(Cache1.class); - assertEquals(c, f2.createClass()); - ProxyFactory f3 = new ProxyFactory(); - f3.setSuperclass(Cache1.class); - f3.setHandler(new Interceptor1()); // deprecated - assertFalse(c == f3.createClass()); - ProxyFactory.useCache = true; - ProxyFactory f4 = new ProxyFactory(); - f4.setSuperclass(Cache1.class); - f4.setInterfaces(new Class[] { Cache2.class }); - Class c4 = f4.createClass(); - assertFalse(c == c4); - ProxyFactory f5 = new ProxyFactory(); - f5.setSuperclass(Cache1.class); - f5.setInterfaces(new Class[] { Cache2.class }); - assertEquals(c4, f5.createClass()); - ProxyFactory f6 = new ProxyFactory(); - f6.setInterfaces(new Class[] { Cache2.class }); - assertFalse(c4 == f6.createClass()); - ProxyFactory.useCache = prev; - } - - public static class Cache1 { - public int foo() { return 0; } - } - - public static interface Cache2 { - public int bar(); - } - - public void testReadWrite() throws Exception { - final String fileName = "read-write.bin"; - ProxyFactory.ClassLoaderProvider cp = ProxyFactory.classLoaderProvider; - ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { - public ClassLoader get(ProxyFactory pf) { - return new javassist.Loader(); - } - }; - ProxyFactory pf = new ProxyFactory(); - pf.setSuperclass(ReadWriteData.class); - Object data = pf.createClass().getConstructor().newInstance(); - // Object data = new ReadWriteData(); - ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName)); - oos.writeObject(data); - oos.close(); - ProxyFactory.classLoaderProvider = cp; - - ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName)); - Object data2 = ois.readObject(); - ois.close(); - int i = ((ReadWriteData)data2).foo(); - assertEquals(4, i); - } - - public static class ReadWriteData implements Serializable { - public int foo() { return 4; } - } - - public void testWriteReplace() throws Exception { - ProxyFactory pf = new ProxyFactory(); - pf.setSuperclass(WriteReplace.class); - Object data = pf.createClass().getConstructor().newInstance(); - assertEquals(data, ((WriteReplace)data).writeReplace()); - - ProxyFactory pf2 = new ProxyFactory(); - pf2.setSuperclass(WriteReplace2.class); - Object data2 = pf2.createClass().getConstructor().newInstance(); - Method meth = data2.getClass().getDeclaredMethod("writeReplace", new Class[0]); - assertEquals("javassist.util.proxy.SerializedProxy", - meth.invoke(data2, new Object[0]).getClass().getName()); - } - - public static class WriteReplace implements Serializable { - public Object writeReplace() { return this; } - } - - public static class WriteReplace2 implements Serializable { - public Object writeReplace(int i) { return Integer.valueOf(i); } - } - - public static void testJIRA189() throws Exception { - Class persistentClass = Target189.PublishedArticle.class; - ProxyFactory factory = new ProxyFactory(); - // factory.writeDirectory = "."; - factory.setUseCache(false); - factory.setSuperclass(persistentClass); - factory.setInterfaces(new Class[] { Target189.TestProxy.class }); - Class cl = factory.createClass(); - Target189.TestProxy proxy = (Target189.TestProxy)cl.getConstructor().newInstance(); - Target189.TestMethodHandler methodHandler = new Target189.TestMethodHandler(); - ((ProxyObject)proxy).setHandler(methodHandler); - ((Target189.Article)proxy).getIssue(); - assertTrue(methodHandler.wasInvokedOnce()); - methodHandler.reset(); - Target189.PublishedArticle article = (Target189.PublishedArticle)proxy; - article.getIssue(); - assertTrue(methodHandler.wasInvokedOnce()); - } - - public void testJIRA127() throws Exception { - ProxyFactory proxyFactory = new ProxyFactory(); - // proxyFactory.writeDirectory = "."; - proxyFactory.setInterfaces(new Class[]{ Target127.Sub.class }); - Target127.Sub proxy = (Target127.Sub)proxyFactory.create(new Class[0], new Object[0], new MethodHandler() { - public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable { - return null; - } - }); - ((Target127.Super)proxy).item(); // proxyFactory must generate a bridge method. - ((Target127.Sub)proxy).item(); - } - - public static void main(String[] args) { - // javassist.bytecode.ClassFile.MAJOR_VERSION = javassist.bytecode.ClassFile.JAVA_6; - junit.textui.TestRunner.run(ProxyTester.class); - } -} +package testproxy; + +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.lang.reflect.InvocationTargetException; +import javassist.util.proxy.ProxyFactory; +import javassist.util.proxy.MethodFilter; +import javassist.util.proxy.MethodHandler; +import javassist.util.proxy.ProxyObject; +import javassist.util.proxy.Proxy; +import junit.framework.Assert; +import junit.framework.TestCase; +import java.io.*; + +public class ProxyTester extends TestCase { + public ProxyTester(String s) { + super(s); + } + + public ProxyTester() { + this("proxy"); + } + + static class Interceptor1 implements MethodHandler { + int counter = 0; + + public Object invoke(Object self, Method m, Method proceed, + Object[] args) throws Exception { + System.out.println("intercept: " + m + ", proceed: " + proceed); + System.out.println(" modifier: " + + Modifier.toString(proceed.getModifiers())); + counter++; + return proceed.invoke(self, args); + } + } + + static class Interceptor2 implements MethodHandler { + int counter = 0; + public Object invoke(Object self, Method m, Method proceed, + Object[] args) throws Exception { + System.out.println("intercept: " + m + ", proceed: " + proceed); + counter++; + if (proceed != null) + return proceed.invoke(self, args); + else + if (m.getReturnType() == int.class) + return Integer.valueOf(3); + else + return "OK"; + } + } + + static MethodFilter finalizeRemover = new MethodFilter() { + public boolean isHandled(Method m) { + return !m.getName().equals("finalize"); + } + }; + + public void testTarget() throws Exception { + ProxyFactory f = new ProxyFactory(); + f.setSuperclass(Target.class); + Interceptor1 interceptor = new Interceptor1(); + // f.setHandler(interceptor); + f.setFilter(finalizeRemover); + f.writeDirectory = "."; + Class c = f.createClass(); + Target obj = (Target)c.getConstructor().newInstance(); + ((Proxy)obj).setHandler(interceptor); + obj.m(); + assertEquals(true, obj.m(true)); + assertEquals((byte)1, obj.m1((byte)1)); + assertEquals('a', obj.m2('a')); + assertEquals((short)2, obj.m3((short)2)); + assertEquals(3, obj.m(3)); + assertEquals(4L, obj.m5(4L)); + assertTrue(5.0F == obj.m6(5.0F)); + assertTrue(6.0 == obj.m7(6.0)); + assertEquals("test", obj.m("test")); + int[] ia = { 1, 2, 3 }; + assertEquals(ia, obj.m7(ia)); + String[] sa = { "1", "2" }; + assertEquals(sa, obj.m8(sa)); + assertEquals(obj, obj.m9(3, obj, null)); + assertEquals(14, interceptor.counter); + } + + public void testTarget1() throws Exception { + ProxyFactory f = new ProxyFactory(); + f.setSuperclass(Target1.class); + Interceptor1 interceptor = new Interceptor1(); + // f.setHandler(interceptor); + f.setFilter(finalizeRemover); + Class c = f.createClass(); + Target1 obj = (Target1)c.getConstructor().newInstance(); + ((Proxy)obj).setHandler(interceptor); + assertEquals(null, obj.m(null)); + assertEquals(1, interceptor.counter); + } + + public void testObject() throws Exception { + ProxyFactory f = new ProxyFactory(); + Interceptor1 interceptor = new Interceptor1(); + // f.setHandler(interceptor); + f.setFilter(finalizeRemover); + Class c = f.createClass(); + Object obj = (Object)c.getConstructor().newInstance(); + ((Proxy)obj).setHandler(interceptor); + System.out.println(obj.toString()); + assertEquals(2, interceptor.counter); + } + + public void testSetter() throws Exception { + ProxyFactory f = new ProxyFactory(); + f.writeDirectory = "."; + Interceptor1 interceptor = new Interceptor1(); + // f.setHandler(interceptor); + f.setFilter(finalizeRemover); + Class c = f.createClass(); + Object obj = (Object)c.getConstructor().newInstance(); + ((Proxy)obj).setHandler(interceptor); + System.out.println("setter1: " + obj.toString()); + ((ProxyObject)obj).setHandler(new MethodHandler() { + public Object invoke(Object self, Method m, Method proceed, + Object[] args) throws Exception { + System.out.print("intercept: " + m); + return "OK"; + } + }); + assertEquals("OK", obj.toString()); + } + + public void testString() throws Exception { + ProxyFactory f = new ProxyFactory(); + Interceptor1 interceptor = new Interceptor1(); + // f.setHandler(interceptor); + f.setFilter(finalizeRemover); + f.setSuperclass(String.class); + try { + Class c = f.createClass(); + Assert.fail("String is final!"); + } + catch (RuntimeException e) { + System.out.println(e); + } + } + + public void testConstructor() throws Exception { + ProxyFactory f = new ProxyFactory(); + Interceptor1 interceptor = new Interceptor1(); + // f.setHandler(interceptor); + f.setFilter(finalizeRemover); + f.setSuperclass(Target2.class); + Class c = f.createClass(); + Constructor[] cons = c.getDeclaredConstructors(); + assertEquals(3, cons.length); + Constructor con1 = c.getDeclaredConstructor(new Class[] { int.class }); + Constructor con2 = c.getDeclaredConstructor(new Class[] { int.class, int.class }); + Method m1 = c.getDeclaredMethod("get", new Class[0]); + Method m2 = c.getDeclaredMethod("foo", new Class[0]); + assertEquals(0, m1.getExceptionTypes().length); + assertEquals("java.io.IOException", m2.getExceptionTypes()[0].getName()); + + Target2 t2 = (Target2)con1.newInstance(new Object[] { Integer.valueOf(1) }); + ((Proxy)t2).setHandler(interceptor); + System.out.println(t2.toString()); + assertEquals(2, interceptor.counter); + + interceptor.counter = 0; + assertEquals(2, t2.foo()); + assertEquals(4, t2._dfoo()); + assertEquals(2, interceptor.counter); + } + + public void testInterface() throws Exception { + ProxyFactory f = new ProxyFactory(); + Interceptor2 interceptor2 = new Interceptor2(); + // f.setHandler(interceptor2); + f.setFilter(finalizeRemover); + f.setInterfaces(new Class[] { Target3.class }); + Class c = f.createClass(); + Target3 obj = (Target3)c.getConstructor().newInstance(); + ((Proxy)obj).setHandler(interceptor2); + assertEquals("OK", obj.m()); + System.out.println(obj.toString()); + assertEquals(3, interceptor2.counter); + } + + public void test2Interfaces() throws Exception { + ProxyFactory f = new ProxyFactory(); + Interceptor2 interceptor2 = new Interceptor2(); + // f.setHandler(interceptor2); + f.setFilter(finalizeRemover); + f.setInterfaces(new Class[] { Target3.class, Target4.class }); + Class c = f.createClass(); + Target3 obj = (Target3)c.getConstructor().newInstance(); + ((Proxy)obj).setHandler(interceptor2); + assertEquals("OK", obj.m()); + System.out.println(obj.toString()); + assertEquals(3, interceptor2.counter); + + interceptor2.counter = 0; + Target4 obj4 = (Target4)c.getConstructor().newInstance(); + ((Proxy)obj4).setHandler(interceptor2); + assertEquals(3, obj4.bar4()); + assertEquals(3, obj4.foo4()); + assertEquals(2, interceptor2.counter); + } + + public void testFilter() throws Exception { + ProxyFactory f = new ProxyFactory(); + Interceptor2 interceptor2 = new Interceptor2(); + // f.setHandler(interceptor2); + f.setFilter(finalizeRemover); + f.setInterfaces(new Class[] { Target3.class }); + f.setFilter(new MethodFilter() { + public boolean isHandled(Method m) { + return m.getDeclaringClass() != Object.class; + } + }); + Class c = f.createClass(); + Target3 obj = (Target3)c.getConstructor().newInstance(); + ((Proxy)obj).setHandler(interceptor2); + assertEquals("OK", obj.m()); + System.out.println(obj.toString()); + assertEquals(1, interceptor2.counter); + } + + public static boolean testInitFlag; + + public void testInit() throws Exception { + ProxyFactory f = new ProxyFactory(); + f.setSuperclass(TargetInit.class); + MethodHandler handler = new MethodHandler() { + public Object invoke(Object self, Method m, + Method proceed, Object[] args) throws Exception { + System.out.println("testInit " + testInitFlag); + return proceed.invoke(self, args); + } + }; + testInitFlag = false; + Class c = f.createClass(); + assertTrue(testInitFlag); // since 3.12. Before then, this line was assertFalse(testInitFlag); + System.out.println("testInit createClass(): " + testInitFlag); + TargetInit obj = (TargetInit)c.getConstructor().newInstance(); + assertTrue(testInitFlag); + System.out.println("testInit newInstance(): " + testInitFlag); + ((ProxyObject)obj).setHandler(handler); + assertEquals("OK", obj.m()); + } + + public void testCreate() throws Exception { + ProxyFactory f = new ProxyFactory(); + f.setSuperclass(Target5.class); + Interceptor1 interceptor = new Interceptor1(); + // f.setHandler(interceptor); + f.setFilter(finalizeRemover); + Class c = f.createClass(); + Target5 obj = (Target5)f.create(new Class[] { int.class }, new Object[] { Integer.valueOf(3) }); + ((Proxy)obj).setHandler(interceptor); + assertEquals(3, obj.get()); + } + + + public void testBridgeMethod() throws Exception { + ProxyFactory f = new ProxyFactory(); + f.writeDirectory = "."; + f.setSuperclass(BridgeMethod.class); + Interceptor1 interceptor = new Interceptor1(); + // f.setHandler(interceptor); + f.setFilter(finalizeRemover); + Class c = f.createClass(); + BridgeMethod obj = (BridgeMethod)c.getConstructor().newInstance(); + ((Proxy)obj).setHandler(interceptor); + Integer value = obj.m1(); + assertEquals(7, value.intValue()); + BridgeMethodInf inf = (BridgeMethodInf)obj; + Number num = inf.m1(); + assertEquals(7, num.intValue()); + BridgeMethodSuper sup = obj; + try { + Object x = sup.id(new Object()); + fail("not cast error"); + } + catch (ClassCastException e) {} + catch (Exception e) { + if (e instanceof InvocationTargetException) + if (e.getCause() instanceof ClassCastException) + return; + + throw e; + } + } + + public void testGetters() throws Exception { + ProxyFactory f = new ProxyFactory(); + Class c = ProxyTester.class; + f.setSuperclass(c); + assertEquals(c, f.getSuperclass()); + Class i = java.io.Serializable.class; + f.setInterfaces(new Class[] { i }); + assertEquals(i, f.getInterfaces()[0]); + } + + static class ProxyFactory2 extends ProxyFactory { + public ClassLoader getClassLoader2() { + return getClassLoader(); + } + } + + public void testProvider() throws Exception { + ProxyFactory.ClassLoaderProvider cp = ProxyFactory.classLoaderProvider; + try { + final ClassLoader cl = Thread.currentThread().getContextClassLoader(); + ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { + public ClassLoader get(ProxyFactory pf) { + return Thread.currentThread().getContextClassLoader(); + } + }; + + ProxyFactory2 pf = new ProxyFactory2(); + assertEquals(cl, pf.getClassLoader2()); + } + finally { + ProxyFactory.classLoaderProvider = cp; + } + } + + @SuppressWarnings("deprecation") + public void testCache() throws Exception { + boolean prev = ProxyFactory.useCache; + ProxyFactory.useCache = true; + ProxyFactory f = new ProxyFactory(); + f.setSuperclass(Cache1.class); + Class c = f.createClass(); + ProxyFactory f2 = new ProxyFactory(); + f2.setSuperclass(Cache1.class); + assertEquals(c, f2.createClass()); + ProxyFactory f3 = new ProxyFactory(); + f3.setSuperclass(Cache1.class); + f3.setHandler(new Interceptor1()); // deprecated + assertFalse(c == f3.createClass()); + ProxyFactory.useCache = true; + ProxyFactory f4 = new ProxyFactory(); + f4.setSuperclass(Cache1.class); + f4.setInterfaces(new Class[] { Cache2.class }); + Class c4 = f4.createClass(); + assertFalse(c == c4); + ProxyFactory f5 = new ProxyFactory(); + f5.setSuperclass(Cache1.class); + f5.setInterfaces(new Class[] { Cache2.class }); + assertEquals(c4, f5.createClass()); + ProxyFactory f6 = new ProxyFactory(); + f6.setInterfaces(new Class[] { Cache2.class }); + assertFalse(c4 == f6.createClass()); + ProxyFactory.useCache = prev; + } + + public static class Cache1 { + public int foo() { return 0; } + } + + public static interface Cache2 { + public int bar(); + } + + public void testReadWrite() throws Exception { + final String fileName = "read-write.bin"; + ProxyFactory.ClassLoaderProvider cp = ProxyFactory.classLoaderProvider; + try { + ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { + public ClassLoader get(ProxyFactory pf) { + /* If javassist.Loader is returned, the super type of ReadWriteData class, + * which is Serializable, is loaded by javassist.Loader as well as ReadWriteData. + * This breaks the implementation of the object serializer. + */ + // return new javassist.Loader(); + return Thread.currentThread().getContextClassLoader(); + } + }; + ProxyFactory pf = new ProxyFactory(); + pf.setSuperclass(ReadWriteData.class); + Object data = pf.createClass().getConstructor().newInstance(); + //Object data = new ReadWriteData(); + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName)); + oos.writeObject(data); + oos.close(); + } + finally { + ProxyFactory.classLoaderProvider = cp; + } + + ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName)); + Object data2 = ois.readObject(); + ois.close(); + int i = ((ReadWriteData)data2).foo(); + assertEquals(4, i); + } + + public static class ReadWriteData implements Serializable { + public int foo() { return 4; } + } + + public void testWriteReplace() throws Exception { + ProxyFactory pf = new ProxyFactory(); + pf.setSuperclass(WriteReplace.class); + Object data = pf.createClass().getConstructor().newInstance(); + assertEquals(data, ((WriteReplace)data).writeReplace()); + + ProxyFactory pf2 = new ProxyFactory(); + pf2.setSuperclass(WriteReplace2.class); + Object data2 = pf2.createClass().getConstructor().newInstance(); + Method meth = data2.getClass().getDeclaredMethod("writeReplace", new Class[0]); + assertEquals("javassist.util.proxy.SerializedProxy", + meth.invoke(data2, new Object[0]).getClass().getName()); + } + + public static class WriteReplace implements Serializable { + public Object writeReplace() { return this; } + } + + public static class WriteReplace2 implements Serializable { + public Object writeReplace(int i) { return Integer.valueOf(i); } + } + + public static void testJIRA189() throws Exception { + Class persistentClass = Target189.PublishedArticle.class; + ProxyFactory factory = new ProxyFactory(); + //factory.writeDirectory = "."; + factory.setUseCache(false); + factory.setSuperclass(persistentClass); + factory.setInterfaces(new Class[] { Target189.TestProxy.class }); + Class cl = factory.createClass(); + Object obj = cl.getConstructor().newInstance(); + System.out.println("JIRA189:" + obj.getClass().getClassLoader() + ", " + obj.getClass().getSuperclass().getName() + + ", " + Target189.PublishedArticle.class.getClassLoader()); + Target189.TestProxy proxy = (Target189.TestProxy)cl.getConstructor().newInstance(); + Target189.TestMethodHandler methodHandler = new Target189.TestMethodHandler(); + ((ProxyObject)proxy).setHandler(methodHandler); + ((Target189.Article)proxy).getIssue(); + assertTrue(methodHandler.wasInvokedOnce()); + methodHandler.reset(); + Target189.PublishedArticle article = (Target189.PublishedArticle)proxy; + article.getIssue(); + assertTrue(methodHandler.wasInvokedOnce()); + } + + public void testJIRA127() throws Exception { + ProxyFactory proxyFactory = new ProxyFactory(); + // proxyFactory.writeDirectory = "."; + proxyFactory.setInterfaces(new Class[]{ Target127.Sub.class }); + Target127.Sub proxy = (Target127.Sub)proxyFactory.create(new Class[0], new Object[0], new MethodHandler() { + public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable { + return null; + } + }); + ((Target127.Super)proxy).item(); // proxyFactory must generate a bridge method. + ((Target127.Sub)proxy).item(); + } + + public static void main(String[] args) { + // javassist.bytecode.ClassFile.MAJOR_VERSION = javassist.bytecode.ClassFile.JAVA_6; + junit.textui.TestRunner.run(ProxyTester.class); + } +} -- 2.39.5