View Javadoc

1   /*
2    * $Id: ServletDispatcherResult.java 454455 2006-10-09 18:49:38Z mrdon $
3    *
4    * Copyright 2006 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.struts2.dispatcher;
19  
20  import javax.servlet.RequestDispatcher;
21  import javax.servlet.http.HttpServletRequest;
22  import javax.servlet.http.HttpServletResponse;
23  import javax.servlet.jsp.PageContext;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.struts2.ServletActionContext;
28  
29  import com.opensymphony.xwork2.ActionInvocation;
30  
31  
32  /***
33   * <!-- START SNIPPET: description -->
34   *
35   * Includes or forwards to a view (usually a jsp). Behind the scenes Struts
36   * will use a RequestDispatcher, where the target servlet/JSP receives the same
37   * request/response objects as the original servlet/JSP. Therefore, you can pass
38   * data between them using request.setAttribute() - the Struts action is
39   * available.
40   * <p/>
41   * There are three possible ways the result can be executed:
42   *  
43   * <ul>
44   *
45   * <li>If we are in the scope of a JSP (a PageContext is available), PageContext's
46   * {@link PageContext#include(String) include} method is called.</li>
47   *
48   * <li>If there is no PageContext and we're not in any sort of include (there is no
49   * "javax.servlet.include.servlet_path" in the request attributes), then a call to
50   * {@link RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) forward}
51   * is made.</li>
52   * 
53   * <li>Otherwise, {@link RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse) include}
54   * is called.</li>
55   * 
56   * </ul>
57   * <!-- END SNIPPET: description -->
58   *
59   * <b>This result type takes the following parameters:</b>
60   *
61   * <!-- START SNIPPET: params -->
62   *
63   * <ul>
64   *
65   * <li><b>location (default)</b> - the location to go to after execution (ex. jsp).</li>
66   *
67   * <li><b>parse</b> - true by default. If set to false, the location param will not be parsed for Ognl expressions.</li>
68   *
69   * </ul>
70   *
71   * <!-- END SNIPPET: params -->
72   *
73   * <b>Example:</b>
74   *
75   * <pre><!-- START SNIPPET: example -->
76   * &lt;result name="success" type="dispatcher"&gt;
77   *   &lt;param name="location"&gt;foo.jsp&lt;/param&gt;
78   * &lt;/result&gt;
79   * <!-- END SNIPPET: example --></pre>
80   *
81   * This result follows the same rules from {@link StrutsResultSupport}.
82   *
83   * @see javax.servlet.RequestDispatcher
84   */
85  public class ServletDispatcherResult extends StrutsResultSupport {
86  
87  	private static final long serialVersionUID = -1970659272360685627L;
88  	
89  	private static final Log log = LogFactory.getLog(ServletDispatcherResult.class);
90  
91  	public ServletDispatcherResult() {
92  		super();
93  	}
94  	
95  	public ServletDispatcherResult(String location) {
96  		super(location);
97  	}
98  	
99      /***
100      * Dispatches to the given location. Does its forward via a RequestDispatcher. If the
101      * dispatch fails a 404 error will be sent back in the http response.
102      *
103      * @param finalLocation the location to dispatch to.
104      * @param invocation    the execution state of the action
105      * @throws Exception if an error occurs. If the dispatch fails the error will go back via the
106      *                   HTTP request.
107      */
108     public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
109         if (log.isDebugEnabled()) {
110             log.debug("Forwarding to location " + finalLocation);
111         }
112 
113         PageContext pageContext = ServletActionContext.getPageContext();
114 
115         if (pageContext != null) {
116             pageContext.include(finalLocation);
117         } else {
118             HttpServletRequest request = ServletActionContext.getRequest();
119             HttpServletResponse response = ServletActionContext.getResponse();
120             RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
121 
122             // if the view doesn't exist, let's do a 404
123             if (dispatcher == null) {
124                 response.sendError(404, "result '" + finalLocation + "' not found");
125 
126                 return;
127             }
128 
129             // If we're included, then include the view
130             // Otherwise do forward 
131             // This allow the page to, for example, set content type 
132             if (!response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) {
133                 request.setAttribute("struts.view_uri", finalLocation);
134                 request.setAttribute("struts.request_uri", request.getRequestURI());
135 
136                 dispatcher.forward(request, response);
137             } else {
138                 dispatcher.include(request, response);
139             }
140         }
141     }
142 }