commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ohe...@apache.org
Subject svn commit: r1408085 - in /commons/proper/configuration/trunk/src: main/java/org/apache/commons/configuration/beanutils/DefaultBeanFactory.java test/java/org/apache/commons/configuration/beanutils/TestDefaultBeanFactory.java
Date Sun, 11 Nov 2012 19:03:58 GMT
Author: oheger
Date: Sun Nov 11 19:03:58 2012
New Revision: 1408085

URL: http://svn.apache.org/viewvc?rev=1408085&view=rev
Log:
[CONFIGURATION-514] DefaultBeanFactory now supports creating beans by invoking a constructor.

Modified:
    commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/beanutils/DefaultBeanFactory.java
    commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/beanutils/TestDefaultBeanFactory.java

Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/beanutils/DefaultBeanFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/beanutils/DefaultBeanFactory.java?rev=1408085&r1=1408084&r2=1408085&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/beanutils/DefaultBeanFactory.java
(original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/beanutils/DefaultBeanFactory.java
Sun Nov 11 19:03:58 2012
@@ -16,6 +16,12 @@
  */
 package org.apache.commons.configuration.beanutils;
 
+import java.lang.reflect.Constructor;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.commons.configuration.PropertyConverter;
+
 /**
  * <p>
  * The default implementation of the {@code BeanFactory} interface.
@@ -89,7 +95,9 @@ public class DefaultBeanFactory implemen
     protected Object createBeanInstance(Class<?> beanClass, BeanDeclaration data)
             throws Exception
     {
-        return beanClass.newInstance();
+        Constructor<?> ctor = BeanHelper.findMatchingConstructor(beanClass, data);
+        Object[] args = fetchConstructorArgs(ctor, data);
+        return ctor.newInstance(args);
     }
 
     /**
@@ -107,4 +115,52 @@ public class DefaultBeanFactory implemen
     {
         BeanHelper.initBean(bean, data);
     }
+
+    /**
+     * Obtains the arguments for a constructor call to create a bean. This method
+     * resolves nested bean declarations and performs necessary type
+     * conversions.
+     *
+     * @param ctor the constructor to be invoked
+     * @param data the current bean declaration
+     * @return an array with constructor arguments
+     */
+    private static Object[] fetchConstructorArgs(Constructor<?> ctor,
+            BeanDeclaration data)
+    {
+        Class<?>[] types = ctor.getParameterTypes();
+        assert types.length == nullSafeConstructorArgs(data).size() :
+            "Wrong number of constructor arguments!";
+        Object[] args = new Object[types.length];
+        int idx = 0;
+
+        for (ConstructorArg arg : nullSafeConstructorArgs(data))
+        {
+            Object val =
+                    arg.isNestedBeanDeclaration() ? BeanHelper.createBean(arg
+                            .getBeanDeclaration()) : arg.getValue();
+            args[idx] = PropertyConverter.to(types[idx], val, null);
+            idx++;
+        }
+
+        return args;
+    }
+
+    /**
+     * Fetches constructor arguments from the given bean declaration. Handles
+     * <b>null</b> values safely.
+     *
+     * @param data the bean declaration
+     * @return the collection with constructor arguments (never <b>null</b>)
+     */
+    private static Collection<ConstructorArg> nullSafeConstructorArgs(
+            BeanDeclaration data)
+    {
+        Collection<ConstructorArg> args = data.getConstructorArgs();
+        if (args == null)
+        {
+            args = Collections.emptySet();
+        }
+        return args;
+    }
 }

Modified: commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/beanutils/TestDefaultBeanFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/beanutils/TestDefaultBeanFactory.java?rev=1408085&r1=1408084&r2=1408085&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/beanutils/TestDefaultBeanFactory.java
(original)
+++ commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/beanutils/TestDefaultBeanFactory.java
Sun Nov 11 19:03:58 2012
@@ -21,7 +21,9 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -41,7 +43,7 @@ import org.junit.Test;
 public class TestDefaultBeanFactory
 {
     /** The object to be tested. */
-    DefaultBeanFactory factory;
+    private DefaultBeanFactory factory;
 
     @Before
     public void setUp() throws Exception
@@ -64,8 +66,12 @@ public class TestDefaultBeanFactory
     @Test
     public void testCreateBean() throws Exception
     {
+        BeanDeclarationTestImpl decl = new BeanDeclarationTestImpl();
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("throwExceptionOnMissing", Boolean.TRUE);
+        decl.setBeanProperties(props);
         Object bean = factory.createBean(PropertiesConfiguration.class,
-                new TestBeanDeclaration(), null);
+                decl, null);
         assertNotNull("New bean is null", bean);
         assertEquals("Bean is of wrong class", PropertiesConfiguration.class,
                 bean.getClass());
@@ -75,40 +81,44 @@ public class TestDefaultBeanFactory
     }
 
     /**
-     * A simple implementation of BeanDeclaration used for testing purposes.
+     * Tests whether a bean can be created by calling its constructor.
      */
-    static class TestBeanDeclaration implements BeanDeclaration
+    @Test
+    public void testCreateBeanConstructor() throws Exception
+    {
+        BeanDeclarationTestImpl decl = new BeanDeclarationTestImpl();
+        Collection<ConstructorArg> args = new ArrayList<ConstructorArg>();
+        args.add(ConstructorArg.forValue("test"));
+        args.add(ConstructorArg.forValue("42"));
+        decl.setConstructorArgs(args);
+        BeanCreationTestCtorBean bean =
+                (BeanCreationTestCtorBean) factory.createBean(
+                        BeanCreationTestCtorBean.class, decl, null);
+        assertEquals("Wrong string property", "test", bean.getStringValue());
+        assertEquals("Wrong int property", 42, bean.getIntValue());
+    }
+
+    /**
+     * Tests whether nested bean declarations in constructor arguments are taken
+     * into account.
+     */
+    @Test
+    public void testCreateBeanConstructorNestedBean() throws Exception
     {
-        public String getBeanFactoryName()
-        {
-            return null;
-        }
-
-        public Object getBeanFactoryParameter()
-        {
-            return null;
-        }
-
-        public String getBeanClassName()
-        {
-            return null;
-        }
-
-        public Map<String, Object> getBeanProperties()
-        {
-            Map<String, Object> props = new HashMap<String, Object>();
-            props.put("throwExceptionOnMissing", Boolean.TRUE);
-            return props;
-        }
-
-        public Map<String, Object> getNestedBeanDeclarations()
-        {
-            return null;
-        }
-
-        public Collection<ConstructorArg> getConstructorArgs()
-        {
-            return null;
-        }
+        BeanDeclarationTestImpl declNested = new BeanDeclarationTestImpl();
+        Collection<ConstructorArg> args = new ArrayList<ConstructorArg>();
+        args.add(ConstructorArg.forValue("test", String.class.getName()));
+        declNested.setConstructorArgs(args);
+        declNested.setBeanClassName(BeanCreationTestCtorBean.class.getName());
+        BeanDeclarationTestImpl decl = new BeanDeclarationTestImpl();
+        decl.setConstructorArgs(Collections.singleton(ConstructorArg
+                .forBeanDeclaration(declNested,
+                        BeanCreationTestBean.class.getName())));
+        BeanCreationTestCtorBean bean =
+                (BeanCreationTestCtorBean) factory.createBean(
+                        BeanCreationTestCtorBean.class, decl, null);
+        assertNotNull("Buddy bean was not set", bean.getBuddy());
+        assertEquals("Wrong property of buddy bean", "test", bean.getBuddy()
+                .getStringValue());
     }
 }



Mime
View raw message