1 /*************************************************
2 * Copyright (c) Shen Li. All rights reserved. *
3 * http://joyaop.sourceforge.net *
4 * -------------------------------------------- *
5 * Distributable under LGPL license. *
6 * See terms of license at gnu.org. *
7 ************************************************/
8 package net.sf.joyaop.impl;
9
10 import net.sf.joyaop.framework.AspectFactory;
11 import net.sf.joyaop.framework.RuntimeAspect;
12
13 import java.io.IOException;
14 import java.io.ObjectInputStream;
15 import java.io.ObjectOutputStream;
16 import java.io.Serializable;
17 import java.util.HashMap;
18 import java.util.Map;
19
20 /***
21 * @author Shen Li
22 */
23 public abstract class RuntimeAspectInstance implements RuntimeInstance {
24 private static AspectFactory aspectFactory = new DefaultAspectFactory();
25 private ObjectReference implementationReference;
26 private Map parameters;
27
28 public static AspectFactory getAspectFactory() {
29 return aspectFactory;
30 }
31
32 public static void setAspectFactory(AspectFactory aspectFactory) {
33 RuntimeAspectInstance.aspectFactory = aspectFactory;
34 }
35
36 protected RuntimeAspectInstance(RuntimeAspect aspect, Class originalClass) {
37 this.parameters = aspect.getParameters();
38 this.implementationReference = createImplementationReference(aspect, originalClass);
39 }
40
41 public Object getParameter(String name) {
42 if (parameters == null) {
43 return null;
44 }
45 return parameters.get(name);
46 }
47
48 protected Object getImplementation() {
49 return implementationReference.get();
50 }
51
52 protected ObjectReference createImplementationReference(RuntimeAspect aspect, Class originalClass) {
53 if (RuntimeAspect.JVM_SCOPE.equals(aspect.getScope())) {
54 return JvmScopeObjectReference.getInstance(aspect.getAspectClass());
55 } else if (RuntimeAspect.CLASS_SCOPE.equals(aspect.getScope())) {
56 return ClassScopeObjectReference.getInstance(aspect.getAspectClass(), originalClass);
57 } else if (RuntimeAspect.INSTANCE_SCOPE.equals(aspect.getScope())) {
58 return new InstanceScopeObjectReference(aspect.getAspectClass());
59 } else if (RuntimeAspect.THREAD_SCOPE.equals(aspect.getScope())) {
60 return ThreadScopeObjectReference.getInstance(aspect.getAspectClass());
61 } else {
62 throw new IllegalArgumentException("The aspect has an unknown scope value: " + aspect.getScope());
63 }
64 }
65
66 private static Object createImplementation(Class implementationClass) {
67 return aspectFactory.newInstance(implementationClass);
68 }
69
70
71 private abstract static class ObjectReference implements Serializable {
72 protected Class implementationClass;
73
74 protected ObjectReference(Class implementationClass) {
75 this.implementationClass = implementationClass;
76 }
77
78 public abstract void set(Object implementation);
79
80 public abstract Object get();
81 }
82
83 private abstract static class LazyInitializingObjectReference extends ObjectReference {
84 protected Object implementation;
85
86 protected LazyInitializingObjectReference(Class implementationClass) {
87 super(implementationClass);
88 }
89
90 public synchronized Object get() {
91 if (implementation == null) {
92 implementation = createImplementation(implementationClass);
93 }
94 return implementation;
95 }
96
97 public void set(Object implementation) {
98 this.implementation = implementation;
99 }
100
101 private void writeObject(ObjectOutputStream out) throws IOException {
102 out.writeObject(implementationClass);
103 if (Serializable.class.isAssignableFrom(implementationClass)) {
104 out.writeObject(implementation);
105 } else {
106 out.writeObject(null);
107 }
108 }
109
110 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
111 implementationClass = (Class) in.readObject();
112 implementation = in.readObject();
113 }
114 }
115
116 private static class JvmScopeObjectReference extends LazyInitializingObjectReference {
117 private static final long serialVersionUID = 0;
118 private static final Map references = new HashMap();
119
120 public static synchronized JvmScopeObjectReference getInstance(Class implementationClass) {
121 JvmScopeObjectReference ref = (JvmScopeObjectReference) references.get(implementationClass);
122 if (ref == null) {
123 ref = new JvmScopeObjectReference(implementationClass);
124 references.put(implementationClass, ref);
125 }
126 return ref;
127 }
128
129 private JvmScopeObjectReference(Class implementationClass) {
130 super(implementationClass);
131 }
132
133 public Object readResolve() {
134 JvmScopeObjectReference ref = getInstance(implementationClass);
135 if (implementation != null) {
136 ref.set(implementation);
137 }
138 return ref;
139 }
140 }
141
142 private static class ClassScopeObjectReference extends LazyInitializingObjectReference {
143 private static final long serialVersionUID = 0;
144 private static final Map references = new HashMap();
145 private Class originalClass;
146
147 public static synchronized ClassScopeObjectReference getInstance(Class implementationClass, Class originalClass) {
148 Map refMap = (Map) references.get(originalClass);
149 if (refMap == null) {
150 refMap = new HashMap();
151 references.put(originalClass, refMap);
152 }
153 ClassScopeObjectReference ref = (ClassScopeObjectReference) refMap.get(implementationClass);
154 if (ref == null) {
155 ref = new ClassScopeObjectReference(implementationClass, originalClass);
156 refMap.put(implementationClass, ref);
157 }
158 return ref;
159 }
160
161 private ClassScopeObjectReference(Class implementationClass, Class originalClass) {
162 super(implementationClass);
163 this.originalClass = originalClass;
164 }
165
166 public Object readResolve() {
167 ClassScopeObjectReference ref = getInstance(implementationClass, originalClass);
168 if (implementation != null) {
169 ref.set(implementation);
170 }
171 return ref;
172 }
173 }
174
175 private static class InstanceScopeObjectReference extends LazyInitializingObjectReference {
176 private static final long serialVersionUID = 0;
177
178 public InstanceScopeObjectReference(Class implementationClass) {
179 super(implementationClass);
180 }
181 }
182
183 private static class ThreadScopeObjectReference extends ObjectReference {
184 private static final long serialVersionUID = 0;
185 private static final Map references = new HashMap();
186 private final transient ThreadLocal implemetationHolder = new ThreadLocal();
187
188 public static synchronized ThreadScopeObjectReference getInstance(Class implementationClass) {
189 ThreadScopeObjectReference ref = (ThreadScopeObjectReference) references.get(implementationClass);
190 if (ref == null) {
191 ref = new ThreadScopeObjectReference(implementationClass);
192 references.put(implementationClass, ref);
193 }
194 return ref;
195 }
196
197 private ThreadScopeObjectReference(Class implementationClass) {
198 super(implementationClass);
199 }
200
201 public Object get() {
202 Object impl = implemetationHolder.get();
203 if (impl == null) {
204 impl = createImplementation(implementationClass);
205 set(impl);
206 }
207 return impl;
208 }
209
210 public void set(Object object) {
211 implemetationHolder.set(object);
212 }
213
214 public Object readResolve() {
215 ThreadScopeObjectReference ref = getInstance(implementationClass);
216 return ref;
217 }
218 }
219 }