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 }