You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by eh...@apache.org on 2003/11/25 15:08:16 UTC
cvs commit: jakarta-tapestry/junit/src/org/apache/tapestry/junit TestBindings.java
ehatcher 2003/11/25 06:08:16
Modified: doc/src/UsersGuide configuration.xml
framework/src/org/apache/tapestry/binding
ExpressionBinding.java
framework/src/org/apache/tapestry Tapestry.java
junit/src/org/apache/tapestry/junit TestBindings.java
Log:
add custom OGNL type converter capability
Revision Changes Path
1.11 +14 -1 jakarta-tapestry/doc/src/UsersGuide/configuration.xml
Index: configuration.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/doc/src/UsersGuide/configuration.xml,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- configuration.xml 18 Oct 2003 11:59:10 -0000 1.10
+++ configuration.xml 25 Nov 2003 14:08:15 -0000 1.11
@@ -528,6 +528,19 @@
</listitem>
</varlistentry>
+<varlistentry>
+<term>org.apache.tapestry.ognl-type-converter</term>
+
+<listitem>
+<para>
+Specifies an implementation of ognl.TypeConverter to be used for expression bindings.
+See OGNL's Type Converter documentation (currently at
+http://www.ognl.org/2.6.3/Documentation/html/typeConversion.html)
+for further information on implementing a custom type converter.
+</para>
+</listitem>
+</varlistentry>
+
</variablelist>
</section> <!-- configuration.extensions -->
1.9 +26 -5 jakarta-tapestry/framework/src/org/apache/tapestry/binding/ExpressionBinding.java
Index: ExpressionBinding.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/binding/ExpressionBinding.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- ExpressionBinding.java 4 Nov 2003 15:09:37 -0000 1.8
+++ ExpressionBinding.java 25 Nov 2003 14:08:15 -0000 1.9
@@ -59,6 +59,7 @@
import ognl.Ognl;
import ognl.OgnlException;
+import ognl.TypeConverter;
import org.apache.tapestry.BindingException;
import org.apache.tapestry.IComponent;
@@ -67,6 +68,7 @@
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.spec.BeanLifecycle;
import org.apache.tapestry.spec.IBeanSpecification;
+import org.apache.tapestry.spec.IApplicationSpecification;
import org.apache.tapestry.util.StringSplitter;
import org.apache.tapestry.util.prop.OgnlUtils;
@@ -239,7 +241,7 @@
{
return Ognl.getValue(_parsedExpression, getOgnlContext(), _root);
}
- catch (Throwable t)
+ catch (OgnlException t)
{
throw new BindingException(
Tapestry.format(
@@ -255,13 +257,32 @@
* Creates an OGNL context used to get or set a value.
* We may extend this in the future to set additional
* context variables (such as page, request cycle and engine).
+ * An optional type converter will be added to the OGNL context
+ * if it is specified as an application extension with the name
+ * {@link Tapestry#OGNL_TYPE_CONVERTER}.
*
**/
private Map getOgnlContext()
{
- if (_context == null)
+ if (_context == null) {
_context = Ognl.createDefaultContext(_root, _resolver);
+ }
+
+ if (_root.getPage() != null) {
+ if (_root.getPage().getEngine() != null) {
+ IApplicationSpecification appSpec =
+ _root.getPage().getEngine().getSpecification();
+ if (appSpec != null && appSpec.checkExtension(Tapestry.OGNL_TYPE_CONVERTER)) {
+ TypeConverter typeConverter =
+ (TypeConverter) appSpec.getExtension(
+ Tapestry.OGNL_TYPE_CONVERTER,
+ TypeConverter.class);
+
+ Ognl.setTypeConverter(_context, typeConverter);
+ }
+ }
+ }
return _context;
}
@@ -417,7 +438,7 @@
return true;
}
}
- catch (Exception ex)
+ catch (OgnlException ex)
{
throw new BindingException(
Tapestry.format(
@@ -560,7 +581,7 @@
{
Ognl.setValue(_parsedExpression, getOgnlContext(), _root, value);
}
- catch (Throwable ex)
+ catch (OgnlException ex)
{
throw new BindingException(
Tapestry.format(
1.19 +103 -96 jakarta-tapestry/framework/src/org/apache/tapestry/Tapestry.java
Index: Tapestry.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/Tapestry.java,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- Tapestry.java 17 Oct 2003 18:53:51 -0000 1.18
+++ Tapestry.java 25 Nov 2003 14:08:15 -0000 1.19
@@ -23,13 +23,13 @@
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
- * 4. The names "Apache" and "Apache Software Foundation", "Tapestry"
+ * 4. The names "Apache" and "Apache Software Foundation", "Tapestry"
* must not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
- * 5. Products derived from this software may not be called "Apache"
- * or "Tapestry", nor may "Apache" or "Tapestry" appear in their
+ * 5. Products derived from this software may not be called "Apache"
+ * or "Tapestry", nor may "Apache" or "Tapestry" appear in their
* name, without prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
@@ -88,7 +88,7 @@
* @since 1.0.1
* @version $Id$
* @author Howard Lewis Ship
- *
+ *
**/
public final class Tapestry
@@ -97,9 +97,9 @@
* Name of a request attribute used with the
* {@link #TAGSUPPORT_SERVICE} service. The attribute
* defines the underlying service to for which a URL will be generated.
- *
+ *
* @since 3.0
- *
+ *
**/
public final static String TAG_SUPPORT_SERVICE_ATTRIBUTE =
@@ -112,7 +112,7 @@
* Tapestry application (which, for the odd-man-out TAGSUPPORT_SERVICE
* may not match HttpServletRequest.getServletPath() because of
* the use of an include.
- *
+ *
* @since 3.0
*/
@@ -125,9 +125,9 @@
* defines an array of objects to be converted into
* service parameters (i.e., for use with the
* {@link #EXTERNAL_SERVICE}).
- *
+ *
* @since 3.0
- *
+ *
**/
public final static String TAG_SUPPORT_PARAMETERS_ATTRIBUTE =
@@ -137,9 +137,9 @@
* Service used to support rendering of JSP tags. tagsupport is provided
* with a service and service parameters via request attributes
* and creates a URI from the result, which is output to the response.
- *
+ *
* @since 3.0
- *
+ *
**/
public static final String TAGSUPPORT_SERVICE = "tagsupport";
@@ -148,7 +148,7 @@
* The name ("action") of a service that allows behavior to be associated with
* an {@link IAction} component, such as {@link org.apache.tapestry.link.ActionLink} or
* {@link org.apache.tapestry.form.Form}.
- *
+ *
* <p>This service is used with actions that are tied to the
* dynamic state of the page, and which require a rewind of the page.
*
@@ -180,7 +180,7 @@
* External pages may be booked marked using their URL for future reference.
*
* <p>An array of Object parameters may be included with the
- * service URL; these will be passed to the
+ * service URL; these will be passed to the
* {@link IExternalPage#activateExternalPage(Object[], IRequestCycle)} method.
*
**/
@@ -232,7 +232,7 @@
* <p>This service is only available if the Java system property
* <code>org.apache.tapestry.enable-reset-service</code>
* is set to <code>true</code>.
- *
+ *
**/
public static final String RESET_SERVICE = "reset";
@@ -242,7 +242,7 @@
* request.
*
* @since 1.0.3
- *
+ *
**/
public static final String SERVICE_QUERY_PARAMETER_NAME = "service";
@@ -252,11 +252,11 @@
* service (this is used with the direct service). Each of these
* values is encoded with {@link java.net.URLEncoder#encode(String)} before
* being added to the URL. Multiple values are handle by repeatedly
- * establishing key/value pairs (this is a change from behavior in
+ * establishing key/value pairs (this is a change from behavior in
* 2.1 and earlier).
*
* @since 1.0.3
- *
+ *
**/
public static final String PARAMETERS_QUERY_PARAMETER_NAME = "sp";
@@ -267,9 +267,9 @@
* component's) immediate container (library or application specification).
* Unlike most properties, value isn't inherited all the way up the chain.
* The default template extension is "html".
- *
+ *
* @since 3.0
- *
+ *
**/
public static final String TEMPLATE_EXTENSION_PROPERTY =
@@ -277,9 +277,9 @@
/**
* The default extension for templates, "html".
- *
+ *
* @since 3.0
- *
+ *
**/
public static final String DEFAULT_TEMPLATE_EXTENSION = "html";
@@ -297,9 +297,9 @@
/**
* Suffix appended to a parameter name to form the name of a property that stores the
* binding for the parameter.
- *
+ *
* @since 3.0
- *
+ *
**/
public static final String PARAMETER_PROPERTY_NAME_SUFFIX = "Binding";
@@ -307,11 +307,11 @@
/**
* Name of application extension used to resolve page and component
* specifications that can't be located by the normal means. The
- * extension must implement
+ * extension must implement
* {@link org.apache.tapestry.resolver.ISpecificationResolverDelegate}.
- *
+ *
* @since 3.0
- *
+ *
**/
public static final String SPECIFICATION_RESOLVER_DELEGATE_EXTENSION_NAME =
@@ -322,9 +322,9 @@
* templates that can't be located by the normal means.
* The extension must implement
* {@link org.apache.tapestry.engine.ITemplateSourceDelegate}.
- *
+ *
* @since 3.0
- *
+ *
**/
public static final String TEMPLATE_SOURCE_DELEGATE_EXTENSION_NAME =
@@ -333,9 +333,9 @@
/**
* Key used to obtain an extension from the application specification. The extension,
* if it exists, implements {@link org.apache.tapestry.request.IRequestDecoder}.
- *
+ *
* @since 2.2
- *
+ *
**/
public static final String REQUEST_DECODER_EXTENSION_NAME =
@@ -347,9 +347,9 @@
* {@link org.apache.tapestry.multipart.IMultipartDecoder}
* (and is generally a configured instance of
* {@link org.apache.tapestry.multipart.DefaultMultipartDecoder}).
- *
+ *
* @since 3.0
- *
+ *
**/
public static final String MULTIPART_DECODER_EXTENSION_NAME =
@@ -376,9 +376,9 @@
* Regular expression defining a simple property name. Used by several different
* parsers. Simple property names match Java variable names; a leading letter
* (or underscore), followed by letters, numbers and underscores.
- *
+ *
* @since 3.0
- *
+ *
**/
public static final String SIMPLE_PROPERTY_NAME_PATTERN = "^_?[a-zA-Z]\\w*$";
@@ -387,7 +387,7 @@
* Name of an application extension used as a factory for
* {@link org.apache.tapestry.engine.IMonitor} instances. The extension
* must implement {@link org.apache.tapestry.engine.IMonitorFactory}.
- *
+ *
* @since 3.0
*/
@@ -395,6 +395,13 @@
"org.apache.tapestry.monitor-factory";
/**
+ * Class name of an {@link ognl.TypeConverter} implementing class
+ * to use as a type converter for {@link org.apache.tapestry.binding.ExpressionBinding}
+ */
+ public static final String OGNL_TYPE_CONVERTER =
+ "org.apache.tapestry.ognl-type-converter";
+
+ /**
* Prevent instantiation.
*
**/
@@ -412,9 +419,9 @@
/**
* Contains strings loaded from TapestryStrings.properties.
- *
+ *
* @since 1.0.8
- *
+ *
**/
private static ResourceBundle _strings;
@@ -850,7 +857,7 @@
* <tr><td>{@link Iterator}</td> <td>Returned as-is.</td>
* <tr><td>{@link Collection}</td> <td>Iterator returned, or null
* if the Collection is empty</td> </tr>
-
+
* <tr><td>Any other</td> <td>{@link Iterator} for singleton collection returned</td> </tr>
* <tr><td>null</td> <td>null returned</td> </tr>
* </table>
@@ -923,7 +930,7 @@
}
- /**
+ /**
* Closes the stream (if not null), ignoring any {@link IOException} thrown.
*
* @since 1.0.2
@@ -946,12 +953,12 @@
}
/**
- * Gets a string from the TapestryStrings resource bundle.
+ * Gets a string from the TapestryStrings resource bundle.
* The string in the bundle
* is treated as a pattern for {@link MessageFormat#format(java.lang.String, java.lang.Object[])}.
- *
+ *
* @since 1.0.8
- *
+ *
**/
public static String format(String key, Object[] args)
@@ -969,7 +976,7 @@
/**
* Convienience method for invoking {@link #format(String, Object[])}.
- *
+ *
* @since 3.0
**/
@@ -980,7 +987,7 @@
/**
* Convienience method for invoking {@link #format(String, Object[])}.
- *
+ *
* @since 3.0
**/
@@ -991,9 +998,9 @@
/**
* Convienience method for invoking {@link #format(String, Object[])}.
- *
+ *
* @since 3.0
- *
+ *
**/
public static String format(String key, Object arg1, Object arg2)
@@ -1003,9 +1010,9 @@
/**
* Convienience method for invoking {@link #format(String, Object[])}.
- *
+ *
* @since 3.0
- *
+ *
**/
public static String format(String key, Object arg1, Object arg2, Object arg3)
@@ -1017,7 +1024,7 @@
/**
* Invoked when the class is initialized to read the current version file.
- *
+ *
**/
private static final String readVersion()
@@ -1046,9 +1053,9 @@
/**
* Returns the size of a collection, or zero if the collection is null.
- *
+ *
* @since 2.2
- *
+ *
**/
public static int size(Collection c)
@@ -1061,9 +1068,9 @@
/**
* Returns the length of the array, or 0 if the array is null.
- *
+ *
* @since 2.2
- *
+ *
**/
public static int size(Object[] array)
@@ -1076,9 +1083,9 @@
/**
* Returns true if the Map is null or empty.
- *
+ *
* @since 3.0
- *
+ *
**/
public static boolean isEmpty(Map map)
@@ -1088,9 +1095,9 @@
/**
* Returns true if the Collection is null or empty.
- *
+ *
* @since 3.0
- *
+ *
**/
public static boolean isEmpty(Collection c)
@@ -1106,10 +1113,10 @@
* the representation as an array will encode more efficiently
* (via {@link org.apache.tapestry.util.io.DataSqueezer} than
* serializing the Map and its contents.
- *
+ *
* @return the array of keys and values, or null if the input
* Map is null or empty
- *
+ *
* @since 2.2
**/
@@ -1136,13 +1143,13 @@
}
/**
- * Converts an even-sized array of objects back
+ * Converts an even-sized array of objects back
* into a {@link Map}.
- *
+ *
* @see #convertMapToArray(Map)
* @return a Map, or null if the array is null or empty
* @since 2.2
- *
+ *
**/
public static Map convertArrayToMap(Object[] array)
@@ -1171,9 +1178,9 @@
* Returns the application root location, which is in the
* {@link javax.servlet.ServletContext}, based on
* the {@link javax.servlet.http.HttpServletRequest#getServletPath() servlet path}.
- *
+ *
* @since 3.0
- *
+ *
**/
public static IResourceLocation getApplicationRootLocation(IRequestCycle cycle)
@@ -1191,7 +1198,7 @@
/**
* Given a Class, creates a presentable name for the class, even if the
* class is a scalar type or Array type.
- *
+ *
* @since 3.0
*/
@@ -1208,7 +1215,7 @@
* Skips over nulls. The objects may be instances of
* {Location or {@link org.apache.tapestry.ILocatable}. May return null
* if no Location found found.
- *
+ *
**/
public static ILocation findLocation(Object[] locations)
@@ -1238,9 +1245,9 @@
/**
* Creates an exception indicating the binding value is null.
- *
- * @since 3.0
- *
+ *
+ * @since 3.0
+ *
**/
public static BindingException createNullBindingException(IBinding binding)
@@ -1292,7 +1299,7 @@
/**
* Clears the list of method invocations.
* @see #checkMethodInvocation(Object, String, Object)
- *
+ *
* @since 3.0
*/
@@ -1303,11 +1310,11 @@
/**
* Adds a method invocation to the list of invocations. This is done
- * in a super-class implementations.
- *
+ * in a super-class implementations.
+ *
* @see #checkMethodInvocation(Object, String, Object)
* @since 3.0
- *
+ *
*/
public static void addMethodInvocation(Object methodId)
@@ -1327,16 +1334,16 @@
* Checks to see if a particular method has been invoked. The method is identified by a
* methodId (usually a String). The methodName and object are used to create an
* error message.
- *
+ *
* <p>
- * The caller should invoke {@link #clearMethodInvocations()}, then invoke a method on
+ * The caller should invoke {@link #clearMethodInvocations()}, then invoke a method on
* the object. The super-class implementation should invoke {@link #addMethodInvocation(Object)}
* to indicate that it was, in fact, invoked. The caller then invokes
* this method to vlaidate that the super-class implementation was invoked.
- *
+ *
* <p>
* The list of method invocations is stored in a {@link ThreadLocal} variable.
- *
+ *
* @since 3.0
*/
@@ -1357,11 +1364,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(
@@ -1382,11 +1389,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(
@@ -1411,11 +1418,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(
@@ -1437,11 +1444,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(
@@ -1463,11 +1470,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(IComponent component, String propertyName, int newValue)
@@ -1486,11 +1493,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(IComponent component, String propertyName, long newValue)
@@ -1509,11 +1516,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(IComponent component, String propertyName, char newValue)
@@ -1532,11 +1539,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(IComponent component, String propertyName, byte newValue)
@@ -1555,11 +1562,11 @@
/**
* Method used by pages and components to send notifications about
* property changes.
- *
+ *
* @param component the component containing the property
* @param propertyName the name of the property which changed
* @param newValue the new value for the property
- *
+ *
* @since 3.0
*/
public static void fireObservedChange(
1.6 +40 -1 jakarta-tapestry/junit/src/org/apache/tapestry/junit/TestBindings.java
Index: TestBindings.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/junit/src/org/apache/tapestry/junit/TestBindings.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- TestBindings.java 25 Apr 2003 23:18:27 -0000 1.5
+++ TestBindings.java 25 Nov 2003 14:08:16 -0000 1.6
@@ -56,6 +56,8 @@
package org.apache.tapestry.junit;
import java.util.HashMap;
+import java.util.Date;
+import java.sql.Timestamp;
import junit.framework.AssertionFailedError;
@@ -66,6 +68,7 @@
import org.apache.tapestry.IPage;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.IResourceResolver;
+import org.apache.tapestry.Tapestry;
import org.apache.tapestry.binding.AbstractBinding;
import org.apache.tapestry.binding.ExpressionBinding;
import org.apache.tapestry.binding.FieldBinding;
@@ -115,6 +118,7 @@
private int _intValue;
private double _doubleValue;
private Object _objectValue;
+ private Timestamp _dateValue;
public boolean getBooleanValue()
{
@@ -156,6 +160,13 @@
_objectValue = objectValue;
}
+ public Timestamp getDateValue() {
+ return _dateValue;
+ }
+
+ public void setDateValue(Timestamp dateValue) {
+ _dateValue = dateValue;
+ }
}
public TestBindings(String name)
@@ -756,5 +767,33 @@
assertSame(c, b.getComponent());
assertEquals("foo", b.getKey());
+ }
+
+ public void testTypeConverter() {
+ BoundPage page = new BoundPage();
+ MockEngine engine = new MockEngine();
+ page.setEngine(engine);
+
+ ExpressionBinding binding = new ExpressionBinding(_resolver, page, "dateValue", null);
+ Date date = new Date();
+
+ try {
+ // try without a converter first, which should fail
+ binding.setObject(date);
+ fail("Should not be able to call setDateValue(Date)");
+ }
+ catch (BindingException expected) {
+ assertTrue(true);
+ }
+
+ // now test with a custom converter enabled
+ MockApplicationSpecification appSpec = new MockApplicationSpecification();
+ HashMap extensions = new HashMap();
+ extensions.put(Tapestry.OGNL_TYPE_CONVERTER, new MockTypeConverter());
+ appSpec.setExtensions(extensions);
+ engine.setSpecification(appSpec);
+
+ binding.setObject(date);
+ assertEquals(date, page.getDateValue());
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org