KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > web > util > UrlPathHelper


1 /*
2  * Copyright 2002-2006 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.util;
18
19 import java.io.UnsupportedEncodingException JavaDoc;
20 import java.net.URLDecoder JavaDoc;
21
22 import javax.servlet.http.HttpServletRequest JavaDoc;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 import org.springframework.core.JdkVersion;
28 import org.springframework.util.StringUtils;
29
30 /**
31  * Helper class for URL path matching. Provides support for URL paths in
32  * RequestDispatcher includes and support for consistent URL decoding.
33  *
34  * <p>Used by AbstractUrlHandlerMapping, AbstractUrlMethodNameResolver
35  * and RequestContext for path matching and/or URI determination.
36  *
37  * @author Juergen Hoeller
38  * @author Rob Harrop
39  * @since 14.01.2004
40  * @see org.springframework.web.servlet.handler.AbstractUrlHandlerMapping
41  * @see org.springframework.web.servlet.mvc.multiaction.AbstractUrlMethodNameResolver
42  * @see org.springframework.web.servlet.support.RequestContext
43  */

44 public class UrlPathHelper {
45
46     /**
47      * @deprecated as of Spring 2.0, in favor of <code>WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE</code>
48      * @see org.springframework.web.util.WebUtils#INCLUDE_REQUEST_URI_ATTRIBUTE
49      */

50     public static final String JavaDoc INCLUDE_URI_REQUEST_ATTRIBUTE = WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE;
51
52     /**
53      * @deprecated as of Spring 2.0, in favor of <code>WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE</code>
54      * @see org.springframework.web.util.WebUtils#INCLUDE_CONTEXT_PATH_ATTRIBUTE
55      */

56     public static final String JavaDoc INCLUDE_CONTEXT_PATH_REQUEST_ATTRIBUTE = WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE;
57
58     /**
59      * @deprecated as of Spring 2.0, in favor of <code>WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE</code>
60      * @see org.springframework.web.util.WebUtils#INCLUDE_SERVLET_PATH_ATTRIBUTE
61      */

62     public static final String JavaDoc INCLUDE_SERVLET_PATH_REQUEST_ATTRIBUTE = WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE;
63
64
65     private final Log logger = LogFactory.getLog(getClass());
66
67     private boolean alwaysUseFullPath = false;
68
69     private boolean urlDecode = false;
70
71     private String JavaDoc defaultEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING;
72
73
74     /**
75      * Set if URL lookup should always use full path within current servlet
76      * context. Else, the path within the current servlet mapping is used
77      * if applicable (i.e. in the case of a ".../*" servlet mapping in web.xml).
78      * Default is "false".
79      */

80     public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
81         this.alwaysUseFullPath = alwaysUseFullPath;
82     }
83
84     /**
85      * Set if context path and request URI should be URL-decoded.
86      * Both are returned <i>undecoded</i> by the Servlet API,
87      * in contrast to the servlet path.
88      * <p>Uses either the request encoding or the default encoding according
89      * to the Servlet spec (ISO-8859-1).
90      * <p>Note: Setting this to "true" requires JDK 1.4 if the encoding differs
91      * from the VM's platform default encoding, as JDK 1.3's URLDecoder class
92      * does not offer a way to specify the encoding.
93      * @see #getServletPath
94      * @see #getContextPath
95      * @see #getRequestUri
96      * @see WebUtils#DEFAULT_CHARACTER_ENCODING
97      * @see javax.servlet.ServletRequest#getCharacterEncoding
98      * @see java.net.URLDecoder#decode(String, String)
99      * @see java.net.URLDecoder#decode(String)
100      */

101     public void setUrlDecode(boolean urlDecode) {
102         this.urlDecode = urlDecode;
103     }
104
105     /**
106      * Set the default character encoding to use for URL decoding.
107      * Default is ISO-8859-1, according to the Servlet spec.
108      * <p>If the request specifies a character encoding itself, the request
109      * encoding will override this setting. This also allows for generically
110      * overriding the character encoding in a filter that invokes the
111      * ServletRequest.setCharacterEncoding method.
112      * @param defaultEncoding the character encoding to use
113      * @see #determineEncoding
114      * @see javax.servlet.ServletRequest#getCharacterEncoding
115      * @see javax.servlet.ServletRequest#setCharacterEncoding
116      * @see WebUtils#DEFAULT_CHARACTER_ENCODING
117      */

118     public void setDefaultEncoding(String JavaDoc defaultEncoding) {
119         this.defaultEncoding = defaultEncoding;
120     }
121
122     /**
123      * Return the default character encoding to use for URL decoding.
124      */

125     protected String JavaDoc getDefaultEncoding() {
126         return defaultEncoding;
127     }
128
129
130     /**
131      * Return the mapping lookup path for the given request, within the current
132      * servlet mapping if applicable, else within the web application.
133      * <p>Regards include request URL if called within a RequestDispatcher include.
134      * @param request current HTTP request
135      * @return the lookup path
136      * @see #getPathWithinApplication
137      * @see #getPathWithinServletMapping
138      */

139     public String JavaDoc getLookupPathForRequest(HttpServletRequest JavaDoc request) {
140         // Always use full path within current servlet context?
141
if (this.alwaysUseFullPath) {
142             return getPathWithinApplication(request);
143         }
144         // Else, use path within current servlet mapping if applicable
145
String JavaDoc rest = getPathWithinServletMapping(request);
146         if (!"".equals(rest)) {
147             return rest;
148         }
149         else {
150             return getPathWithinApplication(request);
151         }
152     }
153
154     /**
155      * Return the path within the servlet mapping for the given request,
156      * i.e. the part of the request's URL beyond the part that called the servlet,
157      * or "" if the whole URL has been used to identify the servlet.
158      * <p>Regards include request URL if called within a RequestDispatcher include.
159      * <p>E.g.: servlet mapping = "/test/*"; request URI = "/test/a" -> "/a".
160      * <p>E.g.: servlet mapping = "/test"; request URI = "/test" -> "".
161      * <p>E.g.: servlet mapping = "/*.test"; request URI = "/a.test" -> "".
162      * @param request current HTTP request
163      * @return the path within the servlet mapping, or ""
164      */

165     public String JavaDoc getPathWithinServletMapping(HttpServletRequest JavaDoc request) {
166         String JavaDoc pathWithinApp = getPathWithinApplication(request);
167         String JavaDoc servletPath = getServletPath(request);
168         if (pathWithinApp.startsWith(servletPath)) {
169             // Normal case: URI contains servlet path.
170
return pathWithinApp.substring(servletPath.length());
171         }
172         else {
173             // Special case: URI is different from servlet path.
174
// Can happen e.g. with index page: URI="/", servletPath="/index.html"
175
// Use servlet path in this case, as it indicates the actual target path.
176
return servletPath;
177         }
178     }
179
180     /**
181      * Return the path within the web application for the given request.
182      * <p>Regards include request URL if called within a RequestDispatcher include.
183      * @param request current HTTP request
184      * @return the path within the web application
185      */

186     public String JavaDoc getPathWithinApplication(HttpServletRequest JavaDoc request) {
187         String JavaDoc contextPath = getContextPath(request);
188         String JavaDoc requestUri = getRequestUri(request);
189         if (StringUtils.startsWithIgnoreCase(requestUri, contextPath)) {
190             // Normal case: URI contains context path.
191
String JavaDoc path = requestUri.substring(contextPath.length());
192             return (StringUtils.hasText(path) ? path : "/");
193         }
194         else {
195             // Special case: rather unusual.
196
return requestUri;
197         }
198     }
199
200
201     /**
202      * Return the request URI for the given request, detecting an include request
203      * URL if called within a RequestDispatcher include.
204      * <p>As the value returned by <code>request.getRequestURI()</code> is <i>not</i>
205      * decoded by the servlet container, this method will decode it.
206      * <p>The URI that the web container resolves <i>should</i> be correct, but some
207      * containers like JBoss/Jetty incorrectly include ";" strings like ";jsessionid"
208      * in the URI. This method cuts off such incorrect appendices.
209      * @param request current HTTP request
210      * @return the request URI
211      */

212     public String JavaDoc getRequestUri(HttpServletRequest JavaDoc request) {
213         String JavaDoc uri = (String JavaDoc) request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE);
214         if (uri == null) {
215             uri = request.getRequestURI();
216         }
217         return decodeAndCleanUriString(request, uri);
218     }
219
220     /**
221      * Return the context path for the given request, detecting an include request
222      * URL if called within a RequestDispatcher include.
223      * <p>As the value returned by <code>request.getContextPath()</code> is <i>not</i>
224      * decoded by the servlet container, this method will decode it.
225      * @param request current HTTP request
226      * @return the context path
227      */

228     public String JavaDoc getContextPath(HttpServletRequest JavaDoc request) {
229         String JavaDoc contextPath = (String JavaDoc) request.getAttribute(WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE);
230         if (contextPath == null) {
231             contextPath = request.getContextPath();
232         }
233         return decodeRequestString(request, contextPath);
234     }
235
236     /**
237      * Return the servlet path for the given request, regarding an include request
238      * URL if called within a RequestDispatcher include.
239      * <p>As the value returned by request.getServletPath() is already decoded by
240      * the servlet container, this method will not attempt to decode it.
241      * @param request current HTTP request
242      * @return the servlet path
243      */

244     public String JavaDoc getServletPath(HttpServletRequest JavaDoc request) {
245         String JavaDoc servletPath = (String JavaDoc) request.getAttribute(WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE);
246         if (servletPath == null) {
247             servletPath = request.getServletPath();
248         }
249         return servletPath;
250     }
251
252
253     /**
254      * Return the request URI for root of the given request. If this is a forwarded request,
255      * correctly resolves to the request URI of the original request. Relies on the Servlet
256      * 2.4 'forward' attributes. These attributes may be set by other components when
257      * running in a Servlet 2.3- environment.
258      */

259     public String JavaDoc getOriginatingRequestUri(HttpServletRequest JavaDoc request) {
260         String JavaDoc uri = (String JavaDoc) request.getAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE);
261         if (uri == null) {
262             uri = request.getRequestURI();
263         }
264         return decodeAndCleanUriString(request, uri);
265     }
266
267     /**
268      * Return the context path for the given request, detecting an include request
269      * URL if called within a RequestDispatcher include.
270      * <p>As the value returned by <code>request.getContextPath()</code> is <i>not</i>
271      * decoded by the servlet container, this method will decode it.
272      * @param request current HTTP request
273      * @return the context path
274      */

275     public String JavaDoc getOriginatingContextPath(HttpServletRequest JavaDoc request) {
276         String JavaDoc contextPath = (String JavaDoc) request.getAttribute(WebUtils.FORWARD_CONTEXT_PATH_ATTRIBUTE);
277         if (contextPath == null) {
278             contextPath = request.getContextPath();
279         }
280         return decodeRequestString(request, contextPath);
281     }
282
283     /**
284      * Return the request URI for root of the given request. If this is a forwarded request,
285      * correctly resolves to the request URI of the original request. Relies on the Servlet
286      * 2.4 'forward' attributes. These attributes may be set by other components when
287      * running in a Servlet 2.3- environment.
288      */

289     public String JavaDoc getOriginatingQueryString(HttpServletRequest JavaDoc request) {
290         String JavaDoc queryString = (String JavaDoc) request.getAttribute(WebUtils.FORWARD_QUERY_STRING_ATTRIBUTE);
291         if (queryString == null) {
292             queryString = request.getQueryString();
293         }
294         return queryString;
295     }
296
297
298     /**
299      * Decode the supplied URI string and strips any extraneous portion after a ';'.
300      */

301     private String JavaDoc decodeAndCleanUriString(HttpServletRequest JavaDoc request, String JavaDoc uri) {
302         uri = decodeRequestString(request, uri);
303         int semicolonIndex = uri.indexOf(';');
304         return (semicolonIndex != -1 ? uri.substring(0, semicolonIndex) : uri);
305     }
306
307     /**
308      * Decode the given source string with a URLDecoder. The encoding will be taken
309      * from the request, falling back to the default "ISO-8859-1".
310      * <p>Default implementation uses <code>URLDecoder.decode(input, enc)</code>
311      * on JDK 1.4+, falling back to <code>URLDecoder.decode(input)</code>
312      * (which uses the platform default encoding) on JDK 1.3.
313      * @param request current HTTP request
314      * @param source the String to decode
315      * @return the decoded String
316      * @see WebUtils#DEFAULT_CHARACTER_ENCODING
317      * @see javax.servlet.ServletRequest#getCharacterEncoding
318      * @see java.net.URLDecoder#decode(String, String)
319      * @see java.net.URLDecoder#decode(String)
320      */

321     public String JavaDoc decodeRequestString(HttpServletRequest JavaDoc request, String JavaDoc source) {
322         if (this.urlDecode) {
323             String JavaDoc enc = determineEncoding(request);
324             try {
325                 if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_14) {
326                     throw new UnsupportedEncodingException JavaDoc("JDK 1.3 URLDecoder does not support custom encoding");
327                 }
328                 return URLDecoder.decode(source, enc);
329             }
330             catch (UnsupportedEncodingException JavaDoc ex) {
331                 if (logger.isWarnEnabled()) {
332                     logger.warn("Could not decode request string [" + source + "] with encoding '" + enc +
333                             "': falling back to platform default encoding; exception message: " + ex.getMessage());
334                 }
335                 return URLDecoder.decode(source);
336             }
337         }
338         return source;
339     }
340
341     /**
342      * Determine the encoding for the given request.
343      * Can be overridden in subclasses.
344      * <p>The default implementation checks the request encoding,
345      * falling back to the default encoding specified for this resolver.
346      * @param request current HTTP request
347      * @return the encoding for the request (never <code>null</code>)
348      * @see javax.servlet.ServletRequest#getCharacterEncoding
349      * @see #setDefaultEncoding
350      */

351     protected String JavaDoc determineEncoding(HttpServletRequest JavaDoc request) {
352         String JavaDoc enc = request.getCharacterEncoding();
353         if (enc == null) {
354             enc = getDefaultEncoding();
355         }
356         return enc;
357     }
358
359 }
360
Popular Tags