| 1 16 17 package org.apache.commons.beanutils; 18 19 20 import java.beans.BeanInfo ; 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 33 import org.apache.commons.collections.FastHashMap; 34 import org.apache.commons.logging.Log; 35 import org.apache.commons.logging.LogFactory; 36 37 38 95 96 public class PropertyUtilsBean { 97 98 100 protected static PropertyUtilsBean getInstance() { 101 return BeanUtilsBean.getInstance().getPropertyUtils(); 102 } 103 104 106 110 private FastHashMap descriptorsCache = null; 111 private FastHashMap mappedDescriptorsCache = null; 112 113 114 private Log log = LogFactory.getLog(PropertyUtils.class); 115 116 118 119 public PropertyUtilsBean() { 120 descriptorsCache = new FastHashMap(); 121 descriptorsCache.setFast(true); 122 mappedDescriptorsCache = new FastHashMap(); 123 mappedDescriptorsCache.setFast(true); 124 } 125 126 127 129 130 135 public void clearDescriptors() { 136 137 descriptorsCache.clear(); 138 mappedDescriptorsCache.clear(); 139 Introspector.flushCaches(); 140 141 } 142 143 144 172 public void copyProperties(Object dest, Object orig) 173 throws IllegalAccessException , InvocationTargetException , 174 NoSuchMethodException { 175 176 if (dest == null) { 177 throw new IllegalArgumentException  178 ("No destination bean specified"); 179 } 180 if (orig == null) { 181 throw new IllegalArgumentException ("No origin bean specified"); 182 } 183 184 if (orig instanceof DynaBean) { 185 DynaProperty origDescriptors[] = 186 ((DynaBean) orig).getDynaClass().getDynaProperties(); 187 for (int i = 0; i < origDescriptors.length; i++) { 188 String name = origDescriptors[i].getName(); 189 if (dest instanceof DynaBean) { 190 if (isWriteable(dest, name)) { 191 Object value = ((DynaBean) orig).get(name); 192 ((DynaBean) dest).set(name, value); 193 } 194 } else { 195 if (isWriteable(dest, name)) { 196 Object value = ((DynaBean) orig).get(name); 197 setSimpleProperty(dest, name, value); 198 } 199 } 200 } 201 } else if (orig instanceof Map ) { 202 Iterator names = ((Map ) orig).keySet().iterator(); 203 while (names.hasNext()) { 204 String name = (String ) names.next(); 205 if (dest instanceof DynaBean) { 206 if (isWriteable(dest, name)) { 207 Object value = ((Map ) orig).get(name); 208 ((DynaBean) dest).set(name, value); 209 } 210 } else { 211 if (isWriteable(dest, name)) { 212 Object value = ((Map ) orig).get(name); 213 setSimpleProperty(dest, name, value); 214 } 215 } 216 } 217 } else { 218 PropertyDescriptor origDescriptors[] = 219 getPropertyDescriptors(orig); 220 for (int i = 0; i < origDescriptors.length; i++) { 221 String name = origDescriptors[i].getName(); 222 if (isReadable(orig, name)) { 223 if (dest instanceof DynaBean) { 224 if (isWriteable(dest, name)) { 225 Object value = getSimpleProperty(orig, name); 226 ((DynaBean) dest).set(name, value); 227 } 228 } else { 229 if (isWriteable(dest, name)) { 230 Object value = getSimpleProperty(orig, name); 231 setSimpleProperty(dest, name, value); 232 } 233 } 234 } 235 } 236 } 237 238 } 239 240 241 259 public Map describe(Object bean) 260 throws IllegalAccessException , InvocationTargetException , 261 NoSuchMethodException { 262 263 if (bean == null) { 264 throw new IllegalArgumentException ("No bean specified"); 265 } 266 Map description = new HashMap (); 267 if (bean instanceof DynaBean) { 268 DynaProperty descriptors[] = 269 ((DynaBean) bean).getDynaClass().getDynaProperties(); 270 for (int i = 0; i < descriptors.length; i++) { 271 String name = descriptors[i].getName(); 272 description.put(name, getProperty(bean, name)); 273 } 274 } else { 275 PropertyDescriptor descriptors[] = 276 getPropertyDescriptors(bean); 277 for (int i = 0; i < descriptors.length; i++) { 278 String name = descriptors[i].getName(); 279 if (descriptors[i].getReadMethod() != null) 280 description.put(name, getProperty(bean, name)); 281 } 282 } 283 return (description); 284 285 } 286 287 288 311 public Object getIndexedProperty(Object bean, String name) 312 throws IllegalAccessException , InvocationTargetException , 313 NoSuchMethodException { 314 315 if (bean == null) { 316 throw new IllegalArgumentException ("No bean specified"); 317 } 318 if (name == null) { 319 throw new IllegalArgumentException ("No name specified"); 320 } 321 322 int delim = name.indexOf(PropertyUtils.INDEXED_DELIM); 324 int delim2 = name.indexOf(PropertyUtils.INDEXED_DELIM2); 325 if ((delim < 0) || (delim2 <= delim)) { 326 throw new IllegalArgumentException ("Invalid indexed property '" + 327 name + "'"); 328 } 329 int index = -1; 330 try { 331 String subscript = name.substring(delim + 1, delim2); 332 index = Integer.parseInt(subscript); 333 } catch (NumberFormatException e) { 334 throw new IllegalArgumentException ("Invalid indexed property '" + 335 name + "'"); 336 } 337 name = name.substring(0, delim); 338 339 return (getIndexedProperty(bean, name, index)); 341 342 } 343 344 345 366 public Object getIndexedProperty(Object bean, 367 String name, int index) 368 throws IllegalAccessException , InvocationTargetException , 369 NoSuchMethodException { 370 371 if (bean == null) { 372 throw new IllegalArgumentException ("No bean specified"); 373 } 374 if (name == null) { 375 throw new IllegalArgumentException ("No name specified"); 376 } 377 378 if (bean instanceof DynaBean) { 380 DynaProperty descriptor = 381 ((DynaBean) bean).getDynaClass().getDynaProperty(name); 382 if (descriptor == null) { 383 throw new NoSuchMethodException ("Unknown property '" + 384 name + "'"); 385 } 386 return (((DynaBean) bean).get(name, index)); 387 } 388 389 PropertyDescriptor descriptor = 391 getPropertyDescriptor(bean, name); 392 if (descriptor == null) { 393 throw new NoSuchMethodException ("Unknown property '" + 394 name + "'"); 395 } 396 397 if (descriptor instanceof IndexedPropertyDescriptor ) { 399 Method readMethod = ((IndexedPropertyDescriptor ) descriptor). 400 getIndexedReadMethod(); 401 if (readMethod != null) { 402 Object subscript[] = new Object [1]; 403 subscript[0] = new Integer (index); 404 try { 405 return (invokeMethod(readMethod,bean, subscript)); 406 } catch (InvocationTargetException e) { 407 if (e.getTargetException() instanceof 408 ArrayIndexOutOfBoundsException ) { 409 throw (ArrayIndexOutOfBoundsException ) 410 e.getTargetException(); 411 } else { 412 throw e; 413 } 414 } 415 } 416 } 417 418 Method readMethod = getReadMethod(descriptor); 420 if (readMethod == null) { 421 throw new NoSuchMethodException ("Property '" + name + 422 "' has no getter method"); 423 } 424 425 Object value = invokeMethod(readMethod, bean, new Object [0]); 427 if (!value.getClass().isArray()) { 428 if (!(value instanceof java.util.List )) { 429 throw new IllegalArgumentException ("Property '" + name 430 + "' is not indexed"); 431 } else { 432 return ((java.util.List ) value).get(index); 434 } 435 } else { 436 return (Array.get(value, index)); 438 } 439 440 } 441 442 443 461 public Object getMappedProperty(Object bean, String name) 462 throws IllegalAccessException , InvocationTargetException , 463 NoSuchMethodException { 464 465 if (bean == null) { 466 throw new IllegalArgumentException ("No bean specified"); 467 } 468 if (name == null) { 469 throw new IllegalArgumentException ("No name specified"); 470 } 471 472 int delim = name.indexOf(PropertyUtils.MAPPED_DELIM); 474 int delim2 = name.indexOf(PropertyUtils.MAPPED_DELIM2); 475 if ((delim < 0) || (delim2 <= delim)) { 476 throw new IllegalArgumentException  477 ("Invalid mapped property '" + name + "'"); 478 } 479 480 String key = name.substring(delim + 1, delim2); 482 name = name.substring(0, delim); 483 484 return (getMappedProperty(bean, name, key)); 486 487 } 488 489 490 505 public Object getMappedProperty(Object bean, 506 String name, String key) 507 throws IllegalAccessException , InvocationTargetException , 508 NoSuchMethodException { 509 510 if (bean == null) { 511 throw new IllegalArgumentException ("No bean specified"); 512 } 513 if (name == null) { 514 throw new IllegalArgumentException ("No name specified"); 515 } 516 if (key == null) { 517 throw new IllegalArgumentException ("No key specified"); 518 } 519 520 if (bean instanceof DynaBean) { 522 DynaProperty descriptor = 523 ((DynaBean) bean).getDynaClass().getDynaProperty(name); 524 if (descriptor == null) { 525 throw new NoSuchMethodException ("Unknown property '" + 526 name + "'"); 527 } 528 return (((DynaBean) bean).get(name, key)); 529 } 530 531 Object result = null; 532 533 PropertyDescriptor descriptor = getPropertyDescriptor(bean, name); 535 if (descriptor == null) { 536 throw new NoSuchMethodException ("Unknown property '" + 537 name + "'"); 538 } 539 540 if (descriptor instanceof MappedPropertyDescriptor) { 541 Method readMethod = ((MappedPropertyDescriptor) descriptor). 543 getMappedReadMethod(); 544 if (readMethod != null) { 545 Object keyArray[] = new Object [1]; 546 keyArray[0] = key; 547 result = invokeMethod(readMethod, bean, keyArray); 548 } else { 549 throw new NoSuchMethodException ("Property '" + name + 550 "' has no mapped getter method"); 551 } 552 } else { 553 554 Method readMethod = descriptor.getReadMethod(); 555 if (readMethod != null) { 556 Object invokeResult = invokeMethod(readMethod, bean, new Object [0]); 557 558 if (invokeResult instanceof java.util.Map ) { 559 result = ((java.util.Map )invokeResult).get(key); 560 } 561 } else { 562 throw new NoSuchMethodException ("Property '" + name + 563 "' has no mapped getter method"); 564 } 565 } 566 return result; 567 568 } 569 570 571 579 public FastHashMap getMappedPropertyDescriptors(Class beanClass) { 580 581 if (beanClass == null) { 582 return null; 583 } 584 585 return (FastHashMap) mappedDescriptorsCache.get(beanClass); 587 588 } 589 590 591 599 public FastHashMap getMappedPropertyDescriptors(Object bean) { 600 601 if (bean == null) { 602 return null; 603 } 604 return (getMappedPropertyDescriptors(bean.getClass())); 605 606 } 607 608 609 627 public Object getNestedProperty(Object bean, String name) 628 throws IllegalAccessException , InvocationTargetException , 629 NoSuchMethodException { 630 631 if (bean == null) { 632 throw new IllegalArgumentException ("No bean specified"); 633 } 634 if (name == null) { 635 throw new IllegalArgumentException ("No name specified"); 636 } 637 638 int indexOfINDEXED_DELIM = -1; 639 int indexOfMAPPED_DELIM = -1; 640 int indexOfMAPPED_DELIM2 = -1; 641 int indexOfNESTED_DELIM = -1; 642 while (true) { 643 indexOfNESTED_DELIM = name.indexOf(PropertyUtils.NESTED_DELIM); 644 indexOfMAPPED_DELIM = name.indexOf(PropertyUtils.MAPPED_DELIM); 645 indexOfMAPPED_DELIM2 = name.indexOf(PropertyUtils.MAPPED_DELIM2); 646 if (indexOfMAPPED_DELIM2 >= 0 && indexOfMAPPED_DELIM >=0 && 647 (indexOfNESTED_DELIM < 0 || indexOfNESTED_DELIM > indexOfMAPPED_DELIM)) { 648 indexOfNESTED_DELIM = 649 name.indexOf(PropertyUtils.NESTED_DELIM, indexOfMAPPED_DELIM2); 650 } else { 651 indexOfNESTED_DELIM = name.indexOf(PropertyUtils.NESTED_DELIM); 652 } 653 if (indexOfNESTED_DELIM < 0) { 654 break; 655 } 656 String next = name.substring(0, indexOfNESTED_DELIM); 657 indexOfINDEXED_DELIM = next.indexOf(PropertyUtils.INDEXED_DELIM); 658 indexOfMAPPED_DELIM = next.indexOf(PropertyUtils.MAPPED_DELIM); 659 if (bean instanceof Map ) { 660 bean = ((Map ) bean).get(next); 661 } else if (indexOfMAPPED_DELIM >= 0) { 662 bean = getMappedProperty(bean, next); 663 } else if (indexOfINDEXED_DELIM >= 0) { 664 bean = getIndexedProperty(bean, next); 665 } else { 666 bean = getSimpleProperty(bean, next); 667 } 668 if (bean == null) { 669 throw new NestedNullException 670 ("Null property value for '" + 671 name.substring(0, indexOfNESTED_DELIM) + "'"); 672 } 673 name = name.substring(indexOfNESTED_DELIM + 1); 674 } 675 676 indexOfINDEXED_DELIM = name.indexOf(PropertyUtils.INDEXED_DELIM); 677 indexOfMAPPED_DELIM = name.indexOf(PropertyUtils.MAPPED_DELIM); 678 679 if (bean instanceof Map ) { 680 bean = ((Map ) bean).get(name); 681 } else if (indexOfMAPPED_DELIM >= 0) { 682 bean = getMappedProperty(bean, name); 683 } else if (indexOfINDEXED_DELIM >= 0) { 684 bean = getIndexedProperty(bean, name); 685 } else { 686 bean = getSimpleProperty(bean, name); 687 } 688 return bean; 689 690 } 691 692 693 711 public Object getProperty(Object bean, String name) 712 throws IllegalAccessException , InvocationTargetException , 713 NoSuchMethodException { 714 715 return (getNestedProperty(bean, name)); 716 717 } 718 719 720 |