1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.proxy.factory.cglib;
19
20 import net.sf.cglib.proxy.Callback;
21 import net.sf.cglib.proxy.CallbackFilter;
22 import net.sf.cglib.proxy.Dispatcher;
23 import net.sf.cglib.proxy.Enhancer;
24 import net.sf.cglib.proxy.MethodProxy;
25 import net.sf.cglib.proxy.MethodInterceptor;
26 import org.apache.commons.proxy.Interceptor;
27 import org.apache.commons.proxy.Invocation;
28 import org.apache.commons.proxy.Invoker;
29 import org.apache.commons.proxy.ObjectProvider;
30 import org.apache.commons.proxy.factory.util.AbstractSubclassingProxyFactory;
31
32 import java.io.Serializable;
33 import java.lang.reflect.Method;
34
35 /**
36 * A <a href="http://cglib.sourceforge.net/">CGLIB</a>-based {@link org.apache.commons.proxy.ProxyFactory}
37 * implementation.
38 * <p/>
39 * <p/>
40 * <b>Dependencies</b>: <ul> <li>CGLIB version 2.0.2 or greater</li> </ul> </p>
41 *
42 * @author James Carman
43 * @since 1.0
44 */
45 public class CglibProxyFactory extends AbstractSubclassingProxyFactory
46 {
47 //**********************************************************************************************************************
48 // Fields
49 //**********************************************************************************************************************
50
51 private static CallbackFilter callbackFilter = new CglibProxyFactoryCallbackFilter();
52
53 //**********************************************************************************************************************
54 // Other Methods
55 //**********************************************************************************************************************
56
57 public Object createDelegatorProxy(ClassLoader classLoader, ObjectProvider targetProvider,
58 Class[] proxyClasses)
59 {
60 final Enhancer enhancer = new Enhancer();
61 enhancer.setClassLoader(classLoader);
62 enhancer.setInterfaces(toInterfaces(proxyClasses));
63 enhancer.setSuperclass(getSuperclass(proxyClasses));
64 enhancer.setCallbackFilter(callbackFilter);
65 enhancer.setCallbacks(new Callback[]{new ObjectProviderDispatcher(targetProvider), new EqualsHandler(), new HashCodeHandler()});
66 return enhancer.create();
67 }
68
69 public Object createInterceptorProxy(ClassLoader classLoader, Object target, Interceptor interceptor,
70 Class[] proxyClasses)
71 {
72 final Enhancer enhancer = new Enhancer();
73 enhancer.setClassLoader(classLoader);
74 enhancer.setInterfaces(toInterfaces(proxyClasses));
75 enhancer.setSuperclass(getSuperclass(proxyClasses));
76 enhancer.setCallbackFilter(callbackFilter);
77 enhancer.setCallbacks(new Callback[]{new InterceptorBridge(target, interceptor), new EqualsHandler(), new HashCodeHandler()});
78 return enhancer.create();
79 }
80
81 public Object createInvokerProxy(ClassLoader classLoader, Invoker invoker,
82 Class[] proxyClasses)
83 {
84 final Enhancer enhancer = new Enhancer();
85 enhancer.setClassLoader(classLoader);
86 enhancer.setInterfaces(toInterfaces(proxyClasses));
87 enhancer.setSuperclass(getSuperclass(proxyClasses));
88 enhancer.setCallbackFilter(callbackFilter);
89 enhancer.setCallbacks(new Callback[]{new InvokerBridge(invoker), new EqualsHandler(), new HashCodeHandler()});
90 return enhancer.create();
91 }
92
93 //**********************************************************************************************************************
94 // Inner Classes
95 //**********************************************************************************************************************
96
97 private static class InterceptorBridge implements net.sf.cglib.proxy.MethodInterceptor, Serializable
98 {
99 private final Interceptor inner;
100 private final Object target;
101
102 public InterceptorBridge(Object target, Interceptor inner)
103 {
104 this.inner = inner;
105 this.target = target;
106 }
107
108 public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable
109 {
110 return inner.intercept(new MethodProxyInvocation(target, method, args, methodProxy));
111 }
112 }
113
114 private static class HashCodeHandler implements MethodInterceptor, Serializable
115 {
116 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
117 {
118 return new Integer(System.identityHashCode(o));
119 }
120 }
121
122 private static class EqualsHandler implements MethodInterceptor, Serializable
123 {
124 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
125 {
126 return Boolean.valueOf(o == objects[0]);
127 }
128 }
129
130
131 private static class InvokerBridge implements net.sf.cglib.proxy.InvocationHandler, Serializable
132 {
133 private final Invoker original;
134
135 public InvokerBridge(Invoker original)
136 {
137 this.original = original;
138 }
139
140 public Object invoke(Object object, Method method, Object[] objects) throws Throwable
141 {
142 return original.invoke(object, method, objects);
143 }
144 }
145
146 private static class MethodProxyInvocation implements Invocation, Serializable
147 {
148 private final MethodProxy methodProxy;
149 private final Method method;
150 private final Object[] args;
151 private final Object target;
152
153 public MethodProxyInvocation(Object target, Method method, Object[] args, MethodProxy methodProxy)
154 {
155 this.target = target;
156 this.method = method;
157 this.methodProxy = methodProxy;
158 this.args = args;
159 }
160
161 public Method getMethod()
162 {
163 return method;
164 }
165
166 public Object[] getArguments()
167 {
168 return args;
169 }
170
171 public Object proceed() throws Throwable
172 {
173 return methodProxy.invoke(target, args);
174 }
175
176 public Object getProxy()
177 {
178 return target;
179 }
180 }
181
182 private static class ObjectProviderDispatcher implements Dispatcher, Serializable
183 {
184 private final ObjectProvider delegateProvider;
185
186 public ObjectProviderDispatcher(ObjectProvider delegateProvider)
187 {
188 this.delegateProvider = delegateProvider;
189 }
190
191 public Object loadObject()
192 {
193 return delegateProvider.getObject();
194 }
195 }
196
197 private static class CglibProxyFactoryCallbackFilter implements CallbackFilter
198 {
199 public int accept(Method method)
200 {
201 if (isEqualsMethod(method))
202 {
203 return 1;
204 }
205 else if (isHashCode(method))
206 {
207 return 2;
208 }
209 else
210 {
211 return 0;
212 }
213 }
214
215
216 }
217 }
218