View Javadoc

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