You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2005/01/27 19:40:29 UTC
cvs commit: jakarta-tapestry/framework/src/scripts TestWMLFormComponents.xml TestWMLComponents.xml
hlship 2005/01/27 10:40:29
Modified: . status.xml
framework/src/java/org/apache/tapestry/form Form.java
framework/src/java/org/apache/tapestry/util IdAllocator.java
framework/src/java/org/apache/tapestry
TapestryStrings.properties
src/documentation/content/xdocs dev.xml
framework/src/java/org/apache/tapestry/services
ServiceConstants.java
framework/src/scripts TestWMLFormComponents.xml
TestWMLComponents.xml
Added: framework/src/java/org/apache/tapestry/form
FormMessages.java FormStrings.properties
Log:
Changed to Form to prevent collisions between query parameters supplied by services (in an ILink) and form element ids.
Revision Changes Path
1.56 +4 -0 jakarta-tapestry/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/status.xml,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- status.xml 27 Jan 2005 14:20:45 -0000 1.55
+++ status.xml 27 Jan 2005 18:40:28 -0000 1.56
@@ -299,6 +299,10 @@
</action>
+ <action type="update" dev="HLS">
+ Changed to Form to prevent collisions between query parameters supplied
+ by services (in an ILink) and form element ids.
+ </action>
</release>
1.9 +107 -42 jakarta-tapestry/framework/src/java/org/apache/tapestry/form/Form.java
Index: Form.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/form/Form.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- Form.java 6 Jan 2005 02:17:18 -0000 1.8
+++ Form.java 27 Jan 2005 18:40:29 -0000 1.9
@@ -15,10 +15,13 @@
package org.apache.tapestry.form;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.HiveMind;
@@ -37,6 +40,7 @@
import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.html.Body;
+import org.apache.tapestry.services.ServiceConstants;
import org.apache.tapestry.util.IdAllocator;
import org.apache.tapestry.util.StringSplitter;
import org.apache.tapestry.valid.IValidationDelegate;
@@ -125,6 +129,15 @@
private List _hiddenValues;
/**
+ * @since 3.1
+ */
+ private Set _standardReservedIds = new HashSet();
+
+ {
+ _standardReservedIds.addAll(Arrays.asList(ServiceConstants.RESERVED_IDS));
+ }
+
+ /**
* Returns the currently active {@link IForm}, or null if no form is active. This is a
* convienience method, the result will be null, or an instance of {@link IForm}, but not
* necessarily a <code>Form</code>.
@@ -206,19 +219,21 @@
{
if (_allocatedIdIndex >= _allocatedIds.size())
{
- throw new StaleLinkException(Tapestry.format(
- "Form.too-many-ids",
- getExtendedId(),
- Integer.toString(_allocatedIds.size()),
- component.getExtendedId()), this);
+ throw new StaleLinkException(FormMessages.formTooManyIds(
+ this,
+ _allocatedIds.size(),
+ component), this);
}
String expected = (String) _allocatedIds.get(_allocatedIdIndex);
if (!result.equals(expected))
- throw new StaleLinkException(Tapestry.format("Form.id-mismatch", new Object[]
- { getExtendedId(), Integer.toString(_allocatedIdIndex + 1), expected, result,
- component.getExtendedId() }), this);
+ throw new StaleLinkException(FormMessages.formIdMismatch(
+ this,
+ _allocatedIdIndex,
+ expected,
+ result,
+ component), this);
}
else
{
@@ -258,8 +273,7 @@
super.prepareForRender(cycle);
if (cycle.getAttribute(ATTRIBUTE_NAME) != null)
- throw new ApplicationRuntimeException(Tapestry.getMessage("Form.forms-may-not-nest"),
- this, null, null);
+ throw new ApplicationRuntimeException(FormMessages.formsMayNotNest(), this, null, null);
cycle.setAttribute(ATTRIBUTE_NAME, this);
}
@@ -312,13 +326,7 @@
_allocatedIdIndex = 0;
if (rewound)
- {
- String storedIdList = cycle.getRequestContext().getParameter(_name);
-
- reconstructAllocatedIds(storedIdList);
- }
-
- ILink link = getLink(cycle, actionId);
+ reconstructAllocatedIds(cycle);
// When rendering, use a nested writer so that an embedded Upload
// component can force the encoding type.
@@ -329,19 +337,18 @@
if (renderForm)
{
+ ILink link = getLink(cycle, actionId);
+
writeAttributes(writer, link);
renderInformalParameters(writer, cycle);
writer.println();
- }
- // Write the hidden's, or at least, reserve the query parameters
- // required by the Gesture.
+ // Write the hidden's, or at least, reserve the query parameters
+ // required by the Gesture.
- writeLinkParameters(writer, link, !renderForm);
+ String extraIds = writeLinkParameters(writer, link, !renderForm);
- if (renderForm)
- {
// What's this for? It's part of checking for stale links.
// We record the list of allocated ids.
// On rewind, we check that the stored list against which
@@ -351,6 +358,10 @@
// of ids will change as well.
writeHiddenField(writer, _name, buildAllocatedIdList());
+
+ if (HiveMind.isNonBlank(extraIds))
+ writeHiddenField(writer, _name, extraIds);
+
writeHiddenValues(writer);
nested.close();
@@ -374,11 +385,8 @@
{
String nextExpectedId = (String) _allocatedIds.get(_allocatedIdIndex);
- throw new StaleLinkException(Tapestry.format(
- "Form.too-few-ids",
- getExtendedId(),
- Integer.toString(expected - _allocatedIdIndex),
- nextExpectedId), this);
+ throw new StaleLinkException(FormMessages.formTooFewIds(this, expected
+ - _allocatedIdIndex, nextExpectedId), this);
}
IActionListener listener = getListener();
@@ -443,8 +451,8 @@
Body body = Body.get(cycle);
if (body == null)
- throw new ApplicationRuntimeException(Tapestry
- .getMessage("Form.needs-body-for-event-handlers"), this, null, null);
+ throw new ApplicationRuntimeException(FormMessages.formNeedsBodyForEventHandlers(),
+ this, null, null);
StringBuffer buffer = new StringBuffer();
@@ -571,22 +579,60 @@
return service.getLink(cycle, parameter);
}
- private void writeLinkParameters(IMarkupWriter writer, ILink link, boolean reserveOnly)
+ /**
+ * Writes parameters provided by the {@link ILink}. These parameters define the information
+ * needed to dispatch the request, plus state information. The names of these parameters must be
+ * reserved so that conflicts don't occur that could disrupt the request processing. For
+ * example, if the id 'page' is not reserved, then a conflict could occur with a component whose
+ * id is 'page'. A certain number of ids are always reserved, and we find any additional ids
+ * beyond that set.
+ *
+ * @return a list of additional reserved ids (not contained within
+ * {@link ServiceConstants#RESERVED_IDS}.
+ */
+
+ private String writeLinkParameters(IMarkupWriter writer, ILink link, boolean reserveOnly)
{
String[] names = link.getParameterNames();
int count = Tapestry.size(names);
+ StringBuffer extraIds = new StringBuffer();
+ String sep = "";
+
+ // All the reserved ids, which are essential for
+ // dispatching the request, are automatically reserved.
+ // Thus, if you have a component with an id of 'service', its element id
+ // will likely be 'service$0'.
+
+ preallocateReservedIds();
+
for (int i = 0; i < count; i++)
{
String name = names[i];
// Reserve the name.
- _elementIdAllocator.allocateId(name);
+ if (!_standardReservedIds.contains(name))
+ {
+ _elementIdAllocator.allocateId(name);
+
+ extraIds.append(sep);
+ extraIds.append(name);
+
+ sep = ",";
+ }
if (!reserveOnly)
writeHiddenFieldsForParameter(writer, link, name);
}
+
+ return extraIds.toString();
+ }
+
+ private void preallocateReservedIds()
+ {
+ for (int i = 0; i < ServiceConstants.RESERVED_IDS.length; i++)
+ _elementIdAllocator.allocateId(ServiceConstants.RESERVED_IDS[i]);
}
/**
@@ -656,24 +702,44 @@
}
/**
+ * Invoked when rewinding a form to re-initialize the _allocatedIds and _elementIdAllocator.
* Converts a string passed as a parameter (and containing a comma separated list of ids) back
- * into the allocateIds property.
+ * into the allocateIds property. In addition, return the state of the ID allocater back to
+ * where it was at the start of the render.
*
* @see #buildAllocatedIdList()
* @since 3.0
*/
- protected void reconstructAllocatedIds(String storedIdList)
+ protected void reconstructAllocatedIds(IRequestCycle cycle)
{
- if (HiveMind.isBlank(storedIdList))
- return;
+ String[] values = cycle.getParameters(_name);
StringSplitter splitter = new StringSplitter(',');
- String[] ids = splitter.splitToArray(storedIdList);
+ String renderList = values[0];
+ if (HiveMind.isNonBlank(renderList))
+ {
+
+ String[] ids = splitter.splitToArray(values[0]);
+
+ for (int i = 0; i < ids.length; i++)
+ _allocatedIds.add(ids[i]);
+ }
+
+ // Now, reconstruct the the initial state of the
+ // id allocator.
+
+ preallocateReservedIds();
- for (int i = 0; i < ids.length; i++)
- _allocatedIds.add(ids[i]);
+ if (values.length > 1)
+ {
+ String extraReservedIds = values[1];
+ String[] ids = splitter.splitToArray(extraReservedIds);
+
+ for (int i = 0; i < ids.length; i++)
+ _elementIdAllocator.allocateId(ids[i]);
+ }
}
public abstract IValidationDelegate getDelegate();
@@ -699,9 +765,8 @@
public void setEncodingType(String encodingType)
{
if (_encodingType != null && !_encodingType.equals(encodingType))
- throw new ApplicationRuntimeException(Tapestry.format(
- "Form.encoding-type-contention",
- getExtendedId(),
+ throw new ApplicationRuntimeException(FormMessages.encodingTypeContention(
+ this,
_encodingType,
encodingType), this, null, null);
1.1 jakarta-tapestry/framework/src/java/org/apache/tapestry/form/FormMessages.java
Index: FormMessages.java
===================================================================
// Copyright 2005 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.form;
import org.apache.hivemind.impl.MessageFormatter;
import org.apache.tapestry.IComponent;
/**
* @author Howard M. Lewis Ship
* @since 3.1
*/
class FormMessages
{
private static final MessageFormatter _formatter = new MessageFormatter(FormMessages.class,
"FormStrings");
public static String formTooManyIds(IComponent form, int actualCount, IComponent component)
{
return _formatter.format(
"form-too-many-ids",
form.getExtendedId(),
new Integer(actualCount),
component.getExtendedId());
}
public static String formIdMismatch(IComponent form, int mismatchIndex, String expectedId,
String actualId, IComponent component)
{
return _formatter.format("form-id-mismatch", new Object[]
{ form.getExtendedId(), new Integer(mismatchIndex + 1), expectedId, actualId,
component.getExtendedId() });
}
public static String formsMayNotNest()
{
return _formatter.getMessage("forms-may-not-nest");
}
public static String formTooFewIds(IComponent form, int remainingCount, String nextExpectedId)
{
return _formatter.format("form-too-few-ids", form.getExtendedId(), new Integer(remainingCount), nextExpectedId);
}
public static String formNeedsBodyForEventHandlers()
{
return _formatter.getMessage("form-needs-body-for-event-handlers");
}
public static String encodingTypeContention(IComponent form, String establishedEncodingType,
String newEncodingType)
{
return _formatter.format(
"encoding-type-contention",
form.getExtendedId(),
establishedEncodingType,
newEncodingType);
}
}
1.1 jakarta-tapestry/framework/src/java/org/apache/tapestry/form/FormStrings.properties
Index: FormStrings.properties
===================================================================
# Copyright 2005 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.
form-too-many-ids=Rewind of form {0} expected only {1} form elements, but an additional id was requested by component {2}.
form-id-mismatch=Rewind of form {0} expected allocated id #{1} to be ''{2}'', but was ''{3}'' (requested by component {4}).
forms-may-not-nest=Forms may not be nested.
form-too-few-ids=Rewind of form {0} expected {1} more form elements, starting with id ''{2}''.
form-needs-body-for-event-handlers=A Form with event handlers must be enclosed by a Body component.
encoding-type-contention=Components within Form {0} have requested conflicting encoding types ''{1}'' and ''{2}''.
1.4 +17 -20 jakarta-tapestry/framework/src/java/org/apache/tapestry/util/IdAllocator.java
Index: IdAllocator.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/util/IdAllocator.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- IdAllocator.java 5 Jan 2005 23:17:03 -0000 1.3
+++ IdAllocator.java 27 Jan 2005 18:40:29 -0000 1.4
@@ -18,14 +18,12 @@
import java.util.Map;
/**
- * Used to "uniquify" names within a given context. A base name
- * is passed in, and the return value is the base name, or the base name
- * extended with a suffix to make it unique.
- *
- * @author Howard Lewis Ship
- * @since 3.0
- *
- **/
+ * Used to "uniquify" names within a given context. A base name is passed in, and the return value
+ * is the base name, or the base name extended with a suffix to make it unique.
+ *
+ * @author Howard Lewis Ship
+ * @since 3.0
+ */
public class IdAllocator
{
@@ -34,6 +32,7 @@
private static class NameGenerator
{
private String _baseId;
+
private int _index;
NameGenerator(String baseId)
@@ -48,10 +47,9 @@
}
/**
- * Allocates the id. Repeated calls for the same name will return
- * "name", "name_0", "name_1", etc.
- *
- **/
+ * Allocates the id. Repeated calls for the same name will return "name", "name$0", "name$1",
+ * etc.
+ */
public String allocateId(String name)
{
@@ -67,8 +65,8 @@
result = g.nextId();
// Handle the degenerate case, where a base name of the form "foo$0" has been
- // requested. Skip over any duplicates thus formed.
-
+ // requested. Skip over any duplicates thus formed.
+
while (_generatorMap.containsKey(result))
result = g.nextId();
@@ -76,14 +74,13 @@
return result;
}
-
+
/**
- * Clears the allocator, resetting it to freshly allocated state.
- *
- **/
-
+ * Clears the allocator, resetting it to freshly allocated state.
+ */
+
public void clear()
{
_generatorMap.clear();
}
-}
+}
\ No newline at end of file
1.13 +0 -7 jakarta-tapestry/framework/src/java/org/apache/tapestry/TapestryStrings.properties
Index: TapestryStrings.properties
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/TapestryStrings.properties,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- TapestryStrings.properties 6 Jan 2005 02:17:12 -0000 1.12
+++ TapestryStrings.properties 27 Jan 2005 18:40:29 -0000 1.13
@@ -155,13 +155,6 @@
AbstractFormComponent.must-be-contained-by-form=This component must be contained within a Form.
-Form.forms-may-not-nest=Forms may not be nested.
-Form.needs-body-for-event-handlers=A Form with event handlers must be enclosed by a Body component.
-Form.too-many-ids=Rewind of form {0} expected only {1} form elements, but an additional id was requested by component {2}.
-Form.too-few-ids=Rewind of form {0} expected {1} more form elements, starting with id ''{2}''.
-Form.id-mismatch=Rewind of form {0} expected allocated id #{1} to be ''{2}'', but was ''{3}'' (requested by component {4}).
-Form.encoding-type-contention=Components within Form {0} have requested conflicting encoding types ''{1}'' and ''{2}''.
-
ListEdit.unable-to-convert-value=Unable to convert {0} to an external string in ListEdit component.
ListEdit.unable-to-convert-string=Unable to convert {0} back into an object in ListEdit component.
1.5 +1 -1 jakarta-tapestry/src/documentation/content/xdocs/dev.xml
Index: dev.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/src/documentation/content/xdocs/dev.xml,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- dev.xml 25 Jan 2005 01:30:18 -0000 1.4
+++ dev.xml 27 Jan 2005 18:40:29 -0000 1.5
@@ -54,7 +54,7 @@
<section>
<title>Paul Ferraro</title>
- Paul has been an avid Tapestry user since 2002.
+ <p>Paul has been an avid Tapestry user since 2002.</p>
</section>
<section>
1.3 +8 -0 jakarta-tapestry/framework/src/java/org/apache/tapestry/services/ServiceConstants.java
Index: ServiceConstants.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/services/ServiceConstants.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ServiceConstants.java 6 Jan 2005 02:17:15 -0000 1.2
+++ ServiceConstants.java 27 Jan 2005 18:40:29 -0000 1.3
@@ -63,4 +63,12 @@
*/
public static final String PARAMETER = "sp";
+
+ /**
+ * A list of all the conttants defined by this class.
+ *
+ * @see org.apache.tapestry.form.Form
+ */
+ public static final String[] RESERVED_IDS =
+ { SERVICE, PAGE, COMPONENT, CONTAINER, SESSION, PARAMETER };
}
\ No newline at end of file
1.4 +6 -1 jakarta-tapestry/framework/src/scripts/TestWMLFormComponents.xml
Index: TestWMLFormComponents.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/scripts/TestWMLFormComponents.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TestWMLFormComponents.xml 6 Jan 2005 02:17:19 -0000 1.3
+++ TestWMLFormComponents.xml 27 Jan 2005 18:40:29 -0000 1.4
@@ -92,6 +92,7 @@
<match>page</match>
<match>service</match>
<match>Go1</match>
+ <match>Go1</match>
<match>v</match>
</assert-output-matches>
@@ -111,6 +112,7 @@
<match>Rewind</match>
<match>action</match>
<match>v</match>
+ <match>action</match>
<match>$(v)</match>
</assert-output-matches>
@@ -122,7 +124,10 @@
<parameter name="action" value="1"/>
<parameter name="component" value="h"/>
- <parameter name="Go1" value="v"/>
+ <parameter name="Go1">
+ <value>v</value>
+ <value>action</value>
+ </parameter>
<parameter name="v" value="VVV"/>
<assert-output name="Card">
1.4 +6 -1 jakarta-tapestry/framework/src/scripts/TestWMLComponents.xml
Index: TestWMLComponents.xml
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/scripts/TestWMLComponents.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TestWMLComponents.xml 6 Jan 2005 02:17:19 -0000 1.3
+++ TestWMLComponents.xml 27 Jan 2005 18:40:29 -0000 1.4
@@ -112,6 +112,7 @@
<match>page</match>
<match>service</match>
<match>Go0</match>
+ <match>Go0</match>
<match>u</match>
<match>l</match>
</assert-output-matches>
@@ -125,6 +126,7 @@
<match>Home</match>
<match>action</match>
<match>u,l</match>
+ <match>action</match>
<match>$(username)</match>
<match>$(l)</match>
</assert-output-matches>
@@ -136,7 +138,10 @@
<parameter name="page" value="Home"/>
<parameter name="action" value="0"/>
<parameter name="component" value="go"/>
- <parameter name="Go0" value="u,l"/>
+ <parameter name="Go0">
+ <value>u,l</value>
+ <value>action</value>
+ </parameter>
<parameter name="u" value="newbie"/>
<parameter name="l" value="0"/>
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org