On Wed, Jul 2, 2008 at 6:44 PM, Evan Gilbert <[EMAIL PROTECTED]> wrote:

> Anyone else with an opinion on the location of test code?
>
> Also, if we move the code, is it OK for the java/social-api/src/test
> project to depend on the java/common/src/test/project, or is there a better
> way to structure this?
>

Yes, anything can depend on common, even if it's in the test structure.


>
> Evan
>
> (P.S. Removed underscores)
>
>
>
>
> On Wed, Jul 2, 2008 at 10:20 AM, Evan Gilbert <[EMAIL PROTECTED]> wrote:
>
>> (I'll fix this as well)
>>
>>
>> On Wed, Jul 2, 2008 at 10:07 AM, Kevin Brown <[EMAIL PROTECTED]> wrote:
>>
>>> The style is also off on this patch -- underscores shouldn't be used. See
>>> also http://cwiki.apache.org/SHINDIGxSITE/java-style.html (this should
>>> have
>>> been linked on incubator.apache.org/shindig, but I guess it never got
>>> added).
>>>
>>> On Wed, Jul 2, 2008 at 9:40 AM, Evan Gilbert <[EMAIL PROTECTED]> wrote:
>>>
>>> > Hi all - I was just following existing convention - the package was
>>> already
>>> > there. If we agree this is the wrong place I'll move the code.
>>> >
>>> > One reason I've heard for putting test utilities in common is so unit
>>> test
>>> > projects can be simple and not have cross-package dependencies. This
>>> > doesn't
>>> > strike me as particularly compelling (anyone know other reasons?).
>>> However,
>>> > I'm also not too worried about shipping a small set of test utilities
>>> along
>>> > with production code.
>>> >
>>> > So put me at +0 either way - I'll follow the group on this one.
>>> >
>>> > Evan
>>> >
>>> >
>>> > On Wed, Jul 2, 2008 at 6:39 AM, Henning P. Schmiedehausen <
>>> > [EMAIL PROTECTED]>
>>> > wrote:
>>> >
>>> > > "Vincent Siveton" <[EMAIL PROTECTED]> writes:
>>> > >
>>> > > >Hi,
>>> > >
>>> > > >Creating a testing harness project will solve your good point.
>>> > >
>>> > > +1
>>> > >
>>> > >        Ciao
>>> > >             Henning
>>> > >
>>> > >
>>> > > >2008/7/2, Henning P. Schmiedehausen <[EMAIL PROTECTED]>:
>>> > > >> [EMAIL PROTECTED] writes:
>>> > > >>
>>> > > >>  Folks, if this is *TEST* code, it belongs in src/test. Else it
>>> gets
>>> > > >>  shipped with the product and at some point, it will no longer be
>>> > > >>  possible to distinguish between "we need this for running" and
>>> "we
>>> > > >>  need this for testing".
>>> > > >>
>>> > > >>  Same for maven dependencies that are used only for testing. They
>>> > > >>  should be marked as test, else the artifact will drag this as
>>> > > >>  dependency around.
>>> > > >>
>>> > > >>         Ciao
>>> > > >>                 Henning
>>> > > >>
>>> > > >>
>>> > > >>  >Author: evan
>>> > > >>  >Date: Tue Jul  1 17:48:26 2008
>>> > > >>  >New Revision: 673243
>>> > > >>
>>> > > >>  >URL: http://svn.apache.org/viewvc?rev=673243&view=rev
>>> > > >>  >Log:
>>> > > >>  >Working on supporting end-to-end testing of social data APIs...
>>> > added
>>> > > FakeHttpServletRequest utility that can be passed into calls to
>>> > HttpServlet.
>>> > > >>
>>> > > >>  >Added:
>>> > > >>  >
>>> > >
>>> >
>>>  
>>> incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/testing/FakeHttpServletRequest.java
>>> > > >>  >Modified:
>>> > > >>  >    incubator/shindig/trunk/java/common/pom.xml
>>> > > >>
>>> > > >>  >Modified: incubator/shindig/trunk/java/common/pom.xml
>>> > > >>  >URL:
>>> > >
>>> >
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/pom.xml?rev=673243&r1=673242&r2=673243&view=diff
>>> > > >>
>>> > >
>>> >
>>>  
>>> >==============================================================================
>>> > > >>  >--- incubator/shindig/trunk/java/common/pom.xml (original)
>>> > > >>  >+++ incubator/shindig/trunk/java/common/pom.xml Tue Jul  1
>>> 17:48:26
>>> > > 2008
>>> > > >>  >@@ -46,6 +46,10 @@
>>> > > >>  >       <artifactId>guice</artifactId>
>>> > > >>  >     </dependency>
>>> > > >>  >     <dependency>
>>> > > >>  >+      <groupId>com.google.code.google-collections</groupId>
>>> > > >>  >+      <artifactId>google-collect</artifactId>
>>> > > >>  >+    </dependency>
>>> > > >>  >+    <dependency>
>>> > > >>  >       <groupId>commons-codec</groupId>
>>> > > >>  >       <artifactId>commons-codec</artifactId>
>>> > > >>  >     </dependency>
>>> > > >>
>>> > > >>  >Added:
>>> > >
>>> >
>>> incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/testing/FakeHttpServletRequest.java
>>> > > >>  >URL:
>>> > >
>>> >
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/testing/FakeHttpServletRequest.java?rev=673243&view=auto
>>> > > >>
>>> > >
>>> >
>>>  
>>> >==============================================================================
>>> > > >>  >---
>>> > >
>>> >
>>> incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/testing/FakeHttpServletRequest.java
>>> > > (added)
>>> > > >>  >+++
>>> > >
>>> >
>>> incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/testing/FakeHttpServletRequest.java
>>> > > Tue Jul  1 17:48:26 2008
>>> > > >>  >@@ -0,0 +1,881 @@
>>> > > >>  >+/*
>>> > > >>  >+ * Licensed to the Apache Software Foundation (ASF) under one
>>> > > >>  >+ * or more contributor license agreements.  See the NOTICE file
>>> > > >>  >+ * distributed with this work for additional information
>>> > > >>  >+ * regarding copyright ownership.  The ASF licenses this file
>>> > > >>  >+ * to you 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.
>>> > > >>  >+ */
>>> > > >>  >+package org.apache.shindig.common.testing;
>>> > > >>  >+
>>> > > >>  >+import com.google.common.collect.Maps;
>>> > > >>  >+
>>> > > >>  >+import java.io.BufferedReader;
>>> > > >>  >+import java.io.ByteArrayInputStream;
>>> > > >>  >+import java.io.IOException;
>>> > > >>  >+import java.io.InputStream;
>>> > > >>  >+import java.io.InputStreamReader;
>>> > > >>  >+import java.io.UnsupportedEncodingException;
>>> > > >>  >+import java.net.MalformedURLException;
>>> > > >>  >+import java.net.URL;
>>> > > >>  >+import java.net.URLDecoder;
>>> > > >>  >+import java.net.URLEncoder;
>>> > > >>  >+import java.text.ParseException;
>>> > > >>  >+import java.text.SimpleDateFormat;
>>> > > >>  >+import java.util.ArrayList;
>>> > > >>  >+import java.util.Collections;
>>> > > >>  >+import java.util.Date;
>>> > > >>  >+import java.util.Enumeration;
>>> > > >>  >+import java.util.HashSet;
>>> > > >>  >+import java.util.Hashtable;
>>> > > >>  >+import java.util.Iterator;
>>> > > >>  >+import java.util.LinkedHashMap;
>>> > > >>  >+import java.util.List;
>>> > > >>  >+import java.util.Locale;
>>> > > >>  >+import java.util.Map;
>>> > > >>  >+import java.util.Set;
>>> > > >>  >+import java.util.StringTokenizer;
>>> > > >>  >+import java.util.TimeZone;
>>> > > >>  >+
>>> > > >>  >+import javax.servlet.RequestDispatcher;
>>> > > >>  >+import javax.servlet.ServletInputStream;
>>> > > >>  >+import javax.servlet.http.Cookie;
>>> > > >>  >+import javax.servlet.http.HttpServletRequest;
>>> > > >>  >+import javax.servlet.http.HttpSession;
>>> > > >>  >+
>>> > > >>  >+/**
>>> > > >>  >+ * This class fakes a HttpServletRequest for unit test
>>> purposes.
>>> > > Currently, it
>>> > > >>  >+ * supports servlet API 2.4.
>>> > > >>  >+ *
>>> > > >>  >+ * <p>
>>> > > >>  >+ * To use this class, you specify the request info (URL,
>>> > parameters)
>>> > > in the
>>> > > >>  >+ * constructors.
>>> > > >>  >+ *
>>> > > >>  >+ * <p>
>>> > > >>  >+ * Lots of stuff are still not implemented here. Feel free to
>>> > > implement them.
>>> > > >>  >+ */
>>> > > >>  >+public class FakeHttpServletRequest implements
>>> HttpServletRequest {
>>> > > >>  >+  protected static final String DEFAULT_HOST = "localhost";
>>> > > >>  >+  protected static final int DEFAULT_PORT = 80;
>>> > > >>  >+  private static final String COOKIE_HEADER = "Cookie";
>>> > > >>  >+  private static final String HOST_HEADER = "Host";
>>> > > >>  >+  private static final String DATE_FORMAT = "EEE, dd MMM yyyy
>>> > > HH:mm:ss zzz";
>>> > > >>  >+
>>> > > >>  >+  protected String scheme_ = "http";
>>> > > >>  >+  protected String host_;
>>> > > >>  >+  protected int port_;
>>> > > >>  >+  protected boolean secure_ = false;
>>> > > >>  >+  protected String method_ = "GET";
>>> > > >>  >+  protected String protocol_ = "HTTP/1.0";
>>> > > >>  >+  protected String contextPath_;
>>> > > >>  >+  protected String servletPath_;
>>> > > >>  >+  protected String pathInfo_ = null;
>>> > > >>  >+  protected String queryString_;
>>> > > >>  >+  protected String ip_ = "127.0.0.1";
>>> > > >>  >+  protected String contentType_;
>>> > > >>  >+
>>> > > >>  >+  protected Hashtable<String, String> headers_ =
>>> > > >>  >+      new Hashtable<String, String>();
>>> > > >>  >+
>>> > > >>  >+  // Use a LinkedHashMap so we can generate a query string that
>>> is
>>> > in
>>> > > the same
>>> > > >>  >+  // order that we set the parameters
>>> > > >>  >+  protected Map<String, String[]> parameters_ =
>>> > > >>  >+      new LinkedHashMap<String, String[]>();
>>> > > >>  >+
>>> > > >>  >+  protected Set<String> postParameters_ = new
>>> HashSet<String>();
>>> > > >>  >+
>>> > > >>  >+  protected Map<String, Cookie> cookies_ = new
>>> Hashtable<String,
>>> > > Cookie>();
>>> > > >>  >+
>>> > > >>  >+
>>> > > >>  >+  // Use a Map rather than a table since the specified behavior
>>> of
>>> > > >>  >+  // setAttribute() allows null values.
>>> > > >>  >+  protected Map<String, Object> attributes_ =
>>> Maps.newHashMap();
>>> > > >>  >+
>>> > > >>  >+  protected Locale locale_ = Locale.US;
>>> > > >>  >+  protected List<Locale> locales_ = null;
>>> > > >>  >+
>>> > > >>  >+  // used by POST methods
>>> > > >>  >+  protected byte[] postData;
>>> > > >>  >+  protected String characterEncoding;
>>> > > >>  >+
>>> > > >>  >+  // the following two booleans ensure that either getReader()
>>> or
>>> > > >>  >+  // getInputStream is called, but not both, to conform to
>>> specs
>>> > for
>>> > > the
>>> > > >>  >+  // HttpServletRequest class.
>>> > > >>  >+  protected boolean getReaderCalled = false;
>>> > > >>  >+  protected boolean getInputStreamCalled = false;
>>> > > >>  >+
>>> > > >>  >+  private HttpSession session;
>>> > > >>  >+
>>> > > >>  >+  static final String METHOD_POST = "POST";
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Example: http://www.example.com:1234/foo/bar?abc=xyz "
>>> > > www.example.com" is
>>> > > >>  >+   * the host 1234 is the port "/foo" is the contextPath "/bar"
>>> is
>>> > > the
>>> > > >>  >+   * servletPath "abc=xyz" is the queryString
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest(String host, int port, String
>>> > > contextPath,
>>> > > >>  >+      String servletPath, String queryString) {
>>> > > >>  >+    constructor(host, port, contextPath, servletPath,
>>> queryString);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest(String host, String port,
>>> String
>>> > > contextPath,
>>> > > >>  >+      String servletPath, String queryString) {
>>> > > >>  >+    this(host, Integer.parseInt(port), contextPath,
>>> servletPath,
>>> > > queryString);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest(String contextPath, String
>>> > > servletPath,
>>> > > >>  >+      String queryString) {
>>> > > >>  >+    this(DEFAULT_HOST, -1, contextPath, servletPath,
>>> queryString);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest() {
>>> > > >>  >+    this(DEFAULT_HOST, DEFAULT_PORT, "", null, null);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest(String urlStr) throws
>>> > > MalformedURLException {
>>> > > >>  >+    URL url = new URL(urlStr);
>>> > > >>  >+    String contextPath;
>>> > > >>  >+    String servletPath;
>>> > > >>  >+    String path = url.getPath();
>>> > > >>  >+    if (path.length() <= 1) {
>>> > > >>  >+      // path must be either empty string or "/"
>>> > > >>  >+      contextPath = path;
>>> > > >>  >+      servletPath = null;
>>> > > >>  >+    } else {
>>> > > >>  >+      // Look for the second slash which separates the servlet
>>> path
>>> > > from the
>>> > > >>  >+      // context path. e.g. "/foo/bar"
>>> > > >>  >+      int secondSlash = path.indexOf("/", 1);
>>> > > >>  >+      if (secondSlash < 0) {
>>> > > >>  >+        // No second slash
>>> > > >>  >+        contextPath = path;
>>> > > >>  >+        servletPath = null;
>>> > > >>  >+      } else {
>>> > > >>  >+        contextPath = path.substring(0, secondSlash);
>>> > > >>  >+        servletPath = path.substring(secondSlash);
>>> > > >>  >+      }
>>> > > >>  >+    }
>>> > > >>  >+
>>> > > >>  >+    // Set the scheme
>>> > > >>  >+    scheme_ = url.getProtocol();
>>> > > >>  >+    if (scheme_.equalsIgnoreCase("https")) {
>>> > > >>  >+      secure_ = true;
>>> > > >>  >+    }
>>> > > >>  >+
>>> > > >>  >+    int port = url.getPort();
>>> > > >>  >+
>>> > > >>  >+    // Call constructor() instead of this() because the later
>>> is
>>> > only
>>> > > allowed
>>> > > >>  >+    // at the begining of a constructor
>>> > > >>  >+    constructor(url.getHost(), port, contextPath, servletPath,
>>> > > url.getQuery());
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest setLocale(Locale locale) {
>>> > > >>  >+    locale_ = locale;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest setLocales(List<Locale>
>>> locales) {
>>> > > >>  >+    locales_ = locales;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest setProtocol(String prot) {
>>> > > >>  >+    protocol_ = prot;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest setSecure(boolean secure) {
>>> > > >>  >+    secure_ = secure;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /*
>>> > > >>  >+   * Set a header on this request. Note that if the header
>>> implies
>>> > > other
>>> > > >>  >+   * attributes of the request I will set them accordingly.
>>> > > Specifically:
>>> > > >>  >+   *
>>> > > >>  >+   * If the header is "Cookie:" then I will automatically call
>>> > > setCookie on all
>>> > > >>  >+   * of the name-value pairs found therein.
>>> > > >>  >+   *
>>> > > >>  >+   * This makes the object easier to use because you can just
>>> feed
>>> > it
>>> > > headers
>>> > > >>  >+   * and the object will remain consistent with the behavior
>>> you'd
>>> > > expect from a
>>> > > >>  >+   * request.
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setHeader(String name, String
>>> > value)
>>> > > {
>>> > > >>  >+    if (name.equals(COOKIE_HEADER)) {
>>> > > >>  >+      String[] pairs = splitAndTrim(value, ";");
>>> > > >>  >+      for (int i = 0; i < pairs.length; i++) {
>>> > > >>  >+        int equalsPos = pairs[i].indexOf('=');
>>> > > >>  >+        if (equalsPos != -1) {
>>> > > >>  >+          String cookieName = pairs[i].substring(0, equalsPos);
>>> > > >>  >+          String cookieValue = pairs[i].substring(equalsPos +
>>> 1);
>>> > > >>  >+          addToCookieMap(new Cookie(cookieName, cookieValue));
>>> > > >>  >+        }
>>> > > >>  >+      }
>>> > > >>  >+      setCookieHeader();
>>> > > >>  >+      return this;
>>> > > >>  >+    }
>>> > > >>  >+
>>> > > >>  >+    addToHeaderMap(name, value);
>>> > > >>  >+
>>> > > >>  >+    if (name.equals(HOST_HEADER)) {
>>> > > >>  >+      host_ = value;
>>> > > >>  >+    }
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  private void addToHeaderMap(String name, String value) {
>>> > > >>  >+    headers_.put(name.toLowerCase(), value);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Associates a set of cookies with this fake request.
>>> > > >>  >+   *
>>> > > >>  >+   * @param cookies the cookies associated with this request.
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setCookies(Cookie... cookies) {
>>> > > >>  >+    for (Cookie cookie : cookies) {
>>> > > >>  >+      addToCookieMap(cookie);
>>> > > >>  >+    }
>>> > > >>  >+    setCookieHeader();
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Sets a single cookie associated with this fake request.
>>> > Cookies
>>> > > are
>>> > > >>  >+   * cumulative, but ones with the same name will overwrite one
>>> > > another.
>>> > > >>  >+   *
>>> > > >>  >+   * @param c the cookie to associate with this request.
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setCookie(Cookie c) {
>>> > > >>  >+    addToCookieMap(c);
>>> > > >>  >+    setCookieHeader();
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  private void addToCookieMap(Cookie c) {
>>> > > >>  >+    cookies_.put(c.getName(), c);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Sets the "Cookie" HTTP header based on the current
>>> cookies.
>>> > > >>  >+   */
>>> > > >>  >+  private void setCookieHeader() {
>>> > > >>  >+    StringBuilder sb = new StringBuilder();
>>> > > >>  >+    boolean isFirst = true;
>>> > > >>  >+    for (Cookie c : cookies_.values()) {
>>> > > >>  >+      if (!isFirst) {
>>> > > >>  >+        sb.append("; ");
>>> > > >>  >+      }
>>> > > >>  >+      sb.append(c.getName());
>>> > > >>  >+      sb.append("=");
>>> > > >>  >+      sb.append(c.getValue());
>>> > > >>  >+      isFirst = false;
>>> > > >>  >+    }
>>> > > >>  >+
>>> > > >>  >+    // We cannot use setHeader() here, because setHeader()
>>> calls
>>> > this
>>> > > method
>>> > > >>  >+    addToHeaderMap(COOKIE_HEADER, sb.toString());
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Sets the a parameter in this fake request.
>>> > > >>  >+   *
>>> > > >>  >+   * @param name the string key
>>> > > >>  >+   * @param values the string array value
>>> > > >>  >+   * @param isPost if the paramenter comes in the post body.
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setParameter(String name,
>>> boolean
>>> > > isPost, String... values) {
>>> > > >>  >+    if (isPost) {
>>> > > >>  >+      postParameters_.add(name);
>>> > > >>  >+    }
>>> > > >>  >+    parameters_.put(name, values);
>>> > > >>  >+    // Old query string no longer matches up, so set it to null
>>> so
>>> > it
>>> > > can be
>>> > > >>  >+    // regenerated on the next call of getQueryString()
>>> > > >>  >+    queryString_ = null;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Sets the a parameter in this fake request.
>>> > > >>  >+   *
>>> > > >>  >+   * @param name the string key
>>> > > >>  >+   * @param values the string array value
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setParameter(String name,
>>> String...
>>> > > values) {
>>> > > >>  >+    setParameter(name, false, values);
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+
>>> > > >>  >+  /** Set the path info field. */
>>> > > >>  >+  public FakeHttpServletRequest setPathInfo(String path) {
>>> > > >>  >+    pathInfo_ = path;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Specify the mock POST data.
>>> > > >>  >+   *
>>> > > >>  >+   * @param postString the mock post data
>>> > > >>  >+   * @param encoding format with which to encode mock post data
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setPostData(String postString,
>>> > String
>>> > > encoding)
>>> > > >>  >+      throws UnsupportedEncodingException {
>>> > > >>  >+    setPostData(postString.getBytes(encoding));
>>> > > >>  >+    characterEncoding = encoding;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Specify the mock POST data in raw binary format.
>>> > > >>  >+   *
>>> > > >>  >+   * This implicitly sets character encoding to not specified.
>>> > > >>  >+   *
>>> > > >>  >+   * @param data the mock post data; this is owned by the
>>> caller,
>>> > so
>>> > > >>  >+   *        modifications made after this call will show up
>>> when
>>> > the
>>> > > post data
>>> > > >>  >+   *        is read
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setPostData(byte[] data) {
>>> > > >>  >+    postData = data;
>>> > > >>  >+    characterEncoding = null;
>>> > > >>  >+    method_ = METHOD_POST;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Set a new value for the query string. The query string
>>> will be
>>> > > parsed and
>>> > > >>  >+   * all parameters reset.
>>> > > >>  >+   *
>>> > > >>  >+   * @param queryString representing the new value. i.e.:
>>> > > "bug=1&id=23"
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setQueryString(String
>>> queryString)
>>> > {
>>> > > >>  >+    queryString_ = queryString;
>>> > > >>  >+    parameters_.clear();
>>> > > >>  >+    decodeQueryString(queryString, parameters_);
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Sets the session for this request.
>>> > > >>  >+   *
>>> > > >>  >+   * @param session the new session
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setSession(HttpSession session)
>>> {
>>> > > >>  >+    this.session = session;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Sets the content type.
>>> > > >>  >+   *
>>> > > >>  >+   * @param contentType of the request.
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setContentType(String
>>> contentType)
>>> > {
>>> > > >>  >+    this.contentType_ = contentType;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  //
>>> > >
>>> >
>>> ///////////////////////////////////////////////////////////////////////////
>>> > > >>  >+  // Implements methods from HttpServletRequest
>>> > > >>  >+  //
>>> > >
>>> >
>>> ///////////////////////////////////////////////////////////////////////////
>>> > > >>  >+
>>> > > >>  >+  public String getAuthType() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public java.lang.String getContextPath() {
>>> > > >>  >+    return contextPath_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public Cookie[] getCookies() {
>>> > > >>  >+    if (cookies_.isEmpty()) {
>>> > > >>  >+      // API promises null return if no cookies
>>> > > >>  >+      return null;
>>> > > >>  >+    }
>>> > > >>  >+    return cookies_.values().toArray(new Cookie[0]);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public long getDateHeader(String name) {
>>> > > >>  >+    String value = getHeader(name);
>>> > > >>  >+    if (value == null) return -1;
>>> > > >>  >+
>>> > > >>  >+    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT,
>>> > > Locale.US);
>>> > > >>  >+    format.setTimeZone(TimeZone.getTimeZone("GMT"));
>>> > > >>  >+    try {
>>> > > >>  >+      return format.parse(value).getTime();
>>> > > >>  >+    } catch (ParseException e) {
>>> > > >>  >+      throw new IllegalArgumentException("Cannot parse number
>>> from
>>> > > header "
>>> > > >>  >+          + name + ":" + value, e);
>>> > > >>  >+    }
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest setDateHeader(String name, long
>>> > > value) {
>>> > > >>  >+    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT,
>>> > > Locale.US);
>>> > > >>  >+    format.setTimeZone(TimeZone.getTimeZone("GMT"));
>>> > > >>  >+    setHeader(name, format.format(new Date(value)));
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getHeader(String name) {
>>> > > >>  >+    return headers_.get(name.toLowerCase());
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public Enumeration<String> getHeaderNames() {
>>> > > >>  >+    return headers_.keys();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public Enumeration<?> getHeaders(String name) {
>>> > > >>  >+    List<String> values = new ArrayList<String>();
>>> > > >>  >+    for (Map.Entry<String, String> entry : headers_.entrySet())
>>> {
>>> > > >>  >+      if (name.equalsIgnoreCase(entry.getKey())) {
>>> > > >>  >+        values.add(entry.getValue());
>>> > > >>  >+      }
>>> > > >>  >+    }
>>> > > >>  >+    return Collections.enumeration(values);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public int getIntHeader(String name) {
>>> > > >>  >+    return Integer.parseInt(getHeader(name));
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getMethod() {
>>> > > >>  >+    return method_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest setMethod(String method) {
>>> > > >>  >+    method_ = method;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getPathInfo() {
>>> > > >>  >+    return pathInfo_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getPathTranslated() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getQueryString() {
>>> > > >>  >+    try {
>>> > > >>  >+      if (queryString_ == null && !parameters_.isEmpty()) {
>>> > > >>  >+        boolean hasPrevious = false;
>>> > > >>  >+        StringBuilder queryString = new StringBuilder();
>>> > > >>  >+        for (Iterator<String> it =
>>> parameters_.keySet().iterator();
>>> > > it.hasNext();) {
>>> > > >>  >+          String key = it.next();
>>> > > >>  >+
>>> > > >>  >+          // We're not interested in blank keys
>>> > > >>  >+          if (key == null || key.equals("") ||
>>> > > postParameters_.contains(key)) {
>>> > > >>  >+            continue;
>>> > > >>  >+          }
>>> > > >>  >+          if (hasPrevious) {
>>> > > >>  >+            queryString.append("&");
>>> > > >>  >+          }
>>> > > >>  >+
>>> > > >>  >+          String[] values = parameters_.get(key);
>>> > > >>  >+          // Append the parameters to the query string
>>> > > >>  >+          if (values.length == 0) {
>>> > > >>  >+            queryString.append(URLEncoder.encode(key,
>>> "UTF-8"));
>>> > > >>  >+          } else {
>>> > > >>  >+            for (int i = 0; i < values.length; i++) {
>>> > > >>  >+              queryString.append(URLEncoder.encode(key,
>>> > > "UTF-8")).append("=").append(
>>> > > >>  >+                  URLEncoder.encode(values[i], "UTF-8"));
>>> > > >>  >+              if (i < values.length - 1) {
>>> > > >>  >+                queryString.append("&");
>>> > > >>  >+              }
>>> > > >>  >+            }
>>> > > >>  >+          }
>>> > > >>  >+          hasPrevious = true;
>>> > > >>  >+
>>> > > >>  >+        }
>>> > > >>  >+        queryString_ = queryString.toString();
>>> > > >>  >+      }
>>> > > >>  >+      return queryString_;
>>> > > >>  >+    } catch (UnsupportedEncodingException e) {
>>> > > >>  >+      throw new RuntimeException("Should always support UTF-8",
>>> e);
>>> > > >>  >+    }
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getRemoteUser() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getRequestedSessionId() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getRequestURI() {
>>> > > >>  >+    StringBuffer buf = new StringBuffer();
>>> > > >>  >+    if (!contextPath_.equals("")) {
>>> > > >>  >+      buf.append(contextPath_);
>>> > > >>  >+    }
>>> > > >>  >+
>>> > > >>  >+    if (servletPath_ != null && !"".equals(servletPath_)) {
>>> > > >>  >+      buf.append(servletPath_);
>>> > > >>  >+    }
>>> > > >>  >+
>>> > > >>  >+    if (buf.length() == 0) {
>>> > > >>  >+      buf.append('/');
>>> > > >>  >+    }
>>> > > >>  >+
>>> > > >>  >+    return buf.toString();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public StringBuffer getRequestURL() {
>>> > > >>  >+    StringBuffer buf =
>>> > > >>  >+        secure_ ? new StringBuffer("https://";) : new
>>> > > StringBuffer("http://";);
>>> > > >>  >+    buf.append(host_);
>>> > > >>  >+    if (port_ >= 0) {
>>> > > >>  >+      buf.append(':');
>>> > > >>  >+      buf.append(port_);
>>> > > >>  >+    }
>>> > > >>  >+    buf.append(getRequestURI()); // always begins with '/'
>>> > > >>  >+    return buf;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getServletPath() {
>>> > > >>  >+    return servletPath_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public FakeHttpServletRequest setServletPath(String
>>> servletPath)
>>> > {
>>> > > >>  >+    this.servletPath_ = servletPath;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public HttpSession getSession() {
>>> > > >>  >+    return getSession(true);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public HttpSession getSession(boolean create) {
>>> > > >>  >+    // TODO return fake session if create && session == null
>>> > > >>  >+    return session;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public java.security.Principal getUserPrincipal() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public boolean isRequestedSessionIdFromCookie() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  @Deprecated
>>> > > >>  >+  public boolean isRequestedSessionIdFromUrl() {
>>> > > >>  >+    throw new UnsupportedOperationException("This method is
>>> > > deprecated");
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public boolean isRequestedSessionIdFromURL() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public boolean isRequestedSessionIdValid() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public boolean isUserInRole(String role) {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  // Implements methods from ServletRequest
>>> > > ///////////////////////////////////
>>> > > >>  >+
>>> > > >>  >+  public Object getAttribute(String name) {
>>> > > >>  >+    return attributes_.get(name);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public Enumeration<?> getAttributeNames() {
>>> > > >>  >+    return Collections.enumeration(attributes_.keySet());
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getCharacterEncoding() {
>>> > > >>  >+    return characterEncoding;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public int getContentLength() {
>>> > > >>  >+    return (postData == null) ? 0 : postData.length;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getContentType() {
>>> > > >>  >+    return contentType_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Get the body of the request (i.e. the POST data) as a
>>> binary
>>> > > stream. As per
>>> > > >>  >+   * Java docs, this OR getReader() may be called, but not both
>>> > > (attempting that
>>> > > >>  >+   * will result in an IllegalStateException)
>>> > > >>  >+   *
>>> > > >>  >+   */
>>> > > >>  >+  public ServletInputStream getInputStream() {
>>> > > >>  >+    if (getReaderCalled) {
>>> > > >>  >+      throw new IllegalStateException(
>>> > > >>  >+          "getInputStream() called after getReader()");
>>> > > >>  >+    }
>>> > > >>  >+    getInputStreamCalled = true; // so that getReader() can no
>>> > longer
>>> > > be called
>>> > > >>  >+
>>> > > >>  >+    final InputStream in = new ByteArrayInputStream(postData);
>>> > > >>  >+    return new ServletInputStream() {
>>> > > >>  >+      @Override public int read() throws IOException {
>>> > > >>  >+        return in.read();
>>> > > >>  >+      }
>>> > > >>  >+    };
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public Locale getLocale() {
>>> > > >>  >+    return locale_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public Enumeration<?> getLocales() {
>>> > > >>  >+    return Collections.enumeration(locales_);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getParameter(String name) {
>>> > > >>  >+    String[] parameters = getParameterValues(name);
>>> > > >>  >+    if (parameters == null || parameters.length < 1) {
>>> > > >>  >+      return null;
>>> > > >>  >+    } else {
>>> > > >>  >+      return parameters[0];
>>> > > >>  >+    }
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public Map<String, String[]> getParameterMap() {
>>> > > >>  >+    return parameters_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public Enumeration<String> getParameterNames() {
>>> > > >>  >+    return Collections.enumeration(parameters_.keySet());
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String[] getParameterValues(String name) {
>>> > > >>  >+    return parameters_.get(name);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getProtocol() {
>>> > > >>  >+    return protocol_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public BufferedReader getReader() throws IOException {
>>> > > >>  >+    if (getInputStreamCalled) {
>>> > > >>  >+      throw new IllegalStateException(
>>> > > >>  >+          "getReader() called after getInputStream()");
>>> > > >>  >+    }
>>> > > >>  >+
>>> > > >>  >+    getReaderCalled = true;
>>> > > >>  >+    BufferedReader br = null;
>>> > > >>  >+    ByteArrayInputStream bais = new
>>> ByteArrayInputStream(postData);
>>> > > >>  >+    InputStreamReader isr;
>>> > > >>  >+    if (characterEncoding != null) {
>>> > > >>  >+      isr = new InputStreamReader(bais, characterEncoding);
>>> > > >>  >+    } else {
>>> > > >>  >+      isr = new InputStreamReader(bais);
>>> > > >>  >+    }
>>> > > >>  >+    br = new BufferedReader(isr);
>>> > > >>  >+    return br;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  @Deprecated
>>> > > >>  >+  public String getRealPath(String path) {
>>> > > >>  >+    throw new UnsupportedOperationException("This method is
>>> > > deprecated");
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getRemoteAddr() {
>>> > > >>  >+    return ip_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * Sets the remote IP address for this [EMAIL PROTECTED]
>>> > > FakeHttpServletRequest}.
>>> > > >>  >+   *
>>> > > >>  >+   * @param ip the IP to set
>>> > > >>  >+   * @return this [EMAIL PROTECTED] FakeHttpServletRequest} object
>>> > > >>  >+   */
>>> > > >>  >+  public FakeHttpServletRequest setRemoteAddr(String ip) {
>>> > > >>  >+    ip_ = ip;
>>> > > >>  >+    return this;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getRemoteHost() {
>>> > > >>  >+    return "localhost";
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+
>>> > > >>  >+  /*
>>> > > >>  >+   * (non-Javadoc)
>>> > > >>  >+   *
>>> > > >>  >+   * New Servlet 2.4 method
>>> > > >>  >+   *
>>> > > >>  >+   * @see javax.servlet.ServletRequest#getLocalPort()
>>> > > >>  >+   */
>>> > > >>  >+  public int getLocalPort() {
>>> > > >>  >+    return 8080;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /*
>>> > > >>  >+   * (non-Javadoc)
>>> > > >>  >+   *
>>> > > >>  >+   * New Servlet 2.4 method
>>> > > >>  >+   *
>>> > > >>  >+   * @see javax.servlet.ServletRequest#getLocalAddr()
>>> > > >>  >+   */
>>> > > >>  >+  public String getLocalAddr() {
>>> > > >>  >+    return "127.0.0.1";
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /*
>>> > > >>  >+   * (non-Javadoc)
>>> > > >>  >+   *
>>> > > >>  >+   * New Servlet 2.4 method
>>> > > >>  >+   *
>>> > > >>  >+   * @see javax.servlet.ServletRequest#getLocalName()
>>> > > >>  >+   */
>>> > > >>  >+  public String getLocalName() {
>>> > > >>  >+    return "localhost";
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /*
>>> > > >>  >+   * (non-Javadoc)
>>> > > >>  >+   *
>>> > > >>  >+   * New Servlet 2.4 method
>>> > > >>  >+   *
>>> > > >>  >+   * @see javax.servlet.ServletRequest#getRemotePort()
>>> > > >>  >+   */
>>> > > >>  >+  public int getRemotePort() {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+
>>> > > >>  >+  public RequestDispatcher getRequestDispatcher(String path) {
>>> > > >>  >+    throw new UnsupportedOperationException();
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getScheme() {
>>> > > >>  >+    return scheme_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public String getServerName() {
>>> > > >>  >+    return host_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public int getServerPort() {
>>> > > >>  >+    return (port_ < 0) ? DEFAULT_PORT : port_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public boolean isSecure() {
>>> > > >>  >+    return secure_;
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public void removeAttribute(String name) {
>>> > > >>  >+    attributes_.remove(name);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  public void setAttribute(String name, Object value) {
>>> > > >>  >+    attributes_.put(name, value);
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * @inheritDoc
>>> > > >>  >+   *
>>> > > >>  >+   * For POST requests, this affects interpretation of POST
>>> body.
>>> > > >>  >+   *
>>> > > >>  >+   * For non-POST requests (original author's comment): Do
>>> nothing
>>> > -
>>> > > all request
>>> > > >>  >+   * components were created as unicode Strings, so this can't
>>> > affect
>>> > > how
>>> > > >>  >+   * they're interpreted anyway.
>>> > > >>  >+   */
>>> > > >>  >+  public void setCharacterEncoding(String env) {
>>> > > >>  >+    if (method_.equals(METHOD_POST)) {
>>> > > >>  >+      characterEncoding = env;
>>> > > >>  >+    }
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  // Helper methods
>>> > > ///////////////////////////////////////////////////////////
>>> > > >>  >+
>>> > > >>  >+  /**
>>> > > >>  >+   * This method serves as the central constructor of this
>>> class.
>>> > The
>>> > > reason it
>>> > > >>  >+   * is not an actual constructor is that Java doesn't allow
>>> > calling
>>> > > another
>>> > > >>  >+   * constructor at the end of a constructor. e.g.
>>> > > >>  >+   *
>>> > > >>  >+   * <pre>
>>> > > >>  >+   * public FakeHttpServletRequest(String foo) {
>>> > > >>  >+   *   // Do something here
>>> > > >>  >+   *   this(foo, bar); // calling another constructor here is
>>> not
>>> > > allowed
>>> > > >>  >+   * }
>>> > > >>  >+   * </pre>
>>> > > >>  >+   */
>>> > > >>  >+  protected void constructor(String host, int port, String
>>> > > contextPath,
>>> > > >>  >+      String servletPath, String queryString) {
>>> > > >>  >+    setHeader(HOST_HEADER, host);
>>> > > >>  >+    port_ = port;
>>> > > >>  >+    contextPath_ = contextPath;
>>> > > >>  >+    servletPath_ = servletPath;
>>> > > >>  >+    queryString_ = queryString;
>>> > > >>  >+    if (queryString != null) {
>>> > > >>  >+      decodeQueryString(queryString, parameters_);
>>> > > >>  >+    }
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  protected void decodeQueryString(String queryString,
>>> > > >>  >+      Map<String, String[]> parameters) {
>>> > > >>  >+    for (String param : queryString.split("&")) {
>>> > > >>  >+      // The first '=' separates the name and value
>>> > > >>  >+      int sepPos = param.indexOf('=');
>>> > > >>  >+      String name, value;
>>> > > >>  >+      if (sepPos < 0) {
>>> > > >>  >+        // if no equal is present, assume a blank value
>>> > > >>  >+        name = param;
>>> > > >>  >+        value = "";
>>> > > >>  >+      } else {
>>> > > >>  >+        name = param.substring(0, sepPos);
>>> > > >>  >+        value = param.substring(sepPos + 1);
>>> > > >>  >+      }
>>> > > >>  >+
>>> > > >>  >+      addParameter(parameters, decodeParameterPart(name),
>>> > > >>  >+          decodeParameterPart(value));
>>> > > >>  >+    }
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  private String decodeParameterPart(String str) {
>>> > > >>  >+    // borrowed from FormUrlDecoder
>>> > > >>  >+    try {
>>> > > >>  >+      // we could infer proper encoding from headers, but
>>> > > setCharacterEncoding
>>> > > >>  >+      // is a noop.
>>> > > >>  >+      return URLDecoder.decode(str, "UTF-8");
>>> > > >>  >+    } catch (IllegalArgumentException iae) {
>>> > > >>  >+      // According to the javadoc of URLDecoder, when the input
>>> > > string is
>>> > > >>  >+      // illegal, it could either leave the illegal characters
>>> > alone
>>> > > or throw
>>> > > >>  >+      // an IllegalArgumentException! To deal with both
>>> > consistently,
>>> > > we
>>> > > >>  >+      // ignore IllegalArgumentException and just return the
>>> > original
>>> > > string.
>>> > > >>  >+      return str;
>>> > > >>  >+    } catch (UnsupportedEncodingException e) {
>>> > > >>  >+      return str;
>>> > > >>  >+    }
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  protected void addParameter(Map<String, String[]> parameters,
>>> > > String name,
>>> > > >>  >+      String value) {
>>> > > >>  >+    if (parameters.containsKey(name)) {
>>> > > >>  >+      String[] existingParamValues = parameters.get(name);
>>> > > >>  >+      String[] newParamValues = new
>>> > String[existingParamValues.length
>>> > > + 1];
>>> > > >>  >+      System.arraycopy(existingParamValues, 0, newParamValues,
>>> 0,
>>> > > >>  >+          existingParamValues.length);
>>> > > >>  >+      newParamValues[newParamValues.length - 1] = value;
>>> > > >>  >+      parameters.put(name, newParamValues);
>>> > > >>  >+    } else {
>>> > > >>  >+      String[] paramValues = {value,};
>>> > > >>  >+      parameters.put(name, paramValues);
>>> > > >>  >+    }
>>> > > >>  >+  }
>>> > > >>  >+
>>> > > >>  >+  private static String[] splitAndTrim(String str, String
>>> delims) {
>>> > > >>  >+    StringTokenizer tokenizer = new StringTokenizer(str,
>>> delims);
>>> > > >>  >+    int n = tokenizer.countTokens();
>>> > > >>  >+    String[] list = new String[n];
>>> > > >>  >+    for (int i = 0; i < n; i++) {
>>> > > >>  >+      list[i] = tokenizer.nextToken().trim();
>>> > > >>  >+    }
>>> > > >>  >+    return list;
>>> > > >>  >+  }
>>> > > >>  >+}
>>> > > >>
>>> > > >>
>>> > > >>  --
>>> > > >>  Henning P. Schmiedehausen  -- [EMAIL PROTECTED] | J2EE, Linux,
>>> > > >>  91054 Buckenhof, Germany   -- +49 9131 506540  | Apache person
>>> > > >>  Open Source Consulting, Development, Design    | Velocity -
>>> Turbine
>>> > guy
>>> > > >>
>>> > > >>  INTERMETA - Gesellschaft fuer Mehrwertdienste mbH - RG Fuerth,
>>> HRB
>>> > 7350
>>> > > >>  Sitz der Gesellschaft: Buckenhof. Geschaeftsfuehrer: Henning
>>> > > Schmiedehausen
>>> > > >>
>>> > > >>    "Professor Peach in the library with the lead piping!" -- Donna
>>> > > >>
>>> > >
>>> > > --
>>> > > Henning P. Schmiedehausen  -- [EMAIL PROTECTED] | J2EE, Linux,
>>> > > 91054 Buckenhof, Germany   -- +49 9131 506540  | Apache person
>>> > > Open Source Consulting, Development, Design    | Velocity - Turbine
>>> guy
>>> > >
>>> > > INTERMETA - Gesellschaft fuer Mehrwertdienste mbH - RG Fuerth, HRB
>>> 7350
>>> > > Sitz der Gesellschaft: Buckenhof. Geschaeftsfuehrer: Henning
>>> > Schmiedehausen
>>> > >
>>> > >   "Professor Peach in the library with the lead piping!" -- Donna
>>> > >
>>> >
>>> >
>>> >
>>> > --
>>> >
>>>
>>
>>
>>
>> --
>>
>>
>

Reply via email to