INT-963 DefaultInboundRequestMapper now returns a MultiValueMap when creating a payload from HTTP request parameters. That means that values in the Map are now Lists of Strings rather than String arrays.

This commit is contained in:
Mark Fisher
2010-01-25 03:01:11 +00:00
parent 8db7e1cd6a
commit 8550cc67b0
3 changed files with 109 additions and 40 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -20,7 +20,9 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -36,6 +38,8 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.integration.core.Message;
import org.springframework.integration.message.MessageBuilder;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
@@ -47,8 +51,10 @@ import org.springframework.web.multipart.MultipartResolver;
* <ul>
* <li>For a GET request or a POST request with a Content-Type of
* "application/x-www-form-urlencoded", the parameter Map will be copied as the
* payload. The map's keys will be Strings, and the values will be String arrays
* as described for {@link ServletRequest#getParameterMap()}.</li>
* payload. The map will be an instance of {@link MultiValueMap} where the keys are
* Strings and the values are Lists of Strings. Those Lists are populated from the
* String array values of the original request parameter Map as described for the
* {@link ServletRequest#getParameterMap()} method.</li>
* <li>If a MultipartResolver has been provided, and a multipart request is
* detected, the multipart file content will be converted to String for any
* "text" content type, or byte arrays otherwise.</li>
@@ -231,8 +237,7 @@ public class DefaultInboundRequestMapper implements InboundRequestMapper {
@SuppressWarnings("unchecked")
private Object createPayloadFromParameterMap(HttpServletRequest request) {
Map<String, String[]> parameterMap = new HashMap<String, String[]>(request.getParameterMap());
return Collections.unmodifiableMap(parameterMap);
return new UnmodifiableRequestParameterMap(request.getParameterMap());
}
private Object createPayloadFromTextContent(HttpServletRequest request) throws IOException {
@@ -289,4 +294,61 @@ public class DefaultInboundRequestMapper implements InboundRequestMapper {
builder.setHeader(HttpHeaders.USER_PRINCIPAL, request.getUserPrincipal());
}
/**
* Map class that extends {@link LinkedMultiValueMap} and implements Serializable.
* The contents of the map are unmodifiable, so calling any modification operation
* (e.g. put, add, or remove) will result in an UnsupportedOperationException.
*/
private static class UnmodifiableRequestParameterMap
extends LinkedMultiValueMap<String, String> implements Serializable {
UnmodifiableRequestParameterMap(Map<String, String[]> parameters) {
for (Map.Entry<String, String[]> entry : parameters.entrySet()) {
super.put(entry.getKey(), Arrays.asList(entry.getValue()));
}
}
@Override
public void add(String key, String value) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public List<String> put(String key, List<String> value) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(Map<? extends String, ? extends List<String>> m) {
throw new UnsupportedOperationException();
}
@Override
public List<String> remove(Object key) {
throw new UnsupportedOperationException();
}
@Override
public void set(String key, String value) {
throw new UnsupportedOperationException();
}
@Override
public void setAll(Map<String, String> values) {
throw new UnsupportedOperationException();
}
@Override
public Map<String, String> toSingleValueMap() {
return Collections.unmodifiableMap(super.toSingleValueMap());
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -16,30 +16,6 @@
package org.springframework.integration.http;
import org.easymock.IAnswer;
import org.easymock.classextension.ConstructorArgs;
import org.junit.Before;
import org.junit.Test;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.core.MessageHeaders;
import org.springframework.integration.message.StringMessage;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.View;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
@@ -54,6 +30,35 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.easymock.IAnswer;
import org.easymock.classextension.ConstructorArgs;
import org.junit.Before;
import org.junit.Test;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.core.MessageHeaders;
import org.springframework.integration.message.StringMessage;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.web.servlet.View;
/**
* @author Alex Peters
*/
@@ -125,8 +130,8 @@ public class HttpInboundEndpointTests {
final Map<?, ?> msgParams = (Map<?, ?>) ((Message) getCurrentArguments()[0]).getPayload();
assertThat(msgParams.size(), is(sourceParams.size()));
for (String key : sourceParams.keySet()) {
assertThat((String[]) msgParams.get(key),
is(new String[] { sourceParams.get(key) }));
assertThat((List<String>) msgParams.get(key),
is(Collections.singletonList(sourceParams.get(key))));
}
return true;
}
@@ -228,10 +233,11 @@ public class HttpInboundEndpointTests {
new IAnswer<Boolean>() {
@SuppressWarnings("unchecked")
public Boolean answer() throws Throwable {
Map<String, String> payloadMap = (Map<String, String>) ((Message) getCurrentArguments()[0]).getPayload();
MultiValueMap<String, String> payloadMap = (MultiValueMap<String, String>)
((Message) getCurrentArguments()[0]).getPayload();
for (String key : sourceParams.keySet()) {
assertThat(payloadMap.get(key),
is((Object) new String[] { sourceParams.get(key) }));
is(Collections.singletonList(sourceParams.get(key))));
}
return true;
}
@@ -339,6 +345,7 @@ public class HttpInboundEndpointTests {
}
@Test
@SuppressWarnings("unchecked")
public void handleRequest_expectReplyWithView_responseDirectedToView() throws Exception {
setupEndpointAsMock(ANY_STRING_PAYLOAD);
View view = createMock(View.class);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -25,7 +25,6 @@ import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
@@ -42,6 +41,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.MultiValueMap;
/**
* @author Mark Fisher
@@ -75,12 +75,12 @@ public class HttpInboundChannelAdapterParserTests {
Message<?> message = requests.receive(0);
assertNotNull(message);
Object payload = message.getPayload();
assertTrue(payload instanceof Map);
Map<String, String[]> map = (Map<String, String[]>) payload;
assertTrue(payload instanceof MultiValueMap);
MultiValueMap<String, String> map = (MultiValueMap<String, String>) payload;
assertEquals(1, map.size());
assertEquals("foo", map.keySet().iterator().next());
assertEquals(1, map.get("foo").length);
assertEquals("bar", map.get("foo")[0]);
assertEquals(1, map.get("foo").size());
assertEquals("bar", map.getFirst("foo"));
}
@Test