KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > web > servlet > view > RedirectView


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.web.servlet.view;
18
19 import java.io.IOException JavaDoc;
20 import java.io.UnsupportedEncodingException JavaDoc;
21 import java.net.URLEncoder JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import javax.servlet.http.HttpServletRequest JavaDoc;
26 import javax.servlet.http.HttpServletResponse JavaDoc;
27
28 import org.springframework.core.JdkVersion;
29
30 /**
31  * <p>View that redirects to an absolute, context relative, or current request
32  * relative URL, exposing all model attributes as HTTP query parameters.
33  *
34  * <p>A URL for this view is supposed to be a HTTP redirect URL, i.e.
35  * suitable for HttpServletResponse's <code>sendRedirect</code> method, which
36  * is what actually does the redirect if the HTTP 1.0 flag is on, or via sending
37  * back an HTTP 303 code - if the HTTP 1.0 compatibility flag is off.
38  *
39  * <p>Note that while the default value for the "contextRelative" flag is off,
40  * you will probably want to almost always set it to true. With the flag off,
41  * URLs starting with "/" are considered relative to the web server root, while
42  * with the flag on, they are considered relative to the web application root.
43  * Since most web apps will never know or care what their context path actually
44  * is, they are much better off setting this flag to true, and submitting paths
45  * which are to be considered relative to the web application root.
46  *
47  * <p>Note that in a Servlet 2.2 environment, i.e. a servlet container which
48  * is only compliant to the limits of this spec, this class will probably fail
49  * when feeding in URLs which are not fully absolute, or relative to the current
50  * request (no leading "/"), as these are the only two types of URL that
51  * <code>sendRedirect</code> supports in a Servlet 2.2 environment.
52  *
53  * @author Rod Johnson
54  * @author Juergen Hoeller
55  * @author Colin Sampaleanu
56  * @see #setContextRelative
57  * @see #setHttp10Compatible
58  * @see javax.servlet.http.HttpServletResponse#sendRedirect
59  */

60 public class RedirectView extends AbstractUrlBasedView {
61
62     /** The default encoding scheme: UTF-8 */
63     public static final String JavaDoc DEFAULT_ENCODING_SCHEME = "UTF-8";
64
65
66     private boolean contextRelative = false;
67
68     private boolean http10Compatible = true;
69
70     private String JavaDoc encodingScheme = DEFAULT_ENCODING_SCHEME;
71
72
73     /**
74      * Constructor for use as a bean.
75      */

76     public RedirectView() {
77     }
78
79     /**
80      * Create a new RedirectView with the given URL.
81      * <p>The given URL will be considered as relative to the web server,
82      * not as relative to the current ServletContext.
83      * @param url the URL to redirect to
84      * @see #RedirectView(String, boolean)
85      */

86     public RedirectView(String JavaDoc url) {
87         super(url);
88     }
89
90     /**
91      * Create a new RedirectView with the given URL.
92      * @param url the URL to redirect to
93      * @param contextRelative whether to interpret the given URL as
94      * relative to the current ServletContext
95      */

96     public RedirectView(String JavaDoc url, boolean contextRelative) {
97         super(url);
98         this.contextRelative = contextRelative;
99     }
100
101     /**
102      * Create a new RedirectView with the given URL.
103      * @param url the URL to redirect to
104      * @param contextRelative whether to interpret the given URL as
105      * relative to the current ServletContext
106      * @param http10Compatible whether to stay compatible with HTTP 1.0 clients
107      */

108     public RedirectView(String JavaDoc url, boolean contextRelative, boolean http10Compatible) {
109         super(url);
110         this.contextRelative = contextRelative;
111         this.http10Compatible = http10Compatible;
112     }
113
114
115     /**
116      * Set whether to interpret a given URL that starts with a slash ("/")
117      * as relative to the current ServletContext, i.e. as relative to the
118      * web application root.
119      * <p>Default is "false": A URL that starts with a slash will be interpreted
120      * as absolute, i.e. taken as-is. If true, the context path will be
121      * prepended to the URL in such a case.
122      * @see javax.servlet.http.HttpServletRequest#getContextPath
123      */

124     public void setContextRelative(boolean contextRelative) {
125         this.contextRelative = contextRelative;
126     }
127
128     /**
129      * Set whether to stay compatible with HTTP 1.0 clients.
130      * <p>In the default implementation, this will enforce HTTP status code 302
131      * in any case, i.e. delegate to <code>HttpServletResponse.sendRedirect</code>.
132      * Turning this off will send HTTP status code 303, which is the correct
133      * code for HTTP 1.1 clients, but not understood by HTTP 1.0 clients.
134      * <p>Many HTTP 1.1 clients treat 302 just like 303, not making any
135      * difference. However, some clients depend on 303 when redirecting
136      * after a POST request; turn this flag off in such a scenario.
137      * @see javax.servlet.http.HttpServletResponse#sendRedirect
138      */

139     public void setHttp10Compatible(boolean http10Compatible) {
140         this.http10Compatible = http10Compatible;
141     }
142
143     /**
144      * Set the encoding scheme for this view. Default is UTF-8.
145      */

146     public void setEncodingScheme(String JavaDoc encodingScheme) {
147         this.encodingScheme = encodingScheme;
148     }
149
150
151     /**
152      * Convert model to request parameters and redirect to the given URL.
153      * @see #appendQueryProperties
154      * @see #sendRedirect
155      */

156     protected final void renderMergedOutputModel(
157             Map JavaDoc model, HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws IOException JavaDoc {
158
159         // Prepare target URL.
160
StringBuffer JavaDoc targetUrl = new StringBuffer JavaDoc();
161         if (this.contextRelative && getUrl().startsWith("/")) {
162             // Do not apply context path to relative URLs.
163
targetUrl.append(request.getContextPath());
164         }
165         targetUrl.append(getUrl());
166         appendQueryProperties(targetUrl, model, this.encodingScheme);
167
168         sendRedirect(request, response, targetUrl.toString(), this.http10Compatible);
169     }
170
171     /**
172      * Append query properties to the redirect URL.
173      * Stringifies, URL-encodes and formats model attributes as query properties.
174      * @param targetUrl the StringBuffer to append the properties to
175      * @param model Map that contains model attributes
176      * @param encodingScheme the encoding scheme to use
177      * @throws UnsupportedEncodingException if string encoding failed
178      * @see #queryProperties
179      */

180     protected void appendQueryProperties(StringBuffer JavaDoc targetUrl, Map JavaDoc model, String JavaDoc encodingScheme)
181             throws UnsupportedEncodingException JavaDoc {
182
183         // Extract anchor fragment, if any.
184
// The following code does not use JDK 1.4's StringBuffer.indexOf(String)
185
// method to retain JDK 1.3 compatibility.
186
String JavaDoc fragment = null;
187         int anchorIndex = targetUrl.toString().indexOf('#');
188         if (anchorIndex > -1) {
189             fragment = targetUrl.substring(anchorIndex);
190             targetUrl.delete(anchorIndex, targetUrl.length());
191         }
192
193         // If there aren't already some parameters, we need a "?".
194
boolean first = (getUrl().indexOf('?') < 0);
195         Iterator JavaDoc entries = queryProperties(model).entrySet().iterator();
196         while (entries.hasNext()) {
197             if (first) {
198                 targetUrl.append('?');
199                 first = false;
200             }
201             else {
202                 targetUrl.append('&');
203             }
204             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
205             String JavaDoc encodedKey = urlEncode(entry.getKey().toString(), encodingScheme);
206             String JavaDoc encodedValue =
207                     (entry.getValue() != null ? urlEncode(entry.getValue().toString(), encodingScheme) : "");
208             targetUrl.append(encodedKey).append('=').append(encodedValue);
209         }
210
211         // Append anchor fragment, if any, to end of URL.
212
if (fragment != null) {
213             targetUrl.append(fragment);
214         }
215     }
216
217     /**
218      * URL-encode the given input String with the given encoding scheme.
219      * <p>Default implementation uses <code>URLEncoder.encode(input, enc)</code>
220      * on JDK 1.4+, falling back to <code>URLEncoder.encode(input)</code>
221      * (which uses the platform default encoding) on JDK 1.3.
222      * @param input the unencoded input String
223      * @param encodingScheme the encoding scheme
224      * @return the encoded output String
225      * @throws UnsupportedEncodingException if thrown by the JDK URLEncoder
226      * @see java.net.URLEncoder#encode(String, String)
227      * @see java.net.URLEncoder#encode(String)
228      */

229     protected String JavaDoc urlEncode(String JavaDoc input, String JavaDoc encodingScheme) throws UnsupportedEncodingException JavaDoc {
230         if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_14) {
231             if (logger.isDebugEnabled()) {
232                 logger.debug("Only JDK 1.3 URLEncoder available: using platform default encoding " +
233                         "instead of the requested scheme '" + encodingScheme + "'");
234             }
235             return URLEncoder.encode(input);
236         }
237         return URLEncoder.encode(input, encodingScheme);
238     }
239
240     /**
241      * Determine name-value pairs for query strings, which will be stringified,
242      * URL-encoded and formatted by appendQueryProperties.
243      * <p>This implementation returns all model elements as-is.
244      * @see #appendQueryProperties
245      */

246     protected Map JavaDoc queryProperties(Map JavaDoc model) {
247         return model;
248     }
249
250     /**
251      * Send a redirect back to the HTTP client
252      * @param request current HTTP request (allows for reacting to request method)
253      * @param response current HTTP response (for sending response headers)
254      * @param targetUrl the target URL to redirect to
255      * @param http10Compatible whether to stay compatible with HTTP 1.0 clients
256      * @throws IOException if thrown by response methods
257      */

258     protected void sendRedirect(
259             HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, String JavaDoc targetUrl, boolean http10Compatible)
260             throws IOException JavaDoc {
261
262         if (http10Compatible) {
263             // Always send status code 302.
264
response.sendRedirect(response.encodeRedirectURL(targetUrl));
265         }
266         else {
267             // Correct HTTP status code is 303, in particular for POST requests.
268
response.setStatus(303);
269             response.setHeader("Location", response.encodeRedirectURL(targetUrl));
270         }
271     }
272
273 }
274
Popular Tags