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.NoOp; 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.lang.reflect.Method; 033 import java.lang.reflect.Modifier; 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 PublicCallbackFilter(); 052 053 //---------------------------------------------------------------------------------------------------------------------- 054 // ProxyFactory Implementation 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 ), NoOp.INSTANCE } ); 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 ), NoOp.INSTANCE } ); 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 ), NoOp.INSTANCE } ); 090 return enhancer.create(); 091 } 092 093 //---------------------------------------------------------------------------------------------------------------------- 094 // Inner Classes 095 //---------------------------------------------------------------------------------------------------------------------- 096 097 private static class PublicCallbackFilter implements CallbackFilter 098 { 099 public int accept( Method method ) 100 { 101 return Modifier.isPublic( method.getModifiers() ) ? 0 : 1; 102 } 103 } 104 105 private class InvokerBridge implements net.sf.cglib.proxy.InvocationHandler 106 { 107 private final Invoker original; 108 109 public InvokerBridge( Invoker original ) 110 { 111 this.original = original; 112 } 113 114 public Object invoke( Object object, Method method, Object[] objects ) throws Throwable 115 { 116 return original.invoke( object, method, objects ); 117 } 118 } 119 120 private class InterceptorBridge implements net.sf.cglib.proxy.MethodInterceptor 121 { 122 private final Interceptor inner; 123 private final Object target; 124 125 public InterceptorBridge( Object target, Interceptor inner ) 126 { 127 this.inner = inner; 128 this.target = target; 129 } 130 131 public Object intercept( Object object, Method method, Object[] args, MethodProxy methodProxy ) throws Throwable 132 { 133 return inner.intercept( new MethodProxyInvocation( target, method, args, methodProxy ) ); 134 } 135 } 136 137 private class MethodProxyInvocation implements Invocation 138 { 139 private final MethodProxy methodProxy; 140 private final Method method; 141 private final Object[] args; 142 private final Object target; 143 144 public MethodProxyInvocation( Object target, Method method, Object[] args, MethodProxy methodProxy ) 145 { 146 this.target = target; 147 this.method = method; 148 this.methodProxy = methodProxy; 149 this.args = args; 150 } 151 152 public Method getMethod() 153 { 154 return method; 155 } 156 157 public Object[] getArguments() 158 { 159 return args; 160 } 161 162 public Object proceed() throws Throwable 163 { 164 return methodProxy.invoke( target, args ); 165 } 166 167 public Object getProxy() 168 { 169 return target; 170 } 171 } 172 173 private class ObjectProviderDispatcher implements Dispatcher 174 { 175 private final ObjectProvider delegateProvider; 176 177 public ObjectProviderDispatcher( ObjectProvider delegateProvider ) 178 { 179 this.delegateProvider = delegateProvider; 180 } 181 182 public Object loadObject() 183 { 184 return delegateProvider.getObject(); 185 } 186 } 187 } 188