1. /*
  2. * Copyright 2002-2004 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.util.Enumeration;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21. import javax.servlet.ServletContext;
  22. import javax.servlet.ServletRequest;
  23. import javax.servlet.http.Cookie;
  24. import javax.servlet.http.HttpServletRequest;
  25. import javax.servlet.http.HttpSession;
  26. import org.springframework.util.StringUtils;
  27. /**
  28. * Miscellaneous utilities for web applications.
  29. * Used by various framework classes.
  30. * @author Rod Johnson
  31. * @author Juergen Hoeller
  32. */
  33. public abstract class WebUtils {
  34. /**
  35. * Default character encoding to use when request.getCharacterEncoding
  36. * returns null, according to the Servlet spec.
  37. * @see ServletRequest#getCharacterEncoding
  38. */
  39. public static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1";
  40. /**
  41. * Standard Servlet spec context attribute that specifies a temporary
  42. * directory for the current web application, of type java.io.File
  43. */
  44. public static final String TEMP_DIR_CONTEXT_ATTRIBUTE = "javax.servlet.context.tempdir";
  45. /**
  46. * Web app root key parameter at the servlet context level
  47. * (i.e. web.xml): "webAppRootKey".
  48. */
  49. public static final String WEB_APP_ROOT_KEY_PARAM = "webAppRootKey";
  50. /** Default web app root key: "webapp.root" */
  51. public static final String DEFAULT_WEB_APP_ROOT_KEY = "webapp.root";
  52. /** Name suffixes in case of image buttons */
  53. public static final String[] SUBMIT_IMAGE_SUFFIXES = {".x", ".y"};
  54. /**
  55. * Set a system property to the web application root directory.
  56. * The key of the system property can be defined with the "webAppRootKey"
  57. * context-param in web.xml. Default is "webapp.root".
  58. * <p>Can be used for toolkits that support substition with System.getProperty
  59. * values, like Log4J's "${key}" syntax within log file locations.
  60. * @param servletContext the servlet context of the web application
  61. * @throws IllegalStateException if the system property is already set,
  62. * or if the WAR file is not expanded
  63. * @see #WEB_APP_ROOT_KEY_PARAM
  64. * @see #DEFAULT_WEB_APP_ROOT_KEY
  65. * @see WebAppRootListener
  66. * @see Log4jWebConfigurer
  67. */
  68. public static void setWebAppRootSystemProperty(ServletContext servletContext) throws IllegalStateException {
  69. String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);
  70. String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY);
  71. String oldValue = System.getProperty(key);
  72. String root = servletContext.getRealPath("/");
  73. if (root == null) {
  74. throw new IllegalStateException("Cannot set web app root system property when WAR file is not expanded");
  75. }
  76. if (oldValue != null && !StringUtils.pathEquals(oldValue, root)) {
  77. throw new IllegalStateException("Web app root system property already set to different value: '" +
  78. key + "' = [" + oldValue +
  79. "] instead of [" + root + "]- Choose unique webAppRootKey values in your web.xml files!");
  80. }
  81. System.setProperty(key, root);
  82. servletContext.log("Set web app root system property: " + key + " = " + root);
  83. }
  84. /**
  85. * Return the temporary directory for the current web application,
  86. * as provided by the servlet container.
  87. * @param servletContext the servlet context of the web application
  88. * @return the File representing the temporary directory
  89. */
  90. public static File getTempDir(ServletContext servletContext) {
  91. return (File) servletContext.getAttribute(TEMP_DIR_CONTEXT_ATTRIBUTE);
  92. }
  93. /**
  94. * Check the given request for a session attribute of the given name.
  95. * Returns null if there is no session or if the session has no such attribute.
  96. * Does not create a new session if none has existed before!
  97. * @param request current HTTP request
  98. * @param name the name of the session attribute
  99. * @return the value of the session attribute, or null if not found
  100. */
  101. public static Object getSessionAttribute(HttpServletRequest request, String name) {
  102. HttpSession session = request.getSession(false);
  103. return (session != null ? session.getAttribute(name) : null);
  104. }
  105. /**
  106. * Check the given request for a session attribute of the given name.
  107. * Throws an exception if there is no session or if the session has no such
  108. * attribute. Does not create a new session if none has existed before!
  109. * @param request current HTTP request
  110. * @param name the name of the session attribute
  111. * @return the value of the session attribute, or null if not found
  112. * @throws IllegalStateException if the session attribute could not be found
  113. */
  114. public static Object getRequiredSessionAttribute(HttpServletRequest request, String name)
  115. throws IllegalStateException {
  116. Object attr = getSessionAttribute(request, name);
  117. if (attr == null) {
  118. throw new IllegalStateException("No session attribute '" + name + "' found");
  119. }
  120. return attr;
  121. }
  122. /**
  123. * Set the session attribute with the given name to the given value.
  124. * Removes the session attribute if value is null, if a session existed at all.
  125. * Does not create a new session if not necessary!
  126. * @param request current HTTP request
  127. * @param name the name of the session attribute
  128. */
  129. public static void setSessionAttribute(HttpServletRequest request, String name, Object value) {
  130. if (value != null) {
  131. request.getSession().setAttribute(name, value);
  132. }
  133. else {
  134. HttpSession session = request.getSession(false);
  135. if (session != null) {
  136. session.removeAttribute(name);
  137. }
  138. }
  139. }
  140. /**
  141. * Get the specified session attribute, creating and setting a new attribute if
  142. * no existing found. The given class needs to have a public no-arg constructor.
  143. * Useful for on-demand state objects in a web tier, like shopping carts.
  144. * @param session current HTTP session
  145. * @param name the name of the session attribute
  146. * @param clazz the class to instantiate for a new attribute
  147. * @return the value of the session attribute, newly created if not found
  148. * @throws IllegalArgumentException if the session attribute could not be instantiated
  149. */
  150. public static Object getOrCreateSessionAttribute(HttpSession session, String name, Class clazz)
  151. throws IllegalArgumentException {
  152. Object sessionObject = session.getAttribute(name);
  153. if (sessionObject == null) {
  154. try {
  155. sessionObject = clazz.newInstance();
  156. }
  157. catch (InstantiationException ex) {
  158. throw new IllegalArgumentException("Could not instantiate class [" + clazz.getName() +
  159. "] for session attribute '" + name + "': " + ex.getMessage());
  160. }
  161. catch (IllegalAccessException ex) {
  162. throw new IllegalArgumentException("Could not access default constructor of class [" + clazz.getName() +
  163. "] for session attribute '" + name + "': " + ex.getMessage());
  164. }
  165. session.setAttribute(name, sessionObject);
  166. }
  167. return sessionObject;
  168. }
  169. /**
  170. * Retrieve the first cookie with the given name. Note that multiple
  171. * cookies can have the same name but different paths or domains.
  172. * @param name cookie name
  173. * @return the first cookie with the given name, or null if none is found
  174. */
  175. public static Cookie getCookie(HttpServletRequest request, String name) {
  176. Cookie cookies[] = request.getCookies();
  177. if (cookies != null) {
  178. for (int i = 0; i < cookies.length; i++) {
  179. if (name.equals(cookies[i].getName()))
  180. return cookies[i];
  181. }
  182. }
  183. return null;
  184. }
  185. /**
  186. * Convenience method to return a map from un-prefixed property names
  187. * to values. E.g. with a prefix of price, price_1, price_2 produce
  188. * a properties object with mappings for 1, 2 to the same values.
  189. * Maps single values to String and multiple values to String array.
  190. * @param request HTTP request in which to look for parameters
  191. * @param base beginning of parameter name
  192. * (if this is null or the empty string, all parameters will match)
  193. * @return map containing request parameters <b>without the prefix</b>,
  194. * containing either a String or a String[] as values
  195. */
  196. public static Map getParametersStartingWith(ServletRequest request, String base) {
  197. Enumeration enum = request.getParameterNames();
  198. Map params = new HashMap();
  199. if (base == null) {
  200. base = "";
  201. }
  202. while (enum != null && enum.hasMoreElements()) {
  203. String paramName = (String) enum.nextElement();
  204. if (base == null || "".equals(base) || paramName.startsWith(base)) {
  205. String unprefixed = paramName.substring(base.length());
  206. String[] values = request.getParameterValues(paramName);
  207. if (values == null) {
  208. // do nothing, no values found at all
  209. }
  210. else if (values.length > 1) {
  211. params.put(unprefixed, values);
  212. }
  213. else {
  214. params.put(unprefixed, values[0]);
  215. }
  216. }
  217. }
  218. return params;
  219. }
  220. /**
  221. * Checks if a specific input type="submit" parameter was sent in the request,
  222. * either via a button (directly with name) or via an image (name + ".x" or
  223. * name + ".y").
  224. * @param request current HTTP request
  225. * @param name name of the parameter
  226. * @return if the parameter was sent
  227. * @see #SUBMIT_IMAGE_SUFFIXES
  228. */
  229. public static boolean hasSubmitParameter(ServletRequest request, String name) {
  230. if (request.getParameter(name) != null) {
  231. return true;
  232. }
  233. for (int i = 0; i < SUBMIT_IMAGE_SUFFIXES.length; i++) {
  234. String suffix = SUBMIT_IMAGE_SUFFIXES[i];
  235. if (request.getParameter(name + suffix) != null) {
  236. return true;
  237. }
  238. }
  239. return false;
  240. }
  241. }