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 16 package javassist.convert; 17 18 import javassist.CtClass; 19 import javassist.CtMethod; 20 import javassist.ClassPool; 21 import javassist.Modifier; 22 import javassist.NotFoundException; 23 import javassist.bytecode.*; 24 25 public class TransformCall extends Transformer { 26 protected String classname, methodname, methodDescriptor; 27 protected String newClassname, newMethodname; 28 protected boolean newMethodIsPrivate; 29 30 /* cache */ 31 protected int newIndex; 32 protected ConstPool constPool; 33 34 public TransformCall(Transformer next, CtMethod origMethod, 35 CtMethod substMethod) 36 { 37 this(next, origMethod.getName(), substMethod); 38 classname = origMethod.getDeclaringClass().getName(); 39 } 40 41 public TransformCall(Transformer next, String oldMethodName, 42 CtMethod substMethod) 43 { 44 super(next); 45 methodname = oldMethodName; 46 methodDescriptor = substMethod.getMethodInfo2().getDescriptor(); 47 classname = newClassname = substMethod.getDeclaringClass().getName(); 48 newMethodname = substMethod.getName(); 49 constPool = null; 50 newMethodIsPrivate = Modifier.isPrivate(substMethod.getModifiers()); 51 } 52 53 public void initialize(ConstPool cp, CodeAttribute attr) { 54 if (constPool != cp) 55 newIndex = 0; 56 } 57 58 /** 59 * Modify INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC and INVOKEVIRTUAL 60 * so that a different method is invoked. The class name in the operand 61 * of these instructions might be a subclass of the target class specified 62 * by <code>classname</code>. This method transforms the instruction 63 * in that case unless the subclass overrides the target method. 64 */ 65 public int transform(CtClass clazz, int pos, CodeIterator iterator, 66 ConstPool cp) throws BadBytecode 67 { 68 int c = iterator.byteAt(pos); 69 if (c == INVOKEINTERFACE || c == INVOKESPECIAL 70 || c == INVOKESTATIC || c == INVOKEVIRTUAL) { 71 int index = iterator.u16bitAt(pos + 1); 72 String cname = cp.eqMember(methodname, methodDescriptor, index); 73 if (cname != null && matchClass(cname, clazz.getClassPool())) { 74 int ntinfo = cp.getMemberNameAndType(index); 75 pos = match(c, pos, iterator, 76 cp.getNameAndTypeDescriptor(ntinfo), cp); 77 } 78 } 79 80 return pos; 81 } 82 83 private boolean matchClass(String name, ClassPool pool) { 84 if (classname.equals(name)) 85 return true; 86 87 try { 88 CtClass clazz = pool.get(name); 89 CtClass declClazz = pool.get(classname); 90 if (clazz.subtypeOf(declClazz)) 91 try { 92 CtMethod m = clazz.getMethod(methodname, methodDescriptor); 93 return m.getDeclaringClass().getName().equals(classname); 94 } 95 catch (NotFoundException e) { 96 // maybe the original method has been removed. 97 return true; 98 } 99 } 100 catch (NotFoundException e) { 101 return false; 102 } 103 104 return false; 105 } 106 107 protected int match(int c, int pos, CodeIterator iterator, 108 int typedesc, ConstPool cp) throws BadBytecode 109 { 110 if (newIndex == 0) { 111 int nt = cp.addNameAndTypeInfo(cp.addUtf8Info(newMethodname), 112 typedesc); 113 int ci = cp.addClassInfo(newClassname); 114 if (c == INVOKEINTERFACE) 115 newIndex = cp.addInterfaceMethodrefInfo(ci, nt); 116 else { 117 if (newMethodIsPrivate && c == INVOKEVIRTUAL) 118 iterator.writeByte(INVOKESPECIAL, pos); 119 120 newIndex = cp.addMethodrefInfo(ci, nt); 121 } 122 123 constPool = cp; 124 } 125 126 iterator.write16bit(newIndex, pos + 1); 127 return pos; 128 } 129 } 130