/************************************************************************************** * Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. * * http://aspectwerkz.codehaus.org * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the LGPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package org.codehaus.aspectwerkz.transform.inlining.spi; import org.codehaus.aspectwerkz.definition.AspectDefinition; import org.codehaus.aspectwerkz.reflect.ClassInfo; import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo; import org.codehaus.aspectwerkz.transform.inlining.AspectInfo; import org.codehaus.aspectwerkz.transform.inlining.compiler.CompilerInput; import org.codehaus.aspectwerkz.transform.inlining.compiler.CompilationInfo; import org.codehaus.aspectwerkz.transform.inlining.compiler.AbstractJoinPointCompiler; import org.codehaus.aspectwerkz.transform.JoinPointCompiler; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; import org.objectweb.asm.ClassVisitor; /** * An aspect model defines a custom hook for the JoinPointCompiler. * <p/> * The AspectModel is registered using AspectModelManager, and the AspectDefinition is linked to the model * "getAspectModelType()" unique identifier. * <p/> * An no arg constructor instance of the model will be callback during aspect registration for defineAspect(..) * </p> * During compilation, different aspect model instance can be instantiated per compilation using the getInstance(..) * method (not returning "this"). * * @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a> * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> */ public interface AspectModel { /** * A prototype patttern. Ones may return "this" if singleton / non thread safe instance is enough. * * @param compilationModel * @return */ AspectModel getInstance(CompilationInfo.Model compilationModel); /** * Returns the aspect model type, which is an id for the the special aspect model, can be anything as long * as it is unique. * * @return the aspect model type id */ String getAspectModelType(); /** * Defines the aspect and adds definition to the aspect definition. * * @param aspectClassInfo * @param aspectDef * @param loader */ void defineAspect(ClassInfo aspectClassInfo, AspectDefinition aspectDef, ClassLoader loader); /** * Returns info about the closure class, name and type (interface or class). * * @return the closure class info */ AroundClosureClassInfo getAroundClosureClassInfo(); /** * Creates the methods required to implement or extend to implement the closure for the specific aspect model type. * * @param cw * @param compiler */ void createMandatoryMethods(ClassWriter cw, JoinPointCompiler compiler); /** * Creates invocation of the super class for the around closure. * <p/> * E.g. the invocation of super(..) in the constructor. * <p/> * Only needed to be implemented if the around closure base class is really a base class and not an interface. * * @param cv */ void createInvocationOfAroundClosureSuperClass(MethodVisitor cv); /** * Creates aspect reference field (field in the jit jointpoint class f.e.) for an aspect instance. * Creates instantiation of an aspect instance and stores them if appropriate (see createAspectReferenceField). * * @param cw for the jp class beeing compiled * @param cv for the <clinit> method * @param aspectInfo * @param joinPointClassName */ void createAndStoreStaticAspectInstantiation(ClassVisitor cw, MethodVisitor cv, AspectInfo aspectInfo, String joinPointClassName); /** * Initializes instance level aspects, retrieves them from the target instance through the * <code>HasInstanceLevelAspect</code> interfaces. * <p/> * Use by 'perInstance', 'perThis' and 'perTarget' deployment models. * * @param cv * @param input * @param aspectInfo */ void createAndStoreRuntimeAspectInstantiation(final MethodVisitor cv, final CompilerInput input, final AspectInfo aspectInfo); /** * Loads the aspect instance on stack. * See loadJoinPointInstance(..) and * * @param cv * @param aspectInfo */ void loadAspect(final MethodVisitor cv, final CompilerInput input, final AspectInfo aspectInfo); /** * Handles the arguments to the around advice. * * @param cv * @param adviceMethodInfo */ void createAroundAdviceArgumentHandling(MethodVisitor cv, CompilerInput input, Type[] joinPointArgumentTypes, AdviceMethodInfo adviceMethodInfo); /** * Handles the arguments to the before or after (after XXX) advice. * * @param cv * @param input * @param joinPointArgumentTypes * @param adviceMethodInfo * @param specialArgIndex index on the stack of the throwned exception / returned value (makes sense for after advice, * else set to INDEX_NOTAVAILABLE) */ public void createBeforeOrAfterAdviceArgumentHandling(MethodVisitor cv, CompilerInput input, Type[] joinPointArgumentTypes, AdviceMethodInfo adviceMethodInfo, int specialArgIndex); /** * Should return true if the aspect model requires that Runtime Type Information (RTTI) is build up * for the join point. Needed for reflective systems and systems that does not support f.e. args() binding. * * @return */ boolean requiresReflectiveInfo(); /** * Info about the around closure class or interface for this specific aspect model. * * @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a> */ public static class AroundClosureClassInfo { private final String m_superClassName; private final String[] m_interfaceNames; public AroundClosureClassInfo(final String superClassName, final String[] interfaceNames) { if (superClassName != null) { m_superClassName = superClassName.replace('.', '/'); } else { m_superClassName = null; } m_interfaceNames = new String[interfaceNames.length]; for (int i = 0; i < interfaceNames.length; i++) { m_interfaceNames[i] = interfaceNames[i].replace('.', '/'); } } public String getSuperClassName() { return m_superClassName; } public String[] getInterfaceNames() { return m_interfaceNames; } /** * Type safe enum for the around closure class type. */ public static class Type { public static final Type INTERFACE = new Type("INTERFACE"); public static final Type CLASS = new Type("CLASS"); private final String m_name; private Type(String name) { m_name = name; } public String toString() { return m_name; } } } }