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