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.MethodAdapter;
011: import com.tc.asm.MethodVisitor;
012: import com.tc.asm.Opcodes;
013:
014: import java.lang.reflect.Modifier;
015:
016: public class JavaUtilTreeMapAdapter extends ClassAdapter implements
017: Opcodes {
018:
019: public JavaUtilTreeMapAdapter(ClassVisitor cv) {
020: super (cv);
021: }
022:
023: public MethodVisitor visitMethod(int access, String name,
024: String desc, String signature, String[] exceptions) {
025: MethodVisitor mv = super .visitMethod(access, name, desc,
026: signature, exceptions);
027: if ("writeObject".equals(name) && Modifier.isPrivate(access)) {
028: return new WriteObjectAdapter(mv);
029: }
030:
031: return mv;
032: }
033:
034: public void visitEnd() {
035: addRemoveEntryForKey();
036: super .visitEnd();
037: }
038:
039: private void addRemoveEntryForKey() {
040: MethodVisitor mv = super .visitMethod(ACC_SYNTHETIC,
041: "removeEntryForKey",
042: "(Ljava/lang/Object;)Ljava/util/TreeMap$Entry;", null,
043: null);
044: mv.visitCode();
045: mv.visitVarInsn(ALOAD, 0);
046: mv.visitVarInsn(ALOAD, 1);
047: mv.visitMethodInsn(INVOKESPECIAL, "java/util/TreeMap",
048: "getEntry",
049: "(Ljava/lang/Object;)Ljava/util/TreeMap$Entry;");
050: mv.visitVarInsn(ASTORE, 2);
051: mv.visitVarInsn(ALOAD, 2);
052: Label entryNotNull = new Label();
053: mv.visitJumpInsn(IFNONNULL, entryNotNull);
054: mv.visitInsn(ACONST_NULL);
055: mv.visitInsn(ARETURN);
056: mv.visitLabel(entryNotNull);
057: mv.visitTypeInsn(NEW, "java/util/TreeMap$Entry");
058: mv.visitInsn(DUP);
059: mv.visitVarInsn(ALOAD, 2);
060: mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/TreeMap$Entry",
061: "getKey", "()Ljava/lang/Object;");
062: mv.visitVarInsn(ALOAD, 2);
063: mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/TreeMap$Entry",
064: "getValue", "()Ljava/lang/Object;");
065: mv.visitInsn(ACONST_NULL);
066: mv
067: .visitMethodInsn(INVOKESPECIAL,
068: "java/util/TreeMap$Entry", "<init>",
069: "(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/TreeMap$Entry;)V");
070: mv.visitVarInsn(ASTORE, 3);
071: mv.visitVarInsn(ALOAD, 0);
072: mv.visitVarInsn(ALOAD, 2);
073: mv.visitMethodInsn(INVOKESPECIAL, "java/util/TreeMap",
074: "deleteEntry", "(Ljava/util/TreeMap$Entry;)V");
075: mv.visitVarInsn(ALOAD, 3);
076: mv.visitInsn(ARETURN);
077: mv.visitMaxs(0, 0);
078: mv.visitEnd();
079: }
080:
081: private static class WriteObjectAdapter extends MethodAdapter
082: implements Opcodes {
083:
084: public WriteObjectAdapter(MethodVisitor mv) {
085: super (mv);
086: }
087:
088: public void visitFieldInsn(int opcode, String owner,
089: String name, String desc) {
090: if (opcode == GETFIELD) {
091: if ("java/util/TreeMap$Entry".equals(owner)) {
092: if ("key".equals(name)) {
093: mv.visitMethodInsn(INVOKEINTERFACE,
094: "java/util/Map$Entry", "getKey",
095: "()Ljava/lang/Object;");
096: } else if ("value".equals(name)) {
097: mv.visitMethodInsn(INVOKEINTERFACE,
098: "java/util/Map$Entry", "getValue",
099: "()Ljava/lang/Object;");
100: } else {
101: throw new AssertionError("unknown field name: "
102: + name);
103: }
104: return;
105: }
106: }
107:
108: super .visitFieldInsn(opcode, owner, name, desc);
109: }
110:
111: public void visitTypeInsn(int opcode, String desc) {
112: if (CHECKCAST == opcode) {
113: if ("java/util/TreeMap$Entry".equals(desc)) {
114: super .visitTypeInsn(opcode, "java/util/Map$Entry");
115: return;
116: }
117: }
118:
119: super.visitTypeInsn(opcode, desc);
120: }
121:
122: }
123:
124: }
|