001: /* Copyright 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015: package org.acegisecurity.webwork;
016:
017: import java.util.Map;
018:
019: import javax.servlet.ServletContext;
020: import javax.servlet.ServletException;
021: import javax.servlet.http.HttpServletRequest;
022: import javax.servlet.http.HttpServletResponse;
023:
024: import org.acegisecurity.ui.ExceptionTranslationFilter;
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027:
028: import com.opensymphony.webwork.ServletActionContext;
029: import com.opensymphony.webwork.dispatcher.DispatcherUtils;
030: import com.opensymphony.webwork.dispatcher.mapper.ActionMapping;
031: import com.opensymphony.xwork.ActionContext;
032: import com.opensymphony.xwork.ActionProxy;
033: import com.opensymphony.xwork.ActionProxyFactory;
034: import com.opensymphony.xwork.Result;
035: import com.opensymphony.xwork.config.ConfigurationException;
036: import com.opensymphony.xwork.util.OgnlValueStack;
037: import com.opensymphony.xwork.util.XWorkContinuationConfig;
038:
039: /**
040: * <p>
041: * WebWork {@link DispatcherUtils} that ignores Acegi exceptions so they can be processed by
042: * {@link ExceptionTranslationFilter}.
043: * </p>
044: *
045: * <p>
046: * This is meant to be fixed inside WebWork, see <a href="http://jira.opensymphony.com/browse/WW-291">WW-291</a>. Known
047: * broken versions are 2.2.3 and 2.2.4.
048: * </p>
049: *
050: * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
051: * @version $Id: AcegiDispatcherUtils.java 1657 2006-09-06 17:18:36Z carlossg $
052: */
053: public class AcegiDispatcherUtils extends DispatcherUtils {
054:
055: private static final Log LOG = LogFactory
056: .getLog(AcegiDispatcherUtils.class);
057:
058: protected AcegiDispatcherUtils(ServletContext servletContext) {
059: super (servletContext);
060: }
061:
062: /**
063: * <p>
064: * Loads the action and executes it. This method first creates the action context from the given parameters then
065: * loads an <tt>ActionProxy</tt> from the given action name and namespace. After that, the action is executed and
066: * output channels throught the response object. Actions not found are sent back to the user via the
067: * {@link DispatcherUtils#sendError} method, using the 404 return code. All other errors are reported by throwing a
068: * ServletException.
069: * </p>
070: *
071: * <p>
072: * Difference between this and WebWork prvided class is that any unhandled exception will be thrown instead of
073: * processed inside WebWork.
074: * </p>
075: *
076: * @param request the HttpServletRequest object
077: * @param response the HttpServletResponse object
078: * @param mapping the action mapping object
079: * @throws ServletException when an unknown error occurs (not a 404, but typically something that would end up as a
080: * 5xx by the servlet container)
081: */
082: public void serviceAction(HttpServletRequest request,
083: HttpServletResponse response, ServletContext context,
084: ActionMapping mapping) throws ServletException {
085: Map extraContext = createContextMap(request, response, mapping,
086: context);
087:
088: // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
089: OgnlValueStack stack = (OgnlValueStack) request
090: .getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
091: if (stack != null) {
092: extraContext.put(ActionContext.VALUE_STACK,
093: new OgnlValueStack(stack));
094: }
095:
096: try {
097: String namespace = mapping.getNamespace();
098: String name = mapping.getName();
099: String method = mapping.getMethod();
100:
101: String id = request
102: .getParameter(XWorkContinuationConfig.CONTINUE_PARAM);
103: if (id != null) {
104: // remove the continue key from the params - we don't want to bother setting
105: // on the value stack since we know it won't work. Besides, this breaks devMode!
106: Map params = (Map) extraContext
107: .get(ActionContext.PARAMETERS);
108: params.remove(XWorkContinuationConfig.CONTINUE_PARAM);
109:
110: // and now put the key in the context to be picked up later by XWork
111: extraContext.put(XWorkContinuationConfig.CONTINUE_KEY,
112: id);
113: }
114:
115: ActionProxy proxy = ActionProxyFactory.getFactory()
116: .createActionProxy(namespace, name, extraContext,
117: true, false);
118: proxy.setMethod(method);
119: request.setAttribute(
120: ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy
121: .getInvocation().getStack());
122:
123: // if the ActionMapping says to go straight to a result, do it!
124: if (mapping.getResult() != null) {
125: Result result = mapping.getResult();
126: result.execute(proxy.getInvocation());
127: } else {
128: proxy.execute();
129: }
130:
131: // If there was a previous value stack then set it back onto the request
132: if (stack != null) {
133: request.setAttribute(
134: ServletActionContext.WEBWORK_VALUESTACK_KEY,
135: stack);
136: }
137: } catch (ConfigurationException e) {
138: LOG.error("Could not find action", e);
139: sendError(request, response, context,
140: HttpServletResponse.SC_NOT_FOUND, e);
141: } catch (Exception e) {
142: throw new ServletException(e);
143: }
144: }
145:
146: }
|