001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.proxy.factory.cglib;
019
020 import net.sf.cglib.proxy.Callback;
021 import net.sf.cglib.proxy.CallbackFilter;
022 import net.sf.cglib.proxy.Dispatcher;
023 import net.sf.cglib.proxy.Enhancer;
024 import net.sf.cglib.proxy.MethodProxy;
025 import net.sf.cglib.proxy.MethodInterceptor;
026 import org.apache.commons.proxy.Interceptor;
027 import org.apache.commons.proxy.Invocation;
028 import org.apache.commons.proxy.Invoker;
029 import org.apache.commons.proxy.ObjectProvider;
030 import org.apache.commons.proxy.factory.util.AbstractSubclassingProxyFactory;
031
032 import java.io.Serializable;
033 import java.lang.reflect.Method;
034
035 /**
036 * A <a href="http://cglib.sourceforge.net/">CGLIB</a>-based {@link org.apache.commons.proxy.ProxyFactory}
037 * implementation.
038 * <p/>
039 * <p/>
040 * <b>Dependencies</b>: <ul> <li>CGLIB version 2.0.2 or greater</li> </ul> </p>
041 *
042 * @author James Carman
043 * @since 1.0
044 */
045 public class CglibProxyFactory extends AbstractSubclassingProxyFactory
046 {
047 //**********************************************************************************************************************
048 // Fields
049 //**********************************************************************************************************************
050
051 private static CallbackFilter callbackFilter = new CglibProxyFactoryCallbackFilter();
052
053 //**********************************************************************************************************************
054 // Other Methods
055 //**********************************************************************************************************************
056
057 public Object createDelegatorProxy(ClassLoader classLoader, ObjectProvider targetProvider,
058 Class[] proxyClasses)
059 {
060 final Enhancer enhancer = new Enhancer();
061 enhancer.setClassLoader(classLoader);
062 enhancer.setInterfaces(toInterfaces(proxyClasses));
063 enhancer.setSuperclass(getSuperclass(proxyClasses));
064 enhancer.setCallbackFilter(callbackFilter);
065 enhancer.setCallbacks(new Callback[]{new ObjectProviderDispatcher(targetProvider), new EqualsHandler(), new HashCodeHandler()});
066 return enhancer.create();
067 }
068
069 public Object createInterceptorProxy(ClassLoader classLoader, Object target, Interceptor interceptor,
070 Class[] proxyClasses)
071 {
072 final Enhancer enhancer = new Enhancer();
073 enhancer.setClassLoader(classLoader);
074 enhancer.setInterfaces(toInterfaces(proxyClasses));
075 enhancer.setSuperclass(getSuperclass(proxyClasses));
076 enhancer.setCallbackFilter(callbackFilter);
077 enhancer.setCallbacks(new Callback[]{new InterceptorBridge(target, interceptor), new EqualsHandler(), new HashCodeHandler()});
078 return enhancer.create();
079 }
080
081 public Object createInvokerProxy(ClassLoader classLoader, Invoker invoker,
082 Class[] proxyClasses)
083 {
084 final Enhancer enhancer = new Enhancer();
085 enhancer.setClassLoader(classLoader);
086 enhancer.setInterfaces(toInterfaces(proxyClasses));
087 enhancer.setSuperclass(getSuperclass(proxyClasses));
088 enhancer.setCallbackFilter(callbackFilter);
089 enhancer.setCallbacks(new Callback[]{new InvokerBridge(invoker), new EqualsHandler(), new HashCodeHandler()});
090 return enhancer.create();
091 }
092
093 //**********************************************************************************************************************
094 // Inner Classes
095 //**********************************************************************************************************************
096
097 private static class InterceptorBridge implements net.sf.cglib.proxy.MethodInterceptor, Serializable
098 {
099 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