You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by mr...@apache.org on 2005/02/15 07:08:36 UTC

svn commit: r153901 - in struts/core/trunk/src: share/org/apache/struts/action/ActionRedirect.java test/org/apache/struts/action/TestActionRedirect.java

Author: mrdon
Date: Mon Feb 14 22:08:33 2005
New Revision: 153901

URL: http://svn.apache.org/viewcvs?view=rev&rev=153901
Log:
Adding Hubert Rabago's patch that adds the ability to send request
parameters with a redirect.
PR: 866
Author: Hubert Rabago

Added:
    struts/core/trunk/src/share/org/apache/struts/action/ActionRedirect.java   (with props)
    struts/core/trunk/src/test/org/apache/struts/action/TestActionRedirect.java   (with props)

Added: struts/core/trunk/src/share/org/apache/struts/action/ActionRedirect.java
URL: http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/action/ActionRedirect.java?view=auto&rev=153901
==============================================================================
--- struts/core/trunk/src/share/org/apache/struts/action/ActionRedirect.java (added)
+++ struts/core/trunk/src/share/org/apache/struts/action/ActionRedirect.java Mon Feb 14 22:08:33 2005
@@ -0,0 +1,307 @@
+/*
+ * $Id$ 
+ *
+ * Copyright 2000-2004 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.struts.action;
+
+import org.apache.struts.config.ForwardConfig;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.util.ResponseUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * A subclass of {@link ActionForward} which is designed for use
+ * in redirecting requests, with support for adding parameters
+ * at runtime.
+ * <br/>
+ * An {@link ForwardConfig} (or subclass) can be passed to the constructor
+ * to copy its configuration:
+ * <br/>
+ * <code>
+ * public ActionForward execute(ActionMapping mapping,
+ *                              ActionForm form,
+ *                              HttpServletRequest request,
+ *                              HttpServletResponse response)
+ *         throws Exception {
+ *     ActionRedirect redirect =
+ *             new ActionRedirect(mapping.findForward("doRedirect"));
+ *     redirect.addParameter("param1","value1");
+ *     redirect.addParameter("param2","2");
+ *     redirect.addParameter("param3","3.0");
+ *     return redirect;
+ * }
+ * </code>
+ * <p/>
+ *
+ * @version $Rev$ $Date$
+ */
+public class ActionRedirect extends ActionForward {
+
+    // ----------------------------------------------------- Static variables
+
+    /**
+     * <p>Commons logging instance.</p> 
+     */ 
+    protected static final Log log = LogFactory.getLog(ActionRedirect.class);
+    
+    
+    // ----------------------------------------------------- Instance variables
+
+    /**
+     * <p>Holds the redirect parameters.
+     * Each entry is either a String or a String[] depending on whether
+     * it has one or more entries.</p>
+     */
+    protected Map parameterValues = null;
+
+
+    // ----------------------------------------------------- Constructors
+
+    /**
+     * <p>Construct a new instance with redirect set to true
+     * and initialize parameter lists.</p>
+     */
+    public ActionRedirect() {
+        setRedirect(true);
+        initializeParameters();
+    }
+
+    /**
+     * <p>Construct a new instance with the specified path
+     * and initialize parameter lists.</p>
+     *
+     * @param path Path for this instance
+     */
+    public ActionRedirect(String path) {
+        super(path);
+        setRedirect(true);
+        initializeParameters();
+    }
+
+    /**
+     * <p>Construct a new instance with the specified values
+     * and initialize parameter lists.</p>
+     *
+     * @param name Name of this instance
+     * @param path Path for this instance
+     * @param module Module prefix, if any
+     */
+    public ActionRedirect(String name, String path, String module) {
+        super(name, path, true);
+        setModule(module);
+        initializeParameters();
+    }
+
+
+    /**
+     * <p>Construct a new instance with a {@link ForwardConfig} object
+     *  to copy name, path, and contextRelative values from.</p>
+     *
+     * @param baseConfig the {@link ForwardConfig}
+     * to copy configuration values from
+     */
+    public ActionRedirect(ForwardConfig baseConfig) {
+        setName(baseConfig.getName());
+        setPath(baseConfig.getPath());
+        setContextRelative(baseConfig.getContextRelative());
+        setModule(baseConfig.getModule());
+        setRedirect(true);
+        initializeParameters();
+    }
+
+
+
+    // ----------------------------------------------------- Private methods
+
+    /**
+     * <p>Initializes the internal objects
+     * used to hold parameter values.</p>
+     */
+    private void initializeParameters() {
+        parameterValues = new HashMap();
+    }
+
+
+    // ----------------------------------------------------- Public methods
+
+    /**
+     * <p>Adds the object's toString() to the list of parameters if it's
+     * not null, or an empty string with the given fieldName if it is.</p>
+     *
+     * @param fieldName the name to use for the parameter
+     * @param valueObj the value for this parameter
+     */
+    public void addParameter(String fieldName, Object valueObj) {
+        
+        String value = (valueObj != null) ? valueObj.toString() : "";
+        if (parameterValues == null) {
+            initializeParameters();
+        }
+
+        //try {
+            value = ResponseUtils.encodeURL(value);
+        //} catch (UnsupportedEncodingException uce) {
+            // this shouldn't happen since UTF-8 is the W3C Recommendation
+       //     String errorMsg = "UTF-8 Character Encoding not supported";
+       //     log.error(errorMsg, uce);
+       //     throw new RuntimeException(errorMsg, uce);
+       // }
+        
+        Object currentValue = parameterValues.get(fieldName);        
+        if (currentValue == null) {
+            // there's no value for this param yet; add it to the map
+            parameterValues.put(fieldName, value);
+            
+        } else if (currentValue instanceof String) {
+            // there's already a value; let's use an array for these parameters
+            String[] newValue = new String[2];
+            newValue[0] = (String) currentValue;
+            newValue[1] = value;
+            parameterValues.put(fieldName, newValue);
+            
+        } else if (currentValue instanceof String[]) {
+            // add the value to the list of existing values
+            List newValues = new ArrayList(Arrays.asList((Object[]) currentValue));
+            newValues.add(value);
+            parameterValues.put(fieldName, (String[]) newValues.toArray(new String[newValues.size()]));
+        }
+    }
+
+
+    /**
+     * <p>Get the original path without the parameters added at runtime.</p>
+     *
+     * @return the original path as configured.
+     */
+    public String getOriginalPath() {
+        return super.getPath();
+    }
+
+
+    /**
+     * <p>Get the path for this object, including any parameters
+     * that may have been added at runtime.</p>
+     */
+    public String getPath() {
+        // get the original path and the parameter string that was formed
+        String originalPath = getOriginalPath();
+        String parameterString = getParameterString();
+
+        StringBuffer result = new StringBuffer(originalPath);
+
+        if ((parameterString != null) && (parameterString.length() > 0)) {
+            // the parameter separator we're going to use
+            String paramSeparator = "?";
+
+            // true if we need to use a parameter separator after originalPath
+            boolean needsParamSeparator = true;
+
+            // does the original path already have a "?"?
+            int paramStartIndex = originalPath.indexOf("?");
+            if (paramStartIndex > 0) {
+                // did the path end with "?"?
+                needsParamSeparator =
+                        (paramStartIndex != originalPath.length() - 1);
+                if (needsParamSeparator) {
+                    paramSeparator = "&";
+                }
+            }
+
+            if (needsParamSeparator) {
+                result.append(paramSeparator);
+            }
+            result.append(parameterString);
+        }
+
+        return result.toString();
+    }
+
+
+    /**
+     * <p>Forms the string containing the parameters
+     *  passed onto this object thru calls to addParameter().</p>
+     *
+     * @return a string which can be appended to the URLs.  The
+     *    return string does not include a leading question
+     *    mark (?).
+     */
+    public String getParameterString() {
+        StringBuffer strParam = new StringBuffer(256);
+        
+        // loop through all parameters
+        Iterator iterator = parameterValues.keySet().iterator();
+        while (iterator.hasNext()) {
+            // get the parameter name
+            String name = (String) iterator.next();
+            
+            // get the value for this parameter
+            Object value = parameterValues.get(name);
+            
+            if (value instanceof String) {
+                // just one value for this param
+                strParam.append(name)
+                        .append("=")
+                        .append(value);
+                
+            } else if (value instanceof String[]) {
+                // loop through all values for this param
+                String[] values = (String[]) value;
+                for (int i = 0; i < values.length; i++) {
+                    strParam.append(name)
+                            .append("=")
+                            .append(values[i]);
+                    if (i < values.length - 1)
+                        strParam.append("&");
+                }
+            }
+            
+            if (iterator.hasNext()) {
+                strParam.append("&");
+            }
+        }
+
+        return strParam.toString();
+    }
+
+
+    // ----------------------------------------------------- toString()
+
+    /**
+     * <p>Return a string description of this object.</p>
+     *
+     * @return a string containing the original path for this object
+     *  and the parameters it currently holds
+     */
+    public String toString() {
+        StringBuffer result = new StringBuffer(256);
+        result.append("ActionRedirect [");
+        result.append("originalPath=").append(getOriginalPath()).append(";");
+        result.append("parameterString=")
+                .append(getParameterString()).append("]");
+        return result.toString();
+    }
+
+
+}

Propchange: struts/core/trunk/src/share/org/apache/struts/action/ActionRedirect.java
------------------------------------------------------------------------------
    svn:executable = *

Added: struts/core/trunk/src/test/org/apache/struts/action/TestActionRedirect.java
URL: http://svn.apache.org/viewcvs/struts/core/trunk/src/test/org/apache/struts/action/TestActionRedirect.java?view=auto&rev=153901
==============================================================================
--- struts/core/trunk/src/test/org/apache/struts/action/TestActionRedirect.java (added)
+++ struts/core/trunk/src/test/org/apache/struts/action/TestActionRedirect.java Mon Feb 14 22:08:33 2005
@@ -0,0 +1,183 @@
+/*
+ * $Id$ 
+ *
+ * Copyright 2000-2004 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.struts.action;
+
+import junit.framework.TestSuite;
+import junit.framework.TestCase;
+import junit.framework.ComparisonFailure;
+import junit.framework.AssertionFailedError;
+import org.apache.struts.action.ActionForward;
+
+import java.util.Map;
+
+/**
+ * <p>Unit tests for the {@link ActionRedirect} class.</p>
+ *
+ * @version $Rev$ $Date$
+ */
+public class TestActionRedirect extends TestCase {
+
+    
+    public TestActionRedirect(String s) {
+        super(s);
+    }
+
+    
+    public static TestSuite getSuite() {
+        return new TestSuite(TestActionRedirect.class);
+    }
+
+    
+    public static void main(String[] args) {
+        junit.textui.TestRunner runner = new junit.textui.TestRunner();
+        runner.doRun(TestActionRedirect.getSuite());
+    }
+
+   
+    
+    // ----------------------------------------------------- Test Methods
+    
+    
+    /**
+     * Check that the redirect flag is set.
+     */
+    public void testActionRedirectRedirectFlag() {
+        ActionRedirect ar = new ActionRedirect("/path.do");
+        assertTrue("Redirect flag should be set to true.",ar.getRedirect());
+    }
+
+
+    /**
+     * Test all addParameter methods accepting different data types.
+     */
+    public void testActionRedirectAddParameter() {
+        ActionRedirect ar = new ActionRedirect("/path.do");
+
+        ar.addParameter("st","test");
+        ar.addParameter("obj",new StringBuffer("someString"));
+        
+        assertTrue("Incorrect path", ar.getPath().indexOf("/path.do") == 0);
+        assertHasParameter(ar.parameterValues, "st", "test");
+        assertHasParameter(ar.parameterValues, "obj", "someString");
+    }
+
+    
+    /**
+     * Test adding parameters with the same name.
+     */
+    public void testActionRedirectAddSameNameParameter() {
+        ActionRedirect ar = new ActionRedirect("/path.do");
+
+        ar.addParameter("param","param1");
+        ar.addParameter("param","param2");
+        ar.addParameter("param",new StringBuffer("someString"));
+        
+        assertTrue("Incorrect path", ar.getPath().indexOf("/path.do") == 0);
+        assertHasParameter(ar.parameterValues, "param", "param1");
+        assertHasParameter(ar.parameterValues, "param", "param2");
+        assertHasParameter(ar.parameterValues, "param", "someString");
+        assertEquals("Incorrect number of parameters", 3, countParameters(ar.parameterValues, "param"));
+    }
+
+    
+    /**
+     * Test creating an ActionRedirect which copies its configuration
+     * from an existing ActionForward.
+     */
+    public void testActionRedirectFromExistingForward() {
+        ActionForward forward = new ActionForward("/path.do?param=param1");
+
+        ActionRedirect ar = new ActionRedirect(forward);
+
+        ar.addParameter("param","param2");
+        ar.addParameter("object1",new StringBuffer("someString"));
+
+        assertTrue("Incorrect path", ar.getPath().indexOf("/path.do") == 0);
+        assertHasParameter(ar.parameterValues, "param", "param2");
+        assertHasParameter(ar.parameterValues, "object1", "someString");
+        assertEquals("Incorrect original path.",forward.getPath(),ar.getOriginalPath());
+    }
+
+
+
+    /**
+     * Assert that the given parameters contains an entry for 
+     * <code>paramValue</code> under the <code>paramName</code> key.
+     * <p/>
+     * @param parameters the map of parameters to check into
+     * @param paramName the key of the value to be checked
+     * @param paramValue the value to check for
+     */ 
+    static void assertHasParameter(
+            Map parameters,
+            String paramName,
+            String paramValue) {
+        Object value = parameters.get(paramName);
+        if (value == null) {
+            throw new AssertionFailedError("Parameter [" + paramName + "] not found");
+        }
+        
+        if (value instanceof String) {
+            if (!paramValue.equals(value)) {
+                throw new ComparisonFailure("Incorrect value found", 
+                        paramValue, (String) value);
+            }
+        } else if (value instanceof String[]) {
+            // see if our value is among those in the array
+            String[] values = (String[]) value;
+            for (int i = 0; i < values.length; i++) {
+                if (paramValue.equals(values[i])) {
+                    return;
+                }
+            }
+            throw new AssertionFailedError("Expected value not found for parameter [" + paramName + "]");
+        } else {
+            // can't recognize the value
+            throw new AssertionFailedError("Unexpected type found as parameter value for [" + paramName + "]");
+        }
+    }
+    
+    /**
+     * Determine the number of values that are available for a
+     * specific parameter.
+     * <p/>
+     * @param parameters    the map of parameters to check into
+     * @param paramName     the key of the value(s) to count
+     * @return the number of values for the specified parameter
+     */ 
+    static int countParameters(Map parameters,
+                               String paramName) {
+        Object value = parameters.get(paramName);
+        if (value == null) {
+            return 0;
+        }
+        
+        if (value instanceof String) {
+            return 1;
+        } else if (value instanceof String[]) {
+            String[] values = (String[]) value;
+            return values.length;
+        } else {
+            // can't recognize the value
+            throw new AssertionFailedError("Unexpected type found as parameter value for [" + paramName + "]");
+        }
+    }
+    
+
+}

Propchange: struts/core/trunk/src/test/org/apache/struts/action/TestActionRedirect.java
------------------------------------------------------------------------------
    svn:executable = *



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org