01: /*
02: * Javassist, a Java-bytecode translator toolkit.
03: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
04: *
05: * The contents of this file are subject to the Mozilla Public License Version
06: * 1.1 (the "License"); you may not use this file except in compliance with
07: * the License. Alternatively, the contents of this file may be used under
08: * the terms of the GNU Lesser General Public License Version 2.1 or later.
09: *
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.Modifier;
21: import javassist.bytecode.*;
22:
23: public class TransformCall extends Transformer {
24: protected String classname, methodname, methodDescriptor;
25: protected String newClassname, newMethodname;
26: protected boolean newMethodIsPrivate;
27:
28: /* cache */
29: protected int newIndex;
30: protected ConstPool constPool;
31:
32: public TransformCall(Transformer next, CtMethod origMethod,
33: CtMethod substMethod) {
34: this (next, origMethod.getName(), substMethod);
35: classname = origMethod.getDeclaringClass().getName();
36: }
37:
38: public TransformCall(Transformer next, String oldMethodName,
39: CtMethod substMethod) {
40: super (next);
41: methodname = oldMethodName;
42: methodDescriptor = substMethod.getMethodInfo2().getDescriptor();
43: classname = newClassname = substMethod.getDeclaringClass()
44: .getName();
45: newMethodname = substMethod.getName();
46: constPool = null;
47: newMethodIsPrivate = Modifier.isPrivate(substMethod
48: .getModifiers());
49: }
50:
51: public void initialize(ConstPool cp, CodeAttribute attr) {
52: if (constPool != cp)
53: newIndex = 0;
54: }
55:
56: /**
57: * Modify INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC and INVOKEVIRTUAL
58: * so that a different method is invoked.
59: */
60: public int transform(CtClass clazz, int pos, CodeIterator iterator,
61: ConstPool cp) throws BadBytecode {
62: int c = iterator.byteAt(pos);
63: if (c == INVOKEINTERFACE || c == INVOKESPECIAL
64: || c == INVOKESTATIC || c == INVOKEVIRTUAL) {
65: int index = iterator.u16bitAt(pos + 1);
66: int typedesc = cp.isMember(classname, methodname, index);
67: if (typedesc != 0)
68: if (cp.getUtf8Info(typedesc).equals(methodDescriptor))
69: pos = match(c, pos, iterator, typedesc, cp);
70: }
71:
72: return pos;
73: }
74:
75: protected int match(int c, int pos, CodeIterator iterator,
76: int typedesc, ConstPool cp) throws BadBytecode {
77: if (newIndex == 0) {
78: int nt = cp.addNameAndTypeInfo(cp
79: .addUtf8Info(newMethodname), typedesc);
80: int ci = cp.addClassInfo(newClassname);
81: if (c == INVOKEINTERFACE)
82: newIndex = cp.addInterfaceMethodrefInfo(ci, nt);
83: else {
84: if (newMethodIsPrivate && c == INVOKEVIRTUAL)
85: iterator.writeByte(INVOKESPECIAL, pos);
86:
87: newIndex = cp.addMethodrefInfo(ci, nt);
88: }
89:
90: constPool = cp;
91: }
92:
93: iterator.write16bit(newIndex, pos + 1);
94: return pos;
95: }
96: }
|