You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2006/09/24 00:46:10 UTC
svn commit: r449321 - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/
main/java/org/apache/tapestry/internal/bindings/
main/java/org/apache/tapestry/internal/structure/
main/resources/org/apache/tapestry/internal/structur...
Author: hlship
Date: Sat Sep 23 15:46:09 2006
New Revision: 449321
URL: http://svn.apache.org/viewvc?view=rev&rev=449321
Log:
Perform type coercion when updating parameters, coercing the value provided to Binding.set().
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Binding.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/StructureMessages.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/structure/StructureStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Binding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Binding.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Binding.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Binding.java Sat Sep 23 15:46:09 2006
@@ -46,4 +46,11 @@
* such values aggressively.
*/
boolean isInvariant();
+
+ /**
+ * Returns the type of the binding, either the type of resource exposed by the binding, or the
+ * type of the property bound.
+ */
+
+ Class getBindingType();
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BasePropBinding.java Sat Sep 23 15:46:09 2006
@@ -30,10 +30,13 @@
{
private final String _toString;
- public BasePropBinding(String toString, Location location)
+ private final Class _bindingType;
+
+ public BasePropBinding(Class bindingType, String toString, Location location)
{
super(location);
+ _bindingType = bindingType;
_toString = toString;
}
@@ -54,5 +57,10 @@
public boolean isInvariant()
{
return false;
+ }
+
+ public Class getBindingType()
+ {
+ return _bindingType;
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/LiteralBinding.java Sat Sep 23 15:46:09 2006
@@ -46,4 +46,11 @@
{
return String.format("LiteralBinding[%s: %s]", _description, _value);
}
+
+ public Class getBindingType()
+ {
+ // Could be a problem for a LiteralBinding of null but that will certainly be read-only.
+ return _value.getClass();
+ }
+
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java Sat Sep 23 15:46:09 2006
@@ -14,6 +14,8 @@
package org.apache.tapestry.internal.bindings;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
+
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.Map;
@@ -34,7 +36,6 @@
import org.apache.tapestry.ioc.services.PropertyAdapter;
import org.apache.tapestry.services.BindingFactory;
import org.apache.tapestry.util.BodyBuilder;
-import org.apache.tapestry.util.CollectionFactory;
/**
* Binding factory for reading and updating JavaBean properties. Uses
@@ -51,7 +52,27 @@
private final ClassFactory _classFactory;
- private final Map<String, Class> _cache = CollectionFactory.newMap();
+ // The key is a combination of class name and property name.
+ private final Map<String, BindingConstructor> _cache = newMap();
+
+ private static class BindingConstructor
+ {
+ private final Class _propertyType;
+
+ private final Constructor _constructor;
+
+ BindingConstructor(Class propertyType, Constructor constructor)
+ {
+ _propertyType = propertyType;
+ _constructor = constructor;
+ }
+
+ Binding newBindingInstance(Object target, String toString, Location location)
+ throws Exception
+ {
+ return (Binding) _constructor.newInstance(target, _propertyType, toString, location);
+ }
+ }
private static final MethodSignature GET_SIGNATURE = new MethodSignature(Object.class, "get",
null, null);
@@ -74,14 +95,12 @@
try
{
- Class bindingClass = findBindingClass(targetClass, expression);
+ BindingConstructor cons = findCachedConstructor(targetClass, expression);
String toString = String.format("PropBinding[%s %s(%s)]", description, component
.getCompleteId(), expression);
- Constructor cons = bindingClass.getConstructors()[0];
-
- return (Binding) cons.newInstance(target, toString, location);
+ return cons.newBindingInstance(target, toString, location);
}
catch (Exception ex)
{
@@ -89,8 +108,18 @@
}
}
+ /**
+ * Searches for a cached binding constructor for the given target class and property name. As
+ * necessary, a new cached constructor is created.
+ *
+ * @param targetClass
+ * the class of the component which contains the property
+ * @param propertyName
+ * the name of the property to expose as a binding
+ * @return
+ */
@Concurrent.Read
- private Class findBindingClass(Class targetClass, String propertyName)
+ private BindingConstructor findCachedConstructor(Class targetClass, String propertyName)
{
// The only problem with this key is if we can get in a situation where two different
// versions of the class (from the default class loader, and the component class loader)
@@ -98,16 +127,17 @@
String key = targetClass.getName() + ":" + propertyName;
- Class result = _cache.get(key);
+ BindingConstructor result = _cache.get(key);
if (result == null)
- result = fillCache(key, targetClass, propertyName);
+ result = createConstructorAndFillCache(key, targetClass, propertyName);
return result;
}
@Concurrent.Write
- private Class fillCache(String key, Class targetClass, String propertyName)
+ private BindingConstructor createConstructorAndFillCache(String key, Class targetClass,
+ String propertyName)
{
// Race condition: simulataneous calls to fillCache() for the same targetClass/propertyName
// combination may result in duplicate binding classes being created, which causes no great
@@ -121,9 +151,15 @@
Class bindingClass = createBindingClass(targetClass, propertyName, adapter);
- _cache.put(key, bindingClass);
+ // The fabricated class is only going to have the one constructor. This is the easiest
+ // way to access it.
- return bindingClass;
+ BindingConstructor result = new BindingConstructor(adapter.getType(), bindingClass
+ .getConstructors()[0]);
+
+ _cache.put(key, result);
+
+ return result;
}
private Class createBindingClass(Class targetClass, String propertyName, PropertyAdapter adapter)
@@ -134,8 +170,11 @@
classFab.addField("_target", targetClass);
- classFab.addConstructor(new Class[]
- { targetClass, String.class, Location.class }, null, "{ super($2, $3); _target = $1; }");
+ classFab.addConstructor(
+ new Class[]
+ { targetClass, Class.class, String.class, Location.class },
+ null,
+ "{ super($2, $3, $4); _target = $1; }");
if (adapter.isRead())
{
@@ -177,6 +216,10 @@
return classFab.createClass();
}
+ /**
+ * The cache contains references to classes loaded by the Tapestry class loader. When that
+ * loader is invalidated (due to class file changes), the cache is cleared and rebuilt.
+ */
@Concurrent.Write
public void objectWasInvalidated(InvalidationEvent event)
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java Sat Sep 23 15:46:09 2006
@@ -469,6 +469,7 @@
}
}
+ @SuppressWarnings("unchecked")
public <T> void writeParameter(String parameterName, T parameterValue)
{
Binding b = getBinding(parameterName);
@@ -477,7 +478,21 @@
// TODO: Type coercion when writing value into binding
- b.set(parameterValue);
+ Class bindingType = b.getBindingType();
+
+ try
+ {
+ Object coerced = _typeCoercer.coerce(parameterValue, bindingType);
+
+ b.set(coerced);
+ }
+ catch (Exception ex)
+ {
+ throw new TapestryException(StructureMessages.writeParameterFailure(
+ parameterName,
+ getCompleteId(),
+ ex), ex);
+ }
}
public boolean isRendering()
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/StructureMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/StructureMessages.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/StructureMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/StructureMessages.java Sat Sep 23 15:46:09 2006
@@ -44,4 +44,9 @@
{
return MESSAGES.format("get-parameter-failure", parameterName, componentId, cause);
}
+
+ static String writeParameterFailure(String parameterName, String componentId, Throwable cause)
+ {
+ return MESSAGES.format("write-parameter-failure", parameterName, componentId, cause);
+ }
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/structure/StructureStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/structure/StructureStrings.properties?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/structure/StructureStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/structure/StructureStrings.properties Sat Sep 23 15:46:09 2006
@@ -14,4 +14,5 @@
missing-parameters=Parameter(s) %s are required for %s, but have not been bound.
no-such-component=Component %s does not contain an embedded component with id '%s'.
-get-parameter-failure=Failure reading parameter %s of component %s: %s
\ No newline at end of file
+get-parameter-failure=Failure reading parameter %s of component %s: %s
+write-parameter-failure=Failure writing parameter %s of component %s: %s
\ No newline at end of file
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/BindingFactoryTest.java Sat Sep 23 15:46:09 2006
@@ -47,6 +47,7 @@
assertEquals(b.get(), "Tapestry5");
assertTrue(b.isInvariant());
+ assertSame(b.getBindingType(), String.class);
try
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java Sat Sep 23 15:46:09 2006
@@ -77,6 +77,8 @@
Binding binding = factory.newBinding("test binding", resources, "objectValue", l);
+ assertSame(binding.getBindingType(), String.class);
+
bean.setObjectValue("first");
assertEquals(binding.get(), "first");
@@ -102,6 +104,8 @@
replay();
Binding binding = factory.newBinding("test binding", resources, "intValue", l);
+
+ assertSame(binding.getBindingType(), int.class);
bean.setIntValue(1);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java?view=diff&rev=449321&r1=449320&r2=449321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java Sat Sep 23 15:46:09 2006
@@ -209,14 +209,20 @@
ComponentLifecycle component = newComponentLifecycle();
Instantiator ins = newInstantiator(component);
ComponentModel model = newComponentModel();
+ TypeCoercer coercer = newTypeCoercer();
Binding binding = newBinding();
+ binding.getBindingType();
+ setReturnValue(Integer.class);
+
+ train_coerce(coercer, 23, Integer.class, 23);
+
binding.set(23);
replay();
- ComponentPageElement cpe = new ComponentPageElementImpl(page, ins, model, null);
+ ComponentPageElement cpe = new ComponentPageElementImpl(page, ins, model, coercer);
cpe.addParameter("barney", binding);