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 = {};
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 @Override
81 public Class getPropertyTypeForSetter(Object object, String name) {
82 Class type = object.getClass();
83
84 if (object instanceof Class) {
85 type = getClassPropertyTypeForSetter((Class) object, name);
86 } else if (object instanceof Map) {
87 Map map = (Map) object;
88 Object value = map.get(name);
89 if (value == null) {
90 type = Object.class;
91 } else {
92 type = value.getClass();
93 }
94 } else 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 return type;
105 }
106
107
108
109
110
111
112
113
114
115
116
117 @Override
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 if (name.indexOf('.') > -1) {
132 StringTokenizer parser = new StringTokenizer(name, ".");
133 while (parser.hasMoreTokens()) {
134 name = parser.nextToken();
135 type = ClassInfo.getInstance(type).getGetterType(name);
136 }
137 } else {
138 type = ClassInfo.getInstance(type).getGetterType(name);
139 }
140
141 return type;
142 }
143
144
145
146
147
148
149
150
151
152
153
154 private Class getClassPropertyTypeForGetter(Class type, String name) {
155
156 if (name.indexOf('.') > -1) {
157 StringTokenizer parser = new StringTokenizer(name, ".");
158 while (parser.hasMoreTokens()) {
159 name = parser.nextToken();
160 type = ClassInfo.getInstance(type).getGetterType(name);
161 }
162 } else {
163 type = ClassInfo.getInstance(type).getGetterType(name);
164 }
165
166 return type;
167 }
168
169
170
171
172
173
174
175
176
177
178
179 private Class getClassPropertyTypeForSetter(Class type, String name) {
180
181 if (name.indexOf('.') > -1) {
182 StringTokenizer parser = new StringTokenizer(name, ".");
183 while (parser.hasMoreTokens()) {
184 name = parser.nextToken();
185 type = ClassInfo.getInstance(type).getSetterType(name);
186 }
187 } else {
188 type = ClassInfo.getInstance(type).getSetterType(name);
189 }
190
191 return type;
192 }
193
194
195
196
197
198
199
200
201
202
203
204 @Override
205 public Object getObject(Object object, String name) {
206 if (name.indexOf('.') <= -1) {
207 return getProperty(object, name);
208 }
209 StringTokenizer parser = new StringTokenizer(name, ".");
210 Object value = object;
211 while (parser.hasMoreTokens()) {
212 value = getProperty(value, parser.nextToken());
213
214 if (value == null) {
215 break;
216 }
217
218 }
219 return value;
220 }
221
222
223
224
225
226
227
228
229
230
231
232 @Override
233 public void setObject(Object object, String name, Object value) {
234 if (name.indexOf('.') > -1) {
235 StringTokenizer parser = new StringTokenizer(name, ".");
236 String property = parser.nextToken();
237 Object child = object;
238 while (parser.hasMoreTokens()) {
239 Class type = getPropertyTypeForSetter(child, property);
240 Object parent = child;
241 child = getProperty(parent, property);
242 if (child == null) {
243 if (value == null) {
244 return;
245 }
246 try {
247 child = ResultObjectFactoryUtil.createObjectThroughFactory(type);
248 setObject(parent, property, child);
249 } catch (Exception e) {
250 throw new ProbeException("Cannot set value of property '" + name + "' because '" + property
251 + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(),
252 e);
253 }
254 }
255 property = parser.nextToken();
256 }
257 setProperty(child, property, value);
258 } else {
259 setProperty(object, name, value);
260 }
261 }
262
263
264
265
266
267
268
269
270
271
272
273 @Override
274 public boolean hasWritableProperty(Object object, String propertyName) {
275 boolean hasProperty = false;
276 if (object instanceof Map) {
277 hasProperty = true;
278 } else if (propertyName.indexOf('.') > -1) {
279 StringTokenizer parser = new StringTokenizer(propertyName, ".");
280 Class type = object.getClass();
281 while (parser.hasMoreTokens()) {
282 propertyName = parser.nextToken();
283 type = ClassInfo.getInstance(type).getGetterType(propertyName);
284 hasProperty = ClassInfo.getInstance(type).hasWritableProperty(propertyName);
285 }
286 } else {
287 hasProperty = ClassInfo.getInstance(object.getClass()).hasWritableProperty(propertyName);
288 }
289 return hasProperty;
290 }
291
292
293
294
295
296
297
298
299
300
301
302 @Override
303 public boolean hasReadableProperty(Object object, String propertyName) {
304 boolean hasProperty = false;
305 if (object instanceof Map) {
306 hasProperty = true;
307 } else if (propertyName.indexOf('.') > -1) {
308 StringTokenizer parser = new StringTokenizer(propertyName, ".");
309 Class type = object.getClass();
310 while (parser.hasMoreTokens()) {
311 propertyName = parser.nextToken();
312 type = ClassInfo.getInstance(type).getGetterType(propertyName);
313 hasProperty = ClassInfo.getInstance(type).hasReadableProperty(propertyName);
314 }
315 } else {
316 hasProperty = ClassInfo.getInstance(object.getClass()).hasReadableProperty(propertyName);
317 }
318 return hasProperty;
319 }
320
321 @Override
322 protected Object getProperty(Object object, String name) {
323 try {
324 Object value = null;
325 if (name.indexOf('[') > -1) {
326 value = getIndexedProperty(object, name);
327 } else if (object instanceof Map) {
328 int index = name.indexOf('.');
329 if (index > -1) {
330 String mapId = name.substring(0, index);
331 value = getProperty(((Map) object).get(mapId), name.substring(index + 1));
332 } else {
333 value = ((Map) object).get(name);
334 }
335
336 } else {
337 int index = name.indexOf('.');
338 if (index > -1) {
339 String newName = name.substring(0, index);
340 value = getProperty(getObject(object, newName), name.substring(index + 1));
341 } else {
342 ClassInfo classCache = ClassInfo.getInstance(object.getClass());
343 Invoker method = classCache.getGetInvoker(name);
344 if (method == null) {
345 throw new NoSuchMethodException(
346 "No GET method for property " + name + " on instance of " + object.getClass().getName());
347 }
348 try {
349 value = method.invoke(object, NO_ARGUMENTS);
350 } catch (Throwable t) {
351 throw ClassInfo.unwrapThrowable(t);
352 }
353 }
354
355 }
356 return value;
357 } catch (ProbeException e) {
358 throw e;
359 } catch (Throwable t) {
360 if (object == null) {
361 throw new ProbeException("Could not get property '" + name + "' from null reference. Cause: " + t.toString(),
362 t);
363 }
364 throw new ProbeException(
365 "Could not get property '" + name + "' from " + object.getClass().getName() + ". Cause: " + t.toString(), t);
366 }
367 }
368
369 @Override
370 protected void setProperty(Object object, String name, Object value) {
371 ClassInfo classCache = ClassInfo.getInstance(object.getClass());
372 try {
373 if (name.indexOf('[') > -1) {
374 setIndexedProperty(object, name, value);
375 } else if (object instanceof Map) {
376 ((Map) object).put(name, value);
377 } else {
378 Invoker method = classCache.getSetInvoker(name);
379 if (method == null) {
380 throw new NoSuchMethodException(
381 "No SET method for property " + name + " on instance of " + object.getClass().getName());
382 }
383 Object[] params = new Object[1];
384 params[0] = value;
385 try {
386 method.invoke(object, params);
387 } catch (Throwable t) {
388 throw ClassInfo.unwrapThrowable(t);
389 }
390 }
391 } catch (ProbeException e) {
392 throw e;
393 } catch (Throwable t) {
394 throw new ProbeException("Could not set property '" + name + "' to value '" + value + "' for "
395 + object.getClass().getName() + ". Cause: " + t.toString(), t);
396 }
397 }
398
399 }