Java tutorial
// // Copyright (C) 2010-2016 Micromata GmbH // // 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 de.micromata.genome.tpsb.httpmockup; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.security.Principal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import javax.servlet.AsyncContext; import javax.servlet.DispatcherType; import javax.servlet.ReadListener; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpUpgradeHandler; import javax.servlet.http.Part; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; /** * Extensions by r.kommer. * * <p> * Mock implementation of an HttpServletRequest object. Allows for setting most values that are likely to be of interest * (and can always be subclassed to affect others). Of key interest and perhaps not completely obvious, the way to get * request parameters into an instance of MockHttpServletRequest is to fetch the parameter map using getParameterMap() * and use the put() and putAll() methods on it. Values must be String arrays. Examples follow: * </p> * * <pre> * MockHttpServletRequest req = new MockHttpServletRequest("/foo", "/bar.action"); * req.getParameterMap().put("param1", new String[] { "value" }); * req.getParameterMap().put("param2", new String[] { "value1", "value2" }); * </pre> * * <p> * It should also be noted that unless you generate an instance of MockHttpSession (or another implementation of * HttpSession) and set it on the request, then your request will <i>never</i> have a session associated with it. * </p> * * @author Tim Fennell * @since Stripes 1.1.1 */ public class MockHttpServletRequest implements HttpServletRequest, HttpRequestMockupBase { private final Logger log = Logger.getLogger(MockHttpServletRequest.class); private byte[] requestData; private String contentType = null; private String authType; private Cookie[] cookies; private Map<String, Object> headers = new HashMap<String, Object>(); private Map<String, Object> attributes = new HashMap<String, Object>(); private Map<String, String[]> parameters = new HashMap<String, String[]>(); private String method = "POST"; private String chacarcterEncoding = CharEncoding.UTF_8; private List<Locale> locales = new ArrayList<Locale>(); private Principal userPrincipal; private Set<String> roles = new HashSet<String>(); private String forwardUrl; private List<String> includedUrls = new ArrayList<String>(); // All the bits of the URL private String protocol = "https"; private String serverName = "localhost"; private int serverPort = 8080; private String contextPath = ""; private String servletPath = ""; private String pathInfo = ""; private String queryString = ""; private MockServletContext servletContext; /** * Minimal constructor that makes sense. Requires a context path (should be the same as the name of the servlet * context, prepended with a '/') and a servlet path. E.g. new MockHttpServletRequest("/myapp", * "/actionType/foo.action"). * * @param contextPath the path of the context * @param servletPath the path of the servlet */ public MockHttpServletRequest(String contextPath, String servletPath) { this.contextPath = contextPath; this.servletPath = servletPath; } public MockHttpServletRequest() { this("/", "/"); } public MockHttpServletRequest(MockServletContext servletContext) { this(servletContext.getContextPath(), "/"); this.servletContext = servletContext; } /** Sets the auth type that will be reported by this request. */ public void setAuthType(String authType) { this.authType = authType; } /** Gets the auth type being used by this request. */ @Override public String getAuthType() { return this.authType; } /** Sets the array of cookies that will be available from the request. */ public void setCookies(Cookie[] cookies) { this.cookies = cookies; } /** Returns any cookies that are set on the request. */ @Override public Cookie[] getCookies() { return this.cookies; } /** * Allows headers to be set on the request. These will be returned by the various getXxHeader() methods. If the header * is a date header it should be set with a Long. If the header is an Int header it should be set with an Integer. */ public void addHeader(String name, Object value) { this.headers.put(name.toLowerCase(), value); } /** Gets the named header as a long. Must have been set as a long with addHeader(). */ @Override public long getDateHeader(String name) { return (Long) this.headers.get(name); } /** Returns any header as a String if it exists. */ @Override public String getHeader(String name) { if (name != null) { name = name.toLowerCase(); } Object header = this.headers.get(name); if (header != null) { return header.toString(); } else { return null; } } /** Returns an enumeration with single value of the named header, or an empty enum if no value. */ @Override public Enumeration getHeaders(String name) { String header = getHeader(name); Collection<String> values = new ArrayList<String>(); if (header != null) { values.add(header); } return Collections.enumeration(values); } /** Returns an enumeration containing all the names of headers supplied. */ @Override public Enumeration getHeaderNames() { return Collections.enumeration(headers.keySet()); } /** Gets the named header as an int. Must have been set as an Integer with addHeader(). */ @Override public int getIntHeader(String name) { return (Integer) this.headers.get(name); } /** Sets the method used by the request. Defaults to POST. */ public void setMethod(String method) { this.method = method; } /** Gets the method used by the request. Defaults to POST. */ @Override public String getMethod() { return this.method; } /** Sets the path info. Defaults to the empty string. */ @Override public void setPathInfo(String pathInfo) { this.pathInfo = pathInfo; } /** Returns the path info. Defaults to the empty string. */ @Override public String getPathInfo() { return this.pathInfo; } /** Always returns the same as getPathInfo(). */ @Override public String getPathTranslated() { return getPathInfo(); } /** Sets the context path. Defaults to the empty string. */ public void setContextPath(String contextPath) { this.contextPath = contextPath; } /** Returns the context path. Defaults to the empty string. */ @Override public String getContextPath() { if (contextPath != null && "/".equals(contextPath) == false) { return contextPath; } if (servletContext != null) { return contextPath = servletContext.getContextPath(); } return this.contextPath; } /** Sets the query string set on the request; this value is not parsed for anything. */ @Override public void setQueryString(String queryString) { this.queryString = queryString; } /** Returns the query string set on the request. */ @Override public String getQueryString() { return this.queryString; } /** Returns the name from the user principal if one exists, otherwise null. */ @Override public String getRemoteUser() { Principal p = getUserPrincipal(); return p == null ? null : p.getName(); } /** Sets the set of roles that the user is deemed to be in for the request. */ public void setRoles(Set<String> roles) { this.roles = roles; } /** Returns true if the set of roles contains the role specified, false otherwise. */ @Override public boolean isUserInRole(String role) { return this.roles.contains(role); } /** Sets the Principal for the current request. */ public void setUserPrincipal(Principal userPrincipal) { this.userPrincipal = userPrincipal; } /** Returns the Principal if one is set on the request. */ @Override public Principal getUserPrincipal() { return this.userPrincipal; } /** Returns the ID of the session if one is attached to this request. Otherwise null. */ @Override public String getRequestedSessionId() { MockHttpSession session = getMockServletContext().getSession(); if (session == null) { return null; } return session.getId(); } /** Returns the request URI as defined by the servlet spec. */ @Override public String getRequestURI() { // if (StringUtils.equals("/", this.contextPath) == true && StringUtils.startsWith(pathInfo, "/") == true) { // return pathInfo; // } return joinPath(joinPath(this.getContextPath(), this.servletPath), this.pathInfo); } String joinPath(String first, String second) { if (StringUtils.isEmpty(first) == true) { return second; } if (StringUtils.isEmpty(second) == true) { return first; } if ("/".equals(first) == true && second.startsWith("/") == true) { return second; } if (first.endsWith("/") == false && second.startsWith("/") == false) { return first + "/" + second; } return first + second; } /** Returns (an attempt at) a reconstructed URL based on it's constituent parts. */ @Override public StringBuffer getRequestURL() { return new StringBuffer().append(this.protocol).append("://").append(this.serverName).append(":") .append(this.serverPort).append(this.getContextPath()).append(this.servletPath) .append(this.pathInfo); } /** Gets the part of the path which matched the servlet. */ @Override public String getServletPath() { return this.servletPath; } @Override public void setServletPath(String servletPath) { this.servletPath = servletPath; } /** Gets the session object attached to this request. */ @Override public HttpSession getSession(boolean b) { MockHttpSession session = getMockServletContext().getSession(); if (b == false) { return session; } if (session == null) { session = new MockHttpSession(getServletContext()); getMockServletContext().setSession(session); } return session; } /** Gets the session object attached to this request. */ @Override public HttpSession getSession() { return getSession(true); } /** Always returns true. */ @Override public boolean isRequestedSessionIdValid() { return true; } /** Always returns true. */ @Override public boolean isRequestedSessionIdFromCookie() { return true; } /** Always returns false. */ @Override public boolean isRequestedSessionIdFromURL() { return false; } /** Always returns false. */ @Override public boolean isRequestedSessionIdFromUrl() { return false; } @Override public boolean authenticate(final HttpServletResponse response) throws IOException, ServletException { return false; } @Override public void login(final String username, final String password) throws ServletException { } @Override public void logout() throws ServletException { } @Override public Collection<Part> getParts() throws IOException, ServletException { return null; } @Override public Part getPart(final String name) throws IOException, ServletException { return null; } /** Gets an enumeration of all request attribute names. */ @Override public Enumeration getAttributeNames() { return Collections.enumeration(this.attributes.keySet()); } /** Gets the character encoding, defaults to UTF-8. */ @Override public String getCharacterEncoding() { return this.chacarcterEncoding; } /** Sets the character encoding that will be returned by getCharacterEncoding(). */ @Override public void setCharacterEncoding(String encoding) { this.chacarcterEncoding = encoding; } /** Gets the first value of the named parameter or null if a value does not exist. */ @Override public String getParameter(String name) { String[] values = getParameterValues(name); if (values != null && values.length > 0) { return values[0]; } return null; } /** Gets an enumeration containing all the parameter names present. */ @Override public Enumeration getParameterNames() { return Collections.enumeration(this.parameters.keySet()); } /** Returns an array of all values for a parameter, or null if the parameter does not exist. */ @Override public String[] getParameterValues(String name) { return this.parameters.get(name); } /** * Provides access to the parameter map. Note that this returns a reference to the live, modifiable parameter map. As * a result it can be used to insert parameters when constructing the request. */ @Override public Map<String, String[]> getParameterMap() { return this.parameters; } /** Sets the protocol for the request. Defaults to "https". */ public void setProtocol(String protocol) { this.protocol = protocol; } /** Gets the protocol for the request. Defaults to "https". */ @Override public String getProtocol() { return this.protocol; } /** Always returns the same as getProtocol. */ @Override public String getScheme() { return getProtocol(); } /** Sets the server name. Defaults to "localhost". */ public void setServerName(String serverName) { this.serverName = serverName; } /** Gets the server name. Defaults to "localhost". */ @Override public String getServerName() { return this.serverName; } /** Sets the server port. Defaults to 8080. */ public void setServerPort(int serverPort) { this.serverPort = serverPort; } /** Returns the server port. Defaults to 8080. */ @Override public int getServerPort() { return this.serverPort; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream(), CharEncoding.UTF_8)); } /** Aways returns "127.0.0.1". */ @Override public String getRemoteAddr() { return "127.0.0.1"; } /** Always returns "localhost". */ @Override public String getRemoteHost() { return "localhost"; } /** Adds a Locale to the set of requested locales. */ public void addLocale(Locale locale) { this.locales.add(locale); } /** Returns the preferred locale. Defaults to the system locale. */ @Override public Locale getLocale() { return getLocales().nextElement(); } /** Returns an enumeration of requested locales. Defaults to the system locale. */ @Override public Enumeration<Locale> getLocales() { if (this.locales.size() == 0) { this.locales.add(Locale.getDefault()); } return Collections.enumeration(this.locales); } /** Returns true if the protocol is set to https (default), false otherwise. */ @Override public boolean isSecure() { return this.protocol.equalsIgnoreCase("https"); } /** * Returns an instance of MockRequestDispatcher that just records what URLs are forwarded to or included. The results * can be examined later by calling getForwardUrl() and getIncludedUrls(). */ @Override public MockRequestDispatcher getRequestDispatcher(String url) { return new MockRequestDispatcher(url, servletContext); } /** Always returns the path passed in without any alteration. */ @Override public String getRealPath(String path) { return path; } /** Always returns 1088 (and yes, that was picked arbitrarily). */ @Override public int getRemotePort() { return 1088; } /** Always returns the same value as getServerName(). */ @Override public String getLocalName() { return getServerName(); } /** Always returns 127.0.0.1). */ @Override public String getLocalAddr() { return "127.0.0.1"; } /** Always returns the same value as getServerPort(). */ @Override public int getLocalPort() { return getServerPort(); } @Override public ServletContext getServletContext() { return servletContext; } public MockServletContext getMockServletContext() { return servletContext; } public void setServletContext(MockServletContext servletContext) { this.servletContext = servletContext; } @Override public AsyncContext startAsync() throws IllegalStateException { return null; } @Override public AsyncContext startAsync(final ServletRequest servletRequest, final ServletResponse servletResponse) throws IllegalStateException { return null; } @Override public boolean isAsyncStarted() { return false; } @Override public boolean isAsyncSupported() { return false; } @Override public AsyncContext getAsyncContext() { return null; } @Override public DispatcherType getDispatcherType() { return null; } /** Used by the request dispatcher to set the forward URL when a forward is invoked. */ void setForwardUrl(String url) { this.forwardUrl = url; } /** Gets the URL that was forwarded to, if a forward was processed. Null otherwise. */ public String getForwardUrl() { return this.forwardUrl; } /** Used by the request dispatcher to record that a URL was included. */ void addIncludedUrl(String url) { this.includedUrls.add(url); } /** Gets the list (potentially empty) or URLs that were included during the request. */ public List<String> getIncludedUrls() { return this.includedUrls; } @Override public Object getAttribute(String key) { Object ret = this.attributes.get(key); if (log.isDebugEnabled() == true) { log.debug("MockupHttpServletRequest.getAttribute(" + key + ") => " + ObjectUtils.toString(ret)); } return ret; } @Override public void removeAttribute(String name) { this.attributes.remove(name); if (log.isDebugEnabled() == true) { log.debug("MockupHttpServletRequest.removeAttribute(" + name + ")"); } } @Override public void setAttribute(String name, Object value) { this.attributes.put(name, value); if (log.isDebugEnabled() == true) { log.debug("MockupHttpServletRequest.setAttribute(" + name + ", " + ObjectUtils.toString(value) + ")"); } } @Override public int getContentLength() { if (requestData != null) { return requestData.length; } return -1; } @Override public String getContentType() { return contentType; } @Override public ServletInputStream getInputStream() throws IOException { if (requestData == null) { return null; } final ByteArrayInputStream bis = new ByteArrayInputStream(requestData); return new ServletInputStream() { @Override public int read() throws IOException { return bis.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } private String joinpath(String first, String second) { if (StringUtils.isBlank(first) == true) { return second; } if (StringUtils.isBlank(second) == true) { return first; } return first + "/" + second; } @Override public String toString() { StringBuilder sb = new StringBuilder(); String p = joinpath(joinpath(contextPath, servletPath), pathInfo) + StringUtils.defaultString(queryString); sb.append(method).append(" ").append(p).append(" HTTP/1.1\n"); for (Map.Entry<String, Object> me : headers.entrySet()) { sb.append(me.getKey()).append(": ").append(me.getValue()).append("\n"); } sb.append("\n"); if (this.requestData != null) { sb.append(new String(this.requestData)); } return sb.toString(); } public byte[] getRequestData() { return requestData; } public void setRequestData(byte[] requestData) { this.requestData = requestData; } public void setContentType(String contentType) { this.contentType = contentType; } @Override public String changeSessionId() { return null; } @Override public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException { return null; } @Override public long getContentLengthLong() { return 0; } public void addRequestParameter(String k, String v) { String[] params = parameters.get(k); if (params == null) { parameters.put(k, new String[] { v }); } else { parameters.put(k, ArrayUtils.add(params, v)); } } }