aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2006-01-11 06:06:30 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2006-01-11 06:06:30 +0000
commit52a455616e4077b5b61823cb4765c02fc6866f9a (patch)
treea9f95d54cccee9e336a667043b4e958d30257064 /src/main
parent5b8d2d6c7ab0102e8a1bb0384cf769ed8f0f34da (diff)
downloadjavassist-52a455616e4077b5b61823cb4765c02fc6866f9a.tar.gz
javassist-52a455616e4077b5b61823cb4765c02fc6866f9a.zip
restructred sub packages
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@233 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
-rw-r--r--src/main/javassist/CtClass.java2
-rw-r--r--src/main/javassist/CtMethod.java2
-rw-r--r--src/main/javassist/bytecode/Bytecode.java2
-rw-r--r--src/main/javassist/bytecode/Descriptor.java1
-rw-r--r--src/main/javassist/bytecode/annotation/package.html2
-rw-r--r--src/main/javassist/expr/MethodCall.java2
-rw-r--r--src/main/javassist/tools/package.html2
-rw-r--r--src/main/javassist/tools/reflect/CannotCreateException.java (renamed from src/main/javassist/reflect/CannotCreateException.java)2
-rw-r--r--src/main/javassist/tools/reflect/CannotInvokeException.java (renamed from src/main/javassist/reflect/CannotInvokeException.java)8
-rw-r--r--src/main/javassist/tools/reflect/CannotReflectException.java (renamed from src/main/javassist/reflect/CannotReflectException.java)4
-rw-r--r--src/main/javassist/tools/reflect/ClassMetaobject.java (renamed from src/main/javassist/reflect/ClassMetaobject.java)6
-rw-r--r--src/main/javassist/tools/reflect/Compiler.java (renamed from src/main/javassist/reflect/Compiler.java)16
-rw-r--r--src/main/javassist/tools/reflect/Loader.java (renamed from src/main/javassist/reflect/Loader.java)34
-rw-r--r--src/main/javassist/tools/reflect/Metalevel.java (renamed from src/main/javassist/reflect/Metalevel.java)2
-rw-r--r--src/main/javassist/tools/reflect/Metaobject.java (renamed from src/main/javassist/reflect/Metaobject.java)8
-rw-r--r--src/main/javassist/tools/reflect/Reflection.java (renamed from src/main/javassist/reflect/Reflection.java)36
-rw-r--r--src/main/javassist/tools/reflect/Sample.java (renamed from src/main/javassist/reflect/Sample.java)2
-rw-r--r--src/main/javassist/tools/reflect/package.html (renamed from src/main/javassist/reflect/package.html)0
-rw-r--r--src/main/javassist/tools/rmi/AppletServer.java (renamed from src/main/javassist/rmi/AppletServer.java)9
-rw-r--r--src/main/javassist/tools/rmi/ObjectImporter.java (renamed from src/main/javassist/rmi/ObjectImporter.java)15
-rw-r--r--src/main/javassist/tools/rmi/ObjectNotFoundException.java (renamed from src/main/javassist/rmi/ObjectNotFoundException.java)2
-rw-r--r--src/main/javassist/tools/rmi/Proxy.java (renamed from src/main/javassist/rmi/Proxy.java)4
-rw-r--r--src/main/javassist/tools/rmi/RemoteException.java (renamed from src/main/javassist/rmi/RemoteException.java)2
-rw-r--r--src/main/javassist/tools/rmi/RemoteRef.java (renamed from src/main/javassist/rmi/RemoteRef.java)2
-rw-r--r--src/main/javassist/tools/rmi/Sample.java (renamed from src/main/javassist/rmi/Sample.java)2
-rw-r--r--src/main/javassist/tools/rmi/StubGenerator.java (renamed from src/main/javassist/rmi/StubGenerator.java)12
-rw-r--r--src/main/javassist/tools/rmi/package.html (renamed from src/main/javassist/rmi/package.html)0
-rw-r--r--src/main/javassist/tools/web/BadHttpRequest.java (renamed from src/main/javassist/web/BadHttpRequest.java)2
-rw-r--r--src/main/javassist/tools/web/Viewer.java (renamed from src/main/javassist/web/Viewer.java)8
-rw-r--r--src/main/javassist/tools/web/Webserver.java (renamed from src/main/javassist/web/Webserver.java)4
-rw-r--r--src/main/javassist/tools/web/package.html (renamed from src/main/javassist/web/package.html)0
-rw-r--r--src/main/javassist/util/HotSwapper.java (renamed from src/main/javassist/tools/HotSwapper.java)4
-rw-r--r--src/main/javassist/util/package.html5
-rw-r--r--src/main/javassist/util/proxy/FactoryHelper.java182
-rw-r--r--src/main/javassist/util/proxy/MethodFilter.java30
-rw-r--r--src/main/javassist/util/proxy/MethodHandler.java48
-rw-r--r--src/main/javassist/util/proxy/ProxyFactory.java699
-rw-r--r--src/main/javassist/util/proxy/ProxyObject.java29
-rw-r--r--src/main/javassist/util/proxy/RuntimeSupport.java157
-rw-r--r--src/main/javassist/util/proxy/package.html5
40 files changed, 1254 insertions, 98 deletions
diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java
index 74ab0d3e..d4178e7f 100644
--- a/src/main/javassist/CtClass.java
+++ b/src/main/javassist/CtClass.java
@@ -703,7 +703,7 @@ public abstract class CtClass {
*
* @param name method name
* @param desc method descriptor
- * @see CtBehavior.getSignature()
+ * @see CtBehavior#getSignature()
* @see javassist.bytecode.Descriptor
*/
public CtMethod getMethod(String name, String desc)
diff --git a/src/main/javassist/CtMethod.java b/src/main/javassist/CtMethod.java
index 043c8d3b..abb42b88 100644
--- a/src/main/javassist/CtMethod.java
+++ b/src/main/javassist/CtMethod.java
@@ -118,7 +118,7 @@ public final class CtMethod extends CtBehavior {
*
* @param src the source text.
* @param declaring the class to which the created method is added.
- * @see CtNewMethod.make(String, CtClass)
+ * @see CtNewMethod#make(String, CtClass)
*/
public static CtMethod make(String src, CtClass declaring)
throws CannotCompileException
diff --git a/src/main/javassist/bytecode/Bytecode.java b/src/main/javassist/bytecode/Bytecode.java
index a1f74c6d..b2a0ee23 100644
--- a/src/main/javassist/bytecode/Bytecode.java
+++ b/src/main/javassist/bytecode/Bytecode.java
@@ -1339,7 +1339,7 @@ public class Bytecode extends ByteVector implements Cloneable, Opcode {
* Appends PUTSTATIC.
*
* @param classname the fully-qualified name of the target class.
- * @param filedName the field name.
+ * @param fieldName the field name.
* @param desc the descriptor of the field type.
*/
public void addPutstatic(String classname, String fieldName, String desc) {
diff --git a/src/main/javassist/bytecode/Descriptor.java b/src/main/javassist/bytecode/Descriptor.java
index ef194b7f..39577ce2 100644
--- a/src/main/javassist/bytecode/Descriptor.java
+++ b/src/main/javassist/bytecode/Descriptor.java
@@ -717,7 +717,6 @@ public class Descriptor {
/**
* Returns the first character of the current element.
- * @return
*/
public char currentChar() { return desc.charAt(curPos); }
diff --git a/src/main/javassist/bytecode/annotation/package.html b/src/main/javassist/bytecode/annotation/package.html
index 6cf7e538..d0656db6 100644
--- a/src/main/javassist/bytecode/annotation/package.html
+++ b/src/main/javassist/bytecode/annotation/package.html
@@ -1,6 +1,6 @@
<html>
<body>
-Annotations API.
+Bytecode-level Annotations API.
<p>This package provides low-level API for editing annotations attributes.
diff --git a/src/main/javassist/expr/MethodCall.java b/src/main/javassist/expr/MethodCall.java
index 7bc2c388..9fd29e2a 100644
--- a/src/main/javassist/expr/MethodCall.java
+++ b/src/main/javassist/expr/MethodCall.java
@@ -120,7 +120,7 @@ public class MethodCall extends Expr {
* The method signature is represented by a character string
* called method descriptor, which is defined in the JVM specification.
*
- * @see javassist.CtBehavior.getSignature()
+ * @see javassist.CtBehavior#getSignature()
* @see javassist.bytecode.Descriptor
* @since 3.1
*/
diff --git a/src/main/javassist/tools/package.html b/src/main/javassist/tools/package.html
index 1566e121..bee6208d 100644
--- a/src/main/javassist/tools/package.html
+++ b/src/main/javassist/tools/package.html
@@ -1,6 +1,6 @@
<html>
<body>
-Utility classes.
+Covenient tools.
</body>
</html>
diff --git a/src/main/javassist/reflect/CannotCreateException.java b/src/main/javassist/tools/reflect/CannotCreateException.java
index a0933830..efa14111 100644
--- a/src/main/javassist/reflect/CannotCreateException.java
+++ b/src/main/javassist/tools/reflect/CannotCreateException.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
/**
* Signals that <code>ClassMetaobject.newInstance()</code> fails.
diff --git a/src/main/javassist/reflect/CannotInvokeException.java b/src/main/javassist/tools/reflect/CannotInvokeException.java
index c778e89d..d283d6d7 100644
--- a/src/main/javassist/reflect/CannotInvokeException.java
+++ b/src/main/javassist/tools/reflect/CannotInvokeException.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.IllegalAccessException;
@@ -22,9 +22,9 @@ import java.lang.IllegalAccessException;
* Thrown when method invocation using the reflection API has thrown
* an exception.
*
- * @see javassist.reflect.Metaobject#trapMethodcall(int, Object[])
- * @see javassist.reflect.ClassMetaobject#trapMethodcall(int, Object[])
- * @see javassist.reflect.ClassMetaobject#invoke(Object, int, Object[])
+ * @see javassist.tools.reflect.Metaobject#trapMethodcall(int, Object[])
+ * @see javassist.tools.reflect.ClassMetaobject#trapMethodcall(int, Object[])
+ * @see javassist.tools.reflect.ClassMetaobject#invoke(Object, int, Object[])
*/
public class CannotInvokeException extends RuntimeException {
diff --git a/src/main/javassist/reflect/CannotReflectException.java b/src/main/javassist/tools/reflect/CannotReflectException.java
index 036ebf49..30c448b3 100644
--- a/src/main/javassist/reflect/CannotReflectException.java
+++ b/src/main/javassist/tools/reflect/CannotReflectException.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
import javassist.CannotCompileException;
@@ -24,7 +24,7 @@ import javassist.CannotCompileException;
* either ClassMetaobject or Metaobject.
*
* @author Brett Randall
- * @see javassist.reflect.Reflection#makeReflective(CtClass,CtClass,CtClass)
+ * @see javassist.tools.reflect.Reflection#makeReflective(CtClass,CtClass,CtClass)
* @see javassist.CannotCompileException
*/
public class CannotReflectException extends CannotCompileException {
diff --git a/src/main/javassist/reflect/ClassMetaobject.java b/src/main/javassist/tools/reflect/ClassMetaobject.java
index 61328452..d0a645cc 100644
--- a/src/main/javassist/reflect/ClassMetaobject.java
+++ b/src/main/javassist/tools/reflect/ClassMetaobject.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
import java.lang.reflect.*;
import java.util.Arrays;
@@ -35,8 +35,8 @@ import java.io.ObjectOutputStream;
* <ul><pre>ClassMetaobject cm = ((Metalevel)reflectiveObject)._getClass();
* </pre></ul>
*
- * @see javassist.reflect.Metaobject
- * @see javassist.reflect.Metalevel
+ * @see javassist.tools.reflect.Metaobject
+ * @see javassist.tools.reflect.Metalevel
*/
public class ClassMetaobject implements Serializable {
/**
diff --git a/src/main/javassist/reflect/Compiler.java b/src/main/javassist/tools/reflect/Compiler.java
index 734f598b..7e1fb943 100644
--- a/src/main/javassist/reflect/Compiler.java
+++ b/src/main/javassist/tools/reflect/Compiler.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
import javassist.CtClass;
import javassist.ClassPool;
@@ -31,7 +31,7 @@ class CompiledClass {
* <p>This translator directly modifies class files on a local disk so that
* the classes represented by those class files are reflective.
* After the modification, the class files can be run with the standard JVM
- * without <code>javassist.reflect.Loader</code>
+ * without <code>javassist.tools.reflect.Loader</code>
* or any other user-defined class loader.
*
* <p>The modified class files are given as the command-line parameters,
@@ -63,9 +63,9 @@ class CompiledClass {
* <p>Note that if the super class is also made reflective, it must be done
* before the sub class.
*
- * @see javassist.reflect.Metaobject
- * @see javassist.reflect.ClassMetaobject
- * @see javassist.reflect.Reflection
+ * @see javassist.tools.reflect.Metaobject
+ * @see javassist.tools.reflect.ClassMetaobject
+ * @see javassist.tools.reflect.Reflection
*/
public class Compiler {
@@ -100,12 +100,12 @@ public class Compiler {
String metaobj, classobj;
if (entries[i].metaobject == null)
- metaobj = "javassist.reflect.Metaobject";
+ metaobj = "javassist.tools.reflect.Metaobject";
else
metaobj = entries[i].metaobject;
if (entries[i].classobject == null)
- classobj = "javassist.reflect.ClassMetaobject";
+ classobj = "javassist.tools.reflect.ClassMetaobject";
else
classobj = entries[i].classobject;
@@ -156,7 +156,7 @@ public class Compiler {
}
private static void help(PrintStream out) {
- out.println("Usage: java javassist.reflect.Compiler");
+ out.println("Usage: java javassist.tools.reflect.Compiler");
out.println(" (<class> [-m <metaobject>] [-c <class metaobject>])+");
}
}
diff --git a/src/main/javassist/reflect/Loader.java b/src/main/javassist/tools/reflect/Loader.java
index 76dce4d6..36189edf 100644
--- a/src/main/javassist/reflect/Loader.java
+++ b/src/main/javassist/tools/reflect/Loader.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
import javassist.CannotCompileException;
import javassist.NotFoundException;
@@ -29,10 +29,10 @@ import javassist.ClassPool;
* <ul><pre>
* public class Main {
* public static void main(String[] args) throws Throwable {
- * javassist.reflect.Loader cl
- * = (javassist.reflect.Loader)Main.class.getClassLoader();
+ * javassist.tools.reflect.Loader cl
+ * = (javassist.tools.reflect.Loader)Main.class.getClassLoader();
* cl.makeReflective("Person", "MyMetaobject",
- * "javassist.reflect.ClassMetaobject");
+ * "javassist.tools.reflect.ClassMetaobject");
* cl.run("MyApp", args);
* }
* }
@@ -40,7 +40,7 @@ import javassist.ClassPool;
*
* <p>Then run this program as follows:
*
- * <ul><pre>% java javassist.reflect.Loader Main arg1, ...</pre></ul>
+ * <ul><pre>% java javassist.tools.reflect.Loader Main arg1, ...</pre></ul>
*
* <p>This command runs <code>Main.main()</code> with <code>arg1</code>, ...
* and <code>Main.main()</code> runs <code>MyApp.main()</code> with
@@ -54,9 +54,9 @@ import javassist.ClassPool;
* <ul><pre>
* public class Main2 {
* public static void main(String[] args) throws Throwable {
- * javassist.reflect.Loader cl = new javassist.reflect.Loader();
+ * javassist.tools.reflect.Loader cl = new javassist.tools.reflect.Loader();
* cl.makeReflective("Person", "MyMetaobject",
- * "javassist.reflect.ClassMetaobject");
+ * "javassist.tools.reflect.ClassMetaobject");
* cl.run("MyApp", args);
* }
* }
@@ -67,11 +67,11 @@ import javassist.ClassPool;
* <ul><pre>% java Main2 arg1, ...</pre></ul>
*
* <p>The difference from the former one is that the class <code>Main</code>
- * is loaded by <code>javassist.reflect.Loader</code> whereas the class
+ * is loaded by <code>javassist.tools.reflect.Loader</code> whereas the class
* <code>Main2</code> is not. Thus, <code>Main</code> belongs
* to the same name space (security domain) as <code>MyApp</code>
* whereas <code>Main2</code> does not; <code>Main2</code> belongs
- * to the same name space as <code>javassist.reflect.Loader</code>.
+ * to the same name space as <code>javassist.tools.reflect.Loader</code>.
* For more details,
* see the notes in the manual page of <code>javassist.Loader</code>.
*
@@ -84,7 +84,7 @@ import javassist.ClassPool;
* javassist.Loader cl
* = new javassist.Loader(ClassPool.getDefault(reflection));
* reflection.makeReflective("Person", "MyMetaobject",
- * "javassist.reflect.ClassMetaobject");
+ * "javassist.tools.reflect.ClassMetaobject");
* cl.run("MyApp", args);
* }
* }
@@ -92,18 +92,18 @@ import javassist.ClassPool;
*
* <p><b>Note:</b>
*
- * <p><code>javassist.reflect.Loader</code> does not make a class reflective
+ * <p><code>javassist.tools.reflect.Loader</code> does not make a class reflective
* if that class is in a <code>java.*</code> or
* <code>javax.*</code> pacakge because of the specifications
* on the class loading algorithm of Java. The JVM does not allow to
* load such a system class with a user class loader.
*
* <p>To avoid this limitation, those classes should be statically
- * modified with <code>javassist.reflect.Compiler</code> and the original
+ * modified with <code>javassist.tools.reflect.Compiler</code> and the original
* class files should be replaced.
*
- * @see javassist.reflect.Reflection
- * @see javassist.reflect.Compiler
+ * @see javassist.tools.reflect.Reflection
+ * @see javassist.tools.reflect.Compiler
* @see javassist.Loader
*/
public class Loader extends javassist.Loader {
@@ -130,7 +130,7 @@ public class Loader extends javassist.Loader {
*/
public Loader() throws CannotCompileException, NotFoundException {
super();
- delegateLoadingOf("javassist.reflect.Loader");
+ delegateLoadingOf("javassist.tools.reflect.Loader");
reflection = new Reflection();
ClassPool pool = ClassPool.getDefault();
@@ -151,8 +151,8 @@ public class Loader extends javassist.Loader {
* <code>ClassMetaobject</code>.
* @return <code>false</code> if the class is already reflective.
*
- * @see javassist.reflect.Metaobject
- * @see javassist.reflect.ClassMetaobject
+ * @see javassist.tools.reflect.Metaobject
+ * @see javassist.tools.reflect.ClassMetaobject
*/
public boolean makeReflective(String clazz,
String metaobject, String metaclass)
diff --git a/src/main/javassist/reflect/Metalevel.java b/src/main/javassist/tools/reflect/Metalevel.java
index 8192267a..db45cad9 100644
--- a/src/main/javassist/reflect/Metalevel.java
+++ b/src/main/javassist/tools/reflect/Metalevel.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
/**
* An interface to access a metaobject and a class metaobject.
diff --git a/src/main/javassist/reflect/Metaobject.java b/src/main/javassist/tools/reflect/Metaobject.java
index 8c3749aa..e89b5398 100644
--- a/src/main/javassist/reflect/Metaobject.java
+++ b/src/main/javassist/tools/reflect/Metaobject.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
import java.lang.reflect.Method;
import java.io.Serializable;
@@ -39,8 +39,8 @@ import java.io.ObjectOutputStream;
* <ul><pre>Metaobject m = ((Metalevel)reflectiveObject)._getMetaobject();
* </pre></ul>
*
- * @see javassist.reflect.ClassMetaobject
- * @see javassist.reflect.Metalevel
+ * @see javassist.tools.reflect.ClassMetaobject
+ * @see javassist.tools.reflect.Metalevel
*/
public class Metaobject implements Serializable {
protected ClassMetaobject classmetaobject;
@@ -88,7 +88,7 @@ public class Metaobject implements Serializable {
/**
* Obtains the class metaobject associated with this metaobject.
*
- * @see javassist.reflect.ClassMetaobject
+ * @see javassist.tools.reflect.ClassMetaobject
*/
public final ClassMetaobject getClassMetaobject() {
return classmetaobject;
diff --git a/src/main/javassist/reflect/Reflection.java b/src/main/javassist/tools/reflect/Reflection.java
index cd4f441c..06ce2ccf 100644
--- a/src/main/javassist/reflect/Reflection.java
+++ b/src/main/javassist/tools/reflect/Reflection.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
import javassist.*;
import javassist.CtMethod.ConstParameter;
@@ -54,10 +54,10 @@ import javassist.CtMethod.ConstParameter;
* }
* </pre></ul>
*
- * @see javassist.reflect.ClassMetaobject
- * @see javassist.reflect.Metaobject
- * @see javassist.reflect.Loader
- * @see javassist.reflect.Compiler
+ * @see javassist.tools.reflect.ClassMetaobject
+ * @see javassist.tools.reflect.Metaobject
+ * @see javassist.tools.reflect.Loader
+ * @see javassist.tools.reflect.Compiler
*/
public class Reflection implements Translator {
@@ -69,9 +69,9 @@ public class Reflection implements Translator {
static final String readPrefix = "_r_";
static final String writePrefix = "_w_";
- static final String metaobjectClassName = "javassist.reflect.Metaobject";
+ static final String metaobjectClassName = "javassist.tools.reflect.Metaobject";
static final String classMetaobjectClassName
- = "javassist.reflect.ClassMetaobject";
+ = "javassist.tools.reflect.ClassMetaobject";
protected CtMethod trapMethod, trapStaticMethod;
protected CtMethod trapRead, trapWrite;
@@ -103,9 +103,9 @@ public class Reflection implements Translator {
public void start(ClassPool pool) throws NotFoundException {
classPool = pool;
final String msg
- = "javassist.reflect.Sample is not found or broken.";
+ = "javassist.tools.reflect.Sample is not found or broken.";
try {
- CtClass c = classPool.get("javassist.reflect.Sample");
+ CtClass c = classPool.get("javassist.tools.reflect.Sample");
trapMethod = c.getDeclaredMethod("trap");
trapStaticMethod = c.getDeclaredMethod("trapStatic");
trapRead = c.getDeclaredMethod("trapRead");
@@ -139,8 +139,8 @@ public class Reflection implements Translator {
* @param metaclass the class name of the class metaobject.
* @return <code>false</code> if the class is already reflective.
*
- * @see javassist.reflect.Metaobject
- * @see javassist.reflect.ClassMetaobject
+ * @see javassist.tools.reflect.Metaobject
+ * @see javassist.tools.reflect.ClassMetaobject
*/
public boolean makeReflective(String classname,
String metaobject, String metaclass)
@@ -165,8 +165,8 @@ public class Reflection implements Translator {
* <code>ClassMetaobject</code>.
* @return <code>false</code> if the class is already reflective.
*
- * @see javassist.reflect.Metaobject
- * @see javassist.reflect.ClassMetaobject
+ * @see javassist.tools.reflect.Metaobject
+ * @see javassist.tools.reflect.ClassMetaobject
*/
public boolean makeReflective(Class clazz,
Class metaobject, Class metaclass)
@@ -191,8 +191,8 @@ public class Reflection implements Translator {
* <code>ClassMetaobject</code>.
* @return <code>false</code> if the class is already reflective.
*
- * @see javassist.reflect.Metaobject
- * @see javassist.reflect.ClassMetaobject
+ * @see javassist.tools.reflect.Metaobject
+ * @see javassist.tools.reflect.ClassMetaobject
*/
public boolean makeReflective(CtClass clazz,
CtClass metaobject, CtClass metaclass)
@@ -243,7 +243,7 @@ public class Reflection implements Translator {
else
clazz.setAttribute("Reflective", new byte[0]);
- CtClass mlevel = classPool.get("javassist.reflect.Metalevel");
+ CtClass mlevel = classPool.get("javassist.tools.reflect.Metalevel");
boolean addMeta = !clazz.subtypeOf(mlevel);
if (addMeta)
clazz.addInterface(mlevel);
@@ -253,7 +253,7 @@ public class Reflection implements Translator {
CtField f;
if (addMeta) {
- f = new CtField(classPool.get("javassist.reflect.Metaobject"),
+ f = new CtField(classPool.get("javassist.tools.reflect.Metaobject"),
metaobjectField, clazz);
f.setModifiers(Modifier.PROTECTED);
clazz.addField(f, CtField.Initializer.byNewWithParams(metaobject));
@@ -262,7 +262,7 @@ public class Reflection implements Translator {
clazz.addMethod(CtNewMethod.setter(metaobjectSetter, f));
}
- f = new CtField(classPool.get("javassist.reflect.ClassMetaobject"),
+ f = new CtField(classPool.get("javassist.tools.reflect.ClassMetaobject"),
classobjectField, clazz);
f.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
clazz.addField(f, CtField.Initializer.byNew(metaclass,
diff --git a/src/main/javassist/reflect/Sample.java b/src/main/javassist/tools/reflect/Sample.java
index 81bad691..4e70236a 100644
--- a/src/main/javassist/reflect/Sample.java
+++ b/src/main/javassist/tools/reflect/Sample.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.reflect;
+package javassist.tools.reflect;
/**
* A template used for defining a reflective class.
diff --git a/src/main/javassist/reflect/package.html b/src/main/javassist/tools/reflect/package.html
index 10a41964..10a41964 100644
--- a/src/main/javassist/reflect/package.html
+++ b/src/main/javassist/tools/reflect/package.html
diff --git a/src/main/javassist/rmi/AppletServer.java b/src/main/javassist/tools/rmi/AppletServer.java
index 89cc92ab..5056e24c 100644
--- a/src/main/javassist/rmi/AppletServer.java
+++ b/src/main/javassist/tools/rmi/AppletServer.java
@@ -13,10 +13,11 @@
* License.
*/
-package javassist.rmi;
+package javassist.tools.rmi;
import java.io.*;
-import javassist.web.*;
+
+import javassist.tools.web.*;
import javassist.CannotCompileException;
import javassist.NotFoundException;
import javassist.ClassPool;
@@ -31,7 +32,7 @@ import java.util.Vector;
* If the classes of the exported objects are requested by the client-side
* JVM, this web server sends proxy classes for the requested classes.
*
- * @see javassist.rmi.ObjectImporter
+ * @see javassist.tools.rmi.ObjectImporter
*/
public class AppletServer extends Webserver {
private StubGenerator stubGen;
@@ -102,7 +103,7 @@ public class AppletServer extends Webserver {
* @param obj the exported object.
* @return the object identifier
*
- * @see javassist.rmi.ObjectImporter#lookupObject(String)
+ * @see javassist.tools.rmi.ObjectImporter#lookupObject(String)
*/
public synchronized int exportObject(String name, Object obj)
throws CannotCompileException
diff --git a/src/main/javassist/rmi/ObjectImporter.java b/src/main/javassist/tools/rmi/ObjectImporter.java
index adad468d..75f5aa60 100644
--- a/src/main/javassist/rmi/ObjectImporter.java
+++ b/src/main/javassist/tools/rmi/ObjectImporter.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.rmi;
+package javassist.tools.rmi;
import java.io.*;
import java.net.*;
@@ -22,7 +22,8 @@ import java.lang.reflect.*;
/**
* The object importer enables applets to call a method on a remote
- * object running on the <code>Webserver</code>.
+ * object running on the <code>Webserver</code> (the <b>main</b> class of this
+ * package).
*
* <p>To access the remote
* object, the applet first calls <code>lookupObject()</code> and
@@ -66,9 +67,9 @@ import java.lang.reflect.*;
* to catch the exception. However, good programs should catch
* the <code>RuntimeException</code>.
*
- * @see javassist.rmi.AppletServer
- * @see javassist.rmi.RemoteException
- * @see javassist.web.Viewer
+ * @see javassist.tools.rmi.AppletServer
+ * @see javassist.tools.rmi.RemoteException
+ * @see javassist.tools.web.Viewer
*/
public class ObjectImporter implements java.io.Serializable {
private final byte[] endofline = { 0x0d, 0x0a };
@@ -95,7 +96,7 @@ public class ObjectImporter implements java.io.Serializable {
/**
* Constructs an object importer.
*
- * <p>If you run a program with <code>javassist.web.Viewer</code>,
+ * <p>If you run a program with <code>javassist.tools.web.Viewer</code>,
* you can construct an object importer as follows:
*
* <ul><pre>
@@ -103,7 +104,7 @@ public class ObjectImporter implements java.io.Serializable {
* ObjectImporter oi = new ObjectImporter(v.getServer(), v.getPort());
* </pre></ul>
*
- * @see javassist.web.Viewer
+ * @see javassist.tools.web.Viewer
*/
public ObjectImporter(String servername, int port) {
this.orgServername = this.servername = servername;
diff --git a/src/main/javassist/rmi/ObjectNotFoundException.java b/src/main/javassist/tools/rmi/ObjectNotFoundException.java
index 85bc316e..e54a3257 100644
--- a/src/main/javassist/rmi/ObjectNotFoundException.java
+++ b/src/main/javassist/tools/rmi/ObjectNotFoundException.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.rmi;
+package javassist.tools.rmi;
public class ObjectNotFoundException extends Exception {
public ObjectNotFoundException(String name) {
diff --git a/src/main/javassist/rmi/Proxy.java b/src/main/javassist/tools/rmi/Proxy.java
index f627ac63..1512b87f 100644
--- a/src/main/javassist/rmi/Proxy.java
+++ b/src/main/javassist/tools/rmi/Proxy.java
@@ -13,12 +13,12 @@
* License.
*/
-package javassist.rmi;
+package javassist.tools.rmi;
/**
* An interface implemented by proxy classes.
*
- * @see javassist.rmi.StubGenerator
+ * @see javassist.tools.rmi.StubGenerator
*/
public interface Proxy {
int _getObjectId();
diff --git a/src/main/javassist/rmi/RemoteException.java b/src/main/javassist/tools/rmi/RemoteException.java
index ceb04f9f..27ebe71e 100644
--- a/src/main/javassist/rmi/RemoteException.java
+++ b/src/main/javassist/tools/rmi/RemoteException.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.rmi;
+package javassist.tools.rmi;
/**
* <code>RemoteException</code> represents any exception thrown
diff --git a/src/main/javassist/rmi/RemoteRef.java b/src/main/javassist/tools/rmi/RemoteRef.java
index fbd93add..edbf349f 100644
--- a/src/main/javassist/rmi/RemoteRef.java
+++ b/src/main/javassist/tools/rmi/RemoteRef.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.rmi;
+package javassist.tools.rmi;
/**
* Remote reference. This class is internally used for sending a remote
diff --git a/src/main/javassist/rmi/Sample.java b/src/main/javassist/tools/rmi/Sample.java
index b632cd03..a65b908d 100644
--- a/src/main/javassist/rmi/Sample.java
+++ b/src/main/javassist/tools/rmi/Sample.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.rmi;
+package javassist.tools.rmi;
/**
* A template used for defining a proxy class.
diff --git a/src/main/javassist/rmi/StubGenerator.java b/src/main/javassist/tools/rmi/StubGenerator.java
index eac40916..7681bd6d 100644
--- a/src/main/javassist/rmi/StubGenerator.java
+++ b/src/main/javassist/tools/rmi/StubGenerator.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.rmi;
+package javassist.tools.rmi;
import javassist.*;
import java.lang.reflect.Method;
@@ -43,7 +43,7 @@ public class StubGenerator implements Translator {
private static final String fieldImporter = "importer";
private static final String fieldObjectId = "objectId";
private static final String accessorObjectId = "_getObjectId";
- private static final String sampleClass = "javassist.rmi.Sample";
+ private static final String sampleClass = "javassist.tools.rmi.Sample";
private ClassPool classPool;
private Hashtable proxyClasses;
@@ -74,13 +74,13 @@ public class StubGenerator implements Translator {
forwardStaticMethod = c.getDeclaredMethod("forwardStatic");
proxyConstructorParamTypes
- = pool.get(new String[] { "javassist.rmi.ObjectImporter",
+ = pool.get(new String[] { "javassist.tools.rmi.ObjectImporter",
"int" });
interfacesForProxy
= pool.get(new String[] { "java.io.Serializable",
- "javassist.rmi.Proxy" });
+ "javassist.tools.rmi.Proxy" });
exceptionForProxy
- = new CtClass[] { pool.get("javassist.rmi.RemoteException") };
+ = new CtClass[] { pool.get("javassist.tools.rmi.RemoteException") };
}
/**
@@ -139,7 +139,7 @@ public class StubGenerator implements Translator {
proxy.setInterfaces(interfacesForProxy);
CtField f
- = new CtField(classPool.get("javassist.rmi.ObjectImporter"),
+ = new CtField(classPool.get("javassist.tools.rmi.ObjectImporter"),
fieldImporter, proxy);
f.setModifiers(Modifier.PRIVATE);
proxy.addField(f, CtField.Initializer.byParameter(0));
diff --git a/src/main/javassist/rmi/package.html b/src/main/javassist/tools/rmi/package.html
index 5432a948..5432a948 100644
--- a/src/main/javassist/rmi/package.html
+++ b/src/main/javassist/tools/rmi/package.html
diff --git a/src/main/javassist/web/BadHttpRequest.java b/src/main/javassist/tools/web/BadHttpRequest.java
index a1aee86a..606ce997 100644
--- a/src/main/javassist/web/BadHttpRequest.java
+++ b/src/main/javassist/tools/web/BadHttpRequest.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.web;
+package javassist.tools.web;
/**
* Thrown when receiving an invalid HTTP request.
diff --git a/src/main/javassist/web/Viewer.java b/src/main/javassist/tools/web/Viewer.java
index debc52af..6e737406 100644
--- a/src/main/javassist/web/Viewer.java
+++ b/src/main/javassist/tools/web/Viewer.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.web;
+package javassist.tools.web;
import java.io.*;
import java.net.*;
@@ -27,7 +27,7 @@ import java.net.*;
*
* <p>To run, you should type:
*
- * <ul><code>% java javassist.web.Viewer <i>host port</i> Main arg1, ...</code></ul>
+ * <ul><code>% java javassist.tools.web.Viewer <i>host port</i> Main arg1, ...</code></ul>
*
* <p>This command calls <code>Main.main()</code> with <code>arg1,...</code>
* All classes including <code>Main</code> are fetched from
@@ -63,7 +63,7 @@ public class Viewer extends ClassLoader {
}
else
System.err.println(
- "Usage: java javassist.web.Viewer <host> <port> class [args ...]");
+ "Usage: java javassist.tools.web.Viewer <host> <port> class [args ...]");
}
/**
@@ -138,7 +138,7 @@ public class Viewer extends ClassLoader {
protected Class findClass(String name) throws ClassNotFoundException {
Class c = null;
if (name.startsWith("java.") || name.startsWith("javax.")
- || name.equals("javassist.web.Viewer"))
+ || name.equals("javassist.tools.web.Viewer"))
c = findSystemClass(name);
if (c == null)
diff --git a/src/main/javassist/web/Webserver.java b/src/main/javassist/tools/web/Webserver.java
index 4da031df..e580feca 100644
--- a/src/main/javassist/web/Webserver.java
+++ b/src/main/javassist/tools/web/Webserver.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.web;
+package javassist.tools.web;
import java.net.*;
import java.io.*;
@@ -82,7 +82,7 @@ public class Webserver {
}
else
System.err.println(
- "Usage: java javassist.web.Webserver <port number>");
+ "Usage: java javassist.tools.web.Webserver <port number>");
}
/**
diff --git a/src/main/javassist/web/package.html b/src/main/javassist/tools/web/package.html
index 0c7fb453..0c7fb453 100644
--- a/src/main/javassist/web/package.html
+++ b/src/main/javassist/tools/web/package.html
diff --git a/src/main/javassist/tools/HotSwapper.java b/src/main/javassist/util/HotSwapper.java
index 7b5b5fa2..07abe7a0 100644
--- a/src/main/javassist/tools/HotSwapper.java
+++ b/src/main/javassist/util/HotSwapper.java
@@ -13,7 +13,7 @@
* License.
*/
-package javassist.tools;
+package javassist.util;
import com.sun.jdi.*;
import com.sun.jdi.connect.*;
@@ -81,7 +81,7 @@ public class HotSwapper {
private Trigger trigger;
private static final String HOST_NAME = "localhost";
- private static final String TRIGGER_NAME = "javassist.tools.Trigger";
+ private static final String TRIGGER_NAME = Trigger.class.getName();
/**
* Connects to the JVM.
diff --git a/src/main/javassist/util/package.html b/src/main/javassist/util/package.html
new file mode 100644
index 00000000..349d9962
--- /dev/null
+++ b/src/main/javassist/util/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Utility classes.
+</body>
+</html>
diff --git a/src/main/javassist/util/proxy/FactoryHelper.java b/src/main/javassist/util/proxy/FactoryHelper.java
new file mode 100644
index 00000000..01bd6bf1
--- /dev/null
+++ b/src/main/javassist/util/proxy/FactoryHelper.java
@@ -0,0 +1,182 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2005 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.
+ *
+ * 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;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import javassist.CannotCompileException;
+import javassist.bytecode.ClassFile;
+
+/**
+ * A helper class for implementing <code>ProxyFactory</code>.
+ * The users of <code>ProxyFactory</code> do not have to see this class.
+ *
+ * @see ProxyFactory
+ */
+public class FactoryHelper {
+ /**
+ * Returns an index for accessing arrays in this class.
+ *
+ * @throws RuntimeException if a given type is not a primitive type.
+ */
+ public static final int typeIndex(Class type) {
+ Class[] list = primitiveTypes;
+ int n = list.length;
+ for (int i = 0; i < n; i++)
+ if (list[i] == type)
+ return i;
+
+ throw new RuntimeException("bad type:" + type.getName());
+ }
+
+ /**
+ * <code>Class</code> objects representing primitive types.
+ */
+ public static final Class[] primitiveTypes = {
+ Boolean.TYPE, Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE,
+ Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE
+ };
+
+ /**
+ * The fully-qualified names of wrapper classes for primitive types.
+ */
+ public static final String[] wrapperTypes = {
+ "java.lang.Boolean", "java.lang.Byte", "java.lang.Character",
+ "java.lang.Short", "java.lang.Integer", "java.lang.Long",
+ "java.lang.Float", "java.lang.Double", "java.lang.Void"
+ };
+
+ /**
+ * The descriptors of the constructors of wrapper classes.
+ */
+ public static final String[] wrapperDesc = {
+ "(Z)V", "(B)V", "(C)V", "(S)V", "(I)V", "(J)V",
+ "(F)V", "(D)V"
+ };
+
+ /**
+ * The names of methods for obtaining a primitive value
+ * from a wrapper object. For example, <code>intValue()</code>
+ * is such a method for obtaining an integer value from a
+ * <code>java.lang.Integer</code> object.
+ */
+ public static final String[] unwarpMethods = {
+ "booleanValue", "byteValue", "charValue", "shortValue",
+ "intValue", "longValue", "floatValue", "doubleValue"
+ };
+
+ /**
+ * The descriptors of the unwrapping methods contained
+ * in <code>unwrapMethods</code>.
+ */
+ public static final String[] unwrapDesc = {
+ "()Z", "()B", "()C", "()S", "()I", "()J", "()F", "()D"
+ };
+
+ /**
+ * The data size of primitive types. <code>long</code>
+ * and <code>double</code> are 2; the others are 1.
+ */
+ public static final int[] dataSize = {
+ 1, 1, 1, 1, 1, 2, 1, 2
+ };
+
+ /**
+ * Loads a class file by a given class loader.
+ */
+ public static Class toClass(ClassFile cf, ClassLoader loader)
+ throws CannotCompileException
+ {
+ try {
+ byte[] b = toBytecode(cf);
+ Class cl = Class.forName("java.lang.ClassLoader");
+ java.lang.reflect.Method method = cl.getDeclaredMethod(
+ "defineClass", new Class[] { String.class, byte[].class,
+ Integer.TYPE, Integer.TYPE });
+ method.setAccessible(true);
+ Object[] args = new Object[] { cf.getName(), b, new Integer(0),
+ new Integer(b.length) };
+ Class clazz = (Class)method.invoke(loader, args);
+ method.setAccessible(false);
+ return clazz;
+ }
+ catch (RuntimeException e) {
+ throw e;
+ }
+ catch (java.lang.reflect.InvocationTargetException e) {
+ throw new CannotCompileException(e.getTargetException());
+ }
+ catch (Exception e) {
+ throw new CannotCompileException(e);
+ }
+ }
+
+ private static byte[] toBytecode(ClassFile cf) throws IOException {
+ ByteArrayOutputStream barray = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(barray);
+ try {
+ cf.write(out);
+ }
+ finally {
+ out.close();
+ }
+
+ return barray.toByteArray();
+ }
+
+ /**
+ * Writes a class file.
+ */
+ public static void writeFile(ClassFile cf, String directoryName)
+ throws CannotCompileException {
+ try {
+ writeFile0(cf, directoryName);
+ }
+ catch (IOException e) {
+ throw new CannotCompileException(e);
+ }
+ }
+
+ private static void writeFile0(ClassFile cf, String directoryName)
+ throws CannotCompileException, IOException {
+ String classname = cf.getName();
+ String filename = directoryName + File.separatorChar
+ + classname.replace('.', File.separatorChar) + ".class";
+ int pos = filename.lastIndexOf(File.separatorChar);
+ if (pos > 0) {
+ String dir = filename.substring(0, pos);
+ if (!dir.equals("."))
+ new File(dir).mkdirs();
+ }
+
+ DataOutputStream out = new DataOutputStream(new BufferedOutputStream(
+ new FileOutputStream(filename)));
+ try {
+ cf.write(out);
+ }
+ catch (IOException e) {
+ throw e;
+ }
+ finally {
+ out.close();
+ }
+ }
+}
diff --git a/src/main/javassist/util/proxy/MethodFilter.java b/src/main/javassist/util/proxy/MethodFilter.java
new file mode 100644
index 00000000..67f9e409
--- /dev/null
+++ b/src/main/javassist/util/proxy/MethodFilter.java
@@ -0,0 +1,30 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2005 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.
+ *
+ * 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;
+
+import java.lang.reflect.Method;
+
+/**
+ * Selector of the methods implemented by a handler.
+ *
+ * @see ProxyFactory#setFilter(MethodFilter)
+ */
+public interface MethodFilter {
+ /**
+ * Returns true if the given method is implemented by a handler.
+ */
+ boolean isHandled(Method m);
+}
diff --git a/src/main/javassist/util/proxy/MethodHandler.java b/src/main/javassist/util/proxy/MethodHandler.java
new file mode 100644
index 00000000..7bd28ba0
--- /dev/null
+++ b/src/main/javassist/util/proxy/MethodHandler.java
@@ -0,0 +1,48 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2005 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.
+ *
+ * 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;
+
+import java.lang.reflect.Method;
+
+/**
+ * The interface implemented by the invocation handler of a proxy
+ * instance.
+ *
+ * @see ProxyFactory#setHandler(MethodHandler)
+ */
+public interface MethodHandler {
+ /**
+ * Is called when a method is invoked on a proxy instance associated
+ * with this handler. This method must process that method invocation.
+ *
+ * @param self the proxy instance.
+ * @param thisMethod the overridden method declared in the super
+ * class or interface.
+ * @param proceed the forwarder method for invoking the overridden
+ * method. It is null if the overridden mehtod is
+ * abstract or declared in the interface.
+ * @param args an array of objects containing the values of
+ * the arguments passed in the method invocation
+ * on the proxy instance. If a parameter type is
+ * a primitive type, the type of the array element
+ * is a wrapper class.
+ * @return the resulting value of the method invocation.
+ *
+ * @throws Exception if the method invocation fails.
+ */
+ Object invoke(Object self, Method thisMethod, Method proceed,
+ Object[] args) throws Exception;
+}
diff --git a/src/main/javassist/util/proxy/ProxyFactory.java b/src/main/javassist/util/proxy/ProxyFactory.java
new file mode 100644
index 00000000..356c23bf
--- /dev/null
+++ b/src/main/javassist/util/proxy/ProxyFactory.java
@@ -0,0 +1,699 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2005 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.
+ *
+ * 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;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javassist.CannotCompileException;
+import javassist.bytecode.*;
+
+/**
+ * Factory of dynamic proxy classes.
+ *
+ * <p>This factory generates a class that extends the given super class and implements
+ * the given interfaces. The calls of the methods inherited from the super class are
+ * forwarded and then <code>invoke()</code> is called on the method handler
+ * associated with the generated class. The calls of the methods from the interfaces
+ * are also forwarded to the method handler.
+ *
+ * <p>For example, if the following code is executed,
+ *
+ * <ul><pre>
+ * ProxyFactory f = new ProxyFactory();
+ * f.setSuperclass(Foo.class);
+ * MethodHandler mi = new MethodHandler() {
+ * public Object invoke(Object self, Method m, Method proceed,
+ * Object[] args) throws Exception {
+ * System.out.println("Name: " + m.getName());
+ * proceed.invoke(self, args); // execute the original method.
+ * }
+ * };
+ * f.setHandler(mi);
+ * Class c = f.createClass();
+ * Foo foo = (Foo)c.newInstance();
+ * </pre></ul>
+ *
+ * <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>.
+ *
+ * <ul><pre>
+ * foo.bar();
+ * </pre></ul>
+ *
+ * <p>To change the method handler during runtime,
+ * execute the following code:
+ *
+ * <ul><pre>
+ * MethodHandler mi2 = ... ; // another handler
+ * ((ProxyObject)foo).setHandler(mi2);
+ * </pre></ul>
+ *
+ * <p>Here is an example of method handler. It does not execute
+ * anything except invoking the original method:
+ *
+ * <ul><pre>
+ * class SimpleHandler implements MethodHandler {
+ * public Object invoke(Object self, Method m,
+ * Method proceed, Object[] args) throws Exception {
+ * return proceed.invoke(self, args);
+ * }
+ * }
+ * </pre></ul>
+ *
+ * @see MethodHandler
+ * @since 3.1
+ */
+public class ProxyFactory {
+ private Class superClass;
+ private Class[] interfaces;
+ private MethodFilter methodFilter;
+ private MethodHandler handler;
+ private Class thisClass;
+
+ /**
+ * If the value of this variable is not null, the class file of
+ * the generated proxy class is written under the directory specified
+ * by this variable. For example, if the value is
+ * <code>"."</code>, then the class file is written under the current
+ * directory. This method is for debugging.
+ *
+ * <p>The default value is null.
+ */
+ public String writeDirectory;
+
+ private static final Class OBJECT_TYPE = Object.class;
+
+ private static final String HOLDER = "_methods_";
+ private static final String HOLDER_TYPE = "[Ljava/lang/reflect/Method;";
+ private static final String HANDLER = "handler";
+ private static final String DEFAULT_INTERCEPTOR = "default_interceptor";
+ private static final String HANDLER_TYPE
+ = 'L' + MethodHandler.class.getName().replace('.', '/') + ';';
+ private static final String HANDLER_SETTER = "setHandler";
+ private static final String HANDLER_SETTER_TYPE = "(" + HANDLER_TYPE + ")V";
+
+ /**
+ * Constructs a factory of proxy class.
+ */
+ public ProxyFactory() {
+ superClass = null;
+ interfaces = null;
+ methodFilter = null;
+ handler = new MethodHandler() {
+ public Object invoke(Object self, Method m,
+ Method proceed, Object[] args)
+ throws Exception
+ {
+ return proceed.invoke(self, args);
+ }
+ };
+ thisClass = null;
+ writeDirectory = null;
+ }
+
+ /**
+ * Sets the super class of a proxy class.
+ */
+ public void setSuperclass(Class clazz) {
+ superClass = clazz;
+ }
+
+ /**
+ * Sets the interfaces of a proxy class.
+ */
+ public void setInterfaces(Class[] ifs) {
+ interfaces = ifs;
+ }
+
+ /**
+ * Sets a filter that selects the methods that will be controlled by a handler.
+ */
+ public void setFilter(MethodFilter mf) {
+ methodFilter = mf;
+ }
+
+ /**
+ * Generates a proxy class.
+ */
+ public Class createClass() {
+ if (thisClass == null)
+ try {
+ ClassFile cf = make();
+ ClassLoader cl = getClassLoader();
+ if (writeDirectory != null)
+ FactoryHelper.writeFile(cf, writeDirectory);
+
+ thisClass = FactoryHelper.toClass(cf, cl);
+ setHandler();
+ }
+ catch (CannotCompileException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+
+ return thisClass;
+ }
+
+ protected ClassLoader getClassLoader() {
+ if (superClass != null && !superClass.getName().equals("java.lang.Object"))
+ return superClass.getClassLoader();
+ else if (interfaces != null && interfaces.length > 0)
+ return interfaces[0].getClassLoader();
+ else
+ return this.getClass().getClassLoader();
+ // return Thread.currentThread().getContextClassLoader();
+ }
+
+ /**
+ * Sets the default invocation handler. This invocation handler is shared
+ * among all the instances of a proxy class unless another is explicitly
+ * specified.
+ */
+ public void setHandler(MethodHandler mi) {
+ handler = mi;
+ setHandler();
+ }
+
+ private void setHandler() {
+ if (thisClass != null && handler != null)
+ try {
+ Field f = thisClass.getField(DEFAULT_INTERCEPTOR);
+ f.setAccessible(true);
+ f.set(null, handler);
+ f.setAccessible(false);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static int counter = 0;
+
+ private ClassFile make() throws CannotCompileException {
+ String superName, classname;
+ if (interfaces == null)
+ interfaces = new Class[0];
+
+ if (superClass == null) {
+ superClass = OBJECT_TYPE;
+ superName = superClass.getName();
+ classname = interfaces.length == 0 ? superName
+ : interfaces[0].getName();
+ }
+ else {
+ superName = superClass.getName();
+ classname = superName;
+ }
+
+ if (Modifier.isFinal(superClass.getModifiers()))
+ throw new CannotCompileException(superName + " is final");
+
+ // generate a proxy name.
+ classname = classname + "_$$_javassist_" + counter++;
+ if (classname.startsWith("java."))
+ classname = "org.javassist.tmp." + classname;
+
+ ClassFile cf = new ClassFile(false, classname, superName);
+ cf.setAccessFlags(AccessFlag.PUBLIC);
+ setInterfaces(cf, interfaces);
+ ConstPool pool = cf.getConstPool();
+ FieldInfo finfo = new FieldInfo(pool, DEFAULT_INTERCEPTOR, HANDLER_TYPE);
+ finfo.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC);
+ cf.addField(finfo);
+
+ FieldInfo finfo2 = new FieldInfo(pool, HANDLER, HANDLER_TYPE);
+ finfo2.setAccessFlags(AccessFlag.PRIVATE);
+ cf.addField(finfo2);
+
+ HashMap allMethods = getMethods(superClass, interfaces);
+ int size = allMethods.size();
+ makeConstructors(classname, cf, pool, classname);
+ int s = overrideMethods(cf, pool, classname, allMethods);
+ addMethodsHolder(cf, pool, classname, s);
+ addSetter(classname, cf, pool);
+
+ thisClass = null;
+ return cf;
+ }
+
+ private static void setInterfaces(ClassFile cf, Class[] interfaces) {
+ String setterIntf = ProxyObject.class.getName();
+ String[] list;
+ if (interfaces == null || interfaces.length == 0)
+ list = new String[] { setterIntf };
+ else {
+ list = new String[interfaces.length + 1];
+ for (int i = 0; i < interfaces.length; i++)
+ list[i] = interfaces[i].getName();
+
+ list[interfaces.length] = setterIntf;
+ }
+
+ cf.setInterfaces(list);
+ }
+
+ private static void addMethodsHolder(ClassFile cf, ConstPool cp,
+ String classname, int size)
+ throws CannotCompileException
+ {
+ FieldInfo finfo = new FieldInfo(cp, HOLDER, HOLDER_TYPE);
+ finfo.setAccessFlags(AccessFlag.PRIVATE | AccessFlag.STATIC);
+ cf.addField(finfo);
+ MethodInfo minfo = new MethodInfo(cp, "<clinit>", "()V");
+ Bytecode code = new Bytecode(cp, 0, 0);
+ code.addIconst(size * 2);
+ code.addAnewarray("java.lang.reflect.Method");
+ code.addPutstatic(classname, HOLDER, HOLDER_TYPE);
+ code.addOpcode(Bytecode.RETURN);
+ minfo.setCodeAttribute(code.toCodeAttribute());
+ cf.addMethod(minfo);
+ }
+
+ private static void addSetter(String classname, ClassFile cf, ConstPool cp)
+ throws CannotCompileException
+ {
+ MethodInfo minfo = new MethodInfo(cp, HANDLER_SETTER,
+ HANDLER_SETTER_TYPE);
+ minfo.setAccessFlags(AccessFlag.PUBLIC);
+ Bytecode code = new Bytecode(cp, 2, 2);
+ code.addAload(0);
+ code.addAload(1);
+ code.addPutfield(classname, HANDLER, HANDLER_TYPE);
+ code.addOpcode(Bytecode.RETURN);
+ minfo.setCodeAttribute(code.toCodeAttribute());
+ cf.addMethod(minfo);
+ }
+
+ private int overrideMethods(ClassFile cf, ConstPool cp, String className,
+ HashMap allMethods)
+ throws CannotCompileException
+ {
+ String prefix = makeUniqueName("_d", allMethods);
+ Set entries = allMethods.entrySet();
+ Iterator it = entries.iterator();
+ int index = 0;
+ while (it.hasNext()) {
+ Map.Entry e = (Map.Entry)it.next();
+ String key = (String)e.getKey();
+ Method meth = (Method)e.getValue();
+ int mod = meth.getModifiers();
+ if (!Modifier.isFinal(mod) && !Modifier.isStatic(mod)
+ && isVisible(mod, className, meth))
+ if (methodFilter == null || methodFilter.isHandled(meth))
+ override(className, meth, prefix, index++,
+ keyToDesc(key), cf, cp);
+ }
+
+ return index;
+ }
+
+ private void override(String thisClassname, Method meth, String prefix,
+ int index, String desc, ClassFile cf, ConstPool cp)
+ throws CannotCompileException
+ {
+ Class declClass = meth.getDeclaringClass();
+ String delegatorName = prefix + index + meth.getName();
+ if (Modifier.isAbstract(meth.getModifiers()))
+ delegatorName = null;
+ else {
+ MethodInfo delegator
+ = makeDelegator(meth, desc, cp, declClass, delegatorName);
+ cf.addMethod(delegator);
+ }
+
+ MethodInfo forwarder
+ = makeForwarder(thisClassname, meth, desc, cp, declClass,
+ delegatorName, index);
+ cf.addMethod(forwarder);
+ }
+
+ private void makeConstructors(String thisClassName, ClassFile cf,
+ ConstPool cp, String classname) throws CannotCompileException
+ {
+ Constructor[] cons = superClass.getDeclaredConstructors();
+ for (int i = 0; i < cons.length; i++) {
+ Constructor c = cons[i];
+ int mod = c.getModifiers();
+ if (!Modifier.isFinal(mod) && !Modifier.isPrivate(mod)
+ && isVisible(mod, classname, c)) {
+ MethodInfo m = makeConstructor(thisClassName, c, cp, superClass);
+ cf.addMethod(m);
+ }
+ }
+ }
+
+ private static String makeUniqueName(String name, HashMap hash) {
+ Set keys = hash.keySet();
+ if (makeUniqueName0(name, keys.iterator()))
+ return name;
+
+ for (int i = 100; i < 999; i++) {
+ String s = name + i;
+ if (makeUniqueName0(s, keys.iterator()))
+ return s;
+ }
+
+ throw new RuntimeException("cannot make a unique method name");
+ }
+
+ private static boolean makeUniqueName0(String name, Iterator it) {
+ while (it.hasNext()) {
+ String key = (String)it.next();
+ if (key.startsWith(name))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if the method is visible from the class.
+ *
+ * @param mod the modifiers of the method.
+ */
+ private static boolean isVisible(int mod, String from, Member meth) {
+ if ((mod & Modifier.PRIVATE) != 0)
+ return false;
+ else if ((mod & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0)
+ return true;
+ else {
+ String p = getPackageName(from);
+ String q = getPackageName(meth.getDeclaringClass().getName());
+ if (p == null)
+ return q == null;
+ else
+ return p.equals(q);
+ }
+ }
+
+ private static String getPackageName(String name) {
+ int i = name.lastIndexOf('.');
+ if (i < 0)
+ return null;
+ else
+ return name.substring(0, i);
+ }
+
+ private static HashMap getMethods(Class superClass, Class[] interfaceTypes) {
+ HashMap hash = new HashMap();
+ for (int i = 0; i < interfaceTypes.length; i++)
+ getMethods(hash, interfaceTypes[i]);
+
+ getMethods(hash, superClass);
+ return hash;
+ }
+
+ private static void getMethods(HashMap hash, Class clazz) {
+ Class[] ifs = clazz.getInterfaces();
+ for (int i = 0; i < ifs.length; i++)
+ getMethods(hash, ifs[i]);
+
+ Class parent = clazz.getSuperclass();
+ if (parent != null)
+ getMethods(hash, parent);
+
+ Method[] methods = clazz.getDeclaredMethods();
+ for (int i = 0; i < methods.length; i++)
+ if (!Modifier.isPrivate(methods[i].getModifiers())) {
+ Method m = methods[i];
+ String key = m.getName() + ':' + RuntimeSupport.makeDescriptor(m);
+ hash.put(key, methods[i]);
+ }
+ }
+
+ private static String keyToDesc(String key) {
+ return key.substring(key.indexOf(':') + 1);
+ }
+
+ private static MethodInfo makeConstructor(String thisClassName, Constructor cons,
+ ConstPool cp, Class superClass) {
+ String desc = RuntimeSupport.makeDescriptor(cons.getParameterTypes(),
+ Void.TYPE);
+ MethodInfo minfo = new MethodInfo(cp, "<init>", desc);
+ minfo.setAccessFlags(Modifier.PUBLIC); // cons.getModifiers() & ~Modifier.NATIVE
+ setThrows(minfo, cp, cons.getExceptionTypes());
+ Bytecode code = new Bytecode(cp, 0, 0);
+ code.addAload(0);
+ code.addGetstatic(thisClassName, DEFAULT_INTERCEPTOR, HANDLER_TYPE);
+ code.addPutfield(thisClassName, HANDLER, HANDLER_TYPE);
+ code.addAload(0);
+ int s = addLoadParameters(code, cons.getParameterTypes(), 1);
+ code.addInvokespecial(superClass.getName(), "<init>", desc);
+ code.addOpcode(Opcode.RETURN);
+ code.setMaxLocals(++s);
+ minfo.setCodeAttribute(code.toCodeAttribute());
+ return minfo;
+ }
+
+ private static MethodInfo makeDelegator(Method meth, String desc,
+ ConstPool cp, Class declClass, String delegatorName) {
+ MethodInfo delegator = new MethodInfo(cp, delegatorName, desc);
+ delegator.setAccessFlags(Modifier.FINAL | Modifier.PUBLIC
+ | (meth.getModifiers() & ~(Modifier.PRIVATE
+ | Modifier.PROTECTED
+ | Modifier.ABSTRACT
+ | Modifier.NATIVE
+ | Modifier.SYNCHRONIZED)));
+ setThrows(delegator, cp, meth);
+ Bytecode code = new Bytecode(cp, 0, 0);
+ code.addAload(0);
+ int s = addLoadParameters(code, meth.getParameterTypes(), 1);
+ code.addInvokespecial(declClass.getName(), meth.getName(), desc);
+ addReturn(code, meth.getReturnType());
+ code.setMaxLocals(++s);
+ delegator.setCodeAttribute(code.toCodeAttribute());
+ return delegator;
+ }
+
+ /**
+ * @param delegatorName null if the original method is abstract.
+ */
+ private static MethodInfo makeForwarder(String thisClassName,
+ Method meth, String desc, ConstPool cp,
+ Class declClass, String delegatorName, int index) {
+ MethodInfo forwarder = new MethodInfo(cp, meth.getName(), desc);
+ forwarder.setAccessFlags(Modifier.FINAL
+ | (meth.getModifiers() & ~(Modifier.ABSTRACT
+ | Modifier.NATIVE
+ | Modifier.SYNCHRONIZED)));
+ setThrows(forwarder, cp, meth);
+ int args = Descriptor.paramSize(desc);
+ Bytecode code = new Bytecode(cp, 0, args + 2);
+ /*
+ * if (methods[index * 2] == null) {
+ * methods[index * 2]
+ * = RuntimeSupport.findMethod(this, <overridden name>, <desc>);
+ * methods[index * 2 + 1]
+ * = RuntimeSupport.findMethod(this, <delegator name>, <desc>);
+ * or = null // the original method is abstract.
+ * }
+ * return ($r)handler.invoke(this, methods[index * 2],
+ * methods[index * 2 + 1], $args);
+ */
+ int origIndex = index * 2;
+ int delIndex = index * 2 + 1;
+ int arrayVar = args + 1;
+ code.addGetstatic(thisClassName, HOLDER, HOLDER_TYPE);
+ code.addAstore(arrayVar);
+ code.addAload(arrayVar);
+ code.addIconst(origIndex);
+ code.addOpcode(Opcode.AALOAD);
+ code.addOpcode(Opcode.IFNONNULL);
+ int pc = code.currentPc();
+ code.addIndex(0);
+
+ callFindMethod(code, "findSuperMethod", arrayVar, origIndex, meth.getName(), desc);
+ callFindMethod(code, "findMethod", arrayVar, delIndex, delegatorName, desc);
+
+ code.write16bit(pc, code.currentPc() - pc + 1);
+ code.addAload(0);
+ code.addGetfield(thisClassName, HANDLER, HANDLER_TYPE);
+ code.addAload(0);
+
+ code.addAload(arrayVar);
+ code.addIconst(origIndex);
+ code.addOpcode(Opcode.AALOAD);
+
+ code.addAload(arrayVar);
+ code.addIconst(delIndex);
+ code.addOpcode(Opcode.AALOAD);
+
+ makeParameterList(code, meth.getParameterTypes());
+ code.addInvokeinterface(MethodHandler.class.getName(), "invoke",
+ "(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;",
+ 5);
+ Class retType = meth.getReturnType();
+ addUnwrapper(code, retType);
+ addReturn(code, retType);
+
+ forwarder.setCodeAttribute(code.toCodeAttribute());
+ return forwarder;
+ }
+
+ private static void setThrows(MethodInfo minfo, ConstPool cp, Method orig) {
+ Class[] exceptions = orig.getExceptionTypes();
+ setThrows(minfo, cp, exceptions);
+ }
+
+ private static void setThrows(MethodInfo minfo, ConstPool cp,
+ Class[] exceptions) {
+ if (exceptions.length == 0)
+ return;
+
+ String[] list = new String[exceptions.length];
+ for (int i = 0; i < exceptions.length; i++)
+ list[i] = exceptions[i].getName();
+
+ ExceptionsAttribute ea = new ExceptionsAttribute(cp);
+ ea.setExceptions(list);
+ minfo.setExceptionsAttribute(ea);
+ }
+
+ private static int addLoadParameters(Bytecode code, Class[] params,
+ int offset) {
+ int stacksize = 0;
+ int n = params.length;
+ for (int i = 0; i < n; ++i)
+ stacksize += addLoad(code, stacksize + offset, params[i]);
+
+ return stacksize;
+ }
+
+ private static int addLoad(Bytecode code, int n, Class type) {
+ if (type.isPrimitive()) {
+ if (type == Long.TYPE) {
+ code.addLload(n);
+ return 2;
+ }
+ else if (type == Float.TYPE)
+ code.addFload(n);
+ else if (type == Double.TYPE) {
+ code.addDload(n);
+ return 2;
+ }
+ else
+ code.addIload(n);
+ }
+ else
+ code.addAload(n);
+
+ return 1;
+ }
+
+ private static int addReturn(Bytecode code, Class type) {
+ if (type.isPrimitive()) {
+ if (type == Long.TYPE) {
+ code.addOpcode(Opcode.LRETURN);
+ return 2;
+ }
+ else if (type == Float.TYPE)
+ code.addOpcode(Opcode.FRETURN);
+ else if (type == Double.TYPE) {
+ code.addOpcode(Opcode.DRETURN);
+ return 2;
+ }
+ else if (type == Void.TYPE) {
+ code.addOpcode(Opcode.RETURN);
+ return 0;
+ }
+ else
+ code.addOpcode(Opcode.IRETURN);
+ }
+ else
+ code.addOpcode(Opcode.ARETURN);
+
+ return 1;
+ }
+
+ private static void makeParameterList(Bytecode code, Class[] params) {
+ int regno = 1;
+ int n = params.length;
+ code.addIconst(n);
+ code.addAnewarray("java/lang/Object");
+ for (int i = 0; i < n; i++) {
+ code.addOpcode(Opcode.DUP);
+ code.addIconst(i);
+ Class type = params[i];
+ if (type.isPrimitive())
+ regno = makeWrapper(code, type, regno);
+ else {
+ code.addAload(regno);
+ regno++;
+ }
+
+ code.addOpcode(Opcode.AASTORE);
+ }
+ }
+
+ private static int makeWrapper(Bytecode code, Class type, int regno) {
+ int index = FactoryHelper.typeIndex(type);
+ String wrapper = FactoryHelper.wrapperTypes[index];
+ code.addNew(wrapper);
+ code.addOpcode(Opcode.DUP);
+ addLoad(code, regno, type);
+ code.addInvokespecial(wrapper, "<init>",
+ FactoryHelper.wrapperDesc[index]);
+ return regno + FactoryHelper.dataSize[index];
+ }
+
+ /**
+ * @param methodName might be null.
+ */
+ private static void callFindMethod(Bytecode code, String findMethod,
+ int arrayVar, int index, String methodName, String desc) {
+ String findClass = RuntimeSupport.class.getName();
+ String findDesc
+ = "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/reflect/Method;";
+
+ code.addAload(arrayVar);
+ code.addIconst(index);
+ if (methodName == null)
+ code.addOpcode(Opcode.ACONST_NULL);
+ else {
+ code.addAload(0);
+ code.addLdc(methodName);
+ code.addLdc(desc);
+ code.addInvokestatic(findClass, findMethod, findDesc);
+ }
+
+ code.addOpcode(Opcode.AASTORE);
+ }
+
+ private static void addUnwrapper(Bytecode code, Class type) {
+ if (type.isPrimitive()) {
+ if (type == Void.TYPE)
+ code.addOpcode(Opcode.POP);
+ else {
+ int index = FactoryHelper.typeIndex(type);
+ String wrapper = FactoryHelper.wrapperTypes[index];
+ code.addCheckcast(wrapper);
+ code.addInvokevirtual(wrapper,
+ FactoryHelper.unwarpMethods[index],
+ FactoryHelper.unwrapDesc[index]);
+ }
+ }
+ else
+ code.addCheckcast(type.getName());
+ }
+}
diff --git a/src/main/javassist/util/proxy/ProxyObject.java b/src/main/javassist/util/proxy/ProxyObject.java
new file mode 100644
index 00000000..4cba5c7b
--- /dev/null
+++ b/src/main/javassist/util/proxy/ProxyObject.java
@@ -0,0 +1,29 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2005 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.
+ *
+ * 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.
+ *
+ * @see ProxyFactory
+ */
+public interface ProxyObject {
+ /**
+ * Sets a handler. It can be used for changing handlers
+ * during runtime.
+ */
+ void setHandler(MethodHandler mi);
+}
diff --git a/src/main/javassist/util/proxy/RuntimeSupport.java b/src/main/javassist/util/proxy/RuntimeSupport.java
new file mode 100644
index 00000000..837ed6ca
--- /dev/null
+++ b/src/main/javassist/util/proxy/RuntimeSupport.java
@@ -0,0 +1,157 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2005 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.
+ *
+ * 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;
+
+import java.lang.reflect.Method;
+
+/**
+ * Runtime support routines that the classes generated by ProxyFactory use.
+ *
+ * @see ProxyFactory
+ */
+public class RuntimeSupport {
+ /**
+ * Finds a method with the given name and descriptor.
+ * It searches only the class of self.
+ *
+ * @throws RuntimeException if the method is not found.
+ */
+ public static Method findMethod(Object self, String name, String desc) {
+ Method m = findMethod2(self.getClass(), name, desc);
+ if (m == null)
+ error(self, name, desc);
+
+ return m;
+ }
+
+ /**
+ * Finds a method that has the given name and descriptor and is declared
+ * in the super class.
+ *
+ * @throws RuntimeException if the method is not found.
+ */
+ public static Method findSuperMethod(Object self, String name, String desc) {
+ Class clazz = self.getClass();
+ Method m = findSuperMethod2(clazz.getSuperclass(), name, desc);
+ if (m == null)
+ m = searchInterfaces(clazz, name, desc);
+
+ if (m == null)
+ error(self, name, desc);
+
+ return m;
+ }
+
+ private static void error(Object self, String name, String desc) {
+ throw new RuntimeException("not found " + name + ":" + desc
+ + " in " + self.getClass().getName());
+ }
+
+ private static Method findSuperMethod2(Class clazz, String name, String desc) {
+ Method m = findMethod2(clazz, name, desc);
+ if (m != null)
+ return m;
+
+ Class superClass = clazz.getSuperclass();
+ if (superClass != null) {
+ m = findSuperMethod2(superClass, name, desc);
+ if (m != null)
+ return m;
+ }
+
+ return searchInterfaces(clazz, name, desc);
+ }
+
+ private static Method searchInterfaces(Class clazz, String name, String desc) {
+ Method m = null;
+ Class[] interfaces = clazz.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ m = findSuperMethod2(interfaces[i], name, desc);
+ if (m != null)
+ return m;
+ }
+
+ return m;
+ }
+
+ private static Method findMethod2(Class clazz, String name, String desc) {
+ Method[] methods = clazz.getDeclaredMethods();
+ int n = methods.length;
+ for (int i = 0; i < n; i++)
+ if (methods[i].getName().equals(name)
+ && makeDescriptor(methods[i]).equals(desc))
+ return methods[i];
+
+ return null;
+ }
+
+ /**
+ * Makes a descriptor for a given method.
+ */
+ public static String makeDescriptor(Method m) {
+ Class[] params = m.getParameterTypes();
+ return makeDescriptor(params, m.getReturnType());
+ }
+
+ /**
+ * Makes a descriptor for a given method.
+ *
+ * @param params parameter types.
+ * @param retType return type.
+ */
+ public static String makeDescriptor(Class[] params, Class retType) {
+ StringBuffer sbuf = new StringBuffer();
+ sbuf.append('(');
+ for (int i = 0; i < params.length; i++)
+ makeDesc(sbuf, params[i]);
+
+ sbuf.append(')');
+ makeDesc(sbuf, retType);
+ return sbuf.toString();
+ }
+
+ private static void makeDesc(StringBuffer sbuf, Class type) {
+ if (type.isArray()) {
+ sbuf.append('[');
+ makeDesc(sbuf, type.getComponentType());
+ }
+ else if (type.isPrimitive()) {
+ if (type == Void.TYPE)
+ sbuf.append('V');
+ else if (type == Integer.TYPE)
+ sbuf.append('I');
+ else if (type == Byte.TYPE)
+ sbuf.append('B');
+ else if (type == Long.TYPE)
+ sbuf.append('J');
+ else if (type == Double.TYPE)
+ sbuf.append('D');
+ else if (type == Float.TYPE)
+ sbuf.append('F');
+ else if (type == Character.TYPE)
+ sbuf.append('C');
+ else if (type == Short.TYPE)
+ sbuf.append('S');
+ else if (type == Boolean.TYPE)
+ sbuf.append('Z');
+ else
+ throw new RuntimeException("bad type: " + type.getName());
+ }
+ else
+ sbuf.append('L').append(type.getName().replace('.', '/'))
+ .append(';');
+ }
+}
diff --git a/src/main/javassist/util/proxy/package.html b/src/main/javassist/util/proxy/package.html
new file mode 100644
index 00000000..6c1354fa
--- /dev/null
+++ b/src/main/javassist/util/proxy/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Dynamic proxy (similar to <code>Enhancer</code> of <a href="http://cglib.sourceforge.net/">cglib</a>).
+</body>
+</html>