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.aspect;
    9
    10  import java.util.HashMap;
    11  import java.util.Map;
    12  import java.util.WeakHashMap;
    13
    14  import org.codehaus.aspectwerkz.AspectContext;
    15
    16
    17  /***
    18   * Abstract base class for the aspect container implementations.
    19   *
    20   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
    21   * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
    22   * @TODO: allow any type of constructor, to support ctor based dependency injection
    23   */
    24  public abstract class AbstractAspectContainer implements AspectContainer {
    25
    26      public static final int ASPECT_CONSTRUCTION_TYPE_UNKNOWN = 0;
    27      public static final int ASPECT_CONSTRUCTION_TYPE_DEFAULT = 1;
    28      public static final int ASPECT_CONSTRUCTION_TYPE_ASPECT_CONTEXT = 2;
    29      public static final Object[] EMPTY_OBJECT_ARRAY = new Object[]{};
    30
    31      /***
    32       * An array with the single aspect context, needed to save one array creation per invocation.
    33       */
    34      protected final Object[] ARRAY_WITH_SINGLE_ASPECT_CONTEXT = new Object[1];
    35
    36      /***
    37       * The aspect construction type.
    38       */
    39      protected int m_constructionType = ASPECT_CONSTRUCTION_TYPE_UNKNOWN;
    40
    41      /***
    42       * The aspect context prototype.
    43       */
    44      protected final AspectContext m_aspectContext;
    45
    46      /***
    47       * Holds a reference to the sole per JVM aspect instance.
    48       */
    49      protected Object m_perJvm;
    50
    51      /***
    52       * Holds references to the per class aspect instances.
    53       */
    54      protected final Map m_perClass = new WeakHashMap();
    55
    56      /***
    57       * Holds references to the per instance aspect instances.
    58       */
    59      protected final Map m_perInstance = new WeakHashMap();
    60
    61      /***
    62       * Holds references to the per thread aspect instances.
    63       */
    64      protected final Map m_perThread = new WeakHashMap();
    65
    66      /***
    67       * Maps the advice infos to the hash codes of the the matching advice method.
    68       */
    69      protected final Map m_adviceInfos = new HashMap();
    70
    71      /***
    72       * Creates a new aspect container strategy.
    73       *
    74       * @param aspectContext the context
    75       */
    76      public AbstractAspectContainer(final AspectContext aspectContext) {
    77          if (aspectContext == null) {
    78              throw new IllegalArgumentException("cross-cutting info can not be null");
    79          }
    80
    81          m_aspectContext = aspectContext;
    82          ARRAY_WITH_SINGLE_ASPECT_CONTEXT[0] = m_aspectContext;
    83      }
    84
    85      /***
    86       * Returns the context.
    87       *
    88       * @return the context
    89       */
    90      public AspectContext getContext() {
    91          return m_aspectContext;
    92      }
    93
    94      /***
    95       * asm
    96       * Creates a new perJVM cross-cutting instance, if it already exists then return it.
    97       *
    98       * @return the cross-cutting instance
    99       */
    100     public Object aspectOf() {
    101         if (m_perJvm == null) {
    102             m_perJvm = createAspect();
    103         }
    104         return m_perJvm;
    105     }
    106
    107     /***
    108      * Creates a new perClass cross-cutting instance, if it already exists then return it.
    109      *
    110      * @param klass
    111      * @return the cross-cutting instance
    112      */
    113     public Object aspectOf(final Class klass) {
    114         synchronized (m_perClass) {
    115             if (!m_perClass.containsKey(klass)) {
    116                 m_perClass.put(klass, createAspect());
    117             }
    118         }
    119         return m_perClass.get(klass);
    120     }
    121
    122     /***
    123      * Creates a new perInstance cross-cutting instance, if it already exists then return it.
    124      *
    125      * @param instance
    126      * @return the cross-cutting instance
    127      */
    128     public Object aspectOf(final Object instance) {
    129         synchronized (m_perInstance) {
    130             if (!m_perInstance.containsKey(instance)) {
    131                 m_perInstance.put(instance, createAspect());
    132             }
    133         }
    134         return m_perInstance.get(instance);
    135     }
    136
    137     /***
    138      * Creates a new perThread cross-cutting instance, if it already exists then return it.
    139      *
    140      * @param thread the thread for the aspect
    141      * @return the cross-cutting instance
    142      */
    143     public Object aspectOf(final Thread thread) {
    144         synchronized (m_perThread) {
    145             if (!m_perThread.containsKey(thread)) {
    146                 m_perThread.put(thread, createAspect());
    147             }
    148         }
    149         return m_perThread.get(thread);
    150     }
    151
    152     /***
    153      * To be implemented by the concrete aspect containers. <p/>Should return a new aspect instance.
    154      *
    155      * @return a new aspect instance
    156      */
    157     protected abstract Object createAspect();
    158 }