KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > dynaop > ProxyTypeBuilder


1 package dynaop;
2
3 import java.io.IOException JavaDoc;
4 import java.io.ObjectInputStream JavaDoc;
5 import java.io.ObjectOutputStream JavaDoc;
6 import java.io.Serializable JavaDoc;
7 import java.lang.reflect.Method JavaDoc;
8 import java.util.ArrayList JavaDoc;
9 import java.util.Arrays JavaDoc;
10 import java.util.Collections JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.HashSet JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.List JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import dynaop.util.*;
19 import dynaop.util.Classes;
20 import dynaop .util.Closure;
21
22 /**
23  * <code>ProxyType</code> builder.
24  *
25  * @author Bob Lee (crazybob@crazybob.org)
26  */

27 class ProxyTypeBuilder {
28
29     private List JavaDoc interfaces = new ArrayList JavaDoc();
30     private Map JavaDoc interceptorFactories = new HashMap JavaDoc();
31     private Class JavaDoc proxiedClass;
32     
33     ProxyTypeBuilder(Class JavaDoc proxiedClass) {
34         this.proxiedClass = proxiedClass;
35         
36         List JavaDoc classes = Classes.getAllInterfacesAsList(proxiedClass);
37         classes.removeAll(Aspects.IGNORED_INTERFACES);
38         this.interfaces.addAll(classes);
39     }
40     
41     /**
42      * Creates proxy type.
43      */

44     public ProxyType createProxyType() {
45         return new ProxyTypeImpl(this);
46     }
47     
48     /**
49      * Returns true if the builder has no interceptors or mixins.
50      */

51     boolean isEmpty() {
52         return this.interceptorFactories.isEmpty();
53     }
54     
55     // interface methods.
56

57     /**
58      * Gets list of interfaces.
59      *
60      * @return <code>List</code> of <code>Class</code>.
61      */

62     public List JavaDoc getInterfaces() {
63         return Collections.unmodifiableList(this.interfaces);
64     }
65
66     /**
67      * Adds interfaces.
68      */

69     public void addInterfaces(List JavaDoc interfaces) {
70         List JavaDoc added = new ArrayList JavaDoc(interfaces);
71         added.removeAll(this.interfaces);
72         added.remove(Object JavaDoc.class);
73         this.interfaces.addAll(added);
74     }
75     
76     /**
77      * Adds interfaces.
78      */

79     public void addInterfaces(Class JavaDoc[] interfaces) {
80         addInterfaces(Arrays.asList(interfaces));
81     }
82
83     /**
84      * Adds interface.
85      */

86     public void addInterface(Class JavaDoc clazz) {
87         if (clazz == null)
88             throw new NullPointerException JavaDoc();
89         if (clazz == Object JavaDoc.class)
90             return;
91         this.interfaces.add(clazz);
92     }
93
94     // interceptor methods.
95

96     /**
97      * Gets list of interceptor factories for method.
98      *
99      * @return <code>List</code> of <code>InterceptorFactory</code>. Can be
100      * <code>null</code>.
101      */

102     public List JavaDoc getInterceptorFactories(Method JavaDoc method) {
103         return (List JavaDoc) this.interceptorFactories.get(method);
104     }
105     
106     /**
107      * Gets mutable list of interceptor factories. Creates list if necessary.
108      */

109     List JavaDoc getInterceptorFactoriesForAddition(Method JavaDoc method) {
110         List JavaDoc interceptors = (List JavaDoc) this.interceptorFactories.get(method);
111         if (interceptors == null) {
112             interceptors = new ArrayList JavaDoc();
113             this.interceptorFactories.put(method, interceptors);
114         }
115         return interceptors;
116     }
117     
118     /**
119      * Adds interceptor factory to method.
120      */

121     public void addInterceptorFactory(Method JavaDoc method,
122             InterceptorFactory factory) {
123         getInterceptorFactoriesForAddition(method).add(factory);
124     }
125     
126     /**
127      * Adds interceptor factory to all methods in current interfaces.
128      */

129     public void addInterceptorFactory(InterceptorFactory factory) {
130         addInterceptorFactory(Pointcuts.ALL_METHODS, factory);
131     }
132
133     /**
134      * Adds interceptor factory to all methods in specified interfaces.
135      */

136     public void addInterceptorFactory(Class JavaDoc[] interfaces,
137             InterceptorFactory factory) {
138         if (factory == null)
139             throw new NullPointerException JavaDoc("Factory is null.");
140
141         Set JavaDoc visitedMethods = new HashSet JavaDoc();
142         for (int i = 0; i < interfaces.length; i++) {
143             Method JavaDoc[] methods = interfaces[i].getMethods();
144             for (int methodIndex = 0; methodIndex < methods.length;
145                     methodIndex++) {
146                 Method JavaDoc method = methods[methodIndex];
147                 if (visitedMethods.contains(method))
148                     continue;
149                 visitedMethods.add(method);
150                 addInterceptorFactory(method, factory);
151             }
152         }
153     }
154
155     /**
156      * Adds interceptor factory to all methods picked by the pointcut.
157      */

158     public void addInterceptorFactory(final MethodPointcut methodPointcut,
159             final InterceptorFactory factory) {
160         if (factory == null)
161             throw new NullPointerException JavaDoc("Factory is null.");
162         
163         execute(new Closure() {
164             public void execute(Object JavaDoc o) {
165                 Method JavaDoc method = (Method JavaDoc) o;
166                 if (methodPointcut.picks(method))
167                     addInterceptorFactory(method, factory);
168             }
169         });
170     }
171     
172     /**
173      * Executes closure against every method in the current type (including
174      * methods in <code>Object</code>).
175      */

176     void execute(Closure closure) {
177         // visit each method once.
178
Set JavaDoc visited = new HashSet JavaDoc();
179
180         Method JavaDoc[] methods = Classes.OBJECT_METHODS;
181         for (int i = 0; i < methods.length; i++) {
182             Method JavaDoc m = methods[i];
183             visited.add(m);
184             closure.execute(m);
185         }
186
187         methods = getProxiedClass().getMethods();
188         for (int i = 0; i < methods.length; i++) {
189             Method JavaDoc m = methods[i];
190             visited.add(m);
191             if (m.getDeclaringClass().equals(Object JavaDoc.class))
192                 continue;
193             closure.execute(m);
194         }
195             
196         for (Iterator JavaDoc iterator = this.interfaces.iterator();
197                 iterator.hasNext();) {
198             Class JavaDoc clazz = (Class JavaDoc) iterator.next();
199             
200             methods = clazz.getMethods();
201             for (int i = 0; i < methods.length; i++) {
202                 if (visited.contains(methods[i]))
203                     continue;
204                 visited.add(methods[i]);
205                 closure.execute(methods[i]);
206             }
207         }
208     }
209     
210     public String JavaDoc toString() {
211         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
212         buffer.append("ProxyTypeBuilder[");
213         buffer.append("interfaces: ");
214         buffer.append(this.interfaces);
215         buffer.append(", interceptors: ");
216         buffer.append(this.interceptorFactories);
217         buffer.append("]");
218         return buffer.toString();
219     }
220
221     Class JavaDoc getProxiedClass() {
222         return proxiedClass;
223     }
224
225     static class ProxyTypeImpl implements ProxyType, Serializable JavaDoc {
226     
227         static long serialVersionUID = 0;
228     
229         Class JavaDoc[] interfaces;
230         transient Map JavaDoc interceptorFactories;
231         
232         ProxyTypeImpl(ProxyTypeBuilder builder) {
233             this.interfaces =
234                 (Class JavaDoc[]) builder.interfaces.toArray(
235                     new Class JavaDoc[builder.interfaces.size()]);
236             
237             // convert factory chains to arrays.
238
this.interceptorFactories = new HashMap JavaDoc();
239             for (Iterator JavaDoc i = builder.interceptorFactories.entrySet().iterator();
240                     i.hasNext();) {
241                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
242                 List JavaDoc list = (List JavaDoc) entry.getValue();
243                 this.interceptorFactories.put(
244                     entry.getKey(),
245                     list.toArray(new InterceptorFactory[list.size()])
246                 );
247             }
248         }
249         
250         public Class JavaDoc[] getInterfaces() {
251             return this.interfaces;
252         }
253         
254         public InterceptorFactory[] getInterceptorFactories(Method JavaDoc method) {
255             return (InterceptorFactory[]) this.interceptorFactories.get(method);
256         }
257         
258         public String JavaDoc toString() {
259             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
260             
261             buffer.append("ProxyType[");
262             
263             buffer.append("interfaces: ");
264             buffer.append(Arrays.asList(this.interfaces));
265             
266             buffer.append(", interceptorFactories: ");
267             Map JavaDoc map = new HashMap JavaDoc();
268             for (Iterator JavaDoc i = this.interceptorFactories.entrySet().iterator();
269                     i.hasNext();) {
270                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
271                 map.put(
272                     entry.getKey(),
273                     Arrays.asList((Object JavaDoc[]) entry.getValue())
274                 );
275             }
276             buffer.append(map);
277             
278             buffer.append("]");
279             
280             return buffer.toString();
281         }
282         
283         private void writeObject(ObjectOutputStream JavaDoc out)
284                 throws IOException JavaDoc {
285             out.defaultWriteObject();
286             out.writeObject(
287                 MethodHandle.handleMethodKeys(this.interceptorFactories));
288         }
289
290         private void readObject(ObjectInputStream JavaDoc in)
291                 throws ClassNotFoundException JavaDoc, IOException JavaDoc {
292             in.defaultReadObject();
293             this.interceptorFactories = MethodHandle.unhandleMethodKeys(
294                     (Map JavaDoc) in.readObject());
295         }
296     }
297 }
298
Popular Tags