/* * Created on 01.10.2004 * * @author rschamberger * $ID$ */ package at.gv.egovernment.moa.id.util; import java.io.IOException; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; import java.util.Vector; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequestWrapper; import at.gv.egovernment.moa.util.URLDecoder; /** * Special ServletRequestWrapper class which provides a more precise implementation of the getParameter* * family. This implementation cares about the order of the parameters from Query String and HTTP POST * Body. Use this as Filter class for Servlets which such needs. * * @author Rudolf Schamberger * @version $Id$ */ public class InOrderServletRequestWrapper extends HttpServletRequestWrapper { /** * standard encoding used to decode the URL string. */ // public static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1"; /** * Vector that stores the order of the query paramters */ private Vector queryParamOrder; /** * Hashtable that stores the content of the query paramters */ private Hashtable queryParameters; /** * Vector that stores the order of the HTTP body paramters */ private Vector bodyParamOrder; /** * Hashtable that stores the content of the HTTP body paramters */ private Hashtable bodyParameters; /** * ServletContext */ private ServletContext context; /** * Identifier used to identify query parameters */ public static final int QUERY_PARAM = 1; /** * Identifier used to identify HTTP body parameters */ public static final int BODY_PARAM = 2; /** * @see HttpServletRequestWrapper */ public InOrderServletRequestWrapper(final HttpServletRequest request, final ServletContext sContext) { super(request); this.context = sContext; } /** * parses the Query and if availlable also HTTP POST parameters * * @param req a HttpServletRequest which should be parsed */ protected final void parseParameters(final HttpServletRequest req) { queryParamOrder = new Vector(); queryParameters = new Hashtable(); bodyParamOrder = new Vector(); bodyParameters = new Hashtable(); //Insert code for Query string parsing String rawQuery = req.getQueryString(); queryParameters = tokenize(queryParameters, queryParamOrder, rawQuery, DEFAULT_CHARACTER_ENCODING); //analyze HTTP Post body parameters if (req.getMethod().equalsIgnoreCase("POST")) { //get body encoding String enc = req.getCharacterEncoding(); if (enc == null) enc = DEFAULT_CHARACTER_ENCODING; if (req.getContentType().equals("application/x-www-form-urlencoded")) { try { bodyParameters = parsePostData(bodyParameters, req.getContentLength(), req.getInputStream(), enc); } catch (IOException e) { context.log("could not open input stream of reqest \n" + e.toString()); } } else { //TODO add multipart code context.log( "ERROR other Content-Types than 'application/x-www-form-urlencoded' not supported!"); } }// end POST } /** * parses the HTTP POST parameters * * @param ht parameter Hashtable to put parameters in. * @param length of content * @param instream the ServletInputStream of the request * @param encoding encoding of the instream * * @return the Hashtable with the parsed data */ private Hashtable parsePostData(Hashtable ht, final int length, final ServletInputStream instream, final String encoding) { int inputLen, offset; byte[] postedBytes = null; boolean dataRemaining = true; String postedBody; StringBuffer sb = new StringBuffer(); if (length <= 0) { return null; } postedBytes = new byte[length]; try { offset = 0; while (dataRemaining) { inputLen = instream.read(postedBytes, offset, length - offset); if (inputLen <= 0) { throw new IOException("read error during reading the HTTP POST body"); } offset += inputLen; if ((length - offset) == 0) { dataRemaining = false; } } } catch (IOException e) { System.out.println("Exception =" + e); return null; } postedBody = new String(postedBytes); Hashtable ht2 = tokenize(ht, bodyParamOrder, postedBody, encoding); return ht2; } /** * tokenizes parameter strings * * @param ht parameter Hashtable to put parameters in. * @param order Vector in which the order of the tokenized parameters will be stored. * @param parameterString String to tokenize. * @param encoding which will be used to decode the parameterString. * * @return the Hashtable with the parsed data */ private Hashtable tokenize(Hashtable ht, Vector order, final String parameterString, final String encoding) { String[] valArray = null; if (null == parameterString) return ht; StringTokenizer st = new StringTokenizer(parameterString, "&"); String key = null; String val = null; while (st.hasMoreTokens()) { String pair = (String) st.nextToken(); int pos = pair.indexOf('='); if (pos == -1) { throw new IllegalArgumentException(); } try { key = URLDecoder.decode(pair.substring(0, pos), encoding); val = URLDecoder.decode(pair.substring(pos + 1, pair.length()), encoding); } catch (Exception e) { throw new IllegalArgumentException(); } if (ht.containsKey(key)) { String oldVals[] = (String[]) ht.get(key); valArray = new String[oldVals.length + 1]; for (int i = 0; i < oldVals.length; i++) { valArray[i] = oldVals[i]; } valArray[oldVals.length] = val; } else { valArray = new String[1]; valArray[0] = val; } ht.put(key, valArray); order.addElement(key); } return ht; } /** * Returns the value of a request parameter as a String, or null if the * parameter does not exist. Request parameters are extra information sent with the request. For HTTP * servlets, parameters are contained in the query string or posted form data. * *

* You should only use this method when you are sure the parameter has only one value. If the parameter * might have more than one value, use {@link #getParameterValues}. * *

* If you use this method with a multivalued parameter, the value returned is equal to the first value in * the array returned by getParameterValues. * *

* If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then * reading the body directly via {@link#getInputStream} or {@link #getReader}can interfere with the * execution of this method. * * @param name a String containing the name of the parameter whose value is requested * * @return a String representing the single value of the parameter * * @see #getParameterValues * */ public final String getParameter(final String name) { String val = getParameter(name, QUERY_PARAM); return (null != val) ? val : getParameter(name, BODY_PARAM); } /** * Returns the value of a request parameter as a String, or null if the * parameter does not exist. * * @param name a String containing the name of the parameter whose value is requested * @param parameterType type of parameter * @see at.gv.egovernment.moa.id.util.ParametersInOrderServlet#QUERY_PARAM * and @see at.gv.egovernment.moa.id.util.ParametersInOrderServlet#BODY_PARAM * @see getParameterValues(String name); * @return value of the (single) parameter or null if not availlable **/ public final String getParameter(final String name, final int parameterType) { Hashtable parameters = (parameterType == QUERY_PARAM) ? queryParameters : bodyParameters; String[] vals = (String[]) parameters.get(name); if (vals == null) { return null; } return vals[0]; } /** * Returns an array of String objects containing all of the values the given request * parameter has, or null if the parameter does not exist. * *

* If the parameter has a single value, the array has a length of 1. * * @param name a String containing the name of the parameter whose value is requested * @param parameterType type of parameter * @see at.gv.egovernment.moa.id.util.ParametersInOrderServlet#QUERY_PARAM * and @see at.gv.egovernment.moa.id.util.ParametersInOrderServlet#BODY_PARAM * @return an array of String objects containing the parameter's values or null * * @see #getParameter */ public final String getParameterValues(final String name, final int parameterType) { Hashtable parameters = (parameterType == QUERY_PARAM) ? queryParameters : bodyParameters; String[] vals = (String[]) parameters.get(name); if (vals == null) { return null; } String vallist = vals[0]; for (int i = 1; i < vals.length; i++) { vallist = vallist + "," + vals[i]; } return vallist; } /** * * Returns an Enumeration of String objects containing the names of the * parameters contained in this request. If the request has no parameters, the method returns an empty * Enumeration. * @param parameterType type of parameter * @see at.gv.egovernment.moa.id.util.ParametersInOrderServlet#QUERY_PARAM * and @see at.gv.egovernment.moa.id.util.ParametersInOrderServlet#BODY_PARAM * * @return an Enumeration of String objects, each String * containing the name of a request parameter; or an empty Enumeration if the * request has no parameters * */ public final Enumeration getParameterNames(final int parameterType) { if (QUERY_PARAM == parameterType) return queryParamOrder.elements(); else return bodyParamOrder.elements(); } } //End InOrderServletRequestWrapper