1/* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 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 16package javassist.convert; 17 18import javassist.bytecode.*; 19import javassist.CtClass; 20import javassist.CannotCompileException; 21 22final 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 { 53 int index; 54 int c = iterator.byteAt(pos); 55 if (c == NEW) { 56 index = iterator.u16bitAt(pos + 1); 57 if (cp.getClassInfo(index).equals(classname)) { 58 if (iterator.byteAt(pos + 3) != DUP) 59 throw new CannotCompileException( 60 "NEW followed by no DUP was found"); 61 62 iterator.writeByte(NOP, pos); 63 iterator.writeByte(NOP, pos + 1); 64 iterator.writeByte(NOP, pos + 2); 65 iterator.writeByte(NOP, pos + 3); 66 ++nested; 67 68 StackMapTable smt 69 = (StackMapTable)iterator.get().getAttribute(StackMapTable.tag); 70 if (smt != null) 71 smt.removeNew(pos); 72 73 StackMap sm 74 = (StackMap)iterator.get().getAttribute(StackMap.tag); 75 if (sm != null) 76 sm.removeNew(pos); 77 } 78 } 79 else if (c == INVOKESPECIAL) { 80 index = iterator.u16bitAt(pos + 1); 81 int typedesc = cp.isConstructor(classname, index); 82 if (typedesc != 0 && nested > 0) { 83 int methodref = computeMethodref(typedesc, cp); 84 iterator.writeByte(INVOKESTATIC, pos); 85 iterator.write16bit(methodref, pos + 1); 86 --nested; 87 } 88 } 89 90 return pos; 91 } 92 93 private int computeMethodref(int typedesc, ConstPool cp) { 94 int classIndex = cp.addClassInfo(trapClass); 95 int mnameIndex = cp.addUtf8Info(trapMethod); 96 typedesc = cp.addUtf8Info( 97 Descriptor.changeReturnType(classname, 98 cp.getUtf8Info(typedesc))); 99 return cp.addMethodrefInfo(classIndex, 100 cp.addNameAndTypeInfo(mnameIndex, typedesc)); 101 } 102} 103