1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.proxy2.cglib;
19
20 import java.io.Serializable;
21 import java.lang.reflect.Method;
22
23 import net.sf.cglib.proxy.Callback;
24 import net.sf.cglib.proxy.CallbackFilter;
25 import net.sf.cglib.proxy.Dispatcher;
26 import net.sf.cglib.proxy.Enhancer;
27 import net.sf.cglib.proxy.MethodInterceptor;
28 import net.sf.cglib.proxy.MethodProxy;
29
30 import org.apache.commons.lang3.ArrayUtils;
31 import org.apache.commons.lang3.ObjectUtils;
32 import org.apache.commons.proxy2.Interceptor;
33 import org.apache.commons.proxy2.Invocation;
34 import org.apache.commons.proxy2.Invoker;
35 import org.apache.commons.proxy2.ObjectProvider;
36 import org.apache.commons.proxy2.ProxyUtils;
37 import org.apache.commons.proxy2.impl.AbstractSubclassingProxyFactory;
38
39
40
41
42 public class CglibProxyFactory extends AbstractSubclassingProxyFactory
43 {
44
45
46
47
48 private static final CallbackFilter CALLBACKFILTER = new CglibProxyFactoryCallbackFilter();
49
50
51
52
53
54
55
56
57 @Override
58 public <T> T createDelegatorProxy(ClassLoader classLoader, ObjectProvider<?> targetProvider,
59 Class<?>... proxyClasses)
60 {
61 final Enhancer enhancer = new Enhancer();
62 enhancer.setClassLoader(classLoader);
63 enhancer.setInterfaces(toInterfaces(proxyClasses));
64 enhancer.setSuperclass(getSuperclass(proxyClasses));
65 enhancer.setCallbackFilter(CALLBACKFILTER);
66 enhancer.setCallbacks(new Callback[] { new ObjectProviderDispatcher(targetProvider), new EqualsHandler(),
67 new HashCodeHandler() });
68 @SuppressWarnings("unchecked")
69 final T result = (T) enhancer.create();
70 return result;
71 }
72
73
74
75
76 @Override
77 public <T> T createInterceptorProxy(ClassLoader classLoader, Object target, Interceptor interceptor,
78 Class<?>... proxyClasses)
79 {
80 final Enhancer enhancer = new Enhancer();
81 enhancer.setClassLoader(classLoader);
82 enhancer.setInterfaces(toInterfaces(proxyClasses));
83 enhancer.setSuperclass(getSuperclass(proxyClasses));
84 enhancer.setCallbackFilter(CALLBACKFILTER);
85 enhancer.setCallbacks(new Callback[] { new InterceptorBridge(target, interceptor), new EqualsHandler(),
86 new HashCodeHandler() });
87 @SuppressWarnings("unchecked")
88 final T result = (T) enhancer.create();
89 return result;
90 }
91
92
93
94
95 @Override
96 public <T> T createInvokerProxy(ClassLoader classLoader, Invoker invoker, Class<?>... proxyClasses)
97 {
98 final Enhancer enhancer = new Enhancer();
99 enhancer.setClassLoader(classLoader);
100 enhancer.setInterfaces(toInterfaces(proxyClasses));
101 enhancer.setSuperclass(getSuperclass(proxyClasses));
102 enhancer.setCallbackFilter(CALLBACKFILTER);
103 enhancer.setCallbacks(
104 new Callback[] { new InvokerBridge(invoker), new EqualsHandler(), new HashCodeHandler() });
105 @SuppressWarnings("unchecked")
106 final T result = (T) enhancer.create();
107 return result;
108 }
109
110
111
112
113
114 private static class CglibProxyFactoryCallbackFilter implements CallbackFilter
115 {
116 @Override
117 public int accept(Method method)
118 {
119 if (ProxyUtils.isEqualsMethod(method))
120 {
121 return 1;
122 }
123 else if (ProxyUtils.isHashCode(method))
124 {
125 return 2;
126 }
127 else
128 {
129 return 0;
130 }
131 }
132 }
133
134 private static class EqualsHandler implements MethodInterceptor, Serializable
135 {
136
137 private static final long serialVersionUID = 1L;
138
139 @Override
140 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
141 {
142 return Boolean.valueOf(o == objects[0]);
143 }
144 }
145
146 private static class HashCodeHandler implements MethodInterceptor, Serializable
147 {
148
149 private static final long serialVersionUID = 1L;
150
151 @Override
152 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
153 {
154 return Integer.valueOf(System.identityHashCode(o));
155 }
156 }
157
158 private static class InterceptorBridge implements MethodInterceptor, Serializable
159 {
160
161 private static final long serialVersionUID = 1L;
162
163 private final Object target;
164 private final Interceptor inner;
165
166 public InterceptorBridge(Object target, Interceptor inner)
167 {
168 this.inner = inner;
169 this.target = target;
170 }
171
172 @Override
173 public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable
174 {
175 return inner.intercept(new MethodProxyInvocation(object, target, method, args, methodProxy));
176 }
177 }
178
179 private static class InvokerBridge implements net.sf.cglib.proxy.InvocationHandler, Serializable
180 {
181
182 private static final long serialVersionUID = 1L;
183
184 private final Invoker original;
185
186 public InvokerBridge(Invoker original)
187 {
188 this.original = original;
189 }
190
191 @Override
192 public Object invoke(Object object, Method method, Object[] objects) throws Throwable
193 {
194 return original.invoke(object, method, objects);
195 }
196 }
197
198 private static class MethodProxyInvocation implements Invocation
199 {
200 private final Object proxy;
201 private final Object target;
202 private final Method method;
203 private final Object[] args;
204 private final MethodProxy methodProxy;
205
206 public MethodProxyInvocation(Object proxy, Object target, Method method, Object[] args, MethodProxy methodProxy)
207 {
208 this.proxy = proxy;
209 this.target = target;
210 this.method = method;
211 this.methodProxy = methodProxy;
212 this.args = ObjectUtils.defaultIfNull(ArrayUtils.clone(args), ProxyUtils.EMPTY_ARGUMENTS);
213 }
214
215 @Override
216 public Method getMethod()
217 {
218 return method;
219 }
220
221 @Override
222 public Object[] getArguments()
223 {
224 return args;
225 }
226
227 @Override
228 public Object proceed() throws Throwable
229 {
230 return methodProxy.invoke(target, args);
231 }
232
233 @Override
234 public Object getProxy()
235 {
236 return proxy;
237 }
238 }
239
240 private static class ObjectProviderDispatcher implements Dispatcher, Serializable
241 {
242
243 private static final long serialVersionUID = 1L;
244
245 private final ObjectProvider<?> delegateProvider;
246
247 public ObjectProviderDispatcher(ObjectProvider<?> delegateProvider)
248 {
249 this.delegateProvider = delegateProvider;
250 }
251
252 @Override
253 public Object loadObject()
254 {
255 return delegateProvider.getObject();
256 }
257 }
258 }