    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18
    19  package org.apache.commons.beanutils;
    20
    21
    22  import java.beans.PropertyDescriptor;
    23  import java.lang.reflect.InvocationTargetException;
    24  import java.lang.reflect.Method;
    25  import java.util.ArrayList;
    26  import java.util.Arrays;
    27  import java.util.HashMap;
    28  import java.util.List;
    29  import java.util.Map;
    30  import java.util.StringTokenizer;
    31
    32  import org.apache.commons.beanutils.priv.PrivateBeanFactory;
    33  import org.apache.commons.beanutils.priv.PrivateDirect;
    34
    35  import junit.framework.TestCase;
    36  import junit.framework.Test;
    37  import junit.framework.TestSuite;
    38
    39
    40  /***
    41   * <p>Test Case for the PropertyUtils class.  The majority of these tests use
    42   * instances of the TestBean class, so be sure to update the tests if you
    43   * change the characteristics of that class.</p>
    44   *
    45   * <p>So far, this test case has tests for the following methods of the
    46   * <code>PropertyUtils</code> class:</p>
    47   * <ul>
    48   * <li>getIndexedProperty(Object,String)</li>
    49   * <li>getIndexedProperty(Object,String,int)</li>
    50   * <li>getMappedProperty(Object,String)</li>
    51   * <li>getMappedProperty(Object,String,String</li>
    52   * <li>getNestedProperty(Object,String)</li>
    53   * <li>getPropertyDescriptor(Object,String)</li>
    54   * <li>getPropertyDescriptors(Object)</li>
    55   * <li>getPropertyType(Object,String)</li>
    56   * <li>getSimpleProperty(Object,String)</li>
    57   * <li>setIndexedProperty(Object,String,Object)</li>
    58   * <li>setIndexedProperty(Object,String,String,Object)</li>
    59   * <li>setMappedProperty(Object,String,Object)</li>
    60   * <li>setMappedProperty(Object,String,String,Object)</li>
    61   * <li>setNestedProperty(Object,String,Object)</li>
    62   * <li>setSimpleProperty(Object,String,Object)</li>
    63   * </ul>
    64   *
    65   * @author Craig R. McClanahan
    66   * @author Jan Sorensen
    67   * @version $Revision: 555184 $ $Date: 2007-07-11 07:25:35 +0100 (Wed, 11 Jul 2007) $
    68   */
    69
    70  public class PropertyUtilsTestCase extends TestCase {
    71
    72
    73      // ---------------------------------------------------- Instance Variables
    74
    75
    76      /***
    77       * The fully qualified class name of our private directly
    78       * implemented interface.
    79       */
    80      private static final String PRIVATE_DIRECT_CLASS =
    81              "org.apache.commons.beanutils.priv.PrivateDirect";
    82
    83
    84      /***
    85       * The fully qualified class name of our private indirectly
    86       * implemented interface.
    87       */
    88      private static final String PRIVATE_INDIRECT_CLASS =
    89              "org.apache.commons.beanutils.priv.PrivateIndirect";
    90
    91
    92      /***
    93       * The fully qualified class name of our test bean class.
    94       */
    95      private static final String TEST_BEAN_CLASS =
    96              "org.apache.commons.beanutils.TestBean";
    97
    98
    99      /***
    100      * The basic test bean for each test.
    101      */
    102     protected TestBean bean = null;
    103
    104
    105     /***
    106      * The "package private subclass" test bean for each test.
    107      */
    108     protected TestBeanPackageSubclass beanPackageSubclass = null;
    109
    110
    111     /***
    112      * The test bean for private access tests.
    113      */
    114     protected PrivateDirect beanPrivate = null;
    115
    116
    117     /***
    118      * The test bean for private access tests of subclasses.
    119      */
    120     protected PrivateDirect beanPrivateSubclass = null;
    121
    122
    123     /***
    124      * The "public subclass" test bean for each test.
    125      */
    126     protected TestBeanPublicSubclass beanPublicSubclass = null;
    127
    128
    129     /***
    130      * The set of properties that should be described.
    131      */
    132     protected String describes[] =
    133     { "booleanProperty",
    134       "booleanSecond",
    135       "doubleProperty",
    136       "floatProperty",
    137       "intArray",
    138       //      "intIndexed",
    139       "intProperty",
    140       "listIndexed",
    141       "longProperty",
    142       //      "mappedObjects",
    143       //      "mappedProperty",
    144       //      "mappedIntProperty",
    145       "nested",
    146       "nullProperty",
    147       //      "readOnlyProperty",
    148       "shortProperty",
    149       "stringArray",
    150       //      "stringIndexed",
    151       "stringProperty"
    152     };
    153
    154
    155     /***
    156      * The set of property names we expect to have returned when calling
    157      * <code>getPropertyDescriptors()</code>.  You should update this list
    158      * when new properties are added to TestBean.
    159      */
    160     protected final static String[] properties = {
    161         "booleanProperty",
    162         "booleanSecond",
    163         "doubleProperty",
    164         "dupProperty",
    165         "floatProperty",
    166         "intArray",
    167         "intIndexed",
    168         "intProperty",
    169         "listIndexed",
    170         "longProperty",
    171         "nested",
    172         "nullProperty",
    173         "readOnlyProperty",
    174         "shortProperty",
    175         "stringArray",
    176         "stringIndexed",
    177         "stringProperty",
    178         "writeOnlyProperty",
    179     };
    180
    181
    182     // ---------------------------------------------------------- Constructors
    183
    184
    185     /***
    186      * Construct a new instance of this test case.
    187      *
    188      * @param name Name of the test case
    189      */
    190     public PropertyUtilsTestCase(String name) {
    191
    192         super(name);
    193
    194     }
    195
    196
    197     // -------------------------------------------------- Overall Test Methods
    198
    199
    200     /***
    201      * Set up instance variables required by this test case.
    202      */
    203     public void setUp() {
    204
    205         bean = new TestBean();
    206         beanPackageSubclass = new TestBeanPackageSubclass();
    207         beanPrivate = PrivateBeanFactory.create();
    208         beanPrivateSubclass = PrivateBeanFactory.createSubclass();
    209         beanPublicSubclass = new TestBeanPublicSubclass();
    210
    211     }
    212
    213
    214     /***
    215      * Return the tests included in this test suite.
    216      */
    217     public static Test suite() {
    218
    219         return (new TestSuite(PropertyUtilsTestCase.class));
    220
    221     }
    222
    223
    224     /***
    225      * Tear down instance variables required by this test case.
    226      */
    227     public void tearDown() {
    228
    229         bean = null;
    230         beanPackageSubclass = null;
    231         beanPrivate = null;
    232         beanPrivateSubclass = null;
    233         beanPublicSubclass = null;
    234
    235     }
    236
    237
    238
    239     // ------------------------------------------------ Individual Test Methods
    240
    241
    242     /***
    243      * Test copyProperties() when the origin is a a <code>Map</code>.
    244      */
    245     public void testCopyPropertiesMap() {
    246
    247         Map map = new HashMap();
    248         map.put("booleanProperty", Boolean.FALSE);
    249         map.put("doubleProperty", new Double(333.0));
    250         map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
    251         map.put("floatProperty", new Float((float) 222.0));
    252         map.put("intArray", new int[] { 0, 100, 200 });
    253         map.put("intProperty", new Integer(111));
    254         map.put("longProperty", new Long(444));
    255         map.put("shortProperty", new Short((short) 555));
    256         map.put("stringProperty", "New String Property");
    257
    258         try {
    259             PropertyUtils.copyProperties(bean, map);
    260         } catch (Throwable t) {
    261             fail("Threw " + t.toString());
    262         }
    263
    264         // Scalar properties
    265         assertEquals("booleanProperty", false,
    266                      bean.getBooleanProperty());
    267         assertEquals("doubleProperty", 333.0,
    268                      bean.getDoubleProperty(), 0.005);
    269         assertEquals("floatProperty", (float) 222.0,
    270                      bean.getFloatProperty(), (float) 0.005);
    271         assertEquals("intProperty", 111,
    272                      bean.getIntProperty());
    273         assertEquals("longProperty", 444,
    274                      bean.getLongProperty());
    275         assertEquals("shortProperty", (short) 555,
    276                      bean.getShortProperty());
    277         assertEquals("stringProperty", "New String Property",
    278                      bean.getStringProperty());
    279
    280         // Indexed Properties
    281         String dupProperty[] = bean.getDupProperty();
    282         assertNotNull("dupProperty present", dupProperty);
    283         assertEquals("dupProperty length", 3, dupProperty.length);
    284         assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
    285         assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
    286         assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
    287         int intArray[] = bean.getIntArray();
    288         assertNotNull("intArray present", intArray);
    289         assertEquals("intArray length", 3, intArray.length);
    290         assertEquals("intArray[0]", 0, intArray[0]);
    291         assertEquals("intArray[1]", 100, intArray[1]);
    292         assertEquals("intArray[2]", 200, intArray[2]);
    293
    294     }
    295
    296
    297     /***
    298      * Test the describe() method.
    299      */
    300     public void testDescribe() {
    301
    302         Map map = null;
    303         try {
    304             map = PropertyUtils.describe(bean);
    305         } catch (Exception e) {
    306             fail("Threw exception " + e);
    307         }
    308
    309         // Verify existence of all the properties that should be present
    310         for (int i = 0; i < describes.length; i++) {
    311             assertTrue("Property '" + describes[i] + "' is present",
    312                        map.containsKey(describes[i]));
    313         }
    314         assertTrue("Property 'writeOnlyProperty' is not present",
    315                    !map.containsKey("writeOnlyProperty"));
    316
    317         // Verify the values of scalar properties
    318         assertEquals("Value of 'booleanProperty'",
    319                      Boolean.TRUE, map.get("booleanProperty"));
    320         assertEquals("Value of 'doubleProperty'",
    321                      new Double(321.0), map.get("doubleProperty"));
    322         assertEquals("Value of 'floatProperty'",
    323                      new Float((float) 123.0), map.get("floatProperty"));
    324         assertEquals("Value of 'intProperty'",
    325                      new Integer(123), map.get("intProperty"));
    326         assertEquals("Value of 'longProperty'",
    327                      new Long(321), map.get("longProperty"));
    328         assertEquals("Value of 'shortProperty'",
    329                      new Short((short) 987), map.get("shortProperty"));
    330         assertEquals("Value of 'stringProperty'",
    331                      "This is a string",
    332                      (String) map.get("stringProperty"));
    333
    334     }
    335
    336
    337     /***
    338      * Corner cases on getPropertyDescriptor invalid arguments.
    339      */
    340     public void testGetDescriptorArguments() {
    341
    342         try {
    343             PropertyUtils.getPropertyDescriptor(null, "stringProperty");
    344             fail("Should throw IllegalArgumentException 1");
    345         } catch (IllegalArgumentException e) {
    346             // Expected response
    347         } catch (Throwable t) {
    348             fail("Threw " + t + " instead of IllegalArgumentException 1");
    349         }
    350
    351         try {
    352             PropertyUtils.getPropertyDescriptor(bean, null);
    353             fail("Should throw IllegalArgumentException 2");
    354         } catch (IllegalArgumentException e) {
    355             // Expected response
    356         } catch (Throwable t) {
    357             fail("Threw " + t + " instead of IllegalArgumentException 2");
    358         }
    359
    360     }
    361
    362
    363     /***
    364      * Positive getPropertyDescriptor on property <code>booleanProperty</code>.
    365      */
    366     public void testGetDescriptorBoolean() {
    367
    368         testGetDescriptorBase("booleanProperty", "getBooleanProperty",
    369                 "setBooleanProperty");
    370
    371     }
    372
    373
    374     /***
    375      * Positive getPropertyDescriptor on property <code>doubleProperty</code>.
    376      */
    377     public void testGetDescriptorDouble() {
    378
    379         testGetDescriptorBase("doubleProperty", "getDoubleProperty",
    380                 "setDoubleProperty");
    381
    382     }
    383
    384
    385     /***
    386      * Positive getPropertyDescriptor on property <code>floatProperty</code>.
    387      */
    388     public void testGetDescriptorFloat() {
    389
    390         testGetDescriptorBase("floatProperty", "getFloatProperty",
    391                 "setFloatProperty");
    392
    393     }
    394
    395
    396     /***
    397      * Positive getPropertyDescriptor on property <code>intProperty</code>.
    398      */
    399     public void testGetDescriptorInt() {
    400
    401         testGetDescriptorBase("intProperty", "getIntProperty",
    402                 "setIntProperty");
    403
    404     }
    405
    406
    407     /***
    408      * <p>Negative tests on an invalid property with two different boolean
    409      * getters (which is fine, according to the JavaBeans spec) but a
    410      * String setter instead of a boolean setter.</p>
    411      *
    412      * <p>Although one could logically argue that this combination of method
    413      * signatures should not identify a property at all, there is a sentence
    414      * in Section 8.3.1 making it clear that the behavior tested for here
    415      * is correct:  "If we find only one of these methods, then we regard
    416      * it as defining either a read-only or write-only property called
    417      * <em>&lt;property-name&gt;</em>.</p>
    418      */
    419     public void testGetDescriptorInvalidBoolean() throws Exception {
    420
    421 	PropertyDescriptor pd =
    422 	    PropertyUtils.getPropertyDescriptor(bean, "invalidBoolean");
    423 	assertNotNull("invalidBoolean is a property", pd);
    424 	assertNotNull("invalidBoolean has a getter method",
    425 		      pd.getReadMethod());
    426 	assertNull("invalidBoolean has no write method",
    427 		   pd.getWriteMethod());
    428 	assertTrue("invalidBoolean getter method is isInvalidBoolean",
    429 		   "isInvalidBoolean".equals(pd.getReadMethod().getName()));
    430
    431     }
    432
    433
    434     /***
    435      * Positive getPropertyDescriptor on property <code>longProperty</code>.
    436      */
    437     public void testGetDescriptorLong() {
    438
    439         testGetDescriptorBase("longProperty", "getLongProperty",
    440                 "setLongProperty");
    441
    442     }
    443
    444     /***
    445      * Test getting mapped descriptor with periods in the key.
    446      */
    447     public void testGetDescriptorMappedPeriods() {
    448
    449         bean.getMappedIntProperty("xyz"); // initializes mappedIntProperty
    450
    451         PropertyDescriptor desc;
    452         Integer testIntegerValue = new Integer(1234);
    453
    454         bean.setMappedIntProperty("key.with.a.dot", testIntegerValue.intValue());
    455         assertEquals("Can retrieve directly",
    456                      testIntegerValue,
    457                      new Integer(bean.getMappedIntProperty("key.with.a.dot")));
    458         try {
    459             desc = PropertyUtils.getPropertyDescriptor
    460                          (bean, "mappedIntProperty(key.with.a.dot)");
    461             assertEquals("Check descriptor type (A)",
    462                          Integer.TYPE,
    463                          ((MappedPropertyDescriptor)desc).getMappedPropertyType());
    464         } catch (Exception e) {
    465             fail("Threw exception (A): " + e);
    466         }
    467
    468         bean.setMappedObjects("nested.property", new TestBean(testIntegerValue.intValue()));
    469         assertEquals("Can retrieve directly",
    470                       testIntegerValue,
    471                       new Integer(((TestBean)bean.getMappedObjects("nested.property")).getIntProperty()));
    472         try {
    473             desc = PropertyUtils.getPropertyDescriptor
    474                          (bean, "mappedObjects(nested.property).intProperty");
    475             assertEquals("Check descriptor type (B)",
    476                          Integer.TYPE,
    477                          desc.getPropertyType());
    478         } catch (Exception e) {
    479             fail("Threw exception (B): " + e);
    480         }
    481     }
    482
    483
    484     /***
    485      * Positive getPropertyDescriptor on property
    486      * <code>readOnlyProperty</code>.
    487      */
    488     public void testGetDescriptorReadOnly() {
    489
    490         testGetDescriptorBase("readOnlyProperty", "getReadOnlyProperty",
    491                 null);
    492
    493     }
    494
    495
    496     /***
    497      * Positive getPropertyDescriptor on property <code>booleanSecond</code>
    498      * that uses an "is" method as the getter.
    499      */
    500     public void testGetDescriptorSecond() {
    501
    502         testGetDescriptorBase("booleanSecond", "isBooleanSecond",
    503                 "setBooleanSecond");
    504
    505     }
    506
    507
    508     /***
    509      * Positive getPropertyDescriptor on property <code>shortProperty</code>.
    510      */
    511     public void testGetDescriptorShort() {
    512
    513         testGetDescriptorBase("shortProperty", "getShortProperty",
    514                 "setShortProperty");
    515
    516     }
    517
    518
    519     /***
    520      * Positive getPropertyDescriptor on property <code>stringProperty</code>.
    521      */
    522     public void testGetDescriptorString() {
    523
    524         testGetDescriptorBase("stringProperty", "getStringProperty",
    525                 "setStringProperty");
    526
    527     }
    528
    529
    530     /***
    531      * Negative getPropertyDescriptor on property <code>unknown</code>.
    532      */
    533     public void testGetDescriptorUnknown() {
    534
    535         testGetDescriptorBase("unknown", null, null);
    536
    537     }
    538
    539
    540     /***
    541      * Positive getPropertyDescriptor on property
    542      * <code>writeOnlyProperty</code>.
    543      */
    544     public void testGetDescriptorWriteOnly() {
    545
    546         testGetDescriptorBase("writeOnlyProperty", null,
    547                 "setWriteOnlyProperty");
    548
    549     }
    550
    551
    552     /***
    553      * Positive test for getPropertyDescriptors().  Each property name
    554      * listed in <code>properties</code> should be returned exactly once.
    555      */
    556     public void testGetDescriptors() {
    557
    558         PropertyDescriptor pd[] =
    559                 PropertyUtils.getPropertyDescriptors(bean);
    560         assertNotNull("Got descriptors", pd);
    561         int count[] = new int[properties.length];
    562         for (int i = 0; i < pd.length; i++) {
    563             String name = pd[i].getName();
    564             for (int j = 0; j < properties.length; j++) {
    565                 if (name.equals(properties[j]))
    566                     count[j]++;
    567             }
    568         }
    569         for (int j = 0; j < properties.length; j++) {
    570             if (count[j] < 0)
    571                 fail("Missing property " + properties[j]);
    572             else if (count[j] > 1)
    573                 fail("Duplicate property " + properties[j]);
    574         }
    575
    576     }
    577
    578
    579     /***
    580      * Corner cases on getPropertyDescriptors invalid arguments.
    581      */
    582     public void testGetDescriptorsArguments() {
    583
    584         try {
    585             PropertyUtils.getPropertyDescriptors(null);
    586             fail("Should throw IllegalArgumentException");
    587         } catch (IllegalArgumentException e) {
    588             // Expected response
    589         } catch (Throwable t) {
    590             fail("Threw " + t + " instead of IllegalArgumentException");
    591         }
    592
    593     }
    594
    595
    596     /***
    597      * Corner cases on getIndexedProperty invalid arguments.
    598      */
    599     public void testGetIndexedArguments() {
    600
    601         // Use explicit index argument
    602
    603         try {
    604             PropertyUtils.getIndexedProperty(null, "intArray", 0);
    605             fail("Should throw IllegalArgumentException 1");
    606         } catch (IllegalArgumentException e) {
    607             // Expected response
    608         } catch (Throwable t) {
    609             fail("Threw " + t + " instead of IllegalArgumentException 1");
    610         }
    611
    612         try {
    613             PropertyUtils.getIndexedProperty(bean, null, 0);
    614             fail("Should throw IllegalArgumentException 2");
    615         } catch (IllegalArgumentException e) {
    616             // Expected response
    617         } catch (Throwable t) {
    618             fail("Threw " + t + " instead of IllegalArgumentException 2");
    619         }
    620
    621         // Use index expression
    622
    623         try {
    624             PropertyUtils.getIndexedProperty(null,
    625                     "intArray[0]");
    626             fail("Should throw IllegalArgumentException 3");
    627         } catch (IllegalArgumentException e) {
    628             // Expected response
    629         } catch (Throwable t) {
    630             fail("Threw " + t + " instead of IllegalArgumentException 3");
    631         }
    632
    633         try {
    634             PropertyUtils.getIndexedProperty(bean, "[0]");
    635             fail("Should throw NoSuchMethodException 4");
    636         } catch (NoSuchMethodException e) {
    637             // Expected response
    638         } catch (Throwable t) {
    639             fail("Threw " + t + " instead of NoSuchMethodException 4");
    640         }
    641
    642         try {
    643             PropertyUtils.getIndexedProperty(bean, "intArray");
    644             fail("Should throw IllegalArgumentException 5");
    645         } catch (IllegalArgumentException e) {
    646             // Expected response
    647         } catch (Throwable t) {
    648             fail("Threw " + t + " instead of IllegalArgumentException 5");
    649         }
    650
    651         // Use explicit index argument
    652
    653         try {
    654             PropertyUtils.getIndexedProperty(null, "intIndexed", 0);
    655             fail("Should throw IllegalArgumentException 1");
    656         } catch (IllegalArgumentException e) {
    657             // Expected response
    658         } catch (Throwable t) {
    659             fail("Threw " + t + " instead of IllegalArgumentException 1");
    660         }
    661
    662         try {
    663             PropertyUtils.getIndexedProperty(bean, null, 0);
    664             fail("Should throw IllegalArgumentException 2");
    665         } catch (IllegalArgumentException e) {
    666             // Expected response
    667         } catch (Throwable t) {
    668             fail("Threw " + t + " instead of IllegalArgumentException 2");
    669         }
    670
    671         // Use index expression
    672
    673         try {
    674             PropertyUtils.getIndexedProperty(null,
    675                     "intIndexed[0]");
    676             fail("Should throw IllegalArgumentException 3");
    677         } catch (IllegalArgumentException e) {
    678             // Expected response
    679         } catch (Throwable t) {
    680             fail("Threw " + t + " instead of IllegalArgumentException 3");
    681         }
    682
    683         try {
    684             PropertyUtils.getIndexedProperty(bean, "[0]");
    685             fail("Should throw NoSuchMethodException 4");
    686         } catch (NoSuchMethodException e) {
    687             // Expected response
    688         } catch (Throwable t) {
    689             fail("Threw " + t + " instead of NoSuchMethodException 4");
    690         }
    691
    692         try {
    693             PropertyUtils.getIndexedProperty(bean, "intIndexed");
    694             fail("Should throw IllegalArgumentException 5");
    695         } catch (IllegalArgumentException e) {
    696             // Expected response
    697         } catch (Throwable t) {
    698             fail("Threw " + t + " instead of IllegalArgumentException 5");
    699         }
    700
    701     }
    702
    703
    704     /***
    705      * Positive and negative tests on getIndexedProperty valid arguments.
    706      */
    707     public void testGetIndexedValues() {
    708
    709         Object value = null;
    710
    711         // Use explicit key argument
    712
    713         for (int i = 0; i < 5; i++) {
    714
    715             try {
    716                 value = PropertyUtils.getIndexedProperty
    717                     (bean, "dupProperty", i);
    718                 assertNotNull("dupProperty returned value " + i, value);
    719                 assertTrue("dupProperty returned String " + i,
    720                         value instanceof String);
    721                 assertEquals("dupProperty returned correct " + i,
    722                              "Dup " + i,
    723                              (String) value);
    724             } catch (Throwable t) {
    725                 fail("dupProperty " + i + " threw " + t);
    726             }
    727
    728             try {
    729                 value =
    730                         PropertyUtils.getIndexedProperty(bean, "intArray", i);
    731                 assertNotNull("intArray returned value " + i, value);
    732                 assertTrue("intArray returned Integer " + i,
    733                         value instanceof Integer);
    734                 assertEquals("intArray returned correct " + i, i * 10,
    735                         ((Integer) value).intValue());
    736             } catch (Throwable t) {
    737                 fail("intArray " + i + " threw " + t);
    738             }
    739
    740             try {
    741                 value =
    742                         PropertyUtils.getIndexedProperty(bean, "intIndexed", i);
    743                 assertNotNull("intIndexed returned value " + i, value);
    744                 assertTrue("intIndexed returned Integer " + i,
    745                         value instanceof Integer);
    746                 assertEquals("intIndexed returned correct " + i, i * 10,
    747                         ((Integer) value).intValue());
    748             } catch (Throwable t) {
    749                 fail("intIndexed " + i + " threw " + t);
    750             }
    751
    752             try {
    753                 value =
    754                         PropertyUtils.getIndexedProperty(bean, "listIndexed", i);
    755                 assertNotNull("listIndexed returned value " + i, value);
    756                 assertTrue("list returned String " + i,
    757                         value instanceof String);
    758                 assertEquals("listIndexed returned correct " + i,
    759                         "String " + i, (String) value);
    760             } catch (Throwable t) {
    761                 fail("listIndexed " + i + " threw " + t);
    762             }
    763
    764             try {
    765                 value =
    766                         PropertyUtils.getIndexedProperty(bean, "stringArray", i);
    767                 assertNotNull("stringArray returned value " + i, value);
    768                 assertTrue("stringArray returned String " + i,
    769                         value instanceof String);
    770                 assertEquals("stringArray returned correct " + i,
    771                         "String " + i, (String) value);
    772             } catch (Throwable t) {
    773                 fail("stringArray " + i + " threw " + t);
    774             }
    775
    776             try {
    777                 value =
    778                         PropertyUtils.getIndexedProperty(bean, "stringIndexed", i);
    779                 assertNotNull("stringIndexed returned value " + i, value);
    780                 assertTrue("stringIndexed returned String " + i,
    781                         value instanceof String);
    782                 assertEquals("stringIndexed returned correct " + i,
    783                         "String " + i, (String) value);
    784             } catch (Throwable t) {
    785                 fail("stringIndexed " + i + " threw " + t);
    786             }
    787
    788         }
    789
    790         // Use key expression
    791
    792         for (int i = 0; i < 5; i++) {
    793
    794             try {
    795                 value = PropertyUtils.getIndexedProperty
    796                     (bean, "dupProperty[" + i + "]");
    797                 assertNotNull("dupProperty returned value " + i, value);
    798                 assertTrue("dupProperty returned String " + i,
    799                         value instanceof String);
    800                 assertEquals("dupProperty returned correct " + i,
    801                              "Dup " + i,
    802                              (String) value);
    803             } catch (Throwable t) {
    804                 fail("dupProperty " + i + " threw " + t);
    805             }
    806
    807             try {
    808                 value =
    809                         PropertyUtils.getIndexedProperty(bean,
    810                                 "intArray[" + i + "]");
    811                 assertNotNull("intArray returned value " + i, value);
    812                 assertTrue("intArray returned Integer " + i,
    813                         value instanceof Integer);
    814                 assertEquals("intArray returned correct " + i, i * 10,
    815                         ((Integer) value).intValue());
    816             } catch (Throwable t) {
    817                 fail("intArray " + i + " threw " + t);
    818             }
    819
    820             try {
    821                 value =
    822                         PropertyUtils.getIndexedProperty(bean,
    823                                 "intIndexed[" + i + "]");
    824                 assertNotNull("intIndexed returned value " + i, value);
    825                 assertTrue("intIndexed returned Integer " + i,
    826                         value instanceof Integer);
    827                 assertEquals("intIndexed returned correct " + i, i * 10,
    828                         ((Integer) value).intValue());
    829             } catch (Throwable t) {
    830                 fail("intIndexed " + i + " threw " + t);
    831             }
    832
    833             try {
    834                 value =
    835                         PropertyUtils.getIndexedProperty(bean,
    836                                 "listIndexed[" + i + "]");
    837                 assertNotNull("listIndexed returned value " + i, value);
    838                 assertTrue("listIndexed returned String " + i,
    839                         value instanceof String);
    840                 assertEquals("listIndexed returned correct " + i,
    841                         "String " + i, (String) value);
    842             } catch (Throwable t) {
    843                 fail("listIndexed " + i + " threw " + t);
    844             }
    845
    846             try {
    847                 value =
    848                         PropertyUtils.getIndexedProperty(bean,
    849                                 "stringArray[" + i + "]");
    850                 assertNotNull("stringArray returned value " + i, value);
    851                 assertTrue("stringArray returned String " + i,
    852                         value instanceof String);
    853                 assertEquals("stringArray returned correct " + i,
    854                         "String " + i, (String) value);
    855             } catch (Throwable t) {
    856                 fail("stringArray " + i + " threw " + t);
    857             }
    858
    859             try {
    860                 value =
    861                         PropertyUtils.getIndexedProperty(bean,
    862                                 "stringIndexed[" + i + "]");
    863                 assertNotNull("stringIndexed returned value " + i, value);
    864                 assertTrue("stringIndexed returned String " + i,
    865                         value instanceof String);
    866                 assertEquals("stringIndexed returned correct " + i,
    867                         "String " + i, (String) value);
    868             } catch (Throwable t) {
    869                 fail("stringIndexed " + i + " threw " + t);
    870             }
    871
    872         }
    873
    874         // Index out of bounds tests
    875
    876         try {
    877             value =
    878                     PropertyUtils.getIndexedProperty(bean,
    879                             "dupProperty", -1);
    880             fail("Should have thrown ArrayIndexOutOfBoundsException");
    881         } catch (ArrayIndexOutOfBoundsException t) {
    882             // Expected results
    883         } catch (Throwable t) {
    884             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    885         }
    886
    887         try {
    888             value =
    889                     PropertyUtils.getIndexedProperty(bean,
    890                             "dupProperty", 5);
    891             fail("Should have thrown ArrayIndexOutOfBoundsException");
    892         } catch (ArrayIndexOutOfBoundsException t) {
    893             // Expected results
    894         } catch (Throwable t) {
    895             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    896         }
    897
    898         try {
    899             value =
    900                     PropertyUtils.getIndexedProperty(bean,
    901                             "intArray", -1);
    902             fail("Should have thrown ArrayIndexOutOfBoundsException");
    903         } catch (ArrayIndexOutOfBoundsException t) {
    904             // Expected results
    905         } catch (Throwable t) {
    906             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    907         }
    908
    909         try {
    910             value =
    911                     PropertyUtils.getIndexedProperty(bean,
    912                             "intArray", 5);
    913             fail("Should have thrown ArrayIndexOutOfBoundsException");
    914         } catch (ArrayIndexOutOfBoundsException t) {
    915             // Expected results
    916         } catch (Throwable t) {
    917             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    918         }
    919
    920         try {
    921             value =
    922                     PropertyUtils.getIndexedProperty(bean,
    923                             "intIndexed", -1);
    924             fail("Should have thrown ArrayIndexOutOfBoundsException");
    925         } catch (ArrayIndexOutOfBoundsException t) {
    926             // Expected results
    927         } catch (Throwable t) {
    928             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    929         }
    930
    931         try {
    932             value =
    933                     PropertyUtils.getIndexedProperty(bean,
    934                             "intIndexed", 5);
    935             fail("Should have thrown ArrayIndexOutOfBoundsException");
    936         } catch (ArrayIndexOutOfBoundsException t) {
    937             // Expected results
    938         } catch (Throwable t) {
    939             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    940         }
    941
    942         try {
    943             value =
    944                     PropertyUtils.getIndexedProperty(bean,
    945                             "listIndexed", -1);
    946             fail("Should have thrown IndexOutOfBoundsException");
    947         } catch (IndexOutOfBoundsException t) {
    948             // Expected results
    949         } catch (Throwable t) {
    950             fail("Threw " + t + " instead of IndexOutOfBoundsException");
    951         }
    952
    953         try {
    954             value =
    955                     PropertyUtils.getIndexedProperty(bean,
    956                             "listIndexed", 5);
    957             fail("Should have thrown IndexOutOfBoundsException");
    958         } catch (IndexOutOfBoundsException t) {
    959             // Expected results
    960         } catch (Throwable t) {
    961             fail("Threw " + t + " instead of IndexOutOfBoundsException");
    962         }
    963
    964         try {
    965             value =
    966                     PropertyUtils.getIndexedProperty(bean,
    967                             "stringArray", -1);
    968             fail("Should have thrown ArrayIndexOutOfBoundsException");
    969         } catch (ArrayIndexOutOfBoundsException t) {
    970             // Expected results
    971         } catch (Throwable t) {
    972             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    973         }
    974
    975         try {
    976             value =
    977                     PropertyUtils.getIndexedProperty(bean,
    978                             "stringArray", 5);
    979             fail("Should have thrown ArrayIndexOutOfBoundsException");
    980         } catch (ArrayIndexOutOfBoundsException t) {
    981             // Expected results
    982         } catch (Throwable t) {
    983             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    984         }
    985
    986         try {
    987             value =
    988                     PropertyUtils.getIndexedProperty(bean,
    989                             "stringIndexed", -1);
    990             fail("Should have thrown ArrayIndexOutOfBoundsException");
    991         } catch (ArrayIndexOutOfBoundsException t) {
    992             // Expected results
    993         } catch (Throwable t) {
    994             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    995         }
    996
    997         try {
    998             value =
    999                     PropertyUtils.getIndexedProperty(bean,
    1000                             "stringIndexed", 5);
    1001             fail("Should have thrown ArrayIndexOutOfBoundsException");
    1002         } catch (ArrayIndexOutOfBoundsException t) {
    1003             // Expected results
    1004         } catch (Throwable t) {
    1005             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    1006         }
    1007
    1008     }
    1009
    1010
    1011     /***
    1012      * Test getting an indexed value out of a multi-dimensional array
    1013      */
    1014     public void testGetIndexedArray() {
    1015         String[] firstArray = new String[] {"FIRST-1", "FIRST-2", "FIRST-3"};
    1016         String[] secondArray = new String[] {"SECOND-1", "SECOND-2", "SECOND-3",  "SECOND-4"};
    1017         String[][] mainArray = {firstArray, secondArray};
    1018         TestBean bean = new TestBean(mainArray);
    1019         try {
    1020             assertEquals("firstArray[0]", firstArray[0],  PropertyUtils.getProperty(bean, "string2dArray[0][0]"));
    1021             assertEquals("firstArray[1]", firstArray[1],  PropertyUtils.getProperty(bean, "string2dArray[0][1]"));
    1022             assertEquals("firstArray[2]", firstArray[2],  PropertyUtils.getProperty(bean, "string2dArray[0][2]"));
    1023             assertEquals("secondArray[0]", secondArray[0], PropertyUtils.getProperty(bean, "string2dArray[1][0]"));
    1024             assertEquals("secondArray[1]", secondArray[1], PropertyUtils.getProperty(bean, "string2dArray[1][1]"));
    1025             assertEquals("secondArray[2]", secondArray[2], PropertyUtils.getProperty(bean, "string2dArray[1][2]"));
    1026             assertEquals("secondArray[3]", secondArray[3], PropertyUtils.getProperty(bean, "string2dArray[1][3]"));
    1027         } catch (Throwable t) {
    1028             fail("Threw " + t + "");
    1029         }
    1030     }
    1031
    1032     /***
    1033      * Test getting an indexed value out of List of Lists
    1034      */
    1035     public void testGetIndexedList() {
    1036         String[] firstArray = new String[] {"FIRST-1", "FIRST-2", "FIRST-3"};
    1037         String[] secondArray = new String[] {"SECOND-1", "SECOND-2", "SECOND-3",  "SECOND-4"};
    1038         List mainList   = new ArrayList();
    1039         mainList.add(Arrays.asList(firstArray));
    1040         mainList.add(Arrays.asList(secondArray));
    1041         TestBean bean = new TestBean(mainList);
    1042         try {
    1043             assertEquals("firstArray[0]", firstArray[0],  PropertyUtils.getProperty(bean, "listIndexed[0][0]"));
    1044             assertEquals("firstArray[1]", firstArray[1],  PropertyUtils.getProperty(bean, "listIndexed[0][1]"));
    1045             assertEquals("firstArray[2]", firstArray[2],  PropertyUtils.getProperty(bean, "listIndexed[0][2]"));
    1046             assertEquals("secondArray[0]", secondArray[0], PropertyUtils.getProperty(bean, "listIndexed[1][0]"));
    1047             assertEquals("secondArray[1]", secondArray[1], PropertyUtils.getProperty(bean, "listIndexed[1][1]"));
    1048             assertEquals("secondArray[2]", secondArray[2], PropertyUtils.getProperty(bean, "listIndexed[1][2]"));
    1049             assertEquals("secondArray[3]", secondArray[3], PropertyUtils.getProperty(bean, "listIndexed[1][3]"));
    1050         } catch (Throwable t) {
    1051             fail("Threw " + t + "");
    1052         }
    1053     }
    1054
    1055     /***
    1056      * Test getting a value out of a mapped Map
    1057      */
    1058     public void testGetIndexedMap() {
    1059         Map firstMap  = new HashMap();
    1060         firstMap.put("FIRST-KEY-1", "FIRST-VALUE-1");
    1061         firstMap.put("FIRST-KEY-2", "FIRST-VALUE-2");
    1062         Map secondMap  = new HashMap();
    1063         secondMap.put("SECOND-KEY-1", "SECOND-VALUE-1");
    1064         secondMap.put("SECOND-KEY-2", "SECOND-VALUE-2");
    1065
    1066         List mainList   = new ArrayList();
    1067         mainList.add(firstMap);
    1068         mainList.add(secondMap);
    1069         TestBean bean = new TestBean(mainList);
    1070         try {
    1071             assertEquals("listIndexed[0](FIRST-KEY-1)",  "FIRST-VALUE-1",   PropertyUtils.getProperty(bean, "listIndexed[0](FIRST-KEY-1)"));
    1072             assertEquals("listIndexed[0](FIRST-KEY-2)",  "FIRST-VALUE-2",   PropertyUtils.getProperty(bean, "listIndexed[0](FIRST-KEY-2)"));
    1073             assertEquals("listIndexed[1](SECOND-KEY-1)", "SECOND-VALUE-1",  PropertyUtils.getProperty(bean, "listIndexed[1](SECOND-KEY-1)"));
    1074             assertEquals("listIndexed[1](SECOND-KEY-2)", "SECOND-VALUE-2",  PropertyUtils.getProperty(bean, "listIndexed[1](SECOND-KEY-2)"));
    1075         } catch (Throwable t) {
    1076             fail("Threw " + t + "");
    1077         }
    1078     }
    1079
    1080     /***
    1081      * Corner cases on getMappedProperty invalid arguments.
    1082      */
    1083     public void testGetMappedArguments() {
    1084
    1085         // Use explicit key argument
    1086
    1087         try {
    1088             PropertyUtils.getMappedProperty(null, "mappedProperty",
    1089                     "First Key");
    1090             fail("Should throw IllegalArgumentException 1");
    1091         } catch (IllegalArgumentException e) {
    1092             // Expected response
    1093         } catch (Throwable t) {
    1094             fail("Threw " + t + " instead of IllegalArgumentException 1");
    1095         }
    1096
    1097         try {
    1098             PropertyUtils.getMappedProperty(bean, null, "First Key");
    1099             fail("Should throw IllegalArgumentException 2");
    1100         } catch (IllegalArgumentException e) {
    1101             // Expected response
    1102         } catch (Throwable t) {
    1103             fail("Threw " + t + " instead of IllegalArgumentException 2");
    1104         }
    1105
    1106         try {
    1107             PropertyUtils.getMappedProperty(bean, "mappedProperty", null);
    1108             fail("Should throw IllegalArgumentException 3");
    1109         } catch (IllegalArgumentException e) {
    1110             // Expected response
    1111         } catch (Throwable t) {
    1112             fail("Threw " + t + " instead of IllegalArgumentException 3");
    1113         }
    1114
    1115         // Use key expression
    1116
    1117         try {
    1118             PropertyUtils.getMappedProperty(null,
    1119                     "mappedProperty(First Key)");
    1120             fail("Should throw IllegalArgumentException 4");
    1121         } catch (IllegalArgumentException e) {
    1122             // Expected response
    1123         } catch (Throwable t) {
    1124             fail("Threw " + t + " instead of IllegalArgumentException 4");
    1125         }
    1126
    1127         try {
    1128             PropertyUtils.getMappedProperty(bean, "(Second Key)");
    1129             fail("Should throw IllegalArgumentException 5");
    1130         } catch (NoSuchMethodException e) {
    1131             // Expected response
    1132         } catch (Throwable t) {
    1133             fail("Threw " + t + " instead of NoSuchMethodException 5");
    1134         }
    1135
    1136         try {
    1137             PropertyUtils.getMappedProperty(bean, "mappedProperty");
    1138             fail("Should throw IllegalArgumentException 6");
    1139         } catch (IllegalArgumentException e) {
    1140             // Expected response
    1141         } catch (Throwable t) {
    1142             fail("Threw " + t + " instead of IllegalArgumentException 6");
    1143         }
    1144
    1145     }
    1146
    1147     /***
    1148      * Test getting an indexed value out of a mapped array
    1149      */
    1150     public void testGetMappedArray() {
    1151         TestBean bean = new TestBean();
    1152         String[] array = new String[] {"abc", "def", "ghi"};
    1153         bean.getMapProperty().put("mappedArray", array);
    1154         try {
    1155             assertEquals("abc", PropertyUtils.getProperty(bean, "mapProperty(mappedArray)[0]"));
    1156             assertEquals("def", PropertyUtils.getProperty(bean, "mapProperty(mappedArray)[1]"));
    1157             assertEquals("ghi", PropertyUtils.getProperty(bean, "mapProperty(mappedArray)[2]"));
    1158         } catch (Throwable t) {
    1159             fail("Threw " + t + "");
    1160         }
    1161     }
    1162
    1163     /***
    1164      * Test getting an indexed value out of a mapped List
    1165      */
    1166     public void testGetMappedList() {
    1167         TestBean bean = new TestBean();
    1168         List list = new ArrayList();
    1169         list.add("klm");
    1170         list.add("nop");
    1171         list.add("qrs");
    1172         bean.getMapProperty().put("mappedList", list);
    1173         try {
    1174             assertEquals("klm", PropertyUtils.getProperty(bean, "mapProperty(mappedList)[0]"));
    1175             assertEquals("nop", PropertyUtils.getProperty(bean, "mapProperty(mappedList)[1]"));
    1176             assertEquals("qrs", PropertyUtils.getProperty(bean, "mapProperty(mappedList)[2]"));
    1177         } catch (Throwable t) {
    1178             fail("Threw " + t + "");
    1179         }
    1180     }
    1181
    1182     /***
    1183      * Test getting a value out of a mapped Map
    1184      */
    1185     public void testGetMappedMap() {
    1186         TestBean bean = new TestBean();
    1187         Map map = new HashMap();
    1188         map.put("sub-key-1", "sub-value-1");
    1189         map.put("sub-key-2", "sub-value-2");
    1190         map.put("sub-key-3", "sub-value-3");
    1191         bean.getMapProperty().put("mappedMap", map);
    1192         try {
    1193             assertEquals("sub-value-1", PropertyUtils.getProperty(bean, "mapProperty(mappedMap)(sub-key-1)"));
    1194             assertEquals("sub-value-2", PropertyUtils.getProperty(bean, "mapProperty(mappedMap)(sub-key-2)"));
    1195             assertEquals("sub-value-3", PropertyUtils.getProperty(bean, "mapProperty(mappedMap)(sub-key-3)"));
    1196         } catch (Throwable t) {
    1197             fail("Threw " + t + "");
    1198         }
    1199     }
    1200
    1201     /***
    1202      * Test getting mapped values with periods in the key.
    1203      */
    1204     public void testGetMappedPeriods() {
    1205
    1206         bean.setMappedProperty("key.with.a.dot", "Special Value");
    1207         assertEquals("Can retrieve directly",
    1208                      "Special Value",
    1209                      bean.getMappedProperty("key.with.a.dot"));
    1210         try {
    1211             assertEquals("Can retrieve via getMappedProperty",
    1212                          "Special Value",
    1213                          PropertyUtils.getMappedProperty
    1214                          (bean, "mappedProperty", "key.with.a.dot"));
    1215         } catch (Exception e) {
    1216             fail("Thew exception: " + e);
    1217         }
    1218         try {
    1219             assertEquals("Can retrieve via getNestedProperty",
    1220                          "Special Value",
    1221                          PropertyUtils.getNestedProperty
    1222                          (bean, "mappedProperty(key.with.a.dot)"));
    1223         } catch (Exception e) {
    1224             fail("Thew exception: " + e);
    1225         }
    1226
    1227         bean.setMappedObjects("nested.property", new TestBean());
    1228         assertNotNull("Can retrieve directly",
    1229                       bean.getMappedObjects("nested.property"));
    1230         try {
    1231             assertEquals("Can retrieve nested",
    1232                          "This is a string",
    1233                          PropertyUtils.getNestedProperty
    1234                          (bean,
    1235                           "mappedObjects(nested.property).stringProperty"));
    1236         } catch (Exception e) {
    1237             fail("Thew exception: " + e);
    1238         }
    1239
    1240         try
    1241         {
    1242             assertEquals("Can't retrieved nested with mapped property",
    1243                          "Mapped Value",
    1244                          PropertyUtils.getNestedProperty(
    1245                              bean,"mappedNested.value(Mapped Key)"));
    1246         } catch (Exception e)
    1247         {
    1248             fail("Thew exception: " + e);
    1249         }
    1250     }
    1251
    1252
    1253     /***
    1254      * Test getting mapped values with slashes in the key.  This is different
    1255      * from periods because slashes are not syntactically significant.
    1256      */
    1257     public void testGetMappedSlashes() {
    1258
    1259         bean.setMappedProperty("key/with/a/slash", "Special Value");
    1260         assertEquals("Can retrieve directly",
    1261                      "Special Value",
    1262                      bean.getMappedProperty("key/with/a/slash"));
    1263         try {
    1264             assertEquals("Can retrieve via getMappedProperty",
    1265                          "Special Value",
    1266                          PropertyUtils.getMappedProperty
    1267                          (bean, "mappedProperty", "key/with/a/slash"));
    1268         } catch (Exception e) {
    1269             fail("Thew exception: " + e);
    1270         }
    1271         try {
    1272             assertEquals("Can retrieve via getNestedProperty",
    1273                          "Special Value",
    1274                          PropertyUtils.getNestedProperty
    1275                          (bean, "mappedProperty(key/with/a/slash)"));
    1276         } catch (Exception e) {
    1277             fail("Thew exception: " + e);
    1278         }
    1279
    1280         bean.setMappedObjects("nested/property", new TestBean());
    1281         assertNotNull("Can retrieve directly",
    1282                       bean.getMappedObjects("nested/property"));
    1283         try {
    1284             assertEquals("Can retrieve nested",
    1285                          "This is a string",
    1286                          PropertyUtils.getNestedProperty
    1287                          (bean,
    1288                           "mappedObjects(nested/property).stringProperty"));
    1289         } catch (Exception e) {
    1290             fail("Thew exception: " + e);
    1291         }
    1292
    1293     }
    1294
    1295
    1296     /***
    1297      * Positive and negative tests on getMappedProperty valid arguments.
    1298      */
    1299     public void testGetMappedValues() {
    1300
    1301         Object value = null;
    1302
    1303         // Use explicit key argument
    1304
    1305         try {
    1306             value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
    1307                     "First Key");
    1308             assertEquals("Can find first value", "First Value", value);
    1309         } catch (Throwable t) {
    1310             fail("Finding first value threw " + t);
    1311         }
    1312
    1313         try {
    1314             value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
    1315                     "Second Key");
    1316             assertEquals("Can find second value", "Second Value", value);
    1317         } catch (Throwable t) {
    1318             fail("Finding second value threw " + t);
    1319         }
    1320
    1321         try {
    1322             value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
    1323                     "Third Key");
    1324             assertNull("Can not find third value", value);
    1325         } catch (Throwable t) {
    1326             fail("Finding third value threw " + t);
    1327         }
    1328
    1329         // Use key expression with parentheses
    1330
    1331         try {
    1332             value =
    1333                     PropertyUtils.getMappedProperty(bean,
    1334                             "mappedProperty(First Key)");
    1335             assertEquals("Can find first value", "First Value", value);
    1336         } catch (Throwable t) {
    1337             fail("Finding first value threw " + t);
    1338         }
    1339
    1340         try {
    1341             value =
    1342                     PropertyUtils.getMappedProperty(bean,
    1343                             "mappedProperty(Second Key)");
    1344             assertEquals("Can find second value", "Second Value", value);
    1345         } catch (Throwable t) {
    1346             fail("Finding second value threw " + t);
    1347         }
    1348
    1349         try {
    1350             value =
    1351                     PropertyUtils.getMappedProperty(bean,
    1352                             "mappedProperty(Third Key)");
    1353             assertNull("Can not find third value", value);
    1354         } catch (Throwable t) {
    1355             fail("Finding third value threw " + t);
    1356         }
    1357
    1358         // Use key expression with dotted syntax
    1359
    1360         try {
    1361             value =
    1362                     PropertyUtils.getNestedProperty(bean,
    1363                             "mapProperty.First Key");
    1364             assertEquals("Can find first value", "First Value", value);
    1365         } catch (Throwable t) {
    1366             fail("Finding first value threw " + t);
    1367         }
    1368
    1369         try {
    1370             value =
    1371                     PropertyUtils.getNestedProperty(bean,
    1372                             "mapProperty.Second Key");
    1373             assertEquals("Can find second value", "Second Value", value);
    1374         } catch (Throwable t) {
    1375             fail("Finding second value threw " + t);
    1376         }
    1377
    1378         try {
    1379             value =
    1380                     PropertyUtils.getNestedProperty(bean,
    1381                             "mapProperty.Third Key");
    1382             assertNull("Can not find third value", value);
    1383         } catch (Throwable t) {
    1384             fail("Finding third value threw " + t);
    1385         }
    1386
    1387     }
    1388
    1389
    1390     /***
    1391      * Corner cases on getNestedProperty invalid arguments.
    1392      */
    1393     public void testGetNestedArguments() {
    1394
    1395         try {
    1396             PropertyUtils.getNestedProperty(null, "stringProperty");
    1397             fail("Should throw IllegalArgumentException 1");
    1398         } catch (IllegalArgumentException e) {
    1399             // Expected response
    1400         } catch (Throwable t) {
    1401             fail("Threw " + t + " instead of IllegalArgumentException 1");
    1402         }
    1403
    1404         try {
    1405             PropertyUtils.getNestedProperty(bean, null);
    1406             fail("Should throw IllegalArgumentException 2");
    1407         } catch (IllegalArgumentException e) {
    1408             // Expected response
    1409         } catch (Throwable t) {
    1410             fail("Threw " + t + " instead of IllegalArgumentException 2");
    1411         }
    1412
    1413     }
    1414
    1415
    1416     /***
    1417      * Test getNestedProperty on a boolean property.
    1418      */
    1419     public void testGetNestedBoolean() {
    1420
    1421         try {
    1422             Object value =
    1423                     PropertyUtils.getNestedProperty
    1424                     (bean, "nested.booleanProperty");
    1425             assertNotNull("Got a value", value);
    1426             assertTrue("Got correct type", (value instanceof Boolean));
    1427             assertTrue("Got correct value",
    1428                     ((Boolean) value).booleanValue() ==
    1429                     bean.getNested().getBooleanProperty());
    1430         } catch (IllegalAccessException e) {
    1431             fail("IllegalAccessException");
    1432         } catch (IllegalArgumentException e) {
    1433             fail("IllegalArgumentException");
    1434         } catch (InvocationTargetException e) {
    1435             fail("InvocationTargetException");
    1436         } catch (NoSuchMethodException e) {
    1437             fail("NoSuchMethodException");
    1438         }
    1439
    1440     }
    1441
    1442
    1443     /***
    1444      * Test getNestedProperty on a double property.
    1445      */
    1446     public void testGetNestedDouble() {
    1447
    1448         try {
    1449             Object value =
    1450                     PropertyUtils.getNestedProperty
    1451                     (bean, "nested.doubleProperty");
    1452             assertNotNull("Got a value", value);
    1453             assertTrue("Got correct type", (value instanceof Double));
    1454             assertEquals("Got correct value",
    1455                     ((Double) value).doubleValue(),
    1456                     bean.getNested().getDoubleProperty(),
    1457                     0.005);
    1458         } catch (IllegalAccessException e) {
    1459             fail("IllegalAccessException");
    1460         } catch (IllegalArgumentException e) {
    1461             fail("IllegalArgumentException");
    1462         } catch (InvocationTargetException e) {
    1463             fail("InvocationTargetException");
    1464         } catch (NoSuchMethodException e) {
    1465             fail("NoSuchMethodException");
    1466         }
    1467
    1468     }
    1469
    1470
    1471     /***
    1472      * Test getNestedProperty on a float property.
    1473      */
    1474     public void testGetNestedFloat() {
    1475
    1476         try {
    1477             Object value =
    1478                     PropertyUtils.getNestedProperty
    1479                     (bean, "nested.floatProperty");
    1480             assertNotNull("Got a value", value);
    1481             assertTrue("Got correct type", (value instanceof Float));
    1482             assertEquals("Got correct value",
    1483                     ((Float) value).floatValue(),
    1484                     bean.getNested().getFloatProperty(),
    1485                     (float) 0.005);
    1486         } catch (IllegalAccessException e) {
    1487             fail("IllegalAccessException");
    1488         } catch (IllegalArgumentException e) {
    1489             fail("IllegalArgumentException");
    1490         } catch (InvocationTargetException e) {
    1491             fail("InvocationTargetException");
    1492         } catch (NoSuchMethodException e) {
    1493             fail("NoSuchMethodException");
    1494         }
    1495
    1496     }
    1497
    1498
    1499     /***
    1500      * Test getNestedProperty on an int property.
    1501      */
    1502     public void testGetNestedInt() {
    1503
    1504         try {
    1505             Object value =
    1506                     PropertyUtils.getNestedProperty
    1507                     (bean, "nested.intProperty");
    1508             assertNotNull("Got a value", value);
    1509             assertTrue("Got correct type", (value instanceof Integer));
    1510             assertEquals("Got correct value",
    1511                     ((Integer) value).intValue(),
    1512                     bean.getNested().getIntProperty());
    1513         } catch (IllegalAccessException e) {
    1514             fail("IllegalAccessException");
    1515         } catch (IllegalArgumentException e) {
    1516             fail("IllegalArgumentException");
    1517         } catch (InvocationTargetException e) {
    1518             fail("InvocationTargetException");
    1519         } catch (NoSuchMethodException e) {
    1520             fail("NoSuchMethodException");
    1521         }
    1522
    1523     }
    1524
    1525
    1526     /***
    1527      * Test getNestedProperty on a long property.
    1528      */
    1529     public void testGetNestedLong() {
    1530
    1531         try {
    1532             Object value =
    1533                     PropertyUtils.getNestedProperty
    1534                     (bean, "nested.longProperty");
    1535             assertNotNull("Got a value", value);
    1536             assertTrue("Got correct type", (value instanceof Long));
    1537             assertEquals("Got correct value",
    1538                     ((Long) value).longValue(),
    1539                     bean.getNested().getLongProperty());
    1540         } catch (IllegalAccessException e) {
    1541             fail("IllegalAccessException");
    1542         } catch (IllegalArgumentException e) {
    1543             fail("IllegalArgumentException");
    1544         } catch (InvocationTargetException e) {
    1545             fail("InvocationTargetException");
    1546         } catch (NoSuchMethodException e) {
    1547             fail("NoSuchMethodException");
    1548         }
    1549
    1550     }
    1551
    1552
    1553     /***
    1554      * Test getNestedProperty on a read-only String property.
    1555      */
    1556     public void testGetNestedReadOnly() {
    1557
    1558         try {
    1559             Object value =
    1560                     PropertyUtils.getNestedProperty
    1561                     (bean, "nested.readOnlyProperty");
    1562             assertNotNull("Got a value", value);
    1563             assertTrue("Got correct type", (value instanceof String));
    1564             assertEquals("Got correct value",
    1565                     (String) value,
    1566                     bean.getReadOnlyProperty());
    1567         } catch (IllegalAccessException e) {
    1568             fail("IllegalAccessException");
    1569         } catch (IllegalArgumentException e) {
    1570             fail("IllegalArgumentException");
    1571         } catch (InvocationTargetException e) {
    1572             fail("InvocationTargetException");
    1573         } catch (NoSuchMethodException e) {
    1574             fail("NoSuchMethodException");
    1575         }
    1576
    1577     }
    1578
    1579
    1580     /***
    1581      * Test getNestedProperty on a short property.
    1582      */
    1583     public void testGetNestedShort() {
    1584
    1585         try {
    1586             Object value =
    1587                     PropertyUtils.getNestedProperty
    1588                     (bean, "nested.shortProperty");
    1589             assertNotNull("Got a value", value);
    1590             assertTrue("Got correct type", (value instanceof Short));
    1591             assertEquals("Got correct value",
    1592                     ((Short) value).shortValue(),
    1593                     bean.getNested().getShortProperty());
    1594         } catch (IllegalAccessException e) {
    1595             fail("IllegalAccessException");
    1596         } catch (IllegalArgumentException e) {
    1597             fail("IllegalArgumentException");
    1598         } catch (InvocationTargetException e) {
    1599             fail("InvocationTargetException");
    1600         } catch (NoSuchMethodException e) {
    1601             fail("NoSuchMethodException");
    1602         }
    1603
    1604     }
    1605
    1606
    1607     /***
    1608      * Test getNestedProperty on a String property.
    1609      */
    1610     public void testGetNestedString() {
    1611
    1612         try {
    1613             Object value =
    1614                     PropertyUtils.getNestedProperty
    1615                     (bean, "nested.stringProperty");
    1616             assertNotNull("Got a value", value);
    1617             assertTrue("Got correct type", (value instanceof String));
    1618             assertEquals("Got correct value",
    1619                     ((String) value),
    1620                     bean.getNested().getStringProperty());
    1621         } catch (IllegalAccessException e) {
    1622             fail("IllegalAccessException");
    1623         } catch (IllegalArgumentException e) {
    1624             fail("IllegalArgumentException");
    1625         } catch (InvocationTargetException e) {
    1626             fail("InvocationTargetException");
    1627         } catch (NoSuchMethodException e) {
    1628             fail("NoSuchMethodException");
    1629         }
    1630
    1631     }
    1632
    1633
    1634     /***
    1635      * Negative test getNestedProperty on an unknown property.
    1636      */
    1637     public void testGetNestedUnknown() {
    1638
    1639         try {
    1640             PropertyUtils.getNestedProperty(bean, "nested.unknown");
    1641             fail("Should have thrown NoSuchMethodException");
    1642         } catch (IllegalAccessException e) {
    1643             fail("IllegalAccessException");
    1644         } catch (IllegalArgumentException e) {
    1645             fail("IllegalArgumentException");
    1646         } catch (InvocationTargetException e) {
    1647             fail("InvocationTargetException");
    1648         } catch (NoSuchMethodException e) {
    1649             // Correct result for this test
    1650         }
    1651
    1652     }
    1653
    1654     /***
    1655      * When a bean has a null property which is reference by the standard access language,
    1656      * this should throw a NestedNullException.
    1657      */
    1658     public void testThrowNestedNull() throws Exception {
    1659         NestedTestBean nestedBean = new NestedTestBean("base");
    1660         // don't init!
    1661
    1662         try {
    1663             NestedTestBean value = (NestedTestBean) PropertyUtils.getProperty(
    1664                                 nestedBean,
    1665                                 "simpleBeanProperty.indexedProperty[0]");
    1666             fail("NestedNullException not thrown");
    1667         } catch (NestedNullException e) {
    1668             // that's what we wanted!
    1669         }
    1670     }
    1671
    1672     /***
    1673      * Test getNestedProperty on a write-only String property.
    1674      */
    1675     public void testGetNestedWriteOnly() {
    1676
    1677         try {
    1678             PropertyUtils.getNestedProperty(bean, "writeOnlyProperty");
    1679             fail("Should have thrown NoSuchMethodException");
    1680         } catch (IllegalAccessException e) {
    1681             fail("IllegalAccessException");
    1682         } catch (IllegalArgumentException e) {
    1683             fail("IllegalArgumentException");
    1684         } catch (InvocationTargetException e) {
    1685             fail("InvocationTargetException");
    1686         } catch (NoSuchMethodException e) {
    1687             // Correct result for this test
    1688         }
    1689
    1690     }
    1691
    1692
    1693     /***
    1694      * Test getPropertyType() on all kinds of properties.
    1695      */
    1696     public void testGetPropertyType() {
    1697
    1698         Class clazz = null;
    1699         int intArray[] = new int[0];
    1700         String stringArray[] = new String[0];
    1701
    1702         try {
    1703
    1704             // Scalar and Indexed Properties
    1705             clazz = PropertyUtils.getPropertyType(bean, "booleanProperty");
    1706             assertEquals("booleanProperty type", Boolean.TYPE, clazz);
    1707             clazz = PropertyUtils.getPropertyType(bean, "booleanSecond");
    1708             assertEquals("booleanSecond type", Boolean.TYPE, clazz);
    1709             clazz = PropertyUtils.getPropertyType(bean, "doubleProperty");
    1710             assertEquals("doubleProperty type", Double.TYPE, clazz);
    1711             clazz = PropertyUtils.getPropertyType(bean, "dupProperty");
    1712             assertEquals("dupProperty type", String.class, clazz);
    1713             clazz = PropertyUtils.getPropertyType(bean, "floatProperty");
    1714             assertEquals("floatProperty type", Float.TYPE, clazz);
    1715             clazz = PropertyUtils.getPropertyType(bean, "intArray");
    1716             assertEquals("intArray type", intArray.getClass(), clazz);
    1717             clazz = PropertyUtils.getPropertyType(bean, "intIndexed");
    1718             assertEquals("intIndexed type", Integer.TYPE, clazz);
    1719             clazz = PropertyUtils.getPropertyType(bean, "intProperty");
    1720             assertEquals("intProperty type", Integer.TYPE, clazz);
    1721             clazz = PropertyUtils.getPropertyType(bean, "listIndexed");
    1722             assertEquals("listIndexed type", List.class, clazz);
    1723             clazz = PropertyUtils.getPropertyType(bean, "longProperty");
    1724             assertEquals("longProperty type", Long.TYPE, clazz);
    1725             clazz = PropertyUtils.getPropertyType(bean, "mappedProperty");
    1726             assertEquals("mappedProperty type", String.class, clazz);
    1727             clazz = PropertyUtils.getPropertyType(bean, "mappedIntProperty");
    1728             assertEquals("mappedIntProperty type", Integer.TYPE, clazz);
    1729             clazz = PropertyUtils.getPropertyType(bean, "readOnlyProperty");
    1730             assertEquals("readOnlyProperty type", String.class, clazz);
    1731             clazz = PropertyUtils.getPropertyType(bean, "shortProperty");
    1732             assertEquals("shortProperty type", Short.TYPE, clazz);
    1733             clazz = PropertyUtils.getPropertyType(bean, "stringArray");
    1734             assertEquals("stringArray type", stringArray.getClass(), clazz);
    1735             clazz = PropertyUtils.getPropertyType(bean, "stringIndexed");
    1736             assertEquals("stringIndexed type", String.class, clazz);
    1737             clazz = PropertyUtils.getPropertyType(bean, "stringProperty");
    1738             assertEquals("stringProperty type", String.class, clazz);
    1739             clazz = PropertyUtils.getPropertyType(bean, "writeOnlyProperty");
    1740             assertEquals("writeOnlyProperty type", String.class, clazz);
    1741
    1742             // Nested Properties
    1743             clazz = PropertyUtils.getPropertyType(bean, "nested.booleanProperty");
    1744             assertEquals("booleanProperty type", Boolean.TYPE, clazz);
    1745             clazz = PropertyUtils.getPropertyType(bean, "nested.booleanSecond");
    1746             assertEquals("booleanSecond type", Boolean.TYPE, clazz);
    1747             clazz = PropertyUtils.getPropertyType(bean, "nested.doubleProperty");
    1748             assertEquals("doubleProperty type", Double.TYPE, clazz);
    1749             clazz = PropertyUtils.getPropertyType(bean, "nested.dupProperty");
    1750             assertEquals("dupProperty type", String.class, clazz);
    1751             clazz = PropertyUtils.getPropertyType(bean, "nested.floatProperty");
    1752             assertEquals("floatProperty type", Float.TYPE, clazz);
    1753             clazz = PropertyUtils.getPropertyType(bean, "nested.intArray");
    1754             assertEquals("intArray type", intArray.getClass(), clazz);
    1755             clazz = PropertyUtils.getPropertyType(bean, "nested.intIndexed");
    1756             assertEquals("intIndexed type", Integer.TYPE, clazz);
    1757             clazz = PropertyUtils.getPropertyType(bean, "nested.intProperty");
    1758             assertEquals("intProperty type", Integer.TYPE, clazz);
    1759             clazz = PropertyUtils.getPropertyType(bean, "nested.listIndexed");
    1760             assertEquals("listIndexed type", List.class, clazz);
    1761             clazz = PropertyUtils.getPropertyType(bean, "nested.longProperty");
    1762             assertEquals("longProperty type", Long.TYPE, clazz);
    1763             clazz = PropertyUtils.getPropertyType(bean, "nested.mappedProperty");
    1764             assertEquals("mappedProperty type", String.class, clazz);
    1765             clazz = PropertyUtils.getPropertyType(bean, "nested.mappedIntProperty");
    1766             assertEquals("mappedIntProperty type", Integer.TYPE, clazz);
    1767             clazz = PropertyUtils.getPropertyType(bean, "nested.readOnlyProperty");
    1768             assertEquals("readOnlyProperty type", String.class, clazz);
    1769             clazz = PropertyUtils.getPropertyType(bean, "nested.shortProperty");
    1770             assertEquals("shortProperty type", Short.TYPE, clazz);
    1771             clazz = PropertyUtils.getPropertyType(bean, "nested.stringArray");
    1772             assertEquals("stringArray type", stringArray.getClass(), clazz);
    1773             clazz = PropertyUtils.getPropertyType(bean, "nested.stringIndexed");
    1774             assertEquals("stringIndexed type", String.class, clazz);
    1775             clazz = PropertyUtils.getPropertyType(bean, "nested.stringProperty");
    1776             assertEquals("stringProperty type", String.class, clazz);
    1777             clazz = PropertyUtils.getPropertyType(bean, "nested.writeOnlyProperty");
    1778             assertEquals("writeOnlyProperty type", String.class, clazz);
    1779
    1780         } catch (Exception e) {
    1781             fail("Exception: " + e.getMessage());
    1782         }
    1783
    1784     }
    1785
    1786
    1787     /***
    1788      * Test getting accessible property reader methods for a specified
    1789      * list of properties of our standard test bean.
    1790      */
    1791     public void testGetReadMethodBasic() {
    1792
    1793         testGetReadMethod(bean, properties, TEST_BEAN_CLASS);
    1794
    1795     }
    1796
    1797
    1798     /***
    1799      * Test getting accessible property reader methods for a specified
    1800      * list of properties of a package private subclass of our standard
    1801      * test bean.
    1802      */
    1803     public void testGetReadMethodPackageSubclass() {
    1804
    1805         testGetReadMethod(beanPackageSubclass, properties, TEST_BEAN_CLASS);
    1806
    1807     }
    1808
    1809
    1810     /***
    1811      * Test getting accessible property reader methods for a specified
    1812      * list of properties that are declared either directly or via
    1813      * implemented interfaces.
    1814      */
    1815     public void testGetReadMethodPublicInterface() {
    1816
    1817         // Properties "bar" and "baz" are visible via implemented interfaces
    1818         // (one direct and one indirect)
    1819         testGetReadMethod(beanPrivate,
    1820                 new String[]{ "bar" },
    1821                 PRIVATE_DIRECT_CLASS);
    1822         testGetReadMethod(beanPrivate,
    1823                 new String[]{ "baz" },
    1824                 PRIVATE_INDIRECT_CLASS);
    1825
    1826         // Properties "bar" and "baz" are visible via implemented interfaces
    1827         // (one direct and one indirect).  The interface is implemented in
    1828         // a superclass
    1829         testGetReadMethod(beanPrivateSubclass,
    1830                 new String[]{ "bar" },
    1831                 PRIVATE_DIRECT_CLASS);
    1832         testGetReadMethod(beanPrivateSubclass,
    1833                 new String[]{ "baz" },
    1834                 PRIVATE_INDIRECT_CLASS);
    1835
    1836         // Property "foo" is not accessible because the underlying
    1837         // class has package scope
    1838         PropertyDescriptor pd[] =
    1839                 PropertyUtils.getPropertyDescriptors(beanPrivate);
    1840         int n = -1;
    1841         for (int i = 0; i < pd.length; i++) {
    1842             if ("foo".equals(pd[i].getName())) {
    1843                 n = i;
    1844                 break;
    1845             }
    1846         }
    1847         assertTrue("Found foo descriptor", n >= 0);
    1848         Method reader = pd[n].getReadMethod();
    1849         assertNotNull("Found foo read method", reader);
    1850         Object value = null;
    1851         try {
    1852             value = reader.invoke(beanPrivate, new Class[0]);
    1853             fail("Foo reader did throw IllegalAccessException");
    1854         } catch (IllegalAccessException e) {
    1855             // Expected result for this test
    1856         } catch (Throwable t) {
    1857             fail("Invoke foo reader: " + t);
    1858         }
    1859
    1860     }
    1861
    1862
    1863     /***
    1864      * Test getting accessible property reader methods for a specified
    1865      * list of properties of a public subclass of our standard test bean.
    1866      */
    1867     public void testGetReadMethodPublicSubclass() {
    1868
    1869         testGetReadMethod(beanPublicSubclass, properties, TEST_BEAN_CLASS);
    1870
    1871     }
    1872
    1873
    1874     /***
    1875      * Corner cases on getSimpleProperty invalid arguments.
    1876      */
    1877     public void testGetSimpleArguments() {
    1878
    1879         try {
    1880             PropertyUtils.getSimpleProperty(null, "stringProperty");
    1881             fail("Should throw IllegalArgumentException 1");
    1882         } catch (IllegalArgumentException e) {
    1883             // Expected response
    1884         } catch (Throwable t) {
    1885             fail("Threw " + t + " instead of IllegalArgumentException 1");
    1886         }
    1887
    1888         try {
    1889             PropertyUtils.getSimpleProperty(bean, null);
    1890             fail("Should throw IllegalArgumentException 2");
    1891         } catch (IllegalArgumentException e) {
    1892             // Expected response
    1893         } catch (Throwable t) {
    1894             fail("Threw " + t + " instead of IllegalArgumentException 2");
    1895         }
    1896
    1897     }
    1898
    1899
    1900     /***
    1901      * Test getSimpleProperty on a boolean property.
    1902      */
    1903     public void testGetSimpleBoolean() {
    1904
    1905         try {
    1906             Object value =
    1907                     PropertyUtils.getSimpleProperty(bean,
    1908                             "booleanProperty");
    1909             assertNotNull("Got a value", value);
    1910             assertTrue("Got correct type", (value instanceof Boolean));
    1911             assertTrue("Got correct value",
    1912                     ((Boolean) value).booleanValue() ==
    1913                     bean.getBooleanProperty());
    1914         } catch (IllegalAccessException e) {
    1915             fail("IllegalAccessException");
    1916         } catch (IllegalArgumentException e) {
    1917             fail("IllegalArgumentException");
    1918         } catch (InvocationTargetException e) {
    1919             fail("InvocationTargetException");
    1920         } catch (NoSuchMethodException e) {
    1921             fail("NoSuchMethodException");
    1922         }
    1923
    1924     }
    1925
    1926
    1927     /***
    1928      * Test getSimpleProperty on a double property.
    1929      */
    1930     public void testGetSimpleDouble() {
    1931
    1932         try {
    1933             Object value =
    1934                     PropertyUtils.getSimpleProperty(bean,
    1935                             "doubleProperty");
    1936             assertNotNull("Got a value", value);
    1937             assertTrue("Got correct type", (value instanceof Double));
    1938             assertEquals("Got correct value",
    1939                     ((Double) value).doubleValue(),
    1940                     bean.getDoubleProperty(), 0.005);
    1941         } catch (IllegalAccessException e) {
    1942             fail("IllegalAccessException");
    1943         } catch (IllegalArgumentException e) {
    1944             fail("IllegalArgumentException");
    1945         } catch (InvocationTargetException e) {
    1946             fail("InvocationTargetException");
    1947         } catch (NoSuchMethodException e) {
    1948             fail("NoSuchMethodException");
    1949         }
    1950
    1951     }
    1952
    1953
    1954     /***
    1955      * Test getSimpleProperty on a float property.
    1956      */
    1957     public void testGetSimpleFloat() {
    1958
    1959         try {
    1960             Object value =
    1961                     PropertyUtils.getSimpleProperty(bean,
    1962                             "floatProperty");
    1963             assertNotNull("Got a value", value);
    1964             assertTrue("Got correct type", (value instanceof Float));
    1965             assertEquals("Got correct value",
    1966                     ((Float) value).floatValue(),
    1967                     bean.getFloatProperty(),
    1968                     (float) 0.005);
    1969         } catch (IllegalAccessException e) {
    1970             fail("IllegalAccessException");
    1971         } catch (IllegalArgumentException e) {
    1972             fail("IllegalArgumentException");
    1973         } catch (InvocationTargetException e) {
    1974             fail("InvocationTargetException");
    1975         } catch (NoSuchMethodException e) {
    1976             fail("NoSuchMethodException");
    1977         }
    1978
    1979     }
    1980
    1981
    1982     /***
    1983      * Negative test getSimpleProperty on an indexed property.
    1984      */
    1985     public void testGetSimpleIndexed() {
    1986
    1987         Object value = null;
    1988         try {
    1989             value = PropertyUtils.getSimpleProperty(bean,
    1990                     "intIndexed[0]");
    1991             fail("Should have thrown IllegalArgumentException");
    1992         } catch (IllegalAccessException e) {
    1993             fail("IllegalAccessException");
    1994         } catch (IllegalArgumentException e) {
    1995             // Correct result for this test
    1996         } catch (InvocationTargetException e) {
    1997             fail("InvocationTargetException");
    1998         } catch (NoSuchMethodException e) {
    1999             fail("NoSuchMethodException");
    2000         }
    2001
    2002     }
    2003
    2004
    2005     /***
    2006      * Test getSimpleProperty on an int property.
    2007      */
    2008     public void testGetSimpleInt() {
    2009
    2010         try {
    2011             Object value =
    2012                     PropertyUtils.getSimpleProperty(bean,
    2013                             "intProperty");
    2014             assertNotNull("Got a value", value);
    2015             assertTrue("Got correct type", (value instanceof Integer));
    2016             assertEquals("Got correct value",
    2017                     ((Integer) value).intValue(),
    2018                     bean.getIntProperty());
    2019         } catch (IllegalAccessException e) {
    2020             fail("IllegalAccessException");
    2021         } catch (IllegalArgumentException e) {
    2022             fail("IllegalArgumentException");
    2023         } catch (InvocationTargetException e) {
    2024             fail("InvocationTargetException");
    2025         } catch (NoSuchMethodException e) {
    2026             fail("NoSuchMethodException");
    2027         }
    2028
    2029     }
    2030
    2031
    2032     /***
    2033      * Test getSimpleProperty on a long property.
    2034      */
    2035     public void testGetSimpleLong() {
    2036
    2037         try {
    2038             Object value =
    2039                     PropertyUtils.getSimpleProperty(bean,
    2040                             "longProperty");
    2041             assertNotNull("Got a value", value);
    2042             assertTrue("Got correct type", (value instanceof Long));
    2043             assertEquals("Got correct value",
    2044                     ((Long) value).longValue(),
    2045                     bean.getLongProperty());
    2046         } catch (IllegalAccessException e) {
    2047             fail("IllegalAccessException");
    2048         } catch (IllegalArgumentException e) {
    2049             fail("IllegalArgumentException");
    2050         } catch (InvocationTargetException e) {
    2051             fail("InvocationTargetException");
    2052         } catch (NoSuchMethodException e) {
    2053             fail("NoSuchMethodException");
    2054         }
    2055
    2056     }
    2057
    2058
    2059     /***
    2060      * Negative test getSimpleProperty on a nested property.
    2061      */
    2062     public void testGetSimpleNested() {
    2063
    2064         Object value = null;
    2065         try {
    2066             value = PropertyUtils.getSimpleProperty(bean,
    2067                     "nested.stringProperty");
    2068             fail("Should have thrown IllegaArgumentException");
    2069         } catch (IllegalAccessException e) {
    2070             fail("IllegalAccessException");
    2071         } catch (IllegalArgumentException e) {
    2072             // Correct result for this test
    2073         } catch (InvocationTargetException e) {
    2074             fail("InvocationTargetException");
    2075         } catch (NoSuchMethodException e) {
    2076             fail("NoSuchMethodException");
    2077         }
    2078
    2079     }
    2080
    2081
    2082     /***
    2083      * Test getSimpleProperty on a read-only String property.
    2084      */
    2085     public void testGetSimpleReadOnly() {
    2086
    2087         try {
    2088             Object value =
    2089                     PropertyUtils.getSimpleProperty(bean,
    2090                             "readOnlyProperty");
    2091             assertNotNull("Got a value", value);
    2092             assertTrue("Got correct type", (value instanceof String));
    2093             assertEquals("Got correct value",
    2094                     (String) value,
    2095                     bean.getReadOnlyProperty());
    2096         } catch (IllegalAccessException e) {
    2097             fail("IllegalAccessException");
    2098         } catch (IllegalArgumentException e) {
    2099             fail("IllegalArgumentException");
    2100         } catch (InvocationTargetException e) {
    2101             fail("InvocationTargetException");
    2102         } catch (NoSuchMethodException e) {
    2103             fail("NoSuchMethodException");
    2104         }
    2105
    2106     }
    2107
    2108
    2109     /***
    2110      * Test getSimpleProperty on a short property.
    2111      */
    2112     public void testGetSimpleShort() {
    2113
    2114         try {
    2115             Object value =
    2116                     PropertyUtils.getSimpleProperty(bean,
    2117                             "shortProperty");
    2118             assertNotNull("Got a value", value);
    2119             assertTrue("Got correct type", (value instanceof Short));
    2120             assertEquals("Got correct value",
    2121                     ((Short) value).shortValue(),
    2122                     bean.getShortProperty());
    2123         } catch (IllegalAccessException e) {
    2124             fail("IllegalAccessException");
    2125         } catch (IllegalArgumentException e) {
    2126             fail("IllegalArgumentException");
    2127         } catch (InvocationTargetException e) {
    2128             fail("InvocationTargetException");
    2129         } catch (NoSuchMethodException e) {
    2130             fail("NoSuchMethodException");
    2131         }
    2132
    2133     }
    2134
    2135
    2136     /***
    2137      * Test getSimpleProperty on a String property.
    2138      */
    2139     public void testGetSimpleString() {
    2140
    2141         try {
    2142             Object value =
    2143                     PropertyUtils.getSimpleProperty(bean,
    2144                             "stringProperty");
    2145             assertNotNull("Got a value", value);
    2146             assertTrue("Got correct type", (value instanceof String));
    2147             assertEquals("Got correct value",
    2148                     (String) value,
    2149                     bean.getStringProperty());
    2150         } catch (IllegalAccessException e) {
    2151             fail("IllegalAccessException");
    2152         } catch (IllegalArgumentException e) {
    2153             fail("IllegalArgumentException");
    2154         } catch (InvocationTargetException e) {
    2155             fail("InvocationTargetException");
    2156         } catch (NoSuchMethodException e) {
    2157             fail("NoSuchMethodException");
    2158         }
    2159
    2160     }
    2161
    2162
    2163     /***
    2164      * Negative test getSimpleProperty on an unknown property.
    2165      */
    2166     public void testGetSimpleUnknown() {
    2167
    2168         try {
    2169             PropertyUtils.getSimpleProperty(bean, "unknown");
    2170             fail("Should have thrown NoSuchMethodException");
    2171         } catch (IllegalAccessException e) {
    2172             fail("IllegalAccessException");
    2173         } catch (IllegalArgumentException e) {
    2174             fail("IllegalArgumentException");
    2175         } catch (InvocationTargetException e) {
    2176             fail("InvocationTargetException");
    2177         } catch (NoSuchMethodException e) {
    2178             // Correct result for this test
    2179             assertEquals("Unknown property 'unknown' on class '" +
    2180                          bean.getClass() + "'", e.getMessage() );
    2181         }
    2182
    2183     }
    2184
    2185
    2186     /***
    2187      * Test getSimpleProperty on a write-only String property.
    2188      */
    2189     public void testGetSimpleWriteOnly() {
    2190
    2191         try {
    2192             PropertyUtils.getSimpleProperty(bean, "writeOnlyProperty");
    2193             fail("Should have thrown NoSuchMethodException");
    2194         } catch (IllegalAccessException e) {
    2195             fail("IllegalAccessException");
    2196         } catch (IllegalArgumentException e) {
    2197             fail("IllegalArgumentException");
    2198         } catch (InvocationTargetException e) {
    2199             fail("InvocationTargetException");
    2200         } catch (NoSuchMethodException e) {
    2201             // Correct result for this test
    2202             assertEquals("Property 'writeOnlyProperty' has no getter method in class '" +
    2203                          bean.getClass() + "'", e.getMessage() );
    2204         }
    2205
    2206     }
    2207
    2208
    2209     /***
    2210      * Test getting accessible property writer methods for a specified
    2211      * list of properties of our standard test bean.
    2212      */
    2213     public void testGetWriteMethodBasic() {
    2214
    2215         testGetWriteMethod(bean, properties, TEST_BEAN_CLASS);
    2216
    2217     }
    2218
    2219
    2220     /***
    2221      * Test getting accessible property writer methods for a specified
    2222      * list of properties of a package private subclass of our standard
    2223      * test bean.
    2224      */
    2225     public void testGetWriteMethodPackageSubclass() {
    2226
    2227         testGetWriteMethod(beanPackageSubclass, properties, TEST_BEAN_CLASS);
    2228
    2229     }
    2230
    2231
    2232     /***
    2233      * Test getting accessible property writer methods for a specified
    2234      * list of properties of a public subclass of our standard test bean.
    2235      */
    2236     public void testGetWriteMethodPublicSubclass() {
    2237
    2238         testGetWriteMethod(beanPublicSubclass, properties, TEST_BEAN_CLASS);
    2239
    2240     }
    2241
    2242     /***
    2243      * Test isReadable() method.
    2244      */
    2245     public void testIsReadable() {
    2246         TestBean bean = new TestBean();
    2247         String property = null;
    2248         try {
    2249             property = "stringProperty";
    2250             assertTrue("Property " + property +" isReadable expeced TRUE", PropertyUtils.isReadable(bean, property));
    2251         } catch (Throwable t) {
    2252             fail("Property " + property +" isReadable Threw exception: " + t);
    2253         }
    2254         try {
    2255             property = "stringIndexed";
    2256             assertTrue("Property " + property +" isReadable expeced TRUE", PropertyUtils.isReadable(bean, property));
    2257         } catch (Throwable t) {
    2258             fail("Property " + property +" isReadable Threw exception: " + t);
    2259         }
    2260         try {
    2261             property = "mappedProperty";
    2262             assertTrue("Property " + property +" isReadable expeced TRUE", PropertyUtils.isReadable(bean, property));
    2263         } catch (Throwable t) {
    2264             fail("Property " + property +" isReadable Threw exception: " + t);
    2265         }
    2266
    2267     }
    2268
    2269     /***
    2270      * Test isWriteable() method.
    2271      */
    2272     public void testIsWriteable() {
    2273         TestBean bean = new TestBean();
    2274         String property = null;
    2275         try {
    2276             property = "stringProperty";
    2277             assertTrue("Property " + property +" isWriteable expeced TRUE", PropertyUtils.isWriteable(bean, property));
    2278         } catch (Throwable t) {
    2279             fail("Property " + property +" isWriteable Threw exception: " + t);
    2280         }
    2281         try {
    2282             property = "stringIndexed";
    2283             assertTrue("Property " + property +" isWriteable expeced TRUE", PropertyUtils.isWriteable(bean, property));
    2284         } catch (Throwable t) {
    2285             fail("Property " + property +" isWriteable Threw exception: " + t);
    2286         }
    2287         try {
    2288             property = "mappedProperty";
    2289             assertTrue("Property " + property +" isWriteable expeced TRUE", PropertyUtils.isWriteable(bean, property));
    2290         } catch (Throwable t) {
    2291             fail("Property " + property +" isWriteable Threw exception: " + t);
    2292         }
    2293
    2294     }
    2295
    2296
    2297     /***
    2298      * Test the mappedPropertyType of MappedPropertyDescriptor.
    2299      */
    2300     public void testMappedPropertyType() throws Exception {
    2301
    2302         MappedPropertyDescriptor desc;
    2303
    2304         // Check a String property
    2305         desc = (MappedPropertyDescriptor)
    2306                 PropertyUtils.getPropertyDescriptor(bean,
    2307                         "mappedProperty");
    2308         assertEquals(String.class, desc.getMappedPropertyType());
    2309
    2310         // Check an int property
    2311         desc = (MappedPropertyDescriptor)
    2312                 PropertyUtils.getPropertyDescriptor(bean,
    2313                         "mappedIntProperty");
    2314         assertEquals(Integer.TYPE, desc.getMappedPropertyType());
    2315
    2316     }
    2317
    2318
    2319     /***
    2320      * Corner cases on setIndexedProperty invalid arguments.
    2321      */
    2322     public void testSetIndexedArguments() {
    2323
    2324         // Use explicit index argument
    2325
    2326         try {
    2327             PropertyUtils.setIndexedProperty(null, "intArray", 0,
    2328                     new Integer(1));
    2329             fail("Should throw IllegalArgumentException 1");
    2330         } catch (IllegalArgumentException e) {
    2331             // Expected response
    2332         } catch (Throwable t) {
    2333             fail("Threw " + t + " instead of IllegalArgumentException 1");
    2334         }
    2335
    2336         try {
    2337             PropertyUtils.setIndexedProperty(bean, null, 0,
    2338                     new Integer(1));
    2339             fail("Should throw IllegalArgumentException 2");
    2340         } catch (IllegalArgumentException e) {
    2341             // Expected response
    2342         } catch (Throwable t) {
    2343             fail("Threw " + t + " instead of IllegalArgumentException 2");
    2344         }
    2345
    2346         // Use index expression
    2347
    2348         try {
    2349             PropertyUtils.setIndexedProperty(null,
    2350                     "intArray[0]",
    2351                     new Integer(1));
    2352             fail("Should throw IllegalArgumentException 3");
    2353         } catch (IllegalArgumentException e) {
    2354             // Expected response
    2355         } catch (Throwable t) {
    2356             fail("Threw " + t + " instead of IllegalArgumentException 3");
    2357         }
    2358
    2359         try {
    2360             PropertyUtils.setIndexedProperty(bean, "[0]",
    2361                     new Integer(1));
    2362             fail("Should throw NoSuchMethodException 4");
    2363         } catch (NoSuchMethodException e) {
    2364             // Expected response
    2365         } catch (Throwable t) {
    2366             fail("Threw " + t + " instead of NoSuchMethodException 4");
    2367         }
    2368
    2369         try {
    2370             PropertyUtils.setIndexedProperty(bean, "intArray",
    2371                     new Integer(1));
    2372             fail("Should throw IllegalArgumentException 5");
    2373         } catch (IllegalArgumentException e) {
    2374             // Expected response
    2375         } catch (Throwable t) {
    2376             fail("Threw " + t + " instead of IllegalArgumentException 5");
    2377         }
    2378
    2379         // Use explicit index argument
    2380
    2381         try {
    2382             PropertyUtils.setIndexedProperty(null, "intIndexed", 0,
    2383                     new Integer(1));
    2384             fail("Should throw IllegalArgumentException 1");
    2385         } catch (IllegalArgumentException e) {
    2386             // Expected response
    2387         } catch (Throwable t) {
    2388             fail("Threw " + t + " instead of IllegalArgumentException 1");
    2389         }
    2390
    2391         try {
    2392             PropertyUtils.setIndexedProperty(bean, null, 0,
    2393                     new Integer(1));
    2394             fail("Should throw IllegalArgumentException 2");
    2395         } catch (IllegalArgumentException e) {
    2396             // Expected response
    2397         } catch (Throwable t) {
    2398             fail("Threw " + t + " instead of IllegalArgumentException 2");
    2399         }
    2400
    2401         // Use index expression
    2402
    2403         try {
    2404             PropertyUtils.setIndexedProperty(null,
    2405                     "intIndexed[0]",
    2406                     new Integer(1));
    2407             fail("Should throw IllegalArgumentException 3");
    2408         } catch (IllegalArgumentException e) {
    2409             // Expected response
    2410         } catch (Throwable t) {
    2411             fail("Threw " + t + " instead of IllegalArgumentException 3");
    2412         }
    2413
    2414         try {
    2415             PropertyUtils.setIndexedProperty(bean, "[0]",
    2416                     new Integer(1));
    2417             fail("Should throw NoSuchMethodException 4");
    2418         } catch (NoSuchMethodException e) {
    2419             // Expected response
    2420         } catch (Throwable t) {
    2421             fail("Threw " + t + " instead of NoSuchMethodException 4");
    2422         }
    2423
    2424         try {
    2425             PropertyUtils.setIndexedProperty(bean, "intIndexed",
    2426                     new Integer(1));
    2427             fail("Should throw IllegalArgumentException 5");
    2428         } catch (IllegalArgumentException e) {
    2429             // Expected response
    2430         } catch (Throwable t) {
    2431             fail("Threw " + t + " instead of IllegalArgumentException 5");
    2432         }
    2433
    2434     }
    2435
    2436     /***
    2437      * Test setting an indexed value out of a multi-dimensional array
    2438      */
    2439     public void testSetIndexedArray() {
    2440         String[] firstArray = new String[] {"FIRST-1", "FIRST-2", "FIRST-3"};
    2441         String[] secondArray = new String[] {"SECOND-1", "SECOND-2", "SECOND-3",  "SECOND-4"};
    2442         String[][] mainArray = {firstArray, secondArray};
    2443         TestBean bean = new TestBean(mainArray);
    2444         assertEquals("BEFORE", "SECOND-3", bean.getString2dArray(1)[2]);
    2445         try {
    2446             PropertyUtils.setProperty(bean, "string2dArray[1][2]", "SECOND-3-UPDATED");
    2447         } catch (Throwable t) {
    2448             fail("Threw " + t + "");
    2449         }
    2450         assertEquals("AFTER", "SECOND-3-UPDATED", bean.getString2dArray(1)[2]);
    2451     }
    2452
    2453     /***
    2454      * Test setting an indexed value out of List of Lists
    2455      */
    2456     public void testSetIndexedList() {
    2457         String[] firstArray = new String[] {"FIRST-1", "FIRST-2", "FIRST-3"};
    2458         String[] secondArray = new String[] {"SECOND-1", "SECOND-2", "SECOND-3",  "SECOND-4"};
    2459         List mainList   = new ArrayList();
    2460         mainList.add(Arrays.asList(firstArray));
    2461         mainList.add(Arrays.asList(secondArray));
    2462         TestBean bean = new TestBean(mainList);
    2463         assertEquals("BEFORE", "SECOND-4", ((List)bean.getListIndexed().get(1)).get(3));
    2464         try {
    2465             PropertyUtils.setProperty(bean, "listIndexed[1][3]", "SECOND-4-UPDATED");
    2466         } catch (Throwable t) {
    2467             fail("Threw " + t + "");
    2468         }
    2469         assertEquals("AFTER", "SECOND-4-UPDATED", ((List)bean.getListIndexed().get(1)).get(3));
    2470     }
    2471
    2472     /***
    2473      * Test setting a value out of a mapped Map
    2474      */
    2475     public void testSetIndexedMap() {
    2476         Map firstMap  = new HashMap();
    2477         firstMap.put("FIRST-KEY-1", "FIRST-VALUE-1");
    2478         firstMap.put("FIRST-KEY-2", "FIRST-VALUE-2");
    2479         Map secondMap  = new HashMap();
    2480         secondMap.put("SECOND-KEY-1", "SECOND-VALUE-1");
    2481         secondMap.put("SECOND-KEY-2", "SECOND-VALUE-2");
    2482
    2483         List mainList = new ArrayList();
    2484         mainList.add(firstMap);
    2485         mainList.add(secondMap);
    2486         TestBean bean = new TestBean(mainList);
    2487
    2488         assertEquals("BEFORE",  null,              ((Map)bean.getListIndexed().get(0)).get("FIRST-NEW-KEY"));
    2489         assertEquals("BEFORE",  "SECOND-VALUE-1",  ((Map)bean.getListIndexed().get(1)).get("SECOND-KEY-1"));
    2490         try {
    2491             PropertyUtils.setProperty(bean, "listIndexed[0](FIRST-NEW-KEY)", "FIRST-NEW-VALUE");
    2492             PropertyUtils.setProperty(bean, "listIndexed[1](SECOND-KEY-1)",  "SECOND-VALUE-1-UPDATED");
    2493         } catch (Throwable t) {
    2494             fail("Threw " + t + "");
    2495         }
    2496         assertEquals("BEFORE", "FIRST-NEW-VALUE",         ((Map)bean.getListIndexed().get(0)).get("FIRST-NEW-KEY"));
    2497         assertEquals("AFTER",  "SECOND-VALUE-1-UPDATED",  ((Map)bean.getListIndexed().get(1)).get("SECOND-KEY-1"));
    2498     }
    2499
    2500
    2501     /***
    2502      * Positive and negative tests on setIndexedProperty valid arguments.
    2503      */
    2504     public void testSetIndexedValues() {
    2505
    2506         Object value = null;
    2507
    2508         // Use explicit index argument
    2509
    2510         try {
    2511             PropertyUtils.setIndexedProperty(bean,
    2512                     "dupProperty", 0,
    2513                     "New 0");
    2514             value =
    2515                     PropertyUtils.getIndexedProperty(bean,
    2516                             "dupProperty", 0);
    2517             assertNotNull("Returned new value 0", value);
    2518             assertTrue("Returned String new value 0",
    2519                     value instanceof String);
    2520             assertEquals("Returned correct new value 0", "New 0",
    2521                     (String) value);
    2522         } catch (Throwable t) {
    2523             fail("Threw " + t);
    2524         }
    2525
    2526         try {
    2527             PropertyUtils.setIndexedProperty(bean,
    2528                     "intArray", 0,
    2529                     new Integer(1));
    2530             value =
    2531                     PropertyUtils.getIndexedProperty(bean,
    2532                             "intArray", 0);
    2533             assertNotNull("Returned new value 0", value);
    2534             assertTrue("Returned Integer new value 0",
    2535                     value instanceof Integer);
    2536             assertEquals("Returned correct new value 0", 1,
    2537                     ((Integer) value).intValue());
    2538         } catch (Throwable t) {
    2539             fail("Threw " + t);
    2540         }
    2541
    2542         try {
    2543             PropertyUtils.setIndexedProperty(bean,
    2544                     "intIndexed", 1,
    2545                     new Integer(11));
    2546             value =
    2547                     PropertyUtils.getIndexedProperty(bean,
    2548                             "intIndexed", 1);
    2549             assertNotNull("Returned new value 1", value);
    2550             assertTrue("Returned Integer new value 1",
    2551                     value instanceof Integer);
    2552             assertEquals("Returned correct new value 1", 11,
    2553                     ((Integer) value).intValue());
    2554         } catch (Throwable t) {
    2555             fail("Threw " + t);
    2556         }
    2557
    2558         try {
    2559             PropertyUtils.setIndexedProperty(bean,
    2560                     "listIndexed", 2,
    2561                     "New Value 2");
    2562             value =
    2563                     PropertyUtils.getIndexedProperty(bean,
    2564                             "listIndexed", 2);
    2565             assertNotNull("Returned new value 2", value);
    2566             assertTrue("Returned String new value 2",
    2567                     value instanceof String);
    2568             assertEquals("Returned correct new value 2", "New Value 2",
    2569                     (String) value);
    2570         } catch (Throwable t) {
    2571             fail("Threw " + t);
    2572         }
    2573
    2574         try {
    2575             PropertyUtils.setIndexedProperty(bean,
    2576                     "stringArray", 2,
    2577                     "New Value 2");
    2578             value =
    2579                     PropertyUtils.getIndexedProperty(bean,
    2580                             "stringArray", 2);
    2581             assertNotNull("Returned new value 2", value);
    2582             assertTrue("Returned String new value 2",
    2583                     value instanceof String);
    2584             assertEquals("Returned correct new value 2", "New Value 2",
    2585                     (String) value);
    2586         } catch (Throwable t) {
    2587             fail("Threw " + t);
    2588         }
    2589
    2590         try {
    2591             PropertyUtils.setIndexedProperty(bean,
    2592                     "stringArray", 3,
    2593                     "New Value 3");
    2594             value =
    2595                     PropertyUtils.getIndexedProperty(bean,
    2596                             "stringArray", 3);
    2597             assertNotNull("Returned new value 3", value);
    2598             assertTrue("Returned String new value 3",
    2599                     value instanceof String);
    2600             assertEquals("Returned correct new value 3", "New Value 3",
    2601                     (String) value);
    2602         } catch (Throwable t) {
    2603             fail("Threw " + t);
    2604         }
    2605
    2606         // Use index expression
    2607
    2608         try {
    2609             PropertyUtils.setIndexedProperty(bean,
    2610                     "dupProperty[4]",
    2611                     "New 4");
    2612             value =
    2613                     PropertyUtils.getIndexedProperty(bean,
    2614                             "dupProperty[4]");
    2615             assertNotNull("Returned new value 4", value);
    2616             assertTrue("Returned String new value 4",
    2617                     value instanceof String);
    2618             assertEquals("Returned correct new value 4", "New 4",
    2619                          (String) value);
    2620         } catch (Throwable t) {
    2621             fail("Threw " + t);
    2622         }
    2623
    2624         try {
    2625             PropertyUtils.setIndexedProperty(bean,
    2626                     "intArray[4]",
    2627                     new Integer(1));
    2628             value =
    2629                     PropertyUtils.getIndexedProperty(bean,
    2630                             "intArray[4]");
    2631             assertNotNull("Returned new value 4", value);
    2632             assertTrue("Returned Integer new value 4",
    2633                     value instanceof Integer);
    2634             assertEquals("Returned correct new value 4", 1,
    2635                     ((Integer) value).intValue());
    2636         } catch (Throwable t) {
    2637             fail("Threw " + t);
    2638         }
    2639
    2640         try {
    2641             PropertyUtils.setIndexedProperty(bean,
    2642                     "intIndexed[3]",
    2643                     new Integer(11));
    2644             value =
    2645                     PropertyUtils.getIndexedProperty(bean,
    2646                             "intIndexed[3]");
    2647             assertNotNull("Returned new value 5", value);
    2648             assertTrue("Returned Integer new value 5",
    2649                     value instanceof Integer);
    2650             assertEquals("Returned correct new value 5", 11,
    2651                     ((Integer) value).intValue());
    2652         } catch (Throwable t) {
    2653             fail("Threw " + t);
    2654         }
    2655
    2656         try {
    2657             PropertyUtils.setIndexedProperty(bean,
    2658                     "listIndexed[1]",
    2659                     "New Value 2");
    2660             value =
    2661                     PropertyUtils.getIndexedProperty(bean,
    2662                             "listIndexed[1]");
    2663             assertNotNull("Returned new value 6", value);
    2664             assertTrue("Returned String new value 6",
    2665                     value instanceof String);
    2666             assertEquals("Returned correct new value 6", "New Value 2",
    2667                     (String) value);
    2668         } catch (Throwable t) {
    2669             fail("Threw " + t);
    2670         }
    2671
    2672         try {
    2673             PropertyUtils.setIndexedProperty(bean,
    2674                     "stringArray[1]",
    2675                     "New Value 2");
    2676             value =
    2677                     PropertyUtils.getIndexedProperty(bean,
    2678                             "stringArray[2]");
    2679             assertNotNull("Returned new value 6", value);
    2680             assertTrue("Returned String new value 6",
    2681                     value instanceof String);
    2682             assertEquals("Returned correct new value 6", "New Value 2",
    2683                     (String) value);
    2684         } catch (Throwable t) {
    2685             fail("Threw " + t);
    2686         }
    2687
    2688         try {
    2689             PropertyUtils.setIndexedProperty(bean,
    2690                     "stringArray[0]",
    2691                     "New Value 3");
    2692             value =
    2693                     PropertyUtils.getIndexedProperty(bean,
    2694                             "stringArray[0]");
    2695             assertNotNull("Returned new value 7", value);
    2696             assertTrue("Returned String new value 7",
    2697                     value instanceof String);
    2698             assertEquals("Returned correct new value 7", "New Value 3",
    2699                     (String) value);
    2700         } catch (Throwable t) {
    2701             fail("Threw " + t);
    2702         }
    2703
    2704         // Index out of bounds tests
    2705
    2706         try {
    2707             PropertyUtils.setIndexedProperty(bean,
    2708                     "dupProperty", -1,
    2709                     "New -1");
    2710             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2711         } catch (ArrayIndexOutOfBoundsException t) {
    2712             // Expected results
    2713         } catch (Throwable t) {
    2714             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2715         }
    2716
    2717         try {
    2718             PropertyUtils.setIndexedProperty(bean,
    2719                     "dupProperty", 5,
    2720                     "New 5");
    2721             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2722         } catch (ArrayIndexOutOfBoundsException t) {
    2723             // Expected results
    2724         } catch (Throwable t) {
    2725             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2726         }
    2727
    2728         try {
    2729             PropertyUtils.setIndexedProperty(bean,
    2730                     "intArray", -1,
    2731                     new Integer(0));
    2732             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2733         } catch (ArrayIndexOutOfBoundsException t) {
    2734             // Expected results
    2735         } catch (Throwable t) {
    2736             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2737         }
    2738
    2739         try {
    2740             PropertyUtils.setIndexedProperty(bean,
    2741                     "intArray", 5,
    2742                     new Integer(0));
    2743             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2744         } catch (ArrayIndexOutOfBoundsException t) {
    2745             // Expected results
    2746         } catch (Throwable t) {
    2747             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2748         }
    2749
    2750         try {
    2751             PropertyUtils.setIndexedProperty(bean,
    2752                     "intIndexed", -1,
    2753                     new Integer(0));
    2754             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2755         } catch (ArrayIndexOutOfBoundsException t) {
    2756             // Expected results
    2757         } catch (Throwable t) {
    2758             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2759         }
    2760
    2761         try {
    2762             PropertyUtils.setIndexedProperty(bean,
    2763                     "intIndexed", 5,
    2764                     new Integer(0));
    2765             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2766         } catch (ArrayIndexOutOfBoundsException t) {
    2767             // Expected results
    2768         } catch (Throwable t) {
    2769             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2770         }
    2771
    2772         try {
    2773             PropertyUtils.setIndexedProperty(bean,
    2774                     "listIndexed", 5,
    2775                     "New String");
    2776             fail("Should have thrown IndexOutOfBoundsException");
    2777         } catch (IndexOutOfBoundsException t) {
    2778             // Expected results
    2779         } catch (Throwable t) {
    2780             fail("Threw " + t + " instead of IndexOutOfBoundsException");
    2781         }
    2782
    2783         try {
    2784             PropertyUtils.setIndexedProperty(bean,
    2785                     "listIndexed", -1,
    2786                     "New String");
    2787             fail("Should have thrown IndexOutOfBoundsException");
    2788         } catch (IndexOutOfBoundsException t) {
    2789             // Expected results
    2790         } catch (Throwable t) {
    2791             fail("Threw " + t + " instead of IndexOutOfBoundsException");
    2792         }
    2793
    2794         try {
    2795             PropertyUtils.setIndexedProperty(bean,
    2796                     "stringArray", -1,
    2797                     "New String");
    2798             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2799         } catch (ArrayIndexOutOfBoundsException t) {
    2800             // Expected results
    2801         } catch (Throwable t) {
    2802             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2803         }
    2804
    2805         try {
    2806             PropertyUtils.setIndexedProperty(bean,
    2807                     "stringArray", 5,
    2808                     "New String");
    2809             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2810         } catch (ArrayIndexOutOfBoundsException t) {
    2811             // Expected results
    2812         } catch (Throwable t) {
    2813             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2814         }
    2815
    2816         try {
    2817             PropertyUtils.setIndexedProperty(bean,
    2818                     "stringIndexed", -1,
    2819                     "New String");
    2820             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2821         } catch (ArrayIndexOutOfBoundsException t) {
    2822             // Expected results
    2823         } catch (Throwable t) {
    2824             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2825         }
    2826
    2827         try {
    2828             PropertyUtils.setIndexedProperty(bean,
    2829                     "stringIndexed", 5,
    2830                     "New String");
    2831             fail("Should have thrown ArrayIndexOutOfBoundsException");
    2832         } catch (ArrayIndexOutOfBoundsException t) {
    2833             // Expected results
    2834         } catch (Throwable t) {
    2835             fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
    2836         }
    2837
    2838     }
    2839
    2840
    2841     /***
    2842      * Corner cases on getMappedProperty invalid arguments.
    2843      */
    2844     public void testSetMappedArguments() {
    2845
    2846         // Use explicit key argument
    2847
    2848         try {
    2849             PropertyUtils.setMappedProperty(null, "mappedProperty",
    2850                     "First Key", "First Value");
    2851             fail("Should throw IllegalArgumentException 1");
    2852         } catch (IllegalArgumentException e) {
    2853             // Expected response
    2854         } catch (Throwable t) {
    2855             fail("Threw " + t + " instead of IllegalArgumentException 1");
    2856         }
    2857
    2858         try {
    2859             PropertyUtils.setMappedProperty(bean, null, "First Key",
    2860                     "First Value");
    2861             fail("Should throw IllegalArgumentException 2");
    2862         } catch (IllegalArgumentException e) {
    2863             // Expected response
    2864         } catch (Throwable t) {
    2865             fail("Threw " + t + " instead of IllegalArgumentException 2");
    2866         }
    2867
    2868         try {
    2869             PropertyUtils.setMappedProperty(bean, "mappedProperty", null,
    2870                     "First Value");
    2871             fail("Should throw IllegalArgumentException 3");
    2872         } catch (IllegalArgumentException e) {
    2873             // Expected response
    2874         } catch (Throwable t) {
    2875             fail("Threw " + t + " instead of IllegalArgumentException 3");
    2876         }
    2877
    2878         // Use key expression
    2879
    2880         try {
    2881             PropertyUtils.setMappedProperty(null,
    2882                     "mappedProperty(First Key)",
    2883                     "First Value");
    2884             fail("Should throw IllegalArgumentException 4");
    2885         } catch (IllegalArgumentException e) {
    2886             // Expected response
    2887         } catch (Throwable t) {
    2888             fail("Threw " + t + " instead of IllegalArgumentException 4");
    2889         }
    2890
    2891         try {
    2892             PropertyUtils.setMappedProperty(bean, "(Second Key)",
    2893                     "Second Value");
    2894             fail("Should throw IllegalArgumentException 5");
    2895         } catch (NoSuchMethodException e) {
    2896             // Expected response
    2897         } catch (Throwable t) {
    2898             fail("Threw " + t + " instead of NoSuchMethodException 5");
    2899         }
    2900
    2901         try {
    2902             PropertyUtils.setMappedProperty(bean, "mappedProperty",
    2903                     "Third Value");
    2904             fail("Should throw IllegalArgumentException 6");
    2905         } catch (IllegalArgumentException e) {
    2906             // Expected response
    2907         } catch (Throwable t) {
    2908             fail("Threw " + t + " instead of IllegalArgumentException 6");
    2909         }
    2910
    2911     }
    2912
    2913
    2914     /***
    2915      * Test setting an indexed value out of a mapped array
    2916      */
    2917     public void testSetMappedArray() {
    2918         TestBean bean = new TestBean();
    2919         String[] array = new String[] {"abc", "def", "ghi"};
    2920         bean.getMapProperty().put("mappedArray", array);
    2921
    2922         assertEquals("BEFORE", "def", ((String[])bean.getMapProperty().get("mappedArray"))[1]);
    2923         try {
    2924             PropertyUtils.setProperty(bean, "mapProperty(mappedArray)[1]", "DEF-UPDATED");
    2925         } catch (Throwable t) {
    2926             fail("Threw " + t + "");
    2927         }
    2928         assertEquals("AFTER", "DEF-UPDATED", ((String[])bean.getMapProperty().get("mappedArray"))[1]);
    2929     }
    2930
    2931     /***
    2932      * Test setting an indexed value out of a mapped List
    2933      */
    2934     public void testSetMappedList() {
    2935         TestBean bean = new TestBean();
    2936         List list = new ArrayList();
    2937         list.add("klm");
    2938         list.add("nop");
    2939         list.add("qrs");
    2940         bean.getMapProperty().put("mappedList", list);
    2941
    2942         assertEquals("BEFORE", "klm", ((List)bean.getMapProperty().get("mappedList")).get(0));
    2943         try {
    2944             PropertyUtils.setProperty(bean, "mapProperty(mappedList)[0]", "KLM-UPDATED");
    2945         } catch (Throwable t) {
    2946             fail("Threw " + t + "");
    2947         }
    2948         assertEquals("AFTER", "KLM-UPDATED", ((List)bean.getMapProperty().get("mappedList")).get(0));
    2949     }
    2950
    2951     /***
    2952      * Test setting a value out of a mapped Map
    2953      */
    2954     public void testSetMappedMap() {
    2955         TestBean bean = new TestBean();
    2956         Map map = new HashMap();
    2957         map.put("sub-key-1", "sub-value-1");
    2958         map.put("sub-key-2", "sub-value-2");
    2959         map.put("sub-key-3", "sub-value-3");
    2960         bean.getMapProperty().put("mappedMap", map);
    2961
    2962         assertEquals("BEFORE", "sub-value-3", ((Map)bean.getMapProperty().get("mappedMap")).get("sub-key-3"));
    2963         try {
    2964             PropertyUtils.setProperty(bean, "mapProperty(mappedMap)(sub-key-3)", "SUB-KEY-3-UPDATED");
    2965         } catch (Throwable t) {
    2966             fail("Threw " + t + "");
    2967         }
    2968         assertEquals("AFTER", "SUB-KEY-3-UPDATED", ((Map)bean.getMapProperty().get("mappedMap")).get("sub-key-3"));
    2969     }
    2970
    2971     /***
    2972      * Positive and negative tests on setMappedProperty valid arguments.
    2973      */
    2974     public void testSetMappedValues() {
    2975
    2976         Object value = null;
    2977
    2978         // Use explicit key argument
    2979
    2980         try {
    2981             value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
    2982                     "Fourth Key");
    2983             assertNull("Can not find fourth value", value);
    2984         } catch (Throwable t) {
    2985             fail("Finding fourth value threw " + t);
    2986         }
    2987
    2988         try {
    2989             PropertyUtils.setMappedProperty(bean, "mappedProperty",
    2990                     "Fourth Key", "Fourth Value");
    2991         } catch (Throwable t) {
    2992             fail("Setting fourth value threw " + t);
    2993         }
    2994
    2995         try {
    2996             value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
    2997                     "Fourth Key");
    2998             assertEquals("Can find fourth value", "Fourth Value", value);
    2999         } catch (Throwable t) {
    3000             fail("Finding fourth value threw " + t);
    3001         }
    3002
    3003         // Use key expression with parentheses
    3004
    3005         try {
    3006             value =
    3007                     PropertyUtils.getMappedProperty(bean,
    3008                             "mappedProperty(Fifth Key)");
    3009             assertNull("Can not find fifth value", value);
    3010         } catch (Throwable t) {
    3011             fail("Finding fifth value threw " + t);
    3012         }
    3013
    3014         try {
    3015             PropertyUtils.setMappedProperty(bean,
    3016                     "mappedProperty(Fifth Key)",
    3017                     "Fifth Value");
    3018         } catch (Throwable t) {
    3019             fail("Setting fifth value threw " + t);
    3020         }
    3021
    3022         try {
    3023             value =
    3024                     PropertyUtils.getMappedProperty(bean,
    3025                             "mappedProperty(Fifth Key)");
    3026             assertEquals("Can find fifth value", "Fifth Value", value);
    3027         } catch (Throwable t) {
    3028             fail("Finding fifth value threw " + t);
    3029         }
    3030
    3031         // Use key expression with dotted expression
    3032
    3033         try {
    3034             value =
    3035                     PropertyUtils.getNestedProperty(bean,
    3036                             "mapProperty.Sixth Key");
    3037             assertNull("Can not find sixth value", value);
    3038         } catch (Throwable t) {
    3039             fail("Finding fifth value threw " + t);
    3040         }
    3041
    3042         try {
    3043             PropertyUtils.setNestedProperty(bean,
    3044                     "mapProperty.Sixth Key",
    3045                     "Sixth Value");
    3046         } catch (Throwable t) {
    3047             fail("Setting sixth value threw " + t);
    3048         }
    3049
    3050         try {
    3051             value =
    3052                     PropertyUtils.getNestedProperty(bean,
    3053                             "mapProperty.Sixth Key");
    3054             assertEquals("Can find sixth value", "Sixth Value", value);
    3055         } catch (Throwable t) {
    3056             fail("Finding sixth value threw " + t);
    3057         }
    3058
    3059     }
    3060
    3061     /***
    3062      * Test setting mapped values with periods in the key.
    3063      */
    3064     public void testSetMappedPeriods() {
    3065
    3066
    3067         // -------- PropertyUtils.setMappedProperty()--------
    3068         bean.setMappedProperty("key.with.a.dot", "Special Value");
    3069         assertEquals("Can retrieve directly (A)",
    3070                      "Special Value",
    3071                      bean.getMappedProperty("key.with.a.dot"));
    3072
    3073         try {
    3074             PropertyUtils.setMappedProperty(bean, "mappedProperty", "key.with.a.dot", "Updated Special Value");
    3075             assertEquals("Check set via setMappedProperty",
    3076                          "Updated Special Value",
    3077                           bean.getMappedProperty("key.with.a.dot"));
    3078         } catch (Exception e) {
    3079             fail("Thew exception: " + e);
    3080         }
    3081
    3082         // -------- PropertyUtils.setNestedProperty() --------
    3083         bean.setMappedProperty("key.with.a.dot", "Special Value");
    3084         assertEquals("Can retrieve directly (B)",
    3085                      "Special Value",
    3086                      bean.getMappedProperty("key.with.a.dot"));
    3087         try {
    3088             PropertyUtils.setNestedProperty(bean, "mappedProperty(key.with.a.dot)", "Updated Special Value");
    3089             assertEquals("Check set via setNestedProperty (B)",
    3090                          "Updated Special Value",
    3091                          bean.getMappedProperty("key.with.a.dot"));
    3092         } catch (Exception e) {
    3093             fail("Thew exception: " + e);
    3094         }
    3095
    3096
    3097         // -------- PropertyUtils.setNestedProperty() --------
    3098         TestBean testBean = new TestBean();
    3099         bean.setMappedObjects("nested.property", testBean);
    3100         assertEquals("Can retrieve directly (C)",
    3101                      "This is a string",
    3102                      testBean.getStringProperty());
    3103         try {
    3104             PropertyUtils.setNestedProperty(bean, "mappedObjects(nested.property).stringProperty",
    3105                                                   "Updated String Value");
    3106             assertEquals("Check set via setNestedProperty (C)",
    3107                          "Updated String Value",
    3108                          testBean.getStringProperty());
    3109         } catch (Exception e) {
    3110             fail("Thew exception: " + e);
    3111         }
    3112
    3113         // -------- PropertyUtils.setNestedProperty() --------
    3114         bean.getNested().setMappedProperty("Mapped Key", "Nested Mapped Value");
    3115         try {
    3116             assertEquals("Can retrieve via getNestedProperty (D)",
    3117                          "Nested Mapped Value",
    3118                          PropertyUtils.getNestedProperty(
    3119                              bean,"nested.mappedProperty(Mapped Key)"));
    3120             PropertyUtils.setNestedProperty(bean, "nested.mappedProperty(Mapped Key)",
    3121                                                   "Updated Nested Mapped Value");
    3122             assertEquals("Check set via setNestedProperty (D)",
    3123                          "Updated Nested Mapped Value",
    3124                          PropertyUtils.getNestedProperty(
    3125                              bean,"nested.mappedProperty(Mapped Key)"));
    3126         } catch (Exception e) {
    3127             fail("Thew exception: " + e);
    3128         }
    3129     }
    3130
    3131
    3132     /***
    3133      * Corner cases on setNestedProperty invalid arguments.
    3134      */
    3135     public void testSetNestedArguments() {
    3136
    3137         try {
    3138             PropertyUtils.setNestedProperty(null, "stringProperty", "");
    3139             fail("Should throw IllegalArgumentException 1");
    3140         } catch (IllegalArgumentException e) {
    3141             // Expected response
    3142         } catch (Throwable t) {
    3143             fail("Threw " + t + " instead of IllegalArgumentException 1");
    3144         }
    3145
    3146         try {
    3147             PropertyUtils.setNestedProperty(bean, null, "");
    3148             fail("Should throw IllegalArgumentException 2");
    3149         } catch (IllegalArgumentException e) {
    3150             // Expected response
    3151         } catch (Throwable t) {
    3152             fail("Threw " + t + " instead of IllegalArgumentException 2");
    3153         }
    3154
    3155     }
    3156
    3157
    3158     /***
    3159      * Test setNextedProperty on a boolean property.
    3160      */
    3161     public void testSetNestedBoolean() {
    3162
    3163         try {
    3164             boolean oldValue = bean.getNested().getBooleanProperty();
    3165             boolean newValue = !oldValue;
    3166             PropertyUtils.setNestedProperty(bean,
    3167                     "nested.booleanProperty",
    3168                     new Boolean(newValue));
    3169             assertTrue("Matched new value",
    3170                     newValue ==
    3171                     bean.getNested().getBooleanProperty());
    3172         } catch (IllegalAccessException e) {
    3173             fail("IllegalAccessException");
    3174         } catch (IllegalArgumentException e) {
    3175             fail("IllegalArgumentException");
    3176         } catch (InvocationTargetException e) {
    3177             fail("InvocationTargetException");
    3178         } catch (NoSuchMethodException e) {
    3179             fail("NoSuchMethodException");
    3180         }
    3181
    3182     }
    3183
    3184
    3185     /***
    3186      * Test setNestedProperty on a double property.
    3187      */
    3188     public void testSetNestedDouble() {
    3189
    3190         try {
    3191             double oldValue = bean.getNested().getDoubleProperty();
    3192             double newValue = oldValue + 1.0;
    3193             PropertyUtils.setNestedProperty(bean,
    3194                     "nested.doubleProperty",
    3195                     new Double(newValue));
    3196             assertEquals("Matched new value",
    3197                     newValue,
    3198                     bean.getNested().getDoubleProperty(),
    3199                     0.005);
    3200         } catch (IllegalAccessException e) {
    3201             fail("IllegalAccessException");
    3202         } catch (IllegalArgumentException e) {
    3203             fail("IllegalArgumentException");
    3204         } catch (InvocationTargetException e) {
    3205             fail("InvocationTargetException");
    3206         } catch (NoSuchMethodException e) {
    3207             fail("NoSuchMethodException");
    3208         }
    3209
    3210     }
    3211
    3212
    3213     /***
    3214      * Test setNestedProperty on a float property.
    3215      */
    3216     public void testSetNestedFloat() {
    3217
    3218         try {
    3219             float oldValue = bean.getNested().getFloatProperty();
    3220             float newValue = oldValue + (float) 1.0;
    3221             PropertyUtils.setNestedProperty(bean,
    3222                     "nested.floatProperty",
    3223                     new Float(newValue));
    3224             assertEquals("Matched new value",
    3225                     newValue,
    3226                     bean.getNested().getFloatProperty(),
    3227                     (float) 0.005);
    3228         } catch (IllegalAccessException e) {
    3229             fail("IllegalAccessException");
    3230         } catch (IllegalArgumentException e) {
    3231             fail("IllegalArgumentException");
    3232         } catch (InvocationTargetException e) {
    3233             fail("InvocationTargetException");
    3234         } catch (NoSuchMethodException e) {
    3235             fail("NoSuchMethodException");
    3236         }
    3237
    3238     }
    3239
    3240
    3241     /***
    3242      * Test setNestedProperty on a int property.
    3243      */
    3244     public void testSetNestedInt() {
    3245
    3246         try {
    3247             int oldValue = bean.getNested().getIntProperty();
    3248             int newValue = oldValue + 1;
    3249             PropertyUtils.setNestedProperty(bean,
    3250                     "nested.intProperty",
    3251                     new Integer(newValue));
    3252             assertEquals("Matched new value",
    3253                     newValue,
    3254                     bean.getNested().getIntProperty());
    3255         } catch (IllegalAccessException e) {
    3256             fail("IllegalAccessException");
    3257         } catch (IllegalArgumentException e) {
    3258             fail("IllegalArgumentException");
    3259         } catch (InvocationTargetException e) {
    3260             fail("InvocationTargetException");
    3261         } catch (NoSuchMethodException e) {
    3262             fail("NoSuchMethodException");
    3263         }
    3264
    3265     }
    3266
    3267
    3268     /***
    3269      * Test setNestedProperty on a long property.
    3270      */
    3271     public void testSetNestedLong() {
    3272
    3273         try {
    3274             long oldValue = bean.getNested().getLongProperty();
    3275             long newValue = oldValue + 1;
    3276             PropertyUtils.setNestedProperty(bean,
    3277                     "nested.longProperty",
    3278                     new Long(newValue));
    3279             assertEquals("Matched new value",
    3280                     newValue,
    3281                     bean.getNested().getLongProperty());
    3282         } catch (IllegalAccessException e) {
    3283             fail("IllegalAccessException");
    3284         } catch (IllegalArgumentException e) {
    3285             fail("IllegalArgumentException");
    3286         } catch (InvocationTargetException e) {
    3287             fail("InvocationTargetException");
    3288         } catch (NoSuchMethodException e) {
    3289             fail("NoSuchMethodException");
    3290         }
    3291
    3292     }
    3293
    3294
    3295     /***
    3296      * Test setNestedProperty on a read-only String property.
    3297      */
    3298     public void testSetNestedReadOnly() {
    3299
    3300         try {
    3301             String oldValue = bean.getNested().getWriteOnlyPropertyValue();
    3302             String newValue = oldValue + " Extra Value";
    3303             PropertyUtils.setNestedProperty(bean,
    3304                     "nested.readOnlyProperty",
    3305                     newValue);
    3306             fail("Should have thrown NoSuchMethodException");
    3307         } catch (IllegalAccessException e) {
    3308             fail("IllegalAccessException");
    3309         } catch (IllegalArgumentException e) {
    3310             fail("IllegalArgumentException");
    3311         } catch (InvocationTargetException e) {
    3312             fail("InvocationTargetException");
    3313         } catch (NoSuchMethodException e) {
    3314             // Correct result for this test
    3315         }
    3316
    3317     }
    3318
    3319
    3320     /***
    3321      * Test setNestedProperty on a short property.
    3322      */
    3323     public void testSetNestedShort() {
    3324
    3325         try {
    3326             short oldValue = bean.getNested().getShortProperty();
    3327             short newValue = oldValue;
    3328             newValue++;
    3329             PropertyUtils.setNestedProperty(bean,
    3330                     "nested.shortProperty",
    3331                     new Short(newValue));
    3332             assertEquals("Matched new value",
    3333                     newValue,
    3334                     bean.getNested().getShortProperty());
    3335         } catch (IllegalAccessException e) {
    3336             fail("IllegalAccessException");
    3337         } catch (IllegalArgumentException e) {
    3338             fail("IllegalArgumentException");
    3339         } catch (InvocationTargetException e) {
    3340             fail("InvocationTargetException");
    3341         } catch (NoSuchMethodException e) {
    3342             fail("NoSuchMethodException");
    3343         }
    3344
    3345     }
    3346
    3347
    3348     /***
    3349      * Test setNestedProperty on a String property.
    3350      */
    3351     public void testSetNestedString() {
    3352
    3353         try {
    3354             String oldValue = bean.getNested().getStringProperty();
    3355             String newValue = oldValue + " Extra Value";
    3356             PropertyUtils.setNestedProperty(bean,
    3357                     "nested.stringProperty",
    3358                     newValue);
    3359             assertEquals("Matched new value",
    3360                     newValue,
    3361                     bean.getNested().getStringProperty());
    3362         } catch (IllegalAccessException e) {
    3363             fail("IllegalAccessException");
    3364         } catch (IllegalArgumentException e) {
    3365             fail("IllegalArgumentException");
    3366         } catch (InvocationTargetException e) {
    3367             fail("InvocationTargetException");
    3368         } catch (NoSuchMethodException e) {
    3369             fail("NoSuchMethodException");
    3370         }
    3371
    3372     }
    3373
    3374
    3375     /***
    3376      * Test setNestedProperty on an unknown property name.
    3377      */
    3378     public void testSetNestedUnknown() {
    3379
    3380         try {
    3381             String newValue = "New String Value";
    3382             PropertyUtils.setNestedProperty(bean,
    3383                     "nested.unknown",
    3384                     newValue);
    3385             fail("Should have thrown NoSuchMethodException");
    3386         } catch (IllegalAccessException e) {
    3387             fail("IllegalAccessException");
    3388         } catch (IllegalArgumentException e) {
    3389             fail("IllegalArgumentException");
    3390         } catch (InvocationTargetException e) {
    3391             fail("InvocationTargetException");
    3392         } catch (NoSuchMethodException e) {
    3393             // Correct result for this test
    3394         }
    3395
    3396     }
    3397
    3398
    3399     /***
    3400      * Test setNestedProperty on a write-only String property.
    3401      */
    3402     public void testSetNestedWriteOnly() {
    3403
    3404         try {
    3405             String oldValue = bean.getNested().getWriteOnlyPropertyValue();
    3406             String newValue = oldValue + " Extra Value";
    3407             PropertyUtils.setNestedProperty(bean,
    3408                     "nested.writeOnlyProperty",
    3409                     newValue);
    3410             assertEquals("Matched new value",
    3411                     newValue,
    3412                     bean.getNested().getWriteOnlyPropertyValue());
    3413         } catch (IllegalAccessException e) {
    3414             fail("IllegalAccessException");
    3415         } catch (IllegalArgumentException e) {
    3416             fail("IllegalArgumentException");
    3417         } catch (InvocationTargetException e) {
    3418             fail("InvocationTargetException");
    3419         } catch (NoSuchMethodException e) {
    3420             fail("NoSuchMethodException");
    3421         }
    3422
    3423     }
    3424
    3425
    3426     /***
    3427      * Corner cases on setSimpleProperty invalid arguments.
    3428      */
    3429     public void testSetSimpleArguments() {
    3430
    3431         try {
    3432             PropertyUtils.setSimpleProperty(null, "stringProperty", "");
    3433             fail("Should throw IllegalArgumentException 1");
    3434         } catch (IllegalArgumentException e) {
    3435             // Expected response
    3436         } catch (Throwable t) {
    3437             fail("Threw " + t + " instead of IllegalArgumentException 1");
    3438         }
    3439
    3440         try {
    3441             PropertyUtils.setSimpleProperty(bean, null, "");
    3442             fail("Should throw IllegalArgumentException 2");
    3443         } catch (IllegalArgumentException e) {
    3444             // Expected response
    3445         } catch (Throwable t) {
    3446             fail("Threw " + t + " instead of IllegalArgumentException 2");
    3447         }
    3448
    3449     }
    3450
    3451
    3452     /***
    3453      * Test setSimpleProperty on a boolean property.
    3454      */
    3455     public void testSetSimpleBoolean() {
    3456
    3457         try {
    3458             boolean oldValue = bean.getBooleanProperty();
    3459             boolean newValue = !oldValue;
    3460             PropertyUtils.setSimpleProperty(bean,
    3461                     "booleanProperty",
    3462                     new Boolean(newValue));
    3463             assertTrue("Matched new value",
    3464                     newValue ==
    3465                     bean.getBooleanProperty());
    3466         } catch (IllegalAccessException e) {
    3467             fail("IllegalAccessException");
    3468         } catch (IllegalArgumentException e) {
    3469             fail("IllegalArgumentException");
    3470         } catch (InvocationTargetException e) {
    3471             fail("InvocationTargetException");
    3472         } catch (NoSuchMethodException e) {
    3473             fail("NoSuchMethodException");
    3474         }
    3475
    3476     }
    3477
    3478
    3479     /***
    3480      * Test setSimpleProperty on a double property.
    3481      */
    3482     public void testSetSimpleDouble() {
    3483
    3484         try {
    3485             double oldValue = bean.getDoubleProperty();
    3486             double newValue = oldValue + 1.0;
    3487             PropertyUtils.setSimpleProperty(bean,
    3488                     "doubleProperty",
    3489                     new Double(newValue));
    3490             assertEquals("Matched new value",
    3491                     newValue,
    3492                     bean.getDoubleProperty(),
    3493                     0.005);
    3494         } catch (IllegalAccessException e) {
    3495             fail("IllegalAccessException");
    3496         } catch (IllegalArgumentException e) {
    3497             fail("IllegalArgumentException");
    3498         } catch (InvocationTargetException e) {
    3499             fail("InvocationTargetException");
    3500         } catch (NoSuchMethodException e) {
    3501             fail("NoSuchMethodException");
    3502         }
    3503
    3504     }
    3505
    3506
    3507     /***
    3508      * Test setSimpleProperty on a float property.
    3509      */
    3510     public void testSetSimpleFloat() {
    3511
    3512         try {
    3513             float oldValue = bean.getFloatProperty();
    3514             float newValue = oldValue + (float) 1.0;
    3515             PropertyUtils.setSimpleProperty(bean,
    3516                     "floatProperty",
    3517                     new Float(newValue));
    3518             assertEquals("Matched new value",
    3519                     newValue,
    3520                     bean.getFloatProperty(),
    3521                     (float) 0.005);
    3522         } catch (IllegalAccessException e) {
    3523             fail("IllegalAccessException");
    3524         } catch (IllegalArgumentException e) {
    3525             fail("IllegalArgumentException");
    3526         } catch (InvocationTargetException e) {
    3527             fail("InvocationTargetException");
    3528         } catch (NoSuchMethodException e) {
    3529             fail("NoSuchMethodException");
    3530         }
    3531
    3532     }
    3533
    3534
    3535     /***
    3536      * Negative test setSimpleProperty on an indexed property.
    3537      */
    3538     public void testSetSimpleIndexed() {
    3539
    3540         try {
    3541             PropertyUtils.setSimpleProperty(bean,
    3542                     "stringIndexed[0]",
    3543                     "New String Value");
    3544             fail("Should have thrown IllegalArgumentException");
    3545         } catch (IllegalAccessException e) {
    3546             fail("IllegalAccessException");
    3547         } catch (IllegalArgumentException e) {
    3548             // Correct result for this test
    3549         } catch (InvocationTargetException e) {
    3550             fail("InvocationTargetException");
    3551         } catch (NoSuchMethodException e) {
    3552             fail("NoSuchMethodException");
    3553         }
    3554
    3555     }
    3556
    3557
    3558     /***
    3559      * Test setSimpleProperty on a int property.
    3560      */
    3561     public void testSetSimpleInt() {
    3562
    3563         try {
    3564             int oldValue = bean.getIntProperty();
    3565             int newValue = oldValue + 1;
    3566             PropertyUtils.setSimpleProperty(bean,
    3567                     "intProperty",
    3568                     new Integer(newValue));
    3569             assertEquals("Matched new value",
    3570                     newValue,
    3571                     bean.getIntProperty());
    3572         } catch (IllegalAccessException e) {
    3573             fail("IllegalAccessException");
    3574         } catch (IllegalArgumentException e) {
    3575             fail("IllegalArgumentException");
    3576         } catch (InvocationTargetException e) {
    3577             fail("InvocationTargetException");
    3578         } catch (NoSuchMethodException e) {
    3579             fail("NoSuchMethodException");
    3580         }
    3581
    3582     }
    3583
    3584
    3585     /***
    3586      * Test setSimpleProperty on a long property.
    3587      */
    3588     public void testSetSimpleLong() {
    3589
    3590         try {
    3591             long oldValue = bean.getLongProperty();
    3592             long newValue = oldValue + 1;
    3593             PropertyUtils.setSimpleProperty(bean,
    3594                     "longProperty",
    3595                     new Long(newValue));
    3596             assertEquals("Matched new value",
    3597                     newValue,
    3598                     bean.getLongProperty());
    3599         } catch (IllegalAccessException e) {
    3600             fail("IllegalAccessException");
    3601         } catch (IllegalArgumentException e) {
    3602             fail("IllegalArgumentException");
    3603         } catch (InvocationTargetException e) {
    3604             fail("InvocationTargetException");
    3605         } catch (NoSuchMethodException e) {
    3606             fail("NoSuchMethodException");
    3607         }
    3608
    3609     }
    3610
    3611
    3612     /***
    3613      * Negative test setSimpleProperty on a nested property.
    3614      */
    3615     public void testSetSimpleNested() {
    3616
    3617         try {
    3618             PropertyUtils.setSimpleProperty(bean,
    3619                     "nested.stringProperty",
    3620                     "New String Value");
    3621             fail("Should have thrown IllegalArgumentException");
    3622         } catch (IllegalAccessException e) {
    3623             fail("IllegalAccessException");
    3624         } catch (IllegalArgumentException e) {
    3625             // Correct result for this test
    3626         } catch (InvocationTargetException e) {
    3627             fail("InvocationTargetException");
    3628         } catch (NoSuchMethodException e) {
    3629             fail("NoSuchMethodException");
    3630         }
    3631
    3632     }
    3633
    3634
    3635     /***
    3636      * Test setSimpleProperty on a read-only String property.
    3637      */
    3638     public void testSetSimpleReadOnly() {
    3639
    3640         try {
    3641             String oldValue = bean.getWriteOnlyPropertyValue();
    3642             String newValue = oldValue + " Extra Value";
    3643             PropertyUtils.setSimpleProperty(bean,
    3644                     "readOnlyProperty",
    3645                     newValue);
    3646             fail("Should have thrown NoSuchMethodException");
    3647         } catch (IllegalAccessException e) {
    3648             fail("IllegalAccessException");
    3649         } catch (IllegalArgumentException e) {
    3650             fail("IllegalArgumentException");
    3651         } catch (InvocationTargetException e) {
    3652             fail("InvocationTargetException");
    3653         } catch (NoSuchMethodException e) {
    3654             // Correct result for this test
    3655             assertEquals("Property 'readOnlyProperty' has no setter method in class '" +
    3656                          bean.getClass() + "'", e.getMessage() );
    3657         }
    3658
    3659     }
    3660
    3661
    3662     /***
    3663      * Test setSimpleProperty on a short property.
    3664      */
    3665     public void testSetSimpleShort() {
    3666
    3667         try {
    3668             short oldValue = bean.getShortProperty();
    3669             short newValue = oldValue;
    3670             newValue++;
    3671             PropertyUtils.setSimpleProperty(bean,
    3672                     "shortProperty",
    3673                     new Short(newValue));
    3674             assertEquals("Matched new value",
    3675                     newValue,
    3676                     bean.getShortProperty());
    3677         } catch (IllegalAccessException e) {
    3678             fail("IllegalAccessException");
    3679         } catch (IllegalArgumentException e) {
    3680             fail("IllegalArgumentException");
    3681         } catch (InvocationTargetException e) {
    3682             fail("InvocationTargetException");
    3683         } catch (NoSuchMethodException e) {
    3684             fail("NoSuchMethodException");
    3685         }
    3686
    3687     }
    3688
    3689
    3690     /***
    3691      * Test setSimpleProperty on a String property.
    3692      */
    3693     public void testSetSimpleString() {
    3694
    3695         try {
    3696             String oldValue = bean.getStringProperty();
    3697             String newValue = oldValue + " Extra Value";
    3698             PropertyUtils.setSimpleProperty(bean,
    3699                     "stringProperty",
    3700                     newValue);
    3701             assertEquals("Matched new value",
    3702                     newValue,
    3703                     bean.getStringProperty());
    3704         } catch (IllegalAccessException e) {
    3705             fail("IllegalAccessException");
    3706         } catch (IllegalArgumentException e) {
    3707             fail("IllegalArgumentException");
    3708         } catch (InvocationTargetException e) {
    3709             fail("InvocationTargetException");
    3710         } catch (NoSuchMethodException e) {
    3711             fail("NoSuchMethodException");
    3712         }
    3713
    3714     }
    3715
    3716
    3717     /***
    3718      * Test setSimpleProperty on an unknown property name.
    3719      */
    3720     public void testSetSimpleUnknown() {
    3721
    3722         try {
    3723             String newValue = "New String Value";
    3724             PropertyUtils.setSimpleProperty(bean,
    3725                     "unknown",
    3726                     newValue);
    3727             fail("Should have thrown NoSuchMethodException");
    3728         } catch (IllegalAccessException e) {
    3729             fail("IllegalAccessException");
    3730         } catch (IllegalArgumentException e) {
    3731             fail("IllegalArgumentException");
    3732         } catch (InvocationTargetException e) {
    3733             fail("InvocationTargetException");
    3734         } catch (NoSuchMethodException e) {
    3735             // Correct result for this test
    3736             assertEquals("Unknown property 'unknown' on class '" +
    3737                          bean.getClass() + "'", e.getMessage() );
    3738         }
    3739
    3740     }
    3741
    3742
    3743     /***
    3744      * Test setSimpleProperty on a write-only String property.
    3745      */
    3746     public void testSetSimpleWriteOnly() {
    3747
    3748         try {
    3749             String oldValue = bean.getWriteOnlyPropertyValue();
    3750             String newValue = oldValue + " Extra Value";
    3751             PropertyUtils.setSimpleProperty(bean,
    3752                     "writeOnlyProperty",
    3753                     newValue);
    3754             assertEquals("Matched new value",
    3755                     newValue,
    3756                     bean.getWriteOnlyPropertyValue());
    3757         } catch (IllegalAccessException e) {
    3758             fail("IllegalAccessException");
    3759         } catch (IllegalArgumentException e) {
    3760             fail("IllegalArgumentException");
    3761         } catch (InvocationTargetException e) {
    3762             fail("InvocationTargetException");
    3763         } catch (NoSuchMethodException e) {
    3764             fail("NoSuchMethodException");
    3765         }
    3766
    3767     }
    3768
    3769
    3770     // ------------------------------------------------------ Protected Methods
    3771
    3772
    3773     /***
    3774      * Base for testGetDescriptorXxxxx() series of tests.
    3775      *
    3776      * @param name Name of the property to be retrieved
    3777      * @param read Expected name of the read method (or null)
    3778      * @param write Expected name of the write method (or null)
    3779      */
    3780     protected void testGetDescriptorBase(String name, String read,
    3781                                          String write) {
    3782
    3783         try {
    3784             PropertyDescriptor pd =
    3785                     PropertyUtils.getPropertyDescriptor(bean, name);
    3786             if ((read != null) || (write != null)) {
    3787                 assertNotNull("Got descriptor", pd);
    3788             } else {
    3789                 assertNull("Got descriptor", pd);
    3790                 return;
    3791             }
    3792             Method rm = pd.getReadMethod();
    3793             if (read != null) {
    3794                 assertNotNull("Got read method", rm);
    3795                 assertEquals("Got correct read method",
    3796                         rm.getName(), read);
    3797             } else {
    3798                 assertNull("Got read method", rm);
    3799             }
    3800             Method wm = pd.getWriteMethod();
    3801             if (write != null) {
    3802                 assertNotNull("Got write method", wm);
    3803                 assertEquals("Got correct write method",
    3804                         wm.getName(), write);
    3805             } else {
    3806                 assertNull("Got write method", wm);
    3807             }
    3808         } catch (IllegalAccessException e) {
    3809             fail("IllegalAccessException");
    3810         } catch (InvocationTargetException e) {
    3811             fail("InvocationTargetException");
    3812         } catch (NoSuchMethodException e) {
    3813             fail("NoSuchMethodException");
    3814         }
    3815
    3816     }
    3817
    3818
    3819     /***
    3820      * Base for testGetReadMethod() series of tests.
    3821      *
    3822      * @param bean Bean for which to retrieve read methods.
    3823      * @param properties Property names to search for
    3824      * @param className Class name where this method should be defined
    3825      */
    3826     protected void testGetReadMethod(Object bean, String properties[],
    3827                                      String className) {
    3828
    3829         PropertyDescriptor pd[] =
    3830                 PropertyUtils.getPropertyDescriptors(bean);
    3831         for (int i = 0; i < properties.length; i++) {
    3832
    3833             // Identify the property descriptor for this property
    3834             if (properties[i].equals("intIndexed"))
    3835                 continue;
    3836             if (properties[i].equals("stringIndexed"))
    3837                 continue;
    3838             if (properties[i].equals("writeOnlyProperty"))
    3839                 continue;
    3840             int n = -1;
    3841             for (int j = 0; j < pd.length; j++) {
    3842                 if (properties[i].equals(pd[j].getName())) {
    3843                     n = j;
    3844                     break;
    3845                 }
    3846             }
    3847             assertTrue("PropertyDescriptor for " + properties[i],
    3848                     n >= 0);
    3849
    3850             // Locate an accessible property reader method for it
    3851             Method reader = PropertyUtils.getReadMethod(pd[n]);
    3852             assertNotNull("Reader for " + properties[i],
    3853                     reader);
    3854             Class clazz = reader.getDeclaringClass();
    3855             assertNotNull("Declaring class for " + properties[i],
    3856                     clazz);
    3857             assertEquals("Correct declaring class for " + properties[i],
    3858                     clazz.getName(),
    3859                     className);
    3860
    3861             // Actually call the reader method we received
    3862             try {
    3863                 reader.invoke(bean, new Class[0]);
    3864             } catch (Throwable t) {
    3865                 fail("Call for " + properties[i] + ": " + t);
    3866             }
    3867
    3868         }
    3869
    3870     }
    3871
    3872
    3873     /***
    3874      * Base for testGetWriteMethod() series of tests.
    3875      *
    3876      * @param bean Bean for which to retrieve write methods.
    3877      * @param properties Property names to search for
    3878      * @param className Class name where this method should be defined
    3879      */
    3880     protected void testGetWriteMethod(Object bean, String properties[],
    3881                                       String className) {
    3882
    3883
    3884         PropertyDescriptor pd[] =
    3885                 PropertyUtils.getPropertyDescriptors(bean);
    3886         for (int i = 0; i < properties.length; i++) {
    3887
    3888             // Identify the property descriptor for this property
    3889             if (properties[i].equals("intIndexed"))
    3890                 continue;
    3891             if (properties[i].equals("listIndexed"))
    3892                 continue;
    3893             if (properties[i].equals("nested"))
    3894                 continue; // This property is read only
    3895             if (properties[i].equals("readOnlyProperty"))
    3896                 continue;
    3897             if (properties[i].equals("stringIndexed"))
    3898                 continue;
    3899             int n = -1;
    3900             for (int j = 0; j < pd.length; j++) {
    3901                 if (properties[i].equals(pd[j].getName())) {
    3902                     n = j;
    3903                     break;
    3904                 }
    3905             }
    3906             assertTrue("PropertyDescriptor for " + properties[i],
    3907                     n >= 0);
    3908
    3909             // Locate an accessible property reader method for it
    3910             Method writer = PropertyUtils.getWriteMethod(pd[n]);
    3911             assertNotNull("Writer for " + properties[i],
    3912                     writer);
    3913             Class clazz = writer.getDeclaringClass();
    3914             assertNotNull("Declaring class for " + properties[i],
    3915                     clazz);
    3916             assertEquals("Correct declaring class for " + properties[i],
    3917                     clazz.getName(),
    3918                     className);
    3919
    3920         }
    3921
    3922     }
    3923
    3924     public void testNestedWithIndex() throws Exception
    3925     {
    3926         NestedTestBean nestedBean = new NestedTestBean("base");
    3927         nestedBean.init();
    3928         nestedBean.getSimpleBeanProperty().init();
    3929
    3930         NestedTestBean
    3931
    3932         // test first calling properties on indexed beans
    3933
    3934         value = (NestedTestBean) PropertyUtils.getProperty(
    3935                                 nestedBean,
    3936                                 "indexedProperty[0]");
    3937         assertEquals("Cannot get simple index(1)", "Bean@0", value.getName());
    3938         assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
    3939
    3940         value = (NestedTestBean) PropertyUtils.getProperty(
    3941                                 nestedBean,
    3942                                 "indexedProperty[1]");
    3943         assertEquals("Cannot get simple index(1)", "Bean@1", value.getName());
    3944         assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
    3945
    3946         String
    3947         prop = (String) PropertyUtils.getProperty(
    3948                                 nestedBean,
    3949                                 "indexedProperty[0].testString");
    3950         assertEquals("Get property on indexes failed (1)", "NOT SET", prop);
    3951
    3952         prop = (String) PropertyUtils.getProperty(
    3953                                 nestedBean,
    3954                                 "indexedProperty[1].testString");
    3955         assertEquals("Get property on indexes failed (2)", "NOT SET", prop);
    3956
    3957         PropertyUtils.setProperty(
    3958                                 nestedBean,
    3959                                 "indexedProperty[0].testString",
    3960                                 "Test#1");
    3961         assertEquals(
    3962                 "Cannot set property on indexed bean (1)",
    3963                 "Test#1",
    3964                 nestedBean.getIndexedProperty(0).getTestString());
    3965
    3966         PropertyUtils.setProperty(
    3967                                 nestedBean,
    3968                                 "indexedProperty[1].testString",
    3969                                 "Test#2");
    3970         assertEquals(
    3971                 "Cannot set property on indexed bean (2)",
    3972                 "Test#2",
    3973                 nestedBean.getIndexedProperty(1).getTestString());
    3974
    3975
    3976         // test first calling indexed properties on a simple property
    3977
    3978         value = (NestedTestBean) PropertyUtils.getProperty(
    3979                                 nestedBean,
    3980                                 "simpleBeanProperty");
    3981         assertEquals("Cannot get simple bean", "Simple Property Bean", value.getName());
    3982         assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
    3983
    3984         value = (NestedTestBean) PropertyUtils.getProperty(
    3985                                 nestedBean,
    3986                                 "simpleBeanProperty.indexedProperty[3]");
    3987         assertEquals("Cannot get index property on property", "Bean@3", value.getName());
    3988         assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
    3989
    3990         PropertyUtils.setProperty(
    3991                                 nestedBean,
    3992                                 "simpleBeanProperty.indexedProperty[3].testString",
    3993                                 "Test#3");
    3994         assertEquals(
    3995             "Cannot set property on indexed property on property",
    3996             "Test#3",
    3997             nestedBean.getSimpleBeanProperty().getIndexedProperty(3).getTestString());
    3998     }
    3999
    4000     /*** Text case for setting properties on inner classes */
    4001     public void testGetSetInnerBean() throws Exception {
    4002         BeanWithInnerBean bean = new BeanWithInnerBean();
    4003
    4004         PropertyUtils.setProperty(bean, "innerBean.fish(loiterTimer)", "5");
    4005         String out = (String) PropertyUtils.getProperty(bean.getInnerBean(), "fish(loiterTimer)");
    4006         assertEquals(
    4007                 "(1) Inner class property set/get property failed.",
    4008                 "5",
    4009                 out);
    4010
    4011         out = (String) PropertyUtils.getProperty(bean, "innerBean.fish(loiterTimer)");
    4012
    4013         assertEquals(
    4014                 "(2) Inner class property set/get property failed.",
    4015                 "5",
    4016                 out);
    4017     }
    4018
    4019     /*** Text case for setting properties on parent */
    4020     public void testGetSetParentBean() throws Exception {
    4021
    4022         SonOfAlphaBean bean = new SonOfAlphaBean("Roger");
    4023
    4024         String out = (String) PropertyUtils.getProperty(bean, "name");
    4025         assertEquals(
    4026                 "(1) Get/Set On Parent.",
    4027                 "Roger",
    4028                 out);
    4029
    4030         PropertyUtils.setProperty(bean, "name", "abcd");
    4031         assertEquals(
    4032                 "(2) Get/Set On Parent.",
    4033                 "abcd",
    4034                 bean.getName());
    4035     }
    4036
    4037     public void testSetNoGetter() throws Exception
    4038     {
    4039         BetaBean bean = new BetaBean("Cedric");
    4040
    4041         // test standard no getter
    4042         bean.setNoGetterProperty("Sigma");
    4043         assertEquals("BetaBean test failed", "Sigma", bean.getSecret());
    4044
    4045         assertNotNull("Descriptor is null", PropertyUtils.getPropertyDescriptor(bean, "noGetterProperty"));
    4046
    4047         BeanUtils.setProperty(bean, "noGetterProperty",  "Omega");
    4048         assertEquals("Cannot set no-getter property", "Omega", bean.getSecret());
    4049
    4050         // test mapped no getter descriptor
    4051         MappedPropertyDescriptor descriptor
    4052             = new MappedPropertyDescriptor("noGetterMappedProperty", BetaBean.class);
    4053
    4054         assertNotNull("Map Descriptor is null", PropertyUtils.getPropertyDescriptor(bean, "noGetterMappedProperty"));
    4055
    4056         PropertyUtils.setMappedProperty(bean, "noGetterMappedProperty",  "Epsilon", "Epsilon");
    4057         assertEquals("Cannot set mapped no-getter property", "MAP:Epsilon", bean.getSecret());
    4058     }
    4059
    4060     /***
    4061      * There is an issue in setNestedProperty/getNestedProperty when the
    4062      * target bean is a map and the name string requests mapped or indexed
    4063      * operations on a field. These are not supported for fields of a Map,
    4064      * but it's an easy mistake to make and this test case ensures that an
    4065      * appropriate exception is thrown when a user does this.
    4066      * <p>
    4067      * The problem is with passing strings of form "a(b)" or "a[3]" to
    4068      * setNestedProperty or getNestedProperty when the target bean they
    4069      * are applied to implements Map. These strings are actually requesting
    4070      * "the result of calling mapped method a on the target object with
    4071      * a parameter of b" or "the result of calling indexed method a on the
    4072      * target object with a parameter of 3". And these requests are not valid
    4073      * when the target is a Map as a Map only supports calling get(fieldName)
    4074      * or put(fieldName), neither of which can be further indexed with a
    4075      * string or an integer.
    4076      * <p>
    4077      * However it is likely that some users will assume that "a[3]" when applied
    4078      * to a map will be equivalent to (map.get("a"))[3] with the appropriate
    4079      * typecasting, or for "a(b)" to be equivalent to map.get("a").get("b").
    4080      * <p>
    4081      * Here we verify that an exception is thrown if the user makes this
    4082      * mistake.
    4083      */
    4084     public void testNestedPropertyKeyOrIndexOnBeanImplementingMap() throws Exception {
    4085         HashMap map = new HashMap();
    4086         HashMap submap = new HashMap();
    4087         BetaBean betaBean1 = new BetaBean("test1");
    4088         BetaBean betaBean2 = new BetaBean("test2");
    4089
    4090         // map.put("submap", submap)
    4091         PropertyUtils.setNestedProperty(map, "submap", submap);
    4092
    4093         // map.get("submap").put("beta1", betaBean1)
    4094         PropertyUtils.setNestedProperty(map, "submap.beta1", betaBean1);
    4095         assertEquals("Unexpected keys in map", "submap", keysToString(map));
    4096         assertEquals("Unexpected keys in submap", "beta1", keysToString(submap));
    4097
    4098         try {
    4099             // One would expect that the command below would be equivalent to
    4100             //   Map m = (Map) map.get("submap");
    4101             //   m.put("beta2", betaBean2)
    4102             // However this isn't how javabeans property methods work. A map
    4103             // only effectively has "simple" properties, even when the
    4104             // returned object is a Map or Array.
    4105             PropertyUtils.setNestedProperty(map, "submap(beta2)", betaBean2);
    4106
    4107             // What, no exception? In that case, setNestedProperties has
    4108             // probably just tried to do
    4109             //    map.set("submap(beta2)", betaBean2)
    4110             // which is almost certainly not what the used expected. This is
    4111             // what beanutils 1.5.0 to 1.7.1 did....
    4112             fail("Exception not thrown for invalid setNestedProperty syntax");
    4113         } catch(IllegalArgumentException ex) {
    4114             // ok, getting an exception was expected. As it is of a generic
    4115             // type, let's check the message string to make sure it really
    4116             // was caused by the issue we expected.
    4117             int index = ex.getMessage().indexOf(
    4118                     "Indexed or mapped properties are not supported");
    4119             assertTrue("Unexpected exception message", index>=0);
    4120         }
    4121
    4122         try {
    4123             // One would expect that "submap[3]" would be equivalent to
    4124             //   Object[] objects = (Object[]) map.get("submap");
    4125             //   return objects[3];
    4126             // However this isn't how javabeans property methods work. A map
    4127             // only effectively has "simple" properties, even when the
    4128             // returned object is a Map or Array.
    4129             Object o = PropertyUtils.getNestedProperty(map, "submap[3]");
    4130
    4131             // What, no exception? In that case, getNestedProperties has
    4132             // probably just tried to do
    4133             //    map.get("submap[3]")
    4134             // which is almost certainly not what the used expected. This is
    4135             // what beanutils 1.5.0 to 1.7.1 did....
    4136             fail("Exception not thrown for invalid setNestedProperty syntax");
    4137         } catch(IllegalArgumentException ex) {
    4138             // ok, getting an exception was expected. As it is of a generic
    4139             // type, let's check the message string to make sure it really
    4140             // was caused by the issue we expected.
    4141             int index = ex.getMessage().indexOf(
    4142                     "Indexed or mapped properties are not supported");
    4143             assertTrue("Unexpected exception message", index>=0);
    4144         }
    4145     }
    4146
    4147     /***
    4148      * Returns a single string containing all the keys in the map,
    4149      * sorted in alphabetical order and separated by ", ".
    4150      * <p>
    4151      * If there are no keys, an empty string is returned.
    4152      */
    4153     private String keysToString(Map map) {
    4154         Object[] mapKeys = map.keySet().toArray();
    4155         java.util.Arrays.sort(mapKeys);
    4156         StringBuffer buf = new StringBuffer();
    4157         for(int i=0; i<mapKeys.length; ++i) {
    4158             if (i != 0)
    4159                 buf.append(", ");
    4160             buf.append(mapKeys[i]);
    4161         }
    4162         return buf.toString();
    4163     }
    4164
    4165     /***
    4166      * This tests to see that classes that implement Map always have their
    4167      * custom properties ignored.
    4168      * <p>
    4169      * Note that this behaviour has changed several times over past releases
    4170      * of beanutils, breaking backwards compatibility each time. Here's hoping
    4171      * that the current 1.7.1 release is the last time this behaviour changes!
    4172      */
    4173     public void testMapExtensionDefault() throws Exception {
    4174         ExtendMapBean bean = new ExtendMapBean();
    4175
    4176         // setting property direct should work, and not affect map
    4177         bean.setUnusuallyNamedProperty("bean value");
    4178         assertEquals("Set property direct failed", "bean value", bean.getUnusuallyNamedProperty());
    4179         assertNull("Get on unset map property failed",
    4180                 PropertyUtils.getNestedProperty(bean, "unusuallyNamedProperty"));
    4181
    4182         // setting simple property should call the setter method only, and not
    4183         // affect the map.
    4184         PropertyUtils.setSimpleProperty(bean, "unusuallyNamedProperty", "new value");
    4185         assertEquals("Set property on map failed (1)", "new value", bean.getUnusuallyNamedProperty());
    4186         assertNull("Get on unset map property failed",
    4187                 PropertyUtils.getNestedProperty(bean, "unusuallyNamedProperty"));
    4188
    4189         // setting via setNestedProperty should affect the map only, and not
    4190         // call the setter method.
    4191         PropertyUtils.setProperty(bean, "unusuallyNamedProperty", "next value");
    4192         assertEquals(
    4193                 "setNestedProperty on map not visible to getNestedProperty",
    4194                 "next value",
    4195                 PropertyUtils.getNestedProperty(bean, "unusuallyNamedProperty"));
    4196         assertEquals(
    4197             "Set nested property on map unexpected affected simple property",
    4198             "new value",
    4199             bean.getUnusuallyNamedProperty());
    4200     }
    4201
    4202     /***
    4203      * This tests to see that it is possible to subclass PropertyUtilsBean
    4204      * and change the behaviour of setNestedProperty/getNestedProperty when
    4205      * dealing with objects that implement Map.
    4206      */
    4207     public void testMapExtensionCustom() throws Exception {
    4208         PropsFirstPropertyUtilsBean utilsBean = new PropsFirstPropertyUtilsBean();
    4209         ExtendMapBean bean = new ExtendMapBean();
    4210
    4211         // hardly worth testing this, really :-)
    4212         bean.setUnusuallyNamedProperty("bean value");
    4213         assertEquals("Set property direct failed", "bean value", bean.getUnusuallyNamedProperty());
    4214
    4215         // setSimpleProperty should affect the simple property
    4216         utilsBean.setSimpleProperty(bean, "unusuallyNamedProperty", "new value");
    4217         assertEquals("Set property on map failed (1)", "new value", bean.getUnusuallyNamedProperty());
    4218
    4219         // setNestedProperty with setter should affect the simple property
    4220         // getNestedProperty with getter should obtain the simple property
    4221         utilsBean.setProperty(bean, "unusuallyNamedProperty", "next value");
    4222         assertEquals("Set property on map failed (2)", "next value", bean.getUnusuallyNamedProperty());
    4223         assertEquals("setNestedProperty on non-simple property failed",
    4224                 "next value",
    4225                 utilsBean.getNestedProperty(bean, "unusuallyNamedProperty"));
    4226
    4227         // setting property without setter should update the map
    4228         // getting property without setter should fetch from the map
    4229         utilsBean.setProperty(bean, "mapProperty", "value1");
    4230         assertEquals("setNestedProperty on non-simple property failed",
    4231                 "value1", utilsBean.getNestedProperty(bean, "mapProperty"));
    4232
    4233         HashMap myMap = new HashMap();
    4234         myMap.put("thebean", bean);
    4235         utilsBean.getNestedProperty(myMap, "thebean.mapitem");
    4236         utilsBean.getNestedProperty(myMap, "thebean(mapitem)");
    4237     }
    4238
    4239     /***
    4240      * Test {@link PropertyUtilsBean}'s invoke method throwing an IllegalArgumentException
    4241      * and check that the "cause" has been properly initialized for JDK 1.4+
    4242      * See BEANUTILS-266 for changes and reason for test
    4243      */
    4244     public void testExceptionFromInvoke() throws Exception {
    4245         if (isPre14JVM()) {
    4246             return;
    4247         }
    4248         try {
    4249             PropertyUtils.setSimpleProperty(bean, "intProperty","XXX");
    4250         } catch(IllegalArgumentException t) {
    4251             Throwable cause = (Throwable)PropertyUtils.getProperty(t, "cause");
    4252             assertNotNull("Cause not found", cause);
    4253             assertTrue("Expected cause to be IllegalArgumentException, but was: " + cause.getClass(),
    4254                     cause instanceof IllegalArgumentException);
    4255             // JDK 1.6 doesn't have "argument type mismatch" message
    4256             // assertEquals("Check error message", "argument type mismatch", cause.getMessage());
    4257         } catch(Throwable t) {
    4258             fail("Expected IllegalArgumentException, but threw " + t);
    4259         }
    4260     }
    4261
    4262     /***
    4263      * Test for JDK 1.4
    4264      */
    4265     private boolean isPre14JVM() {
    4266         String version = System.getProperty("java.specification.version");
    4267         StringTokenizer tokenizer = new StringTokenizer(version,".");
    4268         if (tokenizer.nextToken().equals("1")) {
    4269             String minorVersion = tokenizer.nextToken();
    4270             if (minorVersion.equals("0")) return true;
    4271             if (minorVersion.equals("1")) return true;
    4272             if (minorVersion.equals("2")) return true;
    4273             if (minorVersion.equals("3")) return true;
    4274         }
    4275         return false;
    4276     }
    4277 }