169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.convert; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalfinal public class TransformNew extends Transformer { 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int nested; 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String classname, trapClass, trapMethod; 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public TransformNew(Transformer next, 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String classname, String trapClass, String trapMethod) { 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(next); 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.classname = classname; 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.trapClass = trapClass; 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.trapMethod = trapMethod; 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void initialize(ConstPool cp, CodeAttribute attr) { 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal nested = 0; 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Replace a sequence of 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * NEW classname 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * DUP 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * ... 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * INVOKESPECIAL 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * with 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * NOP 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * NOP 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * ... 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * INVOKESTATIC trapMethod in trapClass 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int transform(CtClass clazz, int pos, CodeIterator iterator, 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ConstPool cp) throws CannotCompileException 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int index; 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int c = iterator.byteAt(pos); 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == NEW) { 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal index = iterator.u16bitAt(pos + 1); 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (cp.getClassInfo(index).equals(classname)) { 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (iterator.byteAt(pos + 3) != DUP) 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException( 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "NEW followed by no DUP was found"); 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.writeByte(NOP, pos); 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.writeByte(NOP, pos + 1); 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.writeByte(NOP, pos + 2); 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.writeByte(NOP, pos + 3); 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++nested; 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StackMapTable smt 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = (StackMapTable)iterator.get().getAttribute(StackMapTable.tag); 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (smt != null) 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal smt.removeNew(pos); 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StackMap sm 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = (StackMap)iterator.get().getAttribute(StackMap.tag); 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (sm != null) 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sm.removeNew(pos); 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (c == INVOKESPECIAL) { 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal index = iterator.u16bitAt(pos + 1); 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int typedesc = cp.isConstructor(classname, index); 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (typedesc != 0 && nested > 0) { 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int methodref = computeMethodref(typedesc, cp); 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.writeByte(INVOKESTATIC, pos); 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.write16bit(methodref, pos + 1); 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal --nested; 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pos; 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int computeMethodref(int typedesc, ConstPool cp) { 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int classIndex = cp.addClassInfo(trapClass); 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int mnameIndex = cp.addUtf8Info(trapMethod); 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal typedesc = cp.addUtf8Info( 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Descriptor.changeReturnType(classname, 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cp.getUtf8Info(typedesc))); 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cp.addMethodrefInfo(classIndex, 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cp.addNameAndTypeInfo(mnameIndex, typedesc)); 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 103