diff options
author | kkhan <kkhan@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2007-01-05 12:17:50 +0000 |
---|---|---|
committer | kkhan <kkhan@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2007-01-05 12:17:50 +0000 |
commit | 956be9c3df1db6123929edbd3a4aad91c0f09618 (patch) | |
tree | 03b9d7816459e3ed6a5ff19ee8fa2969209e327e /src | |
parent | 195d189ecb64eca7e6f8e3299ab2d2e99f988f50 (diff) | |
download | javassist-956be9c3df1db6123929edbd3a4aad91c0f09618.tar.gz javassist-956be9c3df1db6123929edbd3a4aad91c0f09618.zip |
Document CodeConverter.replaceArrayAccess()
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@340 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src')
-rw-r--r-- | src/main/javassist/CodeConverter.java | 338 | ||||
-rw-r--r-- | src/main/javassist/convert/TransformAccessArrayField.java | 174 |
2 files changed, 333 insertions, 179 deletions
diff --git a/src/main/javassist/CodeConverter.java b/src/main/javassist/CodeConverter.java index 77696894..711e52c6 100644 --- a/src/main/javassist/CodeConverter.java +++ b/src/main/javassist/CodeConverter.java @@ -17,7 +17,6 @@ package javassist; import javassist.bytecode.*; import javassist.convert.*; -import javassist.convert.TransformAccessArrayField.MethodNames; /** * Simple translator of method bodies @@ -48,7 +47,7 @@ import javassist.convert.TransformAccessArrayField.MethodNames; * @see javassist.expr.ExprEditor */ public class CodeConverter { - Transformer transformers = null; + protected Transformer transformers = null; /** * Modify a method body so that instantiation of the specified class @@ -64,7 +63,7 @@ public class CodeConverter { * in the method body with: * * <ul><code>Singleton.createPoint(x, y)</code></ul> - * + * * <p>This enables to intercept instantiation of <code>Point</code> * and change the samentics. For example, the following * <code>createPoint()</code> implements the singleton pattern: @@ -169,7 +168,7 @@ public class CodeConverter { * the original * write expression and the assigned value. The return type of the * static method is <code>void</code>. - * + * * <p>For example, the program below * * <ul><pre>Point p = new Point(); @@ -203,16 +202,110 @@ public class CodeConverter { calledMethod); } - public void replaceArrayAccess(CtClass calledClass, MethodNames names) throws NotFoundException + /** + * Modify a method body, so that ALL accesses to an array are replaced with + * calls to static methods within another class. In the case of reading an + * element from the array, this is replaced with a call to a static method with + * the array and the index as arguments, the return value is the value read from + * the array. If writing to an array, this is replaced with a call to a static + * method with the array, index and new value as parameters, the return value of + * the static method is <code>void</code>. + * + * <p>The calledClass parameter is the class containing the static methods to be used + * for array replacement. The names parameter points to an implementation of + * ArrayAccessReplacementMethodNames which specifies the names of the method to be + * used for access for each type of array. For example reading from an int[] will + * require a different method than if writing to an int[], and writing to a long[] + * will require a different method than if writing to a byte[]. If the implementation + * of ArrayAccessReplacementMethodNames does not contain the name for access for a + * type of array, that access is not replaced. + * + * <p>A default implementation of ArrayAccessReplacementMethodNames called + * DefaultArrayAccessReplacementMethodNames has been provided and is what is used in the + * following example. This also assumes that 'foo.ArrayAdvisor' is the name of the + * CtClass passed in. + * + * <p>If we have the following class + * <pre>class POJO{ + * int[] ints = new int[]{1, 2, 3, 4, 5}; + * long[] longs = new int[]{10, 20, 30}; + * Object objects = new Object[]{true, false}; + * Integer[] integers = new Integer[]{new Integer(10)}; + * } + * </pre> + * and this is accessed as + * <pre>POJO p = new POJO(); + * + * //Write to int array + * p.ints[2] = 7; + * + * //Read from int array + * int i = p.ints[2]; + * + * //Write to long array + * p.longs[2] = 1000L; + * + * //Read from long array + * long l = p.longs[2]; + * + * //Write to Object array + * p.objects[2] = "Hello"; + * + * //Read from Object array + * Object o = p.objects[2]; + * + * //Write to Integer array + * Integer integer = new Integer(5); + * p.integers[0] = integer; + * + * //Read from Object array + * integer = p.integers[0]; + * </pre> + * + * Following instrumentation we will have + * <pre>POJO p = new POJO(); + * + * //Write to int array + * ArrayAdvisor.arrayWriteInt(p.ints, 2, 7); + * + * //Read from int array + * int i = ArrayAdvisor.arrayReadInt(p.ints, 2); + * + * //Write to long array + * ArrayAdvisor.arrayWriteLong(p.longs, 2, 1000L); + * + * //Read from long array + * long l = ArrayAdvisor.arrayReadLong(p.longs, 2); + * + * //Write to Object array + * ArrayAdvisor.arrayWriteObject(p.objects, 2, "Hello"); + * + * //Read from Object array + * Object o = ArrayAdvisor.arrayReadObject(p.objects, 2); + * + * //Write to Integer array + * Integer integer = new Integer(5); + * ArrayAdvisor.arrayWriteObject(p.integers, 0, integer); + * + * //Read from Object array + * integer = ArrayAdvisor.arrayWriteObject(p.integers, 0); + * </pre> + * + * @see DefaultArrayAccessReplacementMethodNames + * + * @param calledClass the class containing the static methods + * @param names contains the names of the methods to replace the different kinds of array access with + */ + public void replaceArrayAccess(CtClass calledClass, ArrayAccessReplacementMethodNames names) throws NotFoundException { transformers = new TransformAccessArrayField(transformers, calledClass.getName(), names); } - + /** * Modify method invocations in a method body so that a different * method will be invoked. * - * <p>Note that the target object, the parameters, or + * <p>Note that the target object, the parameters, or * the type of invocation * (static method call, interface call, or private method call) * are not modified. Only the method name is changed. The substituted @@ -254,7 +347,7 @@ public class CodeConverter { * <p>The method must be declared in the same class before and * after it is renamed. * - * <p>Note that the target object, the parameters, or + * <p>Note that the target object, the parameters, or * the type of invocation * (static method call, interface call, or private method call) * are not modified. Only the method name is changed. @@ -368,7 +461,7 @@ public class CodeConverter { /** * Performs code conversion. */ - void doit(CtClass clazz, MethodInfo minfo, ConstPool cp) + protected void doit(CtClass clazz, MethodInfo minfo, ConstPool cp) throws CannotCompileException { Transformer t; @@ -403,4 +496,231 @@ public class CodeConverter { codeAttr.setMaxLocals(codeAttr.getMaxLocals() + locals); } + + /** + * Interface containing the method names to be used as array access replacements + * + * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> + * @version $Revision: 1.11 $ + */ + public interface ArrayAccessReplacementMethodNames + { + /** + * @return the name of a static method with the signature (Ljava/lang/Object;I)B" to replace reading from a byte[] + */ + String byteOrBooleanRead(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;IB)V to replace writing to a byte[] + */ + String byteOrBooleanWrite(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;I)C to replace reading from a char[] + */ + String charRead(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;IC)V to replace writing to a byte[] + */ + String charWrite(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;I)D to replace reading from a double[] + */ + String doubleRead(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;ID)V to replace writing to a double[] + */ + String doubleWrite(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;I)F to replace reading from a float[] + */ + String floatRead(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;IF)V to replace writing to a float[] + */ + String floatWrite(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;I)I to replace reading from a int[] + */ + String intRead(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;II)V to replace writing to a int[] + */ + String intWrite(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;I)J to replace reading from a long[] + */ + String longRead(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;IJ)V to replace writing to a long[] + */ + String longWrite(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;I)Ljava/lang/Object; to replace reading from a Object[] (or any subclass of object) + */ + String objectRead(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;ILjava/lang/Object;)V to replace writing to a Object[] (or any subclass of object) + */ + String objectWrite(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;I)S to replace reading from a short[] + */ + String shortRead(); + + /** + * @return the name of a static method with the signature (Ljava/lang/Object;IS)V to replace writing to a short[] + */ + String shortWrite(); + } + + /** + * Default implementation of the MethodNames interface giving default values for method names to be used for replacing accesses to array elements + * + * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> + * @version $Revision: 1.11 $ + */ + public static class DefaultArrayAccessReplacementMethodNames implements ArrayAccessReplacementMethodNames + { + + /** + * @return "arrayReadByteOrBoolean" as the name of the static method with the signature (Ljava/lang/Object;I)B" to replace reading from a byte[] + */ + public String byteOrBooleanRead() + { + return "arrayReadByteOrBoolean"; + } + + /** + * @return "arrayWriteByteOrBoolean" as the name of the static method with the signature (Ljava/lang/Object;IB)V to replace writing to a byte[] + */ + public String byteOrBooleanWrite() + { + return "arrayWriteByteOrBoolean"; + } + + /** + * @return "arrayReadChar" as the name of the static method with the signature (Ljava/lang/Object;I)C to replace reading from a char[] + */ + public String charRead() + { + return "arrayReadChar"; + } + + /** + * @return "arrayWriteChar" as the name of the static method with the signature (Ljava/lang/Object;IC)V to replace writing to a byte[] + */ + public String charWrite() + { + return "arrayWriteChar"; + } + + /** + * @return "arrayReadDouble" as the name of the static method with the signature (Ljava/lang/Object;I)D to replace reading from a double[] + */ + public String doubleRead() + { + return "arrayReadDouble"; + } + + /** + * @return "arrayWriteDouble" as the name of the static method with the signature (Ljava/lang/Object;ID)V to replace writing to a double[] + */ + public String doubleWrite() + { + return "arrayWriteDouble"; + } + + /** + * @return "arrayReadFloat" as the name of the static method with the signature (Ljava/lang/Object;I)F to replace reading from a float[] + */ + public String floatRead() + { + return "arrayReadFloat"; + } + + /** + * @return "arrayWriteFloat" as the name of the static method with the signature (Ljava/lang/Object;IF)V to replace writing to a float[] + */ + public String floatWrite() + { + return "arrayWriteFloat"; + } + + /** + * @return "arrayReadInt" as the name of the static method with the signature (Ljava/lang/Object;I)I to replace reading from a int[] + */ + public String intRead() + { + return "arrayReadInt"; + } + + /** + * @return "arrayWriteInt" as the name of the static method with the signature (Ljava/lang/Object;II)V to replace writing to a int[] + */ + public String intWrite() + { + return "arrayWriteInt"; + } + + /** + * @return "arrayReadLong" as the name of the static method with the signature (Ljava/lang/Object;I)J to replace reading from a long[] + */ + public String longRead() + { + return "arrayReadLong"; + } + + /** + * @return "arrayWriteLong" as the name of the static method with the signature (Ljava/lang/Object;IJ)V to replace writing to a long[] + */ + public String longWrite() + { + return "arrayWriteLong"; + } + + /** + * @return "arrayReadObject" as the name of the static method with the signature (Ljava/lang/Object;I)Ljava/lang/Object; to replace reading from a Object[] (or any subclass of object) + */ + public String objectRead() + { + return "arrayReadObject"; + } + + /** + * @return "arrayWriteObject" as the name of the static method with the signature (Ljava/lang/Object;ILjava/lang/Object;)V to replace writing to a Object[] (or any subclass of object) + */ + public String objectWrite() + { + return "arrayWriteObject"; + } + + /** + * @return "arrayReadShort" as the name of the static method with the signature (Ljava/lang/Object;I)S to replace reading from a short[] + */ + public String shortRead() + { + return "arrayReadShort"; + } + + /** + * @return "arrayWriteShort" as the name of the static method with the signature (Ljava/lang/Object;IS)V to replace writing to a short[] + */ + public String shortWrite() + { + return "arrayWriteShort"; + } + } } diff --git a/src/main/javassist/convert/TransformAccessArrayField.java b/src/main/javassist/convert/TransformAccessArrayField.java index 56ab5a70..9b08a128 100644 --- a/src/main/javassist/convert/TransformAccessArrayField.java +++ b/src/main/javassist/convert/TransformAccessArrayField.java @@ -17,6 +17,7 @@ package javassist.convert; import javassist.CtClass; import javassist.NotFoundException; +import javassist.CodeConverter.ArrayAccessReplacementMethodNames; import javassist.bytecode.BadBytecode; import javassist.bytecode.CodeIterator; import javassist.bytecode.ConstPool; @@ -24,16 +25,16 @@ import javassist.bytecode.ConstPool; /** * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> - * @version $Revision: 1.1 $ + * @version $Revision: 1.2 $ */ public class TransformAccessArrayField extends Transformer { // CtClass componentType; String methodClassname; - MethodNames names; + ArrayAccessReplacementMethodNames names; - public TransformAccessArrayField(Transformer next, String methodClassname, MethodNames names) throws NotFoundException + public TransformAccessArrayField(Transformer next, String methodClassname, ArrayAccessReplacementMethodNames names) throws NotFoundException { super(next); this.methodClassname = methodClassname; @@ -179,171 +180,4 @@ public class TransformAccessArrayField extends Transformer } throw new BadBytecode(opcode); } - - public interface MethodNames - { - /** - * Give the name of a static method with the signature (Ljava/lang/Object;I)Ljava/lang/Object; - */ - String objectRead(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;I)B" - */ - String byteOrBooleanRead(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;I)C - */ - String charRead(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;I)D - */ - String doubleRead(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;I)F - */ - String floatRead(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;I)I - */ - String intRead(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;I)J - */ - String longRead(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;I)S - */ - String shortRead(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;ILjava/lang/Object;)V - */ - String objectWrite(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;IB)V - */ - String byteOrBooleanWrite(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;IC)V - */ - String charWrite(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;ID)V - */ - String doubleWrite(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;IF)V - */ - String floatWrite(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;II)V - */ - String intWrite(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;IJ)V - */ - String longWrite(); - - /** - * Give the name of a static method with the signature (Ljava/lang/Object;IS)V - */ - String shortWrite(); - } - - public static class DefaultMethodNames implements MethodNames - { - public String byteOrBooleanRead() - { - return "arrayReadByteOrBoolean"; - } - - public String byteOrBooleanWrite() - { - return "arrayWriteByteOrBoolean"; - } - - public String charRead() - { - return "arrayReadChar"; - } - - public String charWrite() - { - return "arrayWriteChar"; - } - - public String doubleRead() - { - return "arrayReadDouble"; - } - - public String doubleWrite() - { - return "arrayWriteDouble"; - } - - public String floatRead() - { - return "arrayReadFloat"; - } - - public String floatWrite() - { - return "arrayWriteFloat"; - } - - public String intRead() - { - return "arrayReadInt"; - } - - public String intWrite() - { - return "arrayWriteInt"; - } - - public String longRead() - { - return "arrayReadLong"; - } - - public String longWrite() - { - return "arrayWriteLong"; - } - - public String objectRead() - { - return "arrayReadObject"; - } - - public String objectWrite() - { - return "arrayWriteObject"; - } - - public String shortRead() - { - return "arrayReadShort"; - } - - public String shortWrite() - { - return "arrayWriteShort"; - } - - } } |