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 }