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.ClassAdapter;
007: import com.tc.asm.ClassVisitor;
008: import com.tc.asm.Label;
009: import com.tc.asm.MethodAdapter;
010: import com.tc.asm.MethodVisitor;
011: import com.tc.asm.Opcodes;
012:
013: public class LogicalClassSerializationAdapter implements Opcodes {
014: public static final String SERIALIZATION_OVERRIDE_METHOD_NAME = ByteCodeUtil.TC_METHOD_PREFIX
015: + "isSerializationOverride";
016: public static final String SERIALIZATION_OVERRIDE_METHOD_DESC = "()Z";
017: public static final String WRITE_OBJECT_SIGNATURE = "writeObject(Ljava/io/ObjectOutputStream;)V";
018: public static final String READ_OBJECT_SIGNATURE = "readObject(Ljava/io/ObjectInputStream;)V";
019:
020: public static void addCheckSerializationOverrideMethod(
021: ClassVisitor cv, boolean returnValue) {
022: MethodVisitor mv = cv.visitMethod(ACC_PROTECTED,
023: SERIALIZATION_OVERRIDE_METHOD_NAME,
024: SERIALIZATION_OVERRIDE_METHOD_DESC, null, null);
025: mv.visitCode();
026: if (returnValue) {
027: mv.visitInsn(ICONST_1);
028: } else {
029: mv.visitInsn(ICONST_0);
030: }
031: mv.visitInsn(IRETURN);
032: mv.visitMaxs(1, 1);
033: mv.visitEnd();
034: }
035:
036: public static void addDelegateFieldWriteObjectCode(
037: MethodVisitor mv, String classNameSlashes,
038: String logicalExtendingClassName, String delegateFieldName) {
039: mv.visitVarInsn(ALOAD, 1);
040: mv.visitVarInsn(ALOAD, 0);
041: mv.visitMethodInsn(INVOKESPECIAL, classNameSlashes,
042: ByteCodeUtil.fieldGetterMethod(delegateFieldName),
043: "()L" + logicalExtendingClassName + ";");
044: mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/ObjectOutputStream",
045: "writeObject", "(Ljava/lang/Object;)V");
046: }
047:
048: public static void addDelegateFieldReadObjectCode(MethodVisitor mv,
049: String classNameSlashes, String logicalExtendingClassName,
050: String delegateFieldName) {
051: mv.visitVarInsn(ALOAD, 0);
052: mv.visitVarInsn(ALOAD, 1);
053: mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/ObjectInputStream",
054: "readObject", "()Ljava/lang/Object;");
055: mv.visitTypeInsn(CHECKCAST, logicalExtendingClassName);
056: mv.visitMethodInsn(INVOKESPECIAL, classNameSlashes,
057: ByteCodeUtil.fieldSetterMethod(delegateFieldName), "(L"
058: + logicalExtendingClassName + ";)V");
059: }
060:
061: public static class LogicalClassSerializationMethodAdapter extends
062: MethodAdapter implements Opcodes {
063: private final String classNameSlashes;
064:
065: public LogicalClassSerializationMethodAdapter(MethodVisitor mv,
066: String classNameSlashes) {
067: super (mv);
068: this .classNameSlashes = classNameSlashes;
069: }
070:
071: public void visitCode() {
072: super .visitCode();
073:
074: mv.visitVarInsn(ALOAD, 0);
075: mv.visitMethodInsn(INVOKEVIRTUAL, classNameSlashes,
076: SERIALIZATION_OVERRIDE_METHOD_NAME,
077: SERIALIZATION_OVERRIDE_METHOD_DESC);
078: Label l1 = new Label();
079: mv.visitJumpInsn(IFEQ, l1);
080: mv.visitInsn(RETURN);
081: visitLabel(l1);
082: }
083: }
084:
085: public static class LogicalSubclassSerializationMethodAdapter
086: extends MethodAdapter implements Opcodes {
087: private final String methodSignature;
088: private final String classNameSlashes;
089: private final String logicalExtendingClassName;
090: private final String delegateFieldName;
091:
092: public LogicalSubclassSerializationMethodAdapter(
093: MethodVisitor mv, String methodSignature,
094: String classNameSlashes,
095: String logicalExtendingClassName,
096: String delegateFieldName) {
097: super (mv);
098: this .methodSignature = methodSignature;
099: this .classNameSlashes = classNameSlashes;
100: this .logicalExtendingClassName = logicalExtendingClassName;
101: this .delegateFieldName = delegateFieldName;
102: }
103:
104: public void visitCode() {
105: super .visitCode();
106: if (WRITE_OBJECT_SIGNATURE.equals(methodSignature)) {
107: addDelegateFieldWriteObjectCode(mv, classNameSlashes,
108: logicalExtendingClassName, delegateFieldName);
109: } else if (READ_OBJECT_SIGNATURE.equals(methodSignature)) {
110: addDelegateFieldReadObjectCode(mv, classNameSlashes,
111: logicalExtendingClassName, delegateFieldName);
112: }
113: }
114: }
115:
116: public static class LogicalClassSerializationClassAdapter extends
117: ClassAdapter implements Opcodes {
118: private final String classNameSlashes;
119:
120: public LogicalClassSerializationClassAdapter(ClassVisitor cv,
121: String className) {
122: super (cv);
123: this .classNameSlashes = className.replace(
124: ChangeClassNameHierarchyAdapter.DOT_DELIMITER,
125: ChangeClassNameHierarchyAdapter.SLASH_DELIMITER);
126: }
127:
128: public MethodVisitor visitMethod(int access, String name,
129: String desc, String signature, String[] exceptions) {
130: String methodDesc = name + desc;
131: if (WRITE_OBJECT_SIGNATURE.equals(methodDesc)
132: || READ_OBJECT_SIGNATURE.equals(methodDesc)) { //
133: return new LogicalClassSerializationAdapter.LogicalClassSerializationMethodAdapter(
134: super .visitMethod(access, name, desc,
135: signature, exceptions),
136: classNameSlashes);
137: }
138:
139: return super .visitMethod(access, name, desc, signature,
140: exceptions);
141: }
142:
143: public void visitEnd() {
144: addCheckSerializationOverrideMethod(cv, false);
145: super.visitEnd();
146: }
147: }
148:
149: }
|