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