wicket.protocol.http.MockHttpServletRequest.java Source code

Java tutorial

Introduction

Here is the source code for wicket.protocol.http.MockHttpServletRequest.java

Source

/*
 * $Id: MockHttpServletRequest.java 5844 2006-05-24 20:53:56 +0000 (Wed, 24 May
 * 2006) joco01 $ $Revision: 6483 $ $Date: 2006-05-24 20:53:56 +0000 (Wed, 24
 * May 2006) $
 * 
 * ==============================================================================
 * Licensed 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 wicket.protocol.http;

import java.io.BufferedReader;
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
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.StringTokenizer;

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.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import wicket.Application;
import wicket.Component;
import wicket.IRedirectListener;
import wicket.IResourceListener;
import wicket.Page;
import wicket.PageMap;
import wicket.markup.html.form.Form;
import wicket.markup.html.form.FormComponent;
import wicket.markup.html.form.IFormSubmitListener;
import wicket.markup.html.form.IOnChangeListener;
import wicket.markup.html.link.BookmarkablePageLink;
import wicket.markup.html.link.ILinkListener;
import wicket.protocol.http.request.WebRequestCodingStrategy;
import wicket.util.lang.Classes;
import wicket.util.value.ValueMap;

/**
 * Mock servlet request. Implements all of the methods from the standard
 * HttpServletRequest class plus helper methods to aid setting up a request.
 * 
 * @author Chris Turner
 */
public class MockHttpServletRequest implements HttpServletRequest {
    /** Logging object */
    private static final Log log = LogFactory.getLog(MockHttpServletRequest.class);

    /** The application */
    private final Application application;

    private final ValueMap attributes = new ValueMap();

    private String authType;

    private String characterEncoding;

    private final ServletContext context;

    private final List<Cookie> cookies = new ArrayList<Cookie>();

    private final Map<String, List<String>> headers = new HashMap<String, List<String>>();

    private String method;

    private final ValueMap parameters = new ValueMap();

    private String path;

    private final HttpSession session;

    private String url;

    /**
     * Create the request using the supplied session object.
     * 
     * @param application
     *            The application that this request is for
     * @param session
     *            The session object
     * @param context
     *            The current servlet context
     */
    public MockHttpServletRequest(final Application application, final HttpSession session,
            final ServletContext context) {
        this.application = application;
        this.session = session;
        this.context = context;
        initialize();
    }

    /**
     * Add a new cookie.
     * 
     * @param cookie
     *            The cookie
     */
    public void addCookie(final Cookie cookie) {
        cookies.add(cookie);
    }

    /**
     * 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);
    }

    /**
     * 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;
    }

    /**
     * Always returns -1 for this implementation.
     * 
     * @return -1
     */
    public int getContentLength() {
        return -1;
    }

    /**
     * Content type is always null in this implementation.
     * 
     * @return Always null
     */
    public String getContentType() {
        return null;
    }

    /**
     * Get the context path. For this mock implementation the name of the
     * application is always returned.
     * 
     * @return The context path
     */
    public String getContextPath() {
        return "/" + application.getName();
    }

    /**
     * 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 l = headers.get(name);
        if (l == null || l.size() < 1) {
            return null;
        } else {
            return (String) 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 getHeaders(final String name) {
        List<String> list = headers.get(name);
        if (list == null) {
            list = new ArrayList<String>();
        }
        return Collections.enumeration(list);
    }

    /**
     * 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 input stream
     * @throws IOException
     *             If an I/O related problem occurs
     */
    public ServletInputStream getInputStream() throws IOException {
        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.
     * 
     * @return The method
     */
    public String getMethod() {
        return 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) {
        return parameters.getString(name);
    }

    /**
     * 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 path;
    }

    /**
     * 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 String value = parameters.getString(name);
                    buf.append(URLEncoder.encode(name, "UTF-8"));
                    buf.append('=');
                    buf.append(URLEncoder.encode(value, "UTF-8"));
                    if (iterator.hasNext()) {
                        buf.append('&');
                    }
                }
            } 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.
     */
    @Deprecated
    public String getRealPath(String name) {
        return context.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";
    }

    /**
     * Get the name of the remote user from the REMOTE_USER header.
     * 
     * @return The name of the remote user
     */
    public String getRemoteUser() {
        return getHeader("REMOTE_USER");
    }

    /**
     * Return a dummy dispatcher that just records that dispatch has occured
     * without actually doing anything.
     * 
     * @param name
     *            The name to dispatch to
     * @return The dispatcher
     */
    public RequestDispatcher getRequestDispatcher(String name) {
        return context.getRequestDispatcher(name);
    }

    /**
     * Get the requested session id. Always returns the id of the current
     * session.
     * 
     * @return The session id
     */
    public String getRequestedSessionId() {
        return session.getId();
    }

    /**
     * Get the request url. Always return the path value.
     * 
     * @return The oath value
     */
    public String getRequestURI() {
        if (url == null) {
            return "";
        }
        return url;
    }

    /**
     * Try to build a rough URL.
     * 
     * @return The url
     */
    public StringBuffer getRequestURL() {
        final StringBuffer buf = new StringBuffer();
        buf.append("http://localhost");
        buf.append(getContextPath());
        if (getPathInfo() != null) {
            buf.append(getPathInfo());
        }

        final String query = getQueryString();
        if (query != null) {
            buf.append('?');
            buf.append(query);
        }
        return buf;
    }

    /**
     * Get the scheme.
     * 
     * @return Always http
     */
    public String getScheme() {
        return "http";
    }

    /**
     * Get the server name.
     * 
     * @return Always localhost
     */
    public String getServerName() {
        return "localhost";
    }

    /**
     * Get the server port.
     * 
     * @return Always 80
     */
    public int getServerPort() {
        return 80;
    }

    /**
     * The servlet path may either be the application name or /. For test
     * purposes we always return the servlet name.
     * 
     * @return The servlet path
     */
    public String getServletPath() {
        return getContextPath();
    }

    /**
     * Get the sessions.
     * 
     * @return The session
     */
    public HttpSession getSession() {
        return session;
    }

    /**
     * Get the session.
     * 
     * @param b
     *            Ignored, there is always a session
     * @return The session
     */
    public HttpSession getSession(boolean b) {
        return session;
    }

    /**
     * Get the user principal.
     * 
     * @return A user principal
     */
    public Principal getUserPrincipal() {
        final String user = getRemoteUser();
        if (user == null) {
            return null;
        } else {
            return new Principal() {
                public String getName() {
                    return user;
                }
            };
        }
    }

    /**
     * Reset the request back to a default state.
     */
    public void initialize() {
        authType = null;
        method = "post";
        cookies.clear();
        setDefaultHeaders();
        path = null;
        characterEncoding = "UTF-8";
        parameters.clear();
        attributes.clear();
    }

    /**
     * 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 false;
    }

    /**
     * NOT IMPLEMENTED.
     * 
     * @param name
     *            The role name
     * @return Always false
     */
    public boolean isUserInRole(String name) {
        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 {
        this.characterEncoding = encoding;
    }

    /**
     * Set the cookies.
     * 
     * @param theCookies
     *            The cookies
     */
    public void setCookies(final Cookie[] theCookies) {
        cookies.clear();
        for (Cookie element : theCookies) {
            cookies.add(element);
        }
    }

    /**
     * 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);
    }

    /**
     * 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 / charater
     * 
     * @param path
     */
    public void setPath(final String path) {
        this.path = path;
    }

    /**
     * Set the complete url for this request. The url will be analized.
     * 
     * @param url
     */
    public void setURL(String url) {
        if (url.startsWith("http://")) {
            int index = url.indexOf("/", 7);
            url = url.substring(index);
        }
        this.url = url;
        if (url.startsWith(getContextPath())) {
            url = url.substring(getContextPath().length());
        }
        if (url.startsWith(getServletPath())) {
            url = url.substring(getServletPath().length());
        }

        int index = url.indexOf("?");
        if (index == -1) {
            path = url;
        } else {
            path = url.substring(0, index);

            String queryString = url.substring(index + 1);
            StringTokenizer st = new StringTokenizer(queryString, "&");
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                int tmp = token.indexOf("=");
                if (tmp != -1) {
                    setParameter(token.substring(0, tmp), token.substring(tmp + 1));
                }
            }

        }
    }

    /**
     * Initialise the request parameters to point to the given bookmarkable
     * page.
     * 
     * @param page
     *            The page to point to
     * @param params
     *            Additional parameters
     */
    public void setRequestToBookmarkablePage(final Page page, final Map<String, String> params) {
        parameters.putAll(params);
        parameters.put(WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME, page.getClass().getName());
    }

    /**
     * Initialise the request parameters to point to the given component.
     * 
     * @param component
     *            The component
     */
    public void setRequestToComponent(final Component component) {
        final PageMap pageMap = component.getPage().getPageMap();
        final String pageMapName = pageMap.isDefault() ? "" : pageMap.getName();
        if (component instanceof BookmarkablePageLink) {
            final Class clazz = ((BookmarkablePageLink) component).getPageClass();
            parameters.put(WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME,
                    pageMapName + ':' + clazz.getName());
        } else {
            int version = component.getPage().getCurrentVersionNumber();
            Class clazz = null;
            if (component instanceof IRedirectListener) {
                clazz = IRedirectListener.class;
            } else if (component instanceof IResourceListener) {
                clazz = IResourceListener.class;
            } else if (component instanceof IFormSubmitListener) {
                clazz = IFormSubmitListener.class;
            } else if (component instanceof ILinkListener) {
                clazz = ILinkListener.class;
            } else if (component instanceof IOnChangeListener) {
                clazz = IOnChangeListener.class;
            } else {
                throw new IllegalArgumentException(
                        "The component class doesn't seem to implement any of the known *Listener Interfaces: "
                                + component.getClass());
            }

            parameters.put(WebRequestCodingStrategy.INTERFACE_PARAMETER_NAME,
                    pageMapName + ':' + component.getPath() + ':' + (version == 0 ? "" : "" + version) + ':'
                            + Classes.simpleName(clazz));
        }
    }

    /**
     * Initialise the request parameters to point to the given form component.
     * The additional map should contain mappings between individual components
     * that appear in the form and the string value that should be submitted for
     * each of these components.
     * 
     * @param form
     *            The for to send the request to
     * @param values
     *            The values for each of the form components
     */
    public void setRequestToFormComponent(final Form form, final Map<Component, String> values) {
        setRequestToComponent(form);

        final Map<String, Component> valuesApplied = new HashMap<String, Component>();
        form.visitChildren(new Component.IVisitor() {
            public Object component(final Component component) {
                if (component instanceof FormComponent) {
                    String value = values.get(component);
                    if (value != null) {
                        parameters.put(((FormComponent) component).getInputName(), values.get(component));
                        valuesApplied.put(component.getId(), component);
                    }
                }
                return CONTINUE_TRAVERSAL;
            }
        });

        if (values.size() != valuesApplied.size()) {
            Map<Component, String> diff = new HashMap<Component, String>();
            diff.putAll(values);

            Iterator<String> iter = valuesApplied.keySet().iterator();
            while (iter.hasNext()) {
                diff.remove(iter.next());
            }

            log.error("Parameter mismatch: didn't find all components referenced in parameter 'values': "
                    + diff.keySet());
        }
    }

    /**
     * Initialise the request parameters from the given redirect string that
     * redirects back to a particular component for display.
     * 
     * @param redirect
     *            The redirect string to display from
     */
    public void setRequestToRedirectString(final String redirect) {
        parameters.clear();

        final String paramPart = redirect.substring(redirect.indexOf('?') + 1);
        final String[] paramTuples = paramPart.split("&");
        for (String element : paramTuples) {
            final String[] bits = element.split("=");
            if (bits.length == 2) {
                try {
                    parameters.put(URLDecoder.decode(bits[0], "UTF-8"), URLDecoder.decode(bits[1], "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    // Should never happen
                }
            }
        }
    }

    /**
     * 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.getDefault();
        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");
    }
}