001: /**************************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.transform.spring;
008:
009: import org.codehaus.aspectwerkz.transform.aopalliance.AopAllianceAspectModel;
010: import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel;
011: import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo;
012: import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
013: import org.codehaus.aspectwerkz.reflect.ClassInfo;
014: import org.codehaus.aspectwerkz.definition.AspectDefinition;
015:
016: import org.aopalliance.intercept.MethodInterceptor;
017:
018: import org.springframework.aop.AfterReturningAdvice;
019: import org.springframework.aop.MethodBeforeAdvice;
020: import org.springframework.aop.ThrowsAdvice;
021:
022: //import org.objectweb.asm.CodeVisitor;
023: //import org.objectweb.asm.ClassWriter;
024: //import org.objectweb.asm.Type;
025: import org.codehaus.aspectwerkz.org.objectweb.asm.CodeVisitor;
026: import org.codehaus.aspectwerkz.org.objectweb.asm.ClassWriter;
027: import org.codehaus.aspectwerkz.org.objectweb.asm.Type;
028:
029: /**
030: * Implementation of the AspectModel interface for Spring framework.
031: * <p/>
032: * Provides methods for definition of aspects and framework specific bytecode generation
033: * used by the join point compiler.
034: *
035: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
036: */
037: public class SpringAspectModel extends AopAllianceAspectModel {
038:
039: protected static final String ASPECT_MODEL_TYPE = "spring";
040:
041: /**
042: * Returns the aspect model type, which is an id for the the special aspect model, can be anything as long
043: * as it is unique.
044: *
045: * @return the aspect model type id
046: */
047: public String getAspectModelType() {
048: return ASPECT_MODEL_TYPE;
049: }
050:
051: /**
052: * Defines the aspect.
053: *
054: * @param classInfo
055: * @param aspectDef
056: * @param loader
057: */
058: public void defineAspect(final ClassInfo classInfo,
059: final AspectDefinition aspectDef, final ClassLoader loader) {
060: ClassInfo[] interfaces = classInfo.getInterfaces();
061: for (int i = 0; i < interfaces.length; i++) {
062: ClassInfo anInterface = interfaces[i];
063: if (anInterface.getName().equals(
064: MethodInterceptor.class.getName())
065: || anInterface.getName().equals(
066: MethodBeforeAdvice.class.getName())
067: || anInterface.getName().equals(
068: AfterReturningAdvice.class.getName())
069: || anInterface.getName().equals(
070: ThrowsAdvice.class.getName())) {
071: aspectDef.setAspectModel(ASPECT_MODEL_TYPE);
072: aspectDef
073: .setContainerClassName(ASPECT_CONTAINER_CLASS_NAME);
074: return;
075: }
076: }
077: }
078:
079: /**
080: * Returns info about the closure class, name and type (interface or class).
081: *
082: * @return the closure class info
083: */
084: public AroundClosureClassInfo getAroundClosureClassInfo() {
085: return new AspectModel.AroundClosureClassInfo(null,
086: new String[] {
087: AOP_ALLIANCE_CLOSURE_CLASS_NAME,
088: MethodBeforeAdvice.class.getName().replace('.',
089: '/'),
090: AfterReturningAdvice.class.getName().replace(
091: '.', '/') });
092: }
093:
094: /**
095: * Creates the methods required to implement or extend to implement the closure for the specific
096: * aspect model type.
097: *
098: * @param cw
099: * @param className
100: */
101: public void createMandatoryMethods(final ClassWriter cw,
102: final String className) {
103: super .createMandatoryMethods(cw, className);
104: }
105:
106: /**
107: * Handles the arguments to the before advice.
108: *
109: * @param cv
110: * @param adviceMethodInfo
111: */
112: public void createBeforeAdviceArgumentHandling(
113: final CodeVisitor cv,
114: final AdviceMethodInfo adviceMethodInfo) {
115: final String joinPointClassName = adviceMethodInfo
116: .getJoinPointClassName();
117: final int joinPointIndex = adviceMethodInfo.getJoinPointIndex();
118: cv.visitFieldInsn(GETSTATIC, joinPointClassName,
119: SIGNATURE_FIELD_NAME,
120: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
121: cv.visitMethodInsn(INVOKEVIRTUAL,
122: METHOD_SIGNATURE_IMPL_CLASS_NAME,
123: GET_METHOD_METHOD_NAME, GET_METHOD_METHOD_SIGNATURE);
124:
125: if (Type.getArgumentTypes(adviceMethodInfo
126: .getCalleeMemberDesc()).length == 0) {
127: cv.visitInsn(ACONST_NULL);
128: } else {
129: cv.visitVarInsn(ALOAD, joinPointIndex);
130: cv.visitMethodInsn(INVOKEVIRTUAL, joinPointClassName,
131: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE);
132: cv.visitTypeInsn(CHECKCAST, METHOD_RTTI_IMPL_CLASS_NAME);
133: cv.visitMethodInsn(INVOKEVIRTUAL,
134: METHOD_RTTI_IMPL_CLASS_NAME,
135: GET_PARAMETER_VALUES_METHOD_NAME,
136: GET_ARGUMENTS_METHOD_SIGNATURE);
137: }
138: cv.visitVarInsn(ALOAD, joinPointIndex);
139: cv.visitFieldInsn(GETFIELD, joinPointClassName,
140: CALLEE_INSTANCE_FIELD_NAME, adviceMethodInfo
141: .getCalleeClassSignature());
142: }
143:
144: /**
145: * Handles the arguments to the after advice.
146: *
147: * @param cv
148: * @param adviceMethodInfo
149: */
150: public void createAfterAdviceArgumentHandling(final CodeVisitor cv,
151: final AdviceMethodInfo adviceMethodInfo) {
152: final String joinPointClassName = adviceMethodInfo
153: .getJoinPointClassName();
154: final int joinPointIndex = adviceMethodInfo.getJoinPointIndex();
155: final String specArgDesc = adviceMethodInfo
156: .getSpecialArgumentTypeDesc();
157: if (specArgDesc == null) {
158: cv.visitInsn(ACONST_NULL);
159: } else {
160: cv.visitVarInsn(ALOAD, adviceMethodInfo
161: .getSpecialArgumentIndex());
162: AsmHelper.wrapPrimitiveType(cv, Type.getType(specArgDesc));
163: }
164: cv.visitFieldInsn(GETSTATIC, joinPointClassName,
165: SIGNATURE_FIELD_NAME,
166: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
167: cv.visitMethodInsn(INVOKEVIRTUAL,
168: METHOD_SIGNATURE_IMPL_CLASS_NAME,
169: GET_METHOD_METHOD_NAME, GET_METHOD_METHOD_SIGNATURE);
170:
171: if (Type.getArgumentTypes(adviceMethodInfo
172: .getCalleeMemberDesc()).length == 0) {
173: cv.visitInsn(ACONST_NULL);
174: } else {
175: cv.visitVarInsn(ALOAD, joinPointIndex);
176: cv.visitMethodInsn(INVOKEVIRTUAL, joinPointClassName,
177: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE);
178: cv.visitTypeInsn(CHECKCAST, METHOD_RTTI_IMPL_CLASS_NAME);
179: cv.visitMethodInsn(INVOKEVIRTUAL,
180: METHOD_RTTI_IMPL_CLASS_NAME,
181: GET_PARAMETER_VALUES_METHOD_NAME,
182: GET_ARGUMENTS_METHOD_SIGNATURE);
183: }
184:
185: cv.visitVarInsn(ALOAD, joinPointIndex);
186: cv.visitFieldInsn(GETFIELD, joinPointClassName,
187: CALLEE_INSTANCE_FIELD_NAME, adviceMethodInfo
188: .getCalleeClassSignature());
189: }
190: }
|