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.ClassVisitor;
007: import com.tc.asm.Label;
008: import com.tc.asm.MethodAdapter;
009: import com.tc.asm.MethodVisitor;
010: import com.tc.asm.Opcodes;
011: import com.tc.asm.Type;
012: import com.tc.object.SerializationUtil;
013: import com.tc.object.config.MethodSpec;
014:
015: public class DateMethodAdapter extends LogicalMethodAdapter {
016:
017: public DateMethodAdapter() {
018: super ();
019: }
020:
021: public DateMethodAdapter(String methodName, int instrumentationType) {
022: super (methodName, instrumentationType);
023: }
024:
025: public MethodVisitor adapt(ClassVisitor classVisitor) {
026: MethodVisitor mv = super .adapt(classVisitor);
027:
028: if (getOwnerSlashes().equals("java/sql/Timestamp")) {
029: return new TimestampMethodAdapter(mv);
030: }
031: return mv;
032: }
033:
034: protected void createWrapperMethod(ClassVisitor classVisitor) {
035: switch (getInstrumentationType()) {
036: case MethodSpec.DATE_ADD_SET_TIME_WRAPPER_LOG:
037: addSetTimeMethodWrapper(classVisitor);
038: break;
039: case MethodSpec.TIMESTAMP_SET_TIME_METHOD_WRAPPER_LOG:
040: addTimestampSetTimeMethodWrapper(classVisitor);
041: break;
042: default:
043: super .createWrapperMethod(classVisitor);
044: }
045: }
046:
047: private class TimestampMethodAdapter extends MethodAdapter
048: implements Opcodes {
049: public TimestampMethodAdapter(MethodVisitor mv) {
050: super (mv);
051: }
052:
053: public void visitMethodInsn(int opcode, String owner,
054: String name, String desc) {
055: if ((opcode == INVOKESPECIAL) && ("setTime".equals(name))) {
056: super .visitMethodInsn(opcode, owner,
057: ByteCodeUtil.TC_METHOD_PREFIX + name, desc);
058: } else {
059: super .visitMethodInsn(opcode, owner, name, desc);
060: }
061: }
062: }
063:
064: private void addTimestampSetTimeMethodWrapper(
065: ClassVisitor classVisitor) {
066: MethodVisitor mv = classVisitor.visitMethod(getWrapperAccess(),
067: getMethodName(), getDescription(), getSignature(),
068: getExceptions());
069: addCheckWriteAccessInstrumentedCode(mv, true);
070: Label l0 = new Label();
071: mv.visitLabel(l0);
072: ByteCodeUtil.pushThis(mv);
073: Type[] params = Type.getArgumentTypes(getDescription());
074: Type returnType = Type.getReturnType(getDescription());
075: for (int i = 0; i < params.length; i++) {
076: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
077: }
078:
079: mv.visitMethodInsn(INVOKESPECIAL, getOwnerSlashes(),
080: getNewName(), getDescription());
081: if (!returnType.equals(Type.VOID_TYPE)) {
082: mv.visitVarInsn(returnType.getOpcode(ISTORE),
083: params.length + 1);
084: }
085: ByteCodeUtil.pushThis(mv);
086: mv.visitLdcInsn(getMethodName() + getDescription());
087:
088: ByteCodeUtil.createParametersToArrayByteCode(mv, params);
089: getManagerHelper().callManagerMethod("logicalInvoke", mv);
090:
091: ByteCodeUtil.pushThis(mv);
092: mv.visitLdcInsn("setNanos(I)V");
093: mv.visitInsn(ICONST_1);
094: mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
095: mv.visitInsn(DUP);
096: mv.visitInsn(ICONST_0);
097: mv.visitTypeInsn(NEW, "java/lang/Integer");
098: mv.visitInsn(DUP);
099: ByteCodeUtil.pushThis(mv);
100: mv.visitMethodInsn(INVOKESPECIAL, getOwnerSlashes(),
101: "getNanos", "()I");
102: mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer",
103: "<init>", "(I)V");
104: mv.visitInsn(AASTORE);
105: getManagerHelper().callManagerMethod("logicalInvoke", mv);
106:
107: if (!returnType.equals(Type.VOID_TYPE)) {
108: mv.visitVarInsn(returnType.getOpcode(ILOAD),
109: params.length + 1);
110: }
111: mv.visitInsn(returnType.getOpcode(IRETURN));
112: mv.visitMaxs(0, 0);
113:
114: }
115:
116: private void addSetTimeMethodWrapper(ClassVisitor classVisitor) {
117: MethodVisitor mv = classVisitor.visitMethod(getWrapperAccess(),
118: getMethodName(), getDescription(), getSignature(),
119: getExceptions());
120: addCheckWriteAccessInstrumentedCode(mv, true);
121: Label l0 = new Label();
122: mv.visitLabel(l0);
123: ByteCodeUtil.pushThis(mv);
124: Type[] params = Type.getArgumentTypes(getDescription());
125: Type returnType = Type.getReturnType(getDescription());
126: for (int i = 0; i < params.length; i++) {
127: mv.visitVarInsn(params[i].getOpcode(ILOAD), i + 1);
128: }
129:
130: mv.visitMethodInsn(INVOKESPECIAL, getOwnerSlashes(),
131: getNewName(), getDescription());
132:
133: addSetTimeInstrumentedCode(mv, params.length + 1);
134:
135: mv.visitInsn(returnType.getOpcode(IRETURN));
136: mv.visitMaxs(0, 0);
137: }
138:
139: private void addSetTimeInstrumentedCode(MethodVisitor mv,
140: int variableOffset) {
141: String getTimeDescription = "()J";
142: Type getTimeReturnType = Type.getReturnType(getTimeDescription);
143: ByteCodeUtil.pushThis(mv);
144: mv.visitMethodInsn(INVOKESPECIAL, getOwnerSlashes(), "getTime",
145: getTimeDescription);
146: mv.visitVarInsn(getTimeReturnType.getOpcode(ISTORE),
147: variableOffset);
148:
149: String setTimeDescription = "(J)V";
150: Type[] setTimeParams = Type
151: .getArgumentTypes(setTimeDescription);
152:
153: ByteCodeUtil.pushThis(mv);
154: mv.visitLdcInsn(SerializationUtil.SET_TIME_SIGNATURE);
155:
156: ByteCodeUtil.createParametersToArrayByteCode(mv, setTimeParams,
157: variableOffset);
158:
159: getManagerHelper().callManagerMethod("logicalInvoke", mv);
160: }
161:
162: }
|