1 package com.atlassian.core.test.util;
2
3 import java.lang.reflect.*;
4 import java.util.*;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class DuckTypeProxy
45 {
46
47
48
49
50
51 public static UnimplementedMethodHandler RETURN_NULL = new UnimplementedMethodHandler()
52 {
53 public Object methodNotImplemented(Method method, Object[] args)
54 {
55 return null;
56 }
57 };
58
59
60
61
62 public static UnimplementedMethodHandler THROW = new UnimplementedMethodHandler()
63 {
64 public Object methodNotImplemented(Method method, Object[] args)
65 {
66 throw new UnsupportedOperationException(method.toString());
67 }
68 };
69
70
71
72
73
74
75
76
77 {
78 return getProxy(new Class[] { implementingClass }, delegates);
79 }
80
81
82
83
84
85 UnimplementedMethodHandler unimplementedMethodHandler)
86 {
87 return getProxy(new Class[] { implementingClass }, delegates, unimplementedMethodHandler);
88 }
89
90
91
92
93
94 public static Object getProxy(Class[] implementingClasses, List delegates)
95 {
96 return getProxy(implementingClasses, delegates, THROW);
97 }
98
99 public static Object getProxy(Class[] implementingClasses, List delegates, UnimplementedMethodHandler unimplementedMethodHandler)
100 {
101 return Proxy.newProxyInstance(DuckTypeProxy.class.getClassLoader(), implementingClasses, new DuckTypeInvocationHandler(delegates,
102 unimplementedMethodHandler));
103 }
104
105
106
107
108
109
110 {
111 return getProxy(new Class[] { implementingClass }, Arrays.asList(new Object[] {delegate}));
112 }
113
114
115
116 public interface UnimplementedMethodHandler
117 {
118 Object methodNotImplemented(Method method, Object[] args);
119 }
120
121
122
123
124 private static class DuckTypeInvocationHandler implements InvocationHandler
125 {
126 private final List delegates;
127 private final UnimplementedMethodHandler unimplementedMethodHandler;
128
129 DuckTypeInvocationHandler(List handlers, UnimplementedMethodHandler unimplementedMethodHandler)
130 {
131 this.delegates = Collections.unmodifiableList(new ArrayList(handlers));
132 this.unimplementedMethodHandler = unimplementedMethodHandler;
133 }
134
135 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
136 {
137 for (Iterator it = delegates.iterator(); it.hasNext();)
138 {
139 Object handler = it.next();
140 Method duckTypeMethod;
141 try
142 {
143 duckTypeMethod = handler.getClass().getMethod(method.getName(), method.getParameterTypes());
144 }
145 catch (NoSuchMethodException ignoreAndTryNext)
146 {
147 continue;
148 }
149 try
150 {
151 duckTypeMethod.setAccessible(true);
152 return duckTypeMethod.invoke(handler, args);
153 }
154 catch (IllegalArgumentException ignoreAndContinue)
155 {
156
157 }
158 catch (IllegalAccessException ignoreAndContinue)
159 {
160
161 }
162 catch (InvocationTargetException e)
163 {
164 throw e.getCause();
165 }
166 }
167 return unimplementedMethodHandler.methodNotImplemented(method, args);
168 }
169 }
170 }