PageRenderTime 27ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/springframework-3.0.5/projects/org.springframework.web/src/main/java/org/springframework/web/util/WebUtils.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 681 lines | 304 code | 48 blank | 329 comment | 72 complexity | 22b76272f625fd0d58e1a7baa162625c MD5 | raw file
  1. /*
  2. * Copyright 2002-2009 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. package org.springframework.web.util;
  17. import java.io.File;
  18. import java.io.FileNotFoundException;
  19. import java.util.Enumeration;
  20. import java.util.Map;
  21. import java.util.TreeMap;
  22. import javax.servlet.ServletContext;
  23. import javax.servlet.ServletRequest;
  24. import javax.servlet.http.Cookie;
  25. import javax.servlet.http.HttpServletRequest;
  26. import javax.servlet.http.HttpServletResponse;
  27. import javax.servlet.http.HttpSession;
  28. import org.springframework.util.Assert;
  29. import org.springframework.util.StringUtils;
  30. /**
  31. * Miscellaneous utilities for web applications.
  32. * Used by various framework classes.
  33. *
  34. * @author Rod Johnson
  35. * @author Juergen Hoeller
  36. */
  37. public abstract class WebUtils {
  38. /**
  39. * Standard Servlet 2.3+ spec request attributes for include URI and paths.
  40. * <p>If included via a RequestDispatcher, the current resource will see the
  41. * originating request. Its own URI and paths are exposed as request attributes.
  42. */
  43. public static final String INCLUDE_REQUEST_URI_ATTRIBUTE = "javax.servlet.include.request_uri";
  44. public static final String INCLUDE_CONTEXT_PATH_ATTRIBUTE = "javax.servlet.include.context_path";
  45. public static final String INCLUDE_SERVLET_PATH_ATTRIBUTE = "javax.servlet.include.servlet_path";
  46. public static final String INCLUDE_PATH_INFO_ATTRIBUTE = "javax.servlet.include.path_info";
  47. public static final String INCLUDE_QUERY_STRING_ATTRIBUTE = "javax.servlet.include.query_string";
  48. /**
  49. * Standard Servlet 2.4+ spec request attributes for forward URI and paths.
  50. * <p>If forwarded to via a RequestDispatcher, the current resource will see its
  51. * own URI and paths. The originating URI and paths are exposed as request attributes.
  52. */
  53. public static final String FORWARD_REQUEST_URI_ATTRIBUTE = "javax.servlet.forward.request_uri";
  54. public static final String FORWARD_CONTEXT_PATH_ATTRIBUTE = "javax.servlet.forward.context_path";
  55. public static final String FORWARD_SERVLET_PATH_ATTRIBUTE = "javax.servlet.forward.servlet_path";
  56. public static final String FORWARD_PATH_INFO_ATTRIBUTE = "javax.servlet.forward.path_info";
  57. public static final String FORWARD_QUERY_STRING_ATTRIBUTE = "javax.servlet.forward.query_string";
  58. /**
  59. * Standard Servlet 2.3+ spec request attributes for error pages.
  60. * <p>To be exposed to JSPs that are marked as error pages, when forwarding
  61. * to them directly rather than through the servlet container's error page
  62. * resolution mechanism.
  63. */
  64. public static final String ERROR_STATUS_CODE_ATTRIBUTE = "javax.servlet.error.status_code";
  65. public static final String ERROR_EXCEPTION_TYPE_ATTRIBUTE = "javax.servlet.error.exception_type";
  66. public static final String ERROR_MESSAGE_ATTRIBUTE = "javax.servlet.error.message";
  67. public static final String ERROR_EXCEPTION_ATTRIBUTE = "javax.servlet.error.exception";
  68. public static final String ERROR_REQUEST_URI_ATTRIBUTE = "javax.servlet.error.request_uri";
  69. public static final String ERROR_SERVLET_NAME_ATTRIBUTE = "javax.servlet.error.servlet_name";
  70. /**
  71. * Prefix of the charset clause in a content type String: ";charset="
  72. */
  73. public static final String CONTENT_TYPE_CHARSET_PREFIX = ";charset=";
  74. /**
  75. * Default character encoding to use when <code>request.getCharacterEncoding</code>
  76. * returns <code>null</code>, according to the Servlet spec.
  77. * @see ServletRequest#getCharacterEncoding
  78. */
  79. public static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1";
  80. /**
  81. * Standard Servlet spec context attribute that specifies a temporary
  82. * directory for the current web application, of type <code>java.io.File</code>.
  83. */
  84. public static final String TEMP_DIR_CONTEXT_ATTRIBUTE = "javax.servlet.context.tempdir";
  85. /**
  86. * HTML escape parameter at the servlet context level
  87. * (i.e. a context-param in <code>web.xml</code>): "defaultHtmlEscape".
  88. */
  89. public static final String HTML_ESCAPE_CONTEXT_PARAM = "defaultHtmlEscape";
  90. /**
  91. * Web app root key parameter at the servlet context level
  92. * (i.e. a context-param in <code>web.xml</code>): "webAppRootKey".
  93. */
  94. public static final String WEB_APP_ROOT_KEY_PARAM = "webAppRootKey";
  95. /** Default web app root key: "webapp.root" */
  96. public static final String DEFAULT_WEB_APP_ROOT_KEY = "webapp.root";
  97. /** Name suffixes in case of image buttons */
  98. public static final String[] SUBMIT_IMAGE_SUFFIXES = {".x", ".y"};
  99. /** Key for the mutex session attribute */
  100. public static final String SESSION_MUTEX_ATTRIBUTE = WebUtils.class.getName() + ".MUTEX";
  101. /**
  102. * Set a system property to the web application root directory.
  103. * The key of the system property can be defined with the "webAppRootKey"
  104. * context-param in <code>web.xml</code>. Default is "webapp.root".
  105. * <p>Can be used for tools that support substition with <code>System.getProperty</code>
  106. * values, like log4j's "${key}" syntax within log file locations.
  107. * @param servletContext the servlet context of the web application
  108. * @throws IllegalStateException if the system property is already set,
  109. * or if the WAR file is not expanded
  110. * @see #WEB_APP_ROOT_KEY_PARAM
  111. * @see #DEFAULT_WEB_APP_ROOT_KEY
  112. * @see WebAppRootListener
  113. * @see Log4jWebConfigurer
  114. */
  115. public static void setWebAppRootSystemProperty(ServletContext servletContext) throws IllegalStateException {
  116. Assert.notNull(servletContext, "ServletContext must not be null");
  117. String root = servletContext.getRealPath("/");
  118. if (root == null) {
  119. throw new IllegalStateException(
  120. "Cannot set web app root system property when WAR file is not expanded");
  121. }
  122. String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);
  123. String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY);
  124. String oldValue = System.getProperty(key);
  125. if (oldValue != null && !StringUtils.pathEquals(oldValue, root)) {
  126. throw new IllegalStateException(
  127. "Web app root system property already set to different value: '" +
  128. key + "' = [" + oldValue + "] instead of [" + root + "] - " +
  129. "Choose unique values for the 'webAppRootKey' context-param in your web.xml files!");
  130. }
  131. System.setProperty(key, root);
  132. servletContext.log("Set web app root system property: '" + key + "' = [" + root + "]");
  133. }
  134. /**
  135. * Remove the system property that points to the web app root directory.
  136. * To be called on shutdown of the web application.
  137. * @param servletContext the servlet context of the web application
  138. * @see #setWebAppRootSystemProperty
  139. */
  140. public static void removeWebAppRootSystemProperty(ServletContext servletContext) {
  141. Assert.notNull(servletContext, "ServletContext must not be null");
  142. String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);
  143. String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY);
  144. System.getProperties().remove(key);
  145. }
  146. /**
  147. * Return whether default HTML escaping is enabled for the web application,
  148. * i.e. the value of the "defaultHtmlEscape" context-param in <code>web.xml</code>
  149. * (if any). Falls back to <code>false</code> in case of no explicit default given.
  150. * @param servletContext the servlet context of the web application
  151. * @return whether default HTML escaping is enabled (default is false)
  152. */
  153. public static boolean isDefaultHtmlEscape(ServletContext servletContext) {
  154. if (servletContext == null) {
  155. return false;
  156. }
  157. String param = servletContext.getInitParameter(HTML_ESCAPE_CONTEXT_PARAM);
  158. return Boolean.valueOf(param);
  159. }
  160. /**
  161. * Return whether default HTML escaping is enabled for the web application,
  162. * i.e. the value of the "defaultHtmlEscape" context-param in <code>web.xml</code>
  163. * (if any).
  164. * <p>This method differentiates between no param specified at all and
  165. * an actual boolean value specified, allowing to have a context-specific
  166. * default in case of no setting at the global level.
  167. * @param servletContext the servlet context of the web application
  168. * @return whether default HTML escaping is enabled (null = no explicit default)
  169. */
  170. public static Boolean getDefaultHtmlEscape(ServletContext servletContext) {
  171. if (servletContext == null) {
  172. return null;
  173. }
  174. Assert.notNull(servletContext, "ServletContext must not be null");
  175. String param = servletContext.getInitParameter(HTML_ESCAPE_CONTEXT_PARAM);
  176. return (StringUtils.hasText(param)? Boolean.valueOf(param) : null);
  177. }
  178. /**
  179. * Return the temporary directory for the current web application,
  180. * as provided by the servlet container.
  181. * @param servletContext the servlet context of the web application
  182. * @return the File representing the temporary directory
  183. */
  184. public static File getTempDir(ServletContext servletContext) {
  185. Assert.notNull(servletContext, "ServletContext must not be null");
  186. return (File) servletContext.getAttribute(TEMP_DIR_CONTEXT_ATTRIBUTE);
  187. }
  188. /**
  189. * Return the real path of the given path within the web application,
  190. * as provided by the servlet container.
  191. * <p>Prepends a slash if the path does not already start with a slash,
  192. * and throws a FileNotFoundException if the path cannot be resolved to
  193. * a resource (in contrast to ServletContext's <code>getRealPath</code>,
  194. * which returns null).
  195. * @param servletContext the servlet context of the web application
  196. * @param path the path within the web application
  197. * @return the corresponding real path
  198. * @throws FileNotFoundException if the path cannot be resolved to a resource
  199. * @see javax.servlet.ServletContext#getRealPath
  200. */
  201. public static String getRealPath(ServletContext servletContext, String path) throws FileNotFoundException {
  202. Assert.notNull(servletContext, "ServletContext must not be null");
  203. // Interpret location as relative to the web application root directory.
  204. if (!path.startsWith("/")) {
  205. path = "/" + path;
  206. }
  207. String realPath = servletContext.getRealPath(path);
  208. if (realPath == null) {
  209. throw new FileNotFoundException(
  210. "ServletContext resource [" + path + "] cannot be resolved to absolute file path - " +
  211. "web application archive not expanded?");
  212. }
  213. return realPath;
  214. }
  215. /**
  216. * Determine the session id of the given request, if any.
  217. * @param request current HTTP request
  218. * @return the session id, or <code>null</code> if none
  219. */
  220. public static String getSessionId(HttpServletRequest request) {
  221. Assert.notNull(request, "Request must not be null");
  222. HttpSession session = request.getSession(false);
  223. return (session != null ? session.getId() : null);
  224. }
  225. /**
  226. * Check the given request for a session attribute of the given name.
  227. * Returns null if there is no session or if the session has no such attribute.
  228. * Does not create a new session if none has existed before!
  229. * @param request current HTTP request
  230. * @param name the name of the session attribute
  231. * @return the value of the session attribute, or <code>null</code> if not found
  232. */
  233. public static Object getSessionAttribute(HttpServletRequest request, String name) {
  234. Assert.notNull(request, "Request must not be null");
  235. HttpSession session = request.getSession(false);
  236. return (session != null ? session.getAttribute(name) : null);
  237. }
  238. /**
  239. * Check the given request for a session attribute of the given name.
  240. * Throws an exception if there is no session or if the session has no such
  241. * attribute. Does not create a new session if none has existed before!
  242. * @param request current HTTP request
  243. * @param name the name of the session attribute
  244. * @return the value of the session attribute, or <code>null</code> if not found
  245. * @throws IllegalStateException if the session attribute could not be found
  246. */
  247. public static Object getRequiredSessionAttribute(HttpServletRequest request, String name)
  248. throws IllegalStateException {
  249. Object attr = getSessionAttribute(request, name);
  250. if (attr == null) {
  251. throw new IllegalStateException("No session attribute '" + name + "' found");
  252. }
  253. return attr;
  254. }
  255. /**
  256. * Set the session attribute with the given name to the given value.
  257. * Removes the session attribute if value is null, if a session existed at all.
  258. * Does not create a new session if not necessary!
  259. * @param request current HTTP request
  260. * @param name the name of the session attribute
  261. * @param value the value of the session attribute
  262. */
  263. public static void setSessionAttribute(HttpServletRequest request, String name, Object value) {
  264. Assert.notNull(request, "Request must not be null");
  265. if (value != null) {
  266. request.getSession().setAttribute(name, value);
  267. }
  268. else {
  269. HttpSession session = request.getSession(false);
  270. if (session != null) {
  271. session.removeAttribute(name);
  272. }
  273. }
  274. }
  275. /**
  276. * Get the specified session attribute, creating and setting a new attribute if
  277. * no existing found. The given class needs to have a public no-arg constructor.
  278. * Useful for on-demand state objects in a web tier, like shopping carts.
  279. * @param session current HTTP session
  280. * @param name the name of the session attribute
  281. * @param clazz the class to instantiate for a new attribute
  282. * @return the value of the session attribute, newly created if not found
  283. * @throws IllegalArgumentException if the session attribute could not be instantiated
  284. */
  285. public static Object getOrCreateSessionAttribute(HttpSession session, String name, Class clazz)
  286. throws IllegalArgumentException {
  287. Assert.notNull(session, "Session must not be null");
  288. Object sessionObject = session.getAttribute(name);
  289. if (sessionObject == null) {
  290. try {
  291. sessionObject = clazz.newInstance();
  292. }
  293. catch (InstantiationException ex) {
  294. throw new IllegalArgumentException(
  295. "Could not instantiate class [" + clazz.getName() +
  296. "] for session attribute '" + name + "': " + ex.getMessage());
  297. }
  298. catch (IllegalAccessException ex) {
  299. throw new IllegalArgumentException(
  300. "Could not access default constructor of class [" + clazz.getName() +
  301. "] for session attribute '" + name + "': " + ex.getMessage());
  302. }
  303. session.setAttribute(name, sessionObject);
  304. }
  305. return sessionObject;
  306. }
  307. /**
  308. * Return the best available mutex for the given session:
  309. * that is, an object to synchronize on for the given session.
  310. * <p>Returns the session mutex attribute if available; usually,
  311. * this means that the HttpSessionMutexListener needs to be defined
  312. * in <code>web.xml</code>. Falls back to the HttpSession itself
  313. * if no mutex attribute found.
  314. * <p>The session mutex is guaranteed to be the same object during
  315. * the entire lifetime of the session, available under the key defined
  316. * by the <code>SESSION_MUTEX_ATTRIBUTE</code> constant. It serves as a
  317. * safe reference to synchronize on for locking on the current session.
  318. * <p>In many cases, the HttpSession reference itself is a safe mutex
  319. * as well, since it will always be the same object reference for the
  320. * same active logical session. However, this is not guaranteed across
  321. * different servlet containers; the only 100% safe way is a session mutex.
  322. * @param session the HttpSession to find a mutex for
  323. * @return the mutex object (never <code>null</code>)
  324. * @see #SESSION_MUTEX_ATTRIBUTE
  325. * @see HttpSessionMutexListener
  326. */
  327. public static Object getSessionMutex(HttpSession session) {
  328. Assert.notNull(session, "Session must not be null");
  329. Object mutex = session.getAttribute(SESSION_MUTEX_ATTRIBUTE);
  330. if (mutex == null) {
  331. mutex = session;
  332. }
  333. return mutex;
  334. }
  335. /**
  336. * Determine whether the given request is an include request,
  337. * that is, not a top-level HTTP request coming in from the outside.
  338. * <p>Checks the presence of the "javax.servlet.include.request_uri"
  339. * request attribute. Could check any request attribute that is only
  340. * present in an include request.
  341. * @param request current servlet request
  342. * @return whether the given request is an include request
  343. */
  344. public static boolean isIncludeRequest(ServletRequest request) {
  345. return (request.getAttribute(INCLUDE_REQUEST_URI_ATTRIBUTE) != null);
  346. }
  347. /**
  348. * Expose the current request URI and paths as {@link javax.servlet.http.HttpServletRequest}
  349. * attributes under the keys defined in the Servlet 2.4 specification,
  350. * for containers that implement 2.3 or an earlier version of the Servlet API:
  351. * <code>javax.servlet.forward.request_uri</code>,
  352. * <code>javax.servlet.forward.context_path</code>,
  353. * <code>javax.servlet.forward.servlet_path</code>,
  354. * <code>javax.servlet.forward.path_info</code>,
  355. * <code>javax.servlet.forward.query_string</code>.
  356. * <p>Does not override values if already present, to not cause conflicts
  357. * with the attributes exposed by Servlet 2.4+ containers themselves.
  358. * @param request current servlet request
  359. */
  360. public static void exposeForwardRequestAttributes(HttpServletRequest request) {
  361. exposeRequestAttributeIfNotPresent(request, FORWARD_REQUEST_URI_ATTRIBUTE, request.getRequestURI());
  362. exposeRequestAttributeIfNotPresent(request, FORWARD_CONTEXT_PATH_ATTRIBUTE, request.getContextPath());
  363. exposeRequestAttributeIfNotPresent(request, FORWARD_SERVLET_PATH_ATTRIBUTE, request.getServletPath());
  364. exposeRequestAttributeIfNotPresent(request, FORWARD_PATH_INFO_ATTRIBUTE, request.getPathInfo());
  365. exposeRequestAttributeIfNotPresent(request, FORWARD_QUERY_STRING_ATTRIBUTE, request.getQueryString());
  366. }
  367. /**
  368. * Expose the Servlet spec's error attributes as {@link javax.servlet.http.HttpServletRequest}
  369. * attributes under the keys defined in the Servlet 2.3 specification, for error pages that
  370. * are rendered directly rather than through the Servlet container's error page resolution:
  371. * <code>javax.servlet.error.status_code</code>,
  372. * <code>javax.servlet.error.exception_type</code>,
  373. * <code>javax.servlet.error.message</code>,
  374. * <code>javax.servlet.error.exception</code>,
  375. * <code>javax.servlet.error.request_uri</code>,
  376. * <code>javax.servlet.error.servlet_name</code>.
  377. * <p>Does not override values if already present, to respect attribute values
  378. * that have been exposed explicitly before.
  379. * <p>Exposes status code 200 by default. Set the "javax.servlet.error.status_code"
  380. * attribute explicitly (before or after) in order to expose a different status code.
  381. * @param request current servlet request
  382. * @param ex the exception encountered
  383. * @param servletName the name of the offending servlet
  384. */
  385. public static void exposeErrorRequestAttributes(HttpServletRequest request, Throwable ex, String servletName) {
  386. exposeRequestAttributeIfNotPresent(request, ERROR_STATUS_CODE_ATTRIBUTE, HttpServletResponse.SC_OK);
  387. exposeRequestAttributeIfNotPresent(request, ERROR_EXCEPTION_TYPE_ATTRIBUTE, ex.getClass());
  388. exposeRequestAttributeIfNotPresent(request, ERROR_MESSAGE_ATTRIBUTE, ex.getMessage());
  389. exposeRequestAttributeIfNotPresent(request, ERROR_EXCEPTION_ATTRIBUTE, ex);
  390. exposeRequestAttributeIfNotPresent(request, ERROR_REQUEST_URI_ATTRIBUTE, request.getRequestURI());
  391. exposeRequestAttributeIfNotPresent(request, ERROR_SERVLET_NAME_ATTRIBUTE, servletName);
  392. }
  393. /**
  394. * Expose the specified request attribute if not already present.
  395. * @param request current servlet request
  396. * @param name the name of the attribute
  397. * @param value the suggested value of the attribute
  398. */
  399. private static void exposeRequestAttributeIfNotPresent(ServletRequest request, String name, Object value) {
  400. if (request.getAttribute(name) == null) {
  401. request.setAttribute(name, value);
  402. }
  403. }
  404. /**
  405. * Clear the Servlet spec's error attributes as {@link javax.servlet.http.HttpServletRequest}
  406. * attributes under the keys defined in the Servlet 2.3 specification:
  407. * <code>javax.servlet.error.status_code</code>,
  408. * <code>javax.servlet.error.exception_type</code>,
  409. * <code>javax.servlet.error.message</code>,
  410. * <code>javax.servlet.error.exception</code>,
  411. * <code>javax.servlet.error.request_uri</code>,
  412. * <code>javax.servlet.error.servlet_name</code>.
  413. * @param request current servlet request
  414. */
  415. public static void clearErrorRequestAttributes(HttpServletRequest request) {
  416. request.removeAttribute(ERROR_STATUS_CODE_ATTRIBUTE);
  417. request.removeAttribute(ERROR_EXCEPTION_TYPE_ATTRIBUTE);
  418. request.removeAttribute(ERROR_MESSAGE_ATTRIBUTE);
  419. request.removeAttribute(ERROR_EXCEPTION_ATTRIBUTE);
  420. request.removeAttribute(ERROR_REQUEST_URI_ATTRIBUTE);
  421. request.removeAttribute(ERROR_SERVLET_NAME_ATTRIBUTE);
  422. }
  423. /**
  424. * Expose the given Map as request attributes, using the keys as attribute names
  425. * and the values as corresponding attribute values. Keys need to be Strings.
  426. * @param request current HTTP request
  427. * @param attributes the attributes Map
  428. */
  429. public static void exposeRequestAttributes(ServletRequest request, Map<String, ?> attributes) {
  430. Assert.notNull(request, "Request must not be null");
  431. Assert.notNull(attributes, "Attributes Map must not be null");
  432. for (Map.Entry<String, ?> entry : attributes.entrySet()) {
  433. request.setAttribute(entry.getKey(), entry.getValue());
  434. }
  435. }
  436. /**
  437. * Retrieve the first cookie with the given name. Note that multiple
  438. * cookies can have the same name but different paths or domains.
  439. * @param request current servlet request
  440. * @param name cookie name
  441. * @return the first cookie with the given name, or <code>null</code> if none is found
  442. */
  443. public static Cookie getCookie(HttpServletRequest request, String name) {
  444. Assert.notNull(request, "Request must not be null");
  445. Cookie cookies[] = request.getCookies();
  446. if (cookies != null) {
  447. for (Cookie cookie : cookies) {
  448. if (name.equals(cookie.getName())) {
  449. return cookie;
  450. }
  451. }
  452. }
  453. return null;
  454. }
  455. /**
  456. * Check if a specific input type="submit" parameter was sent in the request,
  457. * either via a button (directly with name) or via an image (name + ".x" or
  458. * name + ".y").
  459. * @param request current HTTP request
  460. * @param name name of the parameter
  461. * @return if the parameter was sent
  462. * @see #SUBMIT_IMAGE_SUFFIXES
  463. */
  464. public static boolean hasSubmitParameter(ServletRequest request, String name) {
  465. Assert.notNull(request, "Request must not be null");
  466. if (request.getParameter(name) != null) {
  467. return true;
  468. }
  469. for (String suffix : SUBMIT_IMAGE_SUFFIXES) {
  470. if (request.getParameter(name + suffix) != null) {
  471. return true;
  472. }
  473. }
  474. return false;
  475. }
  476. /**
  477. * Obtain a named parameter from the given request parameters.
  478. * <p>See {@link #findParameterValue(java.util.Map, String)}
  479. * for a description of the lookup algorithm.
  480. * @param request current HTTP request
  481. * @param name the <i>logical</i> name of the request parameter
  482. * @return the value of the parameter, or <code>null</code>
  483. * if the parameter does not exist in given request
  484. */
  485. @SuppressWarnings("unchecked")
  486. public static String findParameterValue(ServletRequest request, String name) {
  487. return findParameterValue(request.getParameterMap(), name);
  488. }
  489. /**
  490. * Obtain a named parameter from the given request parameters.
  491. * <p>This method will try to obtain a parameter value using the
  492. * following algorithm:
  493. * <ol>
  494. * <li>Try to get the parameter value using just the given <i>logical</i> name.
  495. * This handles parameters of the form <tt>logicalName = value</tt>. For normal
  496. * parameters, e.g. submitted using a hidden HTML form field, this will return
  497. * the requested value.</li>
  498. * <li>Try to obtain the parameter value from the parameter name, where the
  499. * parameter name in the request is of the form <tt>logicalName_value = xyz</tt>
  500. * with "_" being the configured delimiter. This deals with parameter values
  501. * submitted using an HTML form submit button.</li>
  502. * <li>If the value obtained in the previous step has a ".x" or ".y" suffix,
  503. * remove that. This handles cases where the value was submitted using an
  504. * HTML form image button. In this case the parameter in the request would
  505. * actually be of the form <tt>logicalName_value.x = 123</tt>. </li>
  506. * </ol>
  507. * @param parameters the available parameter map
  508. * @param name the <i>logical</i> name of the request parameter
  509. * @return the value of the parameter, or <code>null</code>
  510. * if the parameter does not exist in given request
  511. */
  512. public static String findParameterValue(Map<String, ?> parameters, String name) {
  513. // First try to get it as a normal name=value parameter
  514. Object value = parameters.get(name);
  515. if (value instanceof String[]) {
  516. String[] values = (String[]) value;
  517. return (values.length > 0 ? values[0] : null);
  518. }
  519. else if (value != null) {
  520. return value.toString();
  521. }
  522. // If no value yet, try to get it as a name_value=xyz parameter
  523. String prefix = name + "_";
  524. for (String paramName : parameters.keySet()) {
  525. if (paramName.startsWith(prefix)) {
  526. // Support images buttons, which would submit parameters as name_value.x=123
  527. for (String suffix : SUBMIT_IMAGE_SUFFIXES) {
  528. if (paramName.endsWith(suffix)) {
  529. return paramName.substring(prefix.length(), paramName.length() - suffix.length());
  530. }
  531. }
  532. return paramName.substring(prefix.length());
  533. }
  534. }
  535. // We couldn't find the parameter value...
  536. return null;
  537. }
  538. /**
  539. * Return a map containing all parameters with the given prefix.
  540. * Maps single values to String and multiple values to String array.
  541. * <p>For example, with a prefix of "spring_", "spring_param1" and
  542. * "spring_param2" result in a Map with "param1" and "param2" as keys.
  543. * @param request HTTP request in which to look for parameters
  544. * @param prefix the beginning of parameter names
  545. * (if this is null or the empty string, all parameters will match)
  546. * @return map containing request parameters <b>without the prefix</b>,
  547. * containing either a String or a String array as values
  548. * @see javax.servlet.ServletRequest#getParameterNames
  549. * @see javax.servlet.ServletRequest#getParameterValues
  550. * @see javax.servlet.ServletRequest#getParameterMap
  551. */
  552. public static Map<String, Object> getParametersStartingWith(ServletRequest request, String prefix) {
  553. Assert.notNull(request, "Request must not be null");
  554. Enumeration paramNames = request.getParameterNames();
  555. Map<String, Object> params = new TreeMap<String, Object>();
  556. if (prefix == null) {
  557. prefix = "";
  558. }
  559. while (paramNames != null && paramNames.hasMoreElements()) {
  560. String paramName = (String) paramNames.nextElement();
  561. if ("".equals(prefix) || paramName.startsWith(prefix)) {
  562. String unprefixed = paramName.substring(prefix.length());
  563. String[] values = request.getParameterValues(paramName);
  564. if (values == null || values.length == 0) {
  565. // Do nothing, no values found at all.
  566. }
  567. else if (values.length > 1) {
  568. params.put(unprefixed, values);
  569. }
  570. else {
  571. params.put(unprefixed, values[0]);
  572. }
  573. }
  574. }
  575. return params;
  576. }
  577. /**
  578. * Return the target page specified in the request.
  579. * @param request current servlet request
  580. * @param paramPrefix the parameter prefix to check for
  581. * (e.g. "_target" for parameters like "_target1" or "_target2")
  582. * @param currentPage the current page, to be returned as fallback
  583. * if no target page specified
  584. * @return the page specified in the request, or current page if not found
  585. */
  586. public static int getTargetPage(ServletRequest request, String paramPrefix, int currentPage) {
  587. Enumeration paramNames = request.getParameterNames();
  588. while (paramNames.hasMoreElements()) {
  589. String paramName = (String) paramNames.nextElement();
  590. if (paramName.startsWith(paramPrefix)) {
  591. for (int i = 0; i < WebUtils.SUBMIT_IMAGE_SUFFIXES.length; i++) {
  592. String suffix = WebUtils.SUBMIT_IMAGE_SUFFIXES[i];
  593. if (paramName.endsWith(suffix)) {
  594. paramName = paramName.substring(0, paramName.length() - suffix.length());
  595. }
  596. }
  597. return Integer.parseInt(paramName.substring(paramPrefix.length()));
  598. }
  599. }
  600. return currentPage;
  601. }
  602. /**
  603. * Extract the URL filename from the given request URL path.
  604. * Correctly resolves nested paths such as "/products/view.html" as well.
  605. * @param urlPath the request URL path (e.g. "/index.html")
  606. * @return the extracted URI filename (e.g. "index")
  607. */
  608. public static String extractFilenameFromUrlPath(String urlPath) {
  609. String filename = extractFullFilenameFromUrlPath(urlPath);
  610. int dotIndex = filename.lastIndexOf('.');
  611. if (dotIndex != -1) {
  612. filename = filename.substring(0, dotIndex);
  613. }
  614. return filename;
  615. }
  616. /**
  617. * Extract the full URL filename (including file extension) from the given request URL path.
  618. * Correctly resolves nested paths such as "/products/view.html" as well.
  619. * @param urlPath the request URL path (e.g. "/products/index.html")
  620. * @return the extracted URI filename (e.g. "index.html")
  621. */
  622. public static String extractFullFilenameFromUrlPath(String urlPath) {
  623. int end = urlPath.indexOf(';');
  624. if (end == -1) {
  625. end = urlPath.indexOf('?');
  626. if (end == -1) {
  627. end = urlPath.length();
  628. }
  629. }
  630. int begin = urlPath.lastIndexOf('/', end) + 1;
  631. return urlPath.substring(begin, end);
  632. }
  633. }