public class CodeConverter extends Object
javassist.expr package).
 Instances of this class specifies how to instrument of the
 bytecodes representing a method body.  They are passed to
 CtClass.instrument() or
 CtMethod.instrument() as a parameter.
 
Example:
 ClassPool cp = ClassPool.getDefault();
 CtClass point = cp.get("Point");
 CtClass singleton = cp.get("Singleton");
 CtClass client = cp.get("Client");
 CodeConverter conv = new CodeConverter();
 conv.replaceNew(point, singleton, "makePoint");
 client.instrument(conv);
 
 This program substitutes "Singleton.makePoint()"
 for all occurrences of "new Point()"
 appearing in methods declared in a Client class.
| Modifier and Type | Class and Description | 
|---|---|
| static interface  | CodeConverter.ArrayAccessReplacementMethodNamesInterface containing the method names to be used
 as array access replacements. | 
| static class  | CodeConverter.DefaultArrayAccessReplacementMethodNamesDefault implementation of the  ArrayAccessReplacementMethodNamesinterface giving default values for method names to be used for replacing
 accesses to array elements. | 
| Modifier and Type | Field and Description | 
|---|---|
| protected Transformer | transformers | 
| Constructor and Description | 
|---|
| CodeConverter() | 
| Modifier and Type | Method and Description | 
|---|---|
| protected void | doit(CtClass clazz,
    MethodInfo minfo,
    ConstPool cp)Performs code conversion. | 
| void | insertAfterMethod(CtMethod origMethod,
                 CtMethod afterMethod)Inserts a call to another method after an existing method call. | 
| void | insertBeforeMethod(CtMethod origMethod,
                  CtMethod beforeMethod)Insert a call to another method before an existing method call. | 
| void | redirectFieldAccess(CtField field,
                   CtClass newClass,
                   String newFieldname)Modify a method body so that field read/write expressions access
 a different field from the original one. | 
| void | redirectMethodCall(CtMethod origMethod,
                  CtMethod substMethod)Modify method invocations in a method body so that a different
 method will be invoked. | 
| void | redirectMethodCall(String oldMethodName,
                  CtMethod newMethod)Correct invocations to a method that has been renamed. | 
| void | replaceArrayAccess(CtClass calledClass,
                  CodeConverter.ArrayAccessReplacementMethodNames names)Modify a method body, so that ALL accesses to an array are replaced with 
 calls to static methods within another class. | 
| void | replaceFieldRead(CtField field,
                CtClass calledClass,
                String calledMethod)Modify a method body so that an expression reading the specified
 field is replaced with a call to the specified static method. | 
| void | replaceFieldWrite(CtField field,
                 CtClass calledClass,
                 String calledMethod)Modify a method body so that an expression writing the specified
 field is replaced with a call to the specified static method. | 
| void | replaceNew(CtClass oldClass,
          CtClass newClass)Modify a method body so that instantiation of the class
 specified by  oldClassis replaced with instantiation of another classnewClass. | 
| void | replaceNew(CtClass newClass,
          CtClass calledClass,
          String calledMethod)Modify a method body so that instantiation of the specified class
 is replaced with a call to the specified static method. | 
protected Transformer transformers
public void replaceNew(CtClass newClass, CtClass calledClass, String calledMethod)
replaceNew(ctPoint, ctSingleton, "createPoint")
 (where ctPoint and ctSingleton are
 compile-time classes for class Point and class
 Singleton, respectively)
 replaces all occurrences of:
 new Point(x, y)in the method body with:
Singleton.createPoint(x, y)
This enables to intercept instantiation of Point
 and change the samentics.  For example, the following
 createPoint() implements the singleton pattern:
 
public static Point createPoint(int x, int y) {
     if (aPoint == null)
         aPoint = new Point(x, y);
     return aPoint;
 }
 
 The static method call substituted for the original new
 expression must be
 able to receive the same set of parameters as the original
 constructor.  If there are multiple constructors with different
 parameter types, then there must be multiple static methods
 with the same name but different parameter types.
 
The return type of the substituted static method must be
 the exactly same as the type of the instantiated class specified by
 newClass.
newClass - the instantiated class.calledClass - the class in which the static method is
                          declared.calledMethod - the name of the static method.public void replaceNew(CtClass oldClass, CtClass newClass)
oldClass
 is replaced with instantiation of another class newClass.
 For example,
 replaceNew(ctPoint, ctPoint2)
 (where ctPoint and ctPoint2 are
 compile-time classes for class Point and class
 Point2, respectively)
 replaces all occurrences of:
 new Point(x, y)in the method body with:
new Point2(x, y)
Note that Point2 must be type-compatible with Point.
 It must have the same set of methods, fields, and constructors as the
 replaced class.
public void redirectFieldAccess(CtField field, CtClass newClass, String newFieldname)
Note that this method changes only the filed name and the class declaring the field; the type of the target object does not change. Therefore, the substituted field must be declared in the same class or a superclass of the original class.
Also, clazz and newClass must specify
 the class directly declaring the field.  They must not specify
 a subclass of that class.
field - the originally accessed field.newClass - the class declaring the substituted field.newFieldname - the name of the substituted field.public void replaceFieldRead(CtField field, CtClass calledClass, String calledMethod)
For example, the program below
Point p = new Point(); int newX = p.x + 3;
can be translated into:
Point p = new Point(); int newX = Accessor.readX(p) + 3;
where
public class Accessor {
     public static int readX(Object target) { ... }
 }
 The type of the parameter of readX() must
 be java.lang.Object independently of the actual
 type of target.  The return type must be the same
 as the field type.
field - the field.calledClass - the class in which the static method is
                          declared.calledMethod - the name of the static method.public void replaceFieldWrite(CtField field, CtClass calledClass, String calledMethod)
void.
 For example, the program below
Point p = new Point(); p.x = 3;
can be translated into:
Point p = new Point(); Accessor.writeX(3);
where
public class Accessor {
     public static void writeX(Object target, int value) { ... }
 }
 The type of the first parameter of writeX() must
 be java.lang.Object independently of the actual
 type of target.  The type of the second parameter
 is the same as the field type.
field - the field.calledClass - the class in which the static method is
                          declared.calledMethod - the name of the static method.public void replaceArrayAccess(CtClass calledClass, CodeConverter.ArrayAccessReplacementMethodNames names) throws NotFoundException
void.
 
 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.
 
 
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.
 
 
If we have the following class:
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)};
 }
 
 and this is accessed as:
 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];Following instrumentation we will have
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);
calledClass - the class containing the static methods.names - contains the names of the methods to replace
                           the different kinds of array access with.NotFoundExceptionCodeConverter.DefaultArrayAccessReplacementMethodNamespublic void redirectMethodCall(CtMethod origMethod, CtMethod substMethod) throws CannotCompileException
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 method must have the same signature that the original one has. If the original method is a static method, the substituted method must be static.
origMethod - original methodsubstMethod - substituted methodCannotCompileExceptionpublic void redirectMethodCall(String oldMethodName, CtMethod newMethod) throws CannotCompileException
The method must be declared in the same class before and after it is renamed.
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.
oldMethodName - the old name of the method.newMethod - the method with the new name.CannotCompileExceptionCtMethod.setName(String)public void insertBeforeMethod(CtMethod origMethod, CtMethod beforeMethod) throws CannotCompileException
void.  As parameters, the before method receives
 the target object and all the parameters to the originally invoked
 method.  For example, if the originally invoked method is
 move():
 class Point {
     Point move(int x, int y) { ... }
 }
 Then the before method must be something like this:
class Verbose {
     static void print(Point target, int x, int y) { ... }
 }
 The CodeConverter would translate bytecode
 equivalent to:
 
Point p2 = p.move(x + y, 0);
into the bytecode equivalent to:
int tmp1 = x + y; int tmp2 = 0; Verbose.print(p, tmp1, tmp2); Point p2 = p.move(tmp1, tmp2);
origMethod - the method originally invoked.beforeMethod - the method invoked before
                          origMethod.CannotCompileExceptionpublic void insertAfterMethod(CtMethod origMethod, CtMethod afterMethod) throws CannotCompileException
void.  As parameters, the after method receives
 the target object and all the parameters to the originally invoked
 method.  For example, if the originally invoked method is
 move():
 class Point {
     Point move(int x, int y) { ... }
 }
 Then the after method must be something like this:
class Verbose {
     static void print(Point target, int x, int y) { ... }
 }
 The CodeConverter would translate bytecode
 equivalent to:
 
Point p2 = p.move(x + y, 0);
into the bytecode equivalent to:
int tmp1 = x + y; int tmp2 = 0; Point p2 = p.move(tmp1, tmp2); Verbose.print(p, tmp1, tmp2);
origMethod - the method originally invoked.afterMethod - the method invoked after
                          origMethod.CannotCompileExceptionprotected void doit(CtClass clazz, MethodInfo minfo, ConstPool cp) throws CannotCompileException
CannotCompileExceptionCopyright © 2016 Shigeru Chiba, www.javassist.org. All Rights Reserved.