1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.beanutils;
19
20
21 import java.beans.IndexedPropertyDescriptor;
22 import java.beans.IntrospectionException;
23 import java.beans.Introspector;
24 import java.beans.PropertyDescriptor;
25 import java.lang.reflect.Array;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.concurrent.CopyOnWriteArrayList;
34
35 import org.apache.commons.beanutils.expression.DefaultResolver;
36 import org.apache.commons.beanutils.expression.Resolver;
37 import org.apache.commons.collections.FastHashMap;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 public class PropertyUtilsBean {
97
98 private Resolver resolver = new DefaultResolver();
99
100
101
102
103
104
105
106 protected static PropertyUtilsBean getInstance() {
107 return BeanUtilsBean.getInstance().getPropertyUtils();
108 }
109
110
111
112
113
114
115
116 private WeakFastHashMap<Class<?>, BeanIntrospectionData> descriptorsCache = null;
117 private WeakFastHashMap<Class<?>, FastHashMap> mappedDescriptorsCache = null;
118
119
120 private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
121
122
123 private final Log log = LogFactory.getLog(PropertyUtils.class);
124
125
126 private final List<BeanIntrospector> introspectors;
127
128
129
130
131 public PropertyUtilsBean() {
132 descriptorsCache = new WeakFastHashMap<Class<?>, BeanIntrospectionData>();
133 descriptorsCache.setFast(true);
134 mappedDescriptorsCache = new WeakFastHashMap<Class<?>, FastHashMap>();
135 mappedDescriptorsCache.setFast(true);
136 introspectors = new CopyOnWriteArrayList<BeanIntrospector>();
137 resetBeanIntrospectors();
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 public Resolver getResolver() {
158 return resolver;
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public void setResolver(final Resolver resolver) {
175 if (resolver == null) {
176 this.resolver = new DefaultResolver();
177 } else {
178 this.resolver = resolver;
179 }
180 }
181
182
183
184
185
186
187
188 public final void resetBeanIntrospectors() {
189 introspectors.clear();
190 introspectors.add(DefaultBeanIntrospector.INSTANCE);
191 }
192
193
194
195
196
197
198
199
200
201
202 public void addBeanIntrospector(final BeanIntrospector introspector) {
203 if (introspector == null) {
204 throw new IllegalArgumentException(
205 "BeanIntrospector must not be null!");
206 }
207 introspectors.add(introspector);
208 }
209
210
211
212
213
214
215
216
217
218 public boolean removeBeanIntrospector(final BeanIntrospector introspector) {
219 return introspectors.remove(introspector);
220 }
221
222
223
224
225
226
227 public void clearDescriptors() {
228
229 descriptorsCache.clear();
230 mappedDescriptorsCache.clear();
231 Introspector.flushCaches();
232
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267 public void copyProperties(final Object dest, final Object orig)
268 throws IllegalAccessException, InvocationTargetException,
269 NoSuchMethodException {
270
271 if (dest == null) {
272 throw new IllegalArgumentException
273 ("No destination bean specified");
274 }
275 if (orig == null) {
276 throw new IllegalArgumentException("No origin bean specified");
277 }
278
279 if (orig instanceof DynaBean) {
280 final DynaProperty[] origDescriptors =
281 ((DynaBean) orig).getDynaClass().getDynaProperties();
282 for (DynaProperty origDescriptor : origDescriptors) {
283 final String name = origDescriptor.getName();
284 if (isReadable(orig, name) && isWriteable(dest, name)) {
285 try {
286 final Object value = ((DynaBean) orig).get(name);
287 if (dest instanceof DynaBean) {
288 ((DynaBean) dest).set(name, value);
289 } else {
290 setSimpleProperty(dest, name, value);
291 }
292 } catch (final NoSuchMethodException e) {
293 if (log.isDebugEnabled()) {
294 log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", e);
295 }
296 }
297 }
298 }
299 } else if (orig instanceof Map) {
300 final Iterator<?> entries = ((Map<?, ?>) orig).entrySet().iterator();
301 while (entries.hasNext()) {
302 final Map.Entry<?, ?> entry = (Entry<?, ?>) entries.next();
303 final String name = (String)entry.getKey();
304 if (isWriteable(dest, name)) {
305 try {
306 if (dest instanceof DynaBean) {
307 ((DynaBean) dest).set(name, entry.getValue());
308 } else {
309 setSimpleProperty(dest, name, entry.getValue());
310 }
311 } catch (final NoSuchMethodException e) {
312 if (log.isDebugEnabled()) {
313 log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", e);
314 }
315 }
316 }
317 }
318 } else {
319 final PropertyDescriptor[] origDescriptors =
320 getPropertyDescriptors(orig);
321 for (PropertyDescriptor origDescriptor : origDescriptors) {
322 final String name = origDescriptor.getName();
323 if (isReadable(orig, name) && isWriteable(dest, name)) {
324 try {
325 final Object value = getSimpleProperty(orig, name);
326 if (dest instanceof DynaBean) {
327 ((DynaBean) dest).set(name, value);
328 } else {
329 setSimpleProperty(dest, name, value);
330 }
331 } catch (final NoSuchMethodException e) {
332 if (log.isDebugEnabled()) {
333 log.debug("Error writing to '" + name + "' on class '" + dest.getClass() + "'", e);
334 }
335 }
336 }
337 }
338 }
339
340 }
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362 public Map<String, Object> describe(final Object bean)
363 throws IllegalAccessException, InvocationTargetException,
364 NoSuchMethodException {
365
366 if (bean == null) {
367 throw new IllegalArgumentException("No bean specified");
368 }
369 final Map<String, Object> description = new HashMap<String, Object>();
370 if (bean instanceof DynaBean) {
371 final DynaProperty[] descriptors =
372 ((DynaBean) bean).getDynaClass().getDynaProperties();
373 for (DynaProperty descriptor : descriptors) {
374 final String name = descriptor.getName();
375 description.put(name, getProperty(bean, name));
376 }
377 } else {
378 final PropertyDescriptor[] descriptors =
379 getPropertyDescriptors(bean);
380 for (PropertyDescriptor descriptor : descriptors) {
381 final String name = descriptor.getName();
382 if (descriptor.getReadMethod() != null) {
383 description.put(name, getProperty(bean, name));
384 }
385 }
386 }
387 return (description);
388
389 }
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 public Object getIndexedProperty(final Object bean, String name)
417 throws IllegalAccessException, InvocationTargetException,
418 NoSuchMethodException {
419
420 if (bean == null) {
421 throw new IllegalArgumentException("No bean specified");
422 }
423 if (name == null) {
424 throw new IllegalArgumentException("No name specified for bean class '" +
425 bean.getClass() + "'");
426 }
427
428
429 int index = -1;
430 try {
431 index = resolver.getIndex(name);
432 } catch (final IllegalArgumentException e) {
433 throw new IllegalArgumentException("Invalid indexed property '" +
434 name + "' on bean class '" + bean.getClass() + "' " +
435 e.getMessage());
436 }
437 if (index < 0) {
438 throw new IllegalArgumentException("Invalid indexed property '" +
439 name + "' on bean class '" + bean.getClass() + "'");
440 }
441
442
443 name = resolver.getProperty(name);
444
445
446 return (getIndexedProperty(bean, name, index));
447
448 }
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473 public Object getIndexedProperty(final Object bean,
474 final String name, final int index)
475 throws IllegalAccessException, InvocationTargetException,
476 NoSuchMethodException {
477
478 if (bean == null) {
479 throw new IllegalArgumentException("No bean specified");
480 }
481 if (name == null || name.length() == 0) {
482 if (bean.getClass().isArray()) {
483 return Array.get(bean, index);
484 } else if (bean instanceof List) {
485 return ((List<?>)bean).get(index);
486 }
487 }
488 if (name == null) {
489 throw new IllegalArgumentException("No name specified for bean class '" +
490 bean.getClass() + "'");
491 }
492
493
494 if (bean instanceof DynaBean) {
495 final DynaProperty descriptor =
496 ((DynaBean) bean).getDynaClass().getDynaProperty(name);
497 if (descriptor == null) {
498 throw new NoSuchMethodException("Unknown property '" +
499 name + "' on bean class '" + bean.getClass() + "'");
500 }
501 return (((DynaBean) bean).get(name, index));
502 }
503
504
505 final PropertyDescriptor descriptor =
506 getPropertyDescriptor(bean, name);
507 if (descriptor == null) {
508 throw new NoSuchMethodException("Unknown property '" +
509 name + "' on bean class '" + bean.getClass() + "'");
510 }
511
512
513 if (descriptor instanceof IndexedPropertyDescriptor) {
514 Method readMethod = ((IndexedPropertyDescriptor) descriptor).
515 getIndexedReadMethod();
516 readMethod = MethodUtils.getAccessibleMethod(bean.getClass(), readMethod);
517 if (readMethod != null) {
518 final Object[] subscript = new Object[1];
519 subscript[0] = new Integer(index);
520 try {
521 return (invokeMethod(readMethod,bean, subscript));
522 } catch (final InvocationTargetException e) {
523 if (e.getTargetException() instanceof
524 IndexOutOfBoundsException) {
525 throw (IndexOutOfBoundsException)
526 e.getTargetException();
527 } else {
528 throw e;
529 }
530 }
531 }
532 }
533
534
535 final Method readMethod = getReadMethod(bean.getClass(), descriptor);
536 if (readMethod == null) {
537 throw new NoSuchMethodException("Property '" + name + "' has no " +
538 "getter method on bean class '" + bean.getClass() + "'");
539 }
540
541
542 final Object value = invokeMethod(readMethod, bean, EMPTY_OBJECT_ARRAY);
543 if (!value.getClass().isArray()) {
544 if (!(value instanceof java.util.List)) {
545 throw new IllegalArgumentException("Property '" + name +
546 "' is not indexed on bean class '" + bean.getClass() + "'");
547 } else {
548
549 return ((java.util.List<?>) value).get(index);
550 }
551 } else {
552
553 try {
554 return (Array.get(value, index));
555 } catch (final ArrayIndexOutOfBoundsException e) {
556 throw new ArrayIndexOutOfBoundsException("Index: " +
557 index + ", Size: " + Array.getLength(value) +
558 " for property '" + name + "'");
559 }
560 }
561
562 }
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584 public Object getMappedProperty(final Object bean, String name)
585 throws IllegalAccessException, InvocationTargetException,
586 NoSuchMethodException {
587
588 if (bean == null) {
589 throw new IllegalArgumentException("No bean specified");
590 }
591 if (name == null) {
592 throw new IllegalArgumentException("No name specified for bean class '" +
593 bean.getClass() + "'");
594 }
595
596
597 String key = null;
598 try {
599 key = resolver.getKey(name);
600 } catch (final IllegalArgumentException e) {
601 throw new IllegalArgumentException
602 ("Invalid mapped property '" + name +
603 "' on bean class '" + bean.getClass() + "' " + e.getMessage());
604 }
605 if (key == null) {
606 throw new IllegalArgumentException("Invalid mapped property '" +
607 name + "' on bean class '" + bean.getClass() + "'");
608 }
609
610
611 name = resolver.getProperty(name);
612
613
614 return (getMappedProperty(bean, name, key));
615
616 }
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635 public Object getMappedProperty(final Object bean,
636 final String name, final String key)
637 throws IllegalAccessException, InvocationTargetException,
638 NoSuchMethodException {
639
640 if (bean == null) {
641 throw new IllegalArgumentException("No bean specified");
642 }
643 if (name == null) {
644 throw new IllegalArgumentException("No name specified for bean class '" +
645 bean.getClass() + "'");
646 }
647 if (key == null) {
648 throw new IllegalArgumentException("No key specified for property '" +
649 name + "' on bean class " + bean.getClass() + "'");
650 }
651
652
653 if (bean instanceof DynaBean) {
654 final DynaProperty descriptor =
655 ((DynaBean) bean).getDynaClass().getDynaProperty(name);
656 if (descriptor == null) {
657 throw new NoSuchMethodException("Unknown property '" +
658 name + "'+ on bean class '" + bean.getClass() + "'");
659 }
660 return (((DynaBean) bean).get(name, key));
661 }
662
663 Object result = null;
664
665
666 final PropertyDescriptor descriptor = getPropertyDescriptor(bean, name);
667 if (descriptor == null) {
668 throw new NoSuchMethodException("Unknown property '" +
669 name + "'+ on bean class '" + bean.getClass() + "'");
670 }
671
672 if (descriptor instanceof MappedPropertyDescriptor) {
673
674 Method readMethod = ((MappedPropertyDescriptor) descriptor).
675 getMappedReadMethod();
676 readMethod = MethodUtils.getAccessibleMethod(bean.getClass(), readMethod);
677 if (readMethod != null) {
678 final Object[] keyArray = new Object[1];
679 keyArray[0] = key;
680 result = invokeMethod(readMethod, bean, keyArray);
681 } else {
682 throw new NoSuchMethodException("Property '" + name +
683 "' has no mapped getter method on bean class '" +
684 bean.getClass() + "'");
685 }
686 } else {
687
688 final Method readMethod = getReadMethod(bean.getClass(), descriptor);
689 if (readMethod != null) {
690 final Object invokeResult = invokeMethod(readMethod, bean, EMPTY_OBJECT_ARRAY);
691
692 if (invokeResult instanceof java.util.Map) {
693 result = ((java.util.Map<?, ?>)invokeResult).get(key);
694 }
695 } else {
696 throw new NoSuchMethodException("Property '" + name +
697 "' has no mapped getter method on bean class '" +
698 bean.getClass() + "'");
699 }
700 }
701 return result;
702
703 }
704
705
706
707
708
709
710
711
712
713
714
715 @Deprecated
716 public FastHashMap getMappedPropertyDescriptors(final Class<?> beanClass) {
717
718 if (beanClass == null) {
719 return null;
720 }
721
722
723 return mappedDescriptorsCache.get(beanClass);
724
725 }
726
727
728
729
730
731
732
733
734
735
736
737 @Deprecated
738 public FastHashMap getMappedPropertyDescriptors(final Object bean) {
739
740 if (bean == null) {
741 return null;
742 }
743 return (getMappedPropertyDescriptors(bean.getClass()));
744
745 }
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767 public Object getNestedProperty(Object bean, String name)
768 throws IllegalAccessException, InvocationTargetException,
769 NoSuchMethodException {
770
771 if (bean == null) {
772 throw new IllegalArgumentException("No bean specified");
773 }
774 if (name == null) {
775 throw new IllegalArgumentException("No name specified for bean class '" +
776 bean.getClass() + "'");
777 }
778
779
780 while (resolver.hasNested(name)) {
781 final String next = resolver.next(name);
782 Object nestedBean = null;
783 if (bean instanceof Map) {
784 nestedBean = getPropertyOfMapBean((Map<?, ?>) bean, next);
785 } else if (resolver.isMapped(next)) {
786 nestedBean = getMappedProperty(bean, next);
787 } else if (resolver.isIndexed(next)) {
788 nestedBean = getIndexedProperty(bean, next);
789 } else {
790 nestedBean = getSimpleProperty(bean, next);
791 }
792 if (nestedBean == null) {
793 throw new NestedNullException
794 ("Null property value for '" + name +
795 "' on bean class '" + bean.getClass() + "'");
796 }
797 bean = nestedBean;
798 name = resolver.remove(name);
799 }
800
801 if (bean instanceof Map) {
802 bean = getPropertyOfMapBean((Map<?, ?>) bean, name);
803 } else if (resolver.isMapped(name)) {
804 bean = getMappedProperty(bean, name);
805 } else if (resolver.isIndexed(name)) {
806 bean = getIndexedProperty(bean, name);
807 } else {
808 bean = getSimpleProperty(bean, name);
809 }
810 return bean;
811
812 }
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838 protected Object getPropertyOfMapBean(final Map<?, ?> bean, String propertyName)
839 throws IllegalArgumentException, IllegalAccessException,
840 InvocationTargetException, NoSuchMethodException {
841
842 if (resolver.isMapped(propertyName)) {
843 final String name = resolver.getProperty(propertyName);
844 if (name == null || name.length() == 0) {
845 propertyName = resolver.getKey(propertyName);
846 }
847 }
848
849 if (resolver.isIndexed(propertyName) ||
850 resolver.isMapped(propertyName)) {
851 throw new IllegalArgumentException(
852 "Indexed or mapped properties are not supported on"
853 + " objects of type Map: " + propertyName);
854 }
855
856 return bean.get(propertyName);
857 }
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880 public Object getProperty(final Object bean, final String name)
881 throws IllegalAccessException, InvocationTargetException,
882 NoSuchMethodException {
883
884 return (getNestedProperty(bean, name));
885
886 }
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919 public PropertyDescriptor getPropertyDescriptor(Object bean,
920 String name)
921 throws IllegalAccessException, InvocationTargetException,
922 NoSuchMethodException {
923
924 if (bean == null) {
925 throw new IllegalArgumentException("No bean specified");
926 }
927 if (name == null) {
928 throw new IllegalArgumentException("No name specified for bean class '" +
929 bean.getClass() + "'");
930 }
931
932
933 while (resolver.hasNested(name)) {
934 final String next = resolver.next(name);
935 final Object nestedBean = getProperty(bean, next);
936 if (nestedBean == null) {
937 throw new NestedNullException
938 ("Null property value for '" + next +
939 "' on bean class '" + bean.getClass() + "'");
940 }
941 bean = nestedBean;
942 name = resolver.remove(name);
943 }
944
945
946 name = resolver.getProperty(name);
947
948
949
950 if (name == null) {
951 return (null);
952 }
953
954 final BeanIntrospectionData data = getIntrospectionData(bean.getClass());
955 PropertyDescriptor result = data.getDescriptor(name);
956 if (result != null) {
957 return result;
958 }
959
960 FastHashMap mappedDescriptors =
961 getMappedPropertyDescriptors(bean);
962 if (mappedDescriptors == null) {
963 mappedDescriptors = new FastHashMap();
964 mappedDescriptors.setFast(true);
965 mappedDescriptorsCache.put(bean.getClass(), mappedDescriptors);
966 }
967 result = (PropertyDescriptor) mappedDescriptors.get(name);
968 if (result == null) {
969
970 try {
971 result = new MappedPropertyDescriptor(name, bean.getClass());
972 } catch (final IntrospectionException ie) {
973
974
975
976 }
977 if (result != null) {
978 mappedDescriptors.put(name, result);
979 }
980 }
981
982 return result;
983
984 }
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999 public PropertyDescriptor[]
1000 getPropertyDescriptors(final Class<?> beanClass) {
1001
1002 return getIntrospectionData(beanClass).getDescriptors();
1003
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018 public PropertyDescriptor[] getPropertyDescriptors(final Object bean) {
1019
1020 if (bean == null) {
1021 throw new IllegalArgumentException("No bean specified");
1022 }
1023 return (getPropertyDescriptors(bean.getClass()));
1024
1025 }
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058 public Class<?> getPropertyEditorClass(final Object bean, final String name)
1059 throws IllegalAccessException, InvocationTargetException,
1060 NoSuchMethodException {
1061
1062 if (bean == null) {
1063 throw new IllegalArgumentException("No bean specified");
1064 }
1065 if (name == null) {
1066 throw new IllegalArgumentException("No name specified for bean class '" +
1067 bean.getClass() + "'");
1068 }
1069
1070 final PropertyDescriptor descriptor =
1071 getPropertyDescriptor(bean, name);
1072 if (descriptor != null) {
1073 return (descriptor.getPropertyEditorClass());
1074 } else {
1075 return (null);
1076 }
1077
1078 }
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113 public Class<?> getPropertyType(Object bean, String name)
1114 throws IllegalAccessException, InvocationTargetException,
1115 NoSuchMethodException {
1116
1117 if (bean == null) {
1118 throw new IllegalArgumentException("No bean specified");
1119 }
1120 if (name == null) {
1121 throw new IllegalArgumentException("No name specified for bean class '" +
1122 bean.getClass() + "'");
1123 }
1124
1125
1126 while (resolver.hasNested(name)) {
1127 final String next = resolver.next(name);
1128 final Object nestedBean = getProperty(bean, next);
1129 if (nestedBean == null) {
1130 throw new NestedNullException
1131 ("Null property value for '" + next +
1132 "' on bean class '" + bean.getClass() + "'");
1133 }
1134 bean = nestedBean;
1135 name = resolver.remove(name);
1136 }
1137
1138
1139 name = resolver.getProperty(name);
1140
1141
1142 if (bean instanceof DynaBean) {
1143 final DynaProperty descriptor =
1144 ((DynaBean) bean).getDynaClass().getDynaProperty(name);
1145 if (descriptor == null) {
1146 return (null);
1147 }
1148 final Class<?> type = descriptor.getType();
1149 if (type == null) {
1150 return (null);
1151 } else if (type.isArray()) {
1152 return (type.getComponentType());
1153 } else {
1154 return (type);
1155 }
1156 }
1157
1158 final PropertyDescriptor descriptor =
1159 getPropertyDescriptor(bean, name);
1160 if (descriptor == null) {
1161 return (null);
1162 } else if (descriptor instanceof IndexedPropertyDescriptor) {
1163 return (((IndexedPropertyDescriptor) descriptor).
1164 getIndexedPropertyType());
1165 } else if (descriptor instanceof MappedPropertyDescriptor) {
1166 return (((MappedPropertyDescriptor) descriptor).
1167 getMappedPropertyType());
1168 } else {
1169 return (descriptor.getPropertyType());
1170 }
1171
1172 }
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184 public Method getReadMethod(final PropertyDescriptor descriptor) {
1185
1186 return (MethodUtils.getAccessibleMethod(descriptor.getReadMethod()));
1187
1188 }
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201 Method getReadMethod(final Class<?> clazz, final PropertyDescriptor descriptor) {
1202 return (MethodUtils.getAccessibleMethod(clazz, descriptor.getReadMethod()));
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225 public Object getSimpleProperty(final Object bean, final String name)
1226 throws IllegalAccessException, InvocationTargetException,
1227 NoSuchMethodException {
1228
1229 if (bean == null) {
1230 throw new IllegalArgumentException("No bean specified");
1231 }
1232 if (name == null) {
1233 throw new IllegalArgumentException("No name specified for bean class '" +
1234 bean.getClass() + "'");
1235 }
1236
1237
1238 if (resolver.hasNested(name)) {
1239 throw new IllegalArgumentException
1240 ("Nested property names are not allowed: Property '" +
1241 name + "' on bean class '" + bean.getClass() + "'");
1242 } else if (resolver.isIndexed(name)) {
1243 throw new IllegalArgumentException
1244 ("Indexed property names are not allowed: Property '" +
1245 name + "' on bean class '" + bean.getClass() + "'");
1246 } else if (resolver.isMapped(name)) {
1247 throw new IllegalArgumentException
1248 ("Mapped property names are not allowed: Property '" +
1249 name + "' on bean class '" + bean.getClass() + "'");
1250 }
1251
1252
1253 if (bean instanceof DynaBean) {
1254 final DynaProperty descriptor =
1255 ((DynaBean) bean).getDynaClass().getDynaProperty(name);
1256 if (descriptor == null) {
1257 throw new NoSuchMethodException("Unknown property '" +
1258 name + "' on dynaclass '" +
1259 ((DynaBean) bean).getDynaClass() + "'" );
1260 }
1261 return (((DynaBean) bean).get(name));
1262 }
1263
1264
1265 final PropertyDescriptor descriptor =
1266 getPropertyDescriptor(bean, name);
1267 if (descriptor == null) {
1268 throw new NoSuchMethodException("Unknown property '" +
1269 name + "' on class '" + bean.getClass() + "'" );
1270 }
1271 final Method readMethod = getReadMethod(bean.getClass(), descriptor);
1272 if (readMethod == null) {
1273 throw new NoSuchMethodException("Property '" + name +
1274 "' has no getter method in class '" + bean.getClass() + "'");
1275 }
1276
1277
1278 final Object value = invokeMethod(readMethod, bean, EMPTY_OBJECT_ARRAY);
1279 return (value);
1280
1281 }
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 public Method getWriteMethod(final PropertyDescriptor descriptor) {
1299
1300 return (MethodUtils.getAccessibleMethod(descriptor.getWriteMethod()));
1301
1302 }
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316 public Method getWriteMethod(final Class<?> clazz, final PropertyDescriptor descriptor) {
1317 final BeanIntrospectionData data = getIntrospectionData(clazz);
1318 return (MethodUtils.getAccessibleMethod(clazz,
1319 data.getWriteMethod(clazz, descriptor)));
1320 }
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338 public boolean isReadable(Object bean, String name) {
1339
1340
1341 if (bean == null) {
1342 throw new IllegalArgumentException("No bean specified");
1343 }
1344 if (name == null) {
1345 throw new IllegalArgumentException("No name specified for bean class '" +
1346 bean.getClass() + "'");
1347 }
1348
1349
1350 while (resolver.hasNested(name)) {
1351 final String next = resolver.next(name);
1352 Object nestedBean = null;
1353 try {
1354 nestedBean = getProperty(bean, next);
1355 } catch (final IllegalAccessException e) {
1356 return false;
1357 } catch (final InvocationTargetException e) {
1358 return false;
1359 } catch (final NoSuchMethodException e) {
1360 return false;
1361 }
1362 if (nestedBean == null) {
1363 throw new NestedNullException
1364 ("Null property value for '" + next +
1365 "' on bean class '" + bean.getClass() + "'");
1366 }
1367 bean = nestedBean;
1368 name = resolver.remove(name);
1369 }
1370
1371
1372 name = resolver.getProperty(name);
1373
1374
1375
1376 if (bean instanceof WrapDynaBean) {
1377 bean = ((WrapDynaBean)bean).getInstance();
1378 }
1379
1380
1381 if (bean instanceof DynaBean) {
1382
1383 return (((DynaBean) bean).getDynaClass().getDynaProperty(name) != null);
1384 } else {
1385 try {
1386 final PropertyDescriptor desc =
1387 getPropertyDescriptor(bean, name);
1388 if (desc != null) {
1389 Method readMethod = getReadMethod(bean.getClass(), desc);
1390 if (readMethod == null) {
1391 if (desc instanceof IndexedPropertyDescriptor) {
1392 readMethod = ((IndexedPropertyDescriptor) desc).getIndexedReadMethod();
1393 } else if (desc instanceof MappedPropertyDescriptor) {
1394 readMethod = ((MappedPropertyDescriptor) desc).getMappedReadMethod();
1395 }
1396 readMethod = MethodUtils.getAccessibleMethod(bean.getClass(), readMethod);
1397 }
1398 return (readMethod != null);
1399 } else {
1400 return (false);
1401 }
1402 } catch (final IllegalAccessException e) {
1403 return (false);
1404 } catch (final InvocationTargetException e) {
1405 return (false);
1406 } catch (final NoSuchMethodException e) {
1407 return (false);
1408 }
1409 }
1410
1411 }
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429 public boolean isWriteable(Object bean, String name) {
1430
1431
1432 if (bean == null) {
1433 throw new IllegalArgumentException("No bean specified");
1434 }
1435 if (name == null) {
1436 throw new IllegalArgumentException("No name specified for bean class '" +
1437 bean.getClass() + "'");
1438 }
1439
1440
1441 while (resolver.hasNested(name)) {
1442 final String next = resolver.next(name);
1443 Object nestedBean = null;
1444 try {
1445 nestedBean = getProperty(bean, next);
1446 } catch (final IllegalAccessException e) {
1447 return false;
1448 } catch (final InvocationTargetException e) {
1449 return false;
1450 } catch (final NoSuchMethodException e) {
1451 return false;
1452 }
1453 if (nestedBean == null) {
1454 throw new NestedNullException
1455 ("Null property value for '" + next +
1456 "' on bean class '" + bean.getClass() + "'");
1457 }
1458 bean = nestedBean;
1459 name = resolver.remove(name);
1460 }
1461
1462
1463 name = resolver.getProperty(name);
1464
1465
1466
1467 if (bean instanceof WrapDynaBean) {
1468 bean = ((WrapDynaBean)bean).getInstance();
1469 }
1470
1471
1472 if (bean instanceof DynaBean) {
1473
1474 return (((DynaBean) bean).getDynaClass().getDynaProperty(name) != null);
1475 } else {
1476 try {
1477 final PropertyDescriptor desc =
1478 getPropertyDescriptor(bean, name);
1479 if (desc != null) {
1480 Method writeMethod = getWriteMethod(bean.getClass(), desc);
1481 if (writeMethod == null) {
1482 if (desc instanceof IndexedPropertyDescriptor) {
1483 writeMethod = ((IndexedPropertyDescriptor) desc).getIndexedWriteMethod();
1484 } else if (desc instanceof MappedPropertyDescriptor) {
1485 writeMethod = ((MappedPropertyDescriptor) desc).getMappedWriteMethod();
1486 }
1487 writeMethod = MethodUtils.getAccessibleMethod(bean.getClass(), writeMethod);
1488 }
1489 return (writeMethod != null);
1490 } else {
1491 return (false);
1492 }
1493 } catch (final IllegalAccessException e) {
1494 return (false);
1495 } catch (final InvocationTargetException e) {
1496 return (false);
1497 } catch (final NoSuchMethodException e) {
1498 return (false);
1499 }
1500 }
1501
1502 }
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530 public void setIndexedProperty(final Object bean, String name,
1531 final Object value)
1532 throws IllegalAccessException, InvocationTargetException,
1533 NoSuchMethodException {
1534
1535 if (bean == null) {
1536 throw new IllegalArgumentException("No bean specified");
1537 }
1538 if (name == null) {
1539 throw new IllegalArgumentException("No name specified for bean class '" +
1540 bean.getClass() + "'");
1541 }
1542
1543
1544 int index = -1;
1545 try {
1546 index = resolver.getIndex(name);
1547 } catch (final IllegalArgumentException e) {
1548 throw new IllegalArgumentException("Invalid indexed property '" +
1549 name + "' on bean class '" + bean.getClass() + "'");
1550 }
1551 if (index < 0) {
1552 throw new IllegalArgumentException("Invalid indexed property '" +
1553 name + "' on bean class '" + bean.getClass() + "'");
1554 }
1555
1556
1557 name = resolver.getProperty(name);
1558
1559
1560 setIndexedProperty(bean, name, index, value);
1561
1562 }
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587 public void setIndexedProperty(final Object bean, final String name,
1588 final int index, final Object value)
1589 throws IllegalAccessException, InvocationTargetException,
1590 NoSuchMethodException {
1591
1592 if (bean == null) {
1593 throw new IllegalArgumentException("No bean specified");
1594 }
1595 if (name == null || name.length() == 0) {
1596 if (bean.getClass().isArray()) {
1597 Array.set(bean, index, value);
1598 return;
1599 } else if (bean instanceof List) {
1600 final List<Object> list = toObjectList(bean);
1601 list.set(index, value);
1602 return;
1603 }
1604 }
1605 if (name == null) {
1606 throw new IllegalArgumentException("No name specified for bean class '" +
1607 bean.getClass() + "'");
1608 }
1609
1610
1611 if (bean instanceof DynaBean) {
1612 final DynaProperty descriptor =
1613 ((DynaBean) bean).getDynaClass().getDynaProperty(name);
1614 if (descriptor == null) {
1615 throw new NoSuchMethodException("Unknown property '" +
1616 name + "' on bean class '" + bean.getClass() + "'");
1617 }
1618 ((DynaBean) bean).set(name, index, value);
1619 return;
1620 }
1621
1622
1623 final PropertyDescriptor descriptor =
1624 getPropertyDescriptor(bean, name);
1625 if (descriptor == null) {
1626 throw new NoSuchMethodException("Unknown property '" +
1627 name + "' on bean class '" + bean.getClass() + "'");
1628 }
1629
1630
1631 if (descriptor instanceof IndexedPropertyDescriptor) {
1632 Method writeMethod = ((IndexedPropertyDescriptor) descriptor).
1633 getIndexedWriteMethod();
1634 writeMethod = MethodUtils.getAccessibleMethod(bean.getClass(), writeMethod);
1635 if (writeMethod != null) {
1636 final Object[] subscript = new Object[2];
1637 subscript[0] = new Integer(index);
1638 subscript[1] = value;
1639 try {
1640 if (log.isTraceEnabled()) {
1641 final String valueClassName =
1642 value == null ? "<null>"
1643 : value.getClass().getName();
1644 log.trace("setSimpleProperty: Invoking method "
1645 + writeMethod +" with index=" + index
1646 + ", value=" + value
1647 + " (class " + valueClassName+ ")");
1648 }
1649 invokeMethod(writeMethod, bean, subscript);
1650 } catch (final InvocationTargetException e) {
1651 if (e.getTargetException() instanceof
1652 IndexOutOfBoundsException) {
1653 throw (IndexOutOfBoundsException)
1654 e.getTargetException();
1655 } else {
1656 throw e;
1657 }
1658 }
1659 return;
1660 }
1661 }
1662
1663
1664 final Method readMethod = getReadMethod(bean.getClass(), descriptor);
1665 if (readMethod == null) {
1666 throw new NoSuchMethodException("Property '" + name +
1667 "' has no getter method on bean class '" + bean.getClass() + "'");
1668 }
1669
1670
1671 final Object array = invokeMethod(readMethod, bean, EMPTY_OBJECT_ARRAY);
1672 if (!array.getClass().isArray()) {
1673 if (array instanceof List) {
1674
1675 final List<Object> list = toObjectList(array);
1676 list.set(index, value);
1677 } else {
1678 throw new IllegalArgumentException("Property '" + name +
1679 "' is not indexed on bean class '" + bean.getClass() + "'");
1680 }
1681 } else {
1682
1683 Array.set(array, index, value);
1684 }
1685
1686 }
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708 public void setMappedProperty(final Object bean, String name,
1709 final Object value)
1710 throws IllegalAccessException, InvocationTargetException,
1711 NoSuchMethodException {
1712
1713 if (bean == null) {
1714 throw new IllegalArgumentException("No bean specified");
1715 }
1716 if (name == null) {
1717 throw new IllegalArgumentException("No name specified for bean class '" +
1718 bean.getClass() + "'");
1719 }
1720
1721
1722 String key = null;
1723 try {
1724 key = resolver.getKey(name);
1725 } catch (final IllegalArgumentException e) {
1726 throw new IllegalArgumentException
1727 ("Invalid mapped property '" + name +
1728 "' on bean class '" + bean.getClass() + "'");
1729 }
1730 if (key == null) {
1731 throw new IllegalArgumentException
1732 ("Invalid mapped property '" + name +
1733 "' on bean class '" + bean.getClass() + "'");
1734 }
1735
1736
1737 name = resolver.getProperty(name);
1738
1739
1740 setMappedProperty(bean, name, key, value);
1741
1742 }
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761 public void setMappedProperty(final Object bean, final String name,
1762 final String key, final Object value)
1763 throws IllegalAccessException, InvocationTargetException,
1764 NoSuchMethodException {
1765
1766 if (bean == null) {
1767 throw new IllegalArgumentException("No bean specified");
1768 }
1769 if (name == null) {
1770 throw new IllegalArgumentException("No name specified for bean class '" +
1771 bean.getClass() + "'");
1772 }
1773 if (key == null) {
1774 throw new IllegalArgumentException("No key specified for property '" +
1775 name + "' on bean class '" + bean.getClass() + "'");
1776 }
1777
1778
1779 if (bean instanceof DynaBean) {
1780 final DynaProperty descriptor =
1781 ((DynaBean) bean).getDynaClass().getDynaProperty(name);
1782 if (descriptor == null) {
1783 throw new NoSuchMethodException("Unknown property '" +
1784 name + "' on bean class '" + bean.getClass() + "'");
1785 }
1786 ((DynaBean) bean).set(name, key, value);
1787 return;
1788 }
1789
1790
1791 final PropertyDescriptor descriptor =
1792 getPropertyDescriptor(bean, name);
1793 if (descriptor == null) {
1794 throw new NoSuchMethodException("Unknown property '" +
1795 name + "' on bean class '" + bean.getClass() + "'");
1796 }
1797
1798 if (descriptor instanceof MappedPropertyDescriptor) {
1799
1800 Method mappedWriteMethod =
1801 ((MappedPropertyDescriptor) descriptor).
1802 getMappedWriteMethod();
1803 mappedWriteMethod = MethodUtils.getAccessibleMethod(bean.getClass(), mappedWriteMethod);
1804 if (mappedWriteMethod != null) {
1805 final Object[] params = new Object[2];
1806 params[0] = key;
1807 params[1] = value;
1808 if (log.isTraceEnabled()) {
1809 final String valueClassName =
1810 value == null ? "<null>" : value.getClass().getName();
1811 log.trace("setSimpleProperty: Invoking method "
1812 + mappedWriteMethod + " with key=" + key
1813 + ", value=" + value
1814 + " (class " + valueClassName +")");
1815 }
1816 invokeMethod(mappedWriteMethod, bean, params);
1817 } else {
1818 throw new NoSuchMethodException
1819 ("Property '" + name + "' has no mapped setter method" +
1820 "on bean class '" + bean.getClass() + "'");
1821 }
1822 } else {
1823
1824 final Method readMethod = getReadMethod(bean.getClass(), descriptor);
1825 if (readMethod != null) {
1826 final Object invokeResult = invokeMethod(readMethod, bean, EMPTY_OBJECT_ARRAY);
1827
1828 if (invokeResult instanceof java.util.Map) {
1829 final java.util.Map<String, Object> map = toPropertyMap(invokeResult);
1830 map.put(key, value);
1831 }
1832 } else {
1833 throw new NoSuchMethodException("Property '" + name +
1834 "' has no mapped getter method on bean class '" +
1835 bean.getClass() + "'");
1836 }
1837 }
1838
1839 }
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872 public void setNestedProperty(Object bean,
1873 String name, final Object value)
1874 throws IllegalAccessException, InvocationTargetException,
1875 NoSuchMethodException {
1876
1877 if (bean == null) {
1878 throw new IllegalArgumentException("No bean specified");
1879 }
1880 if (name == null) {
1881 throw new IllegalArgumentException("No name specified for bean class '" +
1882 bean.getClass() + "'");
1883 }
1884
1885
1886 while (resolver.hasNested(name)) {
1887 final String next = resolver.next(name);
1888 Object nestedBean = null;
1889 if (bean instanceof Map) {
1890 nestedBean = getPropertyOfMapBean((Map<?, ?>)bean, next);
1891 } else if (resolver.isMapped(next)) {
1892 nestedBean = getMappedProperty(bean, next);
1893 } else if (resolver.isIndexed(next)) {
1894 nestedBean = getIndexedProperty(bean, next);
1895 } else {
1896 nestedBean = getSimpleProperty(bean, next);
1897 }
1898 if (nestedBean == null) {
1899 throw new NestedNullException
1900 ("Null property value for '" + name +
1901 "' on bean class '" + bean.getClass() + "'");
1902 }
1903 bean = nestedBean;
1904 name = resolver.remove(name);
1905 }
1906
1907 if (bean instanceof Map) {
1908 setPropertyOfMapBean(toPropertyMap(bean), name, value);
1909 } else if (resolver.isMapped(name)) {
1910 setMappedProperty(bean, name, value);
1911 } else if (resolver.isIndexed(name)) {
1912 setIndexedProperty(bean, name, value);
1913 } else {
1914 setSimpleProperty(bean, name, value);
1915 }
1916
1917 }
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975 protected void setPropertyOfMapBean(final Map<String, Object> bean, String propertyName, final Object value)
1976 throws IllegalArgumentException, IllegalAccessException,
1977 InvocationTargetException, NoSuchMethodException {
1978
1979 if (resolver.isMapped(propertyName)) {
1980 final String name = resolver.getProperty(propertyName);
1981 if (name == null || name.length() == 0) {
1982 propertyName = resolver.getKey(propertyName);
1983 }
1984 }
1985
1986 if (resolver.isIndexed(propertyName) ||
1987 resolver.isMapped(propertyName)) {
1988 throw new IllegalArgumentException(
1989 "Indexed or mapped properties are not supported on"
1990 + " objects of type Map: " + propertyName);
1991 }
1992
1993 bean.put(propertyName, value);
1994 }
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017 public void setProperty(final Object bean, final String name, final Object value)
2018 throws IllegalAccessException, InvocationTargetException,
2019 NoSuchMethodException {
2020
2021 setNestedProperty(bean, name, value);
2022
2023 }
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045 public void setSimpleProperty(final Object bean,
2046 final String name, final Object value)
2047 throws IllegalAccessException, InvocationTargetException,
2048 NoSuchMethodException {
2049
2050 if (bean == null) {
2051 throw new IllegalArgumentException("No bean specified");
2052 }
2053 if (name == null) {
2054 throw new IllegalArgumentException("No name specified for bean class '" +
2055 bean.getClass() + "'");
2056 }
2057
2058
2059 if (resolver.hasNested(name)) {
2060 throw new IllegalArgumentException
2061 ("Nested property names are not allowed: Property '" +
2062 name + "' on bean class '" + bean.getClass() + "'");
2063 } else if (resolver.isIndexed(name)) {
2064 throw new IllegalArgumentException
2065 ("Indexed property names are not allowed: Property '" +
2066 name + "' on bean class '" + bean.getClass() + "'");
2067 } else if (resolver.isMapped(name)) {
2068 throw new IllegalArgumentException
2069 ("Mapped property names are not allowed: Property '" +
2070 name + "' on bean class '" + bean.getClass() + "'");
2071 }
2072
2073
2074 if (bean instanceof DynaBean) {
2075 final DynaProperty descriptor =
2076 ((DynaBean) bean).getDynaClass().getDynaProperty(name);
2077 if (descriptor == null) {
2078 throw new NoSuchMethodException("Unknown property '" +
2079 name + "' on dynaclass '" +
2080 ((DynaBean) bean).getDynaClass() + "'" );
2081 }
2082 ((DynaBean) bean).set(name, value);
2083 return;
2084 }
2085
2086
2087 final PropertyDescriptor descriptor =
2088 getPropertyDescriptor(bean, name);
2089 if (descriptor == null) {
2090 throw new NoSuchMethodException("Unknown property '" +
2091 name + "' on class '" + bean.getClass() + "'" );
2092 }
2093 final Method writeMethod = getWriteMethod(bean.getClass(), descriptor);
2094 if (writeMethod == null) {
2095 throw new NoSuchMethodException("Property '" + name +
2096 "' has no setter method in class '" + bean.getClass() + "'");
2097 }
2098
2099
2100 final Object[] values = new Object[1];
2101 values[0] = value;
2102 if (log.isTraceEnabled()) {
2103 final String valueClassName =
2104 value == null ? "<null>" : value.getClass().getName();
2105 log.trace("setSimpleProperty: Invoking method " + writeMethod
2106 + " with value " + value + " (class " + valueClassName + ")");
2107 }
2108 invokeMethod(writeMethod, bean, values);
2109
2110 }
2111
2112
2113 private Object invokeMethod(
2114 final Method method,
2115 final Object bean,
2116 final Object[] values)
2117 throws
2118 IllegalAccessException,
2119 InvocationTargetException {
2120 if(bean == null) {
2121 throw new IllegalArgumentException("No bean specified " +
2122 "- this should have been checked before reaching this method");
2123 }
2124
2125 try {
2126
2127 return method.invoke(bean, values);
2128
2129 } catch (final NullPointerException cause) {
2130
2131
2132 String valueString = "";
2133 if (values != null) {
2134 for (int i = 0; i < values.length; i++) {
2135 if (i>0) {
2136 valueString += ", " ;
2137 }
2138 if (values[i] == null) {
2139 valueString += "<null>";
2140 } else {
2141 valueString += (values[i]).getClass().getName();
2142 }
2143 }
2144 }
2145 String expectedString = "";
2146 final Class<?>[] parTypes = method.getParameterTypes();
2147 if (parTypes != null) {
2148 for (int i = 0; i < parTypes.length; i++) {
2149 if (i > 0) {
2150 expectedString += ", ";
2151 }
2152 expectedString += parTypes[i].getName();
2153 }
2154 }
2155 final IllegalArgumentException e = new IllegalArgumentException(
2156 "Cannot invoke " + method.getDeclaringClass().getName() + "."
2157 + method.getName() + " on bean class '" + bean.getClass() +
2158 "' - " + cause.getMessage()
2159
2160 + " - had objects of type \"" + valueString
2161 + "\" but expected signature \""
2162 + expectedString + "\""
2163 );
2164 if (!BeanUtils.initCause(e, cause)) {
2165 log.error("Method invocation failed", cause);
2166 }
2167 throw e;
2168 } catch (final IllegalArgumentException cause) {
2169 String valueString = "";
2170 if (values != null) {
2171 for (int i = 0; i < values.length; i++) {
2172 if (i>0) {
2173 valueString += ", " ;
2174 }
2175 if (values[i] == null) {
2176 valueString += "<null>";
2177 } else {
2178 valueString += (values[i]).getClass().getName();
2179 }
2180 }
2181 }
2182 String expectedString = "";
2183 final Class<?>[] parTypes = method.getParameterTypes();
2184 if (parTypes != null) {
2185 for (int i = 0; i < parTypes.length; i++) {
2186 if (i > 0) {
2187 expectedString += ", ";
2188 }
2189 expectedString += parTypes[i].getName();
2190 }
2191 }
2192 final IllegalArgumentException e = new IllegalArgumentException(
2193 "Cannot invoke " + method.getDeclaringClass().getName() + "."
2194 + method.getName() + " on bean class '" + bean.getClass() +
2195 "' - " + cause.getMessage()
2196
2197 + " - had objects of type \"" + valueString
2198 + "\" but expected signature \""
2199 + expectedString + "\""
2200 );
2201 if (!BeanUtils.initCause(e, cause)) {
2202 log.error("Method invocation failed", cause);
2203 }
2204 throw e;
2205
2206 }
2207 }
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218 private BeanIntrospectionData getIntrospectionData(final Class<?> beanClass) {
2219 if (beanClass == null) {
2220 throw new IllegalArgumentException("No bean class specified");
2221 }
2222
2223
2224 BeanIntrospectionData data = descriptorsCache.get(beanClass);
2225 if (data == null) {
2226 data = fetchIntrospectionData(beanClass);
2227 descriptorsCache.put(beanClass, data);
2228 }
2229
2230 return data;
2231 }
2232
2233
2234
2235
2236
2237
2238
2239
2240 private BeanIntrospectionData fetchIntrospectionData(final Class<?> beanClass) {
2241 final DefaultIntrospectionContext ictx = new DefaultIntrospectionContext(beanClass);
2242
2243 for (final BeanIntrospector bi : introspectors) {
2244 try {
2245 bi.introspect(ictx);
2246 } catch (final IntrospectionException iex) {
2247 log.error("Exception during introspection", iex);
2248 }
2249 }
2250
2251 return new BeanIntrospectionData(ictx.getPropertyDescriptors());
2252 }
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262 private static List<Object> toObjectList(final Object obj) {
2263 @SuppressWarnings("unchecked")
2264 final
2265
2266 List<Object> list = (List<Object>) obj;
2267 return list;
2268 }
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278 private static Map<String, Object> toPropertyMap(final Object obj) {
2279 @SuppressWarnings("unchecked")
2280 final
2281
2282 Map<String, Object> map = (Map<String, Object>) obj;
2283 return map;
2284 }
2285 }