1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.dispatcher;
23
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26 import static javax.servlet.http.HttpServletResponse.*;
27
28 import org.apache.struts2.ServletActionContext;
29 import org.apache.struts2.dispatcher.mapper.ActionMapper;
30 import org.apache.struts2.dispatcher.mapper.ActionMapping;
31
32 import com.opensymphony.xwork2.ActionContext;
33 import com.opensymphony.xwork2.ActionInvocation;
34 import com.opensymphony.xwork2.inject.Inject;
35 import com.opensymphony.xwork2.util.logging.Logger;
36 import com.opensymphony.xwork2.util.logging.LoggerFactory;
37
38 import java.io.IOException;
39
40
41 /***
42 * <!-- START SNIPPET: description -->
43 *
44 * Calls the {@link HttpServletResponse#sendRedirect(String) sendRedirect}
45 * method to the location specified. The response is told to redirect the
46 * browser to the specified location (a new request from the client). The
47 * consequence of doing this means that the action (action instance, action
48 * errors, field errors, etc) that was just executed is lost and no longer
49 * available. This is because actions are built on a single-thread model. The
50 * only way to pass data is through the session or with web parameters
51 * (url?name=value) which can be OGNL expressions.
52 *
53 * <!-- END SNIPPET: description -->
54 * <p/>
55 * <b>This result type takes the following parameters:</b>
56 *
57 * <!-- START SNIPPET: params -->
58 *
59 * <ul>
60 *
61 * <li><b>location (default)</b> - the location to go to after execution.</li>
62 *
63 * <li><b>parse</b> - true by default. If set to false, the location param will
64 * not be parsed for Ognl expressions.</li>
65 *
66 * </ul>
67 *
68 * <p>
69 * This result follows the same rules from {@link StrutsResultSupport}.
70 * </p>
71 *
72 * <!-- END SNIPPET: params -->
73 *
74 * <b>Example:</b>
75 *
76 * <pre><!-- START SNIPPET: example -->
77 * <result name="success" type="redirect">
78 * <param name="location">foo.jsp</param>
79 * <param name="parse">false</param>
80 * </result>
81 * <!-- END SNIPPET: example --></pre>
82 *
83 */
84 public class ServletRedirectResult extends StrutsResultSupport {
85
86 private static final long serialVersionUID = 6316947346435301270L;
87
88 private static final Logger LOG = LoggerFactory.getLogger(ServletRedirectResult.class);
89
90 protected boolean prependServletContext = true;
91
92 protected ActionMapper actionMapper;
93
94 protected int statusCode = SC_FOUND;
95
96 public ServletRedirectResult() {
97 super();
98 }
99
100 public ServletRedirectResult(String location) {
101 super(location);
102 }
103
104 @Inject
105 public void setActionMapper(ActionMapper mapper) {
106 this.actionMapper = mapper;
107 }
108
109 public void setStatusCode(int code) {
110 this.statusCode = code;
111 }
112
113 /***
114 * Sets whether or not to prepend the servlet context path to the redirected URL.
115 *
116 * @param prependServletContext <tt>true</tt> to prepend the location with the servlet context path,
117 * <tt>false</tt> otherwise.
118 */
119 public void setPrependServletContext(boolean prependServletContext) {
120 this.prependServletContext = prependServletContext;
121 }
122
123 /***
124 * Redirects to the location specified by calling {@link HttpServletResponse#sendRedirect(String)}.
125 *
126 * @param finalLocation the location to redirect to.
127 * @param invocation an encapsulation of the action execution state.
128 * @throws Exception if an error occurs when redirecting.
129 */
130 protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
131 ActionContext ctx = invocation.getInvocationContext();
132 HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
133 HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
134
135 if (isPathUrl(finalLocation)) {
136 if (!finalLocation.startsWith("/")) {
137 ActionMapping mapping = actionMapper.getMapping(
138 request, Dispatcher.getInstance().getConfigurationManager());
139 String namespace = null;
140 if (mapping != null) {
141 namespace = mapping.getNamespace();
142 }
143
144 if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
145 finalLocation = namespace + "/" + finalLocation;
146 } else {
147 finalLocation = "/" + finalLocation;
148 }
149 }
150
151
152 if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
153 finalLocation = request.getContextPath() + finalLocation;
154 }
155
156 finalLocation = response.encodeRedirectURL(finalLocation);
157 }
158
159 if (LOG.isDebugEnabled()) {
160 LOG.debug("Redirecting to finalLocation " + finalLocation);
161 }
162
163 sendRedirect(response, finalLocation);
164 }
165
166 /***
167 * Sends the redirection. Can be overridden to customize how the redirect is handled (i.e. to use a different
168 * status code)
169 *
170 * @param response The response
171 * @param finalLocation The location URI
172 * @throws IOException
173 */
174 protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException {
175 if (SC_FOUND == statusCode) {
176 response.sendRedirect(finalLocation);
177 } else {
178 response.setStatus(statusCode);
179 response.setHeader("Location", finalLocation);
180 response.getWriter().write(finalLocation);
181 response.getWriter().close();
182 }
183
184 }
185
186 private static boolean isPathUrl(String url) {
187
188
189
190 return (url.indexOf(':') == -1);
191 }
192 }