1
2
3
4
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
45
46 package org.codehaus.groovy.runtime;
47
48 import groovy.lang.Closure;
49 import groovy.lang.GroovyInterceptable;
50 import groovy.lang.GroovyObject;
51 import groovy.lang.GroovyRuntimeException;
52 import groovy.lang.MetaClass;
53 import groovy.lang.MetaClassRegistry;
54 import groovy.lang.MissingMethodException;
55
56 import java.util.Map;
57
58 /***
59 * A helper class to invoke methods or extract properties on arbitrary Java objects dynamically
60 *
61 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
62 * @version $Revision: 4294 $
63 */
64 public class Invoker {
65
66 protected static final Object[] EMPTY_ARGUMENTS = {
67 };
68 protected static final Class[] EMPTY_TYPES = {
69 };
70
71 public MetaClassRegistry getMetaRegistry() {
72 return metaRegistry;
73 }
74
75 private MetaClassRegistry metaRegistry = new MetaClassRegistry();
76
77 public MetaClass getMetaClass(Object object) {
78 return metaRegistry.getMetaClass(object.getClass());
79 }
80
81 /***
82 * Invokes the given method on the object.
83 *
84 * @param object
85 * @param methodName
86 * @param arguments
87 * @return
88 */
89 public Object invokeMethod(Object object, String methodName, Object arguments) {
90
91
92
93
94
95
96
97
98
99
100
101
102 if (object == null) {
103 object = NullObject.getNullObject();
104
105 }
106
107
108 if (object instanceof Class) {
109 Class theClass = (Class) object;
110 MetaClass metaClass = metaRegistry.getMetaClass(theClass);
111 return metaClass.invokeStaticMethod(object, methodName, asArray(arguments));
112 }
113 else
114 {
115
116 if (!(object instanceof GroovyObject)) {
117 Class theClass = object.getClass();
118 MetaClass metaClass = metaRegistry.getMetaClass(theClass);
119 return metaClass.invokeMethod(object, methodName, asArray(arguments));
120 }
121
122 else {
123 GroovyObject groovy = (GroovyObject) object;
124 try {
125
126 if (groovy instanceof GroovyInterceptable) {
127 return groovy.invokeMethod(methodName, asArray(arguments));
128 }
129
130 else {
131 return groovy.getMetaClass().invokeMethod(object, methodName, asArray(arguments));
132 }
133 } catch (MissingMethodException e) {
134 if (e.getMethod().equals(methodName) && object.getClass() == e.getType()) {
135
136 return groovy.invokeMethod(methodName, asArray(arguments));
137 } else {
138 throw e;
139 }
140 }
141 }
142 }
143 }
144
145 public Object invokeSuperMethod(Object object, String methodName, Object arguments) {
146 if (object == null) {
147 throw new NullPointerException("Cannot invoke method " + methodName + "() on null object");
148 }
149
150 Class theClass = object.getClass();
151
152 MetaClass metaClass = metaRegistry.getMetaClass(theClass.getSuperclass());
153 return metaClass.invokeMethod(object, methodName, asArray(arguments));
154 }
155
156 public Object invokeStaticMethod(Class type, String method, Object arguments) {
157 MetaClass metaClass = metaRegistry.getMetaClass(type);
158 return metaClass.invokeStaticMethod(type, method, asArray(arguments));
159 }
160
161 public Object invokeConstructorOf(Class type, Object arguments) {
162 MetaClass metaClass = metaRegistry.getMetaClass(type);
163 return metaClass.invokeConstructor(asArray(arguments));
164 }
165
166 /***
167 * Converts the given object into an array; if its an array then just
168 * cast otherwise wrap it in an array
169 */
170 public Object[] asArray(Object arguments) {
171 if (arguments == null) {
172 return EMPTY_ARGUMENTS;
173 } else if (arguments instanceof Object[]) {
174 return (Object[]) arguments;
175 } else {
176 return new Object[]{arguments};
177 }
178 }
179
180 /***
181 * Looks up the given property of the given object
182 */
183 public Object getProperty(Object object, String property) {
184 if (object == null) {
185 throw new NullPointerException("Cannot get property: " + property + " on null object");
186 }
187 else if (object instanceof GroovyObject) {
188 GroovyObject pogo = (GroovyObject) object;
189 return pogo.getProperty(property);
190 }
191 else if (object instanceof Map) {
192 Map map = (Map) object;
193 return map.get(property);
194 }
195 else if (object instanceof Class) {
196 Class c = (Class) object;
197 return metaRegistry.getMetaClass(c).getProperty(object, property);
198 }
199 else {
200 return metaRegistry.getMetaClass(object.getClass()).getProperty(object, property);
201 }
202 }
203
204 /***
205 * Sets the property on the given object
206 */
207 public void setProperty(Object object, String property, Object newValue) {
208 if (object == null) {
209 throw new GroovyRuntimeException("Cannot set property on null object");
210 }
211 else if (object instanceof GroovyObject) {
212 GroovyObject pogo = (GroovyObject) object;
213 pogo.setProperty(property, newValue);
214 }
215 else if (object instanceof Map) {
216 Map map = (Map) object;
217 map.put(property, newValue);
218 }
219 else {
220 if (object instanceof Class)
221 metaRegistry.getMetaClass((Class) object).setProperty((Class) object, property, newValue);
222 else
223 metaRegistry.getMetaClass(object.getClass()).setProperty(object, property, newValue);
224 }
225 }
226
227 /***
228 * Looks up the given attribute (field) on the given object
229 */
230 public Object getAttribute(Object object, String attribute) {
231 if (object == null) {
232 throw new NullPointerException("Cannot get attribute: " + attribute + " on null object");
233
234 /***
235 } else if (object instanceof GroovyObject) {
236 GroovyObject pogo = (GroovyObject) object;
237 return pogo.getAttribute(attribute);
238 } else if (object instanceof Map) {
239 Map map = (Map) object;
240 return map.get(attribute);
241 */
242 }
243 else {
244 if (object instanceof Class) {
245 return metaRegistry.getMetaClass((Class) object).getAttribute(object, attribute);
246 } else if (object instanceof GroovyObject) {
247 return ((GroovyObject)object).getMetaClass().getAttribute(object, attribute);
248 } else {
249 return metaRegistry.getMetaClass(object.getClass()).getAttribute(object, attribute);
250 }
251 }
252 }
253
254 /***
255 * Sets the given attribute (field) on the given object
256 */
257 public void setAttribute(Object object, String attribute, Object newValue) {
258 if (object == null) {
259 throw new GroovyRuntimeException("Cannot set attribute on null object");
260
261
262
263
264
265
266
267
268 }
269 else {
270 if (object instanceof Class) {
271 metaRegistry.getMetaClass((Class) object).setAttribute(object, attribute, newValue);
272 } else if (object instanceof GroovyObject) {
273 ((GroovyObject)object).getMetaClass().setAttribute(object, attribute, newValue);
274 } else {
275 metaRegistry.getMetaClass(object.getClass()).setAttribute(object, attribute, newValue);
276 }
277 }
278 }
279
280 /***
281 * Returns the method pointer for the given object name
282 */
283 public Closure getMethodPointer(Object object, String methodName) {
284 if (object == null) {
285 throw new NullPointerException("Cannot access method pointer for '" + methodName + "' on null object");
286 }
287 return MetaClassHelper.getMethodPointer(object, methodName);
288 }
289
290 public void removeMetaClass(Class clazz) {
291 getMetaRegistry().removeMetaClass(clazz);
292 }
293 }