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;
019
020 import junit.framework.TestCase;
021 import org.apache.commons.proxy.Interceptor;
022 import org.apache.commons.proxy.Invocation;
023 import org.apache.commons.proxy.Invoker;
024 import org.apache.commons.proxy.ObjectProvider;
025 import org.apache.commons.proxy.ProxyFactory;
026 import org.apache.commons.proxy.provider.BeanProvider;
027 import org.apache.commons.proxy.provider.ConstantProvider;
028 import org.apache.commons.proxy.provider.SingletonProvider;
029 import org.apache.commons.proxy.util.DuplicateEcho;
030 import org.apache.commons.proxy.util.Echo;
031 import org.apache.commons.proxy.util.EchoImpl;
032 import org.apache.commons.proxy.util.SuffixInterceptor;
033
034 import java.io.IOException;
035 import java.lang.reflect.Method;
036 import java.util.Arrays;
037 import java.util.LinkedList;
038 import java.util.List;
039 import java.util.SortedSet;
040 import java.util.TreeSet;
041
042 /**
043 * @author James Carman
044 * @since 1.0
045 */
046 public abstract class AbstractProxyFactoryTestCase extends TestCase
047 {
048 protected final ProxyFactory factory;
049 private static final Class[] ECHO_ONLY = new Class[] { Echo.class };
050
051 protected AbstractProxyFactoryTestCase( ProxyFactory factory )
052 {
053 this.factory = factory;
054 }
055
056 public void testCanProxy()
057 {
058 assertTrue( factory.canProxy( ECHO_ONLY ) );
059 assertFalse( factory.canProxy( new Class[] { EchoImpl.class } ) );
060 }
061
062 public void testInterfaceHierarchies()
063 {
064 final SortedSet set = ( SortedSet ) factory.createDelegatorProxy( new ConstantProvider( new TreeSet() ), new Class[] { SortedSet.class } );
065 set.add( "Hello" );
066 }
067
068 public void testInvokerProxy() throws Exception
069 {
070 final InvokerTester tester = new InvokerTester();
071 final Echo echo = ( Echo )factory.createInvokerProxy( tester, ECHO_ONLY );
072 echo.echoBack( "hello" );
073 assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.method );
074 assertSame( echo, tester.proxy );
075 assertNotNull( tester.args );
076 assertEquals( 1, tester.args.length );
077 assertEquals( "hello", tester.args[0] );
078 }
079
080 public void testDelegatingProxyInterfaceOrder()
081 {
082 final Echo echo = ( Echo ) factory.createDelegatorProxy( createSingletonEcho(), new Class[] { Echo.class, DuplicateEcho.class } );
083 final List expected = new LinkedList( Arrays.asList( new Class[] { Echo.class, DuplicateEcho.class } ) );
084 final List actual = new LinkedList( Arrays.asList( echo.getClass().getInterfaces() ) );
085 actual.retainAll( expected ); // Doesn't alter order!
086 assertEquals( expected, actual );
087 }
088
089 public void testCreateDelegatingProxy()
090 {
091 final Echo echo = ( Echo ) factory.createDelegatorProxy( createSingletonEcho(), ECHO_ONLY );
092 echo.echo();
093 assertEquals( "message", echo.echoBack( "message" ) );
094 assertEquals( "ab", echo.echoBack( "a", "b" ) );
095 }
096
097 public void testBooleanInterceptorParameter()
098 {
099 final Echo echo = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new InterceptorTester(), ECHO_ONLY );
100 assertFalse( echo.echoBack( false ) );
101 assertTrue( echo.echoBack( true ) );
102
103 }
104 public void testPrimitiveParameter()
105 {
106 final Echo echo = ( Echo ) factory.createDelegatorProxy( createSingletonEcho(), ECHO_ONLY );
107 assertEquals( 1, echo.echoBack( 1 ) );
108 }
109
110 public void testCreateInterceptorProxy()
111 {
112 final Echo target = ( Echo ) factory.createDelegatorProxy( createSingletonEcho(), ECHO_ONLY );
113 final Echo proxy = ( Echo ) factory.createInterceptorProxy( target, new SuffixInterceptor( " suffix" ), ECHO_ONLY );
114 proxy.echo();
115 assertEquals( "message suffix", proxy.echoBack( "message" ) );
116 }
117
118 private ObjectProvider createSingletonEcho()
119 {
120 return new SingletonProvider( new BeanProvider( EchoImpl.class ) );
121 }
122
123 public void testMethodInvocationImplementation() throws Exception
124 {
125 final InterceptorTester tester = new InterceptorTester();
126 final EchoImpl target = new EchoImpl();
127 final Echo proxy = ( Echo ) factory.createInterceptorProxy( target, tester, ECHO_ONLY );
128 proxy.echo();
129 assertNotNull( tester.arguments );
130 assertEquals( 0, tester.arguments.length );
131 assertEquals( Echo.class.getMethod( "echo", new Class[] {} ), tester.method );
132 assertEquals( target, tester.proxy );
133 proxy.echoBack( "Hello" );
134 assertNotNull( tester.arguments );
135 assertEquals( 1, tester.arguments.length );
136 assertEquals( "Hello", tester.arguments[0] );
137 assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.method );
138 proxy.echoBack( "Hello", "World" );
139 assertNotNull( tester.arguments );
140 assertEquals( 2, tester.arguments.length );
141 assertEquals( "Hello", tester.arguments[0] );
142 assertEquals( "World", tester.arguments[1] );
143 assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class, String.class } ), tester.method );
144 }
145
146 public void testMethodInvocationDuplicateMethods() throws Exception
147 {
148 final InterceptorTester tester = new InterceptorTester();
149 final EchoImpl target = new EchoImpl();
150 final Echo proxy = ( Echo ) factory.createInterceptorProxy( target, tester, new Class[] { Echo.class, DuplicateEcho.class } );
151 proxy.echoBack( "hello" );
152 assertEquals( Echo.class.getMethod( "echoBack", new Class[] { String.class } ), tester.method );
153 }
154
155
156 public void testMethodInvocationClassCaching() throws Exception
157 {
158 final InterceptorTester tester = new InterceptorTester();
159 final EchoImpl target = new EchoImpl();
160 final Echo proxy1 = ( Echo ) factory.createInterceptorProxy( target, tester, ECHO_ONLY );
161 final Echo proxy2 = ( Echo ) factory.createInterceptorProxy( target, tester, new Class[] { Echo.class, DuplicateEcho.class } );
162 proxy1.echoBack( "hello1" );
163 final Class invocationClass1 = tester.invocationClass;
164 proxy2.echoBack( "hello2" );
165 assertEquals( invocationClass1, tester.invocationClass );
166 }
167
168 public void testDelegatingProxyClassCaching() throws Exception
169 {
170 final Echo proxy1 = ( Echo ) factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), ECHO_ONLY );
171 final Echo proxy2 = ( Echo ) factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), ECHO_ONLY );
172 assertEquals( proxy1.getClass(), proxy2.getClass() );
173 }
174
175 public void testInterceptingProxyClassCaching() throws Exception
176 {
177 final Echo proxy1 = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY );
178 final Echo proxy2 = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY );
179 assertEquals( proxy1.getClass(), proxy2.getClass() );
180 }
181
182 public void testProxyWithCheckedException() throws Exception
183 {
184 final Echo proxy = ( Echo ) factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), ECHO_ONLY );
185 try
186 {
187 proxy.ioException();
188 fail();
189 }
190 catch( IOException e )
191 {
192 }
193 }
194
195 public void testProxyWithUncheckedException() throws Exception
196 {
197 final Echo proxy = ( Echo ) factory.createDelegatorProxy( new ConstantProvider( new EchoImpl() ), ECHO_ONLY );
198 try
199 {
200 proxy.illegalArgument();
201 fail();
202 }
203 catch( IllegalArgumentException e )
204 {
205 }
206 }
207
208 public void testInterceptorProxyWithUncheckedException() throws Exception
209 {
210 final Echo proxy = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY );
211 try
212 {
213 proxy.illegalArgument();
214 fail();
215 }
216 catch( IllegalArgumentException e )
217 {
218 }
219 }
220
221 public void testInterceptorProxyWithCheckedException() throws Exception
222 {
223 final Echo proxy = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY );
224 try
225 {
226 proxy.ioException();
227 fail();
228 }
229 catch( IOException e )
230 {
231 }
232 }
233
234 public void testWithNonAccessibleTargetType()
235 {
236 final Echo proxy = ( Echo ) factory.createInterceptorProxy( new PrivateEcho(), new NoOpMethodInterceptor(), ECHO_ONLY );
237 proxy.echo();
238
239 }
240
241 public void testChangingArguments()
242 {
243 final Echo proxy = ( Echo ) factory.createInterceptorProxy( new EchoImpl(), new ChangeArgumentInterceptor(), ECHO_ONLY );
244 assertEquals( "something different", proxy.echoBack( "whatever" ) );
245 }
246
247 private static class PrivateEcho extends EchoImpl
248 {
249 }
250
251 private static class ChangeArgumentInterceptor implements Interceptor
252 {
253 public Object intercept( Invocation methodInvocation ) throws Throwable
254 {
255 methodInvocation.getArguments()[0] = "something different";
256 return methodInvocation.proceed();
257 }
258 }
259
260 protected static class NoOpMethodInterceptor implements Interceptor
261 {
262 public Object intercept( Invocation methodInvocation ) throws Throwable
263 {
264 return methodInvocation.proceed();
265 }
266 }
267
268 private static class InvokerTester implements Invoker
269 {
270 private Object method;
271 private Object[] args;
272 private Object proxy;
273
274 public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
275 {
276 this.proxy = proxy;
277 this.method = method;
278 this.args = args;
279 return null;
280 }
281 }
282
283 private static class InterceptorTester implements Interceptor
284 {
285 private Object[] arguments;
286 private Method method;
287 private Object proxy;
288 private Class invocationClass;
289
290 public Object intercept( Invocation methodInvocation ) throws Throwable
291 {
292 arguments = methodInvocation.getArguments();
293 method = methodInvocation.getMethod();
294 proxy = methodInvocation.getProxy();
295 invocationClass = methodInvocation.getClass();
296 return methodInvocation.proceed();
297 }
298 }
299 }