1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.proxy.factory;
19
20 import org.apache.commons.proxy.Interceptor;
21 import org.apache.commons.proxy.Invocation;
22 import org.apache.commons.proxy.Invoker;
23 import org.apache.commons.proxy.ObjectProvider;
24 import org.apache.commons.proxy.ProxyFactory;
25 import org.apache.commons.proxy.provider.BeanProvider;
26 import org.apache.commons.proxy.provider.ConstantProvider;
27 import org.apache.commons.proxy.provider.SingletonProvider;
28 import org.apache.commons.proxy.util.AbstractTestCase;
29 import org.apache.commons.proxy.util.DuplicateEcho;
30 import org.apache.commons.proxy.util.Echo;
31 import org.apache.commons.proxy.util.EchoImpl;
32 import org.apache.commons.proxy.util.SuffixInterceptor;
33
34 import java.io.IOException;
35 import java.io.Serializable;
36 import java.lang.reflect.Method;
37 import java.util.Arrays;
38 import java.util.LinkedList;
39 import java.util.List;
40 import java.util.SortedSet;
41 import java.util.TreeSet;
42 import java.util.Date;
43
44 /**
45 * @author James Carman
46 * @since 1.0
47 */
48 public abstract class AbstractProxyFactoryTestCase extends AbstractTestCase
49 {
50 //**********************************************************************************************************************
51 // Fields
52 //**********************************************************************************************************************
53
54 private static final Class[] ECHO_ONLY = new Class[]{Echo.class};
55 protected final ProxyFactory factory;
56 private static final Class[] COMPARABLE_ONLY = new Class[] { Comparable.class };
57
58 //**********************************************************************************************************************
59 // Constructors
60 //**********************************************************************************************************************
61
62 protected AbstractProxyFactoryTestCase(ProxyFactory factory)
63 {
64 this.factory = factory;
65 }
66
67 //**********************************************************************************************************************
68 // Other Methods
69 //**********************************************************************************************************************
70
71 private ObjectProvider createSingletonEcho()
72 {
73 return new SingletonProvider(new BeanProvider(EchoImpl.class));
74 }
75
76 public void testInterceptorHashCode()
77 {
78 final Echo proxy = (Echo) factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY);
79 assertEquals(proxy.hashCode(), System.identityHashCode(proxy));
80 }
81
82 public void testInvokerHashCode() throws Exception
83 {
84 final Echo proxy = (Echo) factory.createInvokerProxy(new InvokerTester(), ECHO_ONLY);
85 assertEquals(proxy.hashCode(), System.identityHashCode(proxy));
86 }
87
88 public void testDelegatorHashCode() throws Exception
89 {
90 final Echo proxy = (Echo) factory.createDelegatorProxy(new ConstantProvider(new EchoImpl()), ECHO_ONLY);
91 assertEquals(proxy.hashCode(), System.identityHashCode(proxy));
92 }
93
94
95 public void testInterceptorEquals()
96 {
97 final Date date = new Date();
98 final Comparable proxy1 = (Comparable) factory.createInterceptorProxy(date,
99 new NoOpMethodInterceptor(), COMPARABLE_ONLY);
100 final Comparable proxy2 = (Comparable) factory.createInterceptorProxy(date,
101 new NoOpMethodInterceptor(), COMPARABLE_ONLY);
102 assertEquals(proxy1, proxy1);
103 assertFalse(proxy1.equals(proxy2));
104 assertFalse(proxy2.equals(proxy1));
105 }
106
107 public void testInvokerEquals() throws Exception
108 {
109 final Comparable proxy1 = (Comparable) factory.createInvokerProxy(new InvokerTester(), COMPARABLE_ONLY);
110 final Comparable proxy2 = (Comparable) factory.createInvokerProxy(new InvokerTester(), COMPARABLE_ONLY);
111 assertEquals(proxy1, proxy1);
112 assertFalse(proxy1.equals(proxy2));
113 assertFalse(proxy2.equals(proxy1));
114 }
115
116 public void testDelegatorEquals() throws Exception
117 {
118 final Date date = new Date();
119 final Comparable proxy1 = (Comparable) factory.createDelegatorProxy(new ConstantProvider(date),
120 COMPARABLE_ONLY);
121 final Comparable proxy2 = (Comparable) factory.createDelegatorProxy(new ConstantProvider(date),
122 COMPARABLE_ONLY);
123 assertEquals(proxy1, proxy1);
124 assertFalse(proxy1.equals(proxy2));
125 assertFalse(proxy2.equals(proxy1));
126 }
127
128 public void testBooleanInterceptorParameter()
129 {
130 final Echo echo = (Echo) factory.createInterceptorProxy(new EchoImpl(), new InterceptorTester(), ECHO_ONLY);
131 assertFalse(echo.echoBack(false));
132 assertTrue(echo.echoBack(true));
133 }
134
135 public void testCanProxy()
136 {
137 assertTrue(factory.canProxy(ECHO_ONLY));
138 assertFalse(factory.canProxy(new Class[]{EchoImpl.class}));
139 }
140
141 public void testChangingArguments()
142 {
143 final Echo proxy = (Echo) factory.createInterceptorProxy(new EchoImpl(), new ChangeArgumentInterceptor(), ECHO_ONLY);
144 assertEquals("something different", proxy.echoBack("whatever"));
145 }
146
147 public void testCreateDelegatingProxy()
148 {
149 final Echo echo = (Echo) factory.createDelegatorProxy(createSingletonEcho(), ECHO_ONLY);
150 echo.echo();
151 assertEquals("message", echo.echoBack("message"));
152 assertEquals("ab", echo.echoBack("a", "b"));
153 }
154
155 public void testCreateInterceptorProxy()
156 {
157 final Echo target = (Echo) factory.createDelegatorProxy(createSingletonEcho(), ECHO_ONLY);
158 final Echo proxy = (Echo) factory.createInterceptorProxy(target, new SuffixInterceptor(" suffix"), ECHO_ONLY);
159 proxy.echo();
160 assertEquals("message suffix", proxy.echoBack("message"));
161 }
162
163 public void testDelegatingProxyClassCaching() throws Exception
164 {
165 final Echo proxy1 = (Echo) factory.createDelegatorProxy(new ConstantProvider(new EchoImpl()), ECHO_ONLY);
166 final Echo proxy2 = (Echo) factory.createDelegatorProxy(new ConstantProvider(new EchoImpl()), ECHO_ONLY);
167 assertNotSame(proxy1, proxy2);
168 assertSame(proxy1.getClass(), proxy2.getClass());
169 }
170
171 public void testDelegatingProxyInterfaceOrder()
172 {
173 final Echo echo = (Echo) factory.createDelegatorProxy(createSingletonEcho(), new Class[]{Echo.class, DuplicateEcho.class});
174 final List expected = new LinkedList(Arrays.asList(new Class[]{Echo.class, DuplicateEcho.class}));
175 final List actual = new LinkedList(Arrays.asList(echo.getClass().getInterfaces()));
176 actual.retainAll(expected); // Doesn't alter order!
177 assertEquals(expected, actual);
178 }
179
180 public void testDelegatingProxySerializable() throws Exception
181 {
182 final Echo proxy = (Echo) factory.createDelegatorProxy(new ConstantProvider(new EchoImpl()), ECHO_ONLY);
183 assertSerializable(proxy);
184 }
185
186 public void testInterceptingProxyClassCaching() throws Exception
187 {
188 final Echo proxy1 = (Echo) factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY);
189 final Echo proxy2 = (Echo) factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY);
190 assertNotSame(proxy1, proxy2);
191 assertSame(proxy1.getClass(), proxy2.getClass());
192 }
193
194 public void testInterceptingProxySerializable() throws Exception
195 {
196 final Echo proxy = (Echo) factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY);
197 assertSerializable(proxy);
198 }
199
200 public void testInterceptorProxyWithCheckedException() throws Exception
201 {
202 final Echo proxy = (Echo) factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY);
203 try
204 {
205 proxy.ioException();
206 fail();
207 }
208 catch (IOException e)
209 {
210 }
211 }
212
213 public void testInterceptorProxyWithUncheckedException() throws Exception
214 {
215 final Echo proxy = (Echo) factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), ECHO_ONLY);
216 try
217 {
218 proxy.illegalArgument();
219 fail();
220 }
221 catch (IllegalArgumentException e)
222 {
223 }
224 }
225
226 public void testInterfaceHierarchies()
227 {
228 final SortedSet set = (SortedSet) factory.createDelegatorProxy(new ConstantProvider(new TreeSet()), new Class[]{SortedSet.class});
229 set.add("Hello");
230 }
231
232 public void testInvokerProxy() throws Exception
233 {
234 final InvokerTester tester = new InvokerTester();
235 final Echo echo = (Echo) factory.createInvokerProxy(tester, ECHO_ONLY);
236 echo.echoBack("hello");
237 assertEquals(Echo.class.getMethod("echoBack", new Class[]{String.class}), tester.method);
238 assertSame(echo, tester.proxy);
239 assertNotNull(tester.args);
240 assertEquals(1, tester.args.length);
241 assertEquals("hello", tester.args[0]);
242 }
243
244 public void testInvokerProxyClassCaching() throws Exception
245 {
246 final Echo proxy1 = (Echo) factory.createInvokerProxy(new InvokerTester(), ECHO_ONLY);
247 final Echo proxy2 = (Echo) factory.createInvokerProxy(new InvokerTester(), ECHO_ONLY);
248 assertNotSame(proxy1, proxy2);
249 assertSame(proxy1.getClass(), proxy2.getClass());
250 }
251
252 public void testInvokerProxySerializable() throws Exception
253 {
254 final Echo proxy = (Echo) factory.createInvokerProxy(new InvokerTester(), ECHO_ONLY);
255 assertSerializable(proxy);
256 }
257
258 public void testMethodInvocationClassCaching() throws Exception
259 {
260 final InterceptorTester tester = new InterceptorTester();
261 final EchoImpl target = new EchoImpl();
262 final Echo proxy1 = (Echo) factory.createInterceptorProxy(target, tester, ECHO_ONLY);
263 final Echo proxy2 = (Echo) factory.createInterceptorProxy(target, tester, new Class[]{Echo.class, DuplicateEcho.class});
264 proxy1.echoBack("hello1");
265 final Class invocationClass1 = tester.invocationClass;
266 proxy2.echoBack("hello2");
267 assertSame(invocationClass1, tester.invocationClass);
268 }
269
270 public void testMethodInvocationDuplicateMethods() throws Exception
271 {
272 final InterceptorTester tester = new InterceptorTester();
273 final EchoImpl target = new EchoImpl();
274 final Echo proxy = (Echo) factory.createInterceptorProxy(target, tester, new Class[]{Echo.class, DuplicateEcho.class});
275 proxy.echoBack("hello");
276 assertEquals(Echo.class.getMethod("echoBack", new Class[]{String.class}), tester.method);
277 }
278
279 public void testMethodInvocationImplementation() throws Exception
280 {
281 final InterceptorTester tester = new InterceptorTester();
282 final EchoImpl target = new EchoImpl();
283 final Echo proxy = (Echo) factory.createInterceptorProxy(target, tester, ECHO_ONLY);
284 proxy.echo();
285 assertNotNull(tester.arguments);
286 assertEquals(0, tester.arguments.length);
287 assertEquals(Echo.class.getMethod("echo", new Class[]{}), tester.method);
288 assertEquals(target, tester.proxy);
289 proxy.echoBack("Hello");
290 assertNotNull(tester.arguments);
291 assertEquals(1, tester.arguments.length);
292 assertEquals("Hello", tester.arguments[0]);
293 assertEquals(Echo.class.getMethod("echoBack", new Class[]{String.class}), tester.method);
294 proxy.echoBack("Hello", "World");
295 assertNotNull(tester.arguments);
296 assertEquals(2, tester.arguments.length);
297 assertEquals("Hello", tester.arguments[0]);
298 assertEquals("World", tester.arguments[1]);
299 assertEquals(Echo.class.getMethod("echoBack", new Class[]{String.class, String.class}), tester.method);
300 }
301
302 public void testPrimitiveParameter()
303 {
304 final Echo echo = (Echo) factory.createDelegatorProxy(createSingletonEcho(), ECHO_ONLY);
305 assertEquals(1, echo.echoBack(1));
306 }
307
308 public void testProxyWithCheckedException() throws Exception
309 {
310 final Echo proxy = (Echo) factory.createDelegatorProxy(new ConstantProvider(new EchoImpl()), ECHO_ONLY);
311 try
312 {
313 proxy.ioException();
314 fail();
315 }
316 catch (IOException e)
317 {
318 }
319 }
320
321 public void testProxyWithUncheckedException() throws Exception
322 {
323 final Echo proxy = (Echo) factory.createDelegatorProxy(new ConstantProvider(new EchoImpl()), ECHO_ONLY);
324 try
325 {
326 proxy.illegalArgument();
327 fail();
328 }
329 catch (IllegalArgumentException e)
330 {
331 }
332 }
333
334 public void testWithNonAccessibleTargetType()
335 {
336 final Echo proxy = (Echo) factory.createInterceptorProxy(new PrivateEcho(), new NoOpMethodInterceptor(), ECHO_ONLY);
337 proxy.echo();
338 }
339
340 //**********************************************************************************************************************
341 // Inner Classes
342 //**********************************************************************************************************************
343
344 private static class ChangeArgumentInterceptor implements Interceptor
345 {
346 public Object intercept(Invocation methodInvocation) throws Throwable
347 {
348 methodInvocation.getArguments()[0] = "something different";
349 return methodInvocation.proceed();
350 }
351 }
352
353 protected static class InterceptorTester implements Interceptor
354 {
355 private Object[] arguments;
356 private Method method;
357 private Object proxy;
358 private Class invocationClass;
359
360 public Object intercept(Invocation methodInvocation) throws Throwable
361 {
362 arguments = methodInvocation.getArguments();
363 method = methodInvocation.getMethod();
364 proxy = methodInvocation.getProxy();
365 invocationClass = methodInvocation.getClass();
366 return methodInvocation.proceed();
367 }
368 }
369
370 protected static class InvokerTester implements Invoker
371 {
372 private Object method;
373 private Object[] args;
374 private Object proxy;
375
376 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
377 {
378 this.proxy = proxy;
379 this.method = method;
380 this.args = args;
381 return null;
382 }
383 }
384
385 protected static class NoOpMethodInterceptor implements Interceptor, Serializable
386 {
387 public Object intercept(Invocation methodInvocation) throws Throwable
388 {
389 return methodInvocation.proceed();
390 }
391 }
392
393 private static class PrivateEcho extends EchoImpl
394 {
395 }
396 }