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 >>> > > >>> > >>> > >>> > >>> > -- >>> > >>> >> >> >> >> -- >> >> >