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 }