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.aspect.container;
005:
006: import com.tc.asm.MethodVisitor;
007: import com.tc.asm.Label;
008: import com.tc.asm.Type;
009:
010: import com.tc.aspectwerkz.aspect.AspectContainer;
011: import com.tc.aspectwerkz.aspect.management.NoAspectBoundException;
012:
013: /**
014: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
015: */
016: public class PerCflowXAspectFactoryCompiler extends
017: LazyPerXFactoryCompiler {
018:
019: public PerCflowXAspectFactoryCompiler(String uuid,
020: String aspectClassName, String aspectQualifiedName,
021: String containerClassName, String rawParameters,
022: ClassLoader loader) {
023: super (uuid, aspectClassName, aspectQualifiedName,
024: containerClassName, rawParameters, loader);
025: }
026:
027: protected String getXSignature() {
028: return "Ljava/lang/Thread;";
029: }
030:
031: /**
032: * Overrides the aspectOf() method to not do lazy aspect instantiation since controlled by bind()/unbind()
033: */
034: protected void createAspectOf() {
035: m_cw.visitField(ACC_PRIVATE + ACC_STATIC, "ASPECTS",
036: MAP_CLASS_SIGNATURE, null, null);
037:
038: m_clinit.visitTypeInsn(NEW, MAP_CLASS_NAME);
039: m_clinit.visitInsn(DUP);
040: m_clinit.visitMethodInsn(INVOKESPECIAL,
041: "java/util/WeakHashMap", INIT_METHOD_NAME, "()V");
042: m_clinit.visitFieldInsn(PUTSTATIC, m_aspectFactoryClassName,
043: "ASPECTS", MAP_CLASS_SIGNATURE);
044:
045: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC + ACC_STATIC
046: + ACC_FINAL, "aspectOf", "(" + getXSignature() + ")"
047: + m_aspectClassSignature, null, null);
048:
049: cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName,
050: "ASPECTS", MAP_CLASS_SIGNATURE);
051: cv.visitVarInsn(ALOAD, 0);//Thread
052: cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME,
053: "getDefault", "(Ljava/lang/Object;)Ljava/lang/Object;");
054: cv.visitVarInsn(ASTORE, 1);
055: cv.visitVarInsn(ALOAD, 1);
056: Label ifBound = new Label();
057: cv.visitJumpInsn(IFNONNULL, ifBound);
058: cv.visitTypeInsn(NEW, Type
059: .getInternalName(NoAspectBoundException.class));
060: cv.visitInsn(DUP);
061: cv.visitLdcInsn("Not bound");
062: cv.visitLdcInsn(m_aspectQualifiedName);
063: cv.visitMethodInsn(INVOKESPECIAL,
064: NO_ASPECT_BOUND_EXCEPTION_CLASS_NAME, INIT_METHOD_NAME,
065: "(Ljava/lang/String;Ljava/lang/String;)V");
066: cv.visitInsn(ATHROW);
067:
068: cv.visitLabel(ifBound);
069: cv.visitVarInsn(ALOAD, 1);
070: cv.visitTypeInsn(CHECKCAST, m_aspectClassName);
071: cv.visitInsn(ARETURN);
072:
073: // create an implicit Thread.currentThread no arg aspectOf() method
074: cv = m_cw.visitMethod(ACC_STATIC + ACC_PUBLIC + ACC_FINAL,
075: "aspectOf", "()" + m_aspectClassSignature, null, null);
076: cv.visitMethodInsn(INVOKESTATIC, Type
077: .getInternalName(Thread.class), "currentThread",
078: "()Ljava/lang/Thread;");
079: cv.visitMethodInsn(INVOKESTATIC, m_aspectFactoryClassName,
080: "aspectOf", "(Ljava/lang/Thread;)" + getXSignature());
081: cv.visitInsn(ARETURN);
082: cv.visitMaxs(0, 0);
083: }
084:
085: protected void createOtherArtifacts() {
086: createBindMethod();
087: createUnbindMethod();
088: }
089:
090: private void createBindMethod() {
091: //FIXME AVF do not bind if already present
092: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC + ACC_STATIC
093: + ACC_FINAL, "bind", "(" + getXSignature() + ")V",
094: null, null);
095:
096: cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName,
097: "ASPECTS", MAP_CLASS_SIGNATURE);
098: if (m_hasAspectContainer) {
099: cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName,
100: "CONTAINER", Type
101: .getDescriptor(AspectContainer.class));
102: cv.visitMethodInsn(INVOKEINTERFACE, Type
103: .getInternalName(AspectContainer.class),
104: "aspectOf", "(" + getXSignature()
105: + ")Ljava/lang/Object;");
106: cv.visitTypeInsn(CHECKCAST, m_aspectClassName);
107: } else {
108: cv.visitTypeInsn(NEW, m_aspectClassName);
109: cv.visitInsn(DUP);
110: cv.visitMethodInsn(INVOKESPECIAL, m_aspectClassName,
111: INIT_METHOD_NAME, "()V");
112: }
113: cv.visitVarInsn(ALOAD, 0);//Thread
114: cv
115: .visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME,
116: "put",
117: "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
118: cv.visitInsn(POP);
119: cv.visitInsn(RETURN);
120: cv.visitMaxs(0, 0);
121: }
122:
123: private void createUnbindMethod() {
124: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC + ACC_STATIC
125: + ACC_FINAL, "unbind", "(" + getXSignature() + ")V",
126: null, null);
127:
128: cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName,
129: "ASPECTS", MAP_CLASS_SIGNATURE);
130: cv.visitVarInsn(ALOAD, 0);//Thread
131: cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, "remove",
132: "(Ljava/lang/Object;)Ljava/lang/Object;");
133: cv.visitInsn(POP);
134: cv.visitInsn(RETURN);
135: cv.visitMaxs(0, 0);
136: }
137: }
|