You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by ni...@apache.org on 2006/03/08 02:53:59 UTC
svn commit: r384090 - in
/struts/extras/trunk/src/java/org/apache/struts/actions:
EventActionDispatcher.java EventDispatchAction.java LocalStrings.properties
Author: niallp
Date: Tue Mar 7 17:53:58 2006
New Revision: 384090
URL: http://svn.apache.org/viewcvs?rev=384090&view=rev
Log:
Bug 38343 - Add EventDispatchAction and EventActionDispatcher - submitted by Paul Benedict
Added:
struts/extras/trunk/src/java/org/apache/struts/actions/EventActionDispatcher.java (with props)
struts/extras/trunk/src/java/org/apache/struts/actions/EventDispatchAction.java (with props)
Modified:
struts/extras/trunk/src/java/org/apache/struts/actions/LocalStrings.properties
Added: struts/extras/trunk/src/java/org/apache/struts/actions/EventActionDispatcher.java
URL: http://svn.apache.org/viewcvs/struts/extras/trunk/src/java/org/apache/struts/actions/EventActionDispatcher.java?rev=384090&view=auto
==============================================================================
--- struts/extras/trunk/src/java/org/apache/struts/actions/EventActionDispatcher.java (added)
+++ struts/extras/trunk/src/java/org/apache/struts/actions/EventActionDispatcher.java Tue Mar 7 17:53:58 2006
@@ -0,0 +1,197 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 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.actions;
+
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+
+/**
+ * <p>An Action helper class that dispatches to to one of the public methods
+ * that are named in the <code>parameter</code> attribute of the corresponding
+ * ActionMapping and matches a submission parameter. This is useful for
+ * developers who prefer to use many submit buttons, images, or submit links
+ * on a single form and whose related actions exist in a single Action class.</p>
+ *
+ * <p>The method(s) in the associated <code>Action</code> must have the same
+ * signature (other than method name) of the standard Action.execute method.</p>
+ *
+ * <p>To configure the use of this action in your
+ * <code>struts-config.xml</code> file, create an entry like this:</p>
+ *
+ * <pre><code>
+ * <action path="/saveSubscription"
+ * type="org.example.SubscriptionAction"
+ * name="subscriptionForm"
+ * scope="request"
+ * input="/subscription.jsp"
+ * parameter="save,back,recalc=recalculate,default=save"/>
+ * </code></pre>
+ *
+ * <p>where <code>parameter</code> contains three possible methods and one
+ * default method if nothing matches (such as the user pressing the enter key).</p>
+ *
+ * <p>For utility purposes, you can use the <code>key=value</code> notation to
+ * alias methods so that they are exposed as different form element names, in the
+ * event of a naming conflict or otherwise. In this example, the <em>recalc</em>
+ * button (via a request parameter) will invoke the <code>recalculate</code>
+ * method. The security-minded person may find this feature valuable to
+ * obfuscate and not expose the methods.</p>
+ *
+ * <p>The <em>default</em> key is purely optional. If this is not specified
+ * and no parameters match the list of method keys, <code>null</code> is
+ * returned which means the <code>unspecified</code> method will be invoked.</p>
+ *
+ * <p>The order of the parameters are guaranteed to be iterated in the order
+ * specified. If multiple buttons were accidently submitted, the first match in
+ * the list will be dispatched.</p>
+ *
+ * <p>To implement this <i>dispatch</i> behaviour in an <code>Action</code>,
+ * class create your custom Action as follows, along with the methods you require
+ * (and optionally "cancelled" and "unspecified" methods):</p> <p/>
+ * <pre>
+ * public class MyCustomAction extends Action {
+ *
+ * protected ActionDispatcher dispatcher = new EventActionDispatcher(this);
+ *
+ * public ActionForward execute(ActionMapping mapping,
+ * ActionForm form,
+ * HttpServletRequest request,
+ * HttpServletResponse response)
+ * throws Exception {
+ * return dispatcher.execute(mapping, form, request, response);
+ * }
+ * }
+ * </pre>
+ * <p/>
+ *
+ * @since Struts 1.2.9
+ */
+public class EventActionDispatcher extends ActionDispatcher {
+
+ /**
+ * Commons Logging instance.
+ */
+ private static final Log LOG = LogFactory.getLog(EventActionDispatcher.class);
+
+ /**
+ * The method key, if present, to use if other specified method keys
+ * do not match a request parameter.
+ */
+ private static final String DEFAULT_METHOD_KEY = "default";
+
+ /**
+ * Constructs a new object for the specified action.
+ * @param action the action
+ */
+ public EventActionDispatcher(Action action) {
+ super(action, -1);
+ }
+
+ /**
+ * 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.
+ * @throws Exception if an error occurs.
+ */
+ protected String getMethodName(ActionMapping mapping, ActionForm form,
+ HttpServletRequest request, HttpServletResponse response,
+ String parameter) throws Exception {
+
+ StringTokenizer st = new StringTokenizer(parameter, ",");
+ String defaultMethodName = null;
+
+ while (st.hasMoreTokens()) {
+ String methodKey = st.nextToken().trim();
+ String methodName = methodKey;
+
+ // The key can either be a direct method name or an alias
+ // to a method as indicated by a "key=value" signature
+ int equals = methodKey.indexOf('=');
+ if (equals > -1) {
+ methodName = methodKey.substring(equals + 1).trim();
+ methodKey = methodKey.substring(0, equals).trim();
+ }
+
+ // Set the default if it passes by
+ if (methodKey.equals(DEFAULT_METHOD_KEY)) {
+ defaultMethodName = methodName;
+ }
+
+ // If the method key exists as a standalone parameter or with
+ // the image suffixes (.x/.y), the method name has been found.
+ if ((request.getParameter(methodKey) != null)
+ || (request.getParameter(methodKey + ".x") != null)) {
+ return methodName;
+ }
+ }
+
+ if (defaultMethodName == null || defaultMethodName.length() == 0) {
+ String message =
+ messages.getMessage("event.parameter", mapping.getPath());
+ LOG.error(message + " " + parameter);
+ throw new ServletException(message);
+ }
+
+ return defaultMethodName;
+ }
+
+ /**
+ * Returns the parameter.
+ *
+ * @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
+ * @return The <code>ActionMapping</code> parameter's value
+ * @throws Exception if the parameter is missing.
+ */
+ protected String getParameter(ActionMapping mapping, ActionForm form,
+ HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ String parameter = mapping.getParameter();
+ if ("".equals(parameter)) {
+ parameter = null;
+ }
+
+ if (parameter == null) {
+ String message =
+ messages.getMessage("dispatch.handler", mapping.getPath());
+ LOG.error(message);
+ throw new ServletException(message);
+ }
+
+ return parameter;
+ }
+}
Propchange: struts/extras/trunk/src/java/org/apache/struts/actions/EventActionDispatcher.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: struts/extras/trunk/src/java/org/apache/struts/actions/EventActionDispatcher.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added: struts/extras/trunk/src/java/org/apache/struts/actions/EventDispatchAction.java
URL: http://svn.apache.org/viewcvs/struts/extras/trunk/src/java/org/apache/struts/actions/EventDispatchAction.java?rev=384090&view=auto
==============================================================================
--- struts/extras/trunk/src/java/org/apache/struts/actions/EventDispatchAction.java (added)
+++ struts/extras/trunk/src/java/org/apache/struts/actions/EventDispatchAction.java Tue Mar 7 17:53:58 2006
@@ -0,0 +1,170 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 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.actions;
+
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+
+/**
+ * <p>An <strong>Action</strong> that dispatches to to one of the public methods
+ * that are named in the <code>parameter</code> attribute of the corresponding
+ * ActionMapping and matches a submission parameter. This is useful for
+ * developers who prefer to use many submit buttons, images, or submit links
+ * on a single form and whose related actions exist in a single Action class.</p>
+ *
+ * <p>The method(s) must have the same signature (other than method name) of the
+ * standard Action.execute method.</p>
+ *
+ * <p>To configure the use of this action in your
+ * <code>struts-config.xml</code> file, create an entry like this:</p>
+ *
+ * <pre><code>
+ * <action path="/saveSubscription"
+ * type="org.example.SubscriptionAction"
+ * name="subscriptionForm"
+ * scope="request"
+ * input="/subscription.jsp"
+ * parameter="save,back,recalc=recalculate,default=save"/>
+ * </code></pre>
+ *
+ * <p>where <code>parameter</code> contains three possible methods and one
+ * default method if nothing matches (such as the user pressing the enter key).</p>
+ *
+ * <p>For utility purposes, you can use the <code>key=value</code> notation to
+ * alias methods so that they are exposed as different form element names, in the
+ * event of a naming conflict or otherwise. In this example, the <em>recalc</em>
+ * button (via a request parameter) will invoke the <code>recalculate</code>
+ * method. The security-minded person may find this feature valuable to
+ * obfuscate and not expose the methods.</p>
+ *
+ * <p>The <em>default</em> key is purely optional. If this is not specified
+ * and no parameters match the list of method keys, <code>null</code> is
+ * returned which means the <code>unspecified</code> method will be invoked.</p>
+ *
+ * <p>The order of the parameters are guaranteed to be iterated in the order
+ * specified. If multiple buttons were accidently submitted, the first match in
+ * the list will be dispatched.</p>
+ *
+ * @since Struts 1.2.9
+ */
+public class EventDispatchAction extends DispatchAction {
+
+ /**
+ * Commons Logging instance.
+ */
+ private static final Log LOG = LogFactory.getLog(EventDispatchAction.class);
+
+ /**
+ * The method key, if present, to use if other specified method keys
+ * do not match a request parameter.
+ */
+ private static final String DEFAULT_METHOD_KEY = "default";
+
+ // --------------------------------------------------------- Protected Methods
+
+ /**
+ * 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.
+ * @throws Exception if an error occurs.
+ */
+ protected String getMethodName(ActionMapping mapping, ActionForm form,
+ HttpServletRequest request, HttpServletResponse response,
+ String parameter) throws Exception {
+
+ StringTokenizer st = new StringTokenizer(parameter, ",");
+ String defaultMethodName = null;
+
+ while (st.hasMoreTokens()) {
+ String methodKey = st.nextToken().trim();
+ String methodName = methodKey;
+
+ // The key can either be a direct method name or an alias
+ // to a method as indicated by a "key=value" signature
+ int equals = methodKey.indexOf('=');
+ if (equals > -1) {
+ methodName = methodKey.substring(equals + 1).trim();
+ methodKey = methodKey.substring(0, equals).trim();
+ }
+
+ // Set the default if it passes by
+ if (methodKey.equals(DEFAULT_METHOD_KEY)) {
+ defaultMethodName = methodName;
+ }
+
+ // If the method key exists as a standalone parameter or with
+ // the image suffixes (.x/.y), the method name has been found.
+ if ((request.getParameter(methodKey) != null)
+ || (request.getParameter(methodKey + ".x") != null)) {
+ return methodName;
+ }
+ }
+
+ if (defaultMethodName == null || defaultMethodName.length() == 0) {
+ String message =
+ messages.getMessage("event.parameter", mapping.getPath());
+ LOG.error(message + " " + parameter);
+ throw new ServletException(message);
+ }
+
+ return defaultMethodName;
+ }
+
+ /**
+ * Returns the parameter.
+ *
+ * @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
+ * @return The <code>ActionMapping</code> parameter's value
+ * @throws Exception if the parameter is missing.
+ */
+ protected String getParameter(ActionMapping mapping, ActionForm form,
+ HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ String parameter = mapping.getParameter();
+ if ("".equals(parameter)) {
+ parameter = null;
+ }
+
+ if (parameter == null) {
+ String message =
+ messages.getMessage("dispatch.handler", mapping.getPath());
+ LOG.error(message);
+ throw new ServletException(message);
+ }
+
+ return parameter;
+ }
+}
Propchange: struts/extras/trunk/src/java/org/apache/struts/actions/EventDispatchAction.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: struts/extras/trunk/src/java/org/apache/struts/actions/EventDispatchAction.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: struts/extras/trunk/src/java/org/apache/struts/actions/LocalStrings.properties
URL: http://svn.apache.org/viewcvs/struts/extras/trunk/src/java/org/apache/struts/actions/LocalStrings.properties?rev=384090&r1=384089&r2=384090&view=diff
==============================================================================
--- struts/extras/trunk/src/java/org/apache/struts/actions/LocalStrings.properties (original)
+++ struts/extras/trunk/src/java/org/apache/struts/actions/LocalStrings.properties Tue Mar 7 17:53:58 2006
@@ -6,6 +6,7 @@
dispatch.method=Action[{0}] does not contain method named '{1}'
dispatch.method.user=Action[{0}] does not contain specified method (check logs)
dispatch.parameter=Request[{0}] does not contain handler parameter named '{1}'. This may be caused by whitespace in the label text.
+event.parameter=Request[{0}] does not contain handler parameter.
dispatch.return=Action[{0}] invalid return type for method '{1}'
dispatch.resource=Action[{0}] missing resource in key method map
forward.path=No context-relative URI specified via the 'parameter' attribute
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org