1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.ibatis.common.beans;
17
18 import com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactoryUtil;
19
20 import java.util.Map;
21 import java.util.StringTokenizer;
22
23
24
25
26
27
28
29
30
31
32
33 public class ComplexBeanProbe extends BaseProbe {
34
35
36 private static final Object[] NO_ARGUMENTS = new Object[0];
37
38
39
40
41 protected ComplexBeanProbe() {
42 }
43
44
45
46
47
48
49
50
51
52 @Override
53 public String[] getReadablePropertyNames(Object object) {
54 return ClassInfo.getInstance(object.getClass()).getReadablePropertyNames();
55 }
56
57
58
59
60
61
62
63
64
65 @Override
66 public String[] getWriteablePropertyNames(Object object) {
67 return ClassInfo.getInstance(object.getClass()).getWriteablePropertyNames();
68 }
69
70
71
72
73
74
75
76
77
78
79
80 public Class getPropertyTypeForSetter(Object object, String name) {
81 Class type = object.getClass();
82
83 if (object instanceof Class) {
84 type = getClassPropertyTypeForSetter((Class) object, name);
85 } else if (object instanceof Map) {
86 Map map = (Map) object;
87 Object value = map.get(name);
88 if (value == null) {
89 type = Object.class;
90 } else {
91 type = value.getClass();
92 }
93 } else {
94 if (name.indexOf('.') > -1) {
95 StringTokenizer parser = new StringTokenizer(name, ".");
96 while (parser.hasMoreTokens()) {
97 name = parser.nextToken();
98 type = ClassInfo.getInstance(type).getSetterType(name);
99 }
100 } else {
101 type = ClassInfo.getInstance(type).getSetterType(name);
102 }
103 }
104
105 return type;
106 }
107
108
109
110
111
112
113
114
115
116
117
118 public Class getPropertyTypeForGetter(Object object, String name) {
119 Class type = object.getClass();
120
121 if (object instanceof Class) {
122 type = getClassPropertyTypeForGetter((Class) object, name);
123 } else if (object instanceof Map) {
124 Map map = (Map) object;
125 Object value = map.get(name);
126 if (value == null) {
127 type = Object.class;
128 } else {
129 type = value.getClass();
130 }
131 } else {
132 if (name.indexOf('.') > -1) {
133 StringTokenizer parser = new StringTokenizer(name, ".");
134 while (parser.hasMoreTokens()) {
135 name = parser.nextToken();
136 type = ClassInfo.getInstance(type).getGetterType(name);
137 }
138 } else {
139 type = ClassInfo.getInstance(type).getGetterType(name);
140 }
141 }
142
143 return type;
144 }
145
146
147
148
149
150
151
152
153
154
155
156 private Class getClassPropertyTypeForGetter(Class type, String name) {
157
158 if (name.indexOf('.') > -1) {
159 StringTokenizer parser = new StringTokenizer(name, ".");
160 while (parser.hasMoreTokens()) {
161 name = parser.nextToken();
162 type = ClassInfo.getInstance(type).getGetterType(name);
163 }
164 } else {
165 type = ClassInfo.getInstance(type).getGetterType(name);
166 }
167
168 return type;
169 }
170
171
172
173
174
175
176
177
178
179
180
181 private Class getClassPropertyTypeForSetter(Class type, String name) {
182
183 if (name.indexOf('.') > -1) {
184 StringTokenizer parser = new StringTokenizer(name, ".");
185 while (parser.hasMoreTokens()) {
186 name = parser.nextToken();
187 type = ClassInfo.getInstance(type).getSetterType(name);
188 }
189 } else {
190 type = ClassInfo.getInstance(type).getSetterType(name);
191 }
192
193 return type;
194 }
195
196
197
198
199
200
201
202
203
204
205
206 public Object getObject(Object object, String name) {
207 if (name.indexOf('.') > -1) {
208 StringTokenizer parser = new StringTokenizer(name, ".");
209 Object value = object;
210 while (parser.hasMoreTokens()) {
211 value = getProperty(value, parser.nextToken());
212
213 if (value == null) {
214 break;
215 }
216
217 }
218 return value;
219 } else {
220 return getProperty(object, name);
221 }
222 }
223
224
225
226
227
228
229
230
231
232
233
234 public void setObject(Object object, String name, Object value) {
235 if (name.indexOf('.') > -1) {
236 StringTokenizer parser = new StringTokenizer(name, ".");
237 String property = parser.nextToken();
238 Object child = object;
239 while (parser.hasMoreTokens()) {
240 Class type = getPropertyTypeForSetter(child, property);
241 Object parent = child;
242 child = getProperty(parent, property);
243 if (child == null) {
244 if (value == null) {
245 return;
246 } else {
247 try {
248 child = ResultObjectFactoryUtil.createObjectThroughFactory(type);
249 setObject(parent, property, child);
250 } catch (Exception e) {
251 throw new ProbeException("Cannot set value of property '" + name + "' because '" + property
252 + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(),
253 e);
254 }
255 }
256 }
257 property = parser.nextToken();
258 }
259 setProperty(child, property, value);
260 } else {
261 setProperty(object, name, value);
262 }
263 }
264
265
266
267
268
269
270
271
272
273
274
275 public boolean hasWritableProperty(Object object, String propertyName) {
276 boolean hasProperty = false;
277 if (object instanceof Map) {
278 hasProperty = true;
279 } else {
280 if (propertyName.indexOf('.') > -1) {
281 StringTokenizer parser = new StringTokenizer(propertyName, ".");
282 Class type = object.getClass();
283 while (parser.hasMoreTokens()) {
284 propertyName = parser.nextToken();
285 type = ClassInfo.getInstance(type).getGetterType(propertyName);
286 hasProperty = ClassInfo.getInstance(type).hasWritableProperty(propertyName);
287 }
288 } else {
289 hasProperty = ClassInfo.getInstance(object.getClass()).hasWritableProperty(propertyName);
290 }
291 }
292 return hasProperty;
293 }
294
295
296
297
298
299
300
301
302
303
304
305 public boolean hasReadableProperty(Object object, String propertyName) {
306 boolean hasProperty = false;
307 if (object instanceof Map) {
308 hasProperty = true;
309 } else {
310 if (propertyName.indexOf('.') > -1) {
311 StringTokenizer parser = new StringTokenizer(propertyName, ".");
312 Class type = object.getClass();
313 while (parser.hasMoreTokens()) {
314 propertyName = parser.nextToken();
315 type = ClassInfo.getInstance(type).getGetterType(propertyName);
316 hasProperty = ClassInfo.getInstance(type).hasReadableProperty(propertyName);
317 }
318 } else {
319 hasProperty = ClassInfo.getInstance(object.getClass()).hasReadableProperty(propertyName);
320 }
321 }
322 return hasProperty;
323 }
324
325 @Override
326 protected Object getProperty(Object object, String name) {
327 try {
328 Object value = null;
329 if (name.indexOf('[') > -1) {
330 value = getIndexedProperty(object, name);
331 } else {
332 if (object instanceof Map) {
333 int index = name.indexOf('.');
334 if (index > -1) {
335 String mapId = name.substring(0, index);
336 value = getProperty(((Map) object).get(mapId), name.substring(index + 1));
337 } else {
338 value = ((Map) object).get(name);
339 }
340
341 } else {
342 int index = name.indexOf('.');
343 if (index > -1) {
344 String newName = name.substring(0, index);
345 value = getProperty(getObject(object, newName), name.substring(index + 1));
346 } else {
347 ClassInfo classCache = ClassInfo.getInstance(object.getClass());
348 Invoker method = classCache.getGetInvoker(name);
349 if (method == null) {
350 throw new NoSuchMethodException(
351 "No GET method for property " + name + " on instance of " + object.getClass().getName());
352 }
353 try {
354 value = method.invoke(object, NO_ARGUMENTS);
355 } catch (Throwable t) {
356 throw ClassInfo.unwrapThrowable(t);
357 }
358 }
359
360 }
361 }
362 return value;
363 } catch (ProbeException e) {
364 throw e;
365 } catch (Throwable t) {
366 if (object == null) {
367 throw new ProbeException("Could not get property '" + name + "' from null reference. Cause: " + t.toString(),
368 t);
369 } else {
370 throw new ProbeException(
371 "Could not get property '" + name + "' from " + object.getClass().getName() + ". Cause: " + t.toString(),
372 t);
373 }
374 }
375 }
376
377 @Override
378 protected void setProperty(Object object, String name, Object value) {
379 ClassInfo classCache = ClassInfo.getInstance(object.getClass());
380 try {
381 if (name.indexOf('[') > -1) {
382 setIndexedProperty(object, name, value);
383 } else {
384 if (object instanceof Map) {
385 ((Map) object).put(name, value);
386 } else {
387 Invoker method = classCache.getSetInvoker(name);
388 if (method == null) {
389 throw new NoSuchMethodException(
390 "No SET method for property " + name + " on instance of " + object.getClass().getName());
391 }
392 Object[] params = new Object[1];
393 params[0] = value;
394 try {
395 method.invoke(object, params);
396 } catch (Throwable t) {
397 throw ClassInfo.unwrapThrowable(t);
398 }
399 }
400 }
401 } catch (ProbeException e) {
402 throw e;
403 } catch (Throwable t) {
404 throw new ProbeException("Could not set property '" + name + "' to value '" + value + "' for "
405 + object.getClass().getName() + ". Cause: " + t.toString(), t);
406 }
407 }
408
409 }