2
0
Эх сурвалжийг харах

Take another apporach and throw all unhandled exceptions wrapped in a ServletException

Carlos Sanchez 19 жил өмнө
parent
commit
30f6871124

+ 11 - 0
sandbox/webwork/pom.xml

@@ -13,5 +13,16 @@
   <description>Acegi Security System for Spring - Support for WebWork 2</description>
   <version>0.1-SNAPSHOT</version>
   <dependencies>
+    <dependency>
+      <groupId>opensymphony</groupId>
+      <artifactId>webwork</artifactId>
+      <version>2.2.3</version>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 </project>

+ 79 - 40
sandbox/webwork/src/main/java/org/acegisecurity/webwork/AcegiDispatcherUtils.java

@@ -14,18 +14,27 @@
  */
 package org.acegisecurity.webwork;
 
-import java.io.IOException;
+import java.util.Map;
 
 import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.acegisecurity.AccessDeniedException;
-import org.acegisecurity.AcegiSecurityException;
-import org.acegisecurity.AuthenticationException;
 import org.acegisecurity.ui.ExceptionTranslationFilter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
+import com.opensymphony.webwork.ServletActionContext;
 import com.opensymphony.webwork.dispatcher.DispatcherUtils;
+import com.opensymphony.webwork.dispatcher.mapper.ActionMapping;
+import com.opensymphony.xwork.ActionContext;
+import com.opensymphony.xwork.ActionProxy;
+import com.opensymphony.xwork.ActionProxyFactory;
+import com.opensymphony.xwork.Result;
+import com.opensymphony.xwork.config.ConfigurationException;
+import com.opensymphony.xwork.util.OgnlValueStack;
+import com.opensymphony.xwork.util.XWorkContinuationConfig;
 
 /**
  * <p>
@@ -43,51 +52,81 @@ import com.opensymphony.webwork.dispatcher.DispatcherUtils;
  */
 public class AcegiDispatcherUtils extends DispatcherUtils {
 
+    private static final Log LOG = LogFactory.getLog(AcegiDispatcherUtils.class);
+
     protected AcegiDispatcherUtils(ServletContext servletContext) {
         super(servletContext);
     }
 
     /**
-     * Sends an HTTP error response code on any exception that it's no an Acegi {@link AuthenticationException} or
-     * {@link AccessDeniedException}
+     * <p>
+     * Loads the action and executes it. This method first creates the action context from the given parameters then
+     * loads an <tt>ActionProxy</tt> from the given action name and namespace. After that, the action is executed and
+     * output channels throught the response object. Actions not found are sent back to the user via the
+     * {@link DispatcherUtils#sendError} method, using the 404 return code. All other errors are reported by throwing a
+     * ServletException.
+     * </p>
+     * 
+     * <p>
+     * Difference between this and WebWork prvided class is that any unhandled exception will be thrown instead of
+     * processed inside WebWork.
+     * </p>
      * 
-     * @param request the HttpServletRequest object.
-     * @param response the HttpServletResponse object.
-     * @param code the HttpServletResponse error code (see {@link javax.servlet.http.HttpServletResponse} for possible
-     * error codes).
-     * @param e the Exception that is reported.
+     * @param request the HttpServletRequest object
+     * @param response the HttpServletResponse object
+     * @param mapping the action mapping object
+     * @throws ServletException when an unknown error occurs (not a 404, but typically something that would end up as a
+     * 5xx by the servlet container)
      */
-    public void sendError(HttpServletRequest request, HttpServletResponse response, ServletContext ctx, int code,
-            Exception e) {
-        if (devMode) {
-            super.sendError(request, response, ctx, code, e);
-        } else {
-            try {
-                // send a http error response to use the servlet defined error handler
-                // make the exception availible to the web.xml defined error page
-                request.setAttribute("javax.servlet.error.exception", e);
-
-                // for compatibility
-                request.setAttribute("javax.servlet.jsp.jspException", e);
-
-                // do not send the error response if it's an acegi exception
-                if (!isAcegiSecurityException(e)) {
-                    response.sendError(code, e.getMessage());
-                }
-            } catch (IOException e1) {
-                // we're already sending an error, not much else we can do if more stuff breaks
-            }
+    public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
+            ActionMapping mapping) throws ServletException {
+        Map extraContext = createContextMap(request, response, mapping, context);
+
+        // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
+        OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
+        if (stack != null) {
+            extraContext.put(ActionContext.VALUE_STACK, new OgnlValueStack(stack));
         }
-    }
 
-    /**
-     * Check if an object is an {@link AcegiSecurityException}.
-     * 
-     * @param o any object or <code>null</code>
-     * @return true if the object passed is an {@link AuthenticationException} or {@link AccessDeniedException}
-     */
-    private boolean isAcegiSecurityException(Object o) {
-        return ((o != null) && ((o instanceof AuthenticationException || o instanceof AccessDeniedException)));
+        try {
+            String namespace = mapping.getNamespace();
+            String name = mapping.getName();
+            String method = mapping.getMethod();
+
+            String id = request.getParameter(XWorkContinuationConfig.CONTINUE_PARAM);
+            if (id != null) {
+                // remove the continue key from the params - we don't want to bother setting
+                // on the value stack since we know it won't work. Besides, this breaks devMode!
+                Map params = (Map) extraContext.get(ActionContext.PARAMETERS);
+                params.remove(XWorkContinuationConfig.CONTINUE_PARAM);
+
+                // and now put the key in the context to be picked up later by XWork
+                extraContext.put(XWorkContinuationConfig.CONTINUE_KEY, id);
+            }
+
+            ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, name, extraContext, true,
+                    false);
+            proxy.setMethod(method);
+            request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());
+
+            // if the ActionMapping says to go straight to a result, do it!
+            if (mapping.getResult() != null) {
+                Result result = mapping.getResult();
+                result.execute(proxy.getInvocation());
+            } else {
+                proxy.execute();
+            }
+
+            // If there was a previous value stack then set it back onto the request
+            if (stack != null) {
+                request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, stack);
+            }
+        } catch (ConfigurationException e) {
+            LOG.error("Could not find action", e);
+            sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
+        } catch (Exception e) {
+            throw new ServletException(e);
+        }
     }
 
 }