diff --git a/build-spring-framework/resources/changelog.txt b/build-spring-framework/resources/changelog.txt index f8a95e3d04..84fe4e1194 100644 --- a/build-spring-framework/resources/changelog.txt +++ b/build-spring-framework/resources/changelog.txt @@ -23,6 +23,7 @@ Changes in version 3.1 RC2 (2011-11-15) * Add ignoreDefaultModelOnRedirect attribute to * Add methods to UriComponentsBuilder for replacing the path or the query. * Add ServletUriComponentsBuilder to build a UriComponents instance starting with a ServletRequest +* Keep contentType field and Content-Type header in sync in MockHttpServletRequest and MockHttpServletResponse Changes in version 3.1 RC1 (2011-10-11) --------------------------------------- diff --git a/org.springframework.orm/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java b/org.springframework.orm/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java index 9c57a5046a..f3b0151971 100644 --- a/org.springframework.orm/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/org.springframework.orm/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -92,6 +92,11 @@ public class MockHttpServletRequest implements HttpServletRequest { */ public static final String DEFAULT_REMOTE_HOST = "localhost"; + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String CHARSET_PREFIX = "charset="; + + private boolean active = true; @@ -295,6 +300,18 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setCharacterEncoding(String characterEncoding) { this.characterEncoding = characterEncoding; + if (this.contentType != null) { + String type = removeCharset(this.contentType); + setContentType(type); + } + } + + private String removeCharset(String contentType) { + int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (index != -1) { + contentType = contentType.substring(0, contentType.lastIndexOf(';', index)); + } + return contentType; } public void setContent(byte[] content) { @@ -307,6 +324,17 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setContentType(String contentType) { this.contentType = contentType; + if (contentType != null) { + int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (charsetIndex != -1) { + String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); + this.characterEncoding = encoding; + } + else if (this.characterEncoding != null) { + this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding; + } + doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true); + } } public String getContentType() { @@ -642,11 +670,19 @@ public class MockHttpServletRequest implements HttpServletRequest { * @see #getDateHeader * @see #getIntHeader */ - @SuppressWarnings("rawtypes") public void addHeader(String name, Object value) { + if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) { + setContentType((String) value); + return; + } + doAddHeaderValue(name, value, false); + } + + @SuppressWarnings("rawtypes") + private void doAddHeaderValue(String name, Object value, boolean replace) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); Assert.notNull(value, "Header value must not be null"); - if (header == null) { + if (header == null || replace) { header = new HeaderValueHolder(); this.headers.put(name, header); } diff --git a/org.springframework.orm/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java b/org.springframework.orm/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java index 2c84f96b8a..5c1070b30e 100644 --- a/org.springframework.orm/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/org.springframework.orm/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -50,6 +50,10 @@ public class MockHttpServletResponse implements HttpServletResponse { private static final String CHARSET_PREFIX = "charset="; + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String CONTENT_LENGTH_HEADER = "Content-Length"; + //--------------------------------------------------------------------- // ServletResponse properties @@ -61,6 +65,8 @@ public class MockHttpServletResponse implements HttpServletResponse { private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; + private boolean charset = false; + private final ByteArrayOutputStream content = new ByteArrayOutputStream(); private final ServletOutputStream outputStream = new ResponseServletOutputStream(this.content); @@ -133,6 +139,19 @@ public class MockHttpServletResponse implements HttpServletResponse { public void setCharacterEncoding(String characterEncoding) { this.characterEncoding = characterEncoding; + this.charset = true; + if (this.contentType != null) { + String type = removeCharset(this.contentType); + setContentType(type); + } + } + + private String removeCharset(String contentType) { + int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (index != -1) { + contentType = contentType.substring(0, contentType.lastIndexOf(';', index)); + } + return contentType; } public String getCharacterEncoding() { @@ -171,6 +190,7 @@ public class MockHttpServletResponse implements HttpServletResponse { public void setContentLength(int contentLength) { this.contentLength = contentLength; + doAddHeaderValue(CONTENT_LENGTH_HEADER, contentLength, true); } public int getContentLength() { @@ -183,8 +203,12 @@ public class MockHttpServletResponse implements HttpServletResponse { int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); if (charsetIndex != -1) { String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); - setCharacterEncoding(encoding); + this.characterEncoding = encoding; } + else if (this.charset) { + this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding; + } + doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true); } } @@ -424,12 +448,32 @@ public class MockHttpServletResponse implements HttpServletResponse { } private void setHeaderValue(String name, Object value) { + if (setSpecialHeader(name, value)) { + return; + } doAddHeaderValue(name, value, true); } private void addHeaderValue(String name, Object value) { + if (setSpecialHeader(name, value)) { + return; + } doAddHeaderValue(name, value, false); } + + private boolean setSpecialHeader(String name, Object value) { + if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) { + setContentType((String) value); + return true; + } + else if (CONTENT_LENGTH_HEADER.equalsIgnoreCase(name)) { + setContentLength(Integer.parseInt((String) value)); + return true; + } + else { + return false; + } + } private void doAddHeaderValue(String name, Object value, boolean replace) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); diff --git a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java index c340d83809..1134d0261f 100644 --- a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -92,6 +92,11 @@ public class MockHttpServletRequest implements HttpServletRequest { */ public static final String DEFAULT_REMOTE_HOST = "localhost"; + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String CHARSET_PREFIX = "charset="; + + private boolean active = true; @@ -295,6 +300,18 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setCharacterEncoding(String characterEncoding) { this.characterEncoding = characterEncoding; + if (this.contentType != null) { + String type = removeCharset(this.contentType); + setContentType(type); + } + } + + private String removeCharset(String contentType) { + int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (index != -1) { + contentType = contentType.substring(0, contentType.lastIndexOf(';', index)); + } + return contentType; } public void setContent(byte[] content) { @@ -307,6 +324,17 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setContentType(String contentType) { this.contentType = contentType; + if (contentType != null) { + int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (charsetIndex != -1) { + String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); + this.characterEncoding = encoding; + } + else if (this.characterEncoding != null) { + this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding; + } + doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true); + } } public String getContentType() { @@ -642,11 +670,19 @@ public class MockHttpServletRequest implements HttpServletRequest { * @see #getDateHeader * @see #getIntHeader */ - @SuppressWarnings("rawtypes") public void addHeader(String name, Object value) { + if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) { + setContentType((String) value); + return; + } + doAddHeaderValue(name, value, false); + } + + @SuppressWarnings("rawtypes") + private void doAddHeaderValue(String name, Object value, boolean replace) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); Assert.notNull(value, "Header value must not be null"); - if (header == null) { + if (header == null || replace) { header = new HeaderValueHolder(); this.headers.put(name, header); } diff --git a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java index 2c84f96b8a..08b11d9dda 100644 --- a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -50,6 +50,9 @@ public class MockHttpServletResponse implements HttpServletResponse { private static final String CHARSET_PREFIX = "charset="; + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String CONTENT_LENGTH_HEADER = "Content-Length"; //--------------------------------------------------------------------- // ServletResponse properties @@ -60,6 +63,8 @@ public class MockHttpServletResponse implements HttpServletResponse { private boolean writerAccessAllowed = true; private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; + + private boolean charset = false; private final ByteArrayOutputStream content = new ByteArrayOutputStream(); @@ -133,8 +138,21 @@ public class MockHttpServletResponse implements HttpServletResponse { public void setCharacterEncoding(String characterEncoding) { this.characterEncoding = characterEncoding; + this.charset = true; + if (this.contentType != null) { + String type = removeCharset(this.contentType); + setContentType(type); + } } - + + private String removeCharset(String contentType) { + int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (index != -1) { + contentType = contentType.substring(0, contentType.lastIndexOf(';', index)); + } + return contentType; + } + public String getCharacterEncoding() { return this.characterEncoding; } @@ -171,6 +189,7 @@ public class MockHttpServletResponse implements HttpServletResponse { public void setContentLength(int contentLength) { this.contentLength = contentLength; + doAddHeaderValue(CONTENT_LENGTH_HEADER, contentLength, true); } public int getContentLength() { @@ -183,8 +202,12 @@ public class MockHttpServletResponse implements HttpServletResponse { int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); if (charsetIndex != -1) { String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); - setCharacterEncoding(encoding); + this.characterEncoding = encoding; } + else if (this.charset) { + this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding; + } + doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true); } } @@ -424,12 +447,32 @@ public class MockHttpServletResponse implements HttpServletResponse { } private void setHeaderValue(String name, Object value) { + if (setSpecialHeader(name, value)) { + return; + } doAddHeaderValue(name, value, true); } private void addHeaderValue(String name, Object value) { + if (setSpecialHeader(name, value)) { + return; + } doAddHeaderValue(name, value, false); } + + private boolean setSpecialHeader(String name, Object value) { + if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) { + setContentType((String) value); + return true; + } + else if (CONTENT_LENGTH_HEADER.equalsIgnoreCase(name)) { + setContentLength(Integer.parseInt((String) value)); + return true; + } + else { + return false; + } + } private void doAddHeaderValue(String name, Object value, boolean replace) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); diff --git a/org.springframework.test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java b/org.springframework.test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java index 78f6325a03..509333204e 100644 --- a/org.springframework.test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java +++ b/org.springframework.test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2006 the original author or authors. + * 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. @@ -25,9 +25,75 @@ import junit.framework.TestCase; /** * @author Rick Evans * @author Mark Fisher + * @author Rossen Stoyanchev */ public class MockHttpServletRequestTests extends TestCase { + public void testSetContentType() { + String contentType = "test/plain"; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setContentType(contentType); + assertEquals(contentType, request.getContentType()); + assertEquals(contentType, request.getHeader("Content-Type")); + assertNull(request.getCharacterEncoding()); + } + + public void testSetContentTypeUTF8() { + String contentType = "test/plain;charset=UTF-8"; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setContentType(contentType); + assertEquals(contentType, request.getContentType()); + assertEquals(contentType, request.getHeader("Content-Type")); + assertEquals("UTF-8", request.getCharacterEncoding()); + } + + public void testSetContentTypeHeader() { + String contentType = "test/plain"; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Content-Type", contentType); + assertEquals(contentType, request.getContentType()); + assertEquals(contentType, request.getHeader("Content-Type")); + assertNull(request.getCharacterEncoding()); + } + + public void testSetContentTypeHeaderUTF8() { + String contentType = "test/plain;charset=UTF-8"; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Content-Type", contentType); + assertEquals(contentType, request.getContentType()); + assertEquals(contentType, request.getHeader("Content-Type")); + assertEquals("UTF-8", request.getCharacterEncoding()); + } + + public void testSetCharacterEncoding() { + String contentType = "test/plain;charset=UTF-8"; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setContentType("test/plain"); + request.setCharacterEncoding("UTF-8"); + assertEquals(contentType, request.getContentType()); + assertEquals(contentType, request.getHeader("Content-Type")); + assertEquals("UTF-8", request.getCharacterEncoding()); + } + + public void testSetCharacterEncodingOppositeOrder() { + String contentType = "test/plain;charset=UTF-8"; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setCharacterEncoding("UTF-8"); + request.setContentType("test/plain"); + assertEquals(contentType, request.getContentType()); + assertEquals(contentType, request.getHeader("Content-Type")); + assertEquals("UTF-8", request.getCharacterEncoding()); + } + + public void testReplaceCharacterEncoding() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setContentType("test/plain;charset=ISO-8859-1"); + request.setCharacterEncoding("UTF-8"); + assertEquals("test/plain;charset=UTF-8", request.getContentType()); + assertEquals("test/plain;charset=UTF-8", request.getHeader("Content-Type")); + assertEquals("UTF-8", request.getCharacterEncoding()); + } + public void testHttpHeaderNameCasingIsPreserved() throws Exception { String headerName = "Header1"; MockHttpServletRequest request = new MockHttpServletRequest(); diff --git a/org.springframework.test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java b/org.springframework.test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java index 9b2869649d..e282de6894 100644 --- a/org.springframework.test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java +++ b/org.springframework.test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * 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. @@ -27,23 +27,95 @@ import org.springframework.web.util.WebUtils; /** * @author Juergen Hoeller * @author Rick Evans + * @author Rossen Stoyanchev * @since 19.02.2006 */ public class MockHttpServletResponseTests extends TestCase { public void testSetContentTypeWithNoEncoding() { + String contentType = "test/plain"; MockHttpServletResponse response = new MockHttpServletResponse(); - response.setContentType("test/plain"); + response.setContentType(contentType); assertEquals("Character encoding should be the default", WebUtils.DEFAULT_CHARACTER_ENCODING, response.getCharacterEncoding()); + assertEquals("Content-Type header not set", contentType, response.getHeader("Content-Type")); } public void testSetContentTypeWithUTF8() { + String contentType = "test/plain; charset=UTF-8"; MockHttpServletResponse response = new MockHttpServletResponse(); - response.setContentType("test/plain; charset=UTF-8"); + response.setContentType(contentType); assertEquals("Character encoding should be 'UTF-8'", "UTF-8", response.getCharacterEncoding()); + assertEquals("Content-Type header not set", contentType, response.getHeader("Content-Type")); + } + + public void testContentTypeHeaderWithNoEncoding() { + String contentType = "test/plain"; + MockHttpServletResponse response = new MockHttpServletResponse(); + response.addHeader("Content-Type", contentType); + assertEquals("contentType field not set", contentType, response.getContentType()); + + response = new MockHttpServletResponse(); + response.setHeader("Content-Type", contentType); + assertEquals("contentType field not set", contentType, response.getContentType()); } + public void testContentTypeHeaderWithUTF8() { + String contentType = "test/plain; charset=UTF-8"; + MockHttpServletResponse response = new MockHttpServletResponse(); + response.addHeader("Content-Type", contentType); + assertEquals("contentType field not set", contentType, response.getContentType()); + assertEquals("Character encoding should be 'UTF-8'", "UTF-8", response.getCharacterEncoding()); + assertEquals("Content-Type header not set", contentType, response.getHeader("Content-Type")); + + response = new MockHttpServletResponse(); + response.setHeader("Content-Type", contentType); + assertEquals("contentType field not set", contentType, response.getContentType()); + assertEquals("Character encoding should be 'UTF-8'", "UTF-8", response.getCharacterEncoding()); + assertEquals("Content-Type header not set", contentType, response.getHeader("Content-Type")); + } + + public void testSetCharacterEncoding() { + MockHttpServletResponse response = new MockHttpServletResponse(); + response.setContentType("test/plain"); + response.setCharacterEncoding("UTF-8"); + assertEquals("Character encoding not set", "UTF-8", response.getCharacterEncoding()); + assertEquals("contentType field not set", "test/plain;charset=UTF-8", response.getContentType()); + assertEquals("Content-Type header not set", "test/plain;charset=UTF-8", response.getHeader("Content-Type")); + } + + public void testSetCharacterEncodingOppositeOrder() { + MockHttpServletResponse response = new MockHttpServletResponse(); + response.setCharacterEncoding("UTF-8"); + response.setContentType("test/plain"); + assertEquals("Character encoding not set", "UTF-8", response.getCharacterEncoding()); + assertEquals("contentType field not set", "test/plain;charset=UTF-8", response.getContentType()); + assertEquals("Content-Type header not set", "test/plain;charset=UTF-8", response.getHeader("Content-Type")); + } + + public void testReplaceCharacterEncoding() { + MockHttpServletResponse response = new MockHttpServletResponse(); + response.setContentType("test/plain;charset=ISO-8859-1"); + response.setCharacterEncoding("UTF-8"); + assertEquals("Character encoding not set", "UTF-8", response.getCharacterEncoding()); + assertEquals("contentType field not set", "test/plain;charset=UTF-8", response.getContentType()); + assertEquals("Content-Type header not set", "test/plain;charset=UTF-8", response.getHeader("Content-Type")); + } + + public void testContentLength() { + MockHttpServletResponse response = new MockHttpServletResponse(); + response.setContentLength(66); + assertEquals("Content length field not set", 66, response.getContentLength()); + assertEquals("Content-Length header not set", "66", response.getHeader("Content-Length")); + } + + public void testContentLengthHeader() { + MockHttpServletResponse response = new MockHttpServletResponse(); + response.addHeader("Content-Length", "66"); + assertEquals("Content length field not set", 66, response.getContentLength()); + assertEquals("Content-Length header not set", "66", response.getHeader("Content-Length")); + } + public void testHttpHeaderNameCasingIsPreserved() throws Exception { final String headerName = "Header1"; diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java b/org.springframework.web.servlet/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java index fd599c2d23..952f3a5137 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -101,6 +101,10 @@ public class MockHttpServletRequest implements HttpServletRequest { */ public static final String DEFAULT_REMOTE_HOST = "localhost"; + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String CHARSET_PREFIX = "charset="; + private boolean active = true; @@ -306,6 +310,18 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setCharacterEncoding(String characterEncoding) { this.characterEncoding = characterEncoding; + if (this.contentType != null) { + String type = removeCharset(this.contentType); + setContentType(type); + } + } + + private String removeCharset(String contentType) { + int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (index != -1) { + contentType = contentType.substring(0, contentType.lastIndexOf(';', index)); + } + return contentType; } public void setContent(byte[] content) { @@ -318,6 +334,17 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setContentType(String contentType) { this.contentType = contentType; + if (contentType != null) { + int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (charsetIndex != -1) { + String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); + this.characterEncoding = encoding; + } + else if (this.characterEncoding != null) { + this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding; + } + doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true); + } } public String getContentType() { @@ -650,9 +677,18 @@ public class MockHttpServletRequest implements HttpServletRequest { * @see #getIntHeader */ public void addHeader(String name, Object value) { + if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) { + setContentType((String) value); + return; + } + doAddHeaderValue(name, value, false); + } + + @SuppressWarnings("rawtypes") + private void doAddHeaderValue(String name, Object value, boolean replace) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); Assert.notNull(value, "Header value must not be null"); - if (header == null) { + if (header == null || replace) { header = new HeaderValueHolder(); this.headers.put(name, header); } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java b/org.springframework.web.servlet/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java index 9f55159e7a..4ad4e08d0b 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -55,6 +55,10 @@ public class MockHttpServletResponse implements HttpServletResponse { private static final String CHARSET_PREFIX = "charset="; + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String CONTENT_LENGTH_HEADER = "Content-Length"; + //--------------------------------------------------------------------- // ServletResponse properties @@ -66,6 +70,8 @@ public class MockHttpServletResponse implements HttpServletResponse { private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; + private boolean charset = false; + private final ByteArrayOutputStream content = new ByteArrayOutputStream(); private final ServletOutputStream outputStream = new ResponseServletOutputStream(this.content); @@ -138,6 +144,19 @@ public class MockHttpServletResponse implements HttpServletResponse { public void setCharacterEncoding(String characterEncoding) { this.characterEncoding = characterEncoding; + this.charset = true; + if (this.contentType != null) { + String type = removeCharset(this.contentType); + setContentType(type); + } + } + + private String removeCharset(String contentType) { + int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (index != -1) { + contentType = contentType.substring(0, contentType.lastIndexOf(';', index)); + } + return contentType; } public String getCharacterEncoding() { @@ -176,6 +195,7 @@ public class MockHttpServletResponse implements HttpServletResponse { public void setContentLength(int contentLength) { this.contentLength = contentLength; + doAddHeaderValue(CONTENT_LENGTH_HEADER, contentLength, true); } public int getContentLength() { @@ -188,8 +208,12 @@ public class MockHttpServletResponse implements HttpServletResponse { int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); if (charsetIndex != -1) { String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); - setCharacterEncoding(encoding); + this.characterEncoding = encoding; } + else if (this.charset) { + this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding; + } + doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true); } } @@ -391,12 +415,32 @@ public class MockHttpServletResponse implements HttpServletResponse { } private void setHeaderValue(String name, Object value) { + if (setSpecialHeader(name, value)) { + return; + } doAddHeaderValue(name, value, true); } private void addHeaderValue(String name, Object value) { + if (setSpecialHeader(name, value)) { + return; + } doAddHeaderValue(name, value, false); } + + private boolean setSpecialHeader(String name, Object value) { + if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) { + setContentType((String) value); + return true; + } + else if (CONTENT_LENGTH_HEADER.equalsIgnoreCase(name)) { + setContentLength(Integer.parseInt((String) value)); + return true; + } + else { + return false; + } + } private void doAddHeaderValue(String name, Object value, boolean replace) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolverTests.java index 231ce95b67..efab531147 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolverTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/RequestPartMethodArgumentResolverTests.java @@ -52,7 +52,6 @@ import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartHttpServletRequest; import org.springframework.mock.web.MockPart; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; -import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; @@ -235,7 +234,6 @@ public class RequestPartMethodArgumentResolverTests { private void testResolveArgument(SimpleBean argValue, MethodParameter parameter) throws IOException, Exception { MediaType contentType = MediaType.TEXT_PLAIN; - multipartRequest.addHeader("Content-Type", contentType.toString()); expect(messageConverter.canRead(SimpleBean.class, contentType)).andReturn(true); expect(messageConverter.read(eq(SimpleBean.class), isA(RequestPartServletServerHttpRequest.class))).andReturn(argValue); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/json/MappingJacksonJsonViewTest.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/json/MappingJacksonJsonViewTest.java index 7b0a8e0c7d..7699019543 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/json/MappingJacksonJsonViewTest.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/json/MappingJacksonJsonViewTest.java @@ -92,7 +92,7 @@ public class MappingJacksonJsonViewTest { assertEquals("no-cache, no-store, max-age=0", response.getHeader("Cache-Control")); assertNotNull(response.getHeader("Expires")); - assertEquals(MappingJacksonJsonView.DEFAULT_CONTENT_TYPE, response.getContentType()); + assertEquals(MappingJacksonJsonView.DEFAULT_CONTENT_TYPE + ";charset=UTF-8", response.getContentType()); String jsonResult = response.getContentAsString(); assertTrue(jsonResult.length() > 0); diff --git a/org.springframework.web/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java b/org.springframework.web/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java index fd599c2d23..952f3a5137 100644 --- a/org.springframework.web/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/org.springframework.web/src/test/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -101,6 +101,10 @@ public class MockHttpServletRequest implements HttpServletRequest { */ public static final String DEFAULT_REMOTE_HOST = "localhost"; + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String CHARSET_PREFIX = "charset="; + private boolean active = true; @@ -306,6 +310,18 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setCharacterEncoding(String characterEncoding) { this.characterEncoding = characterEncoding; + if (this.contentType != null) { + String type = removeCharset(this.contentType); + setContentType(type); + } + } + + private String removeCharset(String contentType) { + int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (index != -1) { + contentType = contentType.substring(0, contentType.lastIndexOf(';', index)); + } + return contentType; } public void setContent(byte[] content) { @@ -318,6 +334,17 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setContentType(String contentType) { this.contentType = contentType; + if (contentType != null) { + int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (charsetIndex != -1) { + String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); + this.characterEncoding = encoding; + } + else if (this.characterEncoding != null) { + this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding; + } + doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true); + } } public String getContentType() { @@ -650,9 +677,18 @@ public class MockHttpServletRequest implements HttpServletRequest { * @see #getIntHeader */ public void addHeader(String name, Object value) { + if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) { + setContentType((String) value); + return; + } + doAddHeaderValue(name, value, false); + } + + @SuppressWarnings("rawtypes") + private void doAddHeaderValue(String name, Object value, boolean replace) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); Assert.notNull(value, "Header value must not be null"); - if (header == null) { + if (header == null || replace) { header = new HeaderValueHolder(); this.headers.put(name, header); } diff --git a/org.springframework.web/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java b/org.springframework.web/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java index 973ef58059..ed2f8e23ff 100644 --- a/org.springframework.web/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/org.springframework.web/src/test/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -54,6 +54,10 @@ public class MockHttpServletResponse implements HttpServletResponse { private static final String CHARSET_PREFIX = "charset="; + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private static final String CONTENT_LENGTH_HEADER = "Content-Length"; + //--------------------------------------------------------------------- // ServletResponse properties @@ -65,6 +69,8 @@ public class MockHttpServletResponse implements HttpServletResponse { private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; + private boolean charset = false; + private final ByteArrayOutputStream content = new ByteArrayOutputStream(); private final ServletOutputStream outputStream = new ResponseServletOutputStream(this.content); @@ -137,6 +143,19 @@ public class MockHttpServletResponse implements HttpServletResponse { public void setCharacterEncoding(String characterEncoding) { this.characterEncoding = characterEncoding; + this.charset = true; + if (this.contentType != null) { + String type = removeCharset(this.contentType); + setContentType(type); + } + } + + private String removeCharset(String contentType) { + int index = contentType.toLowerCase().indexOf(CHARSET_PREFIX); + if (index != -1) { + contentType = contentType.substring(0, contentType.lastIndexOf(';', index)); + } + return contentType; } public String getCharacterEncoding() { @@ -175,6 +194,7 @@ public class MockHttpServletResponse implements HttpServletResponse { public void setContentLength(int contentLength) { this.contentLength = contentLength; + doAddHeaderValue(CONTENT_LENGTH_HEADER, contentLength, true); } public int getContentLength() { @@ -187,8 +207,12 @@ public class MockHttpServletResponse implements HttpServletResponse { int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); if (charsetIndex != -1) { String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); - setCharacterEncoding(encoding); + this.characterEncoding = encoding; } + else if (this.charset) { + this.contentType += ";" + CHARSET_PREFIX + this.characterEncoding; + } + doAddHeaderValue(CONTENT_TYPE_HEADER, this.contentType, true); } } @@ -390,12 +414,32 @@ public class MockHttpServletResponse implements HttpServletResponse { } private void setHeaderValue(String name, Object value) { + if (setSpecialHeader(name, value)) { + return; + } doAddHeaderValue(name, value, true); } private void addHeaderValue(String name, Object value) { + if (setSpecialHeader(name, value)) { + return; + } doAddHeaderValue(name, value, false); } + + private boolean setSpecialHeader(String name, Object value) { + if (CONTENT_TYPE_HEADER.equalsIgnoreCase(name)) { + setContentType((String) value); + return true; + } + else if (CONTENT_LENGTH_HEADER.equalsIgnoreCase(name)) { + setContentLength(Integer.parseInt((String) value)); + return true; + } + else { + return false; + } + } private void doAddHeaderValue(String name, Object value, boolean replace) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);