View Javadoc
1 package net.sf.cglib.transform.impl; 2 3 import net.sf.cglib.transform.*; 4 import net.sf.cglib.core.*; 5 import org.objectweb.asm.ClassVisitor; 6 import org.objectweb.asm.CodeAdapter; 7 import org.objectweb.asm.CodeVisitor; 8 import org.objectweb.asm.Attribute; 9 import org.objectweb.asm.Label; 10 import org.objectweb.asm.Type; 11 12 /*** 13 * @author Juozas Baliuka, Chris Nokleberg 14 */ 15 public class InterceptFieldTransformer extends ClassEmitterTransformer { 16 private static final String CALLBACK_FIELD = "$CGLIB_READ_WRITE_CALLBACK"; 17 private static final Type CALLBACK = 18 TypeUtils.parseType("net.sf.cglib.transform.impl.InterceptFieldCallback"); 19 private static final Type ENABLED = 20 TypeUtils.parseType("net.sf.cglib.transform.impl.InterceptFieldEnabled"); 21 private static final Signature ENABLED_SET = 22 TypeUtils.parseSignature("void setInterceptFieldCallback(net.sf.cglib.transform.impl.InterceptFieldCallback)"); 23 private static final Signature ENABLED_GET = 24 TypeUtils.parseSignature("net.sf.cglib.transform.impl.InterceptFieldCallback getInterceptFieldCallback()"); 25 26 private InterceptFieldFilter filter; 27 28 public InterceptFieldTransformer(InterceptFieldFilter filter) { 29 this.filter = filter; 30 } 31 32 public void begin_class(int access, String className, Type superType, Type[] interfaces, String sourceFile) { 33 if (!TypeUtils.isInterface(access)) { 34 super.begin_class(access, className, superType, TypeUtils.add(interfaces, ENABLED), sourceFile); 35 36 super.declare_field(Constants.ACC_PRIVATE | Constants.ACC_TRANSIENT, 37 CALLBACK_FIELD, 38 CALLBACK, 39 null, 40 null); 41 42 CodeEmitter e; 43 e = super.begin_method(Constants.ACC_PUBLIC, ENABLED_GET, null, null); 44 e.load_this(); 45 e.getfield(CALLBACK_FIELD); 46 e.return_value(); 47 e.end_method(); 48 49 e = super.begin_method(Constants.ACC_PUBLIC, ENABLED_SET, null, null); 50 e.load_this(); 51 e.load_arg(0); 52 e.putfield(CALLBACK_FIELD); 53 e.return_value(); 54 e.end_method(); 55 } else { 56 super.begin_class(access, className, superType, interfaces, sourceFile); 57 } 58 } 59 60 public void declare_field(int access, String name, Type type, Object value, Attribute attrs) { 61 super.declare_field(access, name, type, value, attrs); 62 if (!TypeUtils.isStatic(access)) { 63 if (filter.acceptRead(getClassType(), name)) { 64 addReadMethod(name, type); 65 } 66 if (filter.acceptWrite(getClassType(), name)) { 67 addWriteMethod(name, type); 68 } 69 } 70 } 71 72 private void addReadMethod(String name, Type type) { 73 CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, 74 readMethodSig(name, type.getDescriptor()), 75 null, 76 null); 77 e.load_this(); 78 e.getfield(name); 79 e.load_this(); 80 e.getfield(CALLBACK_FIELD); 81 Label intercept = e.make_label(); 82 e.ifnonnull(intercept); 83 e.return_value(); 84 85 e.mark(intercept); 86 Local result = e.make_local(type); 87 e.store_local(result); 88 e.load_this(); 89 e.getfield(CALLBACK_FIELD); 90 e.load_this(); 91 e.push(name); 92 e.load_local(result); 93 e.invoke_interface(CALLBACK, readCallbackSig(type)); 94 if (!TypeUtils.isPrimitive(type)) { 95 e.checkcast(type); 96 } 97 e.return_value(); 98 e.end_method(); 99 } 100 101 private void addWriteMethod(String name, Type type) { 102 CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, 103 writeMethodSig(name, type.getDescriptor()), 104 null, 105 null); 106 e.load_this(); 107 e.dup(); 108 e.getfield(CALLBACK_FIELD); 109 Label skip = e.make_label(); 110 e.ifnull(skip); 111 112 e.load_this(); 113 e.getfield(CALLBACK_FIELD); 114 e.load_this(); 115 e.push(name); 116 e.load_this(); 117 e.getfield(name); 118 e.load_arg(0); 119 e.invoke_interface(CALLBACK, writeCallbackSig(type)); 120 if (!TypeUtils.isPrimitive(type)) { 121 e.checkcast(type); 122 } 123 Label go = e.make_label(); 124 e.goTo(go); 125 e.mark(skip); 126 e.load_arg(0); 127 e.mark(go); 128 e.putfield(name); 129 e.return_value(); 130 e.end_method(); 131 } 132 133 public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions, Attribute attrs) { 134 return new CodeEmitter(super.begin_method(access, sig, exceptions, attrs)) { 135 public void visitFieldInsn(int opcode, String owner, String name, String desc) { 136 Type towner = TypeUtils.fromInternalName(owner); 137 switch (opcode) { 138 case Constants.GETFIELD: 139 if (filter.acceptRead(towner, name)) { 140 helper(towner, readMethodSig(name, desc)); 141 return; 142 } 143 break; 144 case Constants.PUTFIELD: 145 if (filter.acceptWrite(towner, name)) { 146 helper(towner, writeMethodSig(name, desc)); 147 return; 148 } 149 break; 150 } 151 super.visitFieldInsn(opcode, owner, name, desc); 152 } 153 154 private void helper(Type owner, Signature sig) { 155 invoke_virtual(owner, sig); 156 } 157 }; 158 } 159 160 private static Signature readMethodSig(String name, String desc) { 161 return new Signature("$cglib_read_" + name, "()" + desc); 162 } 163 164 private static Signature writeMethodSig(String name, String desc) { 165 return new Signature("$cglib_write_" + name, "(" + desc + ")V"); 166 } 167 168 private static Signature readCallbackSig(Type type) { 169 Type remap = remap(type); 170 return new Signature("read" + callbackName(remap), 171 remap, 172 new Type[]{ Constants.TYPE_OBJECT, 173 Constants.TYPE_STRING, 174 remap }); 175 } 176 177 private static Signature writeCallbackSig(Type type) { 178 Type remap = remap(type); 179 return new Signature("write" + callbackName(remap), 180 remap, 181 new Type[]{ Constants.TYPE_OBJECT, 182 Constants.TYPE_STRING, 183 remap, 184 remap }); 185 } 186 187 private static Type remap(Type type) { 188 switch (type.getSort()) { 189 case Type.OBJECT: 190 case Type.ARRAY: 191 return Constants.TYPE_OBJECT; 192 default: 193 return type; 194 } 195 } 196 197 private static String callbackName(Type type) { 198 return (type == Constants.TYPE_OBJECT) ? 199 "Object" : 200 TypeUtils.upperFirst(TypeUtils.getClassName(type)); 201 } 202 }

This page was automatically generated by Maven