/Users/lyon/j4p/src/javassist/convert/TransformNew.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.bytecode.*; 
19   import javassist.CtClass; 
20   import javassist.CannotCompileException; 
21    
22   final public class TransformNew extends Transformer { 
23       private int nested; 
24       private String classname, trapClass, trapMethod; 
25    
26       public TransformNew(Transformer next, 
27                           String classname, String trapClass, String trapMethod) { 
28           super(next); 
29           this.classname = classname; 
30           this.trapClass = trapClass; 
31           this.trapMethod = trapMethod; 
32       } 
33    
34       public void initialize(ConstPool cp, CodeAttribute attr) { 
35           nested = 0; 
36       } 
37    
38       /** 
39        * Replace a sequence of 
40        *    NEW classname 
41        *    DUP 
42        *    ... 
43        *    INVOKESPECIAL 
44        * with 
45        *    NOP 
46        *    NOP 
47        *    ... 
48        *    INVOKESTATIC trapMethod in trapClass 
49        */ 
50       public int transform(CtClass clazz, int pos, CodeIterator iterator, 
51                            ConstPool cp) throws CannotCompileException { 
52           int index; 
53           int c = iterator.byteAt(pos); 
54           if (c == NEW) { 
55               index = iterator.u16bitAt(pos + 1); 
56               if (cp.getClassInfo(index).equals(classname)) { 
57                   if (iterator.byteAt(pos + 3) != DUP) 
58                       throw new CannotCompileException( 
59                               "NEW followed by no DUP was found"); 
60    
61                   iterator.writeByte(NOP, pos); 
62                   iterator.writeByte(NOP, pos + 1); 
63                   iterator.writeByte(NOP, pos + 2); 
64                   iterator.writeByte(NOP, pos + 3); 
65                   ++nested; 
66               } 
67           } else if (c == INVOKESPECIAL) { 
68               index = iterator.u16bitAt(pos + 1); 
69               int typedesc = cp.isConstructor(classname, index); 
70               if (typedesc != 0 && nested > 0) { 
71                   int methodref = computeMethodref(typedesc, cp); 
72                   iterator.writeByte(INVOKESTATIC, pos); 
73                   iterator.write16bit(methodref, pos + 1); 
74                   --nested; 
75               } 
76           } 
77    
78           return pos; 
79       } 
80    
81       private int computeMethodref(int typedesc, ConstPool cp) { 
82           int classIndex = cp.addClassInfo(trapClass); 
83           int mnameIndex = cp.addUtf8Info(trapMethod); 
84           typedesc = cp.addUtf8Info( 
85                   Descriptor.changeReturnType(classname, 
86                           cp.getUtf8Info(typedesc))); 
87           return cp.addMethodrefInfo(classIndex, 
88                   cp.addNameAndTypeInfo(mnameIndex, typedesc)); 
89       } 
90   } 
91