1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999- 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 * or the Apache License Version 2.0. 10 * 11 * Software distributed under the License is distributed on an "AS IS" basis, 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 * for the specific language governing rights and limitations under the 14 * License. 15 */ 16 17 package javassist.convert; 18 19 import javassist.ClassPool; 20 import javassist.CtClass; 21 import javassist.CtField; 22 import javassist.Modifier; 23 import javassist.NotFoundException; 24 import javassist.bytecode.BadBytecode; 25 import javassist.bytecode.CodeIterator; 26 import javassist.bytecode.ConstPool; 27 28 public class TransformReadField extends Transformer { 29 protected String fieldname; 30 protected CtClass fieldClass; 31 protected boolean isPrivate; 32 protected String methodClassname, methodName; 33 TransformReadField(Transformer next, CtField field, String methodClassname, String methodName)34 public TransformReadField(Transformer next, CtField field, 35 String methodClassname, String methodName) 36 { 37 super(next); 38 this.fieldClass = field.getDeclaringClass(); 39 this.fieldname = field.getName(); 40 this.methodClassname = methodClassname; 41 this.methodName = methodName; 42 this.isPrivate = Modifier.isPrivate(field.getModifiers()); 43 } 44 isField(ClassPool pool, ConstPool cp, CtClass fclass, String fname, boolean is_private, int index)45 static String isField(ClassPool pool, ConstPool cp, CtClass fclass, 46 String fname, boolean is_private, int index) { 47 if (!cp.getFieldrefName(index).equals(fname)) 48 return null; 49 50 try { 51 CtClass c = pool.get(cp.getFieldrefClassName(index)); 52 if (c == fclass || (!is_private && isFieldInSuper(c, fclass, fname))) 53 return cp.getFieldrefType(index); 54 } 55 catch (NotFoundException e) {} 56 return null; 57 } 58 isFieldInSuper(CtClass clazz, CtClass fclass, String fname)59 static boolean isFieldInSuper(CtClass clazz, CtClass fclass, String fname) { 60 if (!clazz.subclassOf(fclass)) 61 return false; 62 63 try { 64 CtField f = clazz.getField(fname); 65 return f.getDeclaringClass() == fclass; 66 } 67 catch (NotFoundException e) {} 68 return false; 69 } 70 71 @Override transform(CtClass tclazz, int pos, CodeIterator iterator, ConstPool cp)72 public int transform(CtClass tclazz, int pos, CodeIterator iterator, 73 ConstPool cp) throws BadBytecode 74 { 75 int c = iterator.byteAt(pos); 76 if (c == GETFIELD || c == GETSTATIC) { 77 int index = iterator.u16bitAt(pos + 1); 78 String typedesc = isField(tclazz.getClassPool(), cp, 79 fieldClass, fieldname, isPrivate, index); 80 if (typedesc != null) { 81 if (c == GETSTATIC) { 82 iterator.move(pos); 83 pos = iterator.insertGap(1); // insertGap() may insert 4 bytes. 84 iterator.writeByte(ACONST_NULL, pos); 85 pos = iterator.next(); 86 } 87 88 String type = "(Ljava/lang/Object;)" + typedesc; 89 int mi = cp.addClassInfo(methodClassname); 90 int methodref = cp.addMethodrefInfo(mi, methodName, type); 91 iterator.writeByte(INVOKESTATIC, pos); 92 iterator.write16bit(methodref, pos + 1); 93 return pos; 94 } 95 } 96 97 return pos; 98 } 99 } 100