Author: mikus Date: Fri Feb 9 22:32:27 2007 New Revision: 505640 URL: http://svn.apache.org/viewvc?view=rev&rev=505640 Log: ASF Bugzilla Bug 2640 / Jira STR-286: do not autopopulate an action form corresponding to chained action.
Added: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/ActionPostProcess.java (with props) Modified: struts/struts1/trunk/core/src/main/java/org/apache/struts/Globals.java struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/PopulateActionForm.java struts/struts1/trunk/core/src/main/java/org/apache/struts/config/ActionConfig.java struts/struts1/trunk/core/src/main/java/org/apache/struts/util/RequestUtils.java struts/struts1/trunk/core/src/main/resources/org/apache/struts/chain/chain-config.xml struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_3.dtd Modified: struts/struts1/trunk/core/src/main/java/org/apache/struts/Globals.java URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/Globals.java?view=diff&rev=505640&r1=505639&r2=505640 ============================================================================== --- struts/struts1/trunk/core/src/main/java/org/apache/struts/Globals.java (original) +++ struts/struts1/trunk/core/src/main/java/org/apache/struts/Globals.java Fri Feb 9 22:32:27 2007 @@ -209,4 +209,11 @@ * The property under which a transaction token is reported. */ public static final String TOKEN_KEY = TAGLIB_PACKAGE + ".TOKEN"; + + /** + * The request attributes key under which forwarding flag is stored. + * + * @since Struts 1.4 + */ + public static final String FORWARD_KEY = "org.apache.struts.action.FORWARD"; } Added: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/ActionPostProcess.java URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/ActionPostProcess.java?view=auto&rev=505640 ============================================================================== --- struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/ActionPostProcess.java (added) +++ struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/ActionPostProcess.java Fri Feb 9 22:32:27 2007 @@ -0,0 +1,55 @@ +/* + * $Id$ + * + * 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.struts.chain.commands.servlet; + +import org.apache.struts.chain.contexts.ActionContext; +import org.apache.struts.chain.contexts.ServletActionContext; +import org.apache.struts.chain.commands.ActionCommandBase; +import org.apache.struts.Globals; + +import javax.servlet.http.HttpServletRequest; + +/** + * <p>Performs post-processing functions in command chain</p> + * + * @version $Rev$ $Date$ + * @since Struts 1.4 + */ +public class ActionPostProcess extends ActionCommandBase { + + /** + * <p>Performs additional functions after an Action or Command + * has been called.</p> + * + * @param context The <code>Context</code> for the current request + * @return <code>false</code> so that processing continues + * @throws Exception on any error + */ + public boolean execute(ActionContext context) throws Exception { + + ServletActionContext saContext = (ServletActionContext) context; + HttpServletRequest request = saContext.getRequest(); + + // Set flag in request object, notifying chained actions that + // this request was already processed. + request.setAttribute(Globals.FORWARD_KEY, Boolean.TRUE); + + // Continue chain processing + return false; + } +} Propchange: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/ActionPostProcess.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/ActionPostProcess.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Modified: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/PopulateActionForm.java URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/PopulateActionForm.java?view=diff&rev=505640&r1=505639&r2=505640 ============================================================================== --- struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/PopulateActionForm.java (original) +++ struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/servlet/PopulateActionForm.java Fri Feb 9 22:32:27 2007 @@ -31,6 +31,8 @@ import org.apache.struts.config.ActionConfig; import org.apache.struts.util.RequestUtils; +import javax.servlet.http.HttpServletRequest; + /** * <p>Populate the form bean (if any) for this request. Sets the multipart * class from the action config in the request attributes.</p> @@ -42,25 +44,94 @@ private static final Log log = LogFactory.getLog(PopulateActionForm.class); // ------------------------------------------------------- Protected Methods + protected void populate(ActionContext context, ActionConfig actionConfig, ActionForm actionForm) throws Exception { ServletActionContext saContext = (ServletActionContext) context; + HttpServletRequest request = saContext.getRequest(); - RequestUtils.populate(actionForm, actionConfig.getPrefix(), - actionConfig.getSuffix(), saContext.getRequest()); + // Populate the form bean only if configured so + if (isPopulate(request, actionConfig)) { + RequestUtils.populate(actionForm, actionConfig.getPrefix(), + actionConfig.getSuffix(), saContext.getRequest()); + } } protected void reset(ActionContext context, ActionConfig actionConfig, ActionForm actionForm) { + ServletActionContext saContext = (ServletActionContext) context; + HttpServletRequest request = saContext.getRequest(); - actionForm.reset((ActionMapping) actionConfig, saContext.getRequest()); + // Reset the form bean only if configured so + if (isReset(request, actionConfig)) { + actionForm.reset((ActionMapping) actionConfig, saContext.getRequest()); + } // Set the multipart class if (actionConfig.getMultipartClass() != null) { saContext.getRequestScope().put(Globals.MULTIPART_KEY, actionConfig.getMultipartClass()); } + } + + // ---------------------------------------------------------- Helper Methods + + /** + * Verifies whether an action form should be populated + * @param request current HTTP request + * @param actionConfig action config for current request + * @return true if action form should be populated + * + * @since Struts 1.3.7 + */ + protected boolean isPopulate(HttpServletRequest request, ActionConfig actionConfig) { + String strPopulate = actionConfig.getPopulate(); + return getResetOrPopulate(request, strPopulate); + } + + /** + * Verifies whether an action form should be reset + * @param request current HTTP request + * @param actionConfig action config for current request + * @return true if action form should be reset + * + * @since Struts 1.3.7 + */ + protected boolean isReset(HttpServletRequest request, ActionConfig actionConfig) { + String strReset = actionConfig.getReset(); + return getResetOrPopulate(request, strReset); + } + + /** + * Compares current request state (direct or forwarded) with configuration + * from action mapping. + * @param request current HTTP request + * @param strAttr value of either "reset" or "populate" attributes of + * an action mapping + * @return true if action mapping is configured to reset (or populate) + * corresponding action form; false if if action mapping is + * configured not to reset (or populate) the action form. + * + * @since Struts 1.3.7 + */ + protected boolean getResetOrPopulate(HttpServletRequest request, String strAttr) { + // Reset configuration is not defined (should not happen, + // because default value are set to "request,forward". + if (strAttr == null) return true; + + // Reads Globals.FORWARD_KEY attribute from the HTTP request object + boolean forwarded = RequestUtils.isForwarded(request); + + // Forwarded request is configured for reset/populate + if (forwarded && strAttr.indexOf(ActionConfig.FORWARD_STR) > -1) return true; + + // Direct request is configured for reset/populate + if (!forwarded && strAttr.indexOf(ActionConfig.REQUEST_STR) > -1) return true; + + // Do not reset/populate if a user explicity set anything + // else besides "request" or "populate". + return false; } } Modified: struts/struts1/trunk/core/src/main/java/org/apache/struts/config/ActionConfig.java URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/config/ActionConfig.java?view=diff&rev=505640&r1=505639&r2=505640 ============================================================================== --- struts/struts1/trunk/core/src/main/java/org/apache/struts/config/ActionConfig.java (original) +++ struts/struts1/trunk/core/src/main/java/org/apache/struts/config/ActionConfig.java Fri Feb 9 22:32:27 2007 @@ -41,6 +41,23 @@ public class ActionConfig extends BaseConfig { private static final Log log = LogFactory.getLog(ActionConfig.class); + /** + * Literal that describes request condition for "reset" and "populate" + * properties. + * + * @since Struts 1.4 + */ + public static final String REQUEST_STR = "request"; + + /** + * Literal that describes forward condition for "reset" and "populate" + * properties. + * + * @since Struts 1.4 + */ + public static final String FORWARD_STR = "forward"; + + // ----------------------------------------------------- Instance Variables /** @@ -178,6 +195,32 @@ protected String scope = "session"; /** + * <p>Identifies conditions for automatic form reset.</p> + * + * <p>Possible values: null (not specified), "request", "forward" or + * "request-forward" (used when not specified). If not specified then + * the form bean is reset both for direct and for forwarded request.</p> + * + * @since Struts 1.4 + */ + protected String reset = REQUEST_STR + "-" + FORWARD_STR; + + /** + * <p>Identifies conditions for automatic form population with values + * from HTTP request.</p> + * + * <p>Possible values: null (not specified), "request", "forward" or + * "request-forward" (used when not specified). If not specified then + * the form bean is populated both for direct and for forwarded request. + * This means that when a chained action mapping refers to the same + * form bean as originating action, then the form bean is repopulated + * and changes made by originating action are lost.</p> + * + * @since Struts 1.4 + */ + protected String populate = REQUEST_STR + "-" + FORWARD_STR; + + /** * <p> Suffix used to match request parameter names to form bean property * names, if any. </p> */ @@ -626,6 +669,54 @@ } /** + * <p>Reads when a corresponding action form should be reset + * ("request", "session" or "request,session").</p> + * + * @since Struts 1.4 + */ + public String getReset() { + return (this.reset); + } + + /** + * @param reset identifies, when a corresponding action form should be + * reset ("request", "session" or "request,session"). + * + * @since Struts 1.4 + */ + public void setReset(String reset) { + if (configured) { + throw new IllegalStateException("Configuration is frozen"); + } + + this.reset = reset; + } + + /** + * <p>Reads when a corresponding action form should be automatically + * populated ("request", "session" or "request,session").</p> + * + * @since Struts 1.4 + */ + public String getPopulate() { + return (this.populate); + } + + /** + * @param populate identifies, when a corresponding action form should be + * automatically populated ("request", "session" or "request,session"). + * + * @since Struts 1.4 + */ + public void setPopulate(String populate) { + if (configured) { + throw new IllegalStateException("Configuration is frozen"); + } + + this.populate= populate; + } + + /** * <p> Return suffix used to match request parameter names to form bean * property names, if any. </p> */ @@ -1271,6 +1362,16 @@ if (scope != null) { sb.append(",scope="); sb.append(scope); + } + + if (reset != null) { + sb.append(",reset="); + sb.append(reset); + } + + if (populate != null) { + sb.append(",populate="); + sb.append(populate); } if (suffix != null) { Modified: struts/struts1/trunk/core/src/main/java/org/apache/struts/util/RequestUtils.java URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/util/RequestUtils.java?view=diff&rev=505640&r1=505639&r2=505640 ============================================================================== --- struts/struts1/trunk/core/src/main/java/org/apache/struts/util/RequestUtils.java (original) +++ struts/struts1/trunk/core/src/main/java/org/apache/struts/util/RequestUtils.java Fri Feb 9 22:32:27 2007 @@ -1066,4 +1066,17 @@ } return actionIdPath.toString(); } + + /** + * Verifies whether current request is forwarded from one action to + * another or not. + * @param request current HTTP request + * @return true if the request contains Globals.FORWARD_KEY, which means + * that request has been forwarded from another action. + * + * @since Struts 1.4 + */ + public static boolean isForwarded(HttpServletRequest request) { + return request.getAttribute(Globals.FORWARD_KEY) != null; + } } Modified: struts/struts1/trunk/core/src/main/resources/org/apache/struts/chain/chain-config.xml URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/resources/org/apache/struts/chain/chain-config.xml?view=diff&rev=505640&r1=505639&r2=505640 ============================================================================== --- struts/struts1/trunk/core/src/main/resources/org/apache/struts/chain/chain-config.xml (original) +++ struts/struts1/trunk/core/src/main/resources/org/apache/struts/chain/chain-config.xml Fri Feb 9 22:32:27 2007 @@ -200,6 +200,11 @@ <!-- Execute the Action for this request --> <command className="org.apache.struts.chain.commands.servlet.ExecuteAction"/> + + + <!-- Perform action postprocess tasks --> + <command + className="org.apache.struts.chain.commands.servlet.ActionPostProcess"/> </chain> <!-- ========== View Processing chain ======================== --> Modified: struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_3.dtd URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_3.dtd?view=diff&rev=505640&r1=505639&r2=505640 ============================================================================== --- struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_3.dtd (original) +++ struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_3.dtd Fri Feb 9 22:32:27 2007 @@ -91,6 +91,8 @@ --> <!ENTITY % RequestScope "(request|session)"> +<!-- Defines possible values for automatic form bean population --> +<!ENTITY % PopulateStrategy "(request|forward|request-forward|none)"> <!-- ========== Top Level Elements ======================================== --> @@ -452,6 +454,16 @@ action mapping, or set to "false" if you do not want the validate method called. [true] + + reset Allows to specify conditions for automatic form reset. + Possible values: not specified, "request", "forward", + "request-forward" or "none". + [request-forward] + + populate Allows to specify conditions for automatic form population + with HTTP request values. Possible values: not specified, + "request", "forward", "request-forward" or "none". + [request-forward] --> <!ELEMENT action (icon?, display-name?, description?, set-property*, exception*, forward*)> <!ATTLIST action id ID #IMPLIED> @@ -474,6 +486,8 @@ <!ATTLIST action type %ClassName; #IMPLIED> <!ATTLIST action unknown %Boolean; #IMPLIED> <!ATTLIST action validate %Boolean; #IMPLIED> +<!ATTLIST action reset %PopulateStrategy; #IMPLIED> +<!ATTLIST action populate %PopulateStrategy; #IMPLIED> <!-- The "controller" element describes the ControllerConfig bean