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 018package org.apache.commons.proxy2.cglib; 019 020import java.io.Serializable; 021import java.lang.reflect.Method; 022 023import net.sf.cglib.proxy.Callback; 024import net.sf.cglib.proxy.CallbackFilter; 025import net.sf.cglib.proxy.Dispatcher; 026import net.sf.cglib.proxy.Enhancer; 027import net.sf.cglib.proxy.MethodInterceptor; 028import net.sf.cglib.proxy.MethodProxy; 029 030import org.apache.commons.lang3.ArrayUtils; 031import org.apache.commons.lang3.ObjectUtils; 032import org.apache.commons.proxy2.Interceptor; 033import org.apache.commons.proxy2.Invocation; 034import org.apache.commons.proxy2.Invoker; 035import org.apache.commons.proxy2.ObjectProvider; 036import org.apache.commons.proxy2.ProxyUtils; 037import org.apache.commons.proxy2.impl.AbstractSubclassingProxyFactory; 038 039/** 040 * Cglib-based {@link org.apache.commons.proxy2.ProxyFactory ProxyFactory} implementation. 041 */ 042public class CglibProxyFactory extends AbstractSubclassingProxyFactory 043{ 044 //****************************************************************************************************************** 045 // Fields 046 //****************************************************************************************************************** 047 048 private static final CallbackFilter CALLBACKFILTER = new CglibProxyFactoryCallbackFilter(); 049 050 //****************************************************************************************************************** 051 // ProxyFactory Implementation 052 //****************************************************************************************************************** 053 054 /** 055 * {@inheritDoc} 056 */ 057 @Override 058 public <T> T createDelegatorProxy(ClassLoader classLoader, ObjectProvider<?> targetProvider, 059 Class<?>... proxyClasses) 060 { 061 final Enhancer enhancer = new Enhancer(); 062 enhancer.setClassLoader(classLoader); 063 enhancer.setInterfaces(toInterfaces(proxyClasses)); 064 enhancer.setSuperclass(getSuperclass(proxyClasses)); 065 enhancer.setCallbackFilter(CALLBACKFILTER); 066 enhancer.setCallbacks(new Callback[] { new ObjectProviderDispatcher(targetProvider), new EqualsHandler(), 067 new HashCodeHandler() }); 068 @SuppressWarnings("unchecked") // type inference 069 final T result = (T) enhancer.create(); 070 return result; 071 } 072 073 /** 074 * {@inheritDoc} 075 */ 076 @Override 077 public <T> T createInterceptorProxy(ClassLoader classLoader, Object target, Interceptor interceptor, 078 Class<?>... proxyClasses) 079 { 080 final Enhancer enhancer = new Enhancer(); 081 enhancer.setClassLoader(classLoader); 082 enhancer.setInterfaces(toInterfaces(proxyClasses)); 083 enhancer.setSuperclass(getSuperclass(proxyClasses)); 084 enhancer.setCallbackFilter(CALLBACKFILTER); 085 enhancer.setCallbacks(new Callback[] { new InterceptorBridge(target, interceptor), new EqualsHandler(), 086 new HashCodeHandler() }); 087 @SuppressWarnings("unchecked") // type inference 088 final T result = (T) enhancer.create(); 089 return result; 090 } 091 092 /** 093 * {@inheritDoc} 094 */ 095 @Override 096 public <T> T createInvokerProxy(ClassLoader classLoader, Invoker invoker, Class<?>... proxyClasses) 097 { 098 final Enhancer enhancer = new Enhancer(); 099 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}