From 5c65c2f5b51a064802cce719d0aa7a2f72ceece1 Mon Sep 17 00:00:00 2001
From: rudolf <rudolf@d688527b-c9ab-4aba-bd8d-4036d912da1d>
Date: Mon, 17 Jan 2005 11:21:52 +0000
Subject: Servlet Filter to keep the parameters in right order.

git-svn-id: https://joinup.ec.europa.eu/svn/moa-idspss/trunk@215 d688527b-c9ab-4aba-bd8d-4036d912da1d
---
 .../moa/id/util/InOrderServletRequestWrapper.java  | 345 +++++++++++++++++++++
 .../moa/id/util/ParameterInOrderFilter.java        |  62 ++++
 2 files changed, 407 insertions(+)
 create mode 100644 id.server/src/at/gv/egovernment/moa/id/util/InOrderServletRequestWrapper.java
 create mode 100644 id.server/src/at/gv/egovernment/moa/id/util/ParameterInOrderFilter.java

diff --git a/id.server/src/at/gv/egovernment/moa/id/util/InOrderServletRequestWrapper.java b/id.server/src/at/gv/egovernment/moa/id/util/InOrderServletRequestWrapper.java
new file mode 100644
index 000000000..78d0a0db0
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/util/InOrderServletRequestWrapper.java
@@ -0,0 +1,345 @@
+/*
+ * 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 <code>HttpServletRequest</code> 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 <code>String</code>, or <code>null</code> 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.
+   * 
+   * <p>
+   * 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}.
+   * 
+   * <p>
+   * If you use this method with a multivalued parameter, the value returned is equal to the first value in
+   * the array returned by <code>getParameterValues</code>.
+   * 
+   * <p>
+   * 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 <code>String</code> containing the name of the parameter whose value is requested
+   *
+   * @return a <code>String</code> 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 <code>String</code>, or <code>null</code> if the
+  * parameter does not exist. 
+  * 
+  * @param name a <code>String</code> 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 <code>String</code> objects containing all of the values the given request
+   * parameter has, or <code>null</code> if the parameter does not exist.
+   * 
+   * <p>
+   * If the parameter has a single value, the array has a length of 1.
+   * 
+   * @param name a <code>String</code> 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 <code>String</code> 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 <code>Enumeration</code> of <code>String</code> objects containing the names of the
+   * parameters contained in this request. If the request has no parameters, the method returns an empty
+   * <code>Enumeration</code>.
+   * @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 <code>Enumeration</code> of <code>String</code> objects, each <code>String</code>
+   *         containing the name of a request parameter; or an empty <code>Enumeration</code> 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
\ No newline at end of file
diff --git a/id.server/src/at/gv/egovernment/moa/id/util/ParameterInOrderFilter.java b/id.server/src/at/gv/egovernment/moa/id/util/ParameterInOrderFilter.java
new file mode 100644
index 000000000..3f5fddba2
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/util/ParameterInOrderFilter.java
@@ -0,0 +1,62 @@
+package at.gv.egovernment.moa.id.util;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author rschamberger
+ *  
+ */
+/**
+ * A Filter class wich uses the InOrderServletRequestWrapper to provide servlets 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 ParameterInOrderFilter implements Filter
+{
+
+  /**
+   * filterConfig
+   */
+  private FilterConfig filterConfig;
+
+  /**
+   * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
+   */
+  public final void init(final FilterConfig config)
+  {
+    this.filterConfig = config;
+  }
+
+  /**
+   * @see javax.servlet.Filter#destroy()
+   */
+  public final void destroy()
+  {
+  };
+
+  /**
+   * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
+   *      javax.servlet.FilterChain)
+   */
+  public final void doFilter(final ServletRequest request, final ServletResponse response,
+    final FilterChain chain) throws IOException, ServletException
+  {
+    InOrderServletRequestWrapper sRequ = new InOrderServletRequestWrapper((HttpServletRequest) request,
+      filterConfig.getServletContext());
+    //parse the Query (and Body) parameters
+    sRequ.parseParameters((HttpServletRequest) request);
+    //process the rest of filter chain
+    chain.doFilter(sRequ, response);
+  }
+}
\ No newline at end of file
-- 
cgit v1.2.3