Revision: 1006
          http://stripes.svn.sourceforge.net/stripes/?rev=1006&view=rev
Author:   bengunter
Date:     2008-11-20 21:01:55 +0000 (Thu, 20 Nov 2008)

Log Message:
-----------
STS-614: Enhanced the ObjectFactory interface and default impl to support 
constructors with parameters. Also changed MapPropertyAccessor and 
DefaultActionBeanPropertyBinder to use this new feature.

Modified Paths:
--------------
    
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java
    
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultObjectFactory.java
    trunk/stripes/src/net/sourceforge/stripes/controller/ObjectFactory.java
    trunk/stripes/src/net/sourceforge/stripes/util/bean/MapPropertyAccessor.java

Modified: 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java
===================================================================
--- 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java
   2008-11-07 20:46:35 UTC (rev 1005)
+++ 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java
   2008-11-20 21:01:55 UTC (rev 1006)
@@ -39,7 +39,6 @@
 
 import javax.servlet.http.HttpServletRequest;
 import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -785,11 +784,11 @@
                         retval = converter.convert(value, returnType, errors);
                     }
                     else {
-                        Constructor<?> constructor = 
returnType.getConstructor(String.class);
-                        if (constructor != null) {
-                            retval = constructor.newInstance(value);
+                        try {
+                            retval = getConfiguration().getObjectFactory()
+                                    .constructor(returnType, 
String.class).newInstance(value);
                         }
-                        else {
+                        catch (StripesRuntimeException e) {
                             log.debug("Could not find a way to convert the 
parameter ", propertyName.getName(),
                                       " to a ", returnType.getSimpleName(), ". 
No TypeConverter could be ",
                                       "found and the class does not ", "have a 
constructor that takes a ",

Modified: 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultObjectFactory.java
===================================================================
--- 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultObjectFactory.java  
    2008-11-07 20:46:35 UTC (rev 1005)
+++ 
trunk/stripes/src/net/sourceforge/stripes/controller/DefaultObjectFactory.java  
    2008-11-20 21:01:55 UTC (rev 1006)
@@ -14,6 +14,8 @@
  */
 package net.sourceforge.stripes.controller;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -42,6 +44,38 @@
  */
 public class DefaultObjectFactory implements ObjectFactory {
     /**
+     * An implementation of [EMAIL PROTECTED] ConstructorWrapper} that calls 
back to
+     * [EMAIL PROTECTED] DefaultObjectFactory#newInstance(Constructor, 
Object...)} to instantiate a class.
+     */
+    public static class DefaultConstructorWrapper<T> implements 
ConstructorWrapper<T> {
+        private ObjectFactory factory;
+        private Constructor<T> constructor;
+
+        /**
+         * Wrap the given constructor.
+         * 
+         * @param factory The object factory whose
+         *            [EMAIL PROTECTED] ObjectFactory#newInstance(Constructor, 
Object...)} method will be
+         *            called when invoking the constructor.
+         * @param constructor The constructor to wrap.
+         */
+        public DefaultConstructorWrapper(ObjectFactory factory, Constructor<T> 
constructor) {
+            this.factory = factory;
+            this.constructor = constructor;
+        }
+
+        /** Get the [EMAIL PROTECTED] Constructor} object wrapped by this 
instance. */
+        public Constructor<T> getConstructor() {
+            return constructor;
+        }
+
+        /** Invoke the constructor with the specified arguments and return the 
new object. */
+        public T newInstance(Object... args) {
+            return factory.newInstance(constructor, args);
+        }
+    }
+
+    /**
      * Holds a map of commonly used interface types (mostly collections) to a 
class that implements
      * the interface and will, by default, be instantiated when an instance of 
the interface is
      * needed.
@@ -79,9 +113,9 @@
     public <T> T newInstance(Class<T> clazz) {
         try {
             if (clazz.isInterface())
-                return newInterfaceInstance(clazz);
+                return postProcess(newInterfaceInstance(clazz));
             else
-                return clazz.newInstance();
+                return postProcess(clazz.newInstance());
         }
         catch (InstantiationException e) {
             throw new StripesRuntimeException("Could not instantiate " + 
clazz, e);
@@ -132,4 +166,86 @@
     public Class<?> getImplementingClass(Class<?> iface) {
         return interfaceImplementations.get(iface);
     }
+
+    /**
+     * Create a new instance of [EMAIL PROTECTED] clazz} by looking up the 
specified constructor and passing it
+     * and its parameters to [EMAIL PROTECTED] #newInstance(Constructor, 
Object...)}.
+     * 
+     * @param clazz The class to instantiate.
+     * @param constructorArgTypes The type parameters of the constructor to be 
invoked. (See
+     *            [EMAIL PROTECTED] Class#getConstructor(Class...)}.)
+     * @param constructorArgs The parameters to pass to the constructor. (See
+     *            [EMAIL PROTECTED] Constructor#newInstance(Object...)}.)
+     * @return A new instance of the class.
+     */
+    public <T> T newInstance(Class<T> clazz, Class<?>[] constructorArgTypes,
+            Object[] constructorArgs) {
+        try {
+            Constructor<T> constructor = 
clazz.getConstructor(constructorArgTypes);
+            return postProcess(newInstance(constructor, constructorArgs));
+        }
+        catch (SecurityException e) {
+            throw new StripesRuntimeException("Could not instantiate " + 
clazz, e);
+        }
+        catch (NoSuchMethodException e) {
+            throw new StripesRuntimeException("Could not instantiate " + 
clazz, e);
+        }
+        catch (IllegalArgumentException e) {
+            throw new StripesRuntimeException("Could not instantiate " + 
clazz, e);
+        }
+    }
+
+    /**
+     * Calls [EMAIL PROTECTED] Constructor#newInstance(Object...)} with the 
given parameters, passes the new
+     * object to [EMAIL PROTECTED] #postProcess(Object)} and returns it.
+     * 
+     * @param constructor The constructor to invoke.
+     * @param params The parameters to pass to the constructor.
+     */
+    public <T> T newInstance(Constructor<T> constructor, Object... params) {
+        try {
+            return postProcess(constructor.newInstance(params));
+        }
+        catch (InstantiationException e) {
+            throw new StripesRuntimeException("Could not invoke constructor " 
+ constructor, e);
+        }
+        catch (IllegalAccessException e) {
+            throw new StripesRuntimeException("Could not invoke constructor " 
+ constructor, e);
+        }
+        catch (InvocationTargetException e) {
+            throw new StripesRuntimeException("Could not invoke constructor " 
+ constructor, e);
+        }
+    }
+
+    /**
+     * Get a [EMAIL PROTECTED] ConstructorWrapper} that wraps the constructor 
for the given class that accepts
+     * parameters of the given types.
+     * 
+     * @param clazz The class to look up the constructor in.
+     * @param parameterTypes The parameter types that the constructor accepts.
+     */
+    public <T> DefaultConstructorWrapper<T> constructor(Class<T> clazz, 
Class<?>... parameterTypes) {
+        try {
+            return new DefaultConstructorWrapper<T>(this, 
clazz.getConstructor(parameterTypes));
+        }
+        catch (SecurityException e) {
+            throw new StripesRuntimeException("Could not instantiate " + 
clazz, e);
+        }
+        catch (NoSuchMethodException e) {
+            throw new StripesRuntimeException("Could not instantiate " + 
clazz, e);
+        }
+    }
+
+    /**
+     * Perform post-processing on objects created by [EMAIL PROTECTED] 
#newInstance(Class)} or
+     * [EMAIL PROTECTED] #newInstance(Class, Class[], Object[])}. Subclasses 
that do not need to change the way
+     * objects are instantiated but do need to do something to the objects 
before returning them may
+     * override this method to achieve that.
+     * 
+     * @param object A newly created object.
+     * @return The given object, unchanged.
+     */
+    protected <T> T postProcess(T object) {
+        return object;
+    }
 }

Modified: 
trunk/stripes/src/net/sourceforge/stripes/controller/ObjectFactory.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/controller/ObjectFactory.java     
2008-11-07 20:46:35 UTC (rev 1005)
+++ trunk/stripes/src/net/sourceforge/stripes/controller/ObjectFactory.java     
2008-11-20 21:01:55 UTC (rev 1006)
@@ -14,6 +14,8 @@
  */
 package net.sourceforge.stripes.controller;
 
+import java.lang.reflect.Constructor;
+
 import net.sourceforge.stripes.config.ConfigurableComponent;
 
 /**
@@ -34,10 +36,61 @@
  */
 public interface ObjectFactory extends ConfigurableComponent {
     /**
+     * <p>
+     * A wrapper for a [EMAIL PROTECTED] Constructor}. This interface provides 
a builder-style API for
+     * instantiating classes by invoking a specific constructor. Typical usage 
might look like:
+     * </p>
+     * <code>
+     * configuration.getObjectFactory().constructor(targetType, 
String.class).newInstance("FOO");
+     * </code>
+     */
+    public static interface ConstructorWrapper<T> {
+        /** Get the [EMAIL PROTECTED] Constructor} object wrapped by this 
instance. */
+        public Constructor<T> getConstructor();
+
+        /** Invoke the constructor with the specified arguments and return the 
new object. */
+        public T newInstance(Object... args);
+    }
+
+    /**
      * Create a new instance of [EMAIL PROTECTED] clazz} and return it.
      * 
      * @param clazz The class to instantiate.
      * @return A new instances of the class.
      */
     <T> T newInstance(Class<T> clazz);
+
+    /**
+     * Create a new instances of [EMAIL PROTECTED] T} by invoking the given 
constructor.
+     * 
+     * @return A new object instantiated by invoking the constructor.
+     */
+    <T> T newInstance(Constructor<T> constructor, Object... args);
+
+    /**
+     * Create a new instance of [EMAIL PROTECTED] clazz} by calling a specific 
constructor.
+     * 
+     * @param clazz The class to instantiate.
+     * @param constructorArgTypes The type arguments of the constructor to be 
invoked. (See
+     *            [EMAIL PROTECTED] Class#getConstructor(Class...)}.)
+     * @param constructorArgs The arguments to pass to the constructor. (See
+     *            [EMAIL PROTECTED] Constructor#newInstance(Object...)}.)
+     * @return A new instance of the class.
+     */
+    <T> T newInstance(Class<T> clazz, Class<?>[] constructorArgTypes, Object[] 
constructorArgs);
+
+    /**
+     * <p>
+     * Provides a builder-style interface for instantiating objects by calling 
specific
+     * constructors. Typical usage might look like:
+     * </p>
+     * <code>
+     * configuration.getObjectFactory().constructor(targetType, 
String.class).newInstance("FOO");
+     * </code>
+     * 
+     * @param clazz The class whose constructor is to be looked up.
+     * @param parameterTypes The types of the parameters to the constructor.
+     * @return A [EMAIL PROTECTED] ConstructorWrapper} that allows for 
invoking the constructor.
+     */
+    <T> ConstructorWrapper<T> constructor(Class<T> clazz, Class<?>... 
parameterTypes);
 }
\ No newline at end of file

Modified: 
trunk/stripes/src/net/sourceforge/stripes/util/bean/MapPropertyAccessor.java
===================================================================
--- 
trunk/stripes/src/net/sourceforge/stripes/util/bean/MapPropertyAccessor.java    
    2008-11-07 20:46:35 UTC (rev 1005)
+++ 
trunk/stripes/src/net/sourceforge/stripes/util/bean/MapPropertyAccessor.java    
    2008-11-20 21:01:55 UTC (rev 1006)
@@ -24,7 +24,6 @@
 import java.util.Locale;
 import java.util.Collection;
 import java.util.ArrayList;
-import java.lang.reflect.Constructor;
 
 /**
  * Implementation of [EMAIL PROTECTED] PropertyAccessor} for interacting with 
Maps. Uses information
@@ -93,10 +92,8 @@
                 }
                 // Otherwise look for a String constructor
                 else {
-                    Constructor c = declaredType.getConstructor(String.class);
-                    if (c != null) {
-                        return c.newInstance(stringKey);
-                    }
+                    return StripesFilter.getConfiguration().getObjectFactory()
+                            .constructor(declaredType, 
String.class).newInstance(stringKey);
                 }
             }
             catch (Exception e) {


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to