1 /*
2 * Nanning Aspects
3 *
4 * Distributable under LGPL license.
5 * See terms of license at gnu.org.
6 */
7 package org.codehaus.nanning;
8
9 import java.io.Serializable;
10 import java.lang.reflect.InvocationTargetException;
11 import java.lang.reflect.Method;
12 import java.util.*;
13
14 /***
15 * A mixin consists of an interface, a target and a number of interceptors intercepting calls to methods, a mixin
16 * can also be a concrete class (no interface/implementation-separation) but at most one mixins with conrete classes
17 * per AspectInstance is supported.
18 * Create a mixin with interface and target:
19 * <pre><code>
20 new MixinInstance(Interface.class, new Target());
21 </code></pre>
22 * Create a mixin with a concrete class:
23 * <pre><code>
24 new MixinInstance(Target.class);
25 </code></pre>
26 * Add interceptor to method:
27 * <pre><code>
28 Method method = Target.class.getMethod("method", null);
29 MixinInstance mixin = new MixinInstance(Target.class);
30 mixin.addInterceptor(method, new MethodInterceptor() {
31 public Object invoke(Invocation invocation) {
32 return invocation.invokeNext();
33 }
34 }
35 </code></pre>
36 *
37 * <!-- $Id: Mixin.java,v 1.1 2003/07/12 16:48:16 lecando Exp $ -->
38 *
39 * @author $Author: lecando $
40 * @version $Revision: 1.1 $
41 */
42 public class Mixin implements Serializable {
43 static final long serialVersionUID = 7386027290257587762L;
44
45 private Class interfaceClass;
46 private Object target;
47
48 private transient Map methodInterceptors = new HashMap();
49
50 public Mixin() {
51 }
52
53 public Mixin(Class interfaceClass, Object target) {
54 setInterfaceClass(interfaceClass);
55 setTarget(target);
56 }
57
58 public void setInterfaceClass(Class interfaceClass) {
59 this.interfaceClass = interfaceClass;
60 }
61
62 public void setTarget(Object target) {
63 assert !(target instanceof Mixin);
64 this.target = target;
65 }
66
67 public Class getInterfaceClass() {
68 return interfaceClass;
69 }
70
71 public Set getAllInterceptors() {
72 Set allInterceptors = new HashSet();
73 if (methodInterceptors != null) {
74 for (Iterator methodIterator = methodInterceptors.values().iterator(); methodIterator.hasNext();) {
75 List interceptors = (List) methodIterator.next();
76 for (Iterator interceptorIterator = interceptors.iterator(); interceptorIterator.hasNext();) {
77 Interceptor interceptor = (Interceptor) interceptorIterator.next();
78 allInterceptors.add(interceptor);
79 }
80 }
81 }
82 return allInterceptors;
83 }
84
85 public Object getTarget() {
86 return target;
87 }
88
89 public List getInterceptorsForMethod(Method method) {
90 if (methodInterceptors == null) {
91 methodInterceptors = new HashMap();
92 }
93 List interceptors = (List) methodInterceptors.get(method);
94 if (interceptors == null) {
95 interceptors = new ArrayList();
96 methodInterceptors.put(method, interceptors);
97 }
98 return interceptors;
99 }
100
101 protected class InvocationImpl implements Invocation {
102 protected Object proxy;
103 protected final Method method;
104 protected final Object[] args;
105 protected ListIterator interceptors;
106
107 public InvocationImpl(Object proxy, Method method, Object[] args) {
108 this.proxy = proxy;
109 this.method = method;
110 this.args = args;
111 interceptors = getInterceptorsForMethod(method).listIterator();
112 }
113
114 public Object invokeNext() throws Throwable {
115 if (interceptors.hasNext()) {
116 return ((MethodInterceptor) interceptors.next()).invoke(this);
117 } else {
118 try {
119 return method.invoke(getTarget(), args);
120 } catch (InvocationTargetException e) {
121 throwRealException(e);
122 throw e;
123 }
124 }
125 }
126
127 private void throwRealException(InvocationTargetException e) throws Exception {
128 Throwable realException = e.getTargetException();
129 if (realException instanceof Error) {
130 throw (Error) realException;
131 } else if (realException instanceof RuntimeException) {
132 throw (RuntimeException) realException;
133 } else {
134 throw (Exception) realException;
135 }
136 }
137
138 public Interceptor getInterceptor(int index) {
139 return (Interceptor) getInterceptorsForMethod(method).get(index);
140 }
141
142 public Class getTargetInterface() {
143 return getInterfaceClass();
144 }
145
146 public AspectInstance getAspectInstance() {
147 return Aspects.getAspectInstance(getProxy());
148 }
149
150 public int getArgumentCount() {
151 return args.length;
152 }
153
154 public Object getArgument(int arg) {
155 return args[arg];
156 }
157
158 public Object getTarget() {
159 return Mixin.this.target;
160 }
161
162 public void setTarget(Object target) {
163 Mixin.this.setTarget(target);
164 }
165
166 public Object getProxy() {
167 return proxy;
168 }
169
170 public int getCurrentIndex() {
171 return interceptors.previousIndex();
172 }
173
174 public int getfInterceptorCount() {
175 return getInterceptorsForMethod(method).size();
176 }
177
178 public Method getMethod() {
179 return method;
180 }
181
182 public Object[] getArgs() {
183 return args;
184 }
185 }
186
187 public Class getMainClass() {
188 return getInterfaceClass();
189 }
190
191 public Object invokeMethod(Object proxy, Method method, Object[] args)
192 throws Throwable {
193 Invocation invocation = new InvocationImpl(proxy, method, args);
194 Object returnValue = invocation.invokeNext();
195 return returnValue;
196 }
197
198 public boolean isMainMixin() {
199 return !getInterfaceClass().isInterface();
200 }
201
202 /***
203 * Add interceptor to all methods of the mixin.
204 * @param interceptor
205 */
206 public void addInterceptor(MethodInterceptor interceptor) {
207 Method[] methods = getAllMethods();
208 for (int i = 0; i < methods.length; i++) {
209 Method method = methods[i];
210 addInterceptor(method, interceptor);
211 }
212 }
213
214 public boolean equals(Object o) {
215 if (this == o) return true;
216 if (!(o instanceof Mixin)) return false;
217
218 final Mixin mixinInstance = (Mixin) o;
219
220 if (interfaceClass != null ? !interfaceClass.equals(mixinInstance.interfaceClass) : mixinInstance.interfaceClass != null) return false;
221 if (target != null ? !target.equals(mixinInstance.target) : mixinInstance.target != null) return false;
222
223 return true;
224 }
225
226 public int hashCode() {
227 int result;
228 result = (interfaceClass != null ? interfaceClass.hashCode() : 0);
229 result = 29 * result + (target != null ? target.hashCode() : 0);
230 return result;
231 }
232
233 /***
234 * Add interceptor to specified method.
235 * @param method
236 * @param interceptor
237 */
238 public void addInterceptor(Method method, MethodInterceptor interceptor) {
239 getInterceptorsForMethod(method).add(interceptor);
240 }
241
242 public Method[] getAllMethods() {
243 return interfaceClass.getMethods();
244 }
245
246 public String toString() {
247 return "mixin{" + getTarget() + "}";
248 }
249 }
This page was automatically generated by Maven