]> source.dussan.org Git - javassist.git/commitdiff
Changed Callback so that CtBehaviour is independet of Callback. Added testcase
authormarten.hedborg <marten.hedborg@gmail.com>
Sun, 15 Mar 2015 17:37:30 +0000 (18:37 +0100)
committermarten.hedborg <marten.hedborg@gmail.com>
Sun, 15 Mar 2015 17:37:30 +0000 (18:37 +0100)
src/main/javassist/CtBehavior.java
src/main/javassist/tools/Callback.java
src/test/javassist/tools/CallbackTest.java [new file with mode: 0644]
src/test/test/javassist/tools/DummyClass.java [new file with mode: 0644]

index e52fcb792da8936b5d3ed0931ce9ac52dce159e7..9251315914330bec91b704480f37830cfbd76708 100644 (file)
@@ -20,7 +20,6 @@ import javassist.bytecode.*;
 import javassist.compiler.Javac;
 import javassist.compiler.CompileError;
 import javassist.expr.ExprEditor;
-import javassist.tools.Callback;
 
 /**
  * <code>CtBehavior</code> represents a method, a constructor,
@@ -714,29 +713,6 @@ public abstract class CtBehavior extends CtMember {
             declaringClass.checkModify();
     }
 
-    /**
-     * Inserts callback at the beginning of the body.
-     *
-     * <p>If this object represents a constructor,
-     * the callback is inserted before
-     * a constructor in the super class or this class is called.
-     * Therefore, the inserted callback is subject to constraints described
-     * in Section 4.8.2 of The Java Virtual Machine Specification (2nd ed).
-     * For example, it cannot access instance fields or methods although
-     * it may assign a value to an instance field directly declared in this
-     * class.  Accessing static fields and methods is allowed.
-     * Use <code>insertBeforeBody()</code> in <code>CtConstructor</code>.
-     *
-     * @param callback       the source code representing the inserted bytecode.
-     *                  It must be a single statement or block.
-     * @see CtConstructor#insertBeforeBody(String)
-     */
-    public void insertBefore(Callback callback)
-            throws CannotCompileException
-    {
-        insertBefore(callback.toString(), true);
-    }
-
     /**
      * Inserts bytecode at the beginning of the body.
      *
@@ -802,39 +778,6 @@ public abstract class CtBehavior extends CtMember {
         }
     }
 
-    /**
-     * Inserts callback bytecode at the end of the body.
-     * The callback is inserted just before every return insturction.
-     * It is not executed when an exception is thrown.
-     *
-     * @param callback       the source code representing the inserted bytecode.
-     *                  It must be a single statement or block.
-     */
-    public void insertAfter(Callback callback)
-            throws CannotCompileException
-    {
-        insertAfter(callback.toString(), false);
-    }
-
-    /**
-     * Inserts callback bytecode at the end of the body.
-     * The callback is inserted just before every return insturction.
-     * It is not executed when an exception is thrown.
-     *
-     * @param callback       the callback source code representing the inserted bytecode.
-     *                  It must be a single statement or block.
-     * @param asFinally         true if the inserted bytecode is executed
-     *                  not only when the control normally returns
-     *                  but also when an exception is thrown.
-     *                  If this parameter is true, the inserted code cannot
-     *                  access local variables.
-     */
-    public void insertAfter(Callback callback, boolean asFinally)
-            throws CannotCompileException
-    {
-        insertAfter(callback.toString(), asFinally);
-    }
-
     /**
      * Inserts bytecode at the end of the body.
      * The bytecode is inserted just before every return insturction.
@@ -1191,29 +1134,6 @@ public abstract class CtBehavior extends CtMember {
         return insertAt(lineNum, true, src);
     }
 
-    /**
-     * Inserts callback bytecode at the specified line in the body.
-     * It is equivalent to:
-     *
-     * <br><code>insertAt(lineNum, true, src)</code>
-     *
-     * <br>See this method as well.
-     *
-     * @param lineNum   the line number.  The bytecode is inserted at the
-     *                  beginning of the code at the line specified by this
-     *                  line number.
-     * @param callback  the callback source code representing the inserted bytecode.
-     *                  It must be a single statement or block.
-     * @return      the line number at which the callback bytecode has been inserted.
-     *
-     * @see CtBehavior#insertAt(int,boolean,String)
-     */
-    public int insertAt(int lineNum, Callback callback)
-            throws CannotCompileException
-    {
-        return insertAt(lineNum, true, callback.toString());
-    }
-
     /**
      * Inserts bytecode at the specified line in the body.
      *
@@ -1290,32 +1210,4 @@ public abstract class CtBehavior extends CtMember {
             throw new CannotCompileException(e);
         }
     }
-
-    /**
-     * Inserts callback bytecode at the specified line in the body.
-     *
-     * <p>If there is not
-     * a statement at the specified line, the bytecode might be inserted
-     * at the line including the first statement after that line specified.
-     * For example, if there is only a closing brace at that line, the
-     * bytecode would be inserted at another line below.
-     * To know exactly where the bytecode will be inserted, call with
-     * <code>modify</code> set to <code>false</code>.
-     *
-     * @param lineNum   the line number.  The bytecode is inserted at the
-     *                  beginning of the code at the line specified by this
-     *                  line number.
-     * @param modify    if false, this method does not insert the bytecode.
-     *                  It instead only returns the line number at which
-     *                  the bytecode would be inserted.
-     * @param callback  the callback source code representing the inserted bytecode.
-     *                  It must be a single statement or block.
-     *                  If modify is false, the value of src can be null.
-     * @return      the line number at which the bytecode has been inserted.
-     */
-    public int insertAt(int lineNum, boolean modify, Callback callback)
-            throws CannotCompileException
-    {
-       return insertAt(lineNum,modify,callback.toString());
-    }
 }
index 0cf5db47fcac8e864953c03e961a53699e0fadd9..4a1a491fa4556acede6972fc7ba39a652071d07f 100644 (file)
 package javassist.tools;
 
+import javassist.CannotCompileException;
+import javassist.CtBehavior;
+
 import java.util.HashMap;
 import java.util.UUID;
 
 /**
- * Creates bytecode that when executed calls back to the objects result method.
+ * Creates bytecode that when executed calls back to the instance's result method.
+ *
+ * Inserts callbacks in <code>CtBehaviour</code>
+ *
  */
 public abstract class Callback {
 
     public static HashMap<String, Callback> callbacks = new HashMap<String, Callback>();
 
-    private final String callbackCode;
+    private final String sourceCode;
 
     /**
      * Constructs a new <code>Callback</code> object.
      *
-     * @param src         java code that returns one or many objects. if many objects
-     *                    are returned they should be comma separated
+     * @param src       The source code representing the inserted callback bytecode.
+     *                  Can be one or many single statements or blocks each returning one object.
+     *                  If many single statements or blocks are used they must be comma separated.
      */
     public Callback(String src){
         String uuid = UUID.randomUUID().toString();
         callbacks.put(uuid, this);
-        callbackCode = "((javassist.tools.Callback) javassist.tools.Callback.callbacks.get(\""+uuid+"\")).result(new Object[]{"+src+"});";
+        sourceCode = "((javassist.tools.Callback) javassist.tools.Callback.callbacks.get(\""+uuid+"\")).result(new Object[]{"+src+"});";
     }
 
     /**
      * Gets called when bytecode is executed
      *
-     * @param objects     java code that returns one or many objects. if many objects
-     *                    are returned they should be comma separated
+     * @param objects   Objects that the bytecode in callback returns
      */
     public abstract void result(Object... objects);
 
     @Override
     public String toString(){
-        return callbackCode;
+        return sourceCode();
+    }
+
+    public String sourceCode(){
+        return sourceCode;
+    }
+
+    /**
+     * Inserts callback at the beginning of the body.
+     *
+     * @param callback  The callback
+     *
+     * @see CtBehavior#insertBefore(String)
+     */
+    public static void insertBefore(CtBehavior behavior, Callback callback)
+            throws CannotCompileException
+    {
+        behavior.insertBefore(callback.toString());
+    }
+
+    /**
+     * Inserts callback at the end of the body.
+     * The callback is inserted just before every return instruction.
+     * It is not executed when an exception is thrown.
+     *
+     * @param behavior  The behaviour to insert callback in
+     * @param callback  The callback
+     *
+     * @see CtBehavior#insertAfter(String, boolean)
+     */
+    public static void insertAfter(CtBehavior behavior,Callback callback)
+            throws CannotCompileException
+    {
+        behavior.insertAfter(callback.toString(), false);
+    }
+
+    /**
+     * Inserts callback at the end of the body.
+     * The callback is inserted just before every return instruction.
+     * It is not executed when an exception is thrown.
+     *
+     * @param behavior  The behaviour to insert callback in
+     * @param callback  The callback representing the inserted.
+     * @param asFinally True if the inserted is executed
+     *                  Not only when the control normally returns
+     *                  but also when an exception is thrown.
+     *                  If this parameter is true, the inserted code cannot
+     *                  access local variables.
+     *
+     * @see CtBehavior#insertAfter(String, boolean)
+     */
+    public static void insertAfter(CtBehavior behavior, Callback callback, boolean asFinally)
+            throws CannotCompileException
+    {
+        behavior.insertAfter(callback.toString(), asFinally);
+    }
+
+    /**
+     * Inserts callback at the specified line in the body.
+     *
+     * @param behavior  The behaviour to insert callback in
+     * @param callback  The callback representing.
+     * @param lineNum   The line number.  The callback is inserted at the
+     *                  beginning of the code at the line specified by this
+     *                  line number.
+     *
+     * @return      The line number at which the callback has been inserted.
+     *
+     * @see CtBehavior#insertAt(int, String)
+     */
+    public static int insertAt(CtBehavior behavior, Callback callback, int lineNum)
+            throws CannotCompileException
+    {
+        return behavior.insertAt(lineNum, callback.toString());
     }
 }
diff --git a/src/test/javassist/tools/CallbackTest.java b/src/test/javassist/tools/CallbackTest.java
new file mode 100644 (file)
index 0000000..a37ee61
--- /dev/null
@@ -0,0 +1,40 @@
+package javassist.tools;
+
+import javassist.*;
+import junit.framework.TestCase;
+import test.javassist.tools.DummyClass;
+
+import static javassist.tools.Callback.*;
+
+public class CallbackTest extends TestCase {
+
+    public void testSomeCallbacks() throws Exception {
+
+        // Get class and method to change
+        ClassPool pool = ClassPool.getDefault();
+        CtClass classToChange = pool.get("test.javassist.tools.DummyClass");
+        CtMethod methodToChange = classToChange.getDeclaredMethod("dummyMethod");
+
+        // Insert after
+        methodToChange.insertAfter(new Callback("Thread.currentThread(), dummyString") {
+            @Override
+            public void result(Object... objects) {
+                assertEquals(objects[0], Thread.currentThread());
+                assertEquals(objects[1], "dummyStringValue");
+            }
+        }.sourceCode());
+
+        // Insert after using utility method
+        insertAfter(methodToChange, new Callback("Thread.currentThread(), dummyString") {
+            @Override
+            public void result(Object... objects) {
+                assertEquals(objects[0], Thread.currentThread());
+                assertEquals(objects[1], "dummyStringValue");
+            }
+        });
+
+        // Change class and invoke method();
+        classToChange.toClass();
+        new DummyClass().dummyMethod();
+    }
+}
diff --git a/src/test/test/javassist/tools/DummyClass.java b/src/test/test/javassist/tools/DummyClass.java
new file mode 100644 (file)
index 0000000..020aa55
--- /dev/null
@@ -0,0 +1,8 @@
+package test.javassist.tools;
+
+public class DummyClass {
+
+    private String dummyString = "dummyStringValue";
+
+    public void dummyMethod(){}
+}