• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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