View Javadoc

    1   /***************************************************************************************
    2    * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved.                 *
    3    * http://aspectwerkz.codehaus.org                                                    *
    4    * ---------------------------------------------------------------------------------- *
    5    * The software in this package is published under the terms of the LGPL license      *
    6    * a copy of which has been included with this distribution in the license.txt file.  *
    7    **************************************************************************************/
    8   package org.codehaus.aspectwerkz.definition;
    9
    10  import org.codehaus.aspectwerkz.expression.ExpressionInfo;
    11  import org.codehaus.aspectwerkz.reflect.ClassInfo;
    12  import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
    13  import org.codehaus.aspectwerkz.reflect.MethodInfo;
    14  import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
    15  import org.codehaus.aspectwerkz.DeploymentModel;
    16  import org.codehaus.aspectwerkz.aspect.DefaultMixinFactory;
    17  import org.codehaus.aspectwerkz.intercept.AdvisableImpl;
    18  import org.codehaus.aspectwerkz.intercept.Advisable;
    19  import org.codehaus.aspectwerkz.transform.TransformationConstants;
    20
    21  import java.util.ArrayList;
    22  import java.util.Iterator;
    23  import java.util.List;
    24  import java.util.Map;
    25  import java.util.HashMap;
    26  import java.lang.ref.WeakReference;
    27
    28  /***
    29   * Definition for the mixin construct.
    30   *
    31   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
    32   */
    33  public class MixinDefinition {
    34
    35      private final static String DEFAULT_MIXIN_FACTORY = DefaultMixinFactory.class.getName().replace('/', '.');
    36      /***
    37       * The deployment model for the mixin.
    38       */
    39      private DeploymentModel m_deploymentModel;
    40
    41      /***
    42       * Flags the mixin as transient.
    43       */
    44      private boolean m_isTransient;
    45
    46      /***
    47       * The introduced methods info list.
    48       */
    49      private final List m_methodsToIntroduce = new ArrayList();
    50
    51      /***
    52       * The interface classes name.
    53       */
    54      private final List m_interfaceClassNames = new ArrayList();
    55
    56      /***
    57       * The class name for the mixin impl.
    58       */
    59      private final String m_mixinImplClassName;
    60
    61      /***
    62       * The class loader.
    63       */
    64      private final WeakReference m_loaderRef;
    65
    66      /***
    67       * The mixin expressions.
    68       */
    69      private ExpressionInfo[] m_expressionInfos = new ExpressionInfo[]{};
    70
    71      /***
    72       * The attribute for the mixin.
    73       */
    74      private String m_attribute = "";
    75
    76      /***
    77       * The factory class name.
    78       */
    79      private String m_factoryClassName;
    80
    81      /***
    82       * The system definition.
    83       */
    84      private SystemDefinition m_systemDefinition;
    85
    86      /***
    87       * The parameters passed to the mixin at definition time.
    88       */
    89      private Map m_parameters = new HashMap();
    90
    91      /***
    92       * Construct a new definition for mixin.
    93       *
    94       * @param mixinClass      the mixin class
    95       * @param deploymentModel mixin deployment model
    96       * @param isTransient     transient flag
    97       * @param systemDef       the system definition
    98       */
    99      public MixinDefinition(ClassInfo mixinClass,
    100                            final DeploymentModel deploymentModel,
    101                            final boolean isTransient,
    102                            final SystemDefinition systemDef) {
    103         if (isSystemMixin(mixinClass)) {
    104             mixinClass = defineSystemMixin(mixinClass.getClassLoader());
    105         } else {
    106             List allInterfaces = ClassInfoHelper.collectInterfaces(mixinClass);
    107             for (Iterator iterator = allInterfaces.iterator(); iterator.hasNext();) {
    108                 ClassInfo interfaceInfo = (ClassInfo) iterator.next();
    109                 m_interfaceClassNames.add(interfaceInfo.getName());
    110             }
    111
    112             List interfaceDeclaredMethods = ClassInfoHelper.collectMethodsFromInterfacesImplementedBy(mixinClass);
    113             List sortedMethodList = ClassInfoHelper.createInterfaceDefinedMethodList(
    114                     mixinClass, interfaceDeclaredMethods
    115             );
    116             for (Iterator iterator = sortedMethodList.iterator(); iterator.hasNext();) {
    117                 MethodInfo methodInfo = (MethodInfo) iterator.next();
    118                 m_methodsToIntroduce.add(methodInfo);
    119             }
    120         }
    121
    122         m_mixinImplClassName = mixinClass.getName();
    123         m_loaderRef = new WeakReference(mixinClass.getClassLoader());
    124         m_systemDefinition = systemDef;
    125         m_expressionInfos = new ExpressionInfo[]{};
    126
    127         m_deploymentModel = deploymentModel;
    128         m_isTransient = isTransient;
    129
    130         // default factory
    131         setFactoryClassName(DEFAULT_MIXIN_FACTORY);
    132     }
    133
    134     /***
    135      * Sets the factory class name.
    136      *
    137      * @param factoryClassName
    138      */
    139     public void setFactoryClassName(final String factoryClassName) {
    140         m_factoryClassName = factoryClassName;
    141     }
    142
    143     /***
    144      * Returns the factory class name.
    145      *
    146      * @return
    147      */
    148     public String getFactoryClassName() {
    149         return m_factoryClassName;
    150     }
    151
    152     /***
    153      * Returns the methods to introduce.
    154      *
    155      * @return the methods to introduce
    156      */
    157     public List getMethodsToIntroduce() {
    158         return m_methodsToIntroduce;
    159     }
    160
    161     /***
    162      * Returns the deployment model.
    163      *
    164      * @return the deployment model
    165      */
    166     public DeploymentModel getDeploymentModel() {
    167         return m_deploymentModel;
    168     }
    169
    170     /***
    171      * Sets the deployment model.
    172      *
    173      * @param deploymentModel
    174      */
    175     public void setDeploymentModel(final DeploymentModel deploymentModel) {
    176         m_deploymentModel = deploymentModel;
    177     }
    178
    179     /***
    180      * Checks if the mixin is transient.
    181      *
    182      * @return
    183      */
    184     public boolean isTransient() {
    185         return m_isTransient;
    186     }
    187
    188     /***
    189      * Sets the mixin as transient.
    190      *
    191      * @param isTransient
    192      */
    193     public void setTransient(boolean isTransient) {
    194         m_isTransient = isTransient;
    195     }
    196
    197     /***
    198      * Returns the class info for the mixin impl.
    199      *
    200      * @return the class info
    201      */
    202     public ClassInfo getMixinImpl() {
    203         return AsmClassInfo.getClassInfo(m_mixinImplClassName, (ClassLoader) m_loaderRef.get());
    204     }
    205
    206     /***
    207      * Returns the expressions.
    208      *
    209      * @return the expressions array
    210      */
    211     public ExpressionInfo[] getExpressionInfos() {
    212         return m_expressionInfos;
    213     }
    214
    215     /***
    216      * Returns the class name of the interface.
    217      *
    218      * @return the class name of the interface
    219      */
    220     public List getInterfaceClassNames() {
    221         return m_interfaceClassNames;
    222     }
    223
    224     /***
    225      * Returns the attribute.
    226      *
    227      * @return the attribute
    228      */
    229     public String getAttribute() {
    230         return m_attribute;
    231     }
    232
    233     /***
    234      * Sets the attribute.
    235      *
    236      * @param attribute the attribute
    237      */
    238     public void setAttribute(final String attribute) {
    239         m_attribute = attribute;
    240     }
    241
    242     /***
    243      * Returns the system definition.
    244      *
    245      * @return the system definition
    246      */
    247     public SystemDefinition getSystemDefinition() {
    248         return m_systemDefinition;
    249     }
    250
    251     /***
    252      * Adds a new expression info.
    253      *
    254      * @param expression a new expression info
    255      */
    256     public void addExpressionInfo(final ExpressionInfo expression) {
    257         final ExpressionInfo[] tmpExpressions = new ExpressionInfo[m_expressionInfos.length + 1];
    258         java.lang.System.arraycopy(m_expressionInfos, 0, tmpExpressions, 0, m_expressionInfos.length);
    259         tmpExpressions[m_expressionInfos.length] = expression;
    260         m_expressionInfos = new ExpressionInfo[m_expressionInfos.length + 1];
    261         java.lang.System.arraycopy(tmpExpressions, 0, m_expressionInfos, 0, tmpExpressions.length);
    262     }
    263
    264     /***
    265      * Adds an array with new expression infos.
    266      *
    267      * @param expressions an array with new expression infos
    268      */
    269     public void addExpressionInfos(final ExpressionInfo[] expressions) {
    270         final ExpressionInfo[] tmpExpressions = new ExpressionInfo[m_expressionInfos.length + expressions.length];
    271         java.lang.System.arraycopy(m_expressionInfos, 0, tmpExpressions, 0, m_expressionInfos.length);
    272         java.lang.System.arraycopy(expressions, 0, tmpExpressions, m_expressionInfos.length, expressions.length);
    273         m_expressionInfos = new ExpressionInfo[m_expressionInfos.length + expressions.length];
    274         java.lang.System.arraycopy(tmpExpressions, 0, m_expressionInfos, 0, tmpExpressions.length);
    275     }
    276
    277     /***
    278      * Defines system mixins.
    279      *
    280      * @param loader
    281      * @return
    282      */
    283     private ClassInfo defineSystemMixin(final ClassLoader loader) {
    284         // if advisable impl mixin get the class info from the AsmClassInfo to keep the methods starting with aw$
    285         ClassInfo mixinClass = AsmClassInfo.getClassInfo(AdvisableImpl.class.getName(), loader);
    286         MethodInfo[] methods = mixinClass.getMethods();
    287         for (int i = 0; i < methods.length; i++) {
    288             MethodInfo method = methods[i];
    289             if (method.getName().startsWith(TransformationConstants.SYNTHETIC_MEMBER_PREFIX)
    290                 || method.getName().startsWith("aw_")) {//aw$ not reachable in IDEs without AW source code
    291                 m_methodsToIntroduce.add(method);
    292             }
    293         }
    294         m_interfaceClassNames.add(Advisable.class.getName());
    295         return mixinClass;
    296     }
    297
    298     /***
    299      * Checks if the mixin is a system mixin.
    300      *
    301      * @param mixinClass
    302      * @return
    303      */
    304     private boolean isSystemMixin(final ClassInfo mixinClass) {
    305         return mixinClass.getName().equals(AdvisableImpl.class.getName());
    306     }
    307
    308     /***
    309      * Adds a new parameter to the mixin.
    310      *
    311      * @param name  the name of the parameter
    312      * @param value the value for the parameter
    313      */
    314     public void addParameter(final String name, final String value) {
    315         m_parameters.put(name, value);
    316     }
    317
    318     /***
    319      * Returns the parameters as a Map.
    320      *
    321      * @return the parameters
    322      */
    323     public Map getParameters() {
    324         return m_parameters;
    325     }
    326
    327 }