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

This commit is contained in:
Carlos Sanchez 2006-09-06 17:18:36 +00:00
parent e8de53b87c
commit 30f6871124
2 changed files with 88 additions and 38 deletions

View File

@ -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>

View File

@ -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>
*
* @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.
* <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 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);
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
ActionMapping mapping) throws ServletException {
Map extraContext = createContextMap(request, response, mapping, context);
// for compatibility
request.setAttribute("javax.servlet.jsp.jspException", e);
// 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));
}
// 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
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);
}
}
/**
* 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)));
}
}