aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2011-09-01 10:11:05 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2011-09-01 10:11:05 +0000
commit3ad4da6d8cd5f11a8009c70f59d613b52cf4b50d (patch)
tree8b800e9c5d1063c15de7b4e72e2ae86cd7e616ad
parent40376610590391507fcbb46add4b368ad9fc15af (diff)
downloadjavassist-3ad4da6d8cd5f11a8009c70f59d613b52cf4b50d.tar.gz
javassist-3ad4da6d8cd5f11a8009c70f59d613b52cf4b50d.zip
fixed JASSIST-144
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@591 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
-rw-r--r--Readme.html2
-rw-r--r--src/main/javassist/util/proxy/Proxy.java33
-rw-r--r--src/main/javassist/util/proxy/ProxyFactory.java50
-rw-r--r--src/main/javassist/util/proxy/ProxyObject.java13
-rw-r--r--src/main/javassist/util/proxy/ProxyObjectOutputStream.java2
-rw-r--r--src/main/javassist/util/proxy/RuntimeSupport.java2
-rw-r--r--src/main/javassist/util/proxy/SerializedProxy.java5
-rw-r--r--src/test/javassist/JvstTest.java8
-rw-r--r--src/test/javassist/proxyfactory/Tester.java52
9 files changed, 149 insertions, 18 deletions
diff --git a/Readme.html b/Readme.html
index 07908f5b..f53e4680 100644
--- a/Readme.html
+++ b/Readme.html
@@ -283,7 +283,7 @@ see javassist.Dump.
<p>-version 3.16
<ul>
- <li>JIRA JASSIST-127
+ <li>JIRA JASSIST-127, 144
</ul>
<p>-version 3.15 on July 8, 2011
diff --git a/src/main/javassist/util/proxy/Proxy.java b/src/main/javassist/util/proxy/Proxy.java
new file mode 100644
index 00000000..c446523f
--- /dev/null
+++ b/src/main/javassist/util/proxy/Proxy.java
@@ -0,0 +1,33 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. Alternatively, the contents of this file may be used under
+ * the terms of the GNU Lesser General Public License Version 2.1 or later,
+ * or the Apache License Version 2.0.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ */
+
+package javassist.util.proxy;
+
+/**
+ * The interface implemented by proxy classes.
+ * This interface only provides a setter method.
+ * To obtain a handler, call {@link ProxyFactory#getHandler(Proxy)}.
+ *
+ * @see ProxyFactory
+ * @see 3.16
+ */
+public interface Proxy {
+ /**
+ * Sets a handler. It can be used for changing handlers
+ * during runtime.
+ */
+ void setHandler(MethodHandler mi);
+}
diff --git a/src/main/javassist/util/proxy/ProxyFactory.java b/src/main/javassist/util/proxy/ProxyFactory.java
index 721f58c8..9bce51fa 100644
--- a/src/main/javassist/util/proxy/ProxyFactory.java
+++ b/src/main/javassist/util/proxy/ProxyFactory.java
@@ -63,9 +63,11 @@ import javassist.bytecode.*;
* }
* };
* Foo foo = (Foo)c.newInstance();
- * ((ProxyObject)foo).setHandler(mi);
+ * ((Proxy)foo).setHandler(mi);
* </pre></ul>
*
+ * <p>Here, <code>Method</code> is <code>java.lang.reflect.Method</code>.</p>
+ *
* <p>Then, the following method call will be forwarded to MethodHandler
* <code>mi</code> and prints a message before executing the originally called method
* <code>bar()</code> in <code>Foo</code>.
@@ -88,7 +90,7 @@ import javassist.bytecode.*;
*
* <ul><pre>
* MethodHandler mi = ... ; // alternative handler
- * ((ProxyObject)foo).setHandler(mi);
+ * ((Proxy)foo).setHandler(mi);
* </pre></ul>
*
* <p> If setHandler is never called for a proxy instance then it will
@@ -119,7 +121,7 @@ import javassist.bytecode.*;
* with previous releases of javassist. Unfortunately,this legacy behaviour makes caching
* and reuse of proxy classes impossible. The current programming model expects javassist
* clients to set the handler of a proxy instance explicitly by calling method
- * {@link ProxyObject#setHandler(MethodHandler)} as shown in the sample code above. New
+ * {@link Proxy#setHandler(MethodHandler)} as shown in the sample code above. New
* clients are strongly recommended to use this model rather than calling
* {@link ProxyFactory#setHandler(MethodHandler)}.
*
@@ -156,6 +158,7 @@ public class ProxyFactory {
private MethodFilter methodFilter;
private MethodHandler handler; // retained for legacy usage
private List signatureMethods;
+ private boolean hasGetHandler;
private byte[] signature;
private String classname;
private String basename;
@@ -293,8 +296,8 @@ public class ProxyFactory {
*/
public static boolean isProxyClass(Class cl)
{
- // all proxies implement ProxyObject. nothing else should.
- return (ProxyObject.class.isAssignableFrom(cl));
+ // all proxies implement Proxy or ProxyObject. nothing else should.
+ return (Proxy.class.isAssignableFrom(cl));
}
/**
@@ -338,6 +341,7 @@ public class ProxyFactory {
handler = null;
signature = null;
signatureMethods = null;
+ hasGetHandler = false;
thisClass = null;
writeDirectory = null;
factoryUseCache = useCache;
@@ -543,6 +547,26 @@ public class ProxyFactory {
}
/**
+ * Obtains the method handler of the given proxy object.
+ *
+ * @param p a proxy object.
+ * @return the method handler.
+ * @since 3.16
+ */
+ public static MethodHandler getHandler(Proxy p) {
+ try {
+ Field f = p.getClass().getDeclaredField(HANDLER);
+ f.setAccessible(true);
+ Object value = f.get(p);
+ f.setAccessible(false);
+ return (MethodHandler)value;
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* A provider of class loaders.
*
* @see #classLoaderProvider
@@ -633,7 +657,7 @@ public class ProxyFactory {
InstantiationException, IllegalAccessException, InvocationTargetException
{
Object obj = create(paramTypes, args);
- ((ProxyObject)obj).setHandler(mh);
+ ((Proxy)obj).setHandler(mh);
return obj;
}
@@ -658,7 +682,7 @@ public class ProxyFactory {
* specified.
* @deprecated since 3.12
* use of this method is incompatible with proxy class caching.
- * instead clients should call method {@link ProxyObject#setHandler(MethodHandler)} to set the handler
+ * instead clients should call method {@link Proxy#setHandler(MethodHandler)} to set the handler
* for each newly created proxy instance.
* calling this method will automatically disable caching of classes created by the proxy factory.
*/
@@ -684,7 +708,7 @@ public class ProxyFactory {
private ClassFile make() throws CannotCompileException {
ClassFile cf = new ClassFile(false, classname, superName);
cf.setAccessFlags(AccessFlag.PUBLIC);
- setInterfaces(cf, interfaces);
+ setInterfaces(cf, interfaces, hasGetHandler ? Proxy.class : ProxyObject.class);
ConstPool pool = cf.getConstPool();
// legacy: we only add the static field for the default interceptor if caching is disabled
@@ -715,7 +739,8 @@ public class ProxyFactory {
int s = overrideMethods(cf, pool, classname);
addMethodsHolder(cf, pool, classname, s);
addSetter(classname, cf, pool);
- addGetter(classname, cf, pool);
+ if (!hasGetHandler)
+ addGetter(classname, cf, pool);
if (factoryWriteReplace) {
try {
@@ -774,6 +799,7 @@ public class ProxyFactory {
HashMap allMethods = getMethods(superClass, interfaces);
signatureMethods = new ArrayList(allMethods.entrySet());
+ hasGetHandler = allMethods.get(HANDLER_GETTER_KEY) != null;
Collections.sort(signatureMethods, sorter);
}
@@ -833,8 +859,8 @@ public class ProxyFactory {
}
}
- private static void setInterfaces(ClassFile cf, Class[] interfaces) {
- String setterIntf = ProxyObject.class.getName();
+ private static void setInterfaces(ClassFile cf, Class[] interfaces, Class proxyClass) {
+ String setterIntf = proxyClass.getName();
String[] list;
if (interfaces == null || interfaces.length == 0)
list = new String[] { setterIntf };
@@ -1055,6 +1081,8 @@ public class ProxyFactory {
}
}
+ private static final String HANDLER_GETTER_KEY = HANDLER_GETTER + ":()";
+
private static String keyToDesc(String key, Method m) {
String params = key.substring(key.indexOf(':') + 1);
return RuntimeSupport.makeDescriptor(params, m.getReturnType());
diff --git a/src/main/javassist/util/proxy/ProxyObject.java b/src/main/javassist/util/proxy/ProxyObject.java
index 46a0fbee..f04ae9a4 100644
--- a/src/main/javassist/util/proxy/ProxyObject.java
+++ b/src/main/javassist/util/proxy/ProxyObject.java
@@ -18,10 +18,15 @@ package javassist.util.proxy;
/**
* The interface implemented by proxy classes.
+ * This interface is available only if the super class of the proxy object
+ * does not have a <code>getHandler()</code> method. If the super class
+ * has <code>getHandler</code>, then <code>Proxy</code> interface is
+ * available.
*
* @see ProxyFactory
+ * @see Proxy
*/
-public interface ProxyObject {
+public interface ProxyObject extends Proxy {
/**
* Sets a handler. It can be used for changing handlers
* during runtime.
@@ -30,8 +35,10 @@ public interface ProxyObject {
/**
* Get the handler.
- * This can be used to access values of the underlying MethodHandler
- * or to serialize it properly.
+ * This can be used to access the underlying MethodHandler
+ * or to serialize it properly.
+ *
+ * @see ProxyFactory#getHandler(Proxy)
*/
MethodHandler getHandler();
}
diff --git a/src/main/javassist/util/proxy/ProxyObjectOutputStream.java b/src/main/javassist/util/proxy/ProxyObjectOutputStream.java
index 85a9adf7..31c3861b 100644
--- a/src/main/javassist/util/proxy/ProxyObjectOutputStream.java
+++ b/src/main/javassist/util/proxy/ProxyObjectOutputStream.java
@@ -57,7 +57,7 @@ public class ProxyObjectOutputStream extends ObjectOutputStream
writeInt(interfaces.length - 1);
for (int i = 0; i < interfaces.length; i++) {
Class interfaze = interfaces[i];
- if (interfaze != ProxyObject.class) {
+ if (interfaze != ProxyObject.class && interfaze != Proxy.class) {
name = interfaces[i].getName();
writeObject(name);
}
diff --git a/src/main/javassist/util/proxy/RuntimeSupport.java b/src/main/javassist/util/proxy/RuntimeSupport.java
index c11c72d8..687fc8dc 100644
--- a/src/main/javassist/util/proxy/RuntimeSupport.java
+++ b/src/main/javassist/util/proxy/RuntimeSupport.java
@@ -220,6 +220,8 @@ public class RuntimeSupport {
MethodHandler methodHandler = null;
if (proxy instanceof ProxyObject)
methodHandler = ((ProxyObject)proxy).getHandler();
+ else if (proxy instanceof Proxy)
+ methodHandler = ProxyFactory.getHandler((Proxy)proxy);
return new SerializedProxy(clazz, ProxyFactory.getFilterSignature(clazz), methodHandler);
}
diff --git a/src/main/javassist/util/proxy/SerializedProxy.java b/src/main/javassist/util/proxy/SerializedProxy.java
index 3bb13856..36425a88 100644
--- a/src/main/javassist/util/proxy/SerializedProxy.java
+++ b/src/main/javassist/util/proxy/SerializedProxy.java
@@ -43,9 +43,10 @@ class SerializedProxy implements Serializable {
int n = infs.length;
interfaces = new String[n - 1];
String setterInf = ProxyObject.class.getName();
+ String setterInf2 = Proxy.class.getName();
for (int i = 0; i < n; i++) {
String name = infs[i].getName();
- if (!name.equals(setterInf))
+ if (!name.equals(setterInf) && !name.equals(setterInf2))
interfaces[i] = name;
}
}
@@ -81,7 +82,7 @@ class SerializedProxy implements Serializable {
ProxyFactory f = new ProxyFactory();
f.setSuperclass(loadClass(superClass));
f.setInterfaces(infs);
- ProxyObject proxy = (ProxyObject)f.createClass(filterSignature).newInstance();
+ Proxy proxy = (Proxy)f.createClass(filterSignature).newInstance();
proxy.setHandler(handler);
return proxy;
}
diff --git a/src/test/javassist/JvstTest.java b/src/test/javassist/JvstTest.java
index 92154b38..f4ccaf6c 100644
--- a/src/test/javassist/JvstTest.java
+++ b/src/test/javassist/JvstTest.java
@@ -1118,6 +1118,14 @@ public class JvstTest extends JvstTestRoot {
suite.addTestSuite(testproxy.ProxyTester.class);
// suite.addTestSuite(testproxy.ProxyFactoryPerformanceTest.class);
suite.addTestSuite(javassist.proxyfactory.ProxyFactoryTest.class);
+ suite.addTestSuite(javassist.proxyfactory.Tester.class);
+ suite.addTestSuite(test.javassist.proxy.ProxySerializationTest.class);
+ suite.addTestSuite(test.javassist.convert.ArrayAccessReplaceTest.class);
+ suite.addTestSuite(test.javassist.proxy.JASSIST113RegressionTest.class);
+ //suite.addTestSuite(test.javassist.proxy.ProxyCacheGCTest.class);
+ suite.addTestSuite(test.javassist.proxy.ProxyFactoryCompatibilityTest.class);
+ suite.addTestSuite(test.javassist.proxy.ProxySerializationTest.class);
+ suite.addTestSuite(test.javassist.proxy.ProxySimpleTest.class);
return suite;
}
}
diff --git a/src/test/javassist/proxyfactory/Tester.java b/src/test/javassist/proxyfactory/Tester.java
new file mode 100644
index 00000000..39033885
--- /dev/null
+++ b/src/test/javassist/proxyfactory/Tester.java
@@ -0,0 +1,52 @@
+package javassist.proxyfactory;
+
+import junit.framework.*;
+import javassist.util.proxy.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Method;
+
+class Hand implements java.io.Serializable {
+ public int setHandler(int i) { return i; }
+ int getHandler() { return 3; }
+}
+
+public class Tester extends TestCase {
+ static class MHandler implements MethodHandler, java.io.Serializable {
+ public Object invoke(Object self, Method m, Method proceed,
+ Object[] args) throws Throwable {
+ System.out.println("Name: " + m.getName());
+ return proceed.invoke(self, args);
+ }
+ }
+
+ static MethodHandler mi = new MHandler();
+
+ public void test() throws Exception {
+ ProxyFactory f = new ProxyFactory();
+ f.setSuperclass(Hand.class);
+ Class c = f.createClass();
+ Hand foo = (Hand)c.newInstance();
+ ((Proxy)foo).setHandler(mi);
+ assertTrue(ProxyFactory.isProxyClass(c));
+ assertEquals(3, foo.getHandler());
+ }
+
+ public void test2() throws Exception {
+ ProxyFactory f = new ProxyFactory();
+ f.setSuperclass(Hand.class);
+ Hand h = (Hand)f.create(new Class[0], new Object[0], mi);
+ assertEquals(3, h.getHandler());
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ProxyObjectOutputStream out = new ProxyObjectOutputStream(bos);
+ out.writeObject(h);
+ out.close();
+ byte[] bytes = bos.toByteArray();
+ ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+ ProxyObjectInputStream in = new ProxyObjectInputStream(bis);
+ Hand h2 = (Hand)in.readObject();
+ assertEquals(3, h2.getHandler());
+ }
+}