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.ClassPool; 20import javassist.CtClass; 21import javassist.CtField; 22import javassist.NotFoundException; 23import javassist.Modifier; 24 25public class TransformReadField extends Transformer { 26 protected String fieldname; 27 protected CtClass fieldClass; 28 protected boolean isPrivate; 29 protected String methodClassname, methodName; 30 31 public TransformReadField(Transformer next, CtField field, 32 String methodClassname, String methodName) 33 { 34 super(next); 35 this.fieldClass = field.getDeclaringClass(); 36 this.fieldname = field.getName(); 37 this.methodClassname = methodClassname; 38 this.methodName = methodName; 39 this.isPrivate = Modifier.isPrivate(field.getModifiers()); 40 } 41 42 static String isField(ClassPool pool, ConstPool cp, CtClass fclass, 43 String fname, boolean is_private, int index) { 44 if (!cp.getFieldrefName(index).equals(fname)) 45 return null; 46 47 try { 48 CtClass c = pool.get(cp.getFieldrefClassName(index)); 49 if (c == fclass || (!is_private && isFieldInSuper(c, fclass, fname))) 50 return cp.getFieldrefType(index); 51 } 52 catch (NotFoundException e) {} 53 return null; 54 } 55 56 static boolean isFieldInSuper(CtClass clazz, CtClass fclass, String fname) { 57 if (!clazz.subclassOf(fclass)) 58 return false; 59 60 try { 61 CtField f = clazz.getField(fname); 62 return f.getDeclaringClass() == fclass; 63 } 64 catch (NotFoundException e) {} 65 return false; 66 } 67 68 public int transform(CtClass tclazz, int pos, CodeIterator iterator, 69 ConstPool cp) throws BadBytecode 70 { 71 int c = iterator.byteAt(pos); 72 if (c == GETFIELD || c == GETSTATIC) { 73 int index = iterator.u16bitAt(pos + 1); 74 String typedesc = isField(tclazz.getClassPool(), cp, 75 fieldClass, fieldname, isPrivate, index); 76 if (typedesc != null) { 77 if (c == GETSTATIC) { 78 iterator.move(pos); 79 pos = iterator.insertGap(1); // insertGap() may insert 4 bytes. 80 iterator.writeByte(ACONST_NULL, pos); 81 pos = iterator.next(); 82 } 83 84 String type = "(Ljava/lang/Object;)" + typedesc; 85 int mi = cp.addClassInfo(methodClassname); 86 int methodref = cp.addMethodrefInfo(mi, methodName, type); 87 iterator.writeByte(INVOKESTATIC, pos); 88 iterator.write16bit(methodref, pos + 1); 89 return pos; 90 } 91 } 92 93 return pos; 94 } 95} 96