/*
* Copyright 2002-2011 the original author or authors.
*
* 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 org.springframework.test.web.server;
import java.net.URI;
import java.security.Principal;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/**
* A command class to build and execute a request. Use methods on {@link MockMvc} to obtain a new {@link
* DefaultMockHttpServletRequestBuilder} instance.
*/
public class DefaultMockHttpServletRequestBuilder implements MockHttpServletRequestBuilder {
private final URI uri;
private final HttpMethod method;
private final MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
private final MultiValueMap<String, Object> headers = new LinkedMultiValueMap<String, Object>();
private String contentType;
private byte[] requestBody;
private Cookie[] cookies;
private Locale locale;
private String characterEncoding;
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
private final Map<String, Object> sessionAttributes = new LinkedHashMap<String, Object>();
private Principal principal;
/** Use methods on {@link MockMvc} to obtain a new instance. */
DefaultMockHttpServletRequestBuilder(URI uri, HttpMethod method) {
this.uri = uri;
this.method = method;
}
public DefaultMockHttpServletRequestBuilder param(String name, String value, String... values) {
addToMultiValueMap(parameters, name, value, values);
return this;
}
public DefaultMockHttpServletRequestBuilder accept(MediaType mediaType, MediaType... mediaTypes) {
addToMultiValueMap(headers, "Accept", mediaType, mediaTypes);
return this;
}
public DefaultMockHttpServletRequestBuilder contentType(MediaType mediaType) {
Assert.notNull(mediaType, "'mediaType' must not be null");
this.contentType = mediaType.toString();
headers.set("Content-Type", mediaType);
return this;
}
public DefaultMockHttpServletRequestBuilder body(byte[] requestBody) {
this.requestBody = requestBody;
return this;
}
public DefaultMockHttpServletRequestBuilder header(String name, Object value, Object... values) {
addToMultiValueMap(headers, name, value, values);
return this;
}
public DefaultMockHttpServletRequestBuilder cookie(Cookie cookie, Cookie... cookies) {
Assert.notNull(cookie, "'cookie' must not be null");
if (cookies == null) {
this.cookies = new Cookie[]{cookie};
}
else {
this.cookies = new Cookie[1 + cookies.length];
this.cookies[0] = cookie;
System.arraycopy(cookies, 0, this.cookies, 1, cookies.length);
}
return this;
}
public DefaultMockHttpServletRequestBuilder locale(Locale locale) {
this.locale = locale;
return this;
}
public DefaultMockHttpServletRequestBuilder characterEncoding(String characterEncoding) {
this.characterEncoding = characterEncoding;
return this;
}
public DefaultMockHttpServletRequestBuilder requestAttr(String name, Object value) {
Assert.hasLength(name, "'name' must not be empty");
Assert.notNull(value, "'value' must not be null");
attributes.put(name, value);
return this;
}
public DefaultMockHttpServletRequestBuilder sessionAttr(String name, Object value) {
Assert.hasLength(name, "'name' must not be empty");
Assert.notNull(value, "'value' must not be null");
sessionAttributes.put(name, value);
return this;
}
public DefaultMockHttpServletRequestBuilder principal(Principal principal) {
Assert.notNull(principal, "'principal' must not be null");
this.principal = principal;
return this;
}
public MockHttpServletRequest buildRequest(ServletContext servletContext) {
MockHttpServletRequest request = createServletRequest(servletContext);
request.setMethod(method.name());
request.setRequestURI(uri.toString());
for (String name : parameters.keySet()) {
for (String value : parameters.get(name)) {
request.addParameter(name, value);
}
}
for (String name : headers.keySet()) {
for (Object value : headers.get(name)) {
request.addHeader(name, value);
}
}
for (String name : attributes.keySet()) {
request.setAttribute(name, attributes.get(name));
}
for (String name : sessionAttributes.keySet()) {
request.getSession().setAttribute(name, sessionAttributes.get(name));
}
request.setContentType(contentType);
request.setContent(requestBody);
request.setCookies(cookies);
request.setCharacterEncoding(characterEncoding);
request.setUserPrincipal(principal);
if (locale != null) {
request.addPreferredLocale(locale);
}
return request;
}
/**
* Creates a new {@link MockHttpServletRequest} based on the given {@link ServletContext}. Can be overridden in
* subclasses.
*
* @param servletContext the servlet context to use
* @return the created mock request
*/
protected MockHttpServletRequest createServletRequest(ServletContext servletContext) {
return new MockHttpServletRequest(servletContext);
}
private static <T> void addToMultiValueMap(MultiValueMap<String, T> map, String name, T value, T[] values) {
Assert.hasLength(name, "'name' must not be empty");
Assert.notNull(value, "'value' must not be null");
map.add(name, value);
if (values != null) {
map.get(name).addAll(Arrays.asList(values));
}
}
}