KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > riotfamily > common > web > util > ServletUtils


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1
3  * The contents of this file are subject to the Mozilla Public License Version
4  * 1.1 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  * http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the
11  * License.
12  *
13  * The Original Code is Riot.
14  *
15  * The Initial Developer of the Original Code is
16  * Neteye GmbH.
17  * Portions created by the Initial Developer are Copyright (C) 2006
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  * Felix Gnass [fgnass at neteye dot de]
22  *
23  * ***** END LICENSE BLOCK ***** */

24 package org.riotfamily.common.web.util;
25
26 import java.net.URI JavaDoc;
27 import java.net.URISyntaxException JavaDoc;
28 import java.util.Enumeration JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Set JavaDoc;
34
35 import javax.servlet.ServletContext JavaDoc;
36 import javax.servlet.ServletRequest JavaDoc;
37 import javax.servlet.http.HttpServletRequest JavaDoc;
38 import javax.servlet.http.HttpServletResponse JavaDoc;
39
40 import org.riotfamily.common.util.FormatUtils;
41 import org.riotfamily.common.xml.DocumentReader;
42 import org.springframework.util.StringUtils;
43 import org.springframework.util.xml.DomUtils;
44 import org.springframework.web.context.support.ServletContextResource;
45 import org.springframework.web.util.UrlPathHelper;
46 import org.springframework.web.util.WebUtils;
47 import org.w3c.dom.Document JavaDoc;
48 import org.w3c.dom.Element JavaDoc;
49
50 public final class ServletUtils {
51
52     public static final String JavaDoc INCLUDE_URI_REQUEST_ATTRIBUTE =
53             "javax.servlet.include.request_uri";
54
55     private static final String JavaDoc PRAGMA_HEADER = "Pragma";
56
57     private static final String JavaDoc EXPIRES_HEADER = "Expires";
58
59     private static final String JavaDoc CACHE_CONTROL_HEADER = "Cache-Control";
60
61     public static final String JavaDoc REQUESTED_WITH_HEADER = "X-Requested-With";
62
63     public static final String JavaDoc XML_HTTP_REQUEST = "XMLHttpRequest";
64
65     public static final String JavaDoc SCHEME_HTTP = "http";
66
67     public static final String JavaDoc SCHEME_HTTPS = "https";
68
69     /** <p>Valid characters in a scheme.</p>
70      * <p>RFC 1738 says the following:</p>
71      * <blockquote>
72      * Scheme names consist of a sequence of characters. The lower
73      * case letters "a"--"z", digits, and the characters plus ("+"),
74      * period ("."), and hyphen ("-") are allowed. For resiliency,
75      * programs interpreting URLs should treat upper case letters as
76      * equivalent to lower case in scheme names (e.g., allow "HTTP" as
77      * well as "http").
78      * </blockquote>
79      * <p>We treat as absolute any URL that begins with such a scheme name,
80      * followed by a colon.</p>
81      */

82     public static final String JavaDoc VALID_SCHEME_CHARS =
83             "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-";
84
85     private static UrlPathHelper urlPathHelper = new UrlPathHelper();
86
87     private ServletUtils() {
88     }
89
90     public static String JavaDoc getOriginatingContextPath(HttpServletRequest JavaDoc request) {
91         return urlPathHelper.getOriginatingContextPath(request);
92     }
93
94     public static String JavaDoc getOriginatingRequestUri(HttpServletRequest JavaDoc request) {
95         return urlPathHelper.getOriginatingRequestUri(request);
96     }
97
98     public static String JavaDoc getOriginatingServletPath(HttpServletRequest JavaDoc request) {
99         String JavaDoc servletPath = (String JavaDoc) request.getAttribute(
100                 WebUtils.FORWARD_SERVLET_PATH_ATTRIBUTE);
101
102         if (servletPath == null) {
103             servletPath = request.getServletPath();
104         }
105         return servletPath;
106     }
107
108     /**
109      * Return the path within the web application for the given request.
110      * @see UrlPathHelper#getPathWithinApplication(HttpServletRequest)
111      */

112     public static String JavaDoc getPathWithinApplication(HttpServletRequest JavaDoc request) {
113         return urlPathHelper.getPathWithinApplication(request);
114     }
115
116     /**
117      * Return the path within the web application for the given request.
118      * @param request current HTTP request
119      * @return the path within the web application
120      */

121     public static String JavaDoc getOriginatingPathWithinApplication(HttpServletRequest JavaDoc request) {
122         String JavaDoc contextPath = getOriginatingContextPath(request);
123         String JavaDoc requestUri = getOriginatingRequestUri(request);
124         if (StringUtils.startsWithIgnoreCase(requestUri, contextPath)) {
125             // Normal case: URI contains context path.
126
String JavaDoc path = requestUri.substring(contextPath.length());
127             return (StringUtils.hasText(path) ? path : "/");
128         }
129         else {
130             // Special case: rather unusual.
131
return requestUri;
132         }
133     }
134
135     /**
136      * Return the path within the servlet mapping for the given request,
137      * i.e. the part of the request's URL beyond the part that called the servlet,
138      * or "" if the whole URL has been used to identify the servlet.
139      * <p>E.g.: servlet mapping = "/test/*"; request URI = "/test/a" -> "/a".
140      * <p>E.g.: servlet mapping = "/test"; request URI = "/test" -> "".
141      * <p>E.g.: servlet mapping = "/*.test"; request URI = "/a.test" -> "".
142      * @param request current HTTP request
143      * @return the path within the servlet mapping, or ""
144      */

145     public static String JavaDoc getOriginatingPathWithinServletMapping(HttpServletRequest JavaDoc request) {
146         String JavaDoc pathWithinApp = getOriginatingPathWithinApplication(request);
147         String JavaDoc servletPath = getOriginatingServletPath(request);
148         if (pathWithinApp.startsWith(servletPath)) {
149             // Normal case: URI contains servlet path.
150
return pathWithinApp.substring(servletPath.length());
151         }
152         else {
153             // Special case: URI is different from servlet path.
154
// Can happen e.g. with index page: URI="/", servletPath="/index.html"
155
// Use servlet path in this case, as it indicates the actual target path.
156
return servletPath;
157         }
158     }
159
160     /**
161      * Returns the lookup-path for a given request. This is either the path
162      * within the servlet-mapping (in case of a prefix mapping) or the path
163      * within the application without the trailing suffix (in case of a suffix
164      * mapping).
165      */

166     public static String JavaDoc getPathWithoutServletMapping(
167             HttpServletRequest JavaDoc request) {
168
169         String JavaDoc path = urlPathHelper.getPathWithinServletMapping(request);
170         if (path.length() == 0) {
171             path = urlPathHelper.getPathWithinApplication(request);
172             if (path.equals(getServletPrefix(request))) {
173                 return "/";
174             }
175             int dotIndex = path.lastIndexOf('.');
176             if (dotIndex != -1 && dotIndex > path.lastIndexOf('/')) {
177                 path = path.substring(0, dotIndex);
178             }
179         }
180         return path;
181     }
182
183     /**
184      * Returns the lookup-path for a given request. This is either the path
185      * within the servlet-mapping (in case of a prefix mapping) or the path
186      * within the application without the trailing suffix (in case of a suffix
187      * mapping).
188      */

189     public static String JavaDoc getOriginatingPathWithoutServletMapping(
190             HttpServletRequest JavaDoc request) {
191
192         String JavaDoc path = getOriginatingPathWithinServletMapping(request);
193         if (path.length() == 0) {
194             path = getOriginatingPathWithinApplication(request);
195             if (path.equals(getServletPrefix(request))) {
196                 return "/";
197             }
198             int dotIndex = path.lastIndexOf('.');
199             if (dotIndex >= 0) {
200                 path = path.substring(0, dotIndex);
201             }
202         }
203         return path;
204     }
205
206     /**
207      * Returns the servlet-mapping prefix for the given request or an empty
208      * String if the servlet is mapped by a suffix.
209      */

210     public static String JavaDoc getServletPrefix(HttpServletRequest JavaDoc request) {
211         String JavaDoc path = urlPathHelper.getPathWithinApplication(request);
212         String JavaDoc servletPath = urlPathHelper.getServletPath(request);
213         if (path.length() > servletPath.length()
214                 || (path.equals(servletPath) && path.indexOf('.') == -1)) {
215             
216             return servletPath;
217         }
218         return "";
219     }
220
221     /**
222      * Returns the servlet-mapping suffix for the given request or an empty
223      * String if the servlet is mapped by a prefix.
224      */

225     public static String JavaDoc getServletSuffix(HttpServletRequest JavaDoc request) {
226         String JavaDoc path = urlPathHelper.getPathWithinApplication(request);
227         if (path.equals(urlPathHelper.getServletPath(request))) {
228             int dotIndex = path.lastIndexOf('.');
229             if (dotIndex >= 0) {
230                 return path.substring(dotIndex);
231             }
232         }
233         return "";
234     }
235
236     /**
237      * Adds the mapping of the servlet that is mapped to the given request
238      * to the path.
239      */

240     public static String JavaDoc addServletMapping(String JavaDoc path,
241             HttpServletRequest JavaDoc request) {
242         
243         String JavaDoc suffix = getServletPrefix(request);
244         if (suffix.length() > 0) {
245             return path + suffix;
246         }
247         return getServletPrefix(request) + path;
248     }
249
250     /**
251      * Returns a String consisting of the context-path and the servlet-prefix
252      * for the given request. The String will always end with a slash.
253      */

254     public static String JavaDoc getRootPath(HttpServletRequest JavaDoc request) {
255         StringBuffer JavaDoc path = new StringBuffer JavaDoc();
256         path.append(getOriginatingContextPath(request));
257         path.append(getServletPrefix(request));
258         path.append('/');
259         return path.toString();
260     }
261
262     /**
263      * Returns <tt>true</tt> if our current URL is absolute,
264      * <tt>false</tt> otherwise.
265      */

266     public static boolean isAbsoluteUrl(String JavaDoc url) {
267         // a null URL is not absolute, by our definition
268
if (url == null) {
269             return false;
270         }
271         // do a fast, simple check first
272
int colonPos;
273         if ((colonPos = url.indexOf(":")) == -1) {
274             return false;
275         }
276         // if we DO have a colon, make sure that every character
277
// leading up to it is a valid scheme character
278
for (int i = 0; i < colonPos; i++) {
279             if (VALID_SCHEME_CHARS.indexOf(url.charAt(i)) == -1) {
280                 return false;
281             }
282         }
283         // if so, we've got an absolute url
284
return true;
285     }
286
287     /**
288      * @since 6.4
289      */

290     public static boolean isHttpUrl(String JavaDoc url) {
291         return isAbsoluteUrl(url) && url.startsWith("http");
292     }
293
294     public static String JavaDoc resolveUrl(String JavaDoc url, HttpServletRequest JavaDoc request) {
295         if (url == null || isAbsoluteUrl(url)) {
296             return url;
297         }
298         if (url.startsWith("/")) {
299             url = request.getContextPath() + url;
300         }
301         return url;
302     }
303
304     public static String JavaDoc resolveAndEncodeUrl(String JavaDoc url,
305             HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) {
306
307         if (url == null || isAbsoluteUrl(url)) {
308             return url;
309         }
310         url = resolveUrl(url, request);
311         return response.encodeURL(url);
312     }
313
314     public static String JavaDoc getIncludeUri(HttpServletRequest JavaDoc request) {
315         String JavaDoc uri = (String JavaDoc) request.getAttribute(
316                 INCLUDE_URI_REQUEST_ATTRIBUTE);
317
318         if (uri == null) {
319             uri = request.getRequestURI();
320         }
321         return uri;
322     }
323
324     public static Map JavaDoc takeAttributesSnapshot(HttpServletRequest JavaDoc request) {
325         Map JavaDoc snapshot = new HashMap JavaDoc();
326         Enumeration JavaDoc attrNames = request.getAttributeNames();
327         while (attrNames.hasMoreElements()) {
328             String JavaDoc attrName = (String JavaDoc) attrNames.nextElement();
329             snapshot.put(attrName, request.getAttribute(attrName));
330         }
331         return snapshot;
332     }
333
334     /**
335      * Restores request attributes from the given map.
336      */

337     public static void restoreAttributes(HttpServletRequest JavaDoc request,
338             Map JavaDoc attributesSnapshot) {
339
340         // Copy into separate Collection to avoid side upon removal
341
Set JavaDoc attrsToCheck = new HashSet JavaDoc();
342         Enumeration JavaDoc attrNames = request.getAttributeNames();
343         while (attrNames.hasMoreElements()) {
344             String JavaDoc attrName = (String JavaDoc) attrNames.nextElement();
345             attrsToCheck.add(attrName);
346         }
347
348         Iterator JavaDoc it = attrsToCheck.iterator();
349         while (it.hasNext()) {
350             String JavaDoc attrName = (String JavaDoc) it.next();
351             Object JavaDoc attrValue = attributesSnapshot.get(attrName);
352             if (attrValue != null) {
353                 request.setAttribute(attrName, attrValue);
354             }
355             else {
356                 request.removeAttribute(attrName);
357             }
358         }
359     }
360
361     /**
362      * Returns a map of request parameters. Unlike
363      * {@link ServletRequest#getParameterMap()} this method returns Strings
364      * instead of String arrays. When more than one parameter with the same
365      * name is present, only the first value is put into the map.
366      */

367     public static Map JavaDoc getSingularParameterMap(HttpServletRequest JavaDoc request) {
368         HashMap JavaDoc params = new HashMap JavaDoc();
369         Enumeration JavaDoc names = request.getParameterNames();
370         while (names.hasMoreElements()) {
371             String JavaDoc name = (String JavaDoc) names.nextElement();
372             params.put(name, request.getParameter(name));
373         }
374         return params;
375     }
376
377     /**
378      * Returns the path of the given URI. Uses {@link java.net.URI}
379      * internally to parse the given String.
380      *
381      * @throws IllegalArgumentException If the given string violates RFC 2396
382      */

383     public static String JavaDoc getPath(String JavaDoc uri) {
384         try {
385             return new URI JavaDoc(uri).getPath();
386         }
387         catch (URISyntaxException JavaDoc e) {
388             throw new IllegalArgumentException JavaDoc(e.getMessage());
389         }
390     }
391
392     /**
393      * Returns a StringBuffer containing an URL with the protocol, hostname
394      * and port (unless it's the protocol's default port) of the given request.
395      */

396     public static StringBuffer JavaDoc getAbsoluteUrlPrefix(HttpServletRequest JavaDoc request) {
397         StringBuffer JavaDoc url = new StringBuffer JavaDoc();
398         String JavaDoc scheme = request.getScheme();
399         int port = request.getServerPort();
400         if (port <= 0) {
401             port = 80;
402         }
403         url.append(scheme);
404         url.append("://");
405         url.append(request.getServerName());
406         if ((scheme.equals(SCHEME_HTTP) && port != 80)
407                 || (scheme.equals(SCHEME_HTTPS) && port != 443)) {
408
409             url.append(':');
410             url.append(port);
411         }
412         return url;
413     }
414
415     /**
416      * Returns whether the <code>X-Requested-With</code> header is set to
417      * <code>XMLHttpRequest</code> as done by prototype.js.
418      */

419     public static boolean isXmlHttpRequest(HttpServletRequest JavaDoc request) {
420         return XML_HTTP_REQUEST.equals(request.getHeader(REQUESTED_WITH_HEADER));
421     }
422
423     /**
424      * Sets Pragma, Expires and Cache-Control headers to prevent caching.
425      * @since 6.4
426      */

427     public static void setNoCacheHeaders(HttpServletResponse JavaDoc response) {
428         response.setHeader(PRAGMA_HEADER, "No-cache");
429         response.setDateHeader(EXPIRES_HEADER, 1L);
430         response.setHeader(CACHE_CONTROL_HEADER, "no-cache");
431         response.addHeader(CACHE_CONTROL_HEADER, "no-store");
432     }
433
434     /**
435      * Sets Expires and Cache-Control headers to allow caching for the given
436      * period.
437      * @see FormatUtils#parseMillis(String)
438      * @since 6.5
439      */

440     public static void setCacheHeaders(HttpServletResponse JavaDoc response, String JavaDoc period) {
441         long millis = FormatUtils.parseMillis(period);
442         response.setDateHeader(EXPIRES_HEADER, System.currentTimeMillis() + millis);
443         response.setHeader(CACHE_CONTROL_HEADER, "max-age=" + millis / 1000L);
444     }
445
446     /**
447      * Parses the web.xml deployment descriptor and returns the url-pattern
448      * for the given servlet-name, or <code>null</code> if no mapping is found.
449      * @since 6.4
450      */

451     public static String JavaDoc getServletMapping(String JavaDoc servletName,
452             ServletContext JavaDoc servletContext) {
453
454         DocumentReader reader = new DocumentReader(new ServletContextResource(
455                 servletContext, "/WEB-INF/web.xml"));
456
457         Document JavaDoc doc = reader.readDocument();
458         Iterator JavaDoc it = DomUtils.getChildElementsByTagName(
459                 doc.getDocumentElement(), "servlet-mapping").iterator();
460
461         while (it.hasNext()) {
462             Element JavaDoc e = (Element JavaDoc) it.next();
463             Element JavaDoc name = DomUtils.getChildElementByTagName(e, "servlet-name");
464             if (servletName.equals(DomUtils.getTextValue(name))) {
465                 return DomUtils.getTextValue(DomUtils.getChildElementByTagName(
466                         e, "url-pattern")).trim();
467             }
468         }
469         return null;
470     }
471
472     public static String JavaDoc addParameter(String JavaDoc url, String JavaDoc name, String JavaDoc value) {
473         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(url);
474         boolean first = url.indexOf('?') == -1;
475         sb.append(first ? '?' : '&');
476         sb.append(name).append('=').append(FormatUtils.uriEscape(value));
477         return sb.toString();
478     }
479
480     public static String JavaDoc getRequestUrlWithQueryString(
481             HttpServletRequest JavaDoc request) {
482
483         request.getRequestURI();
484         StringBuffer JavaDoc sb = request.getRequestURL();
485         String JavaDoc queryString = request.getQueryString();
486         if (queryString != null) {
487             sb.append('?').append(queryString);
488         }
489         return sb.toString();
490     }
491
492 }
493
Popular Tags