webwork/src/main/webwork/dispatcher ServletDispatcher.java,1.37,1.38

[email protected] Thu, 13 Jun 2002 10:18:23 -0700
Newsgroups gmane.comp.java.webwork.cvs
Message-ID <[email protected]>
Update of /cvsroot/webwork/webwork/src/main/webwork/dispatcher
In directory usw-pr-cvs1:/tmp/cvs-serv24270

Modified Files:
	ServletDispatcher.java 
Log Message:
added action chaining support

Index: ServletDispatcher.java
===================================================================
RCS file: /cvsroot/webwork/webwork/src/main/webwork/dispatcher/ServletDispatcher.java,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- ServletDispatcher.java	30 May 2002 22:58:59 -0000	1.37
+++ ServletDispatcher.java	13 Jun 2002 17:18:20 -0000	1.38
@@ -17,6 +17,7 @@
 import webwork.multipart.MultiPartRequestWrapper;
 import webwork.util.LoggerUtil;
 import webwork.util.ValueStack;
+import webwork.util.BeanUtil;
 
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletConfig;
@@ -39,6 +40,7 @@
  * of the package names in the comma-separated "packages" servlet init parameter.
  *
  * @author Rickard Öberg ([email protected])
+ * @author Matt Baldree ([email protected])
  * @version $Revision$
  */
 public class ServletDispatcher
@@ -155,7 +157,13 @@
    }
 
    /**
-    * Service a request
+    * Service a request.
+    * The request is first checked to see if it is a multi-part. If it is, then the request
+    * is wrapped so WW will be able to work with the multi-part as if it was a normal request.
+    * Next, we will process all actions until an action returns a non-action which is usually
+    * a view. For each action in a chain, the action's context will be first set and then the
+    * action will be instantiated. Next, the previous action if this action isn't the first in
+    * the chain will have its attributes copied to the current action.
     *
     * @param   aRequest
     * @param   aResponse
@@ -168,101 +176,103 @@
       aRequest = wrapRequest(aRequest);
 
       // Get action
-      String pathInfo = (String) aRequest.getAttribute("javax.servlet.include.path_info");
-      if (pathInfo == null)
-         pathInfo = aRequest.getPathInfo();
       String servletPath = (String) aRequest.getAttribute("javax.servlet.include.servlet_path");
       if (servletPath == null)
          servletPath = aRequest.getServletPath();
 
-      // Get action name ("Foo.action" -> "Foo" action)
-      final String actionName;
-      String actionPath = "/";
-      int idx = servletPath.lastIndexOf("/");
-      actionName = servletPath.substring(idx + 1, servletPath.lastIndexOf("."));
-
       // Path is always original path, even if it is included in page with another path
-      actionPath = aRequest.getServletPath();
+      String actionPath = aRequest.getServletPath();
       actionPath = actionPath.substring(0, actionPath.lastIndexOf("/") + 1);
 
-      final Action action;
-
       // Set thread locals so that actions can be initialized properly
       ActionContext oldContext = ActionContext.getContext();
 
-      try {
-         ActionContext context = new ActionContext();
-         context.setName(actionName);
-         context.setRequest(aRequest);
-         context.setResponse(aResponse);
-         context.setServletContext(getServletContext());
-         ActionContext.setContext(context);
+      try
+      {
+         String candidateAction = servletPath;
+         String actionName = "";
+         String result = "";
+         Action action = null;
+         Action prevAction = null;
 
-         try {
-            action = ActionFactory.getAction(actionName);
-         } catch (Exception e) {
-            // Log the error
-            log.error("Could not instantiate action:" + actionName, e);
+         //--------------- run action chain
+         while(isAction(candidateAction))
+         {
+            //strip directories and extension
+            actionName = getActionName(candidateAction);
+            //set action's context
+            setActionContext(actionName, aRequest, aResponse);
 
+            //instantiate action and set its attributes from context
             try {
-               aResponse.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
-               return;
-            } catch (IOException ex) {
-               throw new ServletException(ex);
+               prevAction = action;
+               action = ActionFactory.getAction(actionName);
+            } catch (Exception e) {
+               // Log the error
+               log.error("Could not instantiate action:" + actionName, e);
+
+               try {
+                  aResponse.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
+                  return;
+               } catch (IOException ex) {
+                  throw new ServletException(ex);
+               }
             }
-         }
 
-         // Execute action
-         String result = null;
-         log.debug("Action:" + actionName);
-         NDC.push(actionName);
-         try {
-            result = action.execute();
-         } catch (SecurityException e) {
-            // Security exception thrown
-            throw new ServletException("You're not allowed to access the action " + actionName, e);
-         } catch (ResultException e) {
-            // Show chosen view
-            result = (String) e.getResult();
-         } catch (Exception e) {
-            log.debug("Action execution exception", e);
-            throw new ServletException("System error while executing " + action.getClass(), e);
-         } finally {
-            NDC.pop();
-         }
+            //copy previous actions attributes to new action
+            try {
+               if (prevAction!=null) {
+                  BeanUtil.copy(prevAction, action);
+                  prevAction = null;
+               }
+            } catch (IllegalArgumentException e) {
+               log.error("Error copying previous action to current action.", e);
+               throw new ServletException("Unable to copy previous action attributes to current action.");
+            }
 
-         log.debug("Result:" + result);
+            // Execute action
+            result = null;
+            log.debug("Action:" + actionName);
+            NDC.push(actionName);
+            try {
+               result = action.execute();
+            } catch (SecurityException e) {
+               // Security exception thrown
+               throw new ServletException("You're not allowed to access the action " + actionName, e);
+            } catch (ResultException e) {
+               result = (String) e.getResult();
+            } catch (Exception e) {
+               log.debug("Action execution exception", e);
+               throw new ServletException("System error while executing " + action.getClass(), e);
+            } finally {
+               NDC.pop();
+            }
 
-         // No result
-         if (result == null) {
-            log.debug("Action has no result");
-            throw new ServletException("System error while executing " + action.getClass());
-         }
+            log.debug("Result:" + result);
 
-         // Get view corresponding to result
-         // Check request override first
-         String view;
-         if ((view = aRequest.getParameter(result)) == null) {
-            try {
-               view = (String) mapping.getView(actionName, result);
-            } catch (IllegalArgumentException e) {
-               // No view found
-               log.debug("No view found for action " + actionName);
+            // No result
+            if (result == null) {
+               log.debug("Action has no result");
+               throw new ServletException("System error while executing " + action.getClass());
             }
-         }
+            candidateAction = getView(aRequest, actionName, result);
+         }//while
+
 
+         //------------ show view
+         String view = candidateAction;
          // Only show if a view is assigned to this actions result
-         if (view != null) {
+         if (view != null)
+         {
             // Show view
             if (!view.startsWith("/")) view = actionPath + view; // Add path prefix
-
-            try {
+            try
+            {
                log.debug("View:" + view);
 
                // Push view name onto NDC
                NDC.push(view);
 
-
                RequestDispatcher dispatcher = null;
                try {
                   dispatcher = aRequest.getRequestDispatcher(view);
@@ -304,8 +314,79 @@
       } finally {
          // Reset context. Important if this action was included
          ActionContext.setContext(oldContext);
+      }//try
+   }
+
+
+   /**
+    * Get view corresponding to result of action execution but
+    * first check servlet request for an override.
+    *
+    * @param aRequest The servlet request.
+    * @param actionName The action name. This includes the full name minus the extension.
+    * @param result The result from the execution of the action.
+    * @return String
+    */
+   private String getView(HttpServletRequest aRequest, String actionName, String result)
+   {
+      String view = null;
+      if ((view = aRequest.getParameter(result)) == null)
+      {
+         try {
+            view = (String) mapping.getView(actionName, result);
+         } catch (IllegalArgumentException e) {
+            // No view found
+            e.printStackTrace();
+            log.debug("No view found for action " + actionName);
+         }
       }
+      return view;
+   }
+
+
+   /**
+    * Set action context for action name.
+    */
+   private void setActionContext(String actionName,
+                                 HttpServletRequest request,
+                                 HttpServletResponse response)
+   {
+      ActionContext context = new ActionContext();
+      context.setName(actionName);
+      context.setRequest(request);
+      context.setResponse(response);
+      context.setServletContext(getServletContext());
+      ActionContext.setContext(context);
+   }
+
+
+   /**
+    * Determine action name by extracting last string and removing
+    * extension. (/.../.../Foo.action -> Foo)
+    */
+   private String getActionName(String name)
+   {
+      // Get action name ("Foo.action" -> "Foo" action)
+      int beginIdx = name.lastIndexOf("/");
+      int endIdx = name.lastIndexOf(".");
+      return name.substring((beginIdx==-1 ? 0 : beginIdx + 1),
+            endIdx==-1 ? name.length() : endIdx);
    }
+
+   /**
+    * Is this string an action? Determines if the string
+    * ends with the action extension which is defined by
+    * the property "webwork.action.extension"
+    *
+    * @param action The string to test
+    * @return boolean Whether the string is an action
+    */
+   private boolean isAction(String action)
+   {
+      return (action==null) ? false :
+         action.endsWith(Configuration.getString("webwork.action.extension"));
+   }
+
 
    /**
     * Wrap servlet request with the appropriate request. It will check to



_______________________________________________________________

Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas - http://devcon.sprintpcs.com/adp/index.cfm?source=osdntextlink