/Users/lyon/j4p/src/javassist/convert/TransformCall.java

1    /* 
2     * Javassist, a Java-bytecode translator toolkit. 
3     * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved. 
4     * 
5     * The contents of this file are subject to the Mozilla Public License Version 
6     * 1.1 (the "License"); you may not use this file except in compliance with 
7     * the License.  Alternatively, the contents of this file may be used under 
8     * the terms of the GNU Lesser General Public License Version 2.1 or later. 
9     * 
10    * Software distributed under the License is distributed on an "AS IS" basis, 
11    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
12    * for the specific language governing rights and limitations under the 
13    * License. 
14    */ 
15    
16   package javassist.convert; 
17    
18   import javassist.CtClass; 
19   import javassist.CtMethod; 
20   import javassist.bytecode.*; 
21   import javassist.CannotCompileException; 
22    
23   public class TransformCall extends Transformer { 
24       protected String classname, methodname, methodDescriptor; 
25       protected String newClassname, newMethodname; 
26    
27       /* cache */ 
28       protected int newIndex; 
29       protected ConstPool constPool; 
30    
31       public TransformCall(Transformer next, CtMethod origMethod, 
32                            CtMethod substMethod) { 
33           super(next); 
34           this.classname = origMethod.getDeclaringClass().getName(); 
35           this.methodname = origMethod.getName(); 
36           this.methodDescriptor = origMethod.getMethodInfo2().getDescriptor(); 
37           this.newClassname = substMethod.getDeclaringClass().getName(); 
38           this.newMethodname = substMethod.getName(); 
39           this.constPool = null; 
40       } 
41    
42       public void initialize(ConstPool cp, CodeAttribute attr) { 
43           if (constPool != cp) 
44               newIndex = 0; 
45       } 
46    
47       /** 
48        * Modify INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC and INVOKEVIRTUAL 
49        * so that a different method is invoked. 
50        */ 
51       public int transform(CtClass clazz, int pos, CodeIterator iterator, 
52                            ConstPool cp) throws BadBytecode { 
53           int c = iterator.byteAt(pos); 
54           if (c == INVOKEINTERFACE || c == INVOKESPECIAL 
55                   || c == INVOKESTATIC || c == INVOKEVIRTUAL) { 
56               int index = iterator.u16bitAt(pos + 1); 
57               int typedesc = cp.isMember(classname, methodname, index); 
58               if (typedesc != 0) 
59                   if (cp.getUtf8Info(typedesc).equals(methodDescriptor)) 
60                       pos = match(c, pos, iterator, typedesc, cp); 
61           } 
62    
63           return pos; 
64       } 
65    
66       protected int match(int c, int pos, CodeIterator iterator, 
67                           int typedesc, ConstPool cp) throws BadBytecode { 
68           if (newIndex == 0) { 
69               int nt = cp.addNameAndTypeInfo(cp.addUtf8Info(newMethodname), 
70                       typedesc); 
71               int ci = cp.addClassInfo(newClassname); 
72               if (c == INVOKEINTERFACE) 
73                   newIndex = cp.addInterfaceMethodrefInfo(ci, nt); 
74               else 
75                   newIndex = cp.addMethodrefInfo(ci, nt); 
76    
77               constPool = cp; 
78           } 
79    
80           iterator.write16bit(newIndex, pos + 1); 
81           return pos; 
82       } 
83   } 
84