1 16 17 18 package org.apache.commons.beanutils; 19 20 21 import java.beans.IndexedPropertyDescriptor ; 22 import java.beans.PropertyDescriptor ; 23 import java.lang.reflect.Array ; 24 import java.lang.reflect.InvocationTargetException ; 25 import java.lang.reflect.Method ; 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 import java.util.HashMap ; 29 import java.util.Iterator ; 30 import java.util.Map ; 31 import java.util.WeakHashMap ; 32 33 import org.apache.commons.collections.FastHashMap; 34 import org.apache.commons.logging.Log; 35 import org.apache.commons.logging.LogFactory; 36 37 38 55 56 public class BeanUtilsBean { 57 58 59 61 64 private static final ContextClassLoaderLocal 65 beansByClassLoader = new ContextClassLoaderLocal() { 66 protected Object initialValue() { 68 return new BeanUtilsBean(); 69 } 70 }; 71 72 77 public synchronized static BeanUtilsBean getInstance() { 78 return (BeanUtilsBean) beansByClassLoader.get(); 79 } 80 81 86 public synchronized static void setInstance(BeanUtilsBean newInstance) { 87 beansByClassLoader.set(newInstance); 88 } 89 90 92 95 private Log log = LogFactory.getLog(BeanUtils.class); 96 97 98 private ConvertUtilsBean convertUtilsBean; 99 100 101 private PropertyUtilsBean propertyUtilsBean; 102 103 105 109 public BeanUtilsBean() { 110 this(new ConvertUtilsBean(), new PropertyUtilsBean()); 111 } 112 113 121 public BeanUtilsBean( 122 ConvertUtilsBean convertUtilsBean, 123 PropertyUtilsBean propertyUtilsBean) { 124 125 this.convertUtilsBean = convertUtilsBean; 126 this.propertyUtilsBean = propertyUtilsBean; 127 } 128 129 131 152 public Object cloneBean(Object bean) 153 throws IllegalAccessException , InstantiationException , 154 InvocationTargetException , NoSuchMethodException { 155 156 if (log.isDebugEnabled()) { 157 log.debug("Cloning bean: " + bean.getClass().getName()); 158 } 159 Class clazz = bean.getClass(); 160 Object newBean = null; 161 if (bean instanceof DynaBean) { 162 newBean = ((DynaBean) bean).getDynaClass().newInstance(); 163 } else { 164 newBean = bean.getClass().newInstance(); 165 } 166 getPropertyUtils().copyProperties(newBean, bean); 167 return (newBean); 168 169 } 170 171 172 212 public void copyProperties(Object dest, Object orig) 213 throws IllegalAccessException , InvocationTargetException { 214 215 if (dest == null) { 217 throw new IllegalArgumentException 218 ("No destination bean specified"); 219 } 220 if (orig == null) { 221 throw new IllegalArgumentException ("No origin bean specified"); 222 } 223 if (log.isDebugEnabled()) { 224 log.debug("BeanUtils.copyProperties(" + dest + ", " + 225 orig + ")"); 226 } 227 228 if (orig instanceof DynaBean) { 230 DynaProperty origDescriptors[] = 231 ((DynaBean) orig).getDynaClass().getDynaProperties(); 232 for (int i = 0; i < origDescriptors.length; i++) { 233 String name = origDescriptors[i].getName(); 234 if (getPropertyUtils().isWriteable(dest, name)) { 235 Object value = ((DynaBean) orig).get(name); 236 copyProperty(dest, name, value); 237 } 238 } 239 } else if (orig instanceof Map ) { 240 Iterator names = ((Map ) orig).keySet().iterator(); 241 while (names.hasNext()) { 242 String name = (String ) names.next(); 243 if (getPropertyUtils().isWriteable(dest, name)) { 244 Object value = ((Map ) orig).get(name); 245 copyProperty(dest, name, value); 246 } 247 } 248 } else { 249 PropertyDescriptor origDescriptors[] = 250 getPropertyUtils().getPropertyDescriptors(orig); 251 for (int i = 0; i < origDescriptors.length; i++) { 252 String name = origDescriptors[i].getName(); 253 if ("class".equals(name)) { 254 continue; } 256 if (getPropertyUtils().isReadable(orig, name) && 257 getPropertyUtils().isWriteable(dest, name)) { 258 try { 259 Object value = 260 getPropertyUtils().getSimpleProperty(orig, name); 261 copyProperty(dest, name, value); 262 } catch (NoSuchMethodException e) { 263 ; } 265 } 266 } 267 } 268 269 } 270 271 272 303 public void copyProperty(Object bean, String name, Object value) 304 throws IllegalAccessException , InvocationTargetException { 305 306 if (log.isTraceEnabled()) { 308 StringBuffer sb = new StringBuffer (" copyProperty("); 309 sb.append(bean); 310 sb.append(", "); 311 sb.append(name); 312 sb.append(", "); 313 if (value == null) { 314 sb.append("<NULL>"); 315 } else if (value instanceof String ) { 316 sb.append((String ) value); 317 } else if (value instanceof String []) { 318 String values[] = (String []) value; 319 sb.append('['); 320 for (int i = 0; i < values.length; i++) { 321 if (i > 0) { 322 sb.append(','); 323 } 324 sb.append(values[i]); 325 } 326 sb.append(']'); 327 } else { 328 sb.append(value.toString()); 329 } 330 sb.append(')'); 331 log.trace(sb.toString()); 332 } 333 334 Object target = bean; 336 int delim = name.lastIndexOf(PropertyUtils.NESTED_DELIM); 337 if (delim >= 0) { 338 try { 339 target = 340 getPropertyUtils().getProperty(bean, name.substring(0, delim)); 341 } catch (NoSuchMethodException e) { 342 return; } 344 name = name.substring(delim + 1); 345 if (log.isTraceEnabled()) { 346 log.trace(" Target bean = " + target); 347 log.trace(" Target name = " + name); 348 } 349 } 350 351 String propName = null; Class type = null; int index = -1; String key = null; 357 propName = name; 359 int i = propName.indexOf(PropertyUtils.INDEXED_DELIM); 360 if (i >= 0) { 361 int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2); 362 try { 363 index = 364 Integer.parseInt(propName.substring(i + 1, k)); 365 } catch (NumberFormatException e) { 366 ; 367 } 368 propName = propName.substring(0, i); 369 } 370 int j = propName.indexOf(PropertyUtils.MAPPED_DELIM); 371 if (j >= 0) { 372 int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2); 373 try { 374 key = propName.substring(j + 1, k); 375 } catch (IndexOutOfBoundsException e) { 376 ; 377 } 378 propName = propName.substring(0, j); 379 } 380 381 if (target instanceof DynaBean) { 383 DynaClass dynaClass = ((DynaBean) target).getDynaClass(); 384 DynaProperty dynaProperty = dynaClass.getDynaProperty(propName); 385 if (dynaProperty == null) { 386 return; } 388 type = dynaProperty.getType(); 389 } else { 390 PropertyDescriptor descriptor = null; 391 try { 392 descriptor = 393 getPropertyUtils().getPropertyDescriptor(target, name); 394 if (descriptor == null) { 395 return; } 397 } catch (NoSuchMethodException e) { 398 return; } 400 type = descriptor.getPropertyType(); 401 if (type == null) { 402 if (log.isTraceEnabled()) { 404 log.trace(" target type for property '" + 405 propName + "' is null, so skipping ths setter"); 406 } 407 return; 408 } 409 } 410 if (log.isTraceEnabled()) { 411 log.trace(" target propName=" + propName + ", type=" + 412 type + ", index=" + index + ", key=" + key); 413 } 414 415 if (index >= 0) { Converter converter = getConvertUtils().lookup(type.getComponentType()); 418 if (converter != null) { 419 log.trace(" USING CONVERTER " + converter); 420 value = converter.convert(type, value); 421 } 422 try { 423 getPropertyUtils().setIndexedProperty(target, propName, 424 index, value); 425 } catch (NoSuchMethodException e) { 426 throw new InvocationTargetException 427 (e, "Cannot set " + propName); 428 } 429 } else if (key != null) { try { 434 getPropertyUtils().setMappedProperty(target, propName, 435 key, value); 436 } catch (NoSuchMethodException e) { 437 throw new InvocationTargetException 438 (e, "Cannot set " + propName); 439 } 440 } else { Converter converter = getConvertUtils().lookup(type); 442 if (converter != null) { 443 log.trace(" USING CONVERTER " + converter); 444 value = converter.convert(type, value); 445 } 446 try { 447 getPropertyUtils().setSimpleProperty(target, propName, value); 448 } catch (NoSuchMethodException e) { 449 throw new InvocationTargetException 450 (e, "Cannot set " + propName); 451 } 452 } 453 454 } 455 456 457 477 public Map describe(Object bean) 478 throws IllegalAccessException , InvocationTargetException , 479 NoSuchMethodException { 480 481 if (bean == null) { 482 return (new java.util.HashMap ()); 484 } 485 486 if (log.isDebugEnabled()) { 487 log.debug("Describing bean: " + bean.getClass().getName()); 488 } 489 490 Map description = new HashMap (); 491 if (bean instanceof DynaBean) { 492 DynaProperty descriptors[] = 493 ((DynaBean) bean).getDynaClass().getDynaProperties(); 494 for (int i = 0; i < descriptors.length; i++) { 495 String name = descriptors[i].getName(); 496 description.put(name, getProperty(bean, name)); 497 } 498 } else { 499 PropertyDescriptor descriptors[] = 500 getPropertyUtils().getPropertyDescriptors(bean); 501 for (int i = 0; i < descriptors.length; i++) { 502 String name = descriptors[i].getName(); 503 if (descriptors[i].getReadMethod() != null) 504 description.put(name, getProperty(bean, name)); 505 } 506 } 507 return (description); 508 509 } 510 511 512 526 public String [] getArrayProperty(Object bean, String name) 527 throws IllegalAccessException , InvocationTargetException , 528 NoSuchMethodException { 529 530 Object value = getPropertyUtils().getProperty(bean, name); 531 if (value == null) { 532 return (null); 533 } else if (value instanceof Collection ) { 534 ArrayList values = new ArrayList (); 535 Iterator items = ((Collection ) value).iterator(); 536 while (items.hasNext()) { 537 Object item = items.next(); 538 if (item == null) { 539 values.add((String ) null); 540 } else { 541 values.add(getConvertUtils().convert(item)); 543 } 544 } 545 return ((String []) values.toArray(new String [values.size()])); 546 } else if (value.getClass().isArray()) { 547 int n = Array.getLength(value); 548 String results[] = new String [n]; 549 for (int i = 0; i < n; i++) { 550 Object item = Array.get(value, i); 551 if (item == null) { 552 results[i] = null; 553 } else { 554 results[i] = getConvertUtils().convert(item); 556 } 557 } 558 return (results); 559 } else { 560 String results[] = new String [1]; 561 results[0] = value.toString(); 562 return (results); 563 } 564 565 } 566 567 568 586 public String getIndexedProperty(Object bean, String name) 587 throws IllegalAccessException , InvocationTargetException , 588 NoSuchMethodException { 589 590 Object value = getPropertyUtils().getIndexedProperty(bean, name); 591 return (getConvertUtils().convert(value)); 592 593 } 594 595 596 612 public String getIndexedProperty(Object bean, 613 String name, int index) 614 throws IllegalAccessException , InvocationTargetException , 615 NoSuchMethodException { 616 617 Object value = getPropertyUtils().getIndexedProperty(bean, name, index); 618 return (getConvertUtils().convert(value)); 619 620 } 621 622 623 641 public String getMappedProperty(Object bean, String name) 642 throws IllegalAccessException , InvocationTargetException , 643 NoSuchMethodException { 644 645 Object value = getPropertyUtils().getMappedProperty(bean, name); 646 return (getConvertUtils().convert(value)); 647 648 } 649 650 651 667 public String getMappedProperty(Object bean, 668 String name, String key) 669 throws IllegalAccessException , InvocationTargetException , 670 NoSuchMethodException { 671 672 Object value = getPropertyUtils().getMappedProperty(bean, name, key); 673 return (getConvertUtils().convert(value)); 674 675 } 676 677 678 694 public String getNestedProperty(Object bean, String name) 695 throws IllegalAccessException , InvocationTargetException , 696 NoSuchMethodException { 697 698 Object value = getPropertyUtils().getNestedProperty(bean, name); 699 return (getConvertUtils().convert(value)); 700 701 } 702 703 704 719 public String getProperty(Object bean, String name) 720 throws IllegalAccessException , InvocationTargetException , 721 NoSuchMethodException { 722 723 return (getNestedProperty(bean, name)); 724 725 } 726 727 728 742 public String getSimpleProperty(Object bean, String name) 743 throws IllegalAccessException , InvocationTargetException , 744 NoSuchMethodException { 745 746 Object value = getPropertyUtils().getSimpleProperty(bean, name); 747 return (getConvertUtils().convert(value)); 748 749 } 750 751 752 787 public void populate(Object bean, Map properties) 788 throws IllegalAccessException , InvocationTargetException { 789 790 if ((bean == null) || (properties == null)) { 792 return; 793 } 794 if (log.isDebugEnabled()) { 795 log.debug("BeanUtils.populate(" + bean + ", " + 796 properties + ")"); 797 } 798 799 Iterator names = properties.keySet().iterator(); 801 while (names.hasNext()) { 802 803 String name = (String ) names.next(); 805 if (name == null) { 806 continue; 807 } 808 Object value = properties.get(name); 809 810 setProperty(bean, name, value); 812 813 } 814 815 } 816 817 818 848 public void setProperty(Object bean, String name, Object value) 849 throws IllegalAccessException , InvocationTargetException { 850 851 if (log.isTraceEnabled()) { 853 StringBuffer sb = new StringBuffer (" setProperty("); 854 sb.append(bean); 855 sb.append(", "); 856 sb.append(name); 857 sb.append(", "); 858 if (value == null) { 859 sb.append("<NULL>"); 860 } else if (value instanceof String ) { 861 sb.append((String ) value); 862 } else if (value instanceof String []) { 863 String values[] = (String []) value; 864 sb.append('['); 865 for (int i = 0; i < values.length; i++) { 866 if (i > 0) { 867 sb.append(','); 868 } 869 sb.append(values[i]); 870 } 871 sb.append(']'); 872 } else { 873 sb.append(value.toString()); 874 } 875 sb.append(')'); 876 log.trace(sb.toString()); 877 } 878 879 Object target = bean; 881 int delim = findLastNestedIndex(name); 882 if (delim >= 0) { 883 try { 884 target = 885 getPropertyUtils().getProperty(bean, name.substring(0, delim)); 886 } catch (NoSuchMethodException e) { 887 return; } 889 name = name.substring(delim + 1); 890 if (log.isTraceEnabled()) { 891 log.trace(" Target bean = " + target); 892 log.trace(" Target name = " + name); 893 } 894 } 895 896 String propName = null; Class type = null; int index = -1; String key = null; 902 propName = name; 904 int i = propName.indexOf(PropertyUtils.INDEXED_DELIM); 905 if (i >= 0) { 906 int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2); 907 try { 908 index = 909 Integer.parseInt(propName.substring(i + 1, k)); 910 } catch (NumberFormatException e) { 911 ; 912 } 913 propName = propName.substring(0, i); 914 } 915 int j = propName.indexOf(PropertyUtils.MAPPED_DELIM); 916 if (j >= 0) { 917 int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2); 918 try { 919 key = propName.substring(j + 1, k); 920 } catch (IndexOutOfBoundsException e) { 921 ; 922 } 923 propName = propName.substring(0, j); 924 } 925 926 if (target instanceof DynaBean) { 928 DynaClass dynaClass = ((DynaBean) target).getDynaClass(); 929 DynaProperty dynaProperty = dynaClass.getDynaProperty(propName); 930 if (dynaProperty == null) { 931 return; } 933 type = dynaProperty.getType(); 934 } else { 935 PropertyDescriptor descriptor = null; 936 try { 937 descriptor = 938 getPropertyUtils().getPropertyDescriptor(target, name); 939 if (descriptor == null) { 940 return; } 942 } catch (NoSuchMethodException e) { 943 return; } 945 if (descriptor instanceof MappedPropertyDescriptor) { 946 if (((MappedPropertyDescriptor) descriptor).getMappedWriteMethod() == null) { 947 if (log.isDebugEnabled()) { 948 log.debug("Skipping read-only property"); 949 } 950 return; } 952 type = ((MappedPropertyDescriptor) descriptor). 953 getMappedPropertyType(); 954 } else if (descriptor instanceof IndexedPropertyDescriptor ) { 955 if (((IndexedPropertyDescriptor ) descriptor).getIndexedWriteMethod() == null) { 956 if (log.isDebugEnabled()) { 957 log.debug("Skipping read-only property"); 958 } 959 return; } 961 type = ((IndexedPropertyDescriptor ) descriptor). 962 getIndexedPropertyType(); 963 } else { 964 if (descriptor.getWriteMethod() == null) { 965 if (log.isDebugEnabled()) { 966 log.debug("Skipping read-only property"); 967 } 968 return; } 970 type = descriptor.getPropertyType(); 971 } 972 } 973 974 Object newValue = null; 976 if (type.isArray() && (index < 0)) { if (value == null) { 978 String values[] = new String [1]; 979 values[0] = (String ) value; 980 newValue = getConvertUtils().convert((String []) values, type); 981 } else if (value instanceof String ) { 982 String values[] = new String [1]; 983 values[0] = (String ) value; 984 newValue = getConvertUtils().convert((String []) values, type); 985 } else if (value instanceof String []) { 986 newValue = getConvertUtils().convert((String []) value, type); 987 } else { 988 newValue = value; 989 } 990 } else if (type.isArray()) { if (value instanceof String ) { 992 newValue = getConvertUtils().convert((String ) value, 993 type.getComponentType()); 994 } else if (value instanceof String []) { 995 newValue = getConvertUtils().convert(((String []) value)[0], 996 type.getComponentType()); 997 } else { 998 newValue = value; 999 } 1000 } else { if ((value instanceof String ) || (value == null)) { 1002 newValue = getConvertUtils().convert((String ) value, type); 1003 } else if (value instanceof String []) { 1004 newValue = getConvertUtils().convert(((String []) value)[0], 1005 type); 1006 } else if (getConvertUtils().lookup(value.getClass()) != null) { 1007 newValue = getConvertUtils().convert(value.toString(), type); 1008 } else { 1009 newValue = value; 1010 } 1011 } 1012 1013 try { 1015 if (index >= 0) { 1016 getPropertyUtils().setIndexedProperty(target, propName, 1017 index, newValue); 1018 } else if (key != null) { 1019 getPropertyUtils().setMappedProperty(target, propName, 1020 key, newValue); 1021 } else { 1022 getPropertyUtils().setProperty(target, propName, newValue); 1023 } 1024 } catch (NoSuchMethodException e) { 1025 throw new InvocationTargetException 1026 (e, "Cannot set " + propName); 1027 } 1028 1029 } 1030 1031 private int findLastNestedIndex(String expression) 1032 { 1033 int bracketCount = 0; 1036 for (int i = expression.length() - 1; i>=0 ; i--) { 1037 char at = expression.charAt(i); 1038 switch (at) { 1039 case PropertyUtils.NESTED_DELIM: 1040 if (bracketCount < 1) { 1041 return i; 1042 } 1043 break; 1044 1045 case PropertyUtils.MAPPED_DELIM: 1046 case PropertyUtils.INDEXED_DELIM: 1047 --bracketCount; 1049 break; 1050 1051 case PropertyUtils.MAPPED_DELIM2: 1052 case PropertyUtils.INDEXED_DELIM2: 1053 ++bracketCount; 1055 break; 1056 } 1057 } 1058 return -1; 1060 } 1061 1062 1065 public ConvertUtilsBean getConvertUtils() { 1066 return convertUtilsBean; 1067 } 1068 1069 1072 public PropertyUtilsBean getPropertyUtils() { 1073 return propertyUtilsBean; 1074 } 1075} 1076 | Popular Tags |