Source Code Cross Referenced for PropertyUtilsBean.java in  » Workflow-Engines » OSWorkflow » com » opensymphony » workflow » designer » beanutils » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » OSWorkflow » com.opensymphony.workflow.designer.beanutils 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * The Apache Software License, Version 1.1
0003:         *
0004:         * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
0005:         * reserved.
0006:         *
0007:         * Redistribution and use in source and binary forms, with or without
0008:         * modification, are permitted provided that the following conditions
0009:         * are met:
0010:         *
0011:         * 1. Redistributions of source code must retain the above copyright
0012:         *    notice, this list of conditions and the following disclaimer.
0013:         *
0014:         * 2. Redistributions in binary form must reproduce the above copyright
0015:         *    notice, this list of conditions and the following disclaimer in
0016:         *    the documentation and/or other materials provided with the
0017:         *    distribution.
0018:         *
0019:         * 3. The end-user documentation included with the redistribution,
0020:         *    if any, must include the following acknowledgement:
0021:         *       "This product includes software developed by the
0022:         *        Apache Software Foundation (http://www.apache.org/)."
0023:         *    Alternately, this acknowledgement may appear in the software itself,
0024:         *    if and wherever such third-party acknowledgements normally appear.
0025:         *
0026:         * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software
0027:         *    Foundation" must not be used to endorse or promote products derived
0028:         *    from this software without prior written permission. For written
0029:         *    permission, please contact apache@apache.org.
0030:         *
0031:         * 5. Products derived from this software may not be called "Apache",
0032:         *    "Apache" nor may "Apache" appear in their names without prior
0033:         *    written permission of the Apache Software Foundation.
0034:         *
0035:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0036:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0037:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0038:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0039:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0040:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0041:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0042:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0043:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0044:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0045:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0046:         * SUCH DAMAGE.
0047:         * ====================================================================
0048:         *
0049:         * This software consists of voluntary contributions made by many
0050:         * individuals on behalf of the Apache Software Foundation.  For more
0051:         * information on the Apache Software Foundation, please see
0052:         * <http://www.apache.org/>.
0053:         *
0054:         */
0055:
0056:        package com.opensymphony.workflow.designer.beanutils;
0057:
0058:        import java.beans.*;
0059:        import java.lang.reflect.Array;
0060:        import java.lang.reflect.InvocationTargetException;
0061:        import java.lang.reflect.Method;
0062:        import java.util.*;
0063:
0064:        /**
0065:         * Utility methods for using Java Reflection APIs to facilitate generic
0066:         * property getter and setter operations on Java objects.  Much of this
0067:         * code was originally included in <code>BeanUtils</code>, but has been
0068:         * separated because of the volume of code involved.
0069:         * <p/>
0070:         * In general, the objects that are examined and modified using these
0071:         * methods are expected to conform to the property getter and setter method
0072:         * naming conventions described in the JavaBeans Specification (Version 1.0.1).
0073:         * No data type conversions are performed, and there are no usage of any
0074:         * <code>PropertyEditor</code> classes that have been registered, although
0075:         * a convenient way to access the registered classes themselves is included.
0076:         * <p/>
0077:         * For the purposes of this class, five formats for referencing a particular
0078:         * property value of a bean are defined, with the layout of an identifying
0079:         * String in parentheses:
0080:         * <ul>
0081:         * <li><strong>Simple (<code>name</code>)</strong> - The specified
0082:         * <code>name</code> identifies an individual property of a particular
0083:         * JavaBean.  The name of the actual getter or setter method to be used
0084:         * is determined using standard JavaBeans instrospection, so that (unless
0085:         * overridden by a <code>BeanInfo</code> class, a property named "xyz"
0086:         * will have a getter method named <code>getXyz()</code> or (for boolean
0087:         * properties only) <code>isXyz()</code>, and a setter method named
0088:         * <code>setXyz()</code>.</li>
0089:         * <li><strong>Nested (<code>name1.name2.name3</code>)</strong> The first
0090:         * name element is used to select a property getter, as for simple
0091:         * references above.  The object returned for this property is then
0092:         * consulted, using the same approach, for a property getter for a
0093:         * property named <code>name2</code>, and so on.  The property value that
0094:         * is ultimately retrieved or modified is the one identified by the
0095:         * last name element.</li>
0096:         * <li><strong>Indexed (<code>name[index]</code>)</strong> - The underlying
0097:         * property value is assumed to be an array, or this JavaBean is assumed
0098:         * to have indexed property getter and setter methods.  The appropriate
0099:         * (zero-relative) entry in the array is selected.  <code>List</code>
0100:         * objects are now also supported for read/write.  You simply need to define
0101:         * a getter that returns the <code>List</code></li>
0102:         * <li><strong>Mapped (<code>name(key)</code>)</strong> - The JavaBean
0103:         * is assumed to have an property getter and setter methods with an
0104:         * additional attribute of type <code>java.lang.String</code>.</li>
0105:         * <li><strong>Combined (<code>name1.name2[index].name3(key)</code>)</strong> -
0106:         * Combining mapped, nested, and indexed references is also
0107:         * supported.</li>
0108:         * </ul>
0109:         *
0110:         * @author Craig R. McClanahan
0111:         * @author Ralph Schaer
0112:         * @author Chris Audley
0113:         * @author Rey Fran�ois
0114:         * @author Gregor Ra�man
0115:         * @author Jan Sorensen
0116:         * @author Scott Sanders
0117:         * @see PropertyUtils
0118:         * @since 1.7
0119:         */
0120:
0121:        public class PropertyUtilsBean {
0122:
0123:            private static final PropertyUtilsBean instance = new PropertyUtilsBean();
0124:
0125:            // --------------------------------------------------------- Class Methods
0126:
0127:            protected static PropertyUtilsBean getInstance() {
0128:                return instance;
0129:            }
0130:
0131:            // --------------------------------------------------------- Variables
0132:
0133:            /**
0134:             * The cache of PropertyDescriptor arrays for beans we have already
0135:             * introspected, keyed by the java.lang.Class of this object.
0136:             */
0137:            private Map descriptorsCache = null;
0138:            private Map mappedDescriptorsCache = null;
0139:
0140:            // ---------------------------------------------------------- Constructors
0141:
0142:            /**
0143:             * Base constructor
0144:             */
0145:            public PropertyUtilsBean() {
0146:                descriptorsCache = new HashMap();
0147:                mappedDescriptorsCache = new HashMap();
0148:            }
0149:
0150:            // --------------------------------------------------------- Public Methods
0151:
0152:            /**
0153:             * Clear any cached property descriptors information for all classes
0154:             * loaded by any class loaders.  This is useful in cases where class
0155:             * loaders are thrown away to implement class reloading.
0156:             */
0157:            public void clearDescriptors() {
0158:
0159:                descriptorsCache.clear();
0160:                mappedDescriptorsCache.clear();
0161:                Introspector.flushCaches();
0162:
0163:            }
0164:
0165:            /**
0166:             * <p>Copy property values from the "origin" bean to the "destination" bean
0167:             * for all cases where the property names are the same (even though the
0168:             * actual getter and setter methods might have been customized via
0169:             * <code>BeanInfo</code> classes).  No conversions are performed on the
0170:             * actual property values -- it is assumed that the values retrieved from
0171:             * the origin bean are assignment-compatible with the types expected by
0172:             * the destination bean.</p>
0173:             * <p/>
0174:             * <p>If the origin "bean" is actually a <code>Map</code>, it is assumed
0175:             * to contain String-valued <strong>simple</strong> property names as the keys, pointing
0176:             * at the corresponding property values that will be set in the destination
0177:             * bean.<strong>Note</strong> that this method is intended to perform
0178:             * a "shallow copy" of the properties and so complex properties
0179:             * (for example, nested ones) will not be copied.</p>
0180:             *
0181:             * @param dest Destination bean whose properties are modified
0182:             * @param orig Origin bean whose properties are retrieved
0183:             * @throws IllegalAccessException    if the caller does not have
0184:             *                                   access to the property accessor method
0185:             * @throws IllegalArgumentException  if the <code>dest</code> or
0186:             *                                   <code>orig</code> argument is null
0187:             * @throws InvocationTargetException if the property accessor method
0188:             *                                   throws an exception
0189:             * @throws NoSuchMethodException     if an accessor method for this
0190:             *                                   propety cannot be found
0191:             */
0192:            public void copyProperties(Object dest, Object orig)
0193:                    throws IllegalAccessException, InvocationTargetException,
0194:                    NoSuchMethodException {
0195:
0196:                if (dest == null) {
0197:                    throw new IllegalArgumentException(
0198:                            "No destination bean specified");
0199:                }
0200:                if (orig == null) {
0201:                    throw new IllegalArgumentException(
0202:                            "No origin bean specified");
0203:                }
0204:                if (orig instanceof  Map) {
0205:                    Iterator names = ((Map) orig).keySet().iterator();
0206:                    while (names.hasNext()) {
0207:                        String name = (String) names.next();
0208:                        if (isWriteable(dest, name)) {
0209:                            Object value = ((Map) orig).get(name);
0210:                            setSimpleProperty(dest, name, value);
0211:                        }
0212:                    }
0213:                } else /* if (orig is a standard JavaBean) */
0214:                {
0215:                    PropertyDescriptor origDescriptors[] = getPropertyDescriptors(orig);
0216:                    for (int i = 0; i < origDescriptors.length; i++) {
0217:                        String name = origDescriptors[i].getName();
0218:                        if (isReadable(orig, name)) {
0219:                            if (isWriteable(dest, name)) {
0220:                                Object value = getSimpleProperty(orig, name);
0221:                                setSimpleProperty(dest, name, value);
0222:                            }
0223:                        }
0224:                    }
0225:                }
0226:
0227:            }
0228:
0229:            /**
0230:             * <p>Return the entire set of properties for which the specified bean
0231:             * provides a read method.  This map contains the unconverted property
0232:             * values for all properties for which a read method is provided
0233:             * (i.e. where the <code>getReadMethod()</code> returns non-null).</p>
0234:             * <p/>
0235:             * <p><strong>FIXME</strong> - Does not account for mapped properties.</p>
0236:             *
0237:             * @param bean Bean whose properties are to be extracted
0238:             * @throws IllegalAccessException    if the caller does not have
0239:             *                                   access to the property accessor method
0240:             * @throws IllegalArgumentException  if <code>bean</code> is null
0241:             * @throws InvocationTargetException if the property accessor method
0242:             *                                   throws an exception
0243:             * @throws NoSuchMethodException     if an accessor method for this
0244:             *                                   propety cannot be found
0245:             */
0246:            public Map describe(Object bean) throws IllegalAccessException,
0247:                    InvocationTargetException, NoSuchMethodException {
0248:
0249:                if (bean == null) {
0250:                    throw new IllegalArgumentException("No bean specified");
0251:                }
0252:                Map description = new HashMap();
0253:                PropertyDescriptor descriptors[] = getPropertyDescriptors(bean);
0254:                for (int i = 0; i < descriptors.length; i++) {
0255:                    String name = descriptors[i].getName();
0256:                    if (descriptors[i].getReadMethod() != null)
0257:                        description.put(name, getProperty(bean, name));
0258:                }
0259:                return (description);
0260:
0261:            }
0262:
0263:            /**
0264:             * Return the value of the specified indexed property of the specified
0265:             * bean, with no type conversions.  The zero-relative index of the
0266:             * required value must be included (in square brackets) as a suffix to
0267:             * the property name, or <code>IllegalArgumentException</code> will be
0268:             * thrown.  In addition to supporting the JavaBeans specification, this
0269:             * method has been extended to support <code>List</code> objects as well.
0270:             *
0271:             * @param bean Bean whose property is to be extracted
0272:             * @param name <code>propertyname[index]</code> of the property value
0273:             *             to be extracted
0274:             * @throws ArrayIndexOutOfBoundsException if the specified index
0275:             *                                        is outside the valid range for the underlying array
0276:             * @throws IllegalAccessException         if the caller does not have
0277:             *                                        access to the property accessor method
0278:             * @throws IllegalArgumentException       if <code>bean</code> or
0279:             *                                        <code>name</code> is null
0280:             * @throws InvocationTargetException      if the property accessor method
0281:             *                                        throws an exception
0282:             * @throws NoSuchMethodException          if an accessor method for this
0283:             *                                        propety cannot be found
0284:             */
0285:            public Object getIndexedProperty(Object bean, String name)
0286:                    throws IllegalAccessException, InvocationTargetException,
0287:                    NoSuchMethodException {
0288:
0289:                if (bean == null) {
0290:                    throw new IllegalArgumentException("No bean specified");
0291:                }
0292:                if (name == null) {
0293:                    throw new IllegalArgumentException("No name specified");
0294:                }
0295:
0296:                // Identify the index of the requested individual property
0297:                int delim = name.indexOf(PropertyUtils.INDEXED_DELIM);
0298:                int delim2 = name.indexOf(PropertyUtils.INDEXED_DELIM2);
0299:                if ((delim < 0) || (delim2 <= delim)) {
0300:                    throw new IllegalArgumentException(
0301:                            "Invalid indexed property '" + name + "'");
0302:                }
0303:                int index;
0304:                try {
0305:                    String subscript = name.substring(delim + 1, delim2);
0306:                    index = Integer.parseInt(subscript);
0307:                } catch (NumberFormatException e) {
0308:                    throw new IllegalArgumentException(
0309:                            "Invalid indexed property '" + name + "'");
0310:                }
0311:                name = name.substring(0, delim);
0312:
0313:                // Request the specified indexed property value
0314:                return (getIndexedProperty(bean, name, index));
0315:
0316:            }
0317:
0318:            /**
0319:             * Return the value of the specified indexed property of the specified
0320:             * bean, with no type conversions.  In addition to supporting the JavaBeans
0321:             * specification, this method has been extended to support
0322:             * <code>List</code> objects as well.
0323:             *
0324:             * @param bean  Bean whose property is to be extracted
0325:             * @param name  Simple property name of the property value to be extracted
0326:             * @param index Index of the property value to be extracted
0327:             * @throws ArrayIndexOutOfBoundsException if the specified index
0328:             *                                        is outside the valid range for the underlying array
0329:             * @throws IllegalAccessException         if the caller does not have
0330:             *                                        access to the property accessor method
0331:             * @throws IllegalArgumentException       if <code>bean</code> or
0332:             *                                        <code>name</code> is null
0333:             * @throws InvocationTargetException      if the property accessor method
0334:             *                                        throws an exception
0335:             * @throws NoSuchMethodException          if an accessor method for this
0336:             *                                        propety cannot be found
0337:             */
0338:            public Object getIndexedProperty(Object bean, String name, int index)
0339:                    throws IllegalAccessException, InvocationTargetException,
0340:                    NoSuchMethodException {
0341:
0342:                if (bean == null) {
0343:                    throw new IllegalArgumentException("No bean specified");
0344:                }
0345:                if (name == null) {
0346:                    throw new IllegalArgumentException("No name specified");
0347:                }
0348:
0349:                // Retrieve the property descriptor for the specified property
0350:                PropertyDescriptor descriptor = getPropertyDescriptor(bean,
0351:                        name);
0352:                if (descriptor == null) {
0353:                    throw new NoSuchMethodException("Unknown property '" + name
0354:                            + "'");
0355:                }
0356:
0357:                // Call the indexed getter method if there is one
0358:                if (descriptor instanceof  IndexedPropertyDescriptor) {
0359:                    Method readMethod = ((IndexedPropertyDescriptor) descriptor)
0360:                            .getIndexedReadMethod();
0361:                    if (readMethod != null) {
0362:                        Object subscript[] = new Object[1];
0363:                        subscript[0] = new Integer(index);
0364:                        try {
0365:                            return (invokeMethod(readMethod, bean, subscript));
0366:                        } catch (InvocationTargetException e) {
0367:                            if (e.getTargetException() instanceof  ArrayIndexOutOfBoundsException) {
0368:                                throw (ArrayIndexOutOfBoundsException) e
0369:                                        .getTargetException();
0370:                            } else {
0371:                                throw e;
0372:                            }
0373:                        }
0374:                    }
0375:                }
0376:
0377:                // Otherwise, the underlying property must be an array
0378:                Method readMethod = getReadMethod(descriptor);
0379:                if (readMethod == null) {
0380:                    throw new NoSuchMethodException("Property '" + name
0381:                            + "' has no getter method");
0382:                }
0383:
0384:                // Call the property getter and return the value
0385:                Object value = invokeMethod(readMethod, bean, new Object[0]);
0386:                if (!value.getClass().isArray()) {
0387:                    if (!(value instanceof  java.util.List)) {
0388:                        throw new IllegalArgumentException("Property '" + name
0389:                                + "' is not indexed");
0390:                    } else {
0391:                        //get the List's value
0392:                        return ((java.util.List) value).get(index);
0393:                    }
0394:                } else {
0395:                    //get the array's value
0396:                    return (Array.get(value, index));
0397:                }
0398:
0399:            }
0400:
0401:            /**
0402:             * Return the value of the specified mapped property of the
0403:             * specified bean, with no type conversions.  The key of the
0404:             * required value must be included (in brackets) as a suffix to
0405:             * the property name, or <code>IllegalArgumentException</code> will be
0406:             * thrown.
0407:             *
0408:             * @param bean Bean whose property is to be extracted
0409:             * @param name <code>propertyname(key)</code> of the property value
0410:             *             to be extracted
0411:             * @throws IllegalAccessException    if the caller does not have
0412:             *                                   access to the property accessor method
0413:             * @throws InvocationTargetException if the property accessor method
0414:             *                                   throws an exception
0415:             * @throws NoSuchMethodException     if an accessor method for this
0416:             *                                   propety cannot be found
0417:             */
0418:            public Object getMappedProperty(Object bean, String name)
0419:                    throws IllegalAccessException, InvocationTargetException,
0420:                    NoSuchMethodException {
0421:
0422:                if (bean == null) {
0423:                    throw new IllegalArgumentException("No bean specified");
0424:                }
0425:                if (name == null) {
0426:                    throw new IllegalArgumentException("No name specified");
0427:                }
0428:
0429:                // Identify the index of the requested individual property
0430:                int delim = name.indexOf(PropertyUtils.MAPPED_DELIM);
0431:                int delim2 = name.indexOf(PropertyUtils.MAPPED_DELIM2);
0432:                if ((delim < 0) || (delim2 <= delim)) {
0433:                    throw new IllegalArgumentException(
0434:                            "Invalid mapped property '" + name + "'");
0435:                }
0436:
0437:                // Isolate the name and the key
0438:                String key = name.substring(delim + 1, delim2);
0439:                name = name.substring(0, delim);
0440:
0441:                // Request the specified indexed property value
0442:                return (getMappedProperty(bean, name, key));
0443:
0444:            }
0445:
0446:            /**
0447:             * Return the value of the specified mapped property of the specified
0448:             * bean, with no type conversions.
0449:             *
0450:             * @param bean Bean whose property is to be extracted
0451:             * @param name Mapped property name of the property value to be extracted
0452:             * @param key  Key of the property value to be extracted
0453:             * @throws IllegalAccessException    if the caller does not have
0454:             *                                   access to the property accessor method
0455:             * @throws InvocationTargetException if the property accessor method
0456:             *                                   throws an exception
0457:             * @throws NoSuchMethodException     if an accessor method for this
0458:             *                                   propety cannot be found
0459:             */
0460:            public Object getMappedProperty(Object bean, String name, String key)
0461:                    throws IllegalAccessException, InvocationTargetException,
0462:                    NoSuchMethodException {
0463:
0464:                if (bean == null) {
0465:                    throw new IllegalArgumentException("No bean specified");
0466:                }
0467:                if (name == null) {
0468:                    throw new IllegalArgumentException("No name specified");
0469:                }
0470:                if (key == null) {
0471:                    throw new IllegalArgumentException("No key specified");
0472:                }
0473:
0474:                // Handle DynaBean instances specially
0475:                Object result = null;
0476:
0477:                // Retrieve the property descriptor for the specified property
0478:                PropertyDescriptor descriptor = getPropertyDescriptor(bean,
0479:                        name);
0480:                if (descriptor == null) {
0481:                    throw new NoSuchMethodException("Unknown property '" + name
0482:                            + "'");
0483:                }
0484:
0485:                if (descriptor instanceof  MappedPropertyDescriptor) {
0486:                    // Call the keyed getter method if there is one
0487:                    Method readMethod = ((MappedPropertyDescriptor) descriptor)
0488:                            .getMappedReadMethod();
0489:                    if (readMethod != null) {
0490:                        Object keyArray[] = new Object[1];
0491:                        keyArray[0] = key;
0492:                        result = invokeMethod(readMethod, bean, keyArray);
0493:                    } else {
0494:                        throw new NoSuchMethodException("Property '" + name
0495:                                + "' has no mapped getter method");
0496:                    }
0497:                } else {
0498:                    /* means that the result has to be retrieved from a map */
0499:                    Method readMethod = descriptor.getReadMethod();
0500:                    if (readMethod != null) {
0501:                        Object invokeResult = invokeMethod(readMethod, bean,
0502:                                new Object[0]);
0503:                        /* test and fetch from the map */
0504:                        if (invokeResult instanceof  java.util.Map) {
0505:                            result = ((java.util.Map) invokeResult).get(key);
0506:                        }
0507:                    } else {
0508:                        throw new NoSuchMethodException("Property '" + name
0509:                                + "' has no mapped getter method");
0510:                    }
0511:                }
0512:                return result;
0513:
0514:            }
0515:
0516:            /**
0517:             * <p>Return the mapped property descriptors for this bean class.</p>
0518:             * <p/>
0519:             * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
0520:             *
0521:             * @param beanClass Bean class to be introspected
0522:             */
0523:            public Map getMappedPropertyDescriptors(Class beanClass) {
0524:
0525:                if (beanClass == null) {
0526:                    return null;
0527:                }
0528:
0529:                // Look up any cached descriptors for this bean class
0530:                return (Map) mappedDescriptorsCache.get(beanClass);
0531:
0532:            }
0533:
0534:            /**
0535:             * <p>Return the mapped property descriptors for this bean.</p>
0536:             * <p/>
0537:             * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
0538:             *
0539:             * @param bean Bean to be introspected
0540:             */
0541:            public Map getMappedPropertyDescriptors(Object bean) {
0542:
0543:                if (bean == null) {
0544:                    return null;
0545:                }
0546:                return (getMappedPropertyDescriptors(bean.getClass()));
0547:
0548:            }
0549:
0550:            /**
0551:             * Return the value of the (possibly nested) property of the specified
0552:             * name, for the specified bean, with no type conversions.
0553:             *
0554:             * @param bean Bean whose property is to be extracted
0555:             * @param name Possibly nested name of the property to be extracted
0556:             * @throws IllegalAccessException    if the caller does not have
0557:             *                                   access to the property accessor method
0558:             * @throws IllegalArgumentException  if <code>bean</code> or
0559:             *                                   <code>name</code> is null
0560:             * @throws IllegalArgumentException  if a nested reference to a
0561:             *                                   property returns null
0562:             * @throws InvocationTargetException if the property accessor method throws an exception
0563:             * @throws NoSuchMethodException     if an accessor method for this
0564:             *                                   propety cannot be found
0565:             */
0566:            public Object getNestedProperty(Object bean, String name)
0567:                    throws IllegalAccessException, InvocationTargetException,
0568:                    NoSuchMethodException {
0569:
0570:                if (bean == null) {
0571:                    throw new IllegalArgumentException("No bean specified");
0572:                }
0573:                if (name == null) {
0574:                    throw new IllegalArgumentException("No name specified");
0575:                }
0576:
0577:                int indexOfINDEXED_DELIM;
0578:                int indexOfMAPPED_DELIM;
0579:                int indexOfMAPPED_DELIM2;
0580:                int indexOfNESTED_DELIM;
0581:                while (true) {
0582:                    indexOfNESTED_DELIM = name
0583:                            .indexOf(PropertyUtils.NESTED_DELIM);
0584:                    indexOfMAPPED_DELIM = name
0585:                            .indexOf(PropertyUtils.MAPPED_DELIM);
0586:                    indexOfMAPPED_DELIM2 = name
0587:                            .indexOf(PropertyUtils.MAPPED_DELIM2);
0588:                    if (indexOfMAPPED_DELIM2 >= 0
0589:                            && indexOfMAPPED_DELIM >= 0
0590:                            && (indexOfNESTED_DELIM < 0 || indexOfNESTED_DELIM > indexOfMAPPED_DELIM)) {
0591:                        indexOfNESTED_DELIM = name.indexOf(
0592:                                PropertyUtils.NESTED_DELIM,
0593:                                indexOfMAPPED_DELIM2);
0594:                    } else {
0595:                        indexOfNESTED_DELIM = name
0596:                                .indexOf(PropertyUtils.NESTED_DELIM);
0597:                    }
0598:                    if (indexOfNESTED_DELIM < 0) {
0599:                        break;
0600:                    }
0601:                    String next = name.substring(0, indexOfNESTED_DELIM);
0602:                    indexOfINDEXED_DELIM = next
0603:                            .indexOf(PropertyUtils.INDEXED_DELIM);
0604:                    indexOfMAPPED_DELIM = next
0605:                            .indexOf(PropertyUtils.MAPPED_DELIM);
0606:                    if (bean instanceof  Map) {
0607:                        bean = ((Map) bean).get(next);
0608:                    } else if (indexOfMAPPED_DELIM >= 0) {
0609:                        bean = getMappedProperty(bean, next);
0610:                    } else if (indexOfINDEXED_DELIM >= 0) {
0611:                        bean = getIndexedProperty(bean, next);
0612:                    } else {
0613:                        bean = getSimpleProperty(bean, next);
0614:                    }
0615:                    if (bean == null) {
0616:                        throw new NullPointerException(
0617:                                "Null property value for '"
0618:                                        + name
0619:                                                .substring(0,
0620:                                                        indexOfNESTED_DELIM)
0621:                                        + "'");
0622:                    }
0623:                    name = name.substring(indexOfNESTED_DELIM + 1);
0624:                }
0625:
0626:                indexOfINDEXED_DELIM = name
0627:                        .indexOf(PropertyUtils.INDEXED_DELIM);
0628:                indexOfMAPPED_DELIM = name.indexOf(PropertyUtils.MAPPED_DELIM);
0629:
0630:                if (bean instanceof  Map) {
0631:                    bean = ((Map) bean).get(name);
0632:                } else if (indexOfMAPPED_DELIM >= 0) {
0633:                    bean = getMappedProperty(bean, name);
0634:                } else if (indexOfINDEXED_DELIM >= 0) {
0635:                    bean = getIndexedProperty(bean, name);
0636:                } else {
0637:                    bean = getSimpleProperty(bean, name);
0638:                }
0639:                return bean;
0640:
0641:            }
0642:
0643:            /**
0644:             * Return the value of the specified property of the specified bean,
0645:             * no matter which property reference format is used, with no
0646:             * type conversions.
0647:             *
0648:             * @param bean Bean whose property is to be extracted
0649:             * @param name Possibly indexed and/or nested name of the property
0650:             *             to be extracted
0651:             * @throws IllegalAccessException    if the caller does not have
0652:             *                                   access to the property accessor method
0653:             * @throws IllegalArgumentException  if <code>bean</code> or
0654:             *                                   <code>name</code> is null
0655:             * @throws InvocationTargetException if the property accessor method
0656:             *                                   throws an exception
0657:             * @throws NoSuchMethodException     if an accessor method for this
0658:             *                                   propety cannot be found
0659:             */
0660:            public Object getProperty(Object bean, String name)
0661:                    throws IllegalAccessException, InvocationTargetException,
0662:                    NoSuchMethodException {
0663:
0664:                return (getNestedProperty(bean, name));
0665:
0666:            }
0667:
0668:            /**
0669:             * <p>Retrieve the property descriptor for the specified property of the
0670:             * specified bean, or return <code>null</code> if there is no such
0671:             * descriptor.  This method resolves indexed and nested property
0672:             * references in the same manner as other methods in this class, except
0673:             * that if the last (or only) name element is indexed, the descriptor
0674:             * for the last resolved property itself is returned.</p>
0675:             * <p/>
0676:             * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
0677:             *
0678:             * @param bean Bean for which a property descriptor is requested
0679:             * @param name Possibly indexed and/or nested name of the property for
0680:             *             which a property descriptor is requested
0681:             * @throws IllegalAccessException    if the caller does not have
0682:             *                                   access to the property accessor method
0683:             * @throws IllegalArgumentException  if <code>bean</code> or
0684:             *                                   <code>name</code> is null
0685:             * @throws IllegalArgumentException  if a nested reference to a
0686:             *                                   property returns null
0687:             * @throws InvocationTargetException if the property accessor method
0688:             *                                   throws an exception
0689:             * @throws NoSuchMethodException     if an accessor method for this
0690:             *                                   propety cannot be found
0691:             */
0692:            public PropertyDescriptor getPropertyDescriptor(Object bean,
0693:                    String name) throws IllegalAccessException,
0694:                    InvocationTargetException, NoSuchMethodException {
0695:
0696:                if (bean == null) {
0697:                    throw new IllegalArgumentException("No bean specified");
0698:                }
0699:                if (name == null) {
0700:                    throw new IllegalArgumentException("No name specified");
0701:                }
0702:
0703:                // Resolve nested references
0704:                while (true) {
0705:                    int period = findNextNestedIndex(name);
0706:                    if (period < 0) {
0707:                        break;
0708:                    }
0709:                    String next = name.substring(0, period);
0710:                    int indexOfINDEXED_DELIM = next
0711:                            .indexOf(PropertyUtils.INDEXED_DELIM);
0712:                    int indexOfMAPPED_DELIM = next
0713:                            .indexOf(PropertyUtils.MAPPED_DELIM);
0714:                    if (indexOfMAPPED_DELIM >= 0
0715:                            && (indexOfINDEXED_DELIM < 0 || indexOfMAPPED_DELIM < indexOfINDEXED_DELIM)) {
0716:                        bean = getMappedProperty(bean, next);
0717:                    } else {
0718:                        if (indexOfINDEXED_DELIM >= 0) {
0719:                            bean = getIndexedProperty(bean, next);
0720:                        } else {
0721:                            bean = getSimpleProperty(bean, next);
0722:                        }
0723:                    }
0724:                    if (bean == null) {
0725:                        throw new IllegalArgumentException(
0726:                                "Null property value for '"
0727:                                        + name.substring(0, period) + "'");
0728:                    }
0729:                    name = name.substring(period + 1);
0730:                }
0731:
0732:                // Remove any subscript from the final name value
0733:                int left = name.indexOf(PropertyUtils.INDEXED_DELIM);
0734:                if (left >= 0) {
0735:                    name = name.substring(0, left);
0736:                }
0737:                left = name.indexOf(PropertyUtils.MAPPED_DELIM);
0738:                if (left >= 0) {
0739:                    name = name.substring(0, left);
0740:                }
0741:
0742:                // Look up and return this property from our cache
0743:                // creating and adding it to the cache if not found.
0744:                if ((bean == null) || (name == null)) {
0745:                    return (null);
0746:                }
0747:
0748:                PropertyDescriptor descriptors[] = getPropertyDescriptors(bean);
0749:                if (descriptors != null) {
0750:
0751:                    for (int i = 0; i < descriptors.length; i++) {
0752:                        if (name.equals(descriptors[i].getName()))
0753:                            return (descriptors[i]);
0754:                    }
0755:                }
0756:
0757:                PropertyDescriptor result;
0758:                Map mappedDescriptors = getMappedPropertyDescriptors(bean);
0759:                if (mappedDescriptors == null) {
0760:                    mappedDescriptors = new HashMap();
0761:                    mappedDescriptorsCache.put(bean.getClass(),
0762:                            mappedDescriptors);
0763:                }
0764:                result = (PropertyDescriptor) mappedDescriptors.get(name);
0765:                if (result == null) {
0766:                    // not found, try to create it
0767:                    try {
0768:                        result = new MappedPropertyDescriptor(name, bean
0769:                                .getClass());
0770:                    } catch (IntrospectionException ie) {
0771:                    }
0772:                    if (result != null) {
0773:                        mappedDescriptors.put(name, result);
0774:                    }
0775:                }
0776:
0777:                return result;
0778:
0779:            }
0780:
0781:            private int findNextNestedIndex(String expression) {
0782:                // walk back from the end to the start
0783:                // and find the first index that
0784:                int bracketCount = 0;
0785:                for (int i = 0, size = expression.length(); i < size; i++) {
0786:                    char at = expression.charAt(i);
0787:                    switch (at) {
0788:                    case PropertyUtils.NESTED_DELIM:
0789:                        if (bracketCount < 1) {
0790:                            return i;
0791:                        }
0792:                        break;
0793:
0794:                    case PropertyUtils.MAPPED_DELIM:
0795:                    case PropertyUtils.INDEXED_DELIM:
0796:                        // not bothered which
0797:                        ++bracketCount;
0798:                        break;
0799:
0800:                    case PropertyUtils.MAPPED_DELIM2:
0801:                    case PropertyUtils.INDEXED_DELIM2:
0802:                        // not bothered which
0803:                        --bracketCount;
0804:                        break;
0805:                    }
0806:                }
0807:                // can't find any
0808:                return -1;
0809:            }
0810:
0811:            /**
0812:             * <p>Retrieve the property descriptors for the specified class,
0813:             * introspecting and caching them the first time a particular bean class
0814:             * is encountered.</p>
0815:             * <p/>
0816:             * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
0817:             *
0818:             * @param beanClass Bean class for which property descriptors are requested
0819:             * @throws IllegalArgumentException if <code>beanClass</code> is null
0820:             */
0821:            public PropertyDescriptor[] getPropertyDescriptors(Class beanClass) {
0822:
0823:                if (beanClass == null) {
0824:                    throw new IllegalArgumentException(
0825:                            "No bean class specified");
0826:                }
0827:
0828:                // Look up any cached descriptors for this bean class
0829:                PropertyDescriptor[] descriptors;
0830:                descriptors = (PropertyDescriptor[]) descriptorsCache
0831:                        .get(beanClass);
0832:                if (descriptors != null) {
0833:                    return (descriptors);
0834:                }
0835:
0836:                // Introspect the bean and cache the generated descriptors
0837:                BeanInfo beanInfo;
0838:                try {
0839:                    beanInfo = Introspector.getBeanInfo(beanClass);
0840:                } catch (IntrospectionException e) {
0841:                    return (new PropertyDescriptor[0]);
0842:                }
0843:                descriptors = beanInfo.getPropertyDescriptors();
0844:                if (descriptors == null) {
0845:                    descriptors = new PropertyDescriptor[0];
0846:                }
0847:                descriptorsCache.put(beanClass, descriptors);
0848:                return (descriptors);
0849:
0850:            }
0851:
0852:            /**
0853:             * <p>Retrieve the property descriptors for the specified bean,
0854:             * introspecting and caching them the first time a particular bean class
0855:             * is encountered.</p>
0856:             * <p/>
0857:             * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
0858:             *
0859:             * @param bean Bean for which property descriptors are requested
0860:             * @throws IllegalArgumentException if <code>bean</code> is null
0861:             */
0862:            public PropertyDescriptor[] getPropertyDescriptors(Object bean) {
0863:
0864:                if (bean == null) {
0865:                    throw new IllegalArgumentException("No bean specified");
0866:                }
0867:                return (getPropertyDescriptors(bean.getClass()));
0868:
0869:            }
0870:
0871:            /**
0872:             * <p>Return the Java Class repesenting the property editor class that has
0873:             * been registered for this property (if any).  This method follows the
0874:             * same name resolution rules used by <code>getPropertyDescriptor()</code>,
0875:             * so if the last element of a name reference is indexed, the property
0876:             * editor for the underlying property's class is returned.</p>
0877:             * <p/>
0878:             * <p>Note that <code>null</code> will be returned if there is no property,
0879:             * or if there is no registered property editor class.  Because this
0880:             * return value is ambiguous, you should determine the existence of the
0881:             * property itself by other means.</p>
0882:             * <p/>
0883:             * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
0884:             *
0885:             * @param bean Bean for which a property descriptor is requested
0886:             * @param name Possibly indexed and/or nested name of the property for
0887:             *             which a property descriptor is requested
0888:             * @throws IllegalAccessException    if the caller does not have
0889:             *                                   access to the property accessor method
0890:             * @throws IllegalArgumentException  if <code>bean</code> or
0891:             *                                   <code>name</code> is null
0892:             * @throws IllegalArgumentException  if a nested reference to a
0893:             *                                   property returns null
0894:             * @throws InvocationTargetException if the property accessor method
0895:             *                                   throws an exception
0896:             * @throws NoSuchMethodException     if an accessor method for this
0897:             *                                   propety cannot be found
0898:             */
0899:            public Class getPropertyEditorClass(Object bean, String name)
0900:                    throws IllegalAccessException, InvocationTargetException,
0901:                    NoSuchMethodException {
0902:
0903:                if (bean == null) {
0904:                    throw new IllegalArgumentException("No bean specified");
0905:                }
0906:                if (name == null) {
0907:                    throw new IllegalArgumentException("No name specified");
0908:                }
0909:
0910:                PropertyDescriptor descriptor = getPropertyDescriptor(bean,
0911:                        name);
0912:                if (descriptor != null) {
0913:                    return (descriptor.getPropertyEditorClass());
0914:                } else {
0915:                    return (null);
0916:                }
0917:
0918:            }
0919:
0920:            /**
0921:             * Return the Java Class representing the property type of the specified
0922:             * property, or <code>null</code> if there is no such property for the
0923:             * specified bean.  This method follows the same name resolution rules
0924:             * used by <code>getPropertyDescriptor()</code>, so if the last element
0925:             * of a name reference is indexed, the type of the property itself will
0926:             * be returned.  If the last (or only) element has no property with the
0927:             * specified name, <code>null</code> is returned.
0928:             *
0929:             * @param bean Bean for which a property descriptor is requested
0930:             * @param name Possibly indexed and/or nested name of the property for
0931:             *             which a property descriptor is requested
0932:             * @throws IllegalAccessException    if the caller does not have
0933:             *                                   access to the property accessor method
0934:             * @throws IllegalArgumentException  if <code>bean</code> or
0935:             *                                   <code>name</code> is null
0936:             * @throws IllegalArgumentException  if a nested reference to a
0937:             *                                   property returns null
0938:             * @throws InvocationTargetException if the property accessor method
0939:             *                                   throws an exception
0940:             * @throws NoSuchMethodException     if an accessor method for this
0941:             *                                   propety cannot be found
0942:             */
0943:            public Class getPropertyType(Object bean, String name)
0944:                    throws IllegalAccessException, InvocationTargetException,
0945:                    NoSuchMethodException {
0946:
0947:                if (bean == null) {
0948:                    throw new IllegalArgumentException("No bean specified");
0949:                }
0950:                if (name == null) {
0951:                    throw new IllegalArgumentException("No name specified");
0952:                }
0953:
0954:                PropertyDescriptor descriptor = getPropertyDescriptor(bean,
0955:                        name);
0956:                if (descriptor == null) {
0957:                    return (null);
0958:                } else if (descriptor instanceof  IndexedPropertyDescriptor) {
0959:                    return (((IndexedPropertyDescriptor) descriptor)
0960:                            .getIndexedPropertyType());
0961:                } else if (descriptor instanceof  MappedPropertyDescriptor) {
0962:                    return (((MappedPropertyDescriptor) descriptor)
0963:                            .getMappedPropertyType());
0964:                } else {
0965:                    return (descriptor.getPropertyType());
0966:                }
0967:
0968:            }
0969:
0970:            /**
0971:             * <p>Return an accessible property getter method for this property,
0972:             * if there is one; otherwise return <code>null</code>.</p>
0973:             * <p/>
0974:             * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
0975:             *
0976:             * @param descriptor Property descriptor to return a getter for
0977:             */
0978:            public Method getReadMethod(PropertyDescriptor descriptor) {
0979:
0980:                return (MethodUtils.getAccessibleMethod(descriptor
0981:                        .getReadMethod()));
0982:
0983:            }
0984:
0985:            /**
0986:             * Return the value of the specified simple property of the specified
0987:             * bean, with no type conversions.
0988:             *
0989:             * @param bean Bean whose property is to be extracted
0990:             * @param name Name of the property to be extracted
0991:             * @throws IllegalAccessException    if the caller does not have
0992:             *                                   access to the property accessor method
0993:             * @throws IllegalArgumentException  if <code>bean</code> or
0994:             *                                   <code>name</code> is null
0995:             * @throws IllegalArgumentException  if the property name
0996:             *                                   is nested or indexed
0997:             * @throws InvocationTargetException if the property accessor method
0998:             *                                   throws an exception
0999:             * @throws NoSuchMethodException     if an accessor method for this
1000:             *                                   propety cannot be found
1001:             */
1002:            public Object getSimpleProperty(Object bean, String name)
1003:                    throws IllegalAccessException, InvocationTargetException,
1004:                    NoSuchMethodException {
1005:
1006:                if (bean == null) {
1007:                    throw new IllegalArgumentException("No bean specified");
1008:                }
1009:                if (name == null) {
1010:                    throw new IllegalArgumentException("No name specified");
1011:                }
1012:
1013:                // Validate the syntax of the property name
1014:                if (name.indexOf(PropertyUtils.NESTED_DELIM) >= 0) {
1015:                    throw new IllegalArgumentException(
1016:                            "Nested property names are not allowed");
1017:                } else if (name.indexOf(PropertyUtils.INDEXED_DELIM) >= 0) {
1018:                    throw new IllegalArgumentException(
1019:                            "Indexed property names are not allowed");
1020:                } else if (name.indexOf(PropertyUtils.MAPPED_DELIM) >= 0) {
1021:                    throw new IllegalArgumentException(
1022:                            "Mapped property names are not allowed");
1023:                }
1024:
1025:                // Retrieve the property getter method for the specified property
1026:                PropertyDescriptor descriptor = getPropertyDescriptor(bean,
1027:                        name);
1028:                if (descriptor == null) {
1029:                    throw new NoSuchMethodException("Unknown property '" + name
1030:                            + "' in bean " + bean + " of type "
1031:                            + bean.getClass());
1032:                }
1033:                Method readMethod = getReadMethod(descriptor);
1034:                if (readMethod == null) {
1035:                    throw new NoSuchMethodException("Property '" + name
1036:                            + "' has no getter method");
1037:                }
1038:
1039:                // Call the property getter and return the value
1040:                Object value = invokeMethod(readMethod, bean, new Object[0]);
1041:                return (value);
1042:
1043:            }
1044:
1045:            /**
1046:             * <p>Return an accessible property setter method for this property,
1047:             * if there is one; otherwise return <code>null</code>.</p>
1048:             * <p/>
1049:             * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
1050:             *
1051:             * @param descriptor Property descriptor to return a setter for
1052:             */
1053:            public Method getWriteMethod(PropertyDescriptor descriptor) {
1054:
1055:                return (MethodUtils.getAccessibleMethod(descriptor
1056:                        .getWriteMethod()));
1057:
1058:            }
1059:
1060:            /**
1061:             * <p>Return <code>true</code> if the specified property name identifies
1062:             * a readable property on the specified bean; otherwise, return
1063:             * <code>false</code>.
1064:             *
1065:             * @param bean Bean to be examined
1066:             * @param name Property name to be evaluated
1067:             * @throws IllegalArgumentException if <code>bean</code>
1068:             *                                  or <code>name</code> is <code>null</code>
1069:             * @since BeanUtils 1.6
1070:             */
1071:            public boolean isReadable(Object bean, String name) {
1072:
1073:                // Validate method parameters
1074:                if (bean == null) {
1075:                    throw new IllegalArgumentException("No bean specified");
1076:                }
1077:                if (name == null) {
1078:                    throw new IllegalArgumentException("No name specified");
1079:                }
1080:
1081:                // Return the requested result
1082:                try {
1083:                    PropertyDescriptor desc = getPropertyDescriptor(bean, name);
1084:                    if (desc != null) {
1085:                        Method readMethod = desc.getReadMethod();
1086:                        if ((readMethod == null)
1087:                                && (desc instanceof  IndexedPropertyDescriptor)) {
1088:                            readMethod = ((IndexedPropertyDescriptor) desc)
1089:                                    .getIndexedReadMethod();
1090:                        }
1091:                        return (readMethod != null);
1092:                    } else {
1093:                        return (false);
1094:                    }
1095:                } catch (IllegalAccessException e) {
1096:                    return (false);
1097:                } catch (InvocationTargetException e) {
1098:                    return (false);
1099:                } catch (NoSuchMethodException e) {
1100:                    return (false);
1101:                }
1102:
1103:            }
1104:
1105:            /**
1106:             * <p>Return <code>true</code> if the specified property name identifies
1107:             * a writeable property on the specified bean; otherwise, return
1108:             * <code>false</code>.
1109:             *
1110:             * @param bean Bean to be examined
1111:             * @param name Property name to be evaluated
1112:             * @throws IllegalArgumentException if <code>bean</code>
1113:             *                                  or <code>name</code> is <code>null</code>
1114:             * @since BeanUtils 1.6
1115:             */
1116:            public boolean isWriteable(Object bean, String name) {
1117:
1118:                // Validate method parameters
1119:                if (bean == null) {
1120:                    throw new IllegalArgumentException("No bean specified");
1121:                }
1122:                if (name == null) {
1123:                    throw new IllegalArgumentException("No name specified");
1124:                }
1125:
1126:                // Return the requested result
1127:                try {
1128:                    PropertyDescriptor desc = getPropertyDescriptor(bean, name);
1129:                    if (desc != null) {
1130:                        Method writeMethod = desc.getWriteMethod();
1131:                        if ((writeMethod == null)
1132:                                && (desc instanceof  IndexedPropertyDescriptor)) {
1133:                            writeMethod = ((IndexedPropertyDescriptor) desc)
1134:                                    .getIndexedWriteMethod();
1135:                        }
1136:                        return (writeMethod != null);
1137:                    } else {
1138:                        return (false);
1139:                    }
1140:                } catch (IllegalAccessException e) {
1141:                    return (false);
1142:                } catch (InvocationTargetException e) {
1143:                    return (false);
1144:                } catch (NoSuchMethodException e) {
1145:                    return (false);
1146:                }
1147:            }
1148:
1149:            /**
1150:             * Set the value of the specified indexed property of the specified
1151:             * bean, with no type conversions.  The zero-relative index of the
1152:             * required value must be included (in square brackets) as a suffix to
1153:             * the property name, or <code>IllegalArgumentException</code> will be
1154:             * thrown.  In addition to supporting the JavaBeans specification, this
1155:             * method has been extended to support <code>List</code> objects as well.
1156:             *
1157:             * @param bean  Bean whose property is to be modified
1158:             * @param name  <code>propertyname[index]</code> of the property value
1159:             *              to be modified
1160:             * @param value Value to which the specified property element
1161:             *              should be set
1162:             * @throws ArrayIndexOutOfBoundsException if the specified index
1163:             *                                        is outside the valid range for the underlying array
1164:             * @throws IllegalAccessException         if the caller does not have
1165:             *                                        access to the property accessor method
1166:             * @throws IllegalArgumentException       if <code>bean</code> or
1167:             *                                        <code>name</code> is null
1168:             * @throws InvocationTargetException      if the property accessor method
1169:             *                                        throws an exception
1170:             * @throws NoSuchMethodException          if an accessor method for this
1171:             *                                        propety cannot be found
1172:             */
1173:            public void setIndexedProperty(Object bean, String name,
1174:                    Object value) throws IllegalAccessException,
1175:                    InvocationTargetException, NoSuchMethodException {
1176:
1177:                if (bean == null) {
1178:                    throw new IllegalArgumentException("No bean specified");
1179:                }
1180:                if (name == null) {
1181:                    throw new IllegalArgumentException("No name specified");
1182:                }
1183:
1184:                // Identify the index of the requested individual property
1185:                int delim = name.indexOf(PropertyUtils.INDEXED_DELIM);
1186:                int delim2 = name.indexOf(PropertyUtils.INDEXED_DELIM2);
1187:                if ((delim < 0) || (delim2 <= delim)) {
1188:                    throw new IllegalArgumentException(
1189:                            "Invalid indexed property '" + name + "'");
1190:                }
1191:                int index;
1192:                try {
1193:                    String subscript = name.substring(delim + 1, delim2);
1194:                    index = Integer.parseInt(subscript);
1195:                } catch (NumberFormatException e) {
1196:                    throw new IllegalArgumentException(
1197:                            "Invalid indexed property '" + name + "'");
1198:                }
1199:                name = name.substring(0, delim);
1200:
1201:                // Set the specified indexed property value
1202:                setIndexedProperty(bean, name, index, value);
1203:
1204:            }
1205:
1206:            /**
1207:             * Set the value of the specified indexed property of the specified
1208:             * bean, with no type conversions.  In addition to supporting the JavaBeans
1209:             * specification, this method has been extended to support
1210:             * <code>List</code> objects as well.
1211:             *
1212:             * @param bean  Bean whose property is to be set
1213:             * @param name  Simple property name of the property value to be set
1214:             * @param index Index of the property value to be set
1215:             * @param value Value to which the indexed property element is to be set
1216:             * @throws ArrayIndexOutOfBoundsException if the specified index
1217:             *                                        is outside the valid range for the underlying array
1218:             * @throws IllegalAccessException         if the caller does not have
1219:             *                                        access to the property accessor method
1220:             * @throws IllegalArgumentException       if <code>bean</code> or
1221:             *                                        <code>name</code> is null
1222:             * @throws InvocationTargetException      if the property accessor method
1223:             *                                        throws an exception
1224:             * @throws NoSuchMethodException          if an accessor method for this
1225:             *                                        propety cannot be found
1226:             */
1227:            public void setIndexedProperty(Object bean, String name, int index,
1228:                    Object value) throws IllegalAccessException,
1229:                    InvocationTargetException, NoSuchMethodException {
1230:
1231:                if (bean == null) {
1232:                    throw new IllegalArgumentException("No bean specified");
1233:                }
1234:                if (name == null) {
1235:                    throw new IllegalArgumentException("No name specified");
1236:                }
1237:
1238:                // Retrieve the property descriptor for the specified property
1239:                PropertyDescriptor descriptor = getPropertyDescriptor(bean,
1240:                        name);
1241:                if (descriptor == null) {
1242:                    throw new NoSuchMethodException("Unknown property '" + name
1243:                            + "'");
1244:                }
1245:
1246:                // Call the indexed setter method if there is one
1247:                if (descriptor instanceof  IndexedPropertyDescriptor) {
1248:                    Method writeMethod = ((IndexedPropertyDescriptor) descriptor)
1249:                            .getIndexedWriteMethod();
1250:                    if (writeMethod != null) {
1251:                        Object subscript[] = new Object[2];
1252:                        subscript[0] = new Integer(index);
1253:                        subscript[1] = value;
1254:                        try {
1255:                            invokeMethod(writeMethod, bean, subscript);
1256:                        } catch (InvocationTargetException e) {
1257:                            if (e.getTargetException() instanceof  ArrayIndexOutOfBoundsException) {
1258:                                throw (ArrayIndexOutOfBoundsException) e
1259:                                        .getTargetException();
1260:                            } else {
1261:                                throw e;
1262:                            }
1263:                        }
1264:                        return;
1265:                    }
1266:                }
1267:
1268:                // Otherwise, the underlying property must be an array or a list
1269:                Method readMethod = descriptor.getReadMethod();
1270:                if (readMethod == null) {
1271:                    throw new NoSuchMethodException("Property '" + name
1272:                            + "' has no getter method");
1273:                }
1274:
1275:                // Call the property getter to get the array or list
1276:                Object array = invokeMethod(readMethod, bean, new Object[0]);
1277:                if (!array.getClass().isArray()) {
1278:                    if (array instanceof  List) {
1279:                        // Modify the specified value in the List
1280:                        ((List) array).set(index, value);
1281:                    } else {
1282:                        throw new IllegalArgumentException("Property '" + name
1283:                                + "' is not indexed");
1284:                    }
1285:                } else {
1286:                    // Modify the specified value in the array
1287:                    Array.set(array, index, value);
1288:                }
1289:
1290:            }
1291:
1292:            /**
1293:             * Set the value of the specified mapped property of the
1294:             * specified bean, with no type conversions.  The key of the
1295:             * value to set must be included (in brackets) as a suffix to
1296:             * the property name, or <code>IllegalArgumentException</code> will be
1297:             * thrown.
1298:             *
1299:             * @param bean  Bean whose property is to be set
1300:             * @param name  <code>propertyname(key)</code> of the property value
1301:             *              to be set
1302:             * @param value The property value to be set
1303:             * @throws IllegalAccessException    if the caller does not have
1304:             *                                   access to the property accessor method
1305:             * @throws InvocationTargetException if the property accessor method
1306:             *                                   throws an exception
1307:             * @throws NoSuchMethodException     if an accessor method for this
1308:             *                                   propety cannot be found
1309:             */
1310:            public void setMappedProperty(Object bean, String name, Object value)
1311:                    throws IllegalAccessException, InvocationTargetException,
1312:                    NoSuchMethodException {
1313:
1314:                if (bean == null) {
1315:                    throw new IllegalArgumentException("No bean specified");
1316:                }
1317:                if (name == null) {
1318:                    throw new IllegalArgumentException("No name specified");
1319:                }
1320:
1321:                // Identify the index of the requested individual property
1322:                int delim = name.indexOf(PropertyUtils.MAPPED_DELIM);
1323:                int delim2 = name.indexOf(PropertyUtils.MAPPED_DELIM2);
1324:                if ((delim < 0) || (delim2 <= delim)) {
1325:                    throw new IllegalArgumentException(
1326:                            "Invalid mapped property '" + name + "'");
1327:                }
1328:
1329:                // Isolate the name and the key
1330:                String key = name.substring(delim + 1, delim2);
1331:                name = name.substring(0, delim);
1332:
1333:                // Request the specified indexed property value
1334:                setMappedProperty(bean, name, key, value);
1335:
1336:            }
1337:
1338:            /**
1339:             * Set the value of the specified mapped property of the specified
1340:             * bean, with no type conversions.
1341:             *
1342:             * @param bean  Bean whose property is to be set
1343:             * @param name  Mapped property name of the property value to be set
1344:             * @param key   Key of the property value to be set
1345:             * @param value The property value to be set
1346:             * @throws IllegalAccessException    if the caller does not have
1347:             *                                   access to the property accessor method
1348:             * @throws InvocationTargetException if the property accessor method
1349:             *                                   throws an exception
1350:             * @throws NoSuchMethodException     if an accessor method for this
1351:             *                                   propety cannot be found
1352:             */
1353:            public void setMappedProperty(Object bean, String name, String key,
1354:                    Object value) throws IllegalAccessException,
1355:                    InvocationTargetException, NoSuchMethodException {
1356:
1357:                if (bean == null) {
1358:                    throw new IllegalArgumentException("No bean specified");
1359:                }
1360:                if (name == null) {
1361:                    throw new IllegalArgumentException("No name specified");
1362:                }
1363:                if (key == null) {
1364:                    throw new IllegalArgumentException("No key specified");
1365:                }
1366:
1367:                // Retrieve the property descriptor for the specified property
1368:                PropertyDescriptor descriptor = getPropertyDescriptor(bean,
1369:                        name);
1370:                if (descriptor == null) {
1371:                    throw new NoSuchMethodException("Unknown property '" + name
1372:                            + "'");
1373:                }
1374:
1375:                if (descriptor instanceof  MappedPropertyDescriptor) {
1376:                    // Call the keyed setter method if there is one
1377:                    Method mappedWriteMethod = ((MappedPropertyDescriptor) descriptor)
1378:                            .getMappedWriteMethod();
1379:                    if (mappedWriteMethod != null) {
1380:                        Object params[] = new Object[2];
1381:                        params[0] = key;
1382:                        params[1] = value;
1383:                        invokeMethod(mappedWriteMethod, bean, params);
1384:                    } else {
1385:                        throw new NoSuchMethodException("Property '" + name
1386:                                + "' has no mapped setter method");
1387:                    }
1388:                } else {
1389:                    /* means that the result has to be retrieved from a map */
1390:                    Method readMethod = descriptor.getReadMethod();
1391:                    if (readMethod != null) {
1392:                        Object invokeResult = invokeMethod(readMethod, bean,
1393:                                new Object[0]);
1394:                        /* test and fetch from the map */
1395:                        if (invokeResult instanceof  java.util.Map) {
1396:                            ((java.util.Map) invokeResult).put(key, value);
1397:                        }
1398:                    } else {
1399:                        throw new NoSuchMethodException("Property '" + name
1400:                                + "' has no mapped getter method");
1401:                    }
1402:                }
1403:
1404:            }
1405:
1406:            /**
1407:             * Set the value of the (possibly nested) property of the specified
1408:             * name, for the specified bean, with no type conversions.
1409:             *
1410:             * @param bean  Bean whose property is to be modified
1411:             * @param name  Possibly nested name of the property to be modified
1412:             * @param value Value to which the property is to be set
1413:             * @throws IllegalAccessException    if the caller does not have
1414:             *                                   access to the property accessor method
1415:             * @throws IllegalArgumentException  if <code>bean</code> or
1416:             *                                   <code>name</code> is null
1417:             * @throws IllegalArgumentException  if a nested reference to a
1418:             *                                   property returns null
1419:             * @throws InvocationTargetException if the property accessor method
1420:             *                                   throws an exception
1421:             * @throws NoSuchMethodException     if an accessor method for this
1422:             *                                   propety cannot be found
1423:             */
1424:            public void setNestedProperty(Object bean, String name, Object value)
1425:                    throws IllegalAccessException, InvocationTargetException,
1426:                    NoSuchMethodException {
1427:
1428:                if (bean == null) {
1429:                    throw new IllegalArgumentException("No bean specified");
1430:                }
1431:                if (name == null) {
1432:                    throw new IllegalArgumentException("No name specified");
1433:                }
1434:
1435:                int indexOfINDEXED_DELIM;
1436:                int indexOfMAPPED_DELIM;
1437:                while (true) {
1438:                    int delim = name.indexOf(PropertyUtils.NESTED_DELIM);
1439:                    if (delim < 0) {
1440:                        break;
1441:                    }
1442:                    String next = name.substring(0, delim);
1443:                    indexOfINDEXED_DELIM = next
1444:                            .indexOf(PropertyUtils.INDEXED_DELIM);
1445:                    indexOfMAPPED_DELIM = next
1446:                            .indexOf(PropertyUtils.MAPPED_DELIM);
1447:                    if (bean instanceof  Map) {
1448:                        bean = ((Map) bean).get(next);
1449:                    } else if (indexOfMAPPED_DELIM >= 0) {
1450:                        bean = getMappedProperty(bean, next);
1451:                    } else if (indexOfINDEXED_DELIM >= 0) {
1452:                        bean = getIndexedProperty(bean, next);
1453:                    } else {
1454:                        bean = getSimpleProperty(bean, next);
1455:                    }
1456:                    if (bean == null) {
1457:                        throw new IllegalArgumentException(
1458:                                "Null property value for '"
1459:                                        + name.substring(0, delim) + "'");
1460:                    }
1461:                    name = name.substring(delim + 1);
1462:                }
1463:
1464:                indexOfINDEXED_DELIM = name
1465:                        .indexOf(PropertyUtils.INDEXED_DELIM);
1466:                indexOfMAPPED_DELIM = name.indexOf(PropertyUtils.MAPPED_DELIM);
1467:
1468:                if (bean instanceof  Map) {
1469:                    // check to see if the class has a standard property
1470:                    PropertyDescriptor descriptor = getPropertyDescriptor(bean,
1471:                            name);
1472:                    if (descriptor == null) {
1473:                        // no - then put the value into the map
1474:                        ((Map) bean).put(name, value);
1475:                    } else {
1476:                        // yes - use that instead
1477:                        setSimpleProperty(bean, name, value);
1478:                    }
1479:                } else if (indexOfMAPPED_DELIM >= 0) {
1480:                    setMappedProperty(bean, name, value);
1481:                } else if (indexOfINDEXED_DELIM >= 0) {
1482:                    setIndexedProperty(bean, name, value);
1483:                } else {
1484:                    setSimpleProperty(bean, name, value);
1485:                }
1486:
1487:            }
1488:
1489:            /**
1490:             * Set the value of the specified property of the specified bean,
1491:             * no matter which property reference format is used, with no
1492:             * type conversions.
1493:             *
1494:             * @param bean  Bean whose property is to be modified
1495:             * @param name  Possibly indexed and/or nested name of the property
1496:             *              to be modified
1497:             * @param value Value to which this property is to be set
1498:             * @throws IllegalAccessException    if the caller does not have
1499:             *                                   access to the property accessor method
1500:             * @throws IllegalArgumentException  if <code>bean</code> or
1501:             *                                   <code>name</code> is null
1502:             * @throws InvocationTargetException if the property accessor method
1503:             *                                   throws an exception
1504:             * @throws NoSuchMethodException     if an accessor method for this
1505:             *                                   propety cannot be found
1506:             */
1507:            public void setProperty(Object bean, String name, Object value)
1508:                    throws IllegalAccessException, InvocationTargetException,
1509:                    NoSuchMethodException {
1510:
1511:                setNestedProperty(bean, name, value);
1512:
1513:            }
1514:
1515:            /**
1516:             * Set the value of the specified simple property of the specified bean,
1517:             * with no type conversions.
1518:             *
1519:             * @param bean  Bean whose property is to be modified
1520:             * @param name  Name of the property to be modified
1521:             * @param value Value to which the property should be set
1522:             * @throws IllegalAccessException    if the caller does not have
1523:             *                                   access to the property accessor method
1524:             * @throws IllegalArgumentException  if <code>bean</code> or
1525:             *                                   <code>name</code> is null
1526:             * @throws IllegalArgumentException  if the property name is
1527:             *                                   nested or indexed
1528:             * @throws InvocationTargetException if the property accessor method
1529:             *                                   throws an exception
1530:             * @throws NoSuchMethodException     if an accessor method for this
1531:             *                                   propety cannot be found
1532:             */
1533:            public void setSimpleProperty(Object bean, String name, Object value)
1534:                    throws IllegalAccessException, InvocationTargetException,
1535:                    NoSuchMethodException {
1536:
1537:                if (bean == null) {
1538:                    throw new IllegalArgumentException("No bean specified");
1539:                }
1540:                if (name == null) {
1541:                    throw new IllegalArgumentException("No name specified");
1542:                }
1543:
1544:                // Validate the syntax of the property name
1545:                if (name.indexOf(PropertyUtils.NESTED_DELIM) >= 0) {
1546:                    throw new IllegalArgumentException(
1547:                            "Nested property names are not allowed");
1548:                } else if (name.indexOf(PropertyUtils.INDEXED_DELIM) >= 0) {
1549:                    throw new IllegalArgumentException(
1550:                            "Indexed property names are not allowed");
1551:                } else if (name.indexOf(PropertyUtils.MAPPED_DELIM) >= 0) {
1552:                    throw new IllegalArgumentException(
1553:                            "Mapped property names are not allowed");
1554:                }
1555:
1556:                // Retrieve the property setter method for the specified property
1557:                PropertyDescriptor descriptor = getPropertyDescriptor(bean,
1558:                        name);
1559:                if (descriptor == null) {
1560:                    throw new NoSuchMethodException("Unknown property '" + name
1561:                            + "' in bean " + bean);
1562:                }
1563:                Method writeMethod = getWriteMethod(descriptor);
1564:                if (writeMethod == null) {
1565:                    throw new NoSuchMethodException("Property '" + name
1566:                            + "' has no setter method in bean " + bean);
1567:                }
1568:
1569:                // Call the property setter method
1570:                Object values[] = new Object[1];
1571:                values[0] = value;
1572:                invokeMethod(writeMethod, bean, values);
1573:
1574:            }
1575:
1576:            /**
1577:             * This just catches and wraps IllegalArgumentException.
1578:             */
1579:            private Object invokeMethod(Method method, Object bean,
1580:                    Object[] values) throws IllegalAccessException,
1581:                    InvocationTargetException {
1582:                try {
1583:                    return method.invoke(bean, values);
1584:                } catch (IllegalArgumentException e) {
1585:                    throw new IllegalArgumentException("Cannot invoke "
1586:                            + method.getDeclaringClass().getName() + "."
1587:                            + method.getName() + " - " + e.getMessage());
1588:                }
1589:            }
1590:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.