/*
* 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.logging.Logger;
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, true);
//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, false);
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, boolean decode)
{
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
{
if (decode) {
key = URLDecoder.decode(pair.substring(0, pos), encoding);
val = URLDecoder.decode(pair.substring(pos + 1, pair.length()), encoding);
} else {
key = pair.substring(0, pos);
val = pair.substring(pos + 1, pair.length());
}
//Logger.debug("(" + Integer.toString(key.length()) + "=" + Integer.toString(pair.substring(0, pos).length()) + ")"+key+"|--|"+pair.substring(0, pos));
//Logger.debug("(" + Integer.toString(val.length()) + "=" + Integer.toString(pair.substring(pos + 1, pair.length()).length()) + ")"+val+"|--|"+pair.substring(pos + 1, pair.length()));
}
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. If there are no parameters, the method returns an empty
* Enumeration
.
*
* @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()
{
Vector FullParamOrder = new Vector();
for (Enumeration enu = queryParamOrder.elements(); enu.hasMoreElements();) {
FullParamOrder.addElement(enu.nextElement());
}
for (Enumeration enu = bodyParamOrder.elements(); enu.hasMoreElements();) {
FullParamOrder.addElement(enu.nextElement());
}
return FullParamOrder.elements();
}
/**
*
* 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
*
* @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