1 package org.neo.swarm.core.aop.silc.comp;
2
3 import java.io.Serializable;
4 import java.lang.reflect.AccessibleObject;
5 import java.lang.reflect.Method;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.LinkedList;
11 import java.util.List;
12 import java.util.Map;
13
14 import org.neo.swarm.core.aop.AspectComponent;
15
16
17 /***
18 * This class manages the interceptor chain for an aspected component.
19 *
20 * @author damiang
21 * @author navery
22 */
23 public class AspectComponentImpl extends AccessibleObject implements AspectComponent, Serializable {
24 private Class[] interfaces;
25 private Object key;
26 private Object target;
27 private Map perspectiveInterceptors;
28 private ProxyFactory proxyFactory;
29
30 public AspectComponentImpl(Object key, Class[] interfaces, Object target, ProxyFactory proxyFactory) {
31 if (interfaces == null || interfaces.length == 0) {
32 throw new IllegalArgumentException("interfaces must be supplied");
33 }
34 if (target == null) {
35 throw new IllegalArgumentException("target must not be null");
36 }
37 if (proxyFactory == null) {
38 throw new IllegalArgumentException("ProxyFactory must not be null");
39 }
40 this.key = key;
41 this.target = target;
42 this.interfaces = interfaces;
43 this.proxyFactory = proxyFactory;
44 perspectiveInterceptors = new HashMap();
45
46 addPerspective(Perspective.DEFAULT);
47 }
48
49 /***
50 * Apply an interceptor to all methods - and if needed classify it using the given perspective.
51 */
52 public void addInterceptor(Perspective perspective, MethodInterceptor methodInterceptor) {
53 for (Iterator iter = getPerspectiveInterceptorMap(perspective).values().iterator(); iter.hasNext();) {
54 List interceptors = (List) iter.next();
55 if (!interceptors.contains(methodInterceptor)) {
56 interceptors.add(methodInterceptor);
57 }
58 }
59 }
60
61 /***
62 * Apply interceptor to only one method.
63 * @param method
64 * @param interceptor
65 */
66 public void addInterceptor(Perspective perspective, Method method, MethodInterceptor interceptor) {
67 List interceptors = getInterceptorsForMethod(perspective, method);
68 if (!interceptors.contains(interceptor)) {
69 interceptors.add(interceptor);
70 }
71 }
72
73 public Object getTarget() {
74 return target;
75 }
76
77 public Object getProxy() {
78 return getProxy(Perspective.DEFAULT);
79 }
80
81 public Object getProxy(Perspective perspective) {
82 return proxyFactory.createProxy(perspective, key, interfaces, this);
83 }
84
85
86 public Object getCGLibProxy() {
87 return proxyFactory.createProxy(key, interfaces, this, getPerspectiveInterceptorMap(Perspective.DEFAULT));
88 }
89
90 /***
91 * callback from the invocation handler - this is where we need to apply the associated perspective.
92 */
93 public Object invokeMethod(Object key, Perspective perspective, Object proxy, Method method, Object[] args) throws Throwable {
94 Invocation invocation = getInvocation(key, perspective, method, args);
95 return invocation.proceed();
96 }
97
98 public Method[] getInterfaceMethods() {
99 ArrayList list = new ArrayList();
100 for (int i = 0; i < interfaces.length; i++) {
101 Class anInterface = interfaces[i];
102 list.addAll(Arrays.asList(anInterface.getMethods()));
103 }
104 return (Method[]) list.toArray(new Method[list.size()]);
105 }
106
107 public Class[] getInterfaces() {
108 return interfaces;
109 }
110
111 private Map getPerspectiveInterceptorMap(Perspective perspective) {
112 if (perspectiveInterceptors.get(perspective) == null) {
113 addPerspective(perspective);
114 }
115 return (Map) perspectiveInterceptors.get(perspective);
116 }
117
118
119 private Invocation getInvocation(Object key, Perspective perspective, Method method, Object[] args) {
120 return new AspectInvocation(this, key, target, method, args, getInterceptorsAsArray(perspective, method));
121 }
122
123 private MethodInterceptor[] getInterceptorsAsArray(Perspective perspective, Method method) {
124 List interceptors = getInterceptorsForMethod(perspective, method);
125 if (interceptors == null) {
126 return new MethodInterceptor[0];
127 }
128 return (MethodInterceptor[]) interceptors.toArray(new MethodInterceptor[interceptors.size()]);
129 }
130
131 private List getInterceptorsForMethod(Perspective perspective, Method method) {
132 Map methodMap = getPerspectiveInterceptorMap(perspective);
133 return (List) methodMap.get(getMethodKey(method));
134 }
135
136 private Map createMethodToInterceptorMap() {
137 Map map = new HashMap();
138 for (int i = 0; i < interfaces.length; i++) {
139 initInterceptorChain(interfaces[i].getMethods(), map);
140 }
141 return map;
142 }
143
144 private void initInterceptorChain(Method[] methods, Map map) {
145 for (int i = 0; i < methods.length; i++) {
146 map.put(getMethodKey(methods[i]), new LinkedList());
147 }
148 }
149
150
151 private String getMethodKey(Method method) {
152 return method.getDeclaringClass().getName() + "." + method.getName();
153 }
154
155
156 private void addPerspective(Perspective perspective) {
157 perspectiveInterceptors.put(perspective, createMethodToInterceptorMap());
158 }
159
160 }