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.lang.reflect.InvocationTargetException;
11  import java.util.WeakHashMap;
12  import java.util.Map;
13  
14  import org.codehaus.aspectwerkz.exception.DefinitionException;
15  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
16  import org.codehaus.aspectwerkz.DeploymentModel;
17  
18  /***
19   * Abstract base class for the mixin factory implementations.
20   *
21   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
22   * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
23   */
24  public class DefaultMixinFactory extends AbstractMixinFactory {
25  
26      private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
27  
28      private Object m_perJVM = null;
29  
30      private Map m_perClassMixins = new WeakHashMap();
31  
32      private Map m_perInstanceMixins = new WeakHashMap();
33  
34      /***
35       * Creates a new default mixin factory.
36       *
37       * @param mixinClass
38       * @param deploymentModel
39       */
40      public DefaultMixinFactory(final Class mixinClass, final DeploymentModel deploymentModel) {
41          super(mixinClass, deploymentModel);
42      }
43  
44      /***
45       * Creates a new perJVM mixin instance.
46       *
47       * @return the mixin instance
48       */
49      public Object mixinOf() {
50          if (m_perJVM != null) {
51              return m_perJVM;
52          }
53          synchronized (this) {
54              final Object mixin;
55              if (m_deploymentModel == DeploymentModel.PER_JVM) {
56                  try {
57                      mixin = m_defaultConstructor.newInstance(EMPTY_OBJECT_ARRAY);
58                  } catch (InvocationTargetException e) {
59                      throw new WrappedRuntimeException(e.getTargetException());
60                  } catch (Exception e) {
61                      throw new WrappedRuntimeException(e);
62                  }
63              } else {
64                  throw new DefinitionException(
65                          "Mixins.mixinOf() is can not be invoked for mixin deployed using as " +
66                          m_deploymentModel
67                  );
68              }
69              m_perJVM = mixin;
70          }
71          return m_perJVM;
72      }
73  
74      /***
75       * Creates a new perClass mixin instance.
76       *
77       * @param klass
78       * @return the mixin instance
79       */
80      public Object mixinOf(final Class klass) {
81          if (m_perClassMixins.containsKey(klass)) {
82              return m_perClassMixins.get(klass);
83          }
84          synchronized (m_perClassMixins) {
85              if (!m_perClassMixins.containsKey(klass)) {
86                  final Object mixin;
87                  if (m_deploymentModel == DeploymentModel.PER_CLASS) {
88                      try {
89                          if (m_perClassConstructor != null) {
90                              mixin = m_perClassConstructor.newInstance(new Object[]{klass});
91                          } else if (m_defaultConstructor != null) {
92                              mixin = m_defaultConstructor.newInstance(new Object[]{});
93                          } else {
94                              throw new DefinitionException(
95                                      "no valid constructor found for mixin [" + m_mixinClass.getName() + "]"
96                              );
97                          }
98                      } catch (InvocationTargetException e) {
99                          throw new WrappedRuntimeException(e.getTargetException());
100                     } catch (Exception e) {
101                         throw new WrappedRuntimeException(e);
102                     }
103                 } else {
104                     throw new DefinitionException(
105                             "Mixins.mixinOf(Class) is can not be invoked for mixin deployed using as " +
106                             m_deploymentModel
107                     );
108                 }
109                 m_perClassMixins.put(klass, mixin);
110             }
111             return m_perClassMixins.get(klass);
112         }
113     }
114 
115     /***
116      * Creates a new perInstance mixin instance.
117      *
118      * @param instance
119      * @return the mixin instance
120      */
121     public Object mixinOf(final Object instance) {
122         if (m_perInstanceMixins.containsKey(instance)) {
123             return m_perInstanceMixins.get(instance);
124         }
125         synchronized (m_perInstanceMixins) {
126             if (!m_perInstanceMixins.containsKey(instance)) {
127                 final Object mixin;
128                 if (m_deploymentModel == DeploymentModel.PER_INSTANCE) {
129                     try {
130                         if (m_perInstanceConstructor != null) {
131                             mixin = m_perInstanceConstructor.newInstance(new Object[]{instance});
132                         } else if (m_defaultConstructor != null) {
133                             mixin = m_defaultConstructor.newInstance(new Object[]{});
134                         } else {
135                             throw new DefinitionException(
136                                     "no valid constructor found for mixin [" + m_mixinClass.getName() + "]"
137                             );
138                         }
139                     } catch (InvocationTargetException e) {
140                         throw new WrappedRuntimeException(e.getTargetException());
141                     } catch (Exception e) {
142                         throw new WrappedRuntimeException(e);
143                     }
144                 } else {
145                     throw new DefinitionException(
146                             "Mixins.mixinOf(Object) is can not be invoked for mixin deployed using as " +
147                             m_deploymentModel
148                     );
149                 }
150                 m_perInstanceMixins.put(instance, mixin);
151             }
152             return m_perInstanceMixins.get(instance);
153         }
154     }
155 }