You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by pb...@apache.org on 2008/11/22 23:28:10 UTC
svn commit: r719932 - in /struts/struts1/trunk/core/src/main:
java/org/apache/struts/chain/ java/org/apache/struts/chain/commands/
java/org/apache/struts/config/ resources/org/apache/struts/chain/
resources/org/apache/struts/resources/
Author: pbenedict
Date: Sat Nov 22 14:28:09 2008
New Revision: 719932
URL: http://svn.apache.org/viewvc?rev=719932&view=rev
Log:
STR-3168: Install new ExecuteDispatcher command to execute action, if configured, through a dispatcher
Added:
struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/ExecuteDispatcher.java (with props)
Modified:
struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/Constants.java
struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/AbstractExecuteAction.java
struts/struts1/trunk/core/src/main/java/org/apache/struts/config/ActionConfig.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_4.dtd
Modified: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/Constants.java
URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/Constants.java?rev=719932&r1=719931&r2=719932&view=diff
==============================================================================
--- struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/Constants.java (original)
+++ struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/Constants.java Sat Nov 22 14:28:09 2008
@@ -20,6 +20,8 @@
*/
package org.apache.struts.chain;
+import org.apache.struts.action.Dispatcher;
+
/**
* <p>Global constants for the Chain of Responsibility Library.</p>
@@ -111,6 +113,17 @@
public static final String ACTIONS_KEY = "actions";
/**
+ * <p>The base part of the context attribute under which a Map containing
+ * the Dispatcher instances associated with this module are stored. This value
+ * must be suffixed with the module prefix in order to create a unique key
+ * per module.</p>
+ *
+ * @see Dispatcher
+ * @since Struts 1.4
+ */
+ public static final String DISPATCHERS_KEY = "dispatchers";
+
+ /**
* <p>The context attribute under which the Catalog containing our defined
* command chains has been stored.</p>
*/
Modified: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/AbstractExecuteAction.java
URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/AbstractExecuteAction.java?rev=719932&r1=719931&r2=719932&view=diff
==============================================================================
--- struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/AbstractExecuteAction.java (original)
+++ struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/AbstractExecuteAction.java Sat Nov 22 14:28:09 2008
@@ -30,15 +30,17 @@
* <p>Invoke the appropriate <code>Action</code> for this request, and cache
* the returned <code>ActionForward</code>.</p>
*
- * @version $Rev$ $Date: 2005-06-04 10:58:46 -0400 (Sat, 04 Jun 2005)
- * $
+ * @version $Rev$
+ * @see ExecuteDispatcher
+ * @since Struts 1.3
*/
public abstract class AbstractExecuteAction extends ActionCommandBase {
// ---------------------------------------------------------- Public Methods
/**
- * <p>Invoke the appropriate <code>Action</code> for this request, and
- * cache the returned <code>ActionForward</code>.</p>
+ * <p>Invoke the appropriate <code>Action</code> for this request
+ * if a dispatcher is not available, and cache the returned
+ * <code>ActionForward</code>.</p>
*
* @param actionCtx The <code>Context</code> for the current request
* @return <code>false</code> so that processing continues
@@ -46,21 +48,25 @@
*/
public boolean execute(ActionContext actionCtx)
throws Exception {
+
// Skip processing if the current request is not valid
Boolean valid = actionCtx.getFormValid();
-
if ((valid == null) || !valid.booleanValue()) {
return (false);
}
+
+ // Skip processing if a dispatcher is available
+ ActionConfig actionConfig = actionCtx.getActionConfig();
+ if (actionConfig.getDispatcher() != null) {
+ return false;
+ }
// Acquire the resources we will need to send to the Action
Action action = actionCtx.getAction();
-
if (action == null) {
return (false);
}
- ActionConfig actionConfig = actionCtx.getActionConfig();
ActionForm actionForm = actionCtx.getActionForm();
// Execute the Action for this request, caching returned ActionForward
Added: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/ExecuteDispatcher.java
URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/ExecuteDispatcher.java?rev=719932&view=auto
==============================================================================
--- struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/ExecuteDispatcher.java (added)
+++ struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/ExecuteDispatcher.java Sat Nov 22 14:28:09 2008
@@ -0,0 +1,151 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.struts.action.Action;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.Dispatcher;
+import org.apache.struts.chain.Constants;
+import org.apache.struts.chain.commands.util.ClassUtils;
+import org.apache.struts.chain.contexts.ActionContext;
+import org.apache.struts.config.ActionConfig;
+import org.apache.struts.config.ForwardConfig;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class ExecuteDispatcher extends ActionCommandBase {
+
+ private static final Log log = LogFactory.getLog(ExecuteDispatcher.class);
+
+ /**
+ * Creates the dispatcher of the specified type.
+ *
+ * @param type the dispatcher class name
+ * @param context the current action context
+ * @return the dispatcher
+ * @throws Exception if creation fails
+ * @see ClassUtils#getApplicationInstance(String)
+ */
+ protected Dispatcher createDispatcher(String type, ActionContext context)
+ throws Exception {
+ log.info("Initializing dispatcher of type: " + type);
+ return (Dispatcher) ClassUtils.getApplicationInstance(type);
+ }
+
+ public boolean execute(ActionContext context) throws Exception {
+ // Skip processing if the current request is not valid
+ Boolean valid = context.getFormValid();
+ if ((valid == null) || !valid.booleanValue()) {
+ return (false);
+ }
+
+ // If no dispatcher, skip
+ ActionConfig actionConfig = context.getActionConfig();
+ if (actionConfig.getDispatcher() == null) {
+ return CONTINUE_PROCESSING;
+ }
+
+ // Obtain (or create) the dispatcher cache
+ String cacheKey = Constants.DISPATCHERS_KEY
+ + context.getModuleConfig().getPrefix();
+ Map dispatchers = (Map) context.getApplicationScope().get(cacheKey);
+ if (dispatchers == null) {
+ dispatchers = new HashMap();
+ context.getApplicationScope().put(cacheKey, dispatchers);
+ }
+
+ // Lookup (or create) the dispatch instance
+ Dispatcher dispatcher = null;
+ synchronized (dispatchers) {
+ String actionType = actionConfig.getType();
+ dispatcher = (Dispatcher) dispatchers.get(actionType);
+ if (dispatcher == null) {
+ String dispatcherType = actionConfig.getDispatcher();
+ dispatcher = createDispatcher(dispatcherType, context);
+ dispatchers.put(actionType, dispatcher);
+ }
+ }
+
+ // Dispatch
+ Object result = dispatcher.dispatchAction(context);
+ processDispatchResult(result, context);
+ return CONTINUE_PROCESSING;
+ }
+
+ /**
+ * Interprets the specified dispatch result. Subclasses should override this
+ * method to provide custom result type handling. Four handlings are
+ * automatically provided:
+ * <ol>
+ * <li><code>null</code> type means the response was handled directly,
+ * and therefore no extra processing is perform</li>
+ * <li>{@link ForwardConfig} type is the classical response, and will be
+ * stored in the context</li>
+ * <li>{@link String} type represents the name of a required forward to
+ * lookup, and will be stored in the context</li>
+ * <li>{@link Void} type means the method had no return signature, and
+ * select the {@link Action#SUCCESS} action forward and store in the context</li>
+ * </ol>
+ *
+ * @param result the result value
+ * @param context the current action context
+ * @throws IllegalStateException if unknown result type or the forward
+ * cannot be found
+ * @see ActionMapping#findRequiredForward(String)
+ */
+ protected void processDispatchResult(Object result, ActionContext context) {
+ // Null means the response was handled directly
+ if (result == null) {
+ return;
+ }
+
+ // A forward is the classical response
+ if (result instanceof ForwardConfig) {
+ context.setForwardConfig((ForwardConfig) result);
+ return;
+ }
+
+ // String represents the name of a forward
+ ActionConfig actionConfig = context.getActionConfig();
+ ActionMapping mapping = ((ActionMapping) actionConfig);
+ if (result instanceof String) {
+ context.setForwardConfig(mapping
+ .findRequiredForward((String) result));
+ return;
+ }
+
+ // Select success if no return signature
+ if (result instanceof Void) {
+ context.setForwardConfig(mapping
+ .findRequiredForward(Action.SUCCESS));
+ return;
+ }
+
+ // Unknown result type
+ throw new IllegalStateException("Unknown dispatch return type: "
+ + result.getClass().getName());
+ }
+
+}
Propchange: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/ExecuteDispatcher.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: struts/struts1/trunk/core/src/main/java/org/apache/struts/chain/commands/ExecuteDispatcher.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
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?rev=719932&r1=719931&r2=719932&view=diff
==============================================================================
--- 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 Sat Nov 22 14:28:09 2008
@@ -39,6 +39,7 @@
* @since Struts 1.1
*/
public class ActionConfig extends BaseConfig {
+
private static final Log log = LogFactory.getLog(ActionConfig.class);
// ----------------------------------------------------- Instance Variables
@@ -181,26 +182,22 @@
* <p> Should this action be instantiated once per module (singleton)
* or once per request (prototype)? </p>
*/
- protected boolean singleton = true;
+ private boolean singleton = true;
/**
* <p>Identifies conditions for automatic form reset.</p>
- *
- * @since Struts 1.4
*/
protected String reset = PopulateEvent.ALL;
- protected String[] resetNames = { PopulateEvent.ALL };
+ private String[] resetNames = { PopulateEvent.ALL };
/**
* <p> Identifies conditions for automatic form population with values
* from HTTP request.</p>
- *
- * @since Struts 1.4
*/
protected String populate = PopulateEvent.ALL;
- protected String[] populateNames = { PopulateEvent.ALL };
+ private String[] populateNames = { PopulateEvent.ALL };
/**
* <p> Suffix used to match request parameter names to form bean property
@@ -253,6 +250,14 @@
* @since Struts 1.3.0
*/
protected String catalog = null;
+
+ /**
+ * The name of the {@link org.apache.struts.action.Dispatcher} implementation
+ * that will dispatch to the end point of this action.
+ *
+ * @since Struts 1.4
+ */
+ protected String dispatcher;
/**
* <p>The internal name of this action mapping. If an action has a name, it may be used
@@ -660,7 +665,7 @@
* @see #getResetNames()
* @see #setReset(String)
*/
- public String getReset() {
+ public final String getReset() {
return (this.reset);
}
@@ -672,7 +677,7 @@
* @see #getReset()
* @see PopulateEvent
*/
- public String[] getResetNames() {
+ public final String[] getResetNames() {
return (this.resetNames);
}
@@ -683,7 +688,7 @@
* @see #getReset()
* @see #getResetNames()
*/
- public void setReset(String reset) {
+ public final void setReset(String reset) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
@@ -700,7 +705,7 @@
* @see #getPopulateNames()
* @see #setPopulate(String)
*/
- public String getPopulate() {
+ public final String getPopulate() {
return (this.populate);
}
@@ -712,7 +717,7 @@
* @see #getPopulate()
* @see PopulateEvent
*/
- public String[] getPopulateNames() {
+ public final String[] getPopulateNames() {
return (this.populateNames);
}
@@ -723,7 +728,7 @@
* @see #getPopulate()
* @see #getPopulateNames()
*/
- public void setPopulate(String populate) {
+ public final void setPopulate(String populate) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
@@ -741,7 +746,7 @@
* @see #setSingleton(boolean)
* @since Struts 1.4
*/
- public boolean isSingleton() {
+ public final boolean isSingleton() {
return this.singleton;
}
@@ -752,7 +757,7 @@
* @see #isSingleton()
* @since Struts 1.4
*/
- public void setSingleton(boolean singleton) {
+ public final void setSingleton(boolean singleton) {
this.singleton = singleton;
}
@@ -882,6 +887,36 @@
this.catalog = catalog;
}
+ /**
+ * Retrieves the fully-qualified class name of the
+ * {@link org.apache.struts.action.Dispatcher} implementation that will
+ * dispatch to the this action.
+ *
+ * @return the dispatcher class name or <code>null</code>
+ * @see #setDispatcher(String)
+ * @since Struts 1.4
+ */
+ public final String getDispatcher() {
+ return dispatcher;
+ }
+
+ /**
+ * Stores the fully-qualified class name of the
+ * {@link org.apache.struts.action.Dispatcher} implementation that will
+ * dispatch to the this action.
+ *
+ * @param dispatcher the dispatcher class name
+ * @throws IllegalStateException if the configuration is frozen
+ * @see #getDispatcher()
+ * @since Struts 1.4
+ */
+ public final void setDispatcher(String dispatcher) {
+ if (configured) {
+ throw new IllegalStateException("Configuration is frozen");
+ }
+ this.dispatcher = dispatcher;
+ }
+
// ------------------------------------------------------ Protected Methods
/**
@@ -1360,9 +1395,9 @@
sb.append(command);
}
- if (inherit != null) {
- sb.append(",extends=");
- sb.append(inherit);
+ if (dispatcher != null) {
+ sb.append(",dispatcher=");
+ sb.append(dispatcher);
}
if (forward != null) {
@@ -1375,6 +1410,11 @@
sb.append(include);
}
+ if (inherit != null) {
+ sb.append(",extends=");
+ sb.append(inherit);
+ }
+
if (input != null) {
sb.append(",input=");
sb.append(input);
@@ -1436,4 +1476,5 @@
sb.append("]");
return (sb.toString());
}
+
}
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?rev=719932&r1=719931&r2=719932&view=diff
==============================================================================
--- 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 Sat Nov 22 14:28:09 2008
@@ -104,7 +104,7 @@
processActionCreate CreateAction
- processActionPerform ExecuteAction
+ processActionPerform ExecuteAction / ExecuteDispatcher
-->
@@ -190,11 +190,14 @@
<command
className="org.apache.struts.chain.commands.servlet.PerformInclude"/>
-
<!-- Create (if needed) the Action for this request -->
<command
className="org.apache.struts.chain.commands.servlet.CreateAction"/>
+ <!-- Dispatch the request -->
+ <command
+ className="org.apache.struts.chain.commands.ExecuteDispatcher"/>
+
<!-- Execute the Action for this request -->
<command
className="org.apache.struts.chain.commands.servlet.ExecuteAction"/>
Modified: struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_4.dtd
URL: http://svn.apache.org/viewvc/struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_4.dtd?rev=719932&r1=719931&r2=719932&view=diff
==============================================================================
--- struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_4.dtd (original)
+++ struts/struts1/trunk/core/src/main/resources/org/apache/struts/resources/struts-config_1_4.dtd Sat Nov 22 14:28:09 2008
@@ -386,6 +386,11 @@
command The name of a commons-chain command which should be looked up
and executed as part of servicing this request.
+ dispatcher The fully qualified Java class name of the Dispatcher
+ implementation to use to execute the action. This is optional,
+ and the fallback behavior is to invoke the classical
+ execute() method.
+
extends The path or actionId of the action mapping configuration
that this will inherit configuration information from.
@@ -483,6 +488,7 @@
<!ATTLIST action catalog CDATA #IMPLIED>
<!ATTLIST action className %ClassName; #IMPLIED>
<!ATTLIST action command CDATA #IMPLIED>
+<!ATTLIST action dispatcher %ClassName; #IMPLIED>
<!ATTLIST action extends %RequestPath; #IMPLIED>
<!ATTLIST action forward %RequestPath; #IMPLIED>
<!ATTLIST action include %RequestPath; #IMPLIED>