001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.bytecode;
006:
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.object.TCObject;
014:
015: import java.lang.reflect.AccessibleObject;
016:
017: public class AccessibleObjectAdapter extends ClassAdapter implements
018: Opcodes {
019:
020: public AccessibleObjectAdapter(ClassVisitor cv) {
021: super (cv);
022: }
023:
024: public MethodVisitor visitMethod(int access, String name,
025: String desc, String signature, String[] exceptions) {
026: MethodVisitor mv = super .visitMethod(access, name, desc,
027: signature, exceptions);
028: if ("setAccessible0".equals(name)
029: && "(Ljava/lang/reflect/AccessibleObject;Z)V"
030: .equals(desc)) {
031: return new AccessibleSetAccessibleMethodVisitor(mv);
032: }
033:
034: return mv;
035: }
036:
037: private static class AccessibleSetAccessibleMethodVisitor extends
038: MaxLocalVarStoreDetectingMethodAdapter {
039:
040: private AccessibleSetAccessibleMethodVisitor(MethodVisitor mv) {
041: super (mv);
042: }
043:
044: public void visitFieldInsn(int opcode, String owner,
045: String name, String desc) {
046: if (PUTFIELD == opcode
047: && owner.equals(Type
048: .getInternalName(AccessibleObject.class))
049: && name.equals("override") && desc.equals("Z")) {
050:
051: int boolean_var_store = getMaxLocalVarStore() + 1;
052: int tcobject_var_store = boolean_var_store + 1;
053:
054: // make a copy of the boolean that's currently on the stack,
055: // ready to be assigned to the 'override' field
056: mv.visitInsn(DUP);
057:
058: // store the boolean value in the appropriate local variable slot
059: mv.visitVarInsn(ISTORE, boolean_var_store);
060:
061: // load the reference to the currently executing object instance
062: mv.visitVarInsn(ALOAD, 0);
063:
064: // look up the TCObject from the TC manager that corresponds
065: // to the current object instance
066: mv.visitMethodInsn(INVOKESTATIC, Type
067: .getInternalName(ManagerUtil.class),
068: "lookupExistingOrNull",
069: "(Ljava/lang/Object;)Lcom/tc/object/TCObject;");
070:
071: // store the TCObject in the appropriate local variable slot
072: mv.visitVarInsn(ASTORE, tcobject_var_store);
073:
074: // check if the TCObject instance is null, and jump over the state
075: // modification code that follows
076: mv.visitVarInsn(ALOAD, tcobject_var_store);
077: Label label_tcobject_null = new Label();
078: mv.visitJumpInsn(IFNULL, label_tcobject_null);
079:
080: // if the TCObject instance is not null, obtain it again so
081: // that it can be used to signal the new value for the local 'override"
082: // variable
083: mv.visitVarInsn(ALOAD, tcobject_var_store);
084: mv.visitLdcInsn(AccessibleObject.class.getName());
085: mv.visitLdcInsn(AccessibleObject.class.getName()
086: + ".override");
087: mv.visitVarInsn(ILOAD, boolean_var_store);
088: mv.visitInsn(ICONST_M1);
089: mv.visitMethodInsn(INVOKEINTERFACE, Type
090: .getInternalName(TCObject.class),
091: "booleanFieldChanged",
092: "(Ljava/lang/String;Ljava/lang/String;ZI)V");
093:
094: // label that is jumped to in case the TCObject instance is null
095: mv.visitLabel(label_tcobject_null);
096: }
097: super.visitFieldInsn(opcode, owner, name, desc);
098: }
099: }
100: }
|