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>