001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.bytecode;
005:
006: import com.tc.asm.MethodAdapter;
007: import com.tc.asm.ClassAdapter;
008: import com.tc.asm.ClassVisitor;
009: import com.tc.asm.Label;
010: import com.tc.asm.MethodVisitor;
011: import com.tc.asm.Opcodes;
012: import com.tc.asm.Type;
013: import com.tc.util.FieldUtils;
014:
015: import java.util.HashSet;
016: import java.util.Set;
017:
018: public class JavaLangReflectFieldAdapter extends ClassAdapter implements
019: Opcodes, ClassAdapterFactory {
020:
021: private static final Set setters = new HashSet();
022: private static final Set getters = new HashSet();
023:
024: static {
025: getters.add("get(Ljava/lang/Object;)Ljava/lang/Object;");
026:
027: setters.add("set(Ljava/lang/Object;Ljava/lang/Object;)V");
028: setters.add("setByte(Ljava/lang/Object;B)V");
029: setters.add("setBoolean(Ljava/lang/Object;Z)V");
030: setters.add("setChar(Ljava/lang/Object;C)V");
031: setters.add("setDouble(Ljava/lang/Object;D)V");
032: setters.add("setFloat(Ljava/lang/Object;F)V");
033: setters.add("setInt(Ljava/lang/Object;I)V");
034: setters.add("setLong(Ljava/lang/Object;J)V");
035: setters.add("setShort(Ljava/lang/Object;S)V");
036: }
037:
038: public JavaLangReflectFieldAdapter() {
039: super (null);
040: }
041:
042: private JavaLangReflectFieldAdapter(ClassVisitor cv,
043: ClassLoader caller) {
044: super (cv);
045: }
046:
047: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
048: return new JavaLangReflectFieldAdapter(visitor, loader);
049: }
050:
051: public MethodVisitor visitMethod(int access, String name,
052: String desc, String signature, String[] exceptions) {
053: MethodVisitor mv = super .visitMethod(access, name, desc,
054: signature, exceptions);
055:
056: String method = name + desc;
057:
058: if (setters.contains(method)) {
059: return new FieldSetterMethodAdapter(mv, name, desc);
060: } else if (getters.contains(method)) {
061: rewriteGetter(mv, name, desc);
062: return null;
063: }
064:
065: return mv;
066: }
067:
068: private String getFieldUtilsSetterDesc(String desc) {
069: int index = desc.indexOf(")");
070: StringBuffer sb = new StringBuffer(desc.substring(0, index));
071: sb.append("Ljava/lang/reflect/Field;)Z");
072: return sb.toString();
073: }
074:
075: private void rewriteGetter(MethodVisitor mv, String name,
076: String desc) {
077: Type returnType = Type.getReturnType(desc);
078:
079: mv.visitCode();
080: mv.visitVarInsn(ALOAD, 1);
081: mv.visitVarInsn(ALOAD, 0);
082: mv.visitVarInsn(ALOAD, 0);
083: mv.visitVarInsn(ALOAD, 1);
084: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/reflect/Field",
085: "getFieldAccessor",
086: "(Ljava/lang/Object;)Lsun/reflect/FieldAccessor;");
087: mv.visitMethodInsn(INVOKESTATIC, FieldUtils.CLASS, name,
088: FieldUtils.GET_DESC + returnType.getDescriptor());
089: mv.visitInsn(returnType.getOpcode(IRETURN));
090: mv.visitMaxs(0, 0);
091: mv.visitEnd();
092: }
093:
094: private class FieldSetterMethodAdapter extends MethodAdapter
095: implements Opcodes {
096: private final String name;
097: private final String desc;
098:
099: public FieldSetterMethodAdapter(MethodVisitor mv, String name,
100: String desc) {
101: super (mv);
102: this .name = name;
103: this .desc = desc;
104: }
105:
106: public void visitCode() {
107: super .visitCode();
108: Type type = Type.getArgumentTypes(desc)[1];
109: Label notSet = new Label();
110: super .visitVarInsn(ALOAD, 1);
111: super .visitVarInsn(type.getOpcode(ILOAD), 2);
112: super .visitVarInsn(ALOAD, 0);
113: super.visitMethodInsn(INVOKESTATIC, FieldUtils.CLASS, name,
114: getFieldUtilsSetterDesc(desc));
115: super.visitJumpInsn(IFEQ, notSet);
116: super.visitInsn(RETURN);
117: super.visitLabel(notSet);
118: }
119: }
120: }
|