001: /*
002: * $Id: ServletDispatcherResult.java 471756 2006-11-06 15:01:43Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts2.dispatcher;
022:
023: import javax.servlet.RequestDispatcher;
024: import javax.servlet.http.HttpServletRequest;
025: import javax.servlet.http.HttpServletResponse;
026: import javax.servlet.jsp.PageContext;
027:
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.apache.struts2.ServletActionContext;
031:
032: import com.opensymphony.xwork2.ActionInvocation;
033:
034: /**
035: * <!-- START SNIPPET: description -->
036: *
037: * Includes or forwards to a view (usually a jsp). Behind the scenes Struts
038: * will use a RequestDispatcher, where the target servlet/JSP receives the same
039: * request/response objects as the original servlet/JSP. Therefore, you can pass
040: * data between them using request.setAttribute() - the Struts action is
041: * available.
042: * <p/>
043: * There are three possible ways the result can be executed:
044: *
045: * <ul>
046: *
047: * <li>If we are in the scope of a JSP (a PageContext is available), PageContext's
048: * {@link PageContext#include(String) include} method is called.</li>
049: *
050: * <li>If there is no PageContext and we're not in any sort of include (there is no
051: * "javax.servlet.include.servlet_path" in the request attributes), then a call to
052: * {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) forward}
053: * is made.</li>
054: *
055: * <li>Otherwise, {@link RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse) include}
056: * is called.</li>
057: *
058: * </ul>
059: * <!-- END SNIPPET: description -->
060: *
061: * <b>This result type takes the following parameters:</b>
062: *
063: * <!-- START SNIPPET: params -->
064: *
065: * <ul>
066: *
067: * <li><b>location (default)</b> - the location to go to after execution (ex. jsp).</li>
068: *
069: * <li><b>parse</b> - true by default. If set to false, the location param will not be parsed for Ognl expressions.</li>
070: *
071: * </ul>
072: *
073: * <!-- END SNIPPET: params -->
074: *
075: * <b>Example:</b>
076: *
077: * <pre><!-- START SNIPPET: example -->
078: * <result name="success" type="dispatcher">
079: * <param name="location">foo.jsp</param>
080: * </result>
081: * <!-- END SNIPPET: example --></pre>
082: *
083: * This result follows the same rules from {@link StrutsResultSupport}.
084: *
085: * @see javax.servlet.RequestDispatcher
086: */
087: public class ServletDispatcherResult extends StrutsResultSupport {
088:
089: private static final long serialVersionUID = -1970659272360685627L;
090:
091: private static final Log log = LogFactory
092: .getLog(ServletDispatcherResult.class);
093:
094: public ServletDispatcherResult() {
095: super ();
096: }
097:
098: public ServletDispatcherResult(String location) {
099: super (location);
100: }
101:
102: /**
103: * Dispatches to the given location. Does its forward via a RequestDispatcher. If the
104: * dispatch fails a 404 error will be sent back in the http response.
105: *
106: * @param finalLocation the location to dispatch to.
107: * @param invocation the execution state of the action
108: * @throws Exception if an error occurs. If the dispatch fails the error will go back via the
109: * HTTP request.
110: */
111: public void doExecute(String finalLocation,
112: ActionInvocation invocation) throws Exception {
113: if (log.isDebugEnabled()) {
114: log.debug("Forwarding to location " + finalLocation);
115: }
116:
117: PageContext pageContext = ServletActionContext.getPageContext();
118:
119: if (pageContext != null) {
120: pageContext.include(finalLocation);
121: } else {
122: HttpServletRequest request = ServletActionContext
123: .getRequest();
124: HttpServletResponse response = ServletActionContext
125: .getResponse();
126: RequestDispatcher dispatcher = request
127: .getRequestDispatcher(finalLocation);
128:
129: // if the view doesn't exist, let's do a 404
130: if (dispatcher == null) {
131: response.sendError(404, "result '" + finalLocation
132: + "' not found");
133:
134: return;
135: }
136:
137: // If we're included, then include the view
138: // Otherwise do forward
139: // This allow the page to, for example, set content type
140: if (!response.isCommitted()
141: && (request
142: .getAttribute("javax.servlet.include.servlet_path") == null)) {
143: request.setAttribute("struts.view_uri", finalLocation);
144: request.setAttribute("struts.request_uri", request
145: .getRequestURI());
146:
147: dispatcher.forward(request, response);
148: } else {
149: dispatcher.include(request, response);
150: }
151: }
152: }
153: }
|