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    }