Pārlūkot izejas kodu

Changed Callback so that CtBehaviour is independet of Callback. Added testcase

tags/rel_3_20_0_ga
marten.hedborg pirms 9 gadiem
vecāks
revīzija
89e50989d0

+ 0
- 108
src/main/javassist/CtBehavior.java Parādīt failu

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

+ 87
- 8
src/main/javassist/tools/Callback.java Parādīt failu

@@ -1,39 +1,118 @@
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());
}
}

+ 40
- 0
src/test/javassist/tools/CallbackTest.java Parādīt failu

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

+ 8
- 0
src/test/test/javassist/tools/DummyClass.java Parādīt failu

@@ -0,0 +1,8 @@
package test.javassist.tools;

public class DummyClass {

private String dummyString = "dummyStringValue";

public void dummyMethod(){}
}

Notiek ielāde…
Atcelt
Saglabāt