WebRequestContext.java
Upload User: gdxydsw
Upload Date: 2019-01-29
Package Size: 16721k
Code Size: 14k
Category:

Java Develop

Development Platform:

Java

  1. /*
  2.  * Copyright (c) JForum Team
  3.  * All rights reserved.
  4.  * 
  5.  * Redistribution and use in source and binary forms, 
  6.  * with or without modification, are permitted provided 
  7.  * that the following conditions are met:
  8.  * 
  9.  * 1) Redistributions of source code must retain the above 
  10.  * copyright notice, this list of conditions and the 
  11.  * following  disclaimer.
  12.  * 2)  Redistributions in binary form must reproduce the 
  13.  * above copyright notice, this list of conditions and 
  14.  * the following disclaimer in the documentation and/or 
  15.  * other materials provided with the distribution.
  16.  * 3) Neither the name of "Rafael Steil" nor 
  17.  * the names of its contributors may be used to endorse 
  18.  * or promote products derived from this software without 
  19.  * specific prior written permission.
  20.  * 
  21.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
  22.  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
  23.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
  24.  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  25.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  26.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
  27.  * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  29.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  30.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  31.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  32.  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  33.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
  34.  * IN CONTRACT, STRICT LIABILITY, OR TORT 
  35.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  36.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  37.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
  38.  * 
  39.  * This file creation date: Mar 16, 2003 / 1:31:30 AM
  40.  * The JForum Project
  41.  * http://www.jforum.net
  42.  */
  43. package net.jforum.context.web;
  44. import java.io.File;
  45. import java.io.IOException;
  46. import java.io.UnsupportedEncodingException;
  47. import java.util.ArrayList;
  48. import java.util.Enumeration;
  49. import java.util.HashMap;
  50. import java.util.Iterator;
  51. import java.util.List;
  52. import java.util.Map;
  53. import java.util.StringTokenizer;
  54. import javax.servlet.http.HttpServletRequest;
  55. import javax.servlet.http.HttpServletRequestWrapper;
  56. import net.jforum.UrlPattern;
  57. import net.jforum.UrlPatternCollection;
  58. import net.jforum.context.RequestContext;
  59. import net.jforum.context.SessionContext;
  60. import net.jforum.exceptions.MultipartHandlingException;
  61. import net.jforum.util.legacy.commons.fileupload.FileItem;
  62. import net.jforum.util.legacy.commons.fileupload.FileUploadException;
  63. import net.jforum.util.legacy.commons.fileupload.disk.DiskFileItemFactory;
  64. import net.jforum.util.legacy.commons.fileupload.servlet.ServletFileUpload;
  65. import net.jforum.util.legacy.commons.fileupload.servlet.ServletRequestContext;
  66. import net.jforum.util.preferences.ConfigKeys;
  67. import net.jforum.util.preferences.SystemGlobals;
  68. import org.apache.commons.lang.StringUtils;
  69. /**
  70.  * @author Rafael Steil
  71.  * @version $Id: WebRequestContext.java,v 1.14 2007/09/25 23:38:48 rafaelsteil Exp $
  72.  */
  73. public class WebRequestContext extends HttpServletRequestWrapper implements RequestContext
  74. {
  75. private Map query;
  76. /**
  77.  * Default constructor.
  78.  * 
  79.  * @param superRequest Original <code>HttpServletRequest</code> instance
  80.  * @throws IOException
  81.  */
  82. public WebRequestContext(HttpServletRequest superRequest) throws IOException
  83. {
  84. super(superRequest);
  85. this.query = new HashMap();
  86. boolean isMultipart = false;
  87. String requestType = superRequest.getMethod().toUpperCase();
  88. String contextPath = superRequest.getContextPath();
  89. String requestUri = this.extractRequestUri(superRequest.getRequestURI(), contextPath);
  90. String encoding = SystemGlobals.getValue(ConfigKeys.ENCODING);
  91. String servletExtension = SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION);
  92. boolean isPost = "POST".equals(requestType);
  93. boolean isGet = !isPost;
  94. boolean isQueryStringEmpty = (superRequest.getQueryString() == null 
  95. || superRequest.getQueryString().length() == 0);
  96. if (isGet && isQueryStringEmpty && requestUri.endsWith(servletExtension)) {
  97. superRequest.setCharacterEncoding(encoding); 
  98. this.parseFriendlyURL(requestUri, servletExtension);
  99. }
  100. else if (isPost) {
  101. isMultipart = ServletFileUpload.isMultipartContent(new ServletRequestContext(superRequest));
  102. if (isMultipart) {
  103.     this.handleMultipart(superRequest, encoding);
  104. }
  105. }
  106. if (!isMultipart) {
  107. boolean isAjax = "XMLHttpRequest".equals(superRequest.getHeader("X-Requested-With"));
  108. if (!isAjax) {
  109. superRequest.setCharacterEncoding(encoding);
  110. }
  111. else {
  112. // Ajax requests are *usually* sent using application/x-www-form-urlencoded; charset=UTF-8.
  113. // In JForum, we assume this as always true.
  114. superRequest.setCharacterEncoding("UTF-8");
  115. }
  116. String containerEncoding = SystemGlobals.getValue(ConfigKeys.DEFAULT_CONTAINER_ENCODING);
  117. if (isPost) { 
  118. containerEncoding = encoding;
  119. }
  120. for (Enumeration e = superRequest.getParameterNames(); e.hasMoreElements(); ) {
  121. String name = (String)e.nextElement();
  122. String[] values = superRequest.getParameterValues(name);
  123. if (values != null && values.length > 1) {
  124. for (int i = 0; i < values.length; i++) {
  125. this.addParameter(name, new String(values[i].getBytes(containerEncoding), encoding));
  126. }
  127. }
  128. else {
  129. this.addParameter(name, new String(superRequest.getParameter(name).getBytes(containerEncoding), encoding));
  130. }
  131. }
  132. if (this.getModule() == null && this.getAction() == null) {
  133. int index = requestUri.indexOf('?');
  134. if (index > -1) {
  135. requestUri = requestUri.substring(0, index);
  136. }
  137. this.parseFriendlyURL(requestUri, servletExtension);
  138. }
  139. }
  140. }
  141. /**
  142.  * @param requestUri
  143.  * @param servletExtension
  144.  */
  145. private void parseFriendlyURL(String requestUri, String servletExtension) 
  146. {
  147. requestUri = requestUri.substring(0, requestUri.length() - servletExtension.length());
  148. String[] urlModel = requestUri.split("/");
  149. int moduleIndex = 1;
  150. int actionIndex = 2;
  151. int baseLen = 3;
  152. UrlPattern url = null;
  153. if (urlModel.length >= baseLen) {
  154. // <moduleName>.<actionName>.<numberOfParameters>
  155. StringBuffer sb = new StringBuffer(64)
  156. .append(urlModel[moduleIndex])
  157. .append('.')
  158. .append(urlModel[actionIndex])
  159. .append('.')
  160. .append(urlModel.length - baseLen);
  161. url = UrlPatternCollection.findPattern(sb.toString());
  162. }
  163. if (url != null) {
  164. if (url.getSize() >= urlModel.length - baseLen) {
  165. for (int i = 0; i < url.getSize(); i++) {
  166. this.addParameter(url.getVars()[i], urlModel[i + baseLen]);
  167. }
  168. }
  169. this.addParameter("module", urlModel[moduleIndex]);
  170. this.addParameter("action", urlModel[actionIndex]);
  171. }
  172. else {
  173. this.addParameter("module", null);
  174. this.addParameter("action", null);
  175. }
  176. }
  177.     public SessionContext getSessionContext(boolean create) {
  178.         return new WebSessionContext(this.getSession(true));
  179.     }
  180.     public SessionContext getSessionContext() {
  181.         return new WebSessionContext(this.getSession());
  182.     }
  183.     /**
  184.  * @param superRequest HttpServletRequest
  185.  * @param encoding String
  186.  * @throws UnsupportedEncodingException
  187.  */
  188. private void handleMultipart(HttpServletRequest superRequest, String encoding) throws UnsupportedEncodingException
  189. {
  190. String tmpPath = new StringBuffer(256)
  191.     .append(SystemGlobals.getApplicationPath())
  192.     .append('/')
  193.     .append(SystemGlobals.getValue(ConfigKeys.TMP_DIR))
  194.     .toString();
  195. File tmpDir = new File(tmpPath);
  196. boolean success = false;
  197. try {
  198. if (!tmpDir.exists()) {
  199. tmpDir.mkdirs();
  200. success = true;
  201. }
  202. }
  203. catch (Exception e) {
  204. // We won't log it because the directory
  205. // creation failed for some reason - a SecurityException
  206. // or something else. We don't care about it, as the
  207. // code below tries to use java.io.tmpdir
  208. }
  209. if (!success) {
  210. tmpPath = System.getProperty("java.io.tmpdir");
  211. tmpDir = new File(tmpPath);
  212. }
  213. ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory(100 * 1024, tmpDir));
  214. upload.setHeaderEncoding(encoding);
  215. try {
  216. List items = upload.parseRequest(superRequest);
  217. for (Iterator iter = items.iterator(); iter.hasNext(); ) {
  218. FileItem item = (FileItem)iter.next();
  219. if (item.isFormField()) {
  220. this.addParameter(item.getFieldName(), item.getString(encoding));
  221. }
  222. else {
  223. if (item.getSize() > 0) {
  224. // We really don't want to call addParameter(), as 
  225. // there should not be possible to have multiple
  226. // values for a InputStream data
  227. this.query.put(item.getFieldName(), item);
  228. }
  229. }
  230. }
  231. }
  232. catch (FileUploadException e) {
  233. throw new MultipartHandlingException("Error while processing multipart content: " + e);
  234. }
  235. }
  236. /**
  237.  * @see javax.servlet.ServletRequestWrapper#getParameterValues(java.lang.String)
  238.  */
  239. public String[] getParameterValues(String name) 
  240. {
  241. Object value = this.getObjectParameter(name);
  242. if (value instanceof String) {
  243. return new String[] { (String)value };
  244. }
  245. List l = (List)value;
  246. return l == null
  247. ? super.getParameterValues(name)
  248. : (String[])l.toArray(new String[0]);
  249. }
  250. private String extractRequestUri(String requestUri, String contextPath)
  251. {
  252. // First, remove the context path from the requestUri, 
  253. // so we can work only with the important stuff
  254. if (contextPath != null && contextPath.length() > 0) {
  255. requestUri = requestUri.substring(contextPath.length(), requestUri.length());
  256. }
  257. // Remove the "jsessionid" (or similar) from the URI
  258. // Probably this is not the right way to go, since we're
  259. // discarding the value...
  260. int index = requestUri.indexOf(';');
  261. if (index > -1) {
  262. int lastIndex = requestUri.indexOf('?', index);
  263. if (lastIndex == -1) {
  264. lastIndex = requestUri.indexOf('&', index);
  265. }
  266. if (lastIndex == -1) {
  267. requestUri = requestUri.substring(0, index);
  268. }
  269. else {
  270. String part1 = requestUri.substring(0, index);
  271. requestUri = part1 + requestUri.substring(lastIndex);
  272. }
  273. }
  274. return requestUri;
  275. }
  276. /**
  277.  * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
  278.  */
  279. public String getParameter(String parameter) 
  280. {
  281. return (String)this.query.get(parameter);
  282. }
  283. /**
  284.  * Gets an parameter that is a number.
  285.  * A call to <code>Integer#parseInt(String)</code> is made
  286.  * to do the conversion
  287.  * @param parameter The parameter name to get the value
  288.  * @return int
  289.  */
  290. public int getIntParameter(String parameter)
  291. {
  292. return Integer.parseInt(this.getParameter(parameter));
  293. }
  294. /**
  295.  * Gets some request parameter as <code>Object</code>.
  296.  * This method may be used when you have to get some value
  297.  * of a <i>multipart/form-data</i> request, like a image
  298.  * of file. <br>
  299.  * 
  300.  * @param parameter String
  301.  * @return Object
  302.  */
  303. public Object getObjectParameter(String parameter)
  304. {
  305. return this.query.get(parameter);
  306. }
  307. public void addParameter(String name, Object value)
  308. {
  309. if (!this.query.containsKey(name)) {
  310. this.query.put(name, value);
  311. }
  312. else {
  313. Object currentValue = this.getObjectParameter(name);
  314. List l;
  315. if (!(currentValue instanceof List)) {
  316. l = new ArrayList();
  317. l.add(currentValue);
  318. }
  319. else {
  320. l = (List)currentValue;
  321. }
  322. l.add(value);
  323. this.query.put(name, l);
  324. }
  325. }
  326. public void addOrReplaceParameter(String name, Object value)
  327. {
  328. this.query.put(name, value);
  329. }
  330. /**
  331.  * Gets the <i>action</i> of the current request.
  332.  * 
  333.  * An <i>Action</i> is the parameter name which specifies
  334.  * what next action should be done by the system. It may be
  335.  * add or edit a post, editing the groups, whatever. In the URL, the
  336.  * Action can the represented in two forms:
  337.  * <p>
  338.  * <blockquote>
  339.  * <code>
  340.  * http://www.host.com/webapp/servletName?module=groups&action=list
  341.  * </code>
  342.  * </blockquote>
  343.  * <p>
  344.  * or
  345.  * <p>
  346.  * <blockquote>
  347.  * <code>
  348.  * http://www.host.com/webapp/servletName/groups/list
  349.  * </code>
  350.  * </blockquote>
  351.  * <p>
  352.  * In both situations, the action's name is "list".
  353.  * 
  354.  * @return String representing the action name
  355.  */
  356. public String getAction()
  357. {
  358. return this.getParameter("action");
  359. }
  360. public void changeAction(String newAction)
  361. {
  362. if (this.query.containsKey("action")) {
  363. this.query.remove("action");
  364. this.query.put("action", newAction);
  365. }
  366. else {
  367. this.addParameter("action", newAction);
  368. }
  369. }
  370. /**
  371.  * Gets the <i>module</i> of the current request.
  372.  * 
  373.  * A <i>Module</i> is the parameter name which specifies
  374.  * what module the user is requesting. It may be the group
  375.  * administration, the topics or anything else configured module.
  376.  *In the URL, the Module can the represented in two forms:
  377.  * <p>
  378.  * <blockquote>
  379.  * <code>
  380.  * http://www.host.com/webapp/servletName?module=groups&action=list
  381.  * </code>
  382.  * </blockquote>
  383.  * <p>
  384.  * or
  385.  * <p>
  386.  * <blockquote>
  387.  * <code>
  388.  * http://www.host.com/webapp/servletName/groups/list
  389.  * </code>
  390.  * </blockquote>
  391.  * <p>
  392.  * In both situations, the module's name is "groups".
  393.  * 
  394.  * @return String representing the module name
  395.  */
  396. public String getModule()
  397. {
  398. return this.getParameter("module");
  399. }
  400. public Object getObjectRequestParameter(String parameter)
  401. {
  402. return this.query.get(parameter);
  403. }
  404. /**
  405.  * @see javax.servlet.http.HttpServletRequestWrapper#getContextPath()
  406.  */
  407. public String getContextPath() 
  408. {
  409. String contextPath = super.getContextPath();
  410. String proxiedContextPath = SystemGlobals.getValue(ConfigKeys.PROXIED_CONTEXT_PATH);
  411. if (!StringUtils.isEmpty(proxiedContextPath)) {
  412. contextPath = proxiedContextPath;
  413. }
  414. return contextPath;
  415. }
  416. /**
  417.  * @see javax.servlet.ServletRequestWrapper#getRemoteAddr()
  418.  */
  419. public String getRemoteAddr()
  420. {
  421. // We look if the request is forwarded
  422. // If it is not call the older function.
  423.         String ip = super.getHeader("x-forwarded-for");
  424.         
  425.         if (ip == null) {
  426.          ip = super.getRemoteAddr();
  427.         }
  428.         else {
  429.          // Process the IP to keep the last IP (real ip of the computer on the net)
  430.             StringTokenizer tokenizer = new StringTokenizer(ip, ",");
  431.             // Ignore all tokens, except the last one
  432.             for (int i = 0; i < tokenizer.countTokens() -1 ; i++) {
  433.              tokenizer.nextElement();
  434.             }
  435.             
  436.             ip = tokenizer.nextToken().trim();
  437.             
  438.             if (ip.equals("")) {
  439.              ip = null;
  440.             }
  441.         }
  442.         
  443.         // If the ip is still null, we put 0.0.0.0 to avoid null values
  444.         if (ip == null) {
  445.          ip = "0.0.0.0";
  446.         }
  447.         
  448.         return ip;
  449. }
  450. }