1 package test.javassist.proxy; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7 import java.io.Serializable; 8 import java.lang.reflect.Method; 9 10 import javassist.util.proxy.MethodFilter; 11 import javassist.util.proxy.MethodHandler; 12 import javassist.util.proxy.Proxy; 13 import javassist.util.proxy.ProxyFactory; 14 import junit.framework.TestCase; 15 16 @SuppressWarnings({"rawtypes","unchecked"}) 17 public class ProxySimpleTest extends TestCase { 18 19 String testResult; 20 testProxyFactory()21 public void testProxyFactory() throws Exception { 22 ProxyFactory f = new ProxyFactory(); 23 f.writeDirectory = "./proxy"; 24 f.setSuperclass(Foo.class); 25 f.setFilter(new MethodFilter() { 26 public boolean isHandled(Method m) { 27 return m.getName().startsWith("f"); 28 } 29 }); 30 Class c = f.createClass(); 31 MethodHandler mi = new MethodHandler() { 32 public Object invoke(Object self, Method m, Method proceed, 33 Object[] args) throws Throwable { 34 testResult += args[0].toString(); 35 return proceed.invoke(self, args); // execute the original method. 36 } 37 }; 38 Foo foo = (Foo)c.getConstructor().newInstance(); 39 ((Proxy)foo).setHandler(mi); 40 testResult = ""; 41 foo.foo(1); 42 foo.foo2(2); 43 foo.bar(3); 44 assertEquals("12", testResult); 45 } 46 47 public static class Foo { foo(int i)48 public int foo(int i) { return i + 1; } foo2(int i)49 public int foo2(int i) { return i + 2; } bar(int i)50 public int bar(int i) { return i + 1; } 51 } 52 testReadWrite()53 public void testReadWrite() throws Exception { 54 final String fileName = "read-write.bin"; 55 ProxyFactory.ClassLoaderProvider cp = ProxyFactory.classLoaderProvider; 56 try { 57 ProxyFactory.classLoaderProvider = new ProxyFactory.ClassLoaderProvider() { 58 public ClassLoader get(ProxyFactory pf) { 59 /* If javassist.Loader is returned, the super type of ReadWriteData class, 60 * which is Serializable, is loaded by javassist.Loader as well as ReadWriteData. 61 * This breaks the implementation of the object serializer. 62 */ 63 // return new javassist.Loader(); 64 return Thread.currentThread().getContextClassLoader(); 65 } 66 }; 67 ProxyFactory pf = new ProxyFactory(); 68 pf.setSuperclass(ReadWriteData.class); 69 Object data = pf.createClass().getConstructor().newInstance(); 70 // Object data = new ReadWriteData(); 71 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName)); 72 oos.writeObject(data); 73 oos.close(); 74 } 75 finally { 76 ProxyFactory.classLoaderProvider = cp; 77 } 78 79 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName)); 80 Object data2 = ois.readObject(); 81 ois.close(); 82 int i = ((ReadWriteData)data2).foo(); 83 assertEquals(4, i); 84 } 85 86 public static class ReadWriteData implements Serializable { 87 /** default serialVersionUID */ 88 private static final long serialVersionUID = 1L; 89 foo()90 public int foo() { return 4; } 91 } 92 testWriteReplace()93 public void testWriteReplace() throws Exception { 94 ProxyFactory pf = new ProxyFactory(); 95 pf.setSuperclass(WriteReplace.class); 96 Object data = pf.createClass().getConstructor().newInstance(); 97 assertEquals(data, ((WriteReplace)data).writeReplace()); 98 99 ProxyFactory pf2 = new ProxyFactory(); 100 pf2.setSuperclass(WriteReplace2.class); 101 Object data2 = pf2.createClass().getConstructor().newInstance(); 102 Method meth = data2.getClass().getDeclaredMethod("writeReplace", new Class[0]); 103 assertEquals("javassist.util.proxy.SerializedProxy", 104 meth.invoke(data2, new Object[0]).getClass().getName()); 105 } 106 107 public static class WriteReplace implements Serializable { 108 /** default serialVersionUID */ 109 private static final long serialVersionUID = 1L; 110 writeReplace()111 public Object writeReplace() { return this; } 112 } 113 114 public static class WriteReplace2 implements Serializable { 115 /** default serialVersionUID */ 116 private static final long serialVersionUID = 1L; 117 writeReplace(int i)118 public Object writeReplace(int i) { return Integer.valueOf(i); } 119 } 120 121 String value244; 122 testJIRA244()123 public void testJIRA244() throws Exception { 124 ProxyFactory factory = new ProxyFactory(); 125 factory.setSuperclass(Extended244.class); 126 Extended244 e = (Extended244)factory.create(null, null, new MethodHandler() { 127 @Override 128 public Object invoke(Object self, Method thisMethod, 129 Method proceed, Object[] args) throws Throwable { 130 value244 += thisMethod.getDeclaringClass().getName(); 131 return proceed.invoke(self); 132 } 133 }); 134 135 value244 = ""; 136 assertEquals("base", e.base()); 137 System.out.println(value244); 138 assertEquals(Extended244.class.getName(), value244); 139 140 value244 = ""; 141 assertEquals("ext", e.extended()); 142 System.out.println(value244); 143 assertEquals(Extended244.class.getName(), value244); 144 145 value244 = ""; 146 assertEquals("base2ext2", e.base2()); 147 System.out.println(value244); 148 assertEquals(Extended244.class.getName(), value244); 149 } 150 151 // if Base244 is private, then Extended244 has a bridge method for base(). 152 private static abstract class Base244 { base()153 public String base() { return "base"; } base2()154 public String base2() { return "base2"; } 155 } 156 157 public static class Extended244 extends Base244 { extended()158 public String extended() { return "ext"; } base2()159 public String base2() { return super.base2() + "ext2"; } 160 } 161 162 String valueDefaultMethods = ""; 163 testDefaultMethods()164 public void testDefaultMethods() throws Exception { 165 valueDefaultMethods = ""; 166 ProxyFactory f = new ProxyFactory(); 167 f.writeDirectory = "./proxy"; 168 f.setSuperclass(Default3.class); 169 Class c = f.createClass(); 170 MethodHandler mi = new MethodHandler() { 171 public Object invoke(Object self, Method m, Method proceed, 172 Object[] args) throws Throwable { 173 valueDefaultMethods += "1"; 174 return proceed.invoke(self, args); // execute the original method. 175 } 176 }; 177 Default3 foo = (Default3)c.getConstructor().newInstance(); 178 ((Proxy)foo).setHandler(mi); 179 foo.foo(); 180 foo.bar(); 181 assertEquals("11", valueDefaultMethods); 182 } 183 testDefaultMethods2()184 public void testDefaultMethods2() throws Exception { 185 valueDefaultMethods = ""; 186 ProxyFactory f = new ProxyFactory(); 187 f.writeDirectory = "./proxy"; 188 f.setInterfaces(new Class[] { Default2.class }); 189 Class c = f.createClass(); 190 MethodHandler mi = new MethodHandler() { 191 public Object invoke(Object self, Method m, Method proceed, 192 Object[] args) throws Throwable { 193 valueDefaultMethods += "1"; 194 return proceed.invoke(self, args); // execute the original method. 195 } 196 }; 197 Default2 foo = (Default2)c.getConstructor().newInstance(); 198 ((Proxy)foo).setHandler(mi); 199 foo.foo(); 200 foo.bar(); 201 assertEquals("11", valueDefaultMethods); 202 } 203 204 public static interface Default1 { foo()205 default int foo() { return 0; } baz()206 default int baz() { return 2; } 207 } 208 209 public static interface Default2 extends Default1 { bar()210 default int bar() { return 1; } 211 } 212 213 public static class Default3 implements Default2 { foo()214 public int foo() { return Default2.super.foo(); } 215 } 216 217 public static class Default4 extends Default3 { baz()218 public int baz() { return super.baz(); } 219 } 220 testPublicProxy()221 public void testPublicProxy() throws Exception { 222 ProxyFactory f = new ProxyFactory(); 223 f.writeDirectory = "./proxy"; 224 f.setSuperclass(PubProxy.class); 225 Class c = f.createClass(); 226 MethodHandler mi = new MethodHandler() { 227 public Object invoke(Object self, Method m, Method proceed, 228 Object[] args) throws Throwable { 229 PubProxy.result += args[0].toString(); 230 return proceed.invoke(self, args); 231 } 232 }; 233 PubProxy.result = ""; 234 PubProxy foo = (PubProxy)c.getConstructor().newInstance(); 235 ((Proxy)foo).setHandler(mi); 236 foo.foo(1); 237 foo.bar(2); 238 foo.baz(3); 239 assertEquals("c1p2q3r", PubProxy.result); 240 } 241 242 public static class PubProxy { 243 public static String result; PubProxy()244 public PubProxy() { result += "c"; } PubProxy(int i)245 PubProxy(int i) { result += "d"; } foo(int i)246 void foo(int i) { result += "p"; } bar(int i)247 protected void bar(int i) { result += "q"; } baz(int i)248 public void baz(int i) { result += "r"; } 249 } 250 testPublicProxy2()251 public void testPublicProxy2() throws Exception { 252 boolean b = ProxyFactory.onlyPublicMethods; 253 ProxyFactory.onlyPublicMethods = true; 254 ProxyFactory f = new ProxyFactory(); 255 f.writeDirectory = "./proxy"; 256 f.setSuperclass(PubProxy2.class); 257 Class c = f.createClass(); 258 MethodHandler mi = new MethodHandler() { 259 public Object invoke(Object self, Method m, Method proceed, 260 Object[] args) throws Throwable { 261 PubProxy2.result += args[0].toString(); 262 return proceed.invoke(self, args); 263 } 264 }; 265 266 PubProxy2.result = ""; 267 try { 268 PubProxy2 foo = (PubProxy2)c.getConstructor().newInstance(); 269 ((Proxy)foo).setHandler(mi); 270 foo.foo(1); // mi does not intercept this call. 271 foo.bar(2); 272 foo.baz(3); 273 assertEquals("cp2q3r", PubProxy2.result); 274 } 275 finally { 276 ProxyFactory.onlyPublicMethods = b; 277 } 278 } 279 280 public static class PubProxy2 { 281 public static String result; PubProxy2()282 public PubProxy2() { result += "c"; } PubProxy2(int i)283 PubProxy2(int i) { result += "d"; } foo(int i)284 void foo(int i) { result += "p"; } bar(int i)285 protected void bar(int i) { result += "q"; } baz(int i)286 public void baz(int i) { result += "r"; } 287 } 288 289 290 String value267; 291 testJIRA267()292 public void testJIRA267() throws Exception { 293 Extended267 extended267 = new Extended267(); 294 for (Method method: extended267.getClass().getMethods()) { 295 System.out.println(method.getName() + "::" + method.getModifiers() + ":" + method.getParameterCount() + ":" + method.isSynthetic() + ":" + method.isBridge()); 296 } 297 ProxyFactory factory = new ProxyFactory(); 298 factory.setSuperclass(Extended267.class); 299 Extended267 e = (Extended267)factory.create(null, null, new MethodHandler() { 300 @Override 301 public Object invoke(Object self, Method thisMethod, 302 Method proceed, Object[] args) throws Throwable { 303 value267 += thisMethod.getDeclaringClass().getName(); 304 return proceed.invoke(self, args); 305 } 306 }); 307 308 value267 = ""; 309 assertEquals("base", e.base()); 310 System.out.println(value267); 311 assertEquals(Extended267.class.getName(), value267); 312 313 value267 = ""; 314 assertEquals("base2", e.base("2")); 315 System.out.println(value267); 316 assertEquals(Extended267.class.getName(), value267); 317 318 value267 = ""; 319 assertEquals("extended22", e.base(2)); 320 System.out.println(value267); 321 assertEquals(Extended267.class.getName(), value267); 322 } 323 324 private static abstract class Base267 { base()325 public String base() { return "base"; } base(String s)326 public String base(String s) { return "base" + s; } base(Integer i)327 public String base(Integer i) { return "base" + i; } 328 } 329 330 public static class Extended267 extends Base267 { base(Integer i)331 public String base(Integer i) { return "extended" + i + i; } 332 } 333 334 String value267b; 335 testJIRA267b()336 public void testJIRA267b() throws Exception { 337 Extended267b extended267 = new Extended267b(); 338 ProxyFactory factory = new ProxyFactory(); 339 factory.setSuperclass(Extended267b.class); 340 Extended267b e = (Extended267b)factory.create(null, null, new MethodHandler() { 341 @Override 342 public Object invoke(Object self, Method thisMethod, 343 Method proceed, Object[] args) throws Throwable { 344 value267b += thisMethod.getDeclaringClass().getName(); 345 value267b += ";" + thisMethod.getReturnType().getName(); 346 return proceed.invoke(self, args); 347 } 348 }); 349 350 value267b = ""; 351 assertEquals("extended", e.base()); 352 System.out.println(value267b); 353 assertEquals(Extended267b.class.getName() + ";" + String.class.getName(), value267b); 354 } 355 356 public static class Base267b { base()357 public Object base() { return "base"; } 358 } 359 360 // Extended267b has a bridge method for base():Object, 361 // since Extended267b#base() is covariant. 362 public static class Extended267b extends Base267b { base()363 public String base() { return "extended"; } 364 } 365 } 366