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.aspectwerkz.transform.inlining.weaver;
005:
006: import com.tc.asm.ClassAdapter;
007: import com.tc.asm.ClassVisitor;
008: import com.tc.asm.MethodVisitor;
009: import com.tc.asm.Type;
010:
011: import com.tc.aspectwerkz.joinpoint.management.JoinPointType;
012: import com.tc.aspectwerkz.transform.InstrumentationContext;
013: import com.tc.aspectwerkz.transform.TransformationConstants;
014: import com.tc.aspectwerkz.transform.TransformationUtil;
015: import com.tc.aspectwerkz.transform.inlining.AsmHelper;
016: import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint;
017:
018: import java.util.Set;
019:
020: /**
021: * Adds a "proxy method" to the <tt><clinit></tt> that matches an
022: * <tt>staticinitialization</tt> pointcut as well as prefixing the "original method"
023: * (see {@link com.tc.aspectwerkz.transform.TransformationUtil#getPrefixedOriginalClinitName(String)}).
024: * <br/>
025: *
026: * @author <a href="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
027: */
028: public class StaticInitializationVisitor extends ClassAdapter implements
029: TransformationConstants {
030:
031: private final InstrumentationContext m_ctx;
032: private String m_declaringTypeName;
033: private final Set m_addedMethods;
034:
035: /**
036: * Creates a new class adapter.
037: *
038: * @param cv
039: * @param ctx
040: * @param addedMethods already added methods by AW
041: */
042: public StaticInitializationVisitor(final ClassVisitor cv,
043: final InstrumentationContext ctx, final Set addedMethods) {
044: super (cv);
045: m_ctx = (InstrumentationContext) ctx;
046: m_addedMethods = addedMethods;
047: }
048:
049: /**
050: * Visits the class.
051: *
052: * @param access
053: * @param name
054: * @param signature
055: * @param superName
056: * @param interfaces
057: */
058: public void visit(final int version, final int access,
059: final String name, final String signature,
060: final String super Name, final String[] interfaces) {
061: m_declaringTypeName = name;
062: super .visit(version, access, name, signature, super Name,
063: interfaces);
064: }
065:
066: /**
067: * Visits the methods.
068: *
069: * @param access
070: * @param name
071: * @param desc
072: * @param signature
073: * @param exceptions
074: * @return
075: */
076: public MethodVisitor visitMethod(final int access,
077: final String name, final String desc,
078: final String signature, final String[] exceptions) {
079: if (!CLINIT_METHOD_NAME.equals(name)) {
080: return super .visitMethod(access, name, desc, signature,
081: exceptions);
082: }
083:
084: String prefixedOriginalName = TransformationUtil
085: .getPrefixedOriginalClinitName(m_declaringTypeName);
086: if (m_addedMethods.contains(AlreadyAddedMethodAdapter
087: .getMethodKey(prefixedOriginalName,
088: CLINIT_METHOD_SIGNATURE))) {
089: return super .visitMethod(access, name, desc, signature,
090: exceptions);
091: }
092:
093: m_ctx.markAsAdvised();
094:
095: // create the proxy for the original method
096: createProxyMethod(access, name, desc, signature, exceptions);
097:
098: // prefix the original method
099: return cv.visitMethod(access + ACC_PUBLIC,
100: prefixedOriginalName, desc, signature, exceptions);
101: }
102:
103: /**
104: * Creates the "proxy method", e.g. the method that has the same name and
105: * signature as the original method but a completely other implementation.
106: *
107: * @param access
108: * @param name
109: * @param desc
110: * @param signature
111: * @param exceptions
112: */
113: private void createProxyMethod(final int access, final String name,
114: final String desc, final String signature,
115: final String[] exceptions) {
116: MethodVisitor mv = cv.visitMethod(access, name, desc,
117: signature, exceptions);
118:
119: //caller instance is null
120: mv.visitInsn(ACONST_NULL);
121:
122: int joinPointHash = AsmHelper.calculateMethodHash(name, desc);
123: String joinPointClassName = TransformationUtil
124: .getJoinPointClassName(m_declaringTypeName, name, desc,
125: m_declaringTypeName,
126: JoinPointType.STATIC_INITIALIZATION_INT,
127: joinPointHash);
128:
129: mv.visitMethodInsn(INVOKESTATIC, joinPointClassName,
130: INVOKE_METHOD_NAME, TransformationUtil
131: .getInvokeSignatureForCodeJoinPoints(access,
132: desc, m_declaringTypeName,
133: m_declaringTypeName));
134:
135: AsmHelper.addReturnStatement(mv, Type.VOID_TYPE);
136: mv.visitMaxs(0, 0);
137:
138: // emit the joinpoint
139: m_ctx.addEmittedJoinPoint(new EmittedJoinPoint(
140: JoinPointType.STATIC_INITIALIZATION_INT,
141: m_declaringTypeName, name, desc, access,
142: m_declaringTypeName, name, desc, access, joinPointHash,
143: joinPointClassName, EmittedJoinPoint.NO_LINE_NUMBER));
144: }
145: }
|