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.aspect.AdviceType;
    12  import org.codehaus.aspectwerkz.reflect.MethodInfo;
    13  import org.codehaus.aspectwerkz.util.Strings;
    14  import org.codehaus.aspectwerkz.DeploymentModel;
    15  import org.codehaus.aspectwerkz.cflow.CflowBinding;
    16
    17  import java.util.List;
    18
    19  /***
    20   * Holds the meta-data for the advices.
    21   *
    22   * @author <a href="mailto:jboner@codehaus.org">Jonas Boner </a>
    23   */
    24  public class AdviceDefinition {
    25
    26      /***
    27       * The name of the advice.
    28       * It is the advice method name and optionnaly the call signature.
    29       * e.g. advice or advice() or advice(JoinPoint jp) or myadvice(JoinPoint myJp , java.lang.String foo) ...
    30       */
    31      private String m_name;
    32
    33      /***
    34       * The type of the advice.
    35       */
    36      private AdviceType m_type;
    37
    38      /***
    39       * The aspect class name.
    40       */
    41      private final String m_aspectClassName;
    42
    43      /***
    44       * The aspect name.
    45       */
    46      private final String m_aspectName;
    47
    48      /***
    49       * The pointcut expression.
    50       */
    51      private ExpressionInfo m_expressionInfo;
    52
    53      /***
    54       * The method for the advice.
    55       */
    56      private final MethodInfo m_method;
    57
    58      /***
    59       * The attribute for the advice.
    60       */
    61      private String m_attribute = "";
    62
    63      /***
    64       * The aspect definition holding this advice definition.
    65       */
    66      private AspectDefinition m_aspectDefinition;
    67
    68      /***
    69       * The special arg type, such as returning(TYPE) or throwing(TYPE).
    70       */
    71      private String m_specialArgumentType;
    72
    73      /***
    74       * Indicates if this advice will need a cflow or cflowbelow runtime check
    75       */
    76      private boolean m_hasCflowOrCflowBelow = false;
    77
    78      /***
    79       * TODO only use this method and make ctor private?
    80       * <p/>
    81       * Creates a new advice definition.
    82       *
    83       * @param adviceName          the advice name
    84       * @param adviceType          the advice type
    85       * @param expression          the advice expression
    86       * @param specialArgumentType the arg
    87       * @param aspectName          the aspect name
    88       * @param aspectClassName     the aspect class name
    89       * @param method              the advice method
    90       * @param aspectDef           the aspect definition
    91       * @return the new advice definition
    92       */
    93      public static AdviceDefinition newInstance(final String adviceName,
    94                                                 final AdviceType adviceType,
    95                                                 final String expression,
    96                                                 final String specialArgumentType,
    97                                                 final String aspectName,
    98                                                 final String aspectClassName,
    99                                                 final MethodInfo method,
    100                                                final AspectDefinition aspectDef) {
    101         ExpressionInfo expressionInfo = new ExpressionInfo(
    102                 expression,
    103                 aspectDef.getQualifiedName()
    104         );
    105
    106         // support for pointcut signature
    107         String adviceCallSignature = null;
    108         String resolvedSpecialArgumentType = specialArgumentType;
    109         if (adviceName.indexOf('(') > 0) {
    110             adviceCallSignature = adviceName.substring(adviceName.indexOf('(') + 1, adviceName.lastIndexOf(')'));
    111             String[] parameters = Strings.splitString(adviceCallSignature, ",");
    112             for (int i = 0; i < parameters.length; i++) {
    113                 String[] parameterInfo = Strings.splitString(
    114                         Strings.replaceSubString(parameters[i].trim(), "  ", " "),
    115                         " "
    116                 );
    117                 // skip the parameter if this ones is a after returning / throwing binding
    118                 if (parameterInfo[1].equals(specialArgumentType)) {
    119                     resolvedSpecialArgumentType = parameterInfo[0];
    120                     expressionInfo.setSpecialArgumentName(parameterInfo[1]);
    121                 } else {
    122                     expressionInfo.addArgument(
    123                             parameterInfo[1],
    124                             parameterInfo[0],
    125                             aspectDef.getClassInfo().getClassLoader()
    126                     );
    127                 }
    128             }
    129         }
    130
    131         return new AdviceDefinition(
    132                 adviceName,
    133                 adviceType,
    134                 resolvedSpecialArgumentType,
    135                 aspectName,
    136                 aspectClassName,
    137                 expressionInfo,
    138                 method,
    139                 aspectDef
    140         );
    141     }
    142
    143     /***
    144      * Creates a new advice meta-data instance.
    145      *
    146      * @param name                the name of the expressionInfo
    147      * @param type                the type of the advice
    148      * @param specialArgumentType the special arg type, such as returning(TYPE) or throwing(TYPE)
    149      * @param aspectName          the name of the aspect
    150      * @param aspectClassName     the class name of the aspect
    151      * @param expressionInfo      the expressionInfo
    152      * @param methodInfo          the methodInfo
    153      */
    154     public AdviceDefinition(final String name,
    155                             final AdviceType type,
    156                             final String specialArgumentType,
    157                             final String aspectName,
    158                             final String aspectClassName,
    159                             final ExpressionInfo expressionInfo,
    160                             final MethodInfo methodInfo,
    161                             final AspectDefinition aspectDef) {
    162         if (name == null) {
    163             throw new IllegalArgumentException("name can not be null");
    164         }
    165         if (type == null) {
    166             throw new IllegalArgumentException("illegal advice type");
    167         }
    168         if (aspectName == null) {
    169             throw new IllegalArgumentException("aspect name can not be null");
    170         }
    171         if (aspectClassName == null) {
    172             throw new IllegalArgumentException("class name can not be null");
    173         }
    174         if (methodInfo == null) {
    175             throw new IllegalArgumentException("methodInfo can not be null");
    176         }
    177         if (aspectDef == null) {
    178             throw new IllegalArgumentException("aspect definition can not be null");
    179         }
    180         m_name = name;
    181         m_type = type;
    182         m_specialArgumentType = specialArgumentType;
    183         m_aspectName = aspectName;
    184         m_aspectClassName = aspectClassName;
    185         m_expressionInfo = expressionInfo;
    186         m_method = methodInfo;
    187         m_aspectDefinition = aspectDef;
    188
    189         // get the cflow Advice bindings to know if this advice binding is using cflow or cflowbelow
    190         List cflowBindings = CflowBinding.getCflowBindingsForCflowOf(m_expressionInfo);
    191         m_hasCflowOrCflowBelow = (cflowBindings.size() > 0);
    192     }
    193
    194     /***
    195      * Returns the advice type.
    196      *
    197      * @return the advice type
    198      */
    199     public AdviceType getType() {
    200         return m_type;
    201     }
    202
    203     /***
    204      * Returns the name of the advice.
    205      *
    206      * @return the name
    207      */
    208     public String getName() {
    209         return m_name;
    210     }
    211
    212     /***
    213      * Returns the fully qualified name for the advice
    214      *
    215      * @return the fully qualified name
    216      */
    217     public String getQualifiedName() {
    218         return m_aspectDefinition.getQualifiedName() + '.' + m_name;
    219     }
    220
    221     /***
    222      * Sets the name of the advice.
    223      *
    224      * @param name the name
    225      */
    226     public void setName(final String name) {
    227         m_name = name.trim();
    228     }
    229
    230     /***
    231      * Returns the expression.
    232      * <p/>
    233      * TODO should return NULL object if null
    234      *
    235      * @return the expression
    236      */
    237     public ExpressionInfo getExpressionInfo() {
    238         return m_expressionInfo;
    239     }
    240
    241     /***
    242      * Sets the expression info.
    243      *
    244      * @param newExpression the new expression info
    245      */
    246     public void setExpressionInfo(final ExpressionInfo newExpression) {
    247         m_expressionInfo = newExpression;
    248         // update the hasCflow caracteristic
    249         List cflowBindings = CflowBinding.getCflowBindingsForCflowOf(m_expressionInfo);
    250         m_hasCflowOrCflowBelow = (cflowBindings.size() > 0);
    251     }
    252
    253     /***
    254      * Returns the class name.
    255      *
    256      * @return the class name
    257      */
    258     public String getAspectClassName() {
    259         return m_aspectClassName;
    260     }
    261
    262     /***
    263      * Returns the aspect name.
    264      *
    265      * @return the aspect name
    266      */
    267     public String getAspectName() {
    268         return m_aspectName;
    269     }
    270
    271     /***
    272      * Returns the special arg type, such as returning(TYPE) or throwing(TYPE).
    273      *
    274      * @return
    275      */
    276     public String getSpecialArgumentType() {
    277         return m_specialArgumentType;
    278     }
    279
    280     /***
    281      * Returns the method.
    282      *
    283      * @return the method
    284      */
    285     public MethodInfo getMethodInfo() {
    286         return m_method;
    287     }
    288
    289     /***
    290      * Returns the the deployment model for the advice
    291      *
    292      * @return the deployment model
    293      */
    294     public DeploymentModel getDeploymentModel() {
    295         return m_aspectDefinition.getDeploymentModel();
    296     }
    297
    298     /***
    299      * Returns the attribute.
    300      *
    301      * @return the attribute
    302      */
    303     public String getAttribute() {
    304         return m_attribute;
    305     }
    306
    307     /***
    308      * Sets the attribute.
    309      *
    310      * @param attribute the attribute
    311      */
    312     public void setAttribute(final String attribute) {
    313         m_attribute = attribute;
    314     }
    315
    316     /***
    317      * Returns the definition for the aspect that defines this advice.
    318      *
    319      * @return the aspect definition
    320      */
    321     public AspectDefinition getAspectDefinition() {
    322         return m_aspectDefinition;
    323     }
    324
    325     /***
    326      * Check if the advice is bound to a pointcut with cflow or cflowbelow
    327      *
    328      * @return
    329      */
    330     public boolean hasCflowOrCflowBelow() {
    331         return m_hasCflowOrCflowBelow;
    332     }
    333
    334     /***
    335      * Deep copy of the definition.
    336      *
    337      * @param expressionInfo
    338      * @return
    339      */
    340     public AdviceDefinition copyAt(final ExpressionInfo expressionInfo) {
    341         return new AdviceDefinition(
    342                 getName(),
    343                 getType(),
    344                 getSpecialArgumentType(),
    345                 getAspectName(),
    346                 getAspectClassName(),
    347                 expressionInfo,
    348                 getMethodInfo(),
    349                 m_aspectDefinition
    350         );
    351     }
    352
    353     /***
    354      * Equals and hashcode means we have the same advice if the aspect qualified name (not classname) and
    355      * advice name (may include signature) are the same. [AW-439 fix]
    356      *
    357      * @param o
    358      * @return
    359      */
    360     public boolean equals(Object o) {
    361         if (this == o) return true;
    362         if (!(o instanceof AdviceDefinition)) return false;
    363
    364         final AdviceDefinition adviceDefinition = (AdviceDefinition) o;
    365
    366         if (!m_aspectName.equals(adviceDefinition.m_aspectName)) return false;
    367         if (!m_name.equals(adviceDefinition.m_name)) return false;
    368
    369         return true;
    370     }
    371
    372     public int hashCode() {
    373         int result;
    374         result = m_name.hashCode();
    375         result = 29 * result + m_aspectName.hashCode();
    376         return result;
    377     }
    378 }