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