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