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 2007/02/27 23:11:27 UTC

svn commit: r512442 [1/2] - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/ main/java/org/apache/tapestry/corelib/base/ main/java/org/apache/tapestry/corelib/components/ main/java/org/apache/tapestry/internal/ main/java/o...

Author: hlship
Date: Tue Feb 27 14:11:23 2007
New Revision: 512442

URL: http://svn.apache.org/viewvc?view=rev&rev=512442
Log:
Add basic support for client-side validation.
Move PageRenderSupport from the services package to the root package.
Add a clientValidation flag to Form and BeanEditForm (which defaults to true).
Rename TapestryUtils to TapestryInternalUtils.

Added:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ClientElement.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/PageRenderSupport.java
      - copied, changed from r511996, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PageRenderSupport.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryUtils.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java
      - copied, changed from r510990, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/EnvironmentalShadowBuilderImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/EnvironmentalShadowBuilder.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/tapestry.js
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/TapestryUtilsTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ValidBeanEditorDemo.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java
      - copied, changed from r510990, tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/TapestryUtilsTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/EnvironmentalShadowBuilderImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageRenderSupportImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/validator/MaxTest.java
      - copied unchanged from r510990, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxTest.java
Removed:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PageRenderSupport.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/ScriptDemo.html
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/ScriptDemo.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/TapestryUtilsTest.java
Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Field.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/FieldValidator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Any.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridCell.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Img.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/PageLink.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionGroupModelImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionModelImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyModelImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MessagesSourceImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MetaWorker.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderSupportImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceDigestGeneratorImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceStreamerImpl.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.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/test/InternalBaseTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/EnumSelectModel.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MinLength.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Required.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ValidationMessages.properties
    tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/BeanEditorDemo.html
    tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/Start.html
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/corelib/components/SelectTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/BeanEditorDemo.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/DataBean.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FieldValidatorImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/FieldValidatorSourceImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageTemplateLocatorImplTest.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/ValidForm.html

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ClientElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ClientElement.java?view=auto&rev=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ClientElement.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ClientElement.java Tue Feb 27 14:11:23 2007
@@ -0,0 +1,37 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry;
+
+
+/**
+ * Interface for any kind of object (typically, a component) that can provide a
+ * {@link #getClientId() client-side id}, typically used in the generation of client-side
+ * (JavaScript) logic. For components, the client id will be null or innaccurate until after the
+ * component has rendered itself. Inside of any kind of loop, the clientId property is only accurate
+ * just after the component has rendered, and before it renders again.
+ * <p>
+ * Some components must be configured to provide a client id. In many cases, the client id matches
+ * the component's {@link ComponentResourcesCommon#getId() component id}, typically passed through
+ * {@link PageRenderSupport#allocateClientId(String)} to ensure uniqueness.
+ */
+public interface ClientElement
+{
+    /**
+     * Returns a unique id for the element. This value will be unique for any given rendering of a
+     * page. This value is intended for use as the id attribute of the client-side element, and will
+     * be used with any DHTML/Ajax related JavaScript.
+     */
+    String getClientId();
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Field.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Field.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Field.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Field.java Tue Feb 27 14:11:23 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -17,20 +17,13 @@
 /**
  * Defines a field within a form.
  */
-public interface Field
+public interface Field extends ClientElement
 {
     /**
      * Returns the value used as the name attribute of the rendered element. This value will be
      * unique within an enclosing form, even if the same component renders multiple times.
      */
     String getElementName();
-
-    /**
-     * Returns a unique id for the element. This value will be unique for any given rendering of a
-     * page. This value is intended for use as the id attribute of the client-side element, and will
-     * be used with any DHTML/Ajax related JavaScript.
-     */
-    String getClientId();
 
     /**
      * Returns a user presentable (localized) label for the field, which may be used inside

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/FieldValidator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/FieldValidator.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/FieldValidator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/FieldValidator.java Tue Feb 27 14:11:23 2007
@@ -33,4 +33,12 @@
      *             if the value violates the constraint
      */
     void validate(T value) throws ValidationException;
+
+    /**
+     * Invokes
+     * {@link Validator#render(Field, Object, org.apache.tapestry.ioc.MessageFormatter, MarkupWriter, PageRenderSupport)}.
+     * 
+     * @param writer
+     */
+    void render(MarkupWriter writer);
 }

Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/PageRenderSupport.java (from r511996, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PageRenderSupport.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/PageRenderSupport.java?view=diff&rev=512442&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PageRenderSupport.java&r1=511996&p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/PageRenderSupport.java&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/PageRenderSupport.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/PageRenderSupport.java Tue Feb 27 14:11:23 2007
@@ -12,9 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.services;
+package org.apache.tapestry;
 
-import org.apache.tapestry.Asset;
 import org.apache.tapestry.ioc.internal.util.IdAllocator;
 
 /**
@@ -36,22 +35,33 @@
     String allocateClientId(String id);
 
     /**
-     * Adds a new script asset to the page. Assets are added uniquely, and appear as &lt;script&gt;
-     * elements just inside the &lt;body&gt; element of the rendered page. Duplicate requests to add
-     * the same script are quietly ignored.
+     * Adds one or more new script assets to the page. Assets are added uniquely, and appear as
+     * &lt;script&gt; elements just inside the &lt;body&gt; element of the rendered page. Duplicate
+     * requests to add the same script are quietly ignored.
      * 
-     * @param scriptAsset
+     * @param scriptAssets
      *            asset to the script to add
      */
-    void addScriptLink(Asset scriptAsset);
+    void addScriptLink(Asset... scriptAssets);
+
+    /**
+     * Used to add scripts that are stored on the classpath. Each element has symbol expanded, then
+     * is converted to an asset and added as a script link.
+     * 
+     * @param classpaths
+     *            array of paths. Symbols in the paths are expanded, then the paths are each
+     *            converted into an asset.
+     */
+    void addClasspathScriptLink(String... classpaths);
 
     /**
      * Adds a script statement to the page's script block (which appears at the end of the page,
      * just before the &lt/body&gt; tag).
      * 
-     * @param script
-     *            statement or block of statements to add to the block. Blank or null values will be
-     *            ignored.
+     * @param format
+     *            base string format, to be passed through String.format
+     * @param arguments
+     *            additional arguments formatted to form the final script
      */
-    void addScript(String script);
+    void addScript(String format, Object... arguments);
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryUtils.java?view=auto&rev=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryUtils.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/TapestryUtils.java Tue Feb 27 14:11:23 2007
@@ -0,0 +1,37 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry;
+
+/**
+ * Utilities often needed when building Tapestry applications.
+ */
+public class TapestryUtils
+{
+
+    /**
+     * Quotes the provided value as a JavaScript string literal. The input value is surrounded by
+     * single quotes and any interior single or double quotes are escaped (a preceding backslash is
+     * added).
+     * 
+     * @param text
+     * @return quoted text
+     */
+    public static String quote(String text)
+    {
+        // TODO: Lots more, and maybe use a regexp?
+        
+        return "'" + text.replace("'", "\\'").replace("\"", "\\\"") + "'";
+    }
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Validator.java Tue Feb 27 14:11:23 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -74,4 +74,23 @@
      * is generally false.
      */
     boolean invokeIfBlank();
+
+    /**
+     * Hook used by components to allow the validator to contribute additional attribute or (more
+     * often) client-side JavaScript (via the {@link PageRenderSupport}).
+     * 
+     * @param field
+     *            the field which is currently being rendered
+     * @param constraintValue
+     *            the value used to constrain input
+     * @param formatter
+     *            validation message, in the appropriate locale
+     * @param writer
+     *            markup writer, allowing additional attributes to be written into the active
+     *            element
+     * @param pageRenderSupport
+     *            used to generate client-side JavaScript to support validation
+     */
+    void render(Field field, C constraintValue, MessageFormatter formatter, MarkupWriter writer,
+            PageRenderSupport pageRenderSupport);
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractField.java Tue Feb 27 14:11:23 2007
@@ -22,6 +22,7 @@
 import org.apache.tapestry.Field;
 import org.apache.tapestry.FieldValidator;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.ValidationDecorator;
 import org.apache.tapestry.ValidationException;
 import org.apache.tapestry.annotations.AfterRender;
@@ -34,11 +35,10 @@
 import org.apache.tapestry.corelib.mixins.DiscardBody;
 import org.apache.tapestry.corelib.mixins.RenderDisabled;
 import org.apache.tapestry.corelib.mixins.RenderInformals;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.services.DefaultComponentParameterBindingSource;
 import org.apache.tapestry.services.FormSupport;
-import org.apache.tapestry.services.PageRenderSupport;
 
 /**
  * Provides initialization of the clientId and elementName properties. In addition, adds the
@@ -84,6 +84,10 @@
         {
             // Do nothing
         }
+
+        public void render(MarkupWriter writer)
+        {
+        }
     };
 
     static class SetupAction implements ComponentAction<AbstractField>, Serializable
@@ -150,7 +154,7 @@
 
         String key = componentId + "-label";
 
-        return containerMessages.contains(key) ? containerMessages.get(key) : TapestryUtils
+        return containerMessages.contains(key) ? containerMessages.get(key) : TapestryInternalUtils
                 .toUserPresentable(componentId);
     }
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/base/AbstractTextField.java Tue Feb 27 14:11:23 2007
@@ -138,6 +138,8 @@
             value = _translate.toClient(_value);
 
         writeFieldTag(writer, value);
+        
+        _validate.render(writer);
 
         getValidationDecorator().insideField(this);
     }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/ActionLink.java Tue Feb 27 14:11:23 2007
@@ -21,12 +21,12 @@
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Link;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.annotations.Environmental;
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.Mixin;
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.corelib.mixins.RenderInformals;
-import org.apache.tapestry.services.PageRenderSupport;
 
 /**
  * Component that triggers an action on the server with a subsequent full page refresh.

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Any.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Any.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Any.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Any.java Tue Feb 27 14:11:23 2007
@@ -14,13 +14,14 @@
 
 package org.apache.tapestry.corelib.components;
 
+import org.apache.tapestry.ClientElement;
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.annotations.Environmental;
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.annotations.SupportsInformalParameters;
-import org.apache.tapestry.services.PageRenderSupport;
 
 /**
  * The Any component is a swiss-army knife that emulates any arbitary element. Renders an element
@@ -30,7 +31,7 @@
  * template but does render its body.
  */
 @SupportsInformalParameters
-public class Any
+public class Any implements ClientElement
 {
     /**
      * The element to be rendered by the component. Normally, this matches the element from the

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/BeanEditForm.java Tue Feb 27 14:11:23 2007
@@ -17,6 +17,7 @@
 import java.util.Locale;
 
 import org.apache.tapestry.Block;
+import org.apache.tapestry.ClientElement;
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Field;
 import org.apache.tapestry.FieldValidator;
@@ -56,7 +57,7 @@
  * @see BeanModelSource
  */
 @SupportsInformalParameters
-public class BeanEditForm
+public class BeanEditForm implements ClientElement
 {
     /** The text label for the submit button of the form, by default "Create/Update". */
     @Parameter(value = "message:submit-label", defaultPrefix = "literal")
@@ -71,6 +72,10 @@
     @Parameter(required = true)
     private Object _object;
 
+    /** If true, the default, then the embedded Form component will use client-side validation. */
+    @Parameter("true")
+    private boolean _clientValidation;
+
     @Inject
     private ComponentResources _resources;
 
@@ -92,7 +97,7 @@
     @Inject
     private Block _checkbox;
 
-    @Component
+    @Component(parameters = "clientValidation=clientValidation")
     private Form _form;
 
     @Component(parameters =
@@ -261,8 +266,19 @@
         return _form;
     }
 
+    /** Returns the client id of the embedded form. */
+    public String getClientId()
+    {
+        return _form.getClientId();
+    }
+
     public String getSubmitLabel()
     {
         return _submitLabel;
+    }
+
+    public boolean getClientValidation()
+    {
+        return _clientValidation;
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Form.java Tue Feb 27 14:11:23 2007
@@ -14,17 +14,22 @@
 
 package org.apache.tapestry.corelib.components;
 
+import static java.lang.String.format;
+
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.util.List;
 
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.ClientElement;
 import org.apache.tapestry.ComponentAction;
 import org.apache.tapestry.ComponentEventHandler;
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Field;
 import org.apache.tapestry.Link;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.ValidationTracker;
 import org.apache.tapestry.ValidationTrackerImpl;
@@ -47,7 +52,6 @@
 import org.apache.tapestry.services.Environment;
 import org.apache.tapestry.services.FormSupport;
 import org.apache.tapestry.services.Heartbeat;
-import org.apache.tapestry.services.PageRenderSupport;
 
 /**
  * An HTML form, which will enclose other components to render out the various types of fields.
@@ -67,7 +71,7 @@
  * parameter. This context is encoded into the form's action URI (the parameter is not read when the
  * form is submitted, instead the values encoded into the form are used).
  */
-public class Form
+public class Form implements ClientElement
 {
     /**
      * Invoked to let the containing component(s) prepare for the form rendering or the form
@@ -124,6 +128,16 @@
      */
     public static final String FORM_DATA = "t:formdata";
 
+    /**
+     * If true (the default) then client validation is enabled for the form, and the default set of
+     * JavaScript libraries (Prototype, Scriptaculous and the Tapestry library) will be added to the
+     * rendered page, and the form will register itself for validation. This may be turned off when
+     * client validation is not desired; for example, when many validations are used that do not
+     * operate on the client side at all.
+     */
+    @Parameter("true")
+    private boolean _clientValidation;
+
     @Inject("infrastructure:Environment")
     private Environment _environment;
 
@@ -144,6 +158,17 @@
 
     private FormSupportImpl _formSupport;
 
+    private Element _div;
+
+    @Inject("${tapestry.scriptaculous}/prototype.js")
+    private Asset _prototype;
+
+    @Inject("${tapestry.scriptaculous}/scriptaculous.js")
+    private Asset _scriptaculous;
+
+    @Inject("classpath:/org/apache/tapestry/tapestry.js")
+    private Asset _tapestry;
+
     // Collects a stream of component actions. Each action goes in as a UTF string (the component
     // component id), followed by a ComponentAction
 
@@ -187,23 +212,19 @@
 
     }
 
-    private Element _div;
-
     void beginRender(MarkupWriter writer)
     {
         // Now that the environment is setup, inform the component or other listeners that the form
-        // is about to
-        // render.
+        // is about to render.
 
         Object[] contextArray = _context == null ? new Object[0] : _context.toArray();
 
         _resources.triggerEvent(PREPARE, contextArray, null);
 
-        String name = _pageRenderSupport.allocateClientId(_resources.getId());
+        _name = _pageRenderSupport.allocateClientId(_resources.getId());
 
-        Link link = _resources
-                .createActionLink(TapestryConstants.ACTION_EVENT, true, contextArray);
-        writer.element("form", "name", name, "id", name, "method", "post", "action", link);
+        Link link = _resources.createActionLink(TapestryConstants.ACTION_EVENT, true, contextArray);
+        writer.element("form", "name", _name, "id", _name, "method", "post", "action", link);
 
         _resources.renderInformalParameters(writer);
 
@@ -219,6 +240,13 @@
 
         writer.end(); // div
 
+        if (_clientValidation)
+        {
+            _pageRenderSupport.addScriptLink(_prototype, _scriptaculous, _tapestry);
+
+            _pageRenderSupport.addScript(format("Tapestry.registerForm('%s');", _name));
+        }
+
         _environment.peek(Heartbeat.class).begin();
 
     }
@@ -259,6 +287,8 @@
     @Inject("infrastructure:ComponentEventResultProcessor")
     private ComponentEventResultProcessor _eventResultProcessor;
 
+    private String _name;
+
     @SuppressWarnings("unchecked")
     Object onAction(Object[] context)
     {
@@ -432,4 +462,13 @@
     {
         _tracker.clear();
     }
+
+    /**
+     * Forms use the same value for their name and their id attribute.
+     */
+    public String getClientId()
+    {
+        return _name;
+    }
+
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridCell.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridCell.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridCell.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/GridCell.java Tue Feb 27 14:11:23 2007
@@ -20,7 +20,7 @@
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.beaneditor.PropertyModel;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 
 /**
  * Part of {@link Grid} that renders a single data cell. GridCell is used inside a pair of loops;
@@ -92,6 +92,6 @@
         if (value == null)
             return null;
 
-        return TapestryUtils.getLabelForEnum(_resources.getMessages(), value);
+        return TapestryInternalUtils.getLabelForEnum(_resources.getMessages(), value);
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Img.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Img.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Img.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/Img.java Tue Feb 27 14:11:23 2007
@@ -17,6 +17,7 @@
 import org.apache.tapestry.Asset;
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.annotations.AfterRender;
 import org.apache.tapestry.annotations.BeforeRenderBody;
 import org.apache.tapestry.annotations.BeginRender;
@@ -24,7 +25,6 @@
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.Parameter;
 import org.apache.tapestry.annotations.SupportsInformalParameters;
-import org.apache.tapestry.services.PageRenderSupport;
 
 /**
  * Renders an HTML img element using a supplied {@link Asset} as the image source. This is useful

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/PageLink.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/PageLink.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/PageLink.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/corelib/components/PageLink.java Tue Feb 27 14:11:23 2007
@@ -19,10 +19,10 @@
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Link;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.annotations.Environmental;
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.Parameter;
-import org.apache.tapestry.services.PageRenderSupport;
 
 /**
  * Generates a render request link to some other page in the application. If an activation context

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionGroupModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionGroupModelImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionGroupModelImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionGroupModelImpl.java Tue Feb 27 14:11:23 2007
@@ -33,7 +33,7 @@
     public OptionGroupModelImpl(String label, boolean disabled, List<OptionModel> options,
             String... attributeKeysAndValues)
     {
-        this(label, disabled, options, attributeKeysAndValues.length == 0 ? null : TapestryUtils
+        this(label, disabled, options, attributeKeysAndValues.length == 0 ? null : TapestryInternalUtils
                 .mapFromKeysAndValues(attributeKeysAndValues));
     }
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionModelImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionModelImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/OptionModelImpl.java Tue Feb 27 14:11:23 2007
@@ -30,7 +30,7 @@
 
     public OptionModelImpl(String label, boolean disabled, Object value, String... keysAndValues)
     {
-        this(label, disabled, value, keysAndValues.length > 0 ? TapestryUtils
+        this(label, disabled, value, keysAndValues.length > 0 ? TapestryInternalUtils
                 .mapFromKeysAndValues(keysAndValues) : null);
     }
 

Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java (from r510990, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java?view=diff&rev=512442&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java&r1=510990&p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryUtils.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java Tue Feb 27 14:11:23 2007
@@ -39,11 +39,11 @@
 import org.apache.tapestry.ioc.services.PropertyAdapter;
 
 /** Shared utility methods used by various implementation classes. */
-public class TapestryUtils
+public class TapestryInternalUtils
 {
     private static final URLCodec CODEC = new URLCodec();
 
-    private TapestryUtils()
+    private TapestryInternalUtils()
     {
         // Prevent instantiation.
     }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyModelImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyModelImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/beaneditor/PropertyModelImpl.java Tue Feb 27 14:11:23 2007
@@ -19,7 +19,7 @@
 import org.apache.tapestry.PropertyConduit;
 import org.apache.tapestry.beaneditor.BeanModel;
 import org.apache.tapestry.beaneditor.PropertyModel;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.services.ClassFabUtils;
 
@@ -48,10 +48,10 @@
         _name = name;
         _conduit = conduit;
 
-        _id = TapestryUtils.extractIdFromPropertyExpression(name);
-        _order = TapestryUtils.defaultOrder(conduit);
+        _id = TapestryInternalUtils.extractIdFromPropertyExpression(name);
+        _order = TapestryInternalUtils.defaultOrder(conduit);
 
-        _label = TapestryUtils.defaultLabel(_id, messages, name);
+        _label = TapestryInternalUtils.defaultLabel(_id, messages, name);
 
         // Primitive types need to be converted to wrapper types before checking to see
         // if they are sortable.

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/BeanModelSourceImpl.java Tue Feb 27 14:11:23 2007
@@ -24,7 +24,7 @@
 import org.apache.tapestry.beaneditor.BeanModel;
 import org.apache.tapestry.beaneditor.NonVisual;
 import org.apache.tapestry.events.InvalidationListener;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.internal.beaneditor.BeanModelImpl;
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.services.ClassFactory;
@@ -107,7 +107,7 @@
 
         // Set default property order for properties that are not explicit.
 
-        List<String> orderedNames = TapestryUtils.orderProperties(
+        List<String> orderedNames = TapestryInternalUtils.orderProperties(
                 adapter,
                 _classFactory,
                 propertyNames);

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java Tue Feb 27 14:11:23 2007
@@ -18,7 +18,7 @@
 
 import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.internal.InternalConstants;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.Dispatcher;
 import org.apache.tapestry.services.Request;
@@ -130,7 +130,7 @@
 
         for (int i = 0; i < result.length; i++)
         {
-            result[i] = TapestryUtils.urlDecode(result[i]);
+            result[i] = TapestryInternalUtils.urlDecode(result[i]);
         }
 
         return result;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java Tue Feb 27 14:11:23 2007
@@ -28,7 +28,7 @@
 import java.util.Enumeration;
 import java.util.jar.JarEntry;
 
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry.ioc.util.Stack;
 
@@ -184,7 +184,7 @@
         }
         finally
         {
-            TapestryUtils.close(lineReader);
+            TapestryInternalUtils.close(lineReader);
         }
 
     }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInvocation.java Tue Feb 27 14:11:23 2007
@@ -19,7 +19,7 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.test.pagelevel.PageTester;
 
@@ -106,7 +106,7 @@
         {
             builder.append("/");
 
-            builder.append(TapestryUtils.urlEncode(id));
+            builder.append(TapestryInternalUtils.urlEncode(id));
         }
 
         return builder.toString();

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java Tue Feb 27 14:11:23 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
 import org.apache.tapestry.annotations.MixinClasses;
 import org.apache.tapestry.annotations.Mixins;
 import org.apache.tapestry.internal.KeyValue;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.model.ComponentModel;
 import org.apache.tapestry.model.MutableComponentModel;
@@ -110,7 +110,7 @@
     {
         for (String parameter : parameters)
         {
-            KeyValue kv = TapestryUtils.parseKeyValue(parameter);
+            KeyValue kv = TapestryInternalUtils.parseKeyValue(parameter);
 
             embedded.addParameter(kv.getKey(), kv.getValue());
         }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/CompositeFieldValidator.java Tue Feb 27 14:11:23 2007
@@ -17,6 +17,7 @@
 import java.util.List;
 
 import org.apache.tapestry.FieldValidator;
+import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.ValidationException;
 
 /** Aggregates together a number of field validator instances as a single unit. */
@@ -35,4 +36,11 @@
         for (FieldValidator fv : _validators)
             fv.validate(value);
     }
+
+    public void render(MarkupWriter writer)
+    {
+        for (FieldValidator fv : _validators)
+            fv.render(writer);
+    }
+
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/EnvironmentalShadowBuilderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/EnvironmentalShadowBuilderImpl.java?view=auto&rev=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/EnvironmentalShadowBuilderImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/EnvironmentalShadowBuilderImpl.java Tue Feb 27 14:11:23 2007
@@ -0,0 +1,81 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import static java.lang.String.format;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+
+import org.apache.tapestry.ioc.services.ClassFab;
+import org.apache.tapestry.ioc.services.ClassFactory;
+import org.apache.tapestry.ioc.services.MethodSignature;
+import org.apache.tapestry.services.Environment;
+import org.apache.tapestry.services.EnvironmentalShadowBuilder;
+
+public class EnvironmentalShadowBuilderImpl implements EnvironmentalShadowBuilder
+{
+    private final ClassFactory _classFactory;
+
+    private final Environment _environment;
+
+    public EnvironmentalShadowBuilderImpl(final ClassFactory classFactory,
+            final Environment environment)
+    {
+        _classFactory = classFactory;
+        _environment = environment;
+    }
+
+    public <T> T build(Class<T> serviceType)
+    {
+        // TODO: Check that serviceType is an interface?
+
+        Class proxyClass = buildProxyClass(serviceType);
+
+        try
+        {
+            Constructor cons = proxyClass.getConstructors()[0];
+
+            Object raw = cons.newInstance(_environment, serviceType);
+
+            return serviceType.cast(raw);
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private Class buildProxyClass(Class serviceType)
+    {
+        ClassFab classFab = _classFactory.newClass(serviceType);
+
+        classFab.addField("_environment", Environment.class);
+        classFab.addField("_serviceType", Class.class);
+
+        classFab.addConstructor(new Class[]
+        { Environment.class, Class.class }, null, "{ _environment = $1; _serviceType = $2; }");
+
+        classFab.addMethod(Modifier.PRIVATE, new MethodSignature(serviceType, "_delegate", null,
+                null), "return ($r) _environment.peekRequired(_serviceType); ");
+
+        classFab.proxyMethodsToDelegate(serviceType, "_delegate()", format(
+                "<EnvironmentalProxy for %s>",
+                serviceType.getName()));
+
+        return classFab.createClass();
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorImpl.java Tue Feb 27 14:11:23 2007
@@ -16,6 +16,8 @@
 
 import org.apache.tapestry.Field;
 import org.apache.tapestry.FieldValidator;
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.ValidationException;
 import org.apache.tapestry.Validator;
 import org.apache.tapestry.ioc.MessageFormatter;
@@ -30,25 +32,37 @@
 
     private final Validator _validator;
 
+    private final PageRenderSupport _pageRenderSupport;
+
     public FieldValidatorImpl(Field field, Object constraintValue,
-            MessageFormatter messageFormatter, Validator validator)
+            MessageFormatter messageFormatter, Validator validator,
+            PageRenderSupport pageRenderSupport)
     {
         _field = field;
         _constraintValue = constraintValue;
         _messageFormatter = messageFormatter;
         _validator = validator;
+        _pageRenderSupport = pageRenderSupport;
     }
 
     @SuppressWarnings("unchecked")
     public void validate(Object value) throws ValidationException
     {
-        if (! _validator.invokeIfBlank() && isBlank(value))
+        if (!_validator.invokeIfBlank() && isBlank(value))
             return;
 
         if (value != null && !_validator.getValueType().isInstance(value))
             return;
 
         _validator.validate(_field, _constraintValue, _messageFormatter, value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void render(MarkupWriter writer)
+    {
+        // TODO: Skip this step if the Form's clientValidatio parameter is false?
+
+        _validator.render(_field, _constraintValue, _messageFormatter, writer, _pageRenderSupport);
     }
 
     private boolean isBlank(Object value)

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/FieldValidatorSourceImpl.java Tue Feb 27 14:11:23 2007
@@ -25,6 +25,7 @@
 import org.apache.tapestry.ComponentResources;
 import org.apache.tapestry.Field;
 import org.apache.tapestry.FieldValidator;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.Validator;
 import org.apache.tapestry.ioc.MessageFormatter;
 import org.apache.tapestry.ioc.Messages;
@@ -42,11 +43,15 @@
 
     private final TypeCoercer _typeCoercer;
 
+    private final PageRenderSupport _pageRenderSupport;
+
     public FieldValidatorSourceImpl(ValidationMessagesSource messagesSource,
-            TypeCoercer typeCoercer, Map<String, Validator> validators)
+            TypeCoercer typeCoercer, PageRenderSupport pageRenderSupport,
+            Map<String, Validator> validators)
     {
         _messagesSource = messagesSource;
         _typeCoercer = typeCoercer;
+        _pageRenderSupport = pageRenderSupport;
         _validators = validators;
     }
 
@@ -95,7 +100,8 @@
                 validatorType,
                 validator);
 
-        return new FieldValidatorImpl(field, coercedConstraintValue, formatter, validator);
+        return new FieldValidatorImpl(field, coercedConstraintValue, formatter, validator,
+                _pageRenderSupport);
     }
 
     private MessageFormatter findMessageFormatter(String overrideId, Messages overrideMessages,

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/LocationRenderer.java Tue Feb 27 14:11:23 2007
@@ -26,7 +26,7 @@
 import java.util.Set;
 
 import org.apache.tapestry.MarkupWriter;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.Location;
 import org.apache.tapestry.ioc.Resource;
 import org.apache.tapestry.services.ObjectRenderer;
@@ -124,7 +124,7 @@
         }
         finally
         {
-            TapestryUtils.close(reader);
+            TapestryInternalUtils.close(reader);
         }
 
         writer.end(); // div

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MessagesSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MessagesSourceImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MessagesSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MessagesSourceImpl.java Tue Feb 27 14:11:23 2007
@@ -27,7 +27,7 @@
 import java.util.Map;
 import java.util.Properties;
 
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.internal.event.InvalidationEventHubImpl;
 import org.apache.tapestry.internal.util.MultiKey;
 import org.apache.tapestry.internal.util.URLChangeTracker;
@@ -228,7 +228,7 @@
         }
         finally
         {
-            TapestryUtils.close(is);
+            TapestryInternalUtils.close(is);
         }
 
         for (Map.Entry e : p.entrySet())

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MetaWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MetaWorker.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MetaWorker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/MetaWorker.java Tue Feb 27 14:11:23 2007
@@ -16,7 +16,7 @@
 
 import org.apache.tapestry.annotations.Meta;
 import org.apache.tapestry.internal.KeyValue;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.model.MutableComponentModel;
 import org.apache.tapestry.services.ClassTransformation;
 import org.apache.tapestry.services.ComponentClassTransformWorker;
@@ -37,7 +37,7 @@
 
         for (String meta : annotation.value())
         {
-            KeyValue kv = TapestryUtils.parseKeyValue(meta);
+            KeyValue kv = TapestryInternalUtils.parseKeyValue(meta);
 
             model.setMeta(kv.getKey(), kv.getValue());
         }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java Tue Feb 27 14:11:23 2007
@@ -16,7 +16,7 @@
 
 import java.io.IOException;
 
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.internal.structure.Page;
 import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentClassResolver;
@@ -118,7 +118,7 @@
 
         for (int i = 0; i < context.length; i++)
         {
-            context[i] = TapestryUtils.urlDecode(context[i]);
+            context[i] = TapestryInternalUtils.urlDecode(context[i]);
         }
 
         return context;

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderSupportImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderSupportImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderSupportImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageRenderSupportImpl.java Tue Feb 27 14:11:23 2007
@@ -14,10 +14,15 @@
 
 package org.apache.tapestry.internal.services;
 
+import static java.lang.String.format;
+import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
+
 import org.apache.tapestry.Asset;
-import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.PageRenderSupport;
+import org.apache.tapestry.ioc.Resource;
 import org.apache.tapestry.ioc.internal.util.IdAllocator;
-import org.apache.tapestry.services.PageRenderSupport;
+import org.apache.tapestry.ioc.services.SymbolSource;
+import org.apache.tapestry.services.AssetFactory;
 
 public class PageRenderSupportImpl implements PageRenderSupport
 {
@@ -25,9 +30,16 @@
 
     private final DocumentScriptBuilder _builder;
 
-    public PageRenderSupportImpl(DocumentScriptBuilder builder)
+    private final SymbolSource _symbolSource;
+
+    private final AssetFactory _assetFactory;
+
+    public PageRenderSupportImpl(DocumentScriptBuilder builder, SymbolSource symbolSource,
+            AssetFactory classpathAssetFactory)
     {
         _builder = builder;
+        _symbolSource = symbolSource;
+        _assetFactory = classpathAssetFactory;
     }
 
     public String allocateClientId(String id)
@@ -35,15 +47,34 @@
         return _idAllocator.allocateId(id);
     }
 
-    public void addScriptLink(Asset scriptAsset)
+    public void addScriptLink(Asset... scriptAssets)
+    {
+        for (Asset asset : scriptAssets)
+        {
+            notNull(asset, "scriptAsset");
+
+            _builder.addScriptLink(asset.toClientURL());
+        }
+    }
+
+    public void addClasspathScriptLink(String... classpaths)
     {
-        Defense.notNull(scriptAsset, "scriptAsset");
+        for (String path : classpaths)
+        {
+            String expanded = _symbolSource.expandSymbols(path);
+
+            Resource resource = _assetFactory.getRootResource().forFile(expanded);
 
-        _builder.addScriptLink(scriptAsset.toString());
+            Asset asset = _assetFactory.createAsset(resource);
+
+            _builder.addScriptLink(asset.toClientURL());
+        }
     }
 
-    public void addScript(String script)
+    public void addScript(String format, Object... arguments)
     {
+        String script = format(format, arguments);
+
         _builder.addScript(script);
     }
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceDigestGeneratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceDigestGeneratorImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceDigestGeneratorImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceDigestGeneratorImpl.java Tue Feb 27 14:11:23 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
 import java.security.MessageDigest;
 
 import org.apache.commons.codec.binary.Hex;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.services.ResourceDigestGenerator;
 
 /**
@@ -59,7 +59,7 @@
         }
         finally
         {
-            TapestryUtils.close(stream);
+            TapestryInternalUtils.close(stream);
         }
     }
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceStreamerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceStreamerImpl.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceStreamerImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ResourceStreamerImpl.java Tue Feb 27 14:11:23 2007
@@ -21,7 +21,7 @@
 import java.net.URL;
 import java.net.URLConnection;
 
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.Resource;
 import org.apache.tapestry.services.Response;
 
@@ -95,7 +95,7 @@
         }
         finally
         {
-            TapestryUtils.close(is);
+            TapestryInternalUtils.close(is);
         }
 
     }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/StreamResponseResultProcessor.java Tue Feb 27 14:11:23 2007
@@ -20,7 +20,7 @@
 import java.io.OutputStream;
 
 import org.apache.tapestry.StreamResponse;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.services.ActionResponseGenerator;
 import org.apache.tapestry.services.ComponentEventResultProcessor;
@@ -65,8 +65,8 @@
                 }
                 finally
                 {
-                    TapestryUtils.close(is);
-                    TapestryUtils.close(os);
+                    TapestryInternalUtils.close(is);
+                    TapestryInternalUtils.close(os);
                 }
             }
 

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=512442&r1=512441&r2=512442
==============================================================================
--- 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 Tue Feb 27 14:11:23 2007
@@ -992,17 +992,23 @@
         if (handler == null)
             handler = new NotificationEventHandler(eventType, _completeId);
 
-        ComponentEvent event = new ComponentEventImpl(eventType, _id, context, handler,
-                _typeCoercer);
-
         ComponentPageElement component = this;
+        String componentId = "";
 
         while (component != null)
         {
+            ComponentEvent event = new ComponentEventImpl(eventType, componentId, context, handler,
+                    _typeCoercer);
+
             result |= component.handleEvent(event);
 
             if (event.isAborted())
                 return result;
+
+            // On each bubble up, make the event appear to come from the previous component
+            // in which the event was triggered.
+
+            componentId = component.getId();
 
             component = component.getContainerElement();
         }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java Tue Feb 27 14:11:23 2007
@@ -39,6 +39,7 @@
 import org.apache.tapestry.internal.services.ComponentInstantiatorSource;
 import org.apache.tapestry.internal.services.ComponentInvocationMap;
 import org.apache.tapestry.internal.services.ComponentTemplateSource;
+import org.apache.tapestry.internal.services.DocumentScriptBuilder;
 import org.apache.tapestry.internal.services.FormParameterLookup;
 import org.apache.tapestry.internal.services.Instantiator;
 import org.apache.tapestry.internal.services.LinkFactory;
@@ -401,12 +402,12 @@
         expect(cache.requiresDigest(resource)).andReturn(requiresChecksum);
     }
 
-    protected InvalidationListener newInvalidationListener()
+    protected final InvalidationListener newInvalidationListener()
     {
         return newMock(InvalidationListener.class);
     }
 
-    protected void train_getTimeModified(ResourceCache cache, Resource resource, long timeModified)
+    protected final void train_getTimeModified(ResourceCache cache, Resource resource, long timeModified)
     {
         expect(cache.getTimeModified(resource)).andReturn(timeModified).atLeastOnce();
     }
@@ -451,7 +452,7 @@
         return newMock(LinkFactoryListener.class);
     }
 
-    protected ComponentInvocationMap newComponentInvocationMap()
+    protected final ComponentInvocationMap newComponentInvocationMap()
     {
         return newMock(ComponentInvocationMap.class);
     }
@@ -533,5 +534,10 @@
         in.close();
 
         return buffer.toString();
+    }
+
+    protected final DocumentScriptBuilder newDocumentScriptBuilder()
+    {
+        return newMock(DocumentScriptBuilder.class);
     }
 }

Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/EnvironmentalShadowBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/EnvironmentalShadowBuilder.java?view=auto&rev=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/EnvironmentalShadowBuilder.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/EnvironmentalShadowBuilder.java Tue Feb 27 14:11:23 2007
@@ -0,0 +1,40 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.services;
+
+import org.apache.tapestry.annotations.Environmental;
+import org.apache.tapestry.ioc.services.PropertyShadowBuilder;
+
+/**
+ * Much like {@link PropertyShadowBuilder}, except that instead of accessing a property of some
+ * other service, it accesses a value from within the {@link Environment} service. This is useful
+ * for defining a new service that can be injected into other services (whereas the
+ * {@link Environmental} annotation may only be used within component classes).
+ */
+public interface EnvironmentalShadowBuilder
+{
+    /**
+     * Returns a proxy that delegates all methods to an object obtained from
+     * {@link Environment#peekRequired(Class)}. Note that at the time this method is invoked, the
+     * Environment service may still be virtual, and will often not yet have been loaded with
+     * values, and that's OK, the resolution is deferred to the instant a method is invoked.
+     * 
+     * @param <T>
+     * @param serviceType
+     *            the service type, which is used to obtained the delegate instance
+     * @return a proxy to the service
+     */
+    <T> T build(Class<T> serviceType);
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Tue Feb 27 14:11:23 2007
@@ -28,6 +28,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.tapestry.Link;
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.SelectModel;
 import org.apache.tapestry.StreamResponse;
 import org.apache.tapestry.TapestryConstants;
@@ -50,7 +51,7 @@
 import org.apache.tapestry.dom.DefaultMarkupModel;
 import org.apache.tapestry.dom.Document;
 import org.apache.tapestry.grid.GridDataSource;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.internal.beaneditor.PrimitiveFieldConstraintGenerator;
 import org.apache.tapestry.internal.beaneditor.ValidateAnnotationConstraintGenerator;
 import org.apache.tapestry.internal.bindings.BlockBindingFactory;
@@ -93,6 +94,7 @@
 import org.apache.tapestry.internal.services.DocumentScriptBuilder;
 import org.apache.tapestry.internal.services.DocumentScriptBuilderImpl;
 import org.apache.tapestry.internal.services.EnvironmentImpl;
+import org.apache.tapestry.internal.services.EnvironmentalShadowBuilderImpl;
 import org.apache.tapestry.internal.services.EnvironmentalWorker;
 import org.apache.tapestry.internal.services.FieldValidatorDefaultSourceImpl;
 import org.apache.tapestry.internal.services.FieldValidatorSourceImpl;
@@ -968,7 +970,13 @@
             ThreadLocale threadLocale,
 
             @Inject("infrastructure:AssetSource")
-            AssetSource assetSource)
+            AssetSource assetSource,
+
+            @Inject("service:tapestry.ioc.SymbolSource")
+            final SymbolSource symbolSource,
+
+            @Inject("service:tapestry.internal.ClasspathAssetFactory")
+            final AssetFactory classpathAssetFactory)
     {
         configuration.add("PageRenderSupport", new PageRenderCommand()
         {
@@ -977,7 +985,8 @@
                 DocumentScriptBuilder builder = new DocumentScriptBuilderImpl();
 
                 environment.push(DocumentScriptBuilder.class, builder);
-                environment.push(PageRenderSupport.class, new PageRenderSupportImpl(builder));
+                environment.push(PageRenderSupport.class, new PageRenderSupportImpl(builder,
+                        symbolSource, classpathAssetFactory));
             }
 
             public void cleanup(Environment environment)
@@ -1126,9 +1135,13 @@
             @Inject("infrastructure:TypeCoercer")
             TypeCoercer typeCoercer,
 
+            @Inject("service:PageRenderSupport")
+            PageRenderSupport pageRenderSupport,
+
             Map<String, Validator> configuration)
     {
-        return new FieldValidatorSourceImpl(messagesSource, typeCoercer, configuration);
+        return new FieldValidatorSourceImpl(messagesSource, typeCoercer, pageRenderSupport,
+                configuration);
     }
 
     /**
@@ -1223,7 +1236,7 @@
         {
             public SelectModel coerce(String input)
             {
-                return TapestryUtils.toSelectModel(input);
+                return TapestryInternalUtils.toSelectModel(input);
             }
         });
 
@@ -1231,7 +1244,7 @@
         {
             public SelectModel coerce(Map input)
             {
-                return TapestryUtils.toSelectModel(input);
+                return TapestryInternalUtils.toSelectModel(input);
             }
         });
 
@@ -1514,5 +1527,24 @@
         configuration.add(Request.class, new RequestRenderer());
 
         configuration.add(Location.class, locationRenderer);
+    }
+
+    /**
+     * A service for building proxies that shadow a value stored in the {@link Environment}.
+     */
+    public EnvironmentalShadowBuilder buildEnvironmentalShadowBuilder(
+            @Inject("service:tapestry.ioc.ClassFactory")
+            ClassFactory classFactory)
+    {
+        return new EnvironmentalShadowBuilderImpl(classFactory, _environment);
+    }
+
+    /**
+     * Builds a proxy to the current PageRenderSupport inside this threads {@link Environment}.
+     */
+    public PageRenderSupport buildPageRenderSupport(@Inject("service:EnvironmentalShadowBuilder")
+    EnvironmentalShadowBuilder builder)
+    {
+        return builder.build(PageRenderSupport.class);
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Tue Feb 27 14:11:23 2007
@@ -871,4 +871,19 @@
     
         getMocksControl().andAnswer(answer);
     }
+
+    protected final void train_toClientURL(Asset asset, String URL)
+    {
+        expect(asset.toClientURL()).andReturn(URL).atLeastOnce();
+    }
+
+    protected final void train_forFile(Resource resource, String relativePath, Resource file)
+    {
+        expect(resource.forFile(relativePath)).andReturn(file);
+    }
+
+    protected final void train_forLocale(Resource base, Locale locale, Resource resource)
+    {
+        expect(base.forLocale(locale)).andReturn(resource);
+    }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/EnumSelectModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/EnumSelectModel.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/EnumSelectModel.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/util/EnumSelectModel.java Tue Feb 27 14:11:23 2007
@@ -23,7 +23,7 @@
 import org.apache.tapestry.OptionModel;
 import org.apache.tapestry.SelectModel;
 import org.apache.tapestry.internal.OptionModelImpl;
-import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.ioc.IOCUtilities;
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.internal.util.Defense;
@@ -58,7 +58,7 @@
 
         for (T value : values)
         {
-            String label = TapestryUtils.getLabelForEnum(messages, prefix, value);
+            String label = TapestryInternalUtils.getLabelForEnum(messages, prefix, value);
 
             _options.add(new OptionModelImpl(label, false, value));
         }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Max.java Tue Feb 27 14:11:23 2007
@@ -14,7 +14,11 @@
 
 package org.apache.tapestry.validator;
 
+import static org.apache.tapestry.TapestryUtils.quote;
+
 import org.apache.tapestry.Field;
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.ValidationException;
 import org.apache.tapestry.Validator;
 import org.apache.tapestry.ioc.MessageFormatter;
@@ -46,6 +50,23 @@
             throws ValidationException
     {
         if (value.longValue() > constraintValue)
-            throw new ValidationException(formatter.format(constraintValue, field.getLabel()));
+            throw new ValidationException(buildMessage(formatter, field, constraintValue));
     }
+
+    private String buildMessage(MessageFormatter formatter, Field field, Long constraintValue)
+    {
+        return formatter.format(constraintValue, field.getLabel());
+    }
+
+    public void render(Field field, Long constraintValue, MessageFormatter formatter,
+            MarkupWriter writer, PageRenderSupport pageRenderSupport)
+    {
+        pageRenderSupport.addScript(
+                "Tapestry.Field.max('%s', %d, %s);",
+                field.getClientId(),
+                constraintValue,
+                quote(buildMessage(formatter, field, constraintValue)));
+
+    }
+
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/MaxLength.java Tue Feb 27 14:11:23 2007
@@ -14,7 +14,11 @@
 
 package org.apache.tapestry.validator;
 
+import static org.apache.tapestry.TapestryUtils.quote;
+
 import org.apache.tapestry.Field;
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.ValidationException;
 import org.apache.tapestry.Validator;
 import org.apache.tapestry.ioc.MessageFormatter;
@@ -41,10 +45,25 @@
         return false;
     }
 
-    public void validate(Field field, Integer constraintValue, MessageFormatter formatter, String value)
-            throws ValidationException
+    public void validate(Field field, Integer constraintValue, MessageFormatter formatter,
+            String value) throws ValidationException
     {
         if (value.length() > constraintValue)
-            throw new ValidationException(formatter.format(constraintValue, field.getLabel()));
+            throw new ValidationException(buildMessage(formatter, field, constraintValue));
+    }
+
+    private String buildMessage(MessageFormatter formatter, Field field, Integer constraintValue)
+    {
+        return formatter.format(constraintValue, field.getLabel());
+    }
+
+    public void render(Field field, Integer constraintValue, MessageFormatter formatter,
+            MarkupWriter writer, PageRenderSupport pageRenderSupport)
+    {
+        pageRenderSupport.addScript(
+                "Tapestry.Field.maxlength('%s', %d, %s);",
+                field.getClientId(),
+                constraintValue,
+                quote(buildMessage(formatter, field, constraintValue)));
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java?view=diff&rev=512442&r1=512441&r2=512442
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/validator/Min.java Tue Feb 27 14:11:23 2007
@@ -14,7 +14,11 @@
 
 package org.apache.tapestry.validator;
 
+import static org.apache.tapestry.TapestryUtils.quote;
+
 import org.apache.tapestry.Field;
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.PageRenderSupport;
 import org.apache.tapestry.ValidationException;
 import org.apache.tapestry.Validator;
 import org.apache.tapestry.ioc.MessageFormatter;
@@ -46,6 +50,21 @@
             throws ValidationException
     {
         if (value.longValue() < constraintValue)
-            throw new ValidationException(formatter.format(constraintValue, field.getLabel()));
+            throw new ValidationException(buildMessage(formatter, field, constraintValue));
+    }
+
+    private String buildMessage(MessageFormatter formatter, Field field, Long constraintValue)
+    {
+        return formatter.format(constraintValue, field.getLabel());
+    }
+
+    public void render(Field field, Long constraintValue, MessageFormatter formatter,
+            MarkupWriter writer, PageRenderSupport pageRenderSupport)
+    {
+        pageRenderSupport.addScript(
+                "Tapestry.Field.min('%s', %s, %s);",
+                field.getClientId(),
+                constraintValue,
+                quote(buildMessage(formatter, field, constraintValue)));
     }
 }