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.ClassPool; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtField; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException; 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.Modifier; 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class TransformReadField extends Transformer { 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected String fieldname; 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected CtClass fieldClass; 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected boolean isPrivate; 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected String methodClassname, methodName; 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public TransformReadField(Transformer next, CtField field, 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String methodClassname, String methodName) 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(next); 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.fieldClass = field.getDeclaringClass(); 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.fieldname = field.getName(); 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.methodClassname = methodClassname; 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.methodName = methodName; 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.isPrivate = Modifier.isPrivate(field.getModifiers()); 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static String isField(ClassPool pool, ConstPool cp, CtClass fclass, 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String fname, boolean is_private, int index) { 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!cp.getFieldrefName(index).equals(fname)) 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass c = pool.get(cp.getFieldrefClassName(index)); 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == fclass || (!is_private && isFieldInSuper(c, fclass, fname))) 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cp.getFieldrefType(index); 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) {} 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static boolean isFieldInSuper(CtClass clazz, CtClass fclass, String fname) { 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!clazz.subclassOf(fclass)) 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtField f = clazz.getField(fname); 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return f.getDeclaringClass() == fclass; 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) {} 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int transform(CtClass tclazz, int pos, CodeIterator iterator, 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ConstPool cp) throws BadBytecode 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int c = iterator.byteAt(pos); 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == GETFIELD || c == GETSTATIC) { 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int index = iterator.u16bitAt(pos + 1); 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String typedesc = isField(tclazz.getClassPool(), cp, 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal fieldClass, fieldname, isPrivate, index); 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (typedesc != null) { 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == GETSTATIC) { 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.move(pos); 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = iterator.insertGap(1); // insertGap() may insert 4 bytes. 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.writeByte(ACONST_NULL, pos); 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pos = iterator.next(); 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String type = "(Ljava/lang/Object;)" + typedesc; 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int mi = cp.addClassInfo(methodClassname); 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int methodref = cp.addMethodrefInfo(mi, methodName, type); 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.writeByte(INVOKESTATIC, pos); 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal iterator.write16bit(methodref, pos + 1); 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pos; 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return pos; 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 96