blob: 779aa5e970e0879aed1c4fcb11f01d3def51d1d8 [file] [log] [blame]
/*
* 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.click.servlet;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.Principal;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.click.util.ClickUtils;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
/**
* Mock implementation of {@link javax.servlet.http.HttpServletRequest}.
* <p/>
* Implements all of the methods from the standard HttpServletRequest class
* plus helper methods to aid setting up a request.
* <p/>
* This class was adapted from <a href="http://wicket.apache.org">Apache Wicket</a>.
*/
public class MockRequest implements HttpServletRequest {
// -------------------------------------------------------- Constants
/** Newline indicator. */
private static final String CRLF = "\r\n";
/** File attachment boundary indicator. */
private static final String BOUNDARY = "--abcdefgABCDEFG";
/** The REMOTE_USER header. */
public static final String REMOTE_USER = "REMOTE_USER";
// -------------------------------------------------------- Variables
/** The request default locale. */
private Locale locale = Locale.getDefault();
/** The request attributes map. */
private final Map<String, Object> attributes = new HashMap<String, Object>();
/** The request authentication type (BASIC, FORM, DIGEST, CLIENT_CERT). */
private String authType;
/** The request character encoding. */
private String characterEncoding;
/** The request servlet context. */
private ServletContext servletContext;
/** The request list of cookies. */
private final List<Cookie> cookies = new ArrayList<Cookie>();
/** The request headers map. */
private final Map<String, List<String>> headers = new HashMap<String, List<String>>();
/** The name of the HTTP method with which this request was made. */
private String method = "POST";
/** The request parameter map. */
private final Map<String, Object> parameters = new HashMap<String, Object>();
/** The request HTTP session. */
private HttpSession session;
/**
* Map of uploaded files, where the fieldname is the key and uploaded file
* is the value.
*/
private Map<String, UploadedFile> uploadedFiles = new HashMap<String, UploadedFile>();
/**
* Indicates if this request is multipart (contains binary attachment) or
* not, false by default.
*/
private boolean useMultiPartContentType;
/** The url that was forwarded to. */
private String forward;
/** The list of server side included url's. */
private List<String> includes = new ArrayList<String>();
/** The scheme used to make this request, defaults to "http". */
private String scheme = "http";
/** The request context path, defaults to {@link MockServletContext#DEFAULT_CONTEXT_PATH}. */
private String contextPath = MockServletContext.DEFAULT_CONTEXT_PATH;
/** The request servlet path, defaults to an empty String "". */
private String servletPath = "";
/** The request path info, defaults to an empty String "". */
private String pathInfo = "";
/** The host name to which the request was sent, defaults to "localhost". */
private String serverName = "localhost";
/** The port number to which the request was sent, defaults to 8080. */
private int serverPort = 8080;
/** A random number generator to create unique session id's. */
private Random random = new Random();
/** The user principal. */
private Principal userPrincipal;
/**
* Create new MockRequest.
*/
public MockRequest() {
initialize();
}
/**
* Create new MockRequest for the specified local.
*
* @param locale locale for this request
*/
public MockRequest(final Locale locale) {
this(locale, null);
}
/**
* Create a new MockRequest for the specified context.
*
* @param servletContext the servletContext for this request
*/
public MockRequest(final ServletContext servletContext) {
this(null, servletContext);
}
/**
* Create a new MockRequest for the specified locale and servletContext.
*
* @param locale locale for this request
* @param servletContext the servletContext for this request
*/
public MockRequest(final Locale locale, final ServletContext servletContext) {
this(locale, servletContext, null);
}
/**
* Create a new MockRequest for the specified arguments.
*
* @param locale The request locale, or null to use the default locale
* @param session The session object
* @param servletContext The current servlet context
*/
public MockRequest(final Locale locale, final ServletContext servletContext,
final HttpSession session) {
this(locale, MockServletContext.DEFAULT_CONTEXT_PATH, "", servletContext, session);
}
/**
* Create a new MockRequest for the specified arguments.
*
* @param locale The request locale, or null to use the default locale
* @param contextPath the request context path
* @param servletPath the request servlet path
* @param servletContext The current servlet context
* @param session the request session
*/
public MockRequest(Locale locale, String contextPath, String servletPath,
final ServletContext servletContext, final HttpSession session) {
if (locale != null) {
this.locale = locale;
}
this.contextPath = contextPath;
this.servletPath = servletPath;
this.session = session;
this.servletContext = servletContext;
initialize();
}
// -------------------------------------------------------- Mock intialization methods
/**
* Set the request's servletContext instance.
*
* @param servletContext the new ServletContext instance
*/
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
/**
* Set the request's session instance.
*
* @param session the new HttpSession instance
*/
public void setHttpSession(HttpSession session) {
this.session = session;
}
/**
* Add a new cookie.
*
* @param cookie The cookie
*/
public void addCookie(final Cookie cookie) {
cookies.add(cookie);
}
/**
* Add an uploaded file to the request. Use this to simulate a file that
* has been uploaded to a field.
*
* @param fieldName The fieldname of the upload field.
* @param file The file to upload.
* @param contentType The content type of the file. Must be a correct
* mimetype.
*/
public void addFile(String fieldName, File file, String contentType) {
if (file == null) {
throw new IllegalArgumentException("File must not be null");
}
if (file.exists() == false) {
throw new IllegalArgumentException(
"File does not exist. You must provide an existing file: "
+ file.getAbsolutePath());
}
if (file.isFile() == false) {
throw new IllegalArgumentException(
"You can only add a File, which is not a directory. Only files "
+ "can be uploaded.");
}
if (uploadedFiles == null) {
uploadedFiles = new HashMap<String, UploadedFile>();
}
UploadedFile uf = new UploadedFile(fieldName, file, contentType);
uploadedFiles.put(fieldName, uf);
setUseMultiPartContentType(true);
}
/**
* Add a header to the request.
*
* @param name the name of the header to add
* @param value the value
*/
public void addHeader(String name, String value) {
List<String> list = headers.get(name);
if (list == null) {
list = new ArrayList<String>(1);
headers.put(name, list);
}
list.add(value);
}
/**
* Set request header value. The existing header value will be replaced.
*
* @param name the name of the header to set
* @param value the header value
*/
public void setHeader(String name, String value) {
setHeader(name, new String[] {value});
}
/**
* Set request header values. The existing header values will be replaced.
*
* @param name the name of the header to set
* @param values the header values
*/
public void setHeader(String name, String... values) {
List<String> list = new ArrayList<String>(values.length);
headers.put(name, list);
Collections.addAll(list, values);
}
/**
* Get an attribute.
*
* @param name The attribute name
* @return The value, or null
*/
public Object getAttribute(final String name) {
return attributes.get(name);
}
/**
* Get the names of all of the values.
*
* @return The names
*/
public Enumeration<String> getAttributeNames() {
return Collections.enumeration(attributes.keySet());
}
// -------------------------------------------------------- HttpServletRequest methods
/**
* Get the auth type.
*
* @return The auth type
*/
public String getAuthType() {
return authType;
}
/**
* Get the current character encoding.
*
* @return The character encoding
*/
public String getCharacterEncoding() {
return characterEncoding;
}
/**
* True will force Request to generate multiPart ContentType and ContentLength.
*
* @param useMultiPartContentType true if the request is multi-part, false
* otherwise
*/
public void setUseMultiPartContentType(boolean useMultiPartContentType) {
this.useMultiPartContentType = useMultiPartContentType;
}
/**
* Return the length of the content. This is always -1 except if
* useMultiPartContentType set as true. Then the length will be the length
* of the generated request.
*
* @return -1 if useMultiPartContentType is false. Else the length of the
* generated request.
*/
public int getContentLength() {
if (useMultiPartContentType) {
byte[] request = buildRequest();
return request.length;
}
return -1;
}
/**
* If useMultiPartContentType set as true return the correct content-type.
*
* @return The correct multipart content-type if useMultiPartContentType
* is true. Else null.
*/
public String getContentType() {
if (useMultiPartContentType) {
return FileUploadBase.MULTIPART_FORM_DATA + "; boundary=abcdefgABCDEFG";
}
return null;
}
/**
* Get all of the cookies for this request.
*
* @return The cookies
*/
public Cookie[] getCookies() {
if (cookies.size() == 0) {
return null;
}
Cookie[] result = new Cookie[cookies.size()];
return cookies.toArray(result);
}
/**
* Get the given header as a date.
*
* @param name The header name
* @return The date, or -1 if header not found
* @throws IllegalArgumentException If the header cannot be converted
*/
public long getDateHeader(final String name)
throws IllegalArgumentException {
String value = getHeader(name);
if (value == null) {
return -1;
}
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
try {
return df.parse(value).getTime();
} catch (ParseException e) {
throw new IllegalArgumentException("Can't convert header to date " + name + ": " + value);
}
}
/**
* Get the given header value.
*
* @param name The header name
* @return The header value or null
*/
public String getHeader(final String name) {
final List<String> l = headers.get(name);
if (l == null || l.size() < 1) {
return null;
} else {
return l.get(0);
}
}
/**
* Get the names of all of the headers.
*
* @return The header names
*/
public Enumeration<String> getHeaderNames() {
return Collections.enumeration(headers.keySet());
}
/**
* Get enumeration of all header values with the given name.
*
* @param name The name
* @return The header values
*/
public Enumeration<String> getHeaders(final String name) {
List<String> list = headers.get(name);
if (list == null) {
list = new ArrayList<String>();
}
return Collections.enumeration(list);
}
/**
* Return the map of headers for this request.
*
* @return the map of headers for this request
*/
public Map<String, List<String>> getHeaders() {
return headers;
}
/**
* Returns an input stream if there has been added some uploaded files. Use
* {@link #addFile(String, File, String)} to add some uploaded files.
*
* @return The input stream
* @throws IOException If an I/O related problem occurs
*/
public ServletInputStream getInputStream() throws IOException {
if (uploadedFiles != null && uploadedFiles.size() > 0) {
byte[] request = buildRequest();
// Ok lets make an input stream to return
final ByteArrayInputStream bais = new ByteArrayInputStream(request);
return new ServletInputStream() {
@Override
public int read() {
return bais.read();
}
};
} else {
return new ServletInputStream() {
@Override
public int read() {
return -1;
}
};
}
}
/**
* Get the given header as an int.
*
* @param name The header name
* @return The header value or -1 if header not found
* @throws NumberFormatException If the header is not formatted correctly
*/
public int getIntHeader(final String name) {
String value = getHeader(name);
if (value == null) {
return -1;
}
return Integer.valueOf(value).intValue();
}
/**
* Get the locale of the request. Attempts to decode the Accept-Language
* header and if not found returns the default locale of the JVM.
*
* @return The locale
*/
public Locale getLocale() {
final String header = getHeader("Accept-Language");
if (header == null) {
return Locale.getDefault();
}
final String[] firstLocale = header.split(",");
if (firstLocale.length < 1) {
return Locale.getDefault();
}
final String[] bits = firstLocale[0].split("-");
if (bits.length < 1) {
return Locale.getDefault();
}
final String language = bits[0].toLowerCase();
if (bits.length > 1) {
final String country = bits[1].toUpperCase();
return new Locale(language, country);
} else {
return new Locale(language);
}
}
/**
* Return all the accepted locales. This implementation always returns just
* one.
*
* @return The locales
*/
public Enumeration<Locale> getLocales() {
List<Locale> list = new ArrayList<Locale>(1);
list.add(getLocale());
return Collections.enumeration(list);
}
/**
* Get the method.
* <p/>
* The returned string will be in upper case eg. <tt>POST</tt>.
*
* @return The method
*/
public String getMethod() {
return StringUtils.upperCase(method);
}
/**
* Get the request parameter with the given name.
*
* @param name The parameter name
* @return The parameter value, or null
*/
public String getParameter(final String name) {
Object value = parameters.get(name);
if (value instanceof String[]) {
return ((String[]) value)[0];
} else {
return (String) value;
}
}
/**
* Get the map of all of the parameters.
*
* @return The parameters
*/
public Map<String, Object> getParameterMap() {
return parameters;
}
/**
* Get the names of all of the parameters.
*
* @return The parameter names
*/
public Enumeration<String> getParameterNames() {
return Collections.enumeration(parameters.keySet());
}
/**
* Get the values for the given parameter.
*
* @param name The name of the parameter
* @return The return values
*/
public String[] getParameterValues(final String name) {
Object value = parameters.get(name);
if (value == null) {
return new String[0];
}
if (value instanceof String[]) {
return (String[]) value;
} else {
String[] result = new String[1];
result[0] = value.toString();
return result;
}
}
/**
* Get the path info.
*
* @return The path info
*/
public String getPathInfo() {
return pathInfo;
}
/**
* Always returns null.
*
* @return null
*/
public String getPathTranslated() {
return null;
}
/**
* Get the protocol.
*
* @return Always HTTP/1.1
*/
public String getProtocol() {
return "HTTP/1.1";
}
/**
* Get the query string part of the request.
*
* @return The query string
*/
public String getQueryString() {
if (parameters.size() == 0) {
return null;
} else {
final StringBuffer buf = new StringBuffer();
try {
for (Iterator<String> iterator = parameters.keySet().iterator(); iterator.hasNext();) {
final String name = iterator.next();
final Object value = parameters.get(name);
if (value instanceof String[]) {
String[] aValue = (String[]) value;
for (int i = 0; i < aValue.length; i++) {
buf.append(URLEncoder.encode(name, "UTF-8"));
buf.append('=');
buf.append(URLEncoder.encode(aValue[i], "UTF-8"));
if (i < aValue.length) {
buf.append("&amp;");
}
}
} else {
buf.append(URLEncoder.encode(name, "UTF-8"));
buf.append('=');
buf.append(URLEncoder.encode((String) value, "UTF-8"));
}
if (iterator.hasNext()) {
buf.append("&amp;");
}
}
} catch (UnsupportedEncodingException e) {
// Should never happen!
}
return buf.toString();
}
}
/**
* This feature is not implemented at this time as we are not supporting
* binary servlet input. This functionality may be added in the future.
*
* @return The reader
* @throws IOException If an I/O related problem occurs
*/
public BufferedReader getReader() throws IOException {
return new BufferedReader(new CharArrayReader(new char[0]));
}
/**
* Deprecated method - should not be used.
*
* @param name The name
*
* @return The path
*
* @deprecated Use ServletContext.getRealPath(String) instead.
*/
public String getRealPath(String name) {
return servletContext.getRealPath(name);
}
/**
* Get the remote address of the client.
*
* @return Always 127.0.0.1
*/
public String getRemoteAddr() {
return "127.0.0.1";
}
/**
* Get the remote host.
*
* @return Always localhost
*/
public String getRemoteHost() {
return "localhost";
}
/**
* Return the name of the {@link #userPrincipal} if set, otherwise
* the value of the {@value #REMOTE_USER} header.
* <p/>
* To set the remote user, create an instance of a {@link MockPrincipal}
* and set it on the request through the method
* {@link #setUserPrincipal(java.security.Principal)}.
*
* @return the name of the remote user
*/
public String getRemoteUser() {
if (userPrincipal != null) {
return userPrincipal.getName();
}
return getHeader(REMOTE_USER);
}
/**
* Return the local address, <em>"127.0.0.1"</em>.
*
* @return "127.0.0.1" as the local address
*/
public String getLocalAddr() {
return "127.0.0.1";
}
/**
* Return the local name, <em>"127.0.0.1"</em>.
*
* @return "127.0.0.1" as the local name
*/
public String getLocalName() {
return "127.0.0.1";
}
/**
* Return the local port, <em>80</em>.
*
* @return 80 as the local port
*/
public int getLocalPort() {
return 80;
}
/**
* Return the remote port, <em>80</em>.
*
* @return 80 as the remote port
*/
public int getRemotePort() {
return 80;
}
/**
* Returns a RequestDispatcher for the specified path. The dispatcher
* will not dispatch to the resource. It only records the specified path
* so that one can test if the correct path was dispatched to.
*
* @param path a String specifying the pathname to the resource
* @return a dispatcher for the specified path
*/
public RequestDispatcher getRequestDispatcher(String path) {
return servletContext.getRequestDispatcher(path);
}
/**
* Get the requested session id. Always returns the id of the current
* session.
*
* @return The session id
*/
public String getRequestedSessionId() {
return session.getId();
}
/**
* Returns context path and servlet path concatenated, typically
* <tt>/applicationClassName/applicationClassName</tt>.
*
* @return The path value
* @see javax.servlet.http.HttpServletRequest#getRequestURI()
*/
public String getRequestURI() {
return getContextPath() + getServletPath();
}
/**
* Returns (an attempt at) a reconstructed URL based on it's constituent
* parts.
*
* @return a StringBuffer object containing the reconstructed URL
*/
public StringBuffer getRequestURL() {
StringBuffer buffer = new StringBuffer().append(getScheme());
buffer.append("://");
buffer.append(this.getServerName());
buffer.append(":");
buffer.append(this.getServerPort());
buffer.append(this.contextPath);
buffer.append(this.servletPath);
if (getPathInfo() != null) {
buffer.append(getPathInfo());
}
if (!isPost()) {
final String query = getQueryString();
if (query != null) {
buffer.append('?');
buffer.append(query);
}
}
return buffer;
}
/**
* Return whether the request is a post or not.
*
* @return true if the request is a post, false otherwise
*/
public boolean isPost() {
return getMethod().equalsIgnoreCase("post");
}
/**
* Get the scheme http, https, or ftp.
*
* @return the scheme used by this request
*/
public String getScheme() {
return scheme;
}
/**
* Set the request's scheme, for example http, https, or ftp.
*
* @param scheme the request's scheme
*/
public void setScheme(String scheme) {
this.scheme = scheme;
}
/**
* Get the host server name to which the request was sent.
*
* @return always the host server name
*/
public String getServerName() {
return serverName;
}
/**
* Sets the host server name to which the request was sent.
*
* @param serverName the server name the request was sent to
*/
public void setServerName(String serverName) {
this.serverName = serverName;
}
/**
* Returns the port number to which the request was sent.
*
* @return the server port to which the request was sent
*/
public int getServerPort() {
return serverPort;
}
/**
* Set the port number to which the request was sent.
*
* @param serverPort the port number to which the request was sent
*/
public void setServerPort(int serverPort) {
this.serverPort = serverPort;
}
/**
* Returns the portion of the request URI that indicates the context of the
* request.
*
* @return the portion of the request URI that indicates the context of
* the request.
*/
public String getContextPath() {
// If request's contextPath was set manually (eg user set
// servletContext's contextPath), return that value.
if (!MockServletContext.DEFAULT_CONTEXT_PATH.equals(contextPath)) {
return contextPath;
}
// If servletContext path was set manually (eg user set servletContext's
// contextPath) then use that value in preference to the request default
// contextPath.
if (servletContext instanceof MockServletContext) {
MockServletContext mockServletContext = (MockServletContext) servletContext;
if (!MockServletContext.DEFAULT_CONTEXT_PATH.equals(mockServletContext.getContextPath())) {
return mockServletContext.getContextPath();
}
}
// Lastly fallback to the default contextPath.
return contextPath;
}
/**
* Set the portion of the request URI that indicates the context of the
* request.
*
* @param contextPath the portion of the request URI that indicates the
* context of the request.
*/
public void setContextPath(String contextPath) {
this.contextPath = contextPath;
}
/**
* Return a String containing the name or path of the servlet being called.
*
* @return The servlet path
*/
public String getServletPath() {
return servletPath;
}
/**
* Set the string containing the name or path of the servlet being called.
*
* @param servletPath a String containing the name or path of the servlet
* being called
*/
public void setServletPath(String servletPath) {
this.servletPath = servletPath;
}
/**
* Returns the current HttpSession associated with this request.
*
* @return the session associated with this request
*/
public HttpSession getSession() {
return getSession(true);
}
/**
* Set the current HttpSession associated with this request.
*
* @param session the HttpSession to associate with this request
*/
public void setSession(HttpSession session) {
this.session = session;
}
/**
* Returns the current HttpSession associated with this request.
*
* @param create if true creates a new session if one does not exist
* @return the current HttpSession associated with this request.
*/
public HttpSession getSession(boolean create) {
if (session != null) {
return session;
}
if (create) {
String sessionId = createSessionId();
session = new MockSession(sessionId, servletContext);
}
return session;
}
/**
* Get the user principal. If no user principal was set this method will
* create a user principal for the {@link #getRemoteUser()}.
*
* @return the user principal
*/
public Principal getUserPrincipal() {
if (userPrincipal == null) {
final String user = getRemoteUser();
if (user == null) {
return null;
} else {
userPrincipal = new MockPrincipal() {
@Override
public String getName() {
return user;
}
};
}
}
return userPrincipal;
}
/**
* Set the user principal.
*
* @param userPrincipal the user principal
*/
public void setUserPrincipal(Principal userPrincipal) {
this.userPrincipal = userPrincipal;
}
/**
* @return True if there has been added files to this request using
* {@link #addFile(String, File, String)}.
*/
public boolean hasUploadedFiles() {
return uploadedFiles != null;
}
/**
* Reset the request back to a default state.
*/
public final void initialize() {
authType = null;
method = "post";
cookies.clear();
setDefaultHeaders();
pathInfo = null;
characterEncoding = "UTF-8";
parameters.clear();
attributes.clear();
}
/**
* Delegate to initialize method.
*/
public void reset() {
initialize();
}
/**
* Check whether session id is from a cookie. Always returns true.
*
* @return Always true
*/
public boolean isRequestedSessionIdFromCookie() {
return true;
}
/**
* Check whether session id is from a url rewrite. Always returns false.
*
* @return Always false
*/
public boolean isRequestedSessionIdFromUrl() {
return false;
}
/**
* Check whether session id is from a url rewrite. Always returns false.
*
* @return Always false
*/
public boolean isRequestedSessionIdFromURL() {
return false;
}
/**
* Check whether the session id is valid.
*
* @return Always true
*/
public boolean isRequestedSessionIdValid() {
return true;
}
/**
* Always returns false.
*
* @return Always false
*/
public boolean isSecure() {
return this.scheme.equalsIgnoreCase("https");
}
/**
* Returns true if the {@link #getUserPrincipal() authenticated user} is
* included in the given role, false otherwise.
* <p/>
* To mock up roles for a user, create a {@link MockPrincipal user principal}
* and set the necessary roles. See {@link MockPrincipal} for an example.
*
* @param role the role name
* @return true if the user is included in the specified role, false
* otherwise
*/
public boolean isUserInRole(String role) {
Principal principal = getUserPrincipal();
if (principal instanceof MockPrincipal) {
return ((MockPrincipal) principal).getRoles().contains(role);
}
return false;
}
/**
* Remove the given attribute.
*
* @param name The name of the attribute
*/
public void removeAttribute(final String name) {
attributes.remove(name);
}
/**
* Set the given attribute.
*
* @param name The attribute name
* @param o The value to set
*/
public void setAttribute(final String name, final Object o) {
attributes.put(name, o);
}
/**
* Set the auth type.
*
* @param authType The auth type
*/
public void setAuthType(final String authType) {
this.authType = authType;
}
/**
* Set the character encoding.
*
* @param encoding The character encoding
* @throws UnsupportedEncodingException If encoding not supported
*/
public void setCharacterEncoding(final String encoding)
throws UnsupportedEncodingException {
characterEncoding = encoding;
}
/**
* Set the cookies.
*
* @param theCookies The cookies
*/
public void setCookies(final Cookie[] theCookies) {
cookies.clear();
for (int i = 0; i < theCookies.length; i++) {
cookies.add(theCookies[i]);
}
}
/**
* Set the method.
*
* @param method The method
*/
public void setMethod(final String method) {
this.method = method;
}
/**
* Set a parameter.
*
* @param name The name
* @param value The value
*/
public void setParameter(final String name, final String value) {
parameters.put(name, value);
}
/**
* Set the specified parameter name to the array of strings.
*
* @param name name of the parameter
* @param values the parameter values
*/
public void setParameter(final String name, final String[] values) {
parameters.put(name, values);
}
/**
* Remove the specified parameter.
*
* @param name the parameter name to remove
*/
public void removeParameter(final String name) {
parameters.remove(name);
}
/**
* Sets a map of parameters.
*
* @param parameters the parameters to set
*/
public void setParameters(final Map<String, Object> parameters) {
this.parameters.putAll(parameters);
}
/**
* Set the path that this request is supposed to be serving. The path is
* relative to the web application root and should start with a / character
*
* @param path specifies the request path to serve
*/
public void setPathInfo(final String path) {
this.pathInfo = path;
}
/**
* Returns the url that was forwarded to, otherwise return null.
*
* @see org.apache.click.servlet.MockRequestDispatcher#forward(javax.servlet.ServletRequest,
* javax.servlet.ServletResponse)
*
* @return url that was forwarded to
*/
public String getForward() {
return this.forward;
}
/**
* Returns the list of server side included url's.
*
* @see org.apache.click.servlet.MockRequestDispatcher#include(javax.servlet.ServletRequest,
* javax.servlet.ServletResponse)
*
* @return list of urls that were included
*/
public List<String> getIncludes() {
return this.includes;
}
/**
* Returns the String representation of the mock request.
*
* @return string representation of the mock request
*/
@Override
public String toString() {
return getRequestURL().toString();
}
// ------------------------------------------------ package methods
/**
* MockRequestDispatcher adds server side included url's to the request.
*
* @param url the url to include
*/
void addInclude(String url) {
this.includes.add(url);
}
/**
* MockRequestDispatcher sets the forward url on the request.
*
* @param url the url to forward to
*/
void setForward(String url) {
this.forward = url;
}
// -------------------------------------------------------- Private methods
/**
* Helper method to create some default headers for the request.
*/
private void setDefaultHeaders() {
headers.clear();
addHeader("Accept", "text/xml,application/xml,application/xhtml+xml," + "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
addHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
Locale l = locale;
addHeader("Accept-Language", l.getLanguage().toLowerCase() + "-"
+ l.getCountry().toLowerCase() + "," + l.getLanguage().toLowerCase() + ";q=0.5");
addHeader("User-Agent",
"Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040707 Firefox/0.9.2");
}
/**
* Helper method to create new attachment.
*
* @param out the output stream to add attachment to
* @throws java.io.IOException if an I/O error occurs
*/
private void newAttachment(OutputStream out) throws IOException {
out.write(BOUNDARY.getBytes());
out.write(CRLF.getBytes());
out.write("Content-Disposition: form-data".getBytes());
}
/**
* Build the request based on the uploaded files and the parameters.
*
* @return The request as a string.
*/
private byte[] buildRequest() {
try {
// Build up the input stream based on the files and parameters
ByteArrayOutputStream out = new ByteArrayOutputStream();
// Add parameters
for (String name : parameters.keySet()) {
newAttachment(out);
out.write("; name=\"".getBytes());
out.write(name.getBytes());
out.write("\"".getBytes());
out.write(CRLF.getBytes());
out.write(CRLF.getBytes());
out.write(parameters.get(name).toString().getBytes());
out.write(CRLF.getBytes());
}
// Add files
if (uploadedFiles != null) {
for (String fieldName : uploadedFiles.keySet()) {
UploadedFile uf = uploadedFiles.get(fieldName);
newAttachment(out);
out.write("; name=\"".getBytes());
out.write(fieldName.getBytes());
out.write("\"; filename=\"".getBytes());
out.write(uf.getFile().getName().getBytes());
out.write("\"".getBytes());
out.write(CRLF.getBytes());
out.write("Content-Type: ".getBytes());
out.write(uf.getContentType().getBytes());
out.write(CRLF.getBytes());
out.write(CRLF.getBytes());
// Load the file and put it into the the inputstream
FileInputStream fis = new FileInputStream(uf.getFile());
IOUtils.copy(fis, out);
fis.close();
out.write(CRLF.getBytes());
}
}
out.write(BOUNDARY.getBytes());
out.write("--".getBytes());
out.write(CRLF.getBytes());
return out.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Create and return a new session id.
*
* @return new session id
*/
private String createSessionId() {
String mockId = getRemoteAddr().replaceAll("\\.", "") + "_"
+ System.currentTimeMillis() + "_"
+ Math.abs(random.nextLong());
try {
//make it look secure ;-)
mockId = ClickUtils.toMD5Hash(mockId);
} catch (Exception e) {
//ignore
}
return mockId;
}
/**
* A holder class for an uploaded file.
*
* @author Frank Bille (billen)
*/
private static class UploadedFile {
/** Name of the file field. */
private String fieldName;
/** The uploaded file. */
private File file;
/** The uploaded file content type. */
private String contentType;
/**
* Construct.
*
* @param fieldName name of the file field
* @param file the uploaded file
* @param contentType the uploaded file content type
*/
public UploadedFile(String fieldName, File file, String contentType) {
this.fieldName = fieldName;
this.file = file;
this.contentType = contentType;
}
/**
* Return the uploaded file content type.
*
* @return The content type of the file. Mime type.
*/
public String getContentType() {
return contentType;
}
/**
* Set the uploaded file content type.
*
* @param contentType The content type.
*/
@SuppressWarnings("unused")
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* Return the file field name.
*
* @return The field name.
*/
@SuppressWarnings("unused")
public String getFieldName() {
return fieldName;
}
/**
* Set the file field name.
*
* @param fieldName the name of the file field
*/
@SuppressWarnings("unused")
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
/**
* Return the uploaded file.
*
* @return The uploaded file.
*/
public File getFile() {
return file;
}
/**
* Set the uploaded file.
*
* @param file the uploaded file
*/
@SuppressWarnings("unused")
public void setFile(File file) {
this.file = file;
}
}
}