    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  package org.apache.commons.configuration.beanutils;
    18
    19  import java.util.HashMap;
    20  import java.util.Iterator;
    21  import java.util.Map;
    22
    23  import org.apache.commons.configuration.ConfigurationRuntimeException;
    24
    25  import junit.framework.TestCase;
    26
    27  /***
    28   * Test class for BeanHelper.
    29   *
    30   * @since 1.3
    31   * @author Oliver Heger
    32   * @version $Id: TestBeanHelper.java 439648 2006-09-02 20:42:10Z oheger $
    33   */
    34  public class TestBeanHelper extends TestCase
    35  {
    36      /*** Constant for the name of the test bean factory. */
    37      private static final String TEST_FACTORY = "testFactory";
    38
    39      /***
    40       * Stores the default bean factory. Because this is a static field in
    41       * BeanHelper it is temporarily stored and reset after the tests.
    42       */
    43      private BeanFactory tempDefaultBeanFactory;
    44
    45      protected void setUp() throws Exception
    46      {
    47          super.setUp();
    48          tempDefaultBeanFactory = BeanHelper.getDefaultBeanFactory();
    49      }
    50
    51      protected void tearDown() throws Exception
    52      {
    53          // Remove all bean factories that might have been registered
    54          for (Iterator it = BeanHelper.registeredFactoryNames().iterator(); it
    55                  .hasNext();)
    56          {
    57              BeanHelper.deregisterBeanFactory((String) it.next());
    58          }
    59          assertTrue("Remaining registered bean factories", BeanHelper
    60                  .registeredFactoryNames().isEmpty());
    61
    62          // Reset old default bean factory
    63          BeanHelper.setDefaultBeanFactory(tempDefaultBeanFactory);
    64
    65          super.tearDown();
    66      }
    67
    68      /***
    69       * Tests registering a new bean factory.
    70       */
    71      public void testRegisterBeanFactory()
    72      {
    73          assertTrue("List of registered factories is not empty", BeanHelper
    74                  .registeredFactoryNames().isEmpty());
    75          BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
    76          assertEquals("Wrong number of registered factories", 1, BeanHelper
    77                  .registeredFactoryNames().size());
    78          assertTrue("Test factory is not contained", BeanHelper
    79                  .registeredFactoryNames().contains(TEST_FACTORY));
    80      }
    81
    82      /***
    83       * Tries to register a null factory. This should cause an exception.
    84       */
    85      public void testRegisterBeanFactoryNull()
    86      {
    87          try
    88          {
    89              BeanHelper.registerBeanFactory(TEST_FACTORY, null);
    90              fail("Could register null factory!");
    91          }
    92          catch (IllegalArgumentException iex)
    93          {
    94              // ok
    95          }
    96      }
    97
    98      /***
    99       * Tries to register a bean factory with a null name. This should cause an
    100      * exception.
    101      */
    102     public void testRegisterBeanFactoryNullName()
    103     {
    104         try
    105         {
    106             BeanHelper.registerBeanFactory(null, new TestBeanFactory());
    107             fail("Could register factory with null name!");
    108         }
    109         catch (IllegalArgumentException iex)
    110         {
    111             // ok
    112         }
    113     }
    114
    115     /***
    116      * Tests to deregister a bean factory.
    117      */
    118     public void testDeregisterBeanFactory()
    119     {
    120         assertNull("deregistering non existing factory", BeanHelper
    121                 .deregisterBeanFactory(TEST_FACTORY));
    122         assertNull("deregistering null factory", BeanHelper
    123                 .deregisterBeanFactory(null));
    124         BeanFactory factory = new TestBeanFactory();
    125         BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
    126         assertSame("Could not deregister factory", factory, BeanHelper
    127                 .deregisterBeanFactory(TEST_FACTORY));
    128         assertTrue("List of factories is not empty", BeanHelper
    129                 .registeredFactoryNames().isEmpty());
    130     }
    131
    132     /***
    133      * Tests whether the default bean factory is correctly initialized.
    134      */
    135     public void testGetDefaultBeanFactory()
    136     {
    137         assertSame("Incorrect default bean factory",
    138                 DefaultBeanFactory.INSTANCE, tempDefaultBeanFactory);
    139     }
    140
    141     /***
    142      * Tests setting the default bean factory to null. This should caus an
    143      * exception.
    144      */
    145     public void testSetDefaultBeanFactoryNull()
    146     {
    147         try
    148         {
    149             BeanHelper.setDefaultBeanFactory(null);
    150             fail("Could set default bean factory to null!");
    151         }
    152         catch (IllegalArgumentException iex)
    153         {
    154             // ok
    155         }
    156     }
    157
    158     /***
    159      * Tests initializing a bean.
    160      */
    161     public void testInitBean()
    162     {
    163         BeanHelper.setDefaultBeanFactory(new TestBeanFactory());
    164         TestBeanDeclaration data = setUpBeanDeclaration();
    165         TestBean bean = new TestBean();
    166         BeanHelper.initBean(bean, data);
    167         checkBean(bean);
    168     }
    169
    170     /***
    171      * Tests initializing a bean when the bean declaration does not contain any
    172      * data.
    173      */
    174     public void testInitBeanWithNoData()
    175     {
    176         TestBeanDeclaration data = new TestBeanDeclaration();
    177         TestBean bean = new TestBean();
    178         BeanHelper.initBean(bean, data);
    179         assertNull("Wrong string property", bean.getStringValue());
    180         assertEquals("Wrong int property", 0, bean.getIntValue());
    181         assertNull("Buddy was set", bean.getBuddy());
    182     }
    183
    184     /***
    185      * Tries to initialize a bean with a bean declaration that contains an
    186      * invalid property value. This should cause an exception.
    187      */
    188     public void testInitBeanWithInvalidProperty()
    189     {
    190         TestBeanDeclaration data = setUpBeanDeclaration();
    191         data.getBeanProperties().put("nonExistingProperty", Boolean.TRUE);
    192         try
    193         {
    194             BeanHelper.initBean(new TestBean(), data);
    195             fail("Could initialize non existing property!");
    196         }
    197         catch (ConfigurationRuntimeException cex)
    198         {
    199             // ok
    200         }
    201     }
    202
    203     /***
    204      * Tests creating a bean. All necessary information is stored in the bean
    205      * declaration.
    206      */
    207     public void testCreateBean()
    208     {
    209         TestBeanFactory factory = new TestBeanFactory();
    210         BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
    211         TestBeanDeclaration data = setUpBeanDeclaration();
    212         data.setBeanFactoryName(TEST_FACTORY);
    213         data.setBeanClassName(TestBean.class.getName());
    214         checkBean((TestBean) BeanHelper.createBean(data, null));
    215         assertNull("A parameter was passed", factory.parameter);
    216     }
    217
    218     /***
    219      * Tests creating a bean when no bean declaration is provided. This should
    220      * cause an exception.
    221      */
    222     public void testCreateBeanWithNullDeclaration()
    223     {
    224         try
    225         {
    226             BeanHelper.createBean(null);
    227             fail("Could create bean with null declaration!");
    228         }
    229         catch (IllegalArgumentException iex)
    230         {
    231             // ok
    232         }
    233     }
    234
    235     /***
    236      * Tests creating a bean. The bean's class is specified as the default class
    237      * argument.
    238      */
    239     public void testCreateBeanWithDefaultClass()
    240     {
    241         BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
    242         TestBeanDeclaration data = setUpBeanDeclaration();
    243         data.setBeanFactoryName(TEST_FACTORY);
    244         checkBean((TestBean) BeanHelper.createBean(data, TestBean.class));
    245     }
    246
    247     /***
    248      * Tests creating a bean when the bean's class is specified as the default
    249      * class of the bean factory.
    250      */
    251     public void testCreateBeanWithFactoryDefaultClass()
    252     {
    253         TestBeanFactory factory = new TestBeanFactory();
    254         factory.supportsDefaultClass = true;
    255         BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
    256         TestBeanDeclaration data = setUpBeanDeclaration();
    257         data.setBeanFactoryName(TEST_FACTORY);
    258         checkBean((TestBean) BeanHelper.createBean(data, null));
    259     }
    260
    261     /***
    262      * Tries to create a bean when no class is provided. This should cause an
    263      * exception.
    264      */
    265     public void testCreateBeanWithNoClass()
    266     {
    267         BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
    268         TestBeanDeclaration data = setUpBeanDeclaration();
    269         data.setBeanFactoryName(TEST_FACTORY);
    270         try
    271         {
    272             BeanHelper.createBean(data, null);
    273             fail("Could create bean without class!");
    274         }
    275         catch (ConfigurationRuntimeException cex)
    276         {
    277             // ok
    278         }
    279     }
    280
    281     /***
    282      * Tries to create a bean with a non existing class. This should cause an
    283      * exception.
    284      */
    285     public void testCreateBeanWithInvalidClass()
    286     {
    287         BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
    288         TestBeanDeclaration data = setUpBeanDeclaration();
    289         data.setBeanFactoryName(TEST_FACTORY);
    290         data.setBeanClassName("non.existing.ClassName");
    291         try
    292         {
    293             BeanHelper.createBean(data, null);
    294             fail("Could create bean of an unexisting class!");
    295         }
    296         catch (ConfigurationRuntimeException cex)
    297         {
    298             // ok
    299         }
    300     }
    301
    302     /***
    303      * Tests creating a bean using the default bean factory.
    304      */
    305     public void testCreateBeanWithDefaultFactory()
    306     {
    307         BeanHelper.setDefaultBeanFactory(new TestBeanFactory());
    308         TestBeanDeclaration data = setUpBeanDeclaration();
    309         data.setBeanClassName(TestBean.class.getName());
    310         checkBean((TestBean) BeanHelper.createBean(data, null));
    311     }
    312
    313     /***
    314      * Tests creating a bean using a non registered factory.
    315      */
    316     public void testCreateBeanWithUnknownFactory()
    317     {
    318         TestBeanDeclaration data = setUpBeanDeclaration();
    319         data.setBeanFactoryName(TEST_FACTORY);
    320         data.setBeanClassName(TestBean.class.getName());
    321         try
    322         {
    323             BeanHelper.createBean(data, null);
    324             fail("Could create bean with non registered factory!");
    325         }
    326         catch (ConfigurationRuntimeException cex)
    327         {
    328             // ok
    329         }
    330     }
    331
    332     /***
    333      * Tests creating a bean when the factory throws an exception.
    334      */
    335     public void testCreateBeanWithException()
    336     {
    337         BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
    338         TestBeanDeclaration data = setUpBeanDeclaration();
    339         data.setBeanFactoryName(TEST_FACTORY);
    340         data.setBeanClassName(getClass().getName());
    341         try
    342         {
    343             BeanHelper.createBean(data, null);
    344             fail("Could create bean of wrong class!");
    345         }
    346         catch (ConfigurationRuntimeException cex)
    347         {
    348             // ok
    349         }
    350     }
    351
    352     /***
    353      * Tests if a parameter is correctly passed to the bean factory.
    354      */
    355     public void testCreateBeanWithParameter()
    356     {
    357         Object param = new Integer(42);
    358         TestBeanFactory factory = new TestBeanFactory();
    359         BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
    360         TestBeanDeclaration data = setUpBeanDeclaration();
    361         data.setBeanFactoryName(TEST_FACTORY);
    362         data.setBeanClassName(TestBean.class.getName());
    363         checkBean((TestBean) BeanHelper.createBean(data, null, param));
    364         assertSame("Wrong parameter", param, factory.parameter);
    365     }
    366
    367     /***
    368      * Returns an initialized bean declaration.
    369      *
    370      * @return the bean declaration
    371      */
    372     private TestBeanDeclaration setUpBeanDeclaration()
    373     {
    374         TestBeanDeclaration data = new TestBeanDeclaration();
    375         Map properties = new HashMap();
    376         properties.put("stringValue", "testString");
    377         properties.put("intValue", "42");
    378         data.setBeanProperties(properties);
    379         TestBeanDeclaration buddyData = new TestBeanDeclaration();
    380         Map properties2 = new HashMap();
    381         properties2.put("stringValue", "Another test string");
    382         properties2.put("intValue", new Integer(100));
    383         buddyData.setBeanProperties(properties2);
    384         buddyData.setBeanClassName(TestBean.class.getName());
    385         if (BeanHelper.getDefaultBeanFactory() == null)
    386         {
    387             buddyData.setBeanFactoryName(TEST_FACTORY);
    388         }
    389         Map nested = new HashMap();
    390         nested.put("buddy", buddyData);
    391         data.setNestedBeanDeclarations(nested);
    392         return data;
    393     }
    394
    395     /***
    396      * Tests if the bean was correctly initialized from the data of the test
    397      * bean declaration.
    398      *
    399      * @param bean the bean to be checked
    400      */
    401     private void checkBean(TestBean bean)
    402     {
    403         assertEquals("Wrong string property", "testString", bean
    404                 .getStringValue());
    405         assertEquals("Wrong int property", 42, bean.getIntValue());
    406         TestBean buddy = bean.getBuddy();
    407         assertNotNull("Buddy was not set", buddy);
    408         assertEquals("Wrong string property in buddy", "Another test string",
    409                 buddy.getStringValue());
    410         assertEquals("Wrong int property in buddy", 100, buddy.getIntValue());
    411     }
    412
    413     /***
    414      * A simple bean class used for testing creation operations.
    415      */
    416     public static class TestBean
    417     {
    418         private String stringValue;
    419
    420         private int intValue;
    421
    422         private TestBean buddy;
    423
    424         public TestBean getBuddy()
    425         {
    426             return buddy;
    427         }
    428
    429         public void setBuddy(TestBean buddy)
    430         {
    431             this.buddy = buddy;
    432         }
    433
    434         public int getIntValue()
    435         {
    436             return intValue;
    437         }
    438
    439         public void setIntValue(int intValue)
    440         {
    441             this.intValue = intValue;
    442         }
    443
    444         public String getStringValue()
    445         {
    446             return stringValue;
    447         }
    448
    449         public void setStringValue(String stringValue)
    450         {
    451             this.stringValue = stringValue;
    452         }
    453     }
    454
    455     /***
    456      * An implementation of the BeanFactory interface used for testing. This
    457      * implementation is really simple: If the TestBean class is provided, a new
    458      * instance will be created. Otherwise an exception is thrown.
    459      */
    460     static class TestBeanFactory implements BeanFactory
    461     {
    462         Object parameter;
    463
    464         boolean supportsDefaultClass;
    465
    466         public Object createBean(Class beanClass, BeanDeclaration data, Object param)
    467                 throws Exception
    468         {
    469             parameter = param;
    470             if (TestBean.class.equals(beanClass))
    471             {
    472                 TestBean bean = new TestBean();
    473                 BeanHelper.initBean(bean, data);
    474                 return bean;
    475             }
    476             else
    477             {
    478                 throw new IllegalArgumentException("Unsupported class: "
    479                         + beanClass);
    480             }
    481         }
    482
    483         /***
    484          * Returns the default class, but only if the supportsDefaultClass flag
    485          * is set.
    486          */
    487         public Class getDefaultBeanClass()
    488         {
    489             return supportsDefaultClass ? TestBean.class : null;
    490         }
    491     }
    492
    493     /***
    494      * A test implementation of the BeanDeclaration interface. This
    495      * implementation allows to set the values directly, which should be
    496      * returned by the methods required by the BeanDeclaration interface.
    497      */
    498     static class TestBeanDeclaration implements BeanDeclaration
    499     {
    500         private String beanClassName;
    501
    502         private String beanFactoryName;
    503
    504         private Object beanFactoryParameter;
    505
    506         private Map beanProperties;
    507
    508         private Map nestedBeanDeclarations;
    509
    510         public String getBeanClassName()
    511         {
    512             return beanClassName;
    513         }
    514
    515         public void setBeanClassName(String beanClassName)
    516         {
    517             this.beanClassName = beanClassName;
    518         }
    519
    520         public String getBeanFactoryName()
    521         {
    522             return beanFactoryName;
    523         }
    524
    525         public void setBeanFactoryName(String beanFactoryName)
    526         {
    527             this.beanFactoryName = beanFactoryName;
    528         }
    529
    530         public Object getBeanFactoryParameter()
    531         {
    532             return beanFactoryParameter;
    533         }
    534
    535         public void setBeanFactoryParameter(Object beanFactoryParameter)
    536         {
    537             this.beanFactoryParameter = beanFactoryParameter;
    538         }
    539
    540         public Map getBeanProperties()
    541         {
    542             return beanProperties;
    543         }
    544
    545         public void setBeanProperties(Map beanProperties)
    546         {
    547             this.beanProperties = beanProperties;
    548         }
    549
    550         public Map getNestedBeanDeclarations()
    551         {
    552             return nestedBeanDeclarations;
    553         }
    554
    555         public void setNestedBeanDeclarations(Map nestedBeanDeclarations)
    556         {
    557             this.nestedBeanDeclarations = nestedBeanDeclarations;
    558         }
    559     }
    560 }