提交 f0c397e4 编写于 作者: J Juergen Hoeller

Comprehensive Servlet 3.1 support in spring-web and spring-test

Issue: SPR-14467
上级 177f4ec3
......@@ -55,6 +55,7 @@ configure(allprojects) { project ->
ext.jettyVersion = "9.3.10.v20160621"
ext.jodaVersion = "2.9.4"
ext.jpaVersion = "2.1.1"
ext.jspVersion = "2.3.2-b02"
ext.jtaVersion = "1.2"
ext.junitVersion = "4.12"
ext.junitJupiterVersion = '5.0.0-M1'
......@@ -69,6 +70,7 @@ configure(allprojects) { project ->
ext.reactorNettyVersion = '2.5.0.BUILD-SNAPSHOT'
ext.rxJavaVersion = '1.1.6'
ext.romeVersion = "1.6.0"
ext.servletVersion = "3.1.0"
ext.slf4jVersion = "1.7.21"
ext.snakeyamlVersion = "1.17"
ext.snifferVersion = "1.15"
......@@ -77,6 +79,7 @@ configure(allprojects) { project ->
ext.tomcatVersion = "8.5.3"
ext.tyrusVersion = "1.13"
ext.undertowVersion = "1.4.0.CR3"
ext.websocketVersion = "1.1"
ext.woodstoxVersion = "5.0.2"
ext.xmlunitVersion = "1.6"
ext.xstreamVersion = "1.4.9"
......@@ -516,7 +519,7 @@ project("spring-messaging") {
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("javax.inject:javax.inject-tck:1")
testCompile("javax.servlet:javax.servlet-api:3.1.0")
testCompile("javax.servlet:javax.servlet-api:${servletVersion}")
testCompile("javax.validation:validation-api:${beanvalVersion}")
testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}")
testCompile("org.apache.activemq:activemq-broker:5.8.0")
......@@ -674,9 +677,9 @@ project("spring-web") {
compile(project(":spring-beans")) // for MultipartFilter
compile(project(":spring-context"))
compile(project(":spring-core"))
provided "javax.servlet:javax.servlet-api:3.1.0"
provided "javax.servlet:javax.servlet-api:${servletVersion}"
optional(project(":spring-oxm")) // for MarshallingHttpMessageConverter
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
optional("javax.servlet.jsp:javax.servlet.jsp-api:${jspVersion}")
optional("javax.el:javax.el-api:2.2.5")
optional("javax.faces:javax.faces-api:2.2")
optional("javax.validation:validation-api:${beanvalVersion}")
......@@ -750,7 +753,7 @@ project("spring-orm") {
exclude group: 'org.eclipse.persistence', module: 'javax.persistence'
}
optional("org.hibernate:hibernate-core:${hibernate5Version}")
optional("javax.servlet:javax.servlet-api:3.0.1")
optional("javax.servlet:javax.servlet-api:${servletVersion}")
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
......@@ -768,10 +771,10 @@ project("spring-webmvc") {
compile(files(project(":spring-core").objenesisRepackJar))
compile(project(":spring-expression"))
compile(project(":spring-web"))
provided("javax.servlet:javax.servlet-api:3.1.0")
provided("javax.servlet:javax.servlet-api:${servletVersion}")
optional(project(":spring-context-support")) // for FreeMarker support
optional(project(":spring-oxm")) // for MarshallingView
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
optional("javax.servlet.jsp:javax.servlet.jsp-api:${jspVersion}")
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
optional("org.apache.poi:poi:${poiVersion}")
optional("org.apache.poi:poi-ooxml:${poiVersion}")
......@@ -838,7 +841,7 @@ project("spring-web-reactive") {
compile "org.reactivestreams:reactive-streams:1.0.0"
compile "io.projectreactor:reactor-core:${reactorCoreVersion}"
optional(project(":spring-context-support")) // for FreeMarker support
provided "javax.servlet:javax.servlet-api:3.1.0"
provided "javax.servlet:javax.servlet-api:${servletVersion}"
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
optional("org.freemarker:freemarker:${freemarkerVersion}")
optional "org.apache.httpcomponents:httpclient:4.5.1" // Needed to run Javadoc without error
......@@ -868,8 +871,8 @@ project("spring-websocket") {
compile(project(":spring-web"))
optional(project(":spring-messaging"))
optional(project(":spring-webmvc"))
optional("javax.servlet:javax.servlet-api:3.1.0")
optional("javax.websocket:javax.websocket-api:1.0")
optional("javax.servlet:javax.servlet-api:${servletVersion}")
optional("javax.websocket:javax.websocket-api:${websocketVersion}")
optional("org.apache.tomcat:tomcat-websocket:${tomcatVersion}") {
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
......@@ -926,14 +929,14 @@ project("spring-test") {
optional("org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}")
optional("org.testng:testng:${testngVersion}")
optional("javax.inject:javax.inject:1")
optional("javax.servlet:javax.servlet-api:3.0.1")
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
optional("javax.servlet:javax.servlet-api:${servletVersion}")
optional("javax.servlet.jsp:javax.servlet.jsp-api:${jspVersion}")
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
optional("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
}
optional("javax.el:javax.el-api:2.2.5")
optional("javax.websocket:javax.websocket-api:1.0")
optional("javax.websocket:javax.websocket-api:${websocketVersion}")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
optional("org.hamcrest:hamcrest-core:${hamcrestVersion}")
......@@ -1131,7 +1134,7 @@ configure(rootProject) {
testCompile(project(":spring-test"))
testCompile(project(":spring-tx"))
testCompile(project(":spring-web"))
testCompile("javax.servlet:javax.servlet-api:3.0.1")
testCompile("javax.servlet:javax.servlet-api:${servletVersion}")
testCompile("javax.inject:javax.inject:1")
testCompile("javax.resource:javax.resource-api:${jcaVersion}")
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
......
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
......@@ -18,6 +18,7 @@ package org.springframework.mock.web;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import org.springframework.util.Assert;
......@@ -36,6 +37,8 @@ public class DelegatingServletInputStream extends ServletInputStream {
private final InputStream sourceStream;
private boolean finished = false;
/**
* Create a DelegatingServletInputStream for the given source stream.
......@@ -56,7 +59,11 @@ public class DelegatingServletInputStream extends ServletInputStream {
@Override
public int read() throws IOException {
return this.sourceStream.read();
int data = this.sourceStream.read();
if (data == -1) {
this.finished = true;
}
return data;
}
@Override
......@@ -65,4 +72,19 @@ public class DelegatingServletInputStream extends ServletInputStream {
this.sourceStream.close();
}
@Override
public boolean isFinished() {
return this.finished;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
throw new UnsupportedOperationException();
}
}
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
......@@ -19,6 +19,7 @@ package org.springframework.mock.web;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import org.springframework.util.Assert;
......@@ -71,4 +72,14 @@ public class DelegatingServletOutputStream extends ServletOutputStream {
this.targetStream.close();
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener writeListener) {
throw new UnsupportedOperationException();
}
}
......@@ -51,6 +51,7 @@ 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.springframework.http.MediaType;
......@@ -68,7 +69,7 @@ import org.springframework.util.StringUtils;
* is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale}
* or {@link #setPreferredLocales}.
*
* <p>As of Spring Framework 4.0, this set of mocks is designed on a Servlet 3.0 baseline.
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 3.1 baseline.
*
* @author Juergen Hoeller
* @author Rod Johnson
......@@ -1216,4 +1217,9 @@ public class MockHttpServletRequest implements HttpServletRequest {
return result;
}
@Override
public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
throw new UnsupportedOperationException();
}
}
......@@ -45,9 +45,7 @@ import org.springframework.web.util.WebUtils;
/**
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
*
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline.
* Beyond that, {@code MockHttpServletResponse} is also compatible with Servlet
* 3.1's {@code setContentLengthLong()} method.
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 3.1 baseline.
*
* @author Juergen Hoeller
* @author Rod Johnson
......
......@@ -676,4 +676,9 @@ public class MockServletContext implements ServletContext {
throw new UnsupportedOperationException();
}
@Override
public String getVirtualServerName() {
throw new UnsupportedOperationException();
}
}
......@@ -42,6 +42,9 @@ import org.springframework.web.util.WebUtils;
* (e.g. a {@link org.springframework.web.servlet.View}) is still rendered.
* As such, this filter only saves bandwidth, not server performance.
*
* <p><b>NOTE:</b> As of Spring Framework 5.0, this filter uses request/response
* decorators built on the Servlet 3.1 API.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Juergen Hoeller
......
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
......@@ -39,6 +39,7 @@ import org.springframework.http.HttpMethod;
* and allows this content to be retrieved via a {@link #getContentAsByteArray() byte array}.
*
* <p>Used e.g. by {@link org.springframework.web.filter.AbstractRequestLoggingFilter}.
* Note: As of Spring Framework 5.0, this wrapper is built on the Servlet 3.1 API.
*
* @author Juergen Hoeller
* @author Brian Clozel
......@@ -166,7 +167,6 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
return this.cachedContent.toByteArray();
}
// TODO: this is no longer usable in Servlet 3.0 environment
private class ContentCachingInputStream extends ServletInputStream {
......@@ -197,7 +197,7 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
@Override
public void setReadListener(ReadListener readListener) {
this.setReadListener(readListener);
this.is.setReadListener(readListener);
}
}
......
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
......@@ -34,6 +34,7 @@ import org.springframework.util.FastByteArrayOutputStream;
* and allows this content to be retrieved via a {@link #getContentAsByteArray() byte array}.
*
* <p>Used e.g. by {@link org.springframework.web.filter.ShallowEtagHeaderFilter}.
* Note: As of Spring Framework 5.0, this wrapper is built on the Servlet 3.1 API.
*
* @author Juergen Hoeller
* @since 4.1.3
......@@ -228,7 +229,6 @@ public class ContentCachingResponseWrapper extends HttpServletResponseWrapper {
}
}
// TODO: this is no longer usable in Servlet 3.0 environment
private class ResponseServletOutputStream extends ServletOutputStream {
......
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
......@@ -37,6 +37,8 @@ public class DelegatingServletInputStream extends ServletInputStream {
private final InputStream sourceStream;
private boolean finished = false;
/**
* Create a DelegatingServletInputStream for the given source stream.
......@@ -57,7 +59,11 @@ public class DelegatingServletInputStream extends ServletInputStream {
@Override
public int read() throws IOException {
return this.sourceStream.read();
int data = this.sourceStream.read();
if (data == -1) {
this.finished = true;
}
return data;
}
@Override
......@@ -68,16 +74,17 @@ public class DelegatingServletInputStream extends ServletInputStream {
@Override
public boolean isFinished() {
throw new UnsupportedOperationException();
return this.finished;
}
@Override
public boolean isReady() {
throw new UnsupportedOperationException();
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
throw new UnsupportedOperationException();
}
}
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
......@@ -74,11 +74,12 @@ public class DelegatingServletOutputStream extends ServletOutputStream {
@Override
public boolean isReady() {
throw new UnsupportedOperationException();
return true;
}
@Override
public void setWriteListener(WriteListener writeListener) {
throw new UnsupportedOperationException();
}
}
......@@ -69,7 +69,7 @@ import org.springframework.util.StringUtils;
* is {@link Locale#ENGLISH}. This value can be changed via {@link #addPreferredLocale}
* or {@link #setPreferredLocales}.
*
* <p>As of Spring Framework 4.0, this set of mocks is designed on a Servlet 3.0 baseline.
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 3.1 baseline.
*
* @author Juergen Hoeller
* @author Rod Johnson
......@@ -329,9 +329,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
* throwing an IllegalStateException if not active anymore.
*/
protected void checkActive() throws IllegalStateException {
if (!this.active) {
throw new IllegalStateException("Request is not active anymore");
}
Assert.state(this.active, "Request is not active anymore");
}
......@@ -808,9 +806,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
@Override
public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
if (!this.asyncSupported) {
throw new IllegalStateException("Async not supported");
}
Assert.state(this.asyncSupported, "Async not supported");
this.asyncStarted = true;
this.asyncContext = new MockAsyncContext(request, response);
return this.asyncContext;
......
......@@ -45,9 +45,7 @@ import org.springframework.web.util.WebUtils;
/**
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
*
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline.
* Beyond that, {@code MockHttpServletResponse} is also compatible with Servlet
* 3.1's {@code setContentLengthLong()} method.
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 3.1 baseline.
*
* @author Juergen Hoeller
* @author Rod Johnson
......@@ -154,7 +152,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
* <p>If {@code false}, {@link #getCharacterEncoding()} will return a default encoding value.
*/
public boolean isCharset() {
return charset;
return this.charset;
}
@Override
......@@ -181,17 +179,13 @@ public class MockHttpServletResponse implements HttpServletResponse {
@Override
public ServletOutputStream getOutputStream() {
if (!this.outputStreamAccessAllowed) {
throw new IllegalStateException("OutputStream access not allowed");
}
Assert.state(this.outputStreamAccessAllowed, "OutputStream access not allowed");
return this.outputStream;
}
@Override
public PrintWriter getWriter() throws UnsupportedEncodingException {
if (!this.writerAccessAllowed) {
throw new IllegalStateException("Writer access not allowed");
}
Assert.state(this.writerAccessAllowed, "Writer access not allowed");
if (this.writer == null) {
Writer targetWriter = (this.characterEncoding != null ?
new OutputStreamWriter(this.content, this.characterEncoding) : new OutputStreamWriter(this.content));
......@@ -275,9 +269,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
@Override
public void resetBuffer() {
if (isCommitted()) {
throw new IllegalStateException("Cannot reset buffer - response is already committed");
}
Assert.state(!isCommitted(), "Cannot reset buffer - response is already committed");
this.content.reset();
}
......@@ -456,9 +448,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
@Override
public void sendError(int status, String errorMessage) throws IOException {
if (isCommitted()) {
throw new IllegalStateException("Cannot set error status - response is already committed");
}
Assert.state(!isCommitted(), "Cannot set error status - response is already committed");
this.status = status;
this.errorMessage = errorMessage;
setCommitted(true);
......@@ -466,18 +456,14 @@ public class MockHttpServletResponse implements HttpServletResponse {
@Override
public void sendError(int status) throws IOException {
if (isCommitted()) {
throw new IllegalStateException("Cannot set error status - response is already committed");
}
Assert.state(!isCommitted(), "Cannot set error status - response is already committed");
this.status = status;
setCommitted(true);
}
@Override
public void sendRedirect(String url) throws IOException {
if (isCommitted()) {
throw new IllegalStateException("Cannot send redirect - response is already committed");
}
Assert.state(!isCommitted(), "Cannot send redirect - response is already committed");
Assert.notNull(url, "Redirect URL must not be null");
setHeader(LOCATION_HEADER, url);
setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
......@@ -627,10 +613,8 @@ public class MockHttpServletResponse implements HttpServletResponse {
public String getIncludedUrl() {
int count = this.includedUrls.size();
if (count > 1) {
throw new IllegalStateException(
"More than 1 URL included - check getIncludedUrls instead: " + this.includedUrls);
}
Assert.state(count <= 1,
() -> "More than 1 URL included - check getIncludedUrls instead: " + this.includedUrls);
return (count == 1 ? this.includedUrls.get(0) : null);
}
......
......@@ -355,9 +355,8 @@ public class MockServletContext implements ServletContext {
@Override
public RequestDispatcher getRequestDispatcher(String path) {
if (!path.startsWith("/")) {
throw new IllegalArgumentException("RequestDispatcher path at ServletContext level must start with '/'");
}
Assert.isTrue(path.startsWith("/"),
() -> "RequestDispatcher path [" + path + "] at ServletContext level must start with '/'");
return new MockRequestDispatcher(path);
}
......@@ -545,11 +544,6 @@ public class MockServletContext implements ServletContext {
}
}
@Override
public String getVirtualServerName() {
throw new UnsupportedOperationException();
}
public Set<String> getDeclaredRoles() {
return Collections.unmodifiableSet(this.declaredRoles);
}
......@@ -682,4 +676,9 @@ public class MockServletContext implements ServletContext {
throw new UnsupportedOperationException();
}
@Override
public String getVirtualServerName() {
throw new UnsupportedOperationException();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册