View Javadoc

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      // TODO serialization
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 }