Updated Branches: refs/heads/5.3 6fa4b39eb -> a0987747d
FIXED - TAP5-2063: Add support for multivalued parameters in Link - apply Alejandro Scandroli's patch + test with modifications Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/a0987747 Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/a0987747 Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/a0987747 Branch: refs/heads/5.3 Commit: a0987747db84756f8fc68ae65f9f902adff74618 Parents: 6fa4b39 Author: kaosko <[email protected]> Authored: Sun Apr 14 00:07:12 2013 -0700 Committer: kaosko <[email protected]> Committed: Sun Apr 14 00:07:12 2013 -0700 ---------------------------------------------------------------------- .../src/main/java/org/apache/tapestry5/Link.java | 15 ++++- .../apache/tapestry5/corelib/components/Form.java | 27 +++++--- .../tapestry5/internal/services/LinkImpl.java | 48 ++++++++++---- .../tapestry5/internal/services/LinkImplTest.java | 27 ++++++++ 4 files changed, 91 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0987747/tapestry-core/src/main/java/org/apache/tapestry5/Link.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/Link.java b/tapestry-core/src/main/java/org/apache/tapestry5/Link.java index e08dde0..aa4336d 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/Link.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/Link.java @@ -45,7 +45,13 @@ public interface Link * Returns the value of a specifically named query parameter, or <tt>null</tt> if no such query parameter is stored * in the link. * - * @return the string value of the named parameter + * <p>Use this method only when you are sure the parameter has only one value. If the parameter might have more than + * one value, use {@link #getParameterValues}. + * + * <p>If you use this method with a multivalued parameter, the value returned is equal to the first value in the + * array returned by <code>getParameterValues</code>. + * + * @return a string representing the single value of the named parameter */ String getParameterValue(String name); @@ -55,7 +61,6 @@ public interface Link * * @param parameterName the name of the parameter to store * @param value the value to store, a null or blank value is allowed (as of Tapestry 5.3) - * @throws IllegalArgumentException if the link already has a parameter with the given name */ void addParameter(String parameterName, String value); @@ -155,4 +160,10 @@ public interface Link * @since 5.3 */ LinkSecurity getSecurity(); + + /** + * Returns the parameter values for the given name. Returns null if no such parameter is stored in the link. + */ + String[] getParameterValues(String parameterName); + } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0987747/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java index 5a08e21..d183217 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java @@ -395,18 +395,25 @@ public class Form implements ClientElement, FormValidationControl for (String parameterName : link.getParameterNames()) { - String value = link.getParameterValue(parameterName); - // The parameter value is expected to be encoded, - // but the input value shouldn't be encoded. - try - { - value = URLDecoder.decode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) + String[] values = link.getParameterValues(parameterName); + + for (String value : values) { - logger.error("Enable to decode parameter value", e); + // The parameter value is expected to be encoded, + // but the input value shouldn't be encoded. + try + { + value = URLDecoder.decode(value, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + logger.error(String.format( + "Enable to decode parameter value for parameter %s in form %s", + parameterName, form.getName()), e); + } + writer.element("input", "type", "hidden", "name", parameterName, "value", value); + writer.end(); } - writer.element("input", "type", "hidden", "name", parameterName, "value", value); - writer.end(); } writer.end(); // div http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0987747/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java index 52f4403..4a5075e 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkImpl.java @@ -15,18 +15,19 @@ package org.apache.tapestry5.internal.services; import org.apache.tapestry5.Link; -import org.apache.tapestry5.ioc.internal.util.CollectionFactory; import org.apache.tapestry5.ioc.internal.util.InternalUtils; import org.apache.tapestry5.services.BaseURLSource; import org.apache.tapestry5.services.ContextPathEncoder; import org.apache.tapestry5.services.Response; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.TreeMap; public class LinkImpl implements Link { - private Map<String, String> parameters; + private Map<String, List<String>> parameters; private final String basePath; @@ -63,20 +64,29 @@ public class LinkImpl implements Link for (String name : getParameterNames()) { - copy.addParameter(name, parameters.get(name)); + copy.addParameter(name, getParameterValues(name)); } return copy; } + private void addParameter(String parameterName, String[] value) + { + assert InternalUtils.isNonBlank(parameterName); + if (parameters == null) + parameters = new TreeMap<String, List<String>>(); + + parameters.put(parameterName, Arrays.asList(value)); + } + public void addParameter(String parameterName, String value) { assert InternalUtils.isNonBlank(parameterName); if (parameters == null) - parameters = CollectionFactory.newMap(); + parameters = new TreeMap<String, List<String>>(); - parameters.put(parameterName, value == null ? "" : value); + InternalUtils.addToMapList(parameters, parameterName, value == null ? "" : value); } public String getBasePath() @@ -103,7 +113,8 @@ public class LinkImpl implements Link public String getParameterValue(String name) { - return InternalUtils.get(parameters, name); + List<String> values = InternalUtils.get(parameters, name); + return values != null && !values.isEmpty() ? values.get(0) : null; } public void setAnchor(String anchor) @@ -198,18 +209,21 @@ public class LinkImpl implements Link for (String name : getParameterNames()) { - String value = parameters.get(name); + List<String> values = parameters.get(name); - builder.append(sep); + for (String value : values) + { + builder.append(sep); - // We assume that the name is URL safe and that the value will already have been URL - // encoded if it is not known to be URL safe. + // We assume that the name is URL safe and that the value will already have been URL + // encoded if it is not known to be URL safe. - builder.append(name); - builder.append("="); - builder.append(value); + builder.append(name); + builder.append("="); + builder.append(value); - sep = "&"; + sep = "&"; + } } } @@ -223,4 +237,10 @@ public class LinkImpl implements Link return this; } + public String[] getParameterValues(String parameterName) + { + List<String> values = InternalUtils.get(parameters, parameterName); + return values.toArray(new String[values.size()]); + } + } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0987747/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java index 14948b1..5d861d6 100644 --- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java +++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkImplTest.java @@ -284,6 +284,33 @@ public class LinkImplTest extends InternalBaseTestCase verify(); } + /** + * TAP5-2063 + */ + @Test + public void multivalued_parameter_support() + { + Response response = mockResponse(); + + String expectedURI = "/ctx?barney=&barney=foo&barney=bar&barney=baz&fred=flintstone"; + train_encodeURL(response, expectedURI, expectedURI); + + replay(); + + Link link = new LinkImpl("/ctx", false, LinkSecurity.INSECURE, response, null, null); + + link.addParameter("fred", "flintstone"); + link.addParameter("barney", null); + link.addParameter("barney", "foo"); + link.addParameter("barney", "bar"); + link.addParameter("barney", "baz"); + + assertEquals(link.toURI(), expectedURI); + + verify(); + } + + @Test public void force_link_to_secure() {
