-
-
Notifications
You must be signed in to change notification settings - Fork 5
CRedirect
The CRedirect
annotation can be used to redirect method calls, field accesses and new object creations to a method.
The method signature of the transformer method depends on the redirect target.
When injecting into a static method, the transformer method also needs to be static and vice versa.
For redirecting method calls, the transformer method needs to have the same parameters and return type as the target method call with the addition of the target instance (if the target method is not static) as the first parameter.
//Injecting into a static method, the target method is not static
@CRedirect(target = @CTarget(value = "INVOKE", target = "LOwner;method(ILjava/lang/String;)I"), ...)
public static int transform(final Owner instance, final int arg1, final String arg2)
//Injecting into a non-static method, the target method is static
@CRedirect(target = @CTarget(value = "INVOKE", target = "LOwner;method(ILjava/lang/String;)I"), ...)
public int transform(final int arg1, final String arg2)
For redirecting field getters, the transformer method needs to have the field owner as the first parameter (if the field is not static) and the field type as the return type.
//Injecting into a static method, the target field is not static
@CRedirect(target = @CTarget(value = "GETFIELD", target = "LOwner;field:I"), ...)
public static int transform(final Owner instance)
//Injecting into a non-static method, the target field is static
@CRedirect(target = @CTarget(value = "GETFIELD", target = "LOwner;field:I"), ...)
public int transform()
For redirecting field setters, the transformer method needs to have the field owner as the first parameter (if the field is not static), the field type as the second parameter and the return type as void
.
//Injecting into a static method, the target field is not static
@CRedirect(target = @CTarget(value = "PUTFIELD", target = "LOwner;field:I"), ...)
public static void transform(final Owner instance, final int value)
//Injecting into a non-static method, the target field is static
@CRedirect(target = @CTarget(value = "PUTFIELD", target = "LOwner;field:I"), ...)
public void transform(final int value)
For redirecting new object creations, the transformer method needs to have the same parameters as the target constructor and the return type as the instantiated class.
//Injecting into a static method
@CRedirect(target = @CTarget(value = "NEW", target = "Owner"), ...)
public static Owner transform(final int arg1, final String arg2)
//Injecting into a non-static method
@CRedirect(target = @CTarget(value = "NEW", target = "Owner"), ...)
public Owner transform(final int arg1, final String arg2)
The target
field of the CRedirect
annotation specifies the redirected method/field/constructor.
Check out the CTarget page for more information about the different targets.
Also, check out CSlice for more information about how slices work.
The method
field can be an array of strings to target multiple methods.
The transformer method needs to be compatible with all targeted methods.
@CRedirect(method = {"method1", "method2"}, ...)
public void transform(final String arg)
Original method:
public void method() {
this.test = new Test("This is a test");
System.out.println(this.test.getMessage());
}
Transformer method:
@CRedirect(method = "method", target = @CTarget(value = "INVOKE", target = "Test.getMessage()Ljava/lang/String;"))
public String transform(final Test instance) {
return "This is a redirected test";
}
Injected code:
public void method() {
this.test = new Test("This is a test");
System.out.println(this.transform(this.test));
}
Transformer method:
@CRedirect(method = "method", target = @CTarget(value = "PUTFIELD", target = "Example.test:LTest;"))
public void putField(final Example instance, final Test value) {
instance.test = new Test("This is a redirected test 1");
}
@CRedirect(method = "method", target = @CTarget(value = "GETFIELD", target = "java/lang/System.out:Ljava/io/PrintStream;"))
public PrintStream getField() {
return System.err;
}
Injected code:
public void method() {
this.putField(this, new Test("This is a test"));
this.getField().println(this.test.getMessage());
}
Transformer method:
@CRedirect(method = "method", target = @CTarget(value = "NEW", target = "Test"))
public Test transform(final String message) {
return new Test(message + " 2");
}
Injected code:
public void method() {
this.test = this.transform("This is a test");
System.out.println(this.test.getMessage());
}