]> source.dussan.org Git - javassist.git/commitdiff
Document CodeConverter.replaceArrayAccess()
authorkkhan <kkhan@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Fri, 5 Jan 2007 12:17:50 +0000 (12:17 +0000)
committerkkhan <kkhan@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Fri, 5 Jan 2007 12:17:50 +0000 (12:17 +0000)
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@340 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

src/main/javassist/CodeConverter.java
src/main/javassist/convert/TransformAccessArrayField.java

index 77696894ff0bfe313b33f0c4f8f698c252fb3a87..711e52c652ac0fa167f7c8b4cf11f77f166589d7 100644 (file)
@@ -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";
+       }
+    }
 }
index 56ab5a70ce9cbb75ec2acaa50eccd94c80700f44..9b08a128125c07751e4b57a1c65c2df27897986a 100644 (file)
@@ -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";
-      }
-      
-   }
 }