Author: husted Date: Mon Feb 13 17:28:41 2006 New Revision: 377562 URL: http://svn.apache.org/viewcvs?rev=377562&view=rev Log: Resolve #38374 "Validation always skipped with Globals.CANCEL_KEY" reported by Paul Benedict * ActionConfig: Add cancellable property * AbstractValidationActionForm: Throw InvalidCancelException if Cancel token present but cancellable not set * Add InvalidCancelException class
Added: struts/action/trunk/src/java/org/apache/struts/action/InvalidCancelException.java (with props) Modified: struts/action/trunk/src/java/org/apache/struts/chain/commands/AbstractValidateActionForm.java struts/action/trunk/src/java/org/apache/struts/chain/commands/servlet/PerformForward.java struts/action/trunk/src/java/org/apache/struts/config/ActionConfig.java Added: struts/action/trunk/src/java/org/apache/struts/action/InvalidCancelException.java URL: http://svn.apache.org/viewcvs/struts/action/trunk/src/java/org/apache/struts/action/InvalidCancelException.java?rev=377562&view=auto ============================================================================== --- struts/action/trunk/src/java/org/apache/struts/action/InvalidCancelException.java (added) +++ struts/action/trunk/src/java/org/apache/struts/action/InvalidCancelException.java Mon Feb 13 17:28:41 2006 @@ -0,0 +1,25 @@ +package org.apache.struts.action; + + +/** + * <p> Thrown when a token generated by the Cancel tag is found in the + * request, but the cancellable property for the Action Mapping is not set. + * </p> + */ +public class InvalidCancelException extends Exception { + /** + * <p>Default constructor.</p> + */ + public InvalidCancelException() { + super(); + } + + /** + * <p>Construct the exception with the specified message.</p> + * + * @param message the message + */ + public InvalidCancelException(String message) { + super(message); + } +} Propchange: struts/action/trunk/src/java/org/apache/struts/action/InvalidCancelException.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: struts/action/trunk/src/java/org/apache/struts/chain/commands/AbstractValidateActionForm.java URL: http://svn.apache.org/viewcvs/struts/action/trunk/src/java/org/apache/struts/chain/commands/AbstractValidateActionForm.java?rev=377562&r1=377561&r2=377562&view=diff ============================================================================== --- struts/action/trunk/src/java/org/apache/struts/chain/commands/AbstractValidateActionForm.java (original) +++ struts/action/trunk/src/java/org/apache/struts/chain/commands/AbstractValidateActionForm.java Mon Feb 13 17:28:41 2006 @@ -1,24 +1,10 @@ -/* - * $Id$ - * - * Copyright 2003-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.struts.chain.commands; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; +import org.apache.struts.action.InvalidCancelException; import org.apache.struts.chain.contexts.ActionContext; import org.apache.struts.config.ActionConfig; @@ -32,6 +18,44 @@ */ public abstract class AbstractValidateActionForm extends ActionCommandBase { // ------------------------------------------------------ Instance Variables + + /** + * <p> Provide Commons Logging instance for this class. </p> + */ + private static final Log LOG = + LogFactory.getLog(AbstractSelectForward.class); + + // ------------------------------------------------------ Protected Methods + + /** + * <p>Helper method to verify the Cancel state.</p> + * + * <p>If the state is invalid, Cancel is unset and an + * InvalidCancelException is thrown.</p> + * + * @param actionCtx Our ActionContext + * @param actionConfig Our ActionConfig + * @return true if cancel is set, false otherwise. + * @throws InvalidCancelException + */ + private boolean isCancelled(ActionContext actionCtx, + ActionConfig actionConfig) + throws InvalidCancelException { + Boolean cancel = actionCtx.getCancelled(); + boolean cancelled = ((cancel != null) && cancel.booleanValue()); + boolean cancellable = actionConfig.getCancellable(); + + boolean invalidState = (cancelled && !cancellable); + + if (invalidState) { + actionCtx.setCancelled(Boolean.FALSE); + actionCtx.setFormValid(Boolean.FALSE); + throw new InvalidCancelException(); + } + + return cancelled; + } + // ---------------------------------------------------------- Public Methods /** @@ -46,31 +70,30 @@ */ public boolean execute(ActionContext actionCtx) throws Exception { + // Set form valid until found otherwise + actionCtx.setFormValid(Boolean.TRUE); + // Is there a form bean for this request? ActionForm actionForm = actionCtx.getActionForm(); if (actionForm == null) { - actionCtx.setFormValid(Boolean.TRUE); - - return (false); - } - - // Was this request cancelled? - Boolean cancel = actionCtx.getCancelled(); - - if ((cancel != null) && cancel.booleanValue()) { - actionCtx.setFormValid(Boolean.TRUE); - - return (false); + return false; } // Is validation disabled on this request? ActionConfig actionConfig = actionCtx.getActionConfig(); if (!actionConfig.getValidate()) { - actionCtx.setFormValid(Boolean.TRUE); + return false; + } + + // Was this request cancelled? + if (isCancelled(actionCtx, actionConfig)) { + if (LOG.isDebugEnabled()) { + LOG.debug(" Cancelled transaction, skipping validation"); + } - return (false); + return false; } // Call the validate() method of this form bean @@ -78,9 +101,7 @@ // If there were no errors, proceed normally if ((errors == null) || (errors.isEmpty())) { - actionCtx.setFormValid(Boolean.TRUE); - - return (false); + return false; } // Flag the validation failure and proceed @@ -90,7 +111,7 @@ actionCtx.saveErrors(errors); actionCtx.setFormValid(Boolean.FALSE); - return (false); + return false; } // ------------------------------------------------------- Protected Methods Modified: struts/action/trunk/src/java/org/apache/struts/chain/commands/servlet/PerformForward.java URL: http://svn.apache.org/viewcvs/struts/action/trunk/src/java/org/apache/struts/chain/commands/servlet/PerformForward.java?rev=377562&r1=377561&r2=377562&view=diff ============================================================================== --- struts/action/trunk/src/java/org/apache/struts/chain/commands/servlet/PerformForward.java (original) +++ struts/action/trunk/src/java/org/apache/struts/chain/commands/servlet/PerformForward.java Mon Feb 13 17:28:41 2006 @@ -15,6 +15,8 @@ */ package org.apache.struts.chain.commands.servlet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.struts.action.ActionServlet; import org.apache.struts.chain.commands.AbstractPerformForward; import org.apache.struts.chain.contexts.ActionContext; @@ -23,8 +25,6 @@ import org.apache.struts.config.ModuleConfig; import org.apache.struts.util.MessageResources; import org.apache.struts.util.RequestUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; @@ -37,6 +37,7 @@ */ public class PerformForward extends AbstractPerformForward { private static final Log LOG = LogFactory.getLog(PerformForward.class); + // ------------------------------------------------------- Protected Methods /** @@ -79,6 +80,7 @@ if (uri.startsWith("/")) { uri = request.getContextPath() + uri; } + if (LOG.isDebugEnabled()) { LOG.debug("Redirecting to " + uri); } @@ -88,9 +90,11 @@ } else { RequestDispatcher rd = sacontext.getContext().getRequestDispatcher(uri); + if (LOG.isDebugEnabled()) { LOG.debug("Forwarding to " + uri); } + rd.forward(request, sacontext.getResponse()); } } Modified: struts/action/trunk/src/java/org/apache/struts/config/ActionConfig.java URL: http://svn.apache.org/viewcvs/struts/action/trunk/src/java/org/apache/struts/config/ActionConfig.java?rev=377562&r1=377561&r2=377562&view=diff ============================================================================== --- struts/action/trunk/src/java/org/apache/struts/config/ActionConfig.java (original) +++ struts/action/trunk/src/java/org/apache/struts/config/ActionConfig.java Mon Feb 13 17:28:41 2006 @@ -74,7 +74,16 @@ protected String inherit = null; /** - * <p> Have the inheritance values for this class been applied? + * <p>Can this Action be cancelled? [false]</p> <p> By default, when an + * Action is cancelled, validation is bypassed and the Action should not + * execute the business operation. If a request tries to cancel an Action + * when cancellable is not set, a "InvalidCancelException" is thrown. + * </p> + */ + protected boolean cancellable = false; + + /** + * <p> Have the inheritance values for this class been applied?</p> */ protected boolean extensionProcessed = false; @@ -250,6 +259,28 @@ } /** + * <p>Accessor for cancellable property</p> + * + * @return True if Action can be cancelled + */ + public boolean getCancellable() { + return (this.cancellable); + } + + /** + * <p>Mutator for for cancellable property</p> + * + * @param cancellable + */ + public void setCancellable(boolean cancellable) { + if (configured) { + throw new IllegalStateException("Configuration is frozen"); + } + + this.cancellable = cancellable; + } + + /** * <p>Returns the path of the ActionConfig that this object should inherit * properties from.</p> * @@ -844,7 +875,7 @@ */ public ExceptionConfig findException(Class type) { // Check through the entire superclass hierarchy as needed - ExceptionConfig config = null; + ExceptionConfig config; while (true) { // Check for a locally defined handler @@ -1103,8 +1134,14 @@ public String toString() { StringBuffer sb = new StringBuffer("ActionConfig["); + sb.append("cancellable="); + sb.append(cancellable); + sb.append("path="); sb.append(path); + + sb.append("validate="); + sb.append(validate); if (attribute != null) { sb.append(",attribute="); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]