You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by nb...@apache.org on 2011/07/28 06:13:42 UTC

svn commit: r1151730 - in /velocity/tools/trunk: src/site/xdoc/ velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/ velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/ velocity-tools-struts/src/main/java/org/apac...

Author: nbubna
Date: Thu Jul 28 04:13:40 2011
New Revision: 1151730

URL: http://svn.apache.org/viewvc?rev=1151730&view=rev
Log:
merge recent changes from 2.0.x branch

Added:
    velocity/tools/trunk/velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/DateToolTests.java   (with props)
Modified:
    velocity/tools/trunk/src/site/xdoc/changes.xml
    velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/DateTool.java
    velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LinkTool.java
    velocity/tools/trunk/velocity-tools-struts/src/main/java/org/apache/velocity/tools/struts/StrutsLinkTool.java
    velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/LinkTool.java
    velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/tools/LinkTool.java
    velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/test/blackbox/LinkToolTests.java

Modified: velocity/tools/trunk/src/site/xdoc/changes.xml
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/src/site/xdoc/changes.xml?rev=1151730&r1=1151729&r2=1151730&view=diff
==============================================================================
--- velocity/tools/trunk/src/site/xdoc/changes.xml (original)
+++ velocity/tools/trunk/src/site/xdoc/changes.xml Thu Jul 28 04:13:40 2011
@@ -31,15 +31,27 @@
     <subsection name="2.1-SNAPSHOT">
         <p>This section describes changes after the 2.0 release.</p>
         <ul>
+        <li>Switched engine dependency to 2.0 (cb)</li>
+        <li>Reflect Velocity Engine dependency shading of commons-lang and commons-collections (cb)</li>
+        <li>Removed deprecated class org.apache.velocity.tools.generic.log.LogSystemCommonsLog (cb)</li>
+        <li>MathTool: fixed result type calculations and added bitwise operations (cb)</li>
+        </ul>
+    </subsection>
+
+    <subsection name="2.0.1-SNAPSHOT">
+        <p>This section describes changes after the 2.0 release.</p>
+        <ul>
         <li>Upgraded to Dom4j 1.6.1 and Velocity Engine 1.6.4. (ndb)</li>
         <li>fixed VELTOOLS-129 (thanks to Michael Osipov) (ndb)</li>
         <li>fixed VELTOOLS-128 fix sync problems (ndb)</li>
         <li>correct handling and better reporting of commited responses in error() (cb)</li>
         <li>Added a custom number formats cache in ConversionUtils (cb)</li>
-        <li>Switched engine dependency to 2.0 (cb)</li>
-        <li>Reflect Velocity Engine dependency shading of commons-lang and commons-collections (cb)</li>
-        <li>Removed deprecated class org.apache.velocity.tools.generic.log.LogSystemCommonsLog (cb)</li>
-        <li>MathTool: fixed result type calculations and added bitwise operations (cb)</li>
+        <li>fixed VELTOOLS-144 added localization of DateFormat format strings (schultz)</li>
+        <li>fixed VELTOOLS-145 changed StrutsLinkTool's parent class to restore API backward-compatibility (schultz)</li>
+        <li>fixed VELTOOLS-148 - fixed a LinkTool bug with parametersToIgnore management (schultz)</li>
+        <li>fixed VELTOOLS-149 - changed LinkTool.addRequestParams to accept Object[] (schultz)</li>
+        <li>Added StrutsLinkTool.action and StrutsLinkTool.forward methods as replacements for StrutsLinkTool.setAction ant StrutsLinkTool.setForward to match other new LinkTool methods like LinkTool.relative and LinkTool.absolute (schultz)
+        <li>fixed VELTOOLS-146 $link.absolute($uri) should not encode query strings in the argument</li>
         </ul>
     </subsection>
 

Modified: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/DateTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/DateTool.java?rev=1151730&r1=1151729&r2=1151730&view=diff
==============================================================================
--- velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/DateTool.java (original)
+++ velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/DateTool.java Thu Jul 28 04:13:40 2011
@@ -743,6 +743,34 @@ public class DateTool extends FormatConf
         return ConversionUtils.toCalendar(date, locale);
     }
 
+    /**
+     * Returns a localized date format pattern for the given format.
+     *
+     * SimpleDateFormat uses patterns that are based upon English
+     * words (such as Month = M, Day = d, and Year = y). When displaying
+     * a format pattern to readers of other languages, it is appropriate
+     * to display these patterns using their localized expectations.
+     * For instance, the date pattern yyyy-MM-dd should, for French speakers
+     * appear as "aaaa-MM-jj". {@link SimpleDateFormat#toLocalizedPattern}
+     * provides this functionality, and this method merely calls
+     * that on an appropriately-constructed SimpleDateFormat object.
+     *
+     * @param format the custom or standard pattern to convert
+     * @param locale the {@link Locale} to format for pattern for
+     * @return a format string appropriate for the specified Locale
+     * @since VelocityTools 2.0
+     */
+    public String toLocalizedPattern(String format,
+                                     Locale locale)
+    {
+        DateFormat df = getDateFormat(format, locale, getTimeZone());
+
+        // Just in case DateFormat.getInstance doesn't return SimpleDateFormat
+        if(df instanceof SimpleDateFormat)
+            return ((SimpleDateFormat)df).toLocalizedPattern();
+        else
+            return null; // Got a better idea?
+    }
 
     // ------------------------- default toString() implementation ------------
 

Modified: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LinkTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LinkTool.java?rev=1151730&r1=1151729&r2=1151730&view=diff
==============================================================================
--- velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LinkTool.java (original)
+++ velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LinkTool.java Thu Jul 28 04:13:40 2011
@@ -365,7 +365,7 @@ public class LinkTool extends SafeConfig
             }
             catch (NumberFormatException nfe)
             {
-                debug("Could convert '%s' to int", nfe, obj);
+                debug("Could not convert '%s' to int", nfe, obj);
                 this.port = -2; // use this to mean error
             }
         }
@@ -831,7 +831,9 @@ public class LinkTool extends SafeConfig
      * host, port, path, query, and fragment all to their null-equivalent
      * values.  Otherwise, this will
      * convert the specified object into a {@link URI}, then those same
-     * values from the URI object to this instance.
+     * values from the URI object to this instance, when not null or empty.
+     * In other words, when given a URI this will only set values present
+     * in the URI.
      */
     protected boolean setFromURI(Object obj)
     {
@@ -853,27 +855,51 @@ public class LinkTool extends SafeConfig
         {
             return false;
         }
-        setScheme(uri.getScheme());
+        if (uri.getScheme() != null)
+        {
+            setScheme(uri.getScheme());
+        }
         if (uri.isOpaque())
         {
             this.opaque = true;
-            // path is used as scheme-specific part
-            setPath(uri.getSchemeSpecificPart());
+            if (uri.getSchemeSpecificPart() != null)
+            {
+                // path is used as scheme-specific part
+                setPath(uri.getSchemeSpecificPart());
+            }
         }
         else
         {
-            setUserInfo(uri.getUserInfo());
-            setHost(uri.getHost());
-            setPort(uri.getPort());
+            if (uri.getUserInfo() != null)
+            {
+                setUserInfo(uri.getUserInfo());
+            }
+            if (uri.getHost() != null)
+            {
+                setHost(uri.getHost());
+            }
+            if (uri.getPort() > -1)
+            {
+                setPort(uri.getPort());
+            }
             String pth = uri.getPath();
-            if (pth.equals("/") || pth.length() == 0)
+            if (pth != null)
             {
-                pth = null;
+                if (pth.equals("/") || pth.length() == 0)
+                {
+                    pth = null;
+                }
+                setPath(pth);
             }
-            setPath(pth);
+        }
+        if (uri.getQuery() != null)
+        {
             setQuery(uri.getQuery());
         }
-        setFragment(uri.getFragment());
+        if (uri.getFragment() != null)
+        {
+            setFragment(uri.getFragment());
+        }
         return true;
     }
 
@@ -894,7 +920,7 @@ public class LinkTool extends SafeConfig
             }
             catch (Exception e)
             {
-                debug("Could convert '%s' to URI", e, obj);
+                debug("Could not convert '%s' to URI", e, obj);
                 return null;
             }
         }
@@ -1272,8 +1298,11 @@ public class LinkTool extends SafeConfig
         {
             pth = combinePath(getContextPath(), String.valueOf(obj));
         }
-        copy.setPath(pth);
-        return copy;
+        if (copy.setFromURI(pth))
+        {
+            return copy;
+        }
+        return null;
     }
 
     /**
@@ -1340,52 +1369,25 @@ public class LinkTool extends SafeConfig
     {
         // assume it's just a path value to go with current scheme/host/port
         LinkTool copy = absolute();
-        String pth;
         if (obj == null)
         {
             // just use the current directory path, if any
-            pth = getDirectory();
+            copy.setPath(getDirectory());
         }
         else
         {
-            pth = String.valueOf(obj);
-            if (pth.startsWith(DEFAULT_SCHEME))
+            String pth = String.valueOf(obj);
+            // paths that don't start with '/'
+            // are considered relative to the current directory
+            if (!pth.startsWith(DEFAULT_SCHEME) && !pth.startsWith("/"))
             {
-                // looks absolute already
-                URI uri = toURI(pth);
-                if (uri == null)
-                {
-                    return null;
-                }
-                copy.setScheme(uri.getScheme());
-                copy.setUserInfo(uri.getUserInfo());
-                copy.setHost(uri.getHost());
-                copy.setPort(uri.getPort());
-                // handle path, query and fragment with care
-                pth = uri.getPath();
-                if (pth.equals("/") || pth.length() == 0)
-                {
-                    pth = null;
-                }
-                copy.setPath(pth);
-                if (uri.getQuery() != null)
-                {
-                    copy.setQuery(uri.getQuery());
-                }
-                if (uri.getFragment() != null)
-                {
-                    copy.setFragment(uri.getFragment());
-                }
-                return copy;
+                pth = combinePath(getDirectory(), pth);
             }
-            else if (!pth.startsWith("/"))
+            if (!copy.setFromURI(pth))
             {
-                // paths that don't start with '/'
-                // are considered relative to the current directory
-                pth = combinePath(getDirectory(), pth);
+                return null;
             }
         }
-        copy.setPath(pth);
         return copy;
     }
 

Added: velocity/tools/trunk/velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/DateToolTests.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/DateToolTests.java?rev=1151730&view=auto
==============================================================================
--- velocity/tools/trunk/velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/DateToolTests.java (added)
+++ velocity/tools/trunk/velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/DateToolTests.java Thu Jul 28 04:13:40 2011
@@ -0,0 +1,88 @@
+package org.apache.velocity.tools.generic;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Locale;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+//import org.apache.velocity.tools.generic.DateTool;
+
+/**
+ * <p>Tests for DateToolTests</p>
+ *
+ * @author Christopher Schultz
+ * @since VelocityTools 2.0.1
+ * @version $Id$
+ */
+public class DateToolTests
+{
+    public @Test void toLocalizedPattern_simplePattern() throws Exception
+    {
+        DateTool dt = new DateTool();
+
+        Locale frFR = new Locale("fr", "FR");
+
+        assertEquals("DateTool incorrectly localizes date format pattern",
+                     new SimpleDateFormat("yyyy-MM-dd", frFR).toLocalizedPattern(), // "aaaa-MM-jj"
+                     dt.toLocalizedPattern("yyyy-MM-dd", frFR));
+    }
+
+    public @Test void toLocalizedPattern_predefinedDateTimePattern() throws Exception
+    {
+        DateTool dt = new DateTool();
+
+        Locale frFR = new Locale("fr", "FR");
+
+        assertEquals("DateTool incorrectly localizes date format pattern",
+                     ((SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, frFR)).toLocalizedPattern(),
+                     dt.toLocalizedPattern("short", frFR));
+    }
+
+    public @Test void toLocalizedPattern_predefinedDatePattern() throws Exception
+    {
+        DateTool dt = new DateTool();
+
+        Locale frFR = new Locale("fr", "FR");
+
+        assertEquals("DateTool incorrectly localizes date format pattern",
+                     ((SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, frFR)).toLocalizedPattern(),
+                     dt.toLocalizedPattern("short_date", frFR));
+    }
+
+    public @Test void toLocalizedPattern_predefinedTimePattern() throws Exception
+    {
+        DateTool dt = new DateTool();
+
+        Locale frFR = new Locale("fr", "FR");
+
+        assertEquals("DateTool incorrectly localizes date format pattern",
+                     ((SimpleDateFormat)DateFormat.getTimeInstance(DateFormat.SHORT, frFR)).toLocalizedPattern(),
+                     dt.toLocalizedPattern("short_time", frFR));
+    }
+}

Propchange: velocity/tools/trunk/velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/DateToolTests.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: velocity/tools/trunk/velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/DateToolTests.java
------------------------------------------------------------------------------
    svn:keywords = Revision

Propchange: velocity/tools/trunk/velocity-tools-generic/src/test/java/org/apache/velocity/tools/generic/DateToolTests.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: velocity/tools/trunk/velocity-tools-struts/src/main/java/org/apache/velocity/tools/struts/StrutsLinkTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-struts/src/main/java/org/apache/velocity/tools/struts/StrutsLinkTool.java?rev=1151730&r1=1151729&r2=1151730&view=diff
==============================================================================
--- velocity/tools/trunk/velocity-tools-struts/src/main/java/org/apache/velocity/tools/struts/StrutsLinkTool.java (original)
+++ velocity/tools/trunk/velocity-tools-struts/src/main/java/org/apache/velocity/tools/struts/StrutsLinkTool.java Thu Jul 28 04:13:40 2011
@@ -21,7 +21,7 @@ package org.apache.velocity.tools.struts
 
 import javax.servlet.ServletContext;
 import org.apache.velocity.tools.generic.ValueParser;
-import org.apache.velocity.tools.view.LinkTool;
+import org.apache.velocity.tools.view.tools.LinkTool;
 import org.apache.velocity.tools.view.ViewContext;
 
 /**
@@ -80,11 +80,11 @@ public class StrutsLinkTool extends Link
         StrutsLinkTool sub = null;
         if ("action".equalsIgnoreCase(this.get))
         {
-            sub = setAction(getme);
+            sub = action(getme);
         }
         else if ("forward".equalsIgnoreCase(this.get))
         {
-            sub = setForward(getme);
+            sub = forward(getme);
         }
         else
         {
@@ -110,7 +110,7 @@ public class StrutsLinkTool extends Link
      *
      * @return a new instance of StrutsLinkTool
      */
-    public StrutsLinkTool setAction(String action)
+    public StrutsLinkTool action(String action)
     {
         String url =
             StrutsUtils.getActionMappingURL(application, request, action);
@@ -123,6 +123,21 @@ public class StrutsLinkTool extends Link
         return (StrutsLinkTool)absolute(url);
     }
 
+    /**
+     * <p>Returns a copy of the link with the given action name
+     * converted into a server-relative URI reference. This method
+     * does not check if the specified action really is defined.
+     * This method will overwrite any previous URI reference settings
+     * but will copy the query string.</p>
+     *
+     * @param action an action path as defined in struts-config.xml
+     *
+     * @return a new instance of StrutsLinkTool
+     */
+    public StrutsLinkTool setAction(String action)
+    {
+        return action(action);
+    }
 
     /**
      * <p>Returns a copy of the link with the given global or local forward
@@ -137,7 +152,7 @@ public class StrutsLinkTool extends Link
      *
      * @return a new instance of StrutsLinkTool
      */
-    public StrutsLinkTool setForward(String forward)
+    public StrutsLinkTool forward(String forward)
     {
         String url = StrutsUtils.getForwardURL(request, application, forward);
         if (url == null)
@@ -149,4 +164,21 @@ public class StrutsLinkTool extends Link
         return (StrutsLinkTool)absolute(url);
     }
 
+    /**
+     * <p>Returns a copy of the link with the given global or local forward
+     * name converted into a server-relative URI reference. If the parameter
+     * does not map to an existing global forward name, <code>null</code>
+     * is returned. This method will overwrite any previous URI reference
+     * settings but will copy the query string.</p>
+     *
+     * @param forward a forward name as defined in struts-config.xml
+     *                in either global-forwards or in the currently executing
+     *                action mapping.
+     *
+     * @return a new instance of StrutsLinkTool
+     */
+    public StrutsLinkTool setForward(String forward)
+    {
+        return forward(forward);
+    }
 }

Modified: velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/LinkTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/LinkTool.java?rev=1151730&r1=1151729&r2=1151730&view=diff
==============================================================================
--- velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/LinkTool.java (original)
+++ velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/LinkTool.java Thu Jul 28 04:13:40 2011
@@ -136,7 +136,7 @@ public class LinkTool extends org.apache
      * @return A LinkTool object with the specified parameters from
      *         the current request added to it or all the params if none specified.
      */
-    public LinkTool addRequestParams(String... butOnlyThese)
+    public LinkTool addRequestParams(Object... butOnlyThese)
     {
         return addRequestParams(false, butOnlyThese);
     }
@@ -148,7 +148,7 @@ public class LinkTool extends org.apache
      * @return A LinkTool object with all of the current request's parameters
      *         added to it, except those specified.
      */
-    public LinkTool addRequestParamsExcept(String... ignoreThese)
+    public LinkTool addRequestParamsExcept(Object... ignoreThese)
     {
         return addRequestParams(true, ignoreThese);
     }
@@ -162,13 +162,13 @@ public class LinkTool extends org.apache
      *         added to it, except those specified or those that already have
      *         values.
      */
-    public LinkTool addMissingRequestParams(String... ignoreThese)
+    public LinkTool addMissingRequestParams(Object... ignoreThese)
     {
-        String[] these;
+        Object[] these;
         if (query != null && !query.isEmpty())
         {
             Set keys = query.keySet();
-            these = new String[keys.size() + ignoreThese.length];
+            these = new Object[keys.size() + ignoreThese.length];
             int i = 0;
             for (; i < ignoreThese.length; i++)
             {
@@ -186,7 +186,7 @@ public class LinkTool extends org.apache
         return addRequestParams(true, these);
     }
 
-    private LinkTool addRequestParams(boolean ignore, String... special)
+    private LinkTool addRequestParams(boolean ignore, Object... special)
     {
         LinkTool copy = (LinkTool)duplicate(true);
         Map reqParams = request.getParameterMap();
@@ -207,9 +207,9 @@ public class LinkTool extends org.apache
         return copy;
     }
 
-    private boolean contains(String[] set, String name)
+    private boolean contains(Object[] set, String name)
     {
-        for (String i : set)
+        for (Object i : set)
         {
             if (name.equals(i))
             {

Modified: velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/tools/LinkTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/tools/LinkTool.java?rev=1151730&r1=1151729&r2=1151730&view=diff
==============================================================================
--- velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/tools/LinkTool.java (original)
+++ velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/tools/LinkTool.java Thu Jul 28 04:13:40 2011
@@ -249,7 +249,7 @@ public class LinkTool extends org.apache
     {
         if (this.parametersToIgnore != null)
         {
-            String[] ignoreThese = new String[parametersToIgnore.size()];
+            Object[] ignoreThese = new String[parametersToIgnore.size()];
             return (LinkTool)addRequestParamsExcept(parametersToIgnore.toArray(ignoreThese));
         }
         else if (autoIgnore)
@@ -299,4 +299,14 @@ public class LinkTool extends org.apache
         }
     }
 
+    @Override
+    protected LinkTool duplicate(boolean deep)
+    {
+        LinkTool copy = (LinkTool)super.duplicate(deep);
+        if (this.parametersToIgnore != null)
+        {
+            copy.parametersToIgnore = new HashSet<String>(this.parametersToIgnore);
+        }
+        return copy;
+    }
 }

Modified: velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/test/blackbox/LinkToolTests.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/test/blackbox/LinkToolTests.java?rev=1151730&r1=1151729&r2=1151730&view=diff
==============================================================================
--- velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/test/blackbox/LinkToolTests.java (original)
+++ velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/test/blackbox/LinkToolTests.java Thu Jul 28 04:13:40 2011
@@ -185,4 +185,17 @@ public class LinkToolTests
         Assert.assertEquals("/test/target?a=a&amp;a=b&amp;a=c&amp;a=d", url);
     }
 
+    public @Test void test_VELTOOLS_148()
+    {
+        LinkTool link = newLinkTool("a", new String[] { "a", "b", "c" });
+
+        LinkTool forward = link.setRelative("/foo")
+            .addQueryData("bar", "baz");
+
+        Assert.assertEquals("/test/foo?bar=baz&amp;a=a&amp;a=b&amp;a=c",
+                            forward.addAllParameters().toString());
+
+        Assert.assertEquals("/test/foo?bar=baz&amp;a=a&amp;a=b&amp;a=c",
+                            forward.addAllParameters().toString());
+    }
 }