Java tutorial
/********************************************************************************** * $URL: https://source.sakaiproject.org/contrib/etudes/sakai-jforum/tags/2.9.11/jforum-tool/src/java/org/etudes/jforum/ActionServletRequest.java $ * $Id: ActionServletRequest.java 83559 2013-04-30 19:03:29Z murthy@etudes.org $ *********************************************************************************** * * Copyright (c) 2008 Etudes, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Portions completed before July 1, 2004 Copyright (c) 2003, 2004 Rafael Steil, All rights reserved, licensed under the BSD license. * http://www.opensource.org/licenses/bsd-license.php * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * 2) Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of "Rafael Steil" nor * the names of its contributors may be used to endorse * or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE ***********************************************************************************/ package org.etudes.jforum; import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.etudes.jforum.exceptions.InvalidURLPatternException; import org.etudes.jforum.exceptions.MultipartHandlingException; import org.etudes.jforum.util.legacy.commons.fileupload.FileItem; import org.etudes.jforum.util.legacy.commons.fileupload.FileUploadException; import org.etudes.jforum.util.legacy.commons.fileupload.disk.DiskFileItemFactory; import org.etudes.jforum.util.legacy.commons.fileupload.servlet.ServletFileUpload; import org.etudes.jforum.util.legacy.commons.fileupload.servlet.ServletRequestContext; import org.etudes.jforum.util.preferences.ConfigKeys; import org.etudes.jforum.util.preferences.SakaiSystemGlobals; import org.etudes.jforum.util.preferences.SystemGlobals; /** * @author Rafael Steil * 11/15/06 - Murthy - updated for multipart request to capture mutiple values for * controls like select etc */ public class ActionServletRequest extends HttpServletRequestWrapper { private static final Log logger = LogFactory.getLog(ActionServletRequest.class); /** * URL Patterns keeper. * Represents a single URL pattern. Each pattern is composed * by a name, the pattern itself, the pattern's size and the * splited variables. <br><br> * * The pattern is expected in the form <i>var1, var2, varN</i>, in the * correct order. This means that if <i>var1</i> comes first, it <b>must</b> * come first in the URL. The same is valid to others.<br><br> * * Please note that "first" here is "first" after regular URL, which is * composed by server and servlet name, in the most simple case.<br><br> * * <b>Example:</b><br> * * URL: <i>http://localhost:8080/webappName/someDir/myServlet/news/view/3.page<i>. * <br> * In this case, <i>http://localhost:8080/webappName/someDir/myServlet/</i> is the * regular URL, the part that we don't care about. We only want the part * <i>news/view/3.page</i> ( where .page is the servlet extension ). * <br>For this URL, we could make the following pattern:<br><br> * * <i>news.view.1 = news_id</i><br><br> * * Here, <i>news.view.1</i> is the pattern's name, and <i>news_id</i> is * the patterns itself. <br> * Another example:<br><br> * * <i>news.view.2 = page, news_id</i><br><br> * * In this case we have a new var called <i>page</i>, that represents the page being seen.<br> * Each entry is composed in the form:<br><br> * * <i><moduleName>.<actionName>.<numberOfParameters> = <var 1>,<var n></i> * <br><br> * * Please note that module and action's name aren't pattern's composition, so * don't put them there. The system will consider that the pattern only contains * the variables diferent to each request ( e.g, id's ). If the pattern you're * constructing doesn't have any variable, just leave it blank, like<br><br> * * <i>myModule.myAction.0 = </i><br><br> * * @author Rafael Steil */ private static class UrlPattern { private static final Log logger = LogFactory.getLog(UrlPattern.class); private String name; private String value; private int size; private String[] vars; public UrlPattern(String name, String value) { this.name = name; this.value = value; this.processPattern(); } private void processPattern() { String[] p = this.value.split(","); this.vars = new String[p.length]; this.size = ((((p[0]).trim()).equals("")) ? 0 : p.length); for (int i = 0; i < this.size; i++) { this.vars[i] = (p[i]).trim(); } } /** * Gets the pattern name * * @return String with the pattern name */ public String getName() { return this.name; } /** * Get pattern's total vars * * @return The total */ public int getSize() { return this.size; } /** * Gets the vars. * The URL variables are in the correct order, which means * that the first position always will be "something1", the * second "something2" and so on. The system expects this * order never changes from requisition to requisition. * * @return The vars */ public String[] getVars() { return this.vars; } } /** * Keeps a collection of <code>UrlPattern</code> objects. * * @author Rafael Steil */ private static class UrlPatternCollection { private static final Log logger = LogFactory.getLog(UrlPatternCollection.class); private static HashMap patternsMap = new HashMap(); /** * Try to find a <code>UrlPattern</code> by its name. * * @param name The pattern name * @return The <code>UrlPattern</code> object if a match was found, or <code>null</code> if not */ public static UrlPattern findPattern(String name) { return (UrlPattern) UrlPatternCollection.patternsMap.get(name); } /** * Adds a new <code>UrlPattern</code>. * * @param name The pattern name * @param value The pattern value */ public static void addPattern(String name, String value) { UrlPatternCollection.patternsMap.put(name, new UrlPattern(name, value)); } } private Map query; /** * Default constructor. * * @param superRequest Original <code>HttpServletRequest</code> instance * @throws IOException */ public ActionServletRequest(HttpServletRequest superRequest) throws IOException { super(superRequest); if (logger.isDebugEnabled()) logger.debug("building an ActionServletRequest"); this.query = new HashMap(); boolean isMultipart = false; String requestType = (superRequest.getMethod()).toUpperCase(); String requestUri = superRequest.getRequestURI(); // Remove the "jsessionid" (or similar) from the URI // Probably this is not the right way to go, since we're // discarting the value... int index = requestUri.indexOf(';'); if (index > -1) { int lastIndex = requestUri.indexOf('?', index); if (lastIndex == -1) { lastIndex = requestUri.indexOf('&', index); } if (lastIndex == -1) { requestUri = requestUri.substring(0, index); } else { String part1 = requestUri.substring(0, index); requestUri = part1 + requestUri.substring(lastIndex); } } // String encoding = SystemGlobals.getValue(ConfigKeys.ENCODING); String encoding = SakaiSystemGlobals.getValue(ConfigKeys.ENCODING); if ((("GET").equals(requestType) && (StringUtils.trimToNull(superRequest.getQueryString()) == null)) && requestUri.endsWith(SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION))) { //superRequest.setCharacterEncoding(SystemGlobals.getValue(ConfigKeys.ENCODING)); superRequest.setCharacterEncoding(SakaiSystemGlobals.getValue(ConfigKeys.ENCODING)); String[] urlModel = requestUri.split("/"); // If (context name is not null) { // 0: empty // 1: context name // 2: module // 3: action // 4 .. n: request dependent data // } else { // 0: empty // 1: module // 2: action // 3 .. n: request dependent data // } int moduleIndex = 2; int actionIndex = 3; int baseLen = 4; String contextName = superRequest.getContextPath(); if ((contextName == null) || contextName.equals("")) { moduleIndex = 1; actionIndex = 2; baseLen = 3; } urlModel[urlModel.length - 1] = (urlModel[urlModel.length - 1]).substring(0, (urlModel[urlModel.length - 1]).indexOf(SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION))); // <moduleName>.<actionName>.<numberOfParameters> UrlPattern url = UrlPatternCollection.findPattern( urlModel[moduleIndex] + "." + urlModel[actionIndex] + "." + (urlModel.length - baseLen)); if (url == null) { throw new InvalidURLPatternException("The request '" + superRequest.getRequestURI() + "' is not valid. A correspondent URL Pattern was not found"); } this.addParameter("module", urlModel[moduleIndex]); this.addParameter("action", urlModel[actionIndex]); // We have parameters? if (url.getSize() >= urlModel.length - baseLen) { for (int i = 0; i < url.getSize(); i++) { this.addParameter(url.getVars()[i], urlModel[i + baseLen]); } } } else if (("POST").equals(requestType)) { isMultipart = ServletFileUpload.isMultipartContent(new ServletRequestContext(superRequest)); if (isMultipart) { String tmpDir = SystemGlobals.getApplicationPath() + "/" + SystemGlobals.getValue(ConfigKeys.TMP_DIR); ServletFileUpload upload = new ServletFileUpload( new DiskFileItemFactory(100 * 1024, new File(tmpDir))); try { List items = upload.parseRequest(superRequest); for (Iterator iter = items.iterator(); iter.hasNext();) { FileItem item = (FileItem) iter.next(); if (item.isFormField()) { //<<<11/15/06 Murthy - added to capture mutiple values for controls like select etc if (this.query.containsKey(item.getFieldName())) { String paramValuesExisting[] = (String[]) this.query .get(item.getFieldName() + "ParamValues"); String paramValues[] = null; if (paramValuesExisting != null) { paramValues = new String[paramValuesExisting.length + 1]; System.arraycopy(paramValuesExisting, 0, paramValues, 0, paramValuesExisting.length); paramValues[paramValuesExisting.length] = item.getString(encoding); } else { paramValues = new String[2]; paramValues[0] = (String) this.query.get(item.getFieldName()); paramValues[1] = item.getString(encoding); } this.query.put(item.getFieldName() + "ParamValues", paramValues); } //>>>11/15/06 Murthy - added to capture mutiple values for controls like select etc this.query.put(item.getFieldName(), item.getString(encoding)); } else { if (item.getSize() > 0) { this.query.put(item.getFieldName(), item); } } } } catch (FileUploadException e) { throw new MultipartHandlingException("Error while processing multipart content: " + e); } } } if (isMultipart == false) { superRequest.setCharacterEncoding(encoding); String containerEncoding = SystemGlobals.getValue(ConfigKeys.DEFAULT_CONTAINER_ENCODING); for (Enumeration e = superRequest.getParameterNames(); e.hasMoreElements();) { String name = (String) e.nextElement(); this.query.put(name, new String(superRequest.getParameter(name).getBytes(containerEncoding), encoding)); } } } /** * @see javax.servlet.ServletRequest#getParameter(java.lang.String) */ public String getParameter(String parameter) { return (String) this.query.get(parameter); } /** * Gets an parameter that is a number. * A call to <code>Integer#parseInt(String)</code> is made * to do the conversion * @param parameter The parameter name to get the value * @return */ public int getIntParameter(String parameter) { return Integer.parseInt(this.getParameter(parameter)); } /** * Gets all parameters of the current request. * * @return <code>java.util.Map</code> with all request * data. */ public Map dumpRequest() { return this.query; } /** * Restores a request "dump". * * @param query A <code>java.util.Map</code> with all request * data. Usually it will be the result of a previous call * to @link #dumpRequest() */ public void restoreDump(Map query) { this.query = query; } /** * Gets some request parameter as <code>Object</code>. * This method may be used when you have to get some value * of a <i>multipart/form-data</i> request, like a image * of file. <br> * * @param parameter * @return */ public Object getObjectParameter(String parameter) { return this.query.get(parameter); } /** * Adds a new <code>UrlPattern</code>. * * @param name The pattern name * @param value The Pattern value */ public static void addUrlPattern(String name, String value) { UrlPatternCollection.addPattern(name, value); } /** * Adds a new parameter to the request. * * If you want to have one more, or to modify an existing one parameter, * you should use this method to the job. * * @param name Parameter name * @param value Parameter value */ public void addParameter(String name, Object value) { this.query.put(name, value); } /** * Gets the <i>action</i> of the current request. * * An <i>Action</i> is the parameter name which specifies * what next action should be done by the system. It may be * add or edit a post, editing the groups, whatever. In the URL, the * Action can the represented in two forms: * <p> * <blockquote> * <code> * http://www.host.com/webapp/servletName?module=groups&action=list * </code> * </blockquote> * <p> * or * <p> * <blockquote> * <code> * http://www.host.com/webapp/servletName/groups/list * </code> * </blockquote> * <p> * In both situations, the action's name is "list". * * @return String representing the action name */ public String getAction() { return this.getParameter("action"); } /** * Gets the <i>module</i> of the current request. * * A <i>Module</i> is the parameter name which specifies * what module the user is requesting. It may be the group * administration, the topics or anything else configured module. *In the URL, the Module can the represented in two forms: * <p> * <blockquote> * <code> * http://www.host.com/webapp/servletName?module=groups&action=list * </code> * </blockquote> * <p> * or * <p> * <blockquote> * <code> * http://www.host.com/webapp/servletName/groups/list * </code> * </blockquote> * <p> * In both situations, the module's name is "groups". * * @return String representing the module name */ public String getModule() { return this.getParameter("module"); } public Object getObjectRequestParameter(String parameter) { return this.query.get(parameter); } }