rleland 2003/08/12 21:53:43 Modified: src/share/org/apache/struts/actions DispatchAction.java LocalStrings.properties LookupDispatchAction.java Log: Bug 18002 Enhancement patches provided -TWICE-- by Leonardo Quijano This adds a 'default' and a 'cancel' handler to the DispatchAction and LookupDispatchAction DispatchAction - added a new method getMethodName for refactoring, added cancel handler (default is to throw an exception). LookupDispatchAction - general refactoring, a more accurate error reporting (this action's error are a little bit too mysterious) LocalStrings.properties - new error messages for LookupDispatchAction, added some quotes - making error identification easier. Revision Changes Path 1.17 +113 -57 jakarta-struts/src/share/org/apache/struts/actions/DispatchAction.java Index: DispatchAction.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/actions/DispatchAction.java,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- DispatchAction.java 11 Jul 2003 23:47:57 -0000 1.16 +++ DispatchAction.java 13 Aug 2003 04:53:43 -0000 1.17 @@ -123,9 +123,17 @@ * constraints over what types of handlers may reasonably be packaged into * the same <code>DispatchAction</code> subclass.</p> * + * <p><strong>NOTE</strong> - If the value of the request parameter is empty, + * a method named <code>unspecified</code> is called. The default action is + * to throw an exception. If the request was cancelled (a <code>html:cancel</code> + * button was pressed), the custom handler <code>cancelled</code> will be used instead. + * You can also override the <code>getMethodName</code> method to override the action's + * default handler selection.</p> + * * @author Niall Pemberton <[EMAIL PROTECTED]> * @author Craig R. McClanahan * @author Ted Husted + * @author Leonardo Quijano * @version $Revision$ $Date$ */ public abstract class DispatchAction extends Action { @@ -150,8 +158,8 @@ * The message resources for this package. */ protected static MessageResources messages = - MessageResources.getMessageResources - ("org.apache.struts.actions.LocalStrings"); + MessageResources.getMessageResources + ("org.apache.struts.actions.LocalStrings"); /** @@ -168,11 +176,11 @@ * are the same for all calls, so calculate them only once. */ protected Class[] types = - { - ActionMapping.class, - ActionForm.class, - HttpServletRequest.class, - HttpServletResponse.class }; + { + ActionMapping.class, + ActionForm.class, + HttpServletRequest.class, + HttpServletResponse.class}; @@ -197,25 +205,28 @@ ActionForm form, HttpServletRequest request, HttpServletResponse response) - throws Exception { + throws Exception { - // Identify the request parameter containing the method name - String parameter = mapping.getParameter(); - if (parameter == null) { - String message = - messages.getMessage("dispatch.handler", mapping.getPath()); - - log.error(message); - - throw new ServletException(message); - } + if (isCancelled(request)) { + return cancelled(mapping, form, request, response); + } else { + // Identify the request parameter containing the method name + String parameter = mapping.getParameter(); + if (parameter == null) { + String message = + messages.getMessage("dispatch.handler", mapping.getPath()); - // Identify the method name to be dispatched to. - // dispatchMethod() will call unspecified() if name is null - String name = request.getParameter(parameter); + log.error(message); - // Invoke the named method, and return the result - return dispatchMethod(mapping, form, request, response, name); + throw new ServletException(message); + } + + // Get the method's name. This could be overridden in subclasses. + String name = getMethodName(mapping, form, request, response, parameter); + + // Invoke the named method, and return the result + return dispatchMethod(mapping, form, request, response, name); + } } @@ -226,23 +237,46 @@ * to provide default behavior different than throwing a ServletException. */ protected ActionForward unspecified( - ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) - throws Exception { + ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response) + throws Exception { String message = - messages.getMessage( - "dispatch.parameter", - mapping.getPath(), - mapping.getParameter()); + messages.getMessage( + "dispatch.parameter", + mapping.getPath(), + mapping.getParameter()); log.error(message); throw new ServletException(message); } + /** + * Method which is dispatched to when the request is a cancel button submit. + * Subclasses of <code>DispatchAction</code> should override this method if + * they wish to provide default behavior different than throwing a + * ServletException. + * + */ + protected ActionForward cancelled(ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response) + throws Exception { + + String message = + messages.getMessage( + "dispatch.cancelled", + mapping.getPath(), + mapping.getParameter()); + + log.error(message); + + throw new ServletException(message); + } // ----------------------------------------------------- Protected Methods @@ -251,12 +285,12 @@ * Dispatch to the specified method. * @since Struts 1.1 */ - protected ActionForward dispatchMethod(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response, - String name) throws Exception { - + protected ActionForward dispatchMethod(ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response, + String name) throws Exception { + // Make sure we have a valid method name to call. // This may be null if the user hacks the query string. if (name == null) { @@ -267,32 +301,32 @@ Method method = null; try { method = getMethod(name); - - } catch (NoSuchMethodException e) { + + } catch(NoSuchMethodException e) { String message = - messages.getMessage("dispatch.method", mapping.getPath(), name); + messages.getMessage("dispatch.method", mapping.getPath(), name); log.error(message, e); throw e; } ActionForward forward = null; try { - Object args[] = { mapping, form, request, response }; + Object args[] = {mapping, form, request, response}; forward = (ActionForward) method.invoke(this, args); - - } catch (ClassCastException e) { + + } catch(ClassCastException e) { String message = - messages.getMessage("dispatch.return", mapping.getPath(), name); + messages.getMessage("dispatch.return", mapping.getPath(), name); log.error(message, e); throw e; - - } catch (IllegalAccessException e) { + + } catch(IllegalAccessException e) { String message = - messages.getMessage("dispatch.error", mapping.getPath(), name); + messages.getMessage("dispatch.error", mapping.getPath(), name); log.error(message, e); throw e; - - } catch (InvocationTargetException e) { + + } catch(InvocationTargetException e) { // Rethrow the target exception if possible so that the // exception handling machinery can deal with it Throwable t = e.getTargetException(); @@ -300,7 +334,7 @@ throw ((Exception) t); } else { String message = - messages.getMessage("dispatch.error", mapping.getPath(), name); + messages.getMessage("dispatch.error", mapping.getPath(), name); log.error(message, e); throw new ServletException(t); } @@ -321,9 +355,9 @@ * @exception NoSuchMethodException if no such method can be found */ protected Method getMethod(String name) - throws NoSuchMethodException { + throws NoSuchMethodException { - synchronized (methods) { + synchronized(methods) { Method method = (Method) methods.get(name); if (method == null) { method = clazz.getMethod(name, types); @@ -334,5 +368,27 @@ } + /** + * Returns the method name, given a parameter's value. + * + * @param mapping The ActionMapping used to select this instance + * @param form The optional ActionForm bean for this request (if any) + * @param request The HTTP request we are processing + * @param response The HTTP response we are creating + * @param parameter The <code>ActionMapping</code> parameter's name + * + * @return The method's name. + */ + protected String getMethodName(ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response, + String parameter) + throws Exception { + + // Identify the method name to be dispatched to. + // dispatchMethod() will call unspecified() if name is null + return request.getParameter(parameter); + } } 1.8 +10 -7 jakarta-struts/src/share/org/apache/struts/actions/LocalStrings.properties Index: LocalStrings.properties =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/actions/LocalStrings.properties,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- LocalStrings.properties 12 Aug 2003 03:26:53 -0000 1.7 +++ LocalStrings.properties 13 Aug 2003 04:53:43 -0000 1.8 @@ -1,14 +1,17 @@ -dispatch.error=Dispatch[{0}] to method {1} returned an exception +dispatch.cancelled=Action[{0}] does not contain a cancel handler +dispatch.error=Dispatch[{0}] to method '{1}' returned an exception dispatch.handler=DispatchMapping[{0}] does not define a handler property +dispatch.lookup=Action[{0}] does not contain handler for resource '{1}' dispatch.mapping=ActionMapping[{0}] is not of type DispatchMapping -dispatch.method=Action[{0}] does not contain method named {1} -dispatch.parameter=Request[{0}] does not contain handler parameter named {1}. This may be caused by whitespace in the label text. -dispatch.return=Action[{0}] invalid return type for method {1} +dispatch.method=Action[{0}] does not contain method named '{1}' +dispatch.parameter=Request[{0}] does not contain handler parameter named '{1}'. This may be caused by whitespace in the label text. +dispatch.return=Action[{0}] invalid return type for method '{1}' +dispatch.resource=Action[{0}] missing resource '{1}' in key method map forward.path=No context-relative URI specified via the 'parameter' attribute -forward.rd=Cannot create request dispatcher for path {0} +forward.rd=Cannot create request dispatcher for path '{0}' include.path=No context-relative URI specified via the 'parameter' attribute -include.rd=Cannot create request dispatcher for path {0} -switch.prefix=Invalid module prefix {0} was specified +include.rd=Cannot create request dispatcher for path '{0}' +switch.prefix=Invalid module prefix '{0}' was specified switch.required=Switch requires both 'prefix' and 'page' request parameters success.required=SuccessAction could not find an ActionForward named 'success' for path '{0}' mapping.parameter=ActionMapping[{0}] does not define a 'parameter' attribute 1.13 +87 -44 jakarta-struts/src/share/org/apache/struts/actions/LookupDispatchAction.java Index: LookupDispatchAction.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/actions/LookupDispatchAction.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- LookupDispatchAction.java 3 Jul 2003 02:42:58 -0000 1.12 +++ LookupDispatchAction.java 13 Aug 2003 04:53:43 -0000 1.13 @@ -2,7 +2,7 @@ * $Header$ * $Revision$ * $Date$ - * + * * ==================================================================== * * The Apache Software License, Version 1.1 @@ -69,6 +69,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.StringUtils; import org.apache.struts.Globals; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; @@ -143,11 +144,15 @@ * * <strong>Notes</strong> - If duplicate values exist for the keys returned by * getKeys, only the first one found will be returned. If no corresponding key - * is found then an exception will be thrown. + * is found then an exception will be thrown. You can override the + * method <code>unspecified</code> to provide a custom handler. If the submit + * was cancelled (a <code>html:cancel</code> button was pressed), the custom + * handler <code>cancelled</code> will be used instead. * * @author Erik Hatcher * @author Scott Carlson * @author David Graham + * @author Leonardo Quijano */ public abstract class LookupDispatchAction extends DispatchAction { @@ -178,46 +183,27 @@ * @exception Exception if an error occurs */ public ActionForward execute( - ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) - throws Exception { - - // Identify the request parameter containing the method name - String parameter = mapping.getParameter(); - if (parameter == null) { - String message = messages.getMessage("dispatch.handler", mapping.getPath()); - throw new ServletException(message); - } - - // Identify the string to lookup - String name = request.getParameter(parameter); - if (name == null) { - String message = - messages.getMessage("dispatch.parameter", mapping.getPath(), parameter); - throw new ServletException(message); - } - - // Based on this request's Locale get the lookupMap - Map lookupMap = null; - - synchronized (localeMap) { - Locale userLocale = this.getLocale(request); - lookupMap = (Map) this.localeMap.get(userLocale); - - if (lookupMap == null) { - lookupMap = this.initLookupMap(request, userLocale); - this.localeMap.put(userLocale, lookupMap); + ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response) + throws Exception { + + if (isCancelled(request)) { + return cancelled(mapping, form, request, response); + } else { + // Identify the request parameter containing the method name + String parameter = mapping.getParameter(); + if (parameter == null) { + String message = messages.getMessage("dispatch.handler", mapping.getPath()); + throw new ServletException(message); } - } - - // Find the key - String key = (String) lookupMap.get(name); - String methodName = (String) keyMethodMap.get(key); + // Identify the string to lookup + String methodName = getMethodName(mapping, form, request, response, parameter); - return this.dispatchMethod(mapping, form, request, response, methodName); + return dispatchMethod(mapping, form, request, response, methodName); + } } /** @@ -230,7 +216,7 @@ this.keyMethodMap = this.getKeyMethodMap(); ModuleConfig moduleConfig = - (ModuleConfig) request.getAttribute(Globals.MODULE_KEY); + (ModuleConfig) request.getAttribute(Globals.MODULE_KEY); MessageResourcesConfig[] mrc = moduleConfig.findMessageResourcesConfigs(); @@ -250,7 +236,7 @@ } } } - + return lookupMap; } @@ -260,5 +246,62 @@ * @return Resource key / method name map. */ protected abstract Map getKeyMethodMap(); + + /** + * Returns the method name, given a parameter's value. + * + * @param mapping The ActionMapping used to select this instance + * @param form The optional ActionForm bean for this request (if any) + * @param request The HTTP request we are processing + * @param response The HTTP response we are creating + * @param parameter The <code>ActionMapping</code> parameter's name + * + * @return The method's name. + */ + protected String getMethodName(ActionMapping mapping, + ActionForm form, + HttpServletRequest request, + HttpServletResponse response, + String parameter) + throws Exception { + + // Identify the method name to be dispatched to. + // dispatchMethod() will call unspecified() if name is null + String keyName = request.getParameter(parameter); + if (StringUtils.isEmpty(keyName)) { + return null; + } + + // Based on this request's Locale get the lookupMap + Map lookupMap = null; + + synchronized(localeMap) { + Locale userLocale = this.getLocale(request); + lookupMap = (Map) this.localeMap.get(userLocale); + + if (lookupMap == null) { + lookupMap = this.initLookupMap(request, userLocale); + this.localeMap.put(userLocale, lookupMap); + } + } + + // Find the key for the resource + String key = (String) lookupMap.get(keyName); + if (key == null) { + String message = messages.getMessage( + "dispatch.resource", mapping.getPath(), keyName); + throw new ServletException(message); + } + + // Find the method name + String methodName = (String) keyMethodMap.get(key); + if (methodName == null) { + String message = messages.getMessage( + "dispatch.lookup", mapping.getPath(), key); + throw new ServletException(message); + } + + return methodName; + } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]