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.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   * Cglib-based {@link org.apache.commons.proxy2.ProxyFactory ProxyFactory} implementation.
41   */
42  public class CglibProxyFactory extends AbstractSubclassingProxyFactory
43  {
44      //******************************************************************************************************************
45      // Fields
46      //******************************************************************************************************************
47  
48      private static final CallbackFilter CALLBACKFILTER = new CglibProxyFactoryCallbackFilter();
49  
50      //******************************************************************************************************************
51      // ProxyFactory Implementation
52      //******************************************************************************************************************
53  
54      /**
55       * {@inheritDoc}
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") // type inference
69          final T result = (T) enhancer.create();
70          return result;
71      }
72  
73      /**
74       * {@inheritDoc}
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") // type inference
88          final T result = (T) enhancer.create();
89          return result;
90      }
91  
92      /**
93       * {@inheritDoc}
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") // type inference
106         final T result = (T) enhancer.create();
107         return result;
108     }
109 
110     //******************************************************************************************************************
111     // Inner Classes
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         /** Serialization version */
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         /** Serialization version */
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         /** Serialization version */
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         /** Serialization version */
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         /** Serialization version */
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 }