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.model;
005:
006: import com.tc.asm.MethodVisitor;
007: import com.tc.asm.Type;
008:
009: import com.tc.aspectwerkz.aspect.AdviceType;
010: import com.tc.aspectwerkz.definition.AspectDefinition;
011: import com.tc.aspectwerkz.transform.inlining.AdviceMethodInfo;
012: import com.tc.aspectwerkz.transform.inlining.AsmHelper;
013: import com.tc.aspectwerkz.transform.inlining.compiler.CompilerInput;
014: import com.tc.aspectwerkz.transform.inlining.spi.AspectModel;
015: import com.tc.aspectwerkz.reflect.ClassInfo;
016:
017: /**
018: * Implementation of the AspectModel interface for Spring framework.
019: * <p/>
020: * Provides methods for definition of aspects and framework specific bytecode generation
021: * used by the join point compiler.
022: *
023: * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
024: */
025: public class SpringAspectModel extends AopAllianceAspectModel {
026:
027: protected static final String ASPECT_MODEL_TYPE = "spring";
028:
029: private static final String METHOD_INTERCEPTOR_CLASS = "org.aopalliance.intercept.MethodInterceptor";
030: private static final String AFTER_RETURNING_ADVICE_CLASS = "org.springframework.aop.AfterReturningAdvice";
031: private static final String METHOD_BEFORE_ADVICE_CLASS = "org.springframework.aop.MethodBeforeAdvice";
032: private static final String THROWS_ADVICE_CLASS = "org.springframework.aop.ThrowsAdvice";
033:
034: /**
035: * Returns the aspect model type, which is an id for the the special aspect model, can be anything as long
036: * as it is unique.
037: *
038: * @return the aspect model type id
039: */
040: public String getAspectModelType() {
041: return ASPECT_MODEL_TYPE;
042: }
043:
044: /**
045: * Defines the aspect.
046: */
047: public void defineAspect(final ClassInfo classInfo,
048: final AspectDefinition aspectDef, final ClassLoader loader) {
049: ClassInfo[] interfaces = classInfo.getInterfaces();
050: for (int i = 0; i < interfaces.length; i++) {
051: String name = interfaces[i].getName();
052: if (METHOD_INTERCEPTOR_CLASS.equals(name)
053: || METHOD_BEFORE_ADVICE_CLASS.equals(name)
054: || AFTER_RETURNING_ADVICE_CLASS.equals(name)
055: || THROWS_ADVICE_CLASS.equals(name)) {
056: aspectDef.setAspectModel(ASPECT_MODEL_TYPE);
057: aspectDef.setContainerClassName(null);
058: return;
059: }
060: }
061: }
062:
063: /**
064: * Returns info about the closure class, name and type (interface or class).
065: *
066: * @return the closure class info
067: */
068: public AroundClosureClassInfo getAroundClosureClassInfo() {
069: return new AspectModel.AroundClosureClassInfo(
070: null,
071: new String[] { AOP_ALLIANCE_CLOSURE_CLASS_NAME,
072: METHOD_BEFORE_ADVICE_CLASS.replace('.', '/'),
073: AFTER_RETURNING_ADVICE_CLASS.replace('.', '/') });
074: }
075:
076: public void createBeforeOrAfterAdviceArgumentHandling(
077: MethodVisitor methodVisitor, CompilerInput compilerInput,
078: Type[] types, AdviceMethodInfo adviceMethodInfo, int i) {
079: if (AdviceType.BEFORE.equals(adviceMethodInfo.getAdviceInfo()
080: .getType())) {
081: createBeforeAdviceArgumentHandling(methodVisitor,
082: adviceMethodInfo,
083: compilerInput.joinPointInstanceIndex);
084: } else {
085: // after advice no matter what
086: createAfterAdviceArgumentHandling(methodVisitor,
087: adviceMethodInfo,
088: compilerInput.joinPointInstanceIndex);
089: }
090: }
091:
092: /**
093: * Handles the arguments to the before advice.
094: */
095: public void createBeforeAdviceArgumentHandling(
096: final MethodVisitor cv,
097: final AdviceMethodInfo adviceMethodInfo,
098: final int joinPointInstanceIndex) {
099: final String joinPointClassName = adviceMethodInfo
100: .getJoinPointClassName();
101: final int joinPointIndex = joinPointInstanceIndex;
102: cv.visitFieldInsn(GETSTATIC, joinPointClassName,
103: SIGNATURE_FIELD_NAME,
104: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
105: cv.visitMethodInsn(INVOKEVIRTUAL,
106: METHOD_SIGNATURE_IMPL_CLASS_NAME,
107: GET_METHOD_METHOD_NAME, GET_METHOD_METHOD_SIGNATURE);
108:
109: if (Type.getArgumentTypes(adviceMethodInfo
110: .getCalleeMemberDesc()).length == 0) {
111: cv.visitInsn(ACONST_NULL);
112: } else {
113: cv.visitVarInsn(ALOAD, joinPointIndex);
114: cv.visitMethodInsn(INVOKEVIRTUAL, joinPointClassName,
115: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE);
116: cv.visitTypeInsn(CHECKCAST, METHOD_RTTI_IMPL_CLASS_NAME);
117: cv.visitMethodInsn(INVOKEVIRTUAL,
118: METHOD_RTTI_IMPL_CLASS_NAME,
119: GET_PARAMETER_VALUES_METHOD_NAME,
120: GET_ARGUMENTS_METHOD_SIGNATURE);
121: }
122: cv.visitVarInsn(ALOAD, joinPointIndex);
123: cv.visitFieldInsn(GETFIELD, joinPointClassName,
124: CALLEE_INSTANCE_FIELD_NAME, adviceMethodInfo
125: .getCalleeClassSignature());
126: }
127:
128: /**
129: * Handles the arguments to the after advice.
130: */
131: public void createAfterAdviceArgumentHandling(
132: final MethodVisitor cv,
133: final AdviceMethodInfo adviceMethodInfo,
134: final int joinPointInstanceIndex) {
135: final String joinPointClassName = adviceMethodInfo
136: .getJoinPointClassName();
137: final int joinPointIndex = joinPointInstanceIndex;
138: final String specArgDesc = adviceMethodInfo
139: .getSpecialArgumentTypeDesc();
140: if (specArgDesc == null) {
141: cv.visitInsn(ACONST_NULL);
142: } else {
143: cv.visitVarInsn(ALOAD, adviceMethodInfo
144: .getSpecialArgumentIndex());
145: AsmHelper.wrapPrimitiveType(cv, Type.getType(specArgDesc));
146: }
147: cv.visitFieldInsn(GETSTATIC, joinPointClassName,
148: SIGNATURE_FIELD_NAME,
149: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
150: cv.visitMethodInsn(INVOKEVIRTUAL,
151: METHOD_SIGNATURE_IMPL_CLASS_NAME,
152: GET_METHOD_METHOD_NAME, GET_METHOD_METHOD_SIGNATURE);
153:
154: if (Type.getArgumentTypes(adviceMethodInfo
155: .getCalleeMemberDesc()).length == 0) {
156: cv.visitInsn(ACONST_NULL);
157: } else {
158: cv.visitVarInsn(ALOAD, joinPointIndex);
159: cv.visitMethodInsn(INVOKEVIRTUAL, joinPointClassName,
160: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE);
161: cv.visitTypeInsn(CHECKCAST, METHOD_RTTI_IMPL_CLASS_NAME);
162: cv.visitMethodInsn(INVOKEVIRTUAL,
163: METHOD_RTTI_IMPL_CLASS_NAME,
164: GET_PARAMETER_VALUES_METHOD_NAME,
165: GET_ARGUMENTS_METHOD_SIGNATURE);
166: }
167:
168: cv.visitVarInsn(ALOAD, joinPointIndex);
169: cv.visitFieldInsn(GETFIELD, joinPointClassName,
170: CALLEE_INSTANCE_FIELD_NAME, adviceMethodInfo
171: .getCalleeClassSignature());
172: }
173: }
|