Browse Source

restructred sub packages


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@233 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 18 years ago
parent
commit
52a455616e
55 changed files with 1303 additions and 140 deletions
  1. 14
    10
      Readme.html
  2. 9
    6
      build.xml
  3. 1
    1
      sample/duplicate/DuplicatedObject.java
  4. 4
    4
      sample/duplicate/Main.java
  5. 1
    1
      sample/evolve/DemoServer.java
  6. 3
    3
      sample/evolve/Evolution.java
  7. 1
    1
      sample/evolve/VersionManager.java
  8. 1
    1
      sample/hotswap/Test.java
  9. 3
    3
      sample/reflect/Main.java
  10. 2
    2
      sample/reflect/Person.java
  11. 1
    1
      sample/reflect/VerboseMetaobj.java
  12. 3
    3
      sample/rmi/CountApplet.java
  13. 1
    1
      sample/rmi/Counter.java
  14. 1
    1
      sample/rmi/start.html
  15. 4
    4
      sample/rmi/webdemo.html
  16. 1
    1
      src/main/javassist/CtClass.java
  17. 1
    1
      src/main/javassist/CtMethod.java
  18. 1
    1
      src/main/javassist/bytecode/Bytecode.java
  19. 0
    1
      src/main/javassist/bytecode/Descriptor.java
  20. 1
    1
      src/main/javassist/bytecode/annotation/package.html
  21. 1
    1
      src/main/javassist/expr/MethodCall.java
  22. 1
    1
      src/main/javassist/tools/package.html
  23. 1
    1
      src/main/javassist/tools/reflect/CannotCreateException.java
  24. 4
    4
      src/main/javassist/tools/reflect/CannotInvokeException.java
  25. 2
    2
      src/main/javassist/tools/reflect/CannotReflectException.java
  26. 3
    3
      src/main/javassist/tools/reflect/ClassMetaobject.java
  27. 8
    8
      src/main/javassist/tools/reflect/Compiler.java
  28. 17
    17
      src/main/javassist/tools/reflect/Loader.java
  29. 1
    1
      src/main/javassist/tools/reflect/Metalevel.java
  30. 4
    4
      src/main/javassist/tools/reflect/Metaobject.java
  31. 18
    18
      src/main/javassist/tools/reflect/Reflection.java
  32. 1
    1
      src/main/javassist/tools/reflect/Sample.java
  33. 0
    0
      src/main/javassist/tools/reflect/package.html
  34. 5
    4
      src/main/javassist/tools/rmi/AppletServer.java
  35. 8
    7
      src/main/javassist/tools/rmi/ObjectImporter.java
  36. 1
    1
      src/main/javassist/tools/rmi/ObjectNotFoundException.java
  37. 2
    2
      src/main/javassist/tools/rmi/Proxy.java
  38. 1
    1
      src/main/javassist/tools/rmi/RemoteException.java
  39. 1
    1
      src/main/javassist/tools/rmi/RemoteRef.java
  40. 1
    1
      src/main/javassist/tools/rmi/Sample.java
  41. 6
    6
      src/main/javassist/tools/rmi/StubGenerator.java
  42. 0
    0
      src/main/javassist/tools/rmi/package.html
  43. 1
    1
      src/main/javassist/tools/web/BadHttpRequest.java
  44. 4
    4
      src/main/javassist/tools/web/Viewer.java
  45. 2
    2
      src/main/javassist/tools/web/Webserver.java
  46. 0
    0
      src/main/javassist/tools/web/package.html
  47. 2
    2
      src/main/javassist/util/HotSwapper.java
  48. 5
    0
      src/main/javassist/util/package.html
  49. 182
    0
      src/main/javassist/util/proxy/FactoryHelper.java
  50. 30
    0
      src/main/javassist/util/proxy/MethodFilter.java
  51. 48
    0
      src/main/javassist/util/proxy/MethodHandler.java
  52. 699
    0
      src/main/javassist/util/proxy/ProxyFactory.java
  53. 29
    0
      src/main/javassist/util/proxy/ProxyObject.java
  54. 157
    0
      src/main/javassist/util/proxy/RuntimeSupport.java
  55. 5
    0
      src/main/javassist/util/proxy/package.html

+ 14
- 10
Readme.html View File

@@ -137,7 +137,7 @@ set CLASSPATH=.;javassist.jar

<ul><pre>
% javac sample/reflect/*.java
% java javassist.reflect.Loader sample.reflect.Main Joe
% java javassist.tools.reflect.Loader sample.reflect.Main Joe
</pre></ul>

<p>Compare this result with that of the regular execution without reflection:
@@ -151,7 +151,7 @@ set CLASSPATH=.;javassist.jar
To do this, type the commands:

<ul><pre>
% java javassist.reflect.Compiler sample.reflect.Person -m sample.reflect.VerboseMetaobj
% java javassist.tools.reflect.Compiler sample.reflect.Person -m sample.reflect.VerboseMetaobj
</pre></ul>

<p> Then,
@@ -292,14 +292,18 @@ see javassist.Dump.
<li>The return type of CtClass.stopPruning() was changed from void
to boolean.
<li>toMethod() in javassist.CtConstructor has been implemented.
<li>javassist.preproc package was elminated and the source was
moved to the sample directory.
</ul>

<p>- version 3.1

<ul>
<li>javassist.tool package was renamed to javassist.tools.
<li>It includes new javassist.util.proxy package
similar to Enhancer of CGLIB.

<p>
<li>The subpackages of Javassist were restructured.
<ul>
<li>javassist.tool package was renamed to javassist.tools.
<li>HotSwapper was moved to javassist.util.
<li>Several subpackages were moved to javassist.tools.
<li>javassist.preproc package was elminated and the source was
moved to the sample directory.
</ul>
</ul>

<p>- version 3.1 RC2 in September 7, 2005

+ 9
- 6
build.xml View File

@@ -109,18 +109,18 @@ to ${build.classes.dir}.</echo>
excludepackagenames="javassist.compiler.*,javassist.convert.*"
sourcepath="src/main"
defaultexcludes="yes"
locale="en_US"
charset="iso-8859-1"
destdir="html"
author="true"
version="true"
use="true"
Locale="en_US"
charset="iso-8859-1"
Public="true"
public="true"
nohelp="true"
windowtitle="Javassist API">
<doctitle><![CDATA[<h1>Javassist</h1>]]></doctitle>
<bottom><![CDATA[<i>Javassist, a Java-bytecode translator toolkit.
Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.</i>]]></bottom>
Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.</i>]]></bottom>
</javadoc>
</target>

@@ -151,7 +151,8 @@ Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.</i>]]></bottom>

<target name = "sample-all"
depends="sample-test,sample-reflect,sample-duplicate,sample-vector">
<echo>** please run sample-rmi and sample-evolve separately **</echo>
<echo>** please run sample-rmi, sample-evolve, and</echo>
<echo> sample-hotswap (or -hotswap5) separately **</echo>
</target>

<target name = "sample-test" depends="sample" >
@@ -161,7 +162,7 @@ Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.</i>]]></bottom>
</target>

<target name = "sample-reflect" depends="sample" >
<java fork="true" dir="${run.dir}" classname="javassist.reflect.Loader">
<java fork="true" dir="${run.dir}" classname="javassist.tools.reflect.Loader">
<classpath refid="classpath"/>
<arg line="sample.reflect.Main Joe" />
</java>
@@ -212,6 +213,7 @@ Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.</i>]]></bottom>
<!-- for JDK 1.4 -->
<target name = "sample-hotswap" depends="sample">
<echo>** JAVA_HOME/lib/tools.jar must be included in CLASS_PATH</echo>
<echo>** for JDK 1.4</echo>
<java fork="true" dir="${run.dir}" classname="Test">
<jvmarg line="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000" />
<classpath refid="classpath"/>
@@ -221,6 +223,7 @@ Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.</i>]]></bottom>
<!-- for Java 5 -->
<target name = "sample-hotswap5" depends="sample">
<echo>** JAVA_HOME/lib/tools.jar must be included in CLASS_PATH</echo>
<echo>** for JDK 1.5 or later</echo>
<java fork="true" dir="${run.dir}" classname="Test">
<jvmarg line="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000" />
<classpath refid="classpath"/>

+ 1
- 1
sample/duplicate/DuplicatedObject.java View File

@@ -1,6 +1,6 @@
package sample.duplicate;
import javassist.reflect.*;
import javassist.tools.reflect.*;
public class DuplicatedObject extends Metaobject {
private DuplicatedObject backup;

+ 4
- 4
sample/duplicate/Main.java View File

@@ -3,7 +3,7 @@ package sample.duplicate;
/*
Runtime metaobject (JDK 1.2 or later only).
With the javassist.reflect package, the users can attach a metaobject
With the javassist.tools.reflect package, the users can attach a metaobject
to an object. The metaobject can control the behavior of the object.
For example, you can implement fault tolerancy with this ability. One
of the implementation techniques of fault tolernacy is to make a copy
@@ -30,15 +30,15 @@ package sample.duplicate;
% java sample.duplicate.Main
You would see two balls in a window. This is because
sample.duplicate.Viewer is loaded by javassist.reflect.Loader so that
sample.duplicate.Viewer is loaded by javassist.tools.reflect.Loader so that
a metaobject would be attached.
*/
public class Main {
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("sample.duplicate.Ball",
"sample.duplicate.DuplicatedObject",
"javassist.reflect.ClassMetaobject");
"javassist.tools.reflect.ClassMetaobject");
cl.run("sample.duplicate.Viewer", args);
}
}

+ 1
- 1
sample/evolve/DemoServer.java View File

@@ -1,6 +1,6 @@
package sample.evolve;
import javassist.web.*;
import javassist.tools.web.*;
import java.io.*;
/**

+ 3
- 3
sample/evolve/Evolution.java View File

@@ -60,9 +60,9 @@ public class Evolution implements Translator {
private void onLoadUpdatable(String classname) throws NotFoundException,
CannotCompileException {
// if the class is a concrete class,
// classname is <updatableClassName>$<version>.
// classname is <updatableClassName>$$<version>.
int i = classname.lastIndexOf('$');
int i = classname.lastIndexOf("$$");
if (i <= 0)
return;
@@ -72,7 +72,7 @@ public class Evolution implements Translator {
int version;
try {
version = Integer.parseInt(classname.substring(i + 1));
version = Integer.parseInt(classname.substring(i + 2));
}
catch (NumberFormatException e) {
throw new NotFoundException(classname, e);

+ 1
- 1
sample/evolve/VersionManager.java View File

@@ -41,7 +41,7 @@ public class VersionManager {
else
version = ((Integer)found).intValue() + 1;
Class c = Class.forName(qualifiedClassname + '$' + version);
Class c = Class.forName(qualifiedClassname + "$$" + version);
versionNo.put(qualifiedClassname, new Integer(version));
return c;
}

+ 1
- 1
sample/hotswap/Test.java View File

@@ -1,5 +1,5 @@
import java.io.*;
import javassist.tools.HotSwapper;
import javassist.util.HotSwapper;

public class Test {
public static void main(String[] args) throws Exception {

+ 3
- 3
sample/reflect/Main.java View File

@@ -1,6 +1,6 @@
package sample.reflect;
import javassist.reflect.Loader;
import javassist.tools.reflect.Loader;
/*
The "verbose metaobject" example (JDK 1.2 or later only).
@@ -14,7 +14,7 @@ import javassist.reflect.Loader;
To run,
% java javassist.reflect.Loader sample.reflect.Main Joe
% java javassist.tools.reflect.Loader sample.reflect.Main Joe
Compare this result with that of the regular execution without reflection:
@@ -25,7 +25,7 @@ public class Main {
Loader cl = (Loader)Main.class.getClassLoader();
cl.makeReflective("sample.reflect.Person",
"sample.reflect.VerboseMetaobj",
"javassist.reflect.ClassMetaobject");
"javassist.tools.reflect.ClassMetaobject");
cl.run("sample.reflect.Person", args);
}

+ 2
- 2
sample/reflect/Person.java View File

@@ -4,8 +4,8 @@
package sample.reflect;
import javassist.reflect.Metalevel;
import javassist.reflect.Metaobject;
import javassist.tools.reflect.Metalevel;
import javassist.tools.reflect.Metaobject;
public class Person {
public String name;

+ 1
- 1
sample/reflect/VerboseMetaobj.java View File

@@ -1,6 +1,6 @@
package sample.reflect;
import javassist.reflect.*;
import javassist.tools.reflect.*;
public class VerboseMetaobj extends Metaobject {
public VerboseMetaobj(Object self, Object[] args) {

+ 3
- 3
sample/rmi/CountApplet.java View File

@@ -3,9 +3,9 @@ package sample.rmi;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javassist.rmi.ObjectImporter;
import javassist.rmi.ObjectNotFoundException;
import javassist.web.Viewer;
import javassist.tools.rmi.ObjectImporter;
import javassist.tools.rmi.ObjectNotFoundException;
import javassist.tools.web.Viewer;
public class CountApplet extends Applet implements ActionListener {
private Font font;

+ 1
- 1
sample/rmi/Counter.java View File

@@ -1,6 +1,6 @@
package sample.rmi;
import javassist.rmi.AppletServer;
import javassist.tools.rmi.AppletServer;
import java.io.IOException;
import javassist.CannotCompileException;
import javassist.NotFoundException;

+ 1
- 1
sample/rmi/start.html View File

@@ -12,4 +12,4 @@ Start!
<p>If you don't want to use a web browser, do as follows:
<ul><pre>% java javassist.web.Viewer localhost 5001 sample.rmi.CountApplet</pre></ul>
<ul><pre>% java javassist.tools.web.Viewer localhost 5001 sample.rmi.CountApplet</pre></ul>

+ 4
- 4
sample/rmi/webdemo.html View File

@@ -6,7 +6,7 @@
local object. The applet can communicate through a socket with the
host that executes the web server distributing that applet. However,
the applet cannot directly call a method on an object if the object is
on a remote host. The <code>javassist.rmi</code> package provides
on a remote host. The <code>javassist.tools.rmi</code> package provides
a mechanism for the applet to transparently access the remote object.
The rules that the applet must be subject to are simpler than the
standard Java RMI.
@@ -36,7 +36,7 @@ Look at the lines shown with red:
<p><b>Figure 1: Applet</b>
<pre>
<font color="red">import javassist.rmi.ObjectImporter;</font>
<font color="red">import javassist.tools.rmi.ObjectImporter;</font>
public class CountApplet extends Applet implements ActionListener {
private Font font;
@@ -106,7 +106,7 @@ public class Counter {
}
</pre>
<p>Note that the <code>javassist.rmi</code> package does not require
<p>Note that the <code>javassist.tools.rmi</code> package does not require
the <code>Counter</code> class to be an interface unlike the Java RMI,
with which <code>Counter</code> must be an interface and it must be
implemented by another class.
@@ -167,7 +167,7 @@ following features:
<p> With the Java RMI or Voyager, the applet programmer must define
an interface for every remote object class and access the remote object
through that interface.
On the other hand, the <code>javassist.rmi</code> package does not
On the other hand, the <code>javassist.tools.rmi</code> package does not
require the programmer to follow that programming convention.
It is suitable for writing simple distributed programs like applets.

+ 1
- 1
src/main/javassist/CtClass.java View File

@@ -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)

+ 1
- 1
src/main/javassist/CtMethod.java View File

@@ -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

+ 1
- 1
src/main/javassist/bytecode/Bytecode.java View File

@@ -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) {

+ 0
- 1
src/main/javassist/bytecode/Descriptor.java View File

@@ -717,7 +717,6 @@ public class Descriptor {

/**
* Returns the first character of the current element.
* @return
*/
public char currentChar() { return desc.charAt(curPos); }


+ 1
- 1
src/main/javassist/bytecode/annotation/package.html View File

@@ -1,6 +1,6 @@
<html>
<body>
Annotations API.
Bytecode-level Annotations API.

<p>This package provides low-level API for editing annotations attributes.


+ 1
- 1
src/main/javassist/expr/MethodCall.java View File

@@ -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
*/

+ 1
- 1
src/main/javassist/tools/package.html View File

@@ -1,6 +1,6 @@
<html>
<body>
Utility classes.
Covenient tools.

</body>
</html>

src/main/javassist/reflect/CannotCreateException.java → src/main/javassist/tools/reflect/CannotCreateException.java View File

@@ -13,7 +13,7 @@
* License.
*/

package javassist.reflect;
package javassist.tools.reflect;

/**
* Signals that <code>ClassMetaobject.newInstance()</code> fails.

src/main/javassist/reflect/CannotInvokeException.java → src/main/javassist/tools/reflect/CannotInvokeException.java View File

@@ -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 {


src/main/javassist/reflect/CannotReflectException.java → src/main/javassist/tools/reflect/CannotReflectException.java View File

@@ -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 {

src/main/javassist/reflect/ClassMetaobject.java → src/main/javassist/tools/reflect/ClassMetaobject.java View File

@@ -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 {
/**

src/main/javassist/reflect/Compiler.java → src/main/javassist/tools/reflect/Compiler.java View File

@@ -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>])+");
}
}

src/main/javassist/reflect/Loader.java → src/main/javassist/tools/reflect/Loader.java View File

@@ -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)

src/main/javassist/reflect/Metalevel.java → src/main/javassist/tools/reflect/Metalevel.java View File

@@ -13,7 +13,7 @@
* License.
*/

package javassist.reflect;
package javassist.tools.reflect;

/**
* An interface to access a metaobject and a class metaobject.

src/main/javassist/reflect/Metaobject.java → src/main/javassist/tools/reflect/Metaobject.java View File

@@ -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;

src/main/javassist/reflect/Reflection.java → src/main/javassist/tools/reflect/Reflection.java View File

@@ -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,

src/main/javassist/reflect/Sample.java → src/main/javassist/tools/reflect/Sample.java View File

@@ -13,7 +13,7 @@
* License.
*/

package javassist.reflect;
package javassist.tools.reflect;

/**
* A template used for defining a reflective class.

src/main/javassist/reflect/package.html → src/main/javassist/tools/reflect/package.html View File


src/main/javassist/rmi/AppletServer.java → src/main/javassist/tools/rmi/AppletServer.java View File

@@ -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

src/main/javassist/rmi/ObjectImporter.java → src/main/javassist/tools/rmi/ObjectImporter.java View File

@@ -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;

src/main/javassist/rmi/ObjectNotFoundException.java → src/main/javassist/tools/rmi/ObjectNotFoundException.java View File

@@ -13,7 +13,7 @@
* License.
*/

package javassist.rmi;
package javassist.tools.rmi;

public class ObjectNotFoundException extends Exception {
public ObjectNotFoundException(String name) {

src/main/javassist/rmi/Proxy.java → src/main/javassist/tools/rmi/Proxy.java View File

@@ -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();

src/main/javassist/rmi/RemoteException.java → src/main/javassist/tools/rmi/RemoteException.java View File

@@ -13,7 +13,7 @@
* License.
*/

package javassist.rmi;
package javassist.tools.rmi;

/**
* <code>RemoteException</code> represents any exception thrown

src/main/javassist/rmi/RemoteRef.java → src/main/javassist/tools/rmi/RemoteRef.java View File

@@ -13,7 +13,7 @@
* License.
*/

package javassist.rmi;
package javassist.tools.rmi;

/**
* Remote reference. This class is internally used for sending a remote

src/main/javassist/rmi/Sample.java → src/main/javassist/tools/rmi/Sample.java View File

@@ -13,7 +13,7 @@
* License.
*/

package javassist.rmi;
package javassist.tools.rmi;

/**
* A template used for defining a proxy class.

src/main/javassist/rmi/StubGenerator.java → src/main/javassist/tools/rmi/StubGenerator.java View File

@@ -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));

src/main/javassist/rmi/package.html → src/main/javassist/tools/rmi/package.html View File


src/main/javassist/web/BadHttpRequest.java → src/main/javassist/tools/web/BadHttpRequest.java View File

@@ -13,7 +13,7 @@
* License.
*/

package javassist.web;
package javassist.tools.web;

/**
* Thrown when receiving an invalid HTTP request.

src/main/javassist/web/Viewer.java → src/main/javassist/tools/web/Viewer.java View File

@@ -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)

src/main/javassist/web/Webserver.java → src/main/javassist/tools/web/Webserver.java View File

@@ -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>");
}

/**

src/main/javassist/web/package.html → src/main/javassist/tools/web/package.html View File


src/main/javassist/tools/HotSwapper.java → src/main/javassist/util/HotSwapper.java View File

@@ -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.

+ 5
- 0
src/main/javassist/util/package.html View File

@@ -0,0 +1,5 @@
<html>
<body>
Utility classes.
</body>
</html>

+ 182
- 0
src/main/javassist/util/proxy/FactoryHelper.java View File

@@ -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();
}
}
}

+ 30
- 0
src/main/javassist/util/proxy/MethodFilter.java View File

@@ -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);
}

+ 48
- 0
src/main/javassist/util/proxy/MethodHandler.java View File

@@ -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;
}

+ 699
- 0
src/main/javassist/util/proxy/ProxyFactory.java View File

@@ -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());
}
}

+ 29
- 0
src/main/javassist/util/proxy/ProxyObject.java View File

@@ -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);
}

+ 157
- 0
src/main/javassist/util/proxy/RuntimeSupport.java View File

@@ -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(';');
}
}

+ 5
- 0
src/main/javassist/util/proxy/package.html View File

@@ -0,0 +1,5 @@
<html>
<body>
Dynamic proxy (similar to <code>Enhancer</code> of <a href="http://cglib.sourceforge.net/">cglib</a>).
</body>
</html>

Loading…
Cancel
Save