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.aopalliance;
008:
009: import org.codehaus.aspectwerkz.definition.AspectDefinition;
010: import org.codehaus.aspectwerkz.reflect.ClassInfo;
011: import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel;
012: import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo;
013: import org.codehaus.aspectwerkz.transform.inlining.AspectInfo;
014: import org.codehaus.aspectwerkz.transform.inlining.compiler.AbstractJoinPointCompiler;
015: import org.codehaus.aspectwerkz.transform.TransformationConstants;
016:
017: import org.aopalliance.intercept.MethodInterceptor;
018: import org.aopalliance.intercept.ConstructorInterceptor;
019:
020: //import org.objectweb.asm.CodeVisitor;
021: //import org.objectweb.asm.ClassWriter;
022: import org.codehaus.aspectwerkz.org.objectweb.asm.CodeVisitor;
023: import org.codehaus.aspectwerkz.org.objectweb.asm.ClassWriter;
024:
025: /**
026: * TODO support ConstructorInvocation (1h work) (plus tests)
027: * <p/>
028: * Implementation of the AspectModel interface for AOP Alliance based frameworks (e.g. Spring, dynaop etc.).
029: * <p/>
030: * Provides methods for definition of aspects and framework specific bytecode generation
031: * used by the join point compiler.
032: *
033: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
034: */
035: public class AopAllianceAspectModel implements AspectModel,
036: TransformationConstants {
037:
038: protected static final String ASPECT_MODEL_TYPE = "aop-alliance";
039: protected static final String AOP_ALLIANCE_CLOSURE_CLASS_NAME = "org/aopalliance/intercept/MethodInvocation";
040: protected static final String AOP_ALLIANCE_CLOSURE_PROCEED_METHOD_NAME = "invoke";
041: protected static final String AOP_ALLIANCE_CLOSURE_PROCEED_METHOD_SIGNATURE = "(Lorg/aopalliance/intercept/MethodInvocation;)Ljava/lang/Object;";
042: protected static final String ASPECT_CONTAINER_CLASS_NAME = AopAllianceAspectContainer.class
043: .getName();
044: protected static final String GET_METHOD_METHOD_NAME = "getMethod";
045: protected static final String GET_METHOD_METHOD_SIGNATURE = "()Ljava/lang/reflect/Method;";
046: protected static final String GET_STATIC_PART_METHOD_NAME = "getStaticPart";
047: protected static final String GET_STATIC_PART_METHOD_SIGNATURE = "()Ljava/lang/reflect/AccessibleObject;";
048: protected static final String GET_PARAMETER_VALUES_METHOD_NAME = "getParameterValues";
049: protected static final String GET_ARGUMENTS_METHOD_SIGNATURE = "()[Ljava/lang/Object;";
050: protected static final String GET_ARGUMENTS_METHOD_NAME = "getArguments";
051:
052: /**
053: * Returns the aspect model type, which is an id for the the special aspect model, can be anything as long
054: * as it is unique.
055: *
056: * @return the aspect model type id
057: */
058: public String getAspectModelType() {
059: return ASPECT_MODEL_TYPE;
060: }
061:
062: /**
063: * Defines the aspect.
064: *
065: * @param classInfo
066: * @param aspectDef
067: * @param loader
068: */
069: public void defineAspect(final ClassInfo classInfo,
070: final AspectDefinition aspectDef, final ClassLoader loader) {
071: ClassInfo[] interfaces = classInfo.getInterfaces();
072: for (int i = 0; i < interfaces.length; i++) {
073: ClassInfo anInterface = interfaces[i];
074: if (anInterface.getName().equals(
075: MethodInterceptor.class.getName())
076: || anInterface.getName().equals(
077: ConstructorInterceptor.class.getName())) {
078: aspectDef.setAspectModel(ASPECT_MODEL_TYPE);
079: aspectDef
080: .setContainerClassName(ASPECT_CONTAINER_CLASS_NAME);
081: return;
082: }
083: }
084: }
085:
086: /**
087: * AOP Alliance is a reflection based model and therefore in need of RTTI info: returns true.
088: *
089: * @return true
090: */
091: public boolean requiresReflectiveInfo() {
092: return true;
093: }
094:
095: /**
096: * Returns info about the closure class, name and type (interface or class).
097: *
098: * @return the closure class info
099: */
100: public AroundClosureClassInfo getAroundClosureClassInfo() {
101: return new AspectModel.AroundClosureClassInfo(null,
102: new String[] { AOP_ALLIANCE_CLOSURE_CLASS_NAME });
103: }
104:
105: /**
106: * Creates the methods required to implement or extend to implement the closure for the specific
107: * aspect model type.
108: *
109: * @param cw
110: * @param className
111: */
112: public void createMandatoryMethods(final ClassWriter cw,
113: final String className) {
114: CodeVisitor cv;
115:
116: // invoke
117: {
118: cv = cw.visitMethod(ACC_PUBLIC,
119: AOP_ALLIANCE_CLOSURE_PROCEED_METHOD_NAME,
120: AOP_ALLIANCE_CLOSURE_PROCEED_METHOD_SIGNATURE,
121: new String[] { THROWABLE_CLASS_NAME }, null);
122: cv.visitVarInsn(ALOAD, 0);
123: cv.visitMethodInsn(INVOKEVIRTUAL, className,
124: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
125: cv.visitInsn(ARETURN);
126: cv.visitMaxs(0, 0);
127: }
128:
129: // getStaticPart
130: {
131: cv = cw.visitMethod(ACC_PUBLIC,
132: GET_STATIC_PART_METHOD_NAME,
133: GET_STATIC_PART_METHOD_SIGNATURE, null, null);
134: cv.visitFieldInsn(GETSTATIC, className,
135: SIGNATURE_FIELD_NAME,
136: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
137: cv.visitTypeInsn(CHECKCAST,
138: METHOD_SIGNATURE_IMPL_CLASS_NAME);
139: cv
140: .visitMethodInsn(INVOKEVIRTUAL,
141: METHOD_SIGNATURE_IMPL_CLASS_NAME,
142: GET_METHOD_METHOD_NAME,
143: GET_METHOD_METHOD_SIGNATURE);
144: cv.visitInsn(ARETURN);
145: cv.visitMaxs(1, 1);
146: }
147:
148: // getMethod
149: {
150: cv = cw.visitMethod(ACC_PUBLIC, GET_METHOD_METHOD_NAME,
151: GET_METHOD_METHOD_SIGNATURE, null, null);
152: cv.visitFieldInsn(GETSTATIC, className,
153: SIGNATURE_FIELD_NAME,
154: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
155: cv.visitTypeInsn(CHECKCAST,
156: METHOD_SIGNATURE_IMPL_CLASS_NAME);
157: cv
158: .visitMethodInsn(INVOKEVIRTUAL,
159: METHOD_SIGNATURE_IMPL_CLASS_NAME,
160: GET_METHOD_METHOD_NAME,
161: GET_METHOD_METHOD_SIGNATURE);
162: cv.visitInsn(ARETURN);
163: cv.visitMaxs(1, 1);
164: }
165:
166: // getArguments
167: {
168: cv = cw.visitMethod(ACC_PUBLIC, GET_ARGUMENTS_METHOD_NAME,
169: GET_ARGUMENTS_METHOD_SIGNATURE, null, null);
170: cv.visitVarInsn(ALOAD, 0);
171: cv.visitMethodInsn(INVOKESPECIAL, className,
172: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE);
173: cv.visitTypeInsn(CHECKCAST, METHOD_RTTI_IMPL_CLASS_NAME);
174: cv.visitMethodInsn(INVOKEVIRTUAL,
175: METHOD_RTTI_IMPL_CLASS_NAME,
176: GET_PARAMETER_VALUES_METHOD_NAME,
177: GET_ARGUMENTS_METHOD_SIGNATURE);
178: cv.visitInsn(ARETURN);
179: cv.visitMaxs(1, 1);
180: }
181:
182: }
183:
184: /**
185: * Creates an invocation of the around closure class' constructor.
186: *
187: * @param cv
188: */
189: public void createInvocationOfAroundClosureSuperClass(
190: final CodeVisitor cv) {
191: }
192:
193: /**
194: * Creates host of the aop alliance aspect instance by invoking aspectOf().
195: *
196: * @param cw
197: * @param aspectInfo
198: * @param joinPointClassName
199: */
200: public void createAspectReferenceField(final ClassWriter cw,
201: final AspectInfo aspectInfo, final String joinPointClassName) {
202: AbstractJoinPointCompiler.createAspectReferenceField(cw,
203: aspectInfo);
204: }
205:
206: /**
207: * Creates instantiation of the aop alliance aspect instance by invoking aspectOf().
208: *
209: * @param cv
210: * @param aspectInfo
211: * @param joinPointClassName
212: */
213: public void createAspectInstantiation(final CodeVisitor cv,
214: final AspectInfo aspectInfo, final String joinPointClassName) {
215: AbstractJoinPointCompiler.createAspectInstantiation(cv,
216: aspectInfo, joinPointClassName);
217: }
218:
219: /**
220: * Handles the arguments to the before around.
221: *
222: * @param cv
223: * @param adviceMethodInfo
224: */
225: public void createAroundAdviceArgumentHandling(
226: final CodeVisitor cv,
227: final AdviceMethodInfo adviceMethodInfo) {
228: }
229:
230: /**
231: * Handles the arguments to the before advice.
232: *
233: * @param cv
234: * @param adviceMethodInfo
235: */
236: public void createBeforeAdviceArgumentHandling(
237: final CodeVisitor cv,
238: final AdviceMethodInfo adviceMethodInfo) {
239: }
240:
241: /**
242: * Handles the arguments to the after advice.
243: *
244: * @param cv
245: * @param adviceMethodInfo
246: */
247: public void createAfterAdviceArgumentHandling(final CodeVisitor cv,
248: final AdviceMethodInfo adviceMethodInfo) {
249: }
250: }
|