Use Gradle test fixture support for spring-web
See gh-23550
This commit is contained in:
@@ -46,6 +46,7 @@ import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
|
||||
import org.springframework.protobuf.Msg;
|
||||
import org.springframework.protobuf.SecondMsg;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
/**
|
||||
* Test scenarios for data buffer leaks.
|
||||
|
||||
@@ -37,10 +37,10 @@ import org.springframework.core.codec.CharSequenceEncoder;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.ISO_8859_1;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
@@ -32,9 +32,9 @@ import org.springframework.core.testfixture.io.buffer.AbstractLeakCheckingTests;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ import org.springframework.core.testfixture.io.buffer.AbstractLeakCheckingTests;
|
||||
import org.springframework.core.testfixture.io.buffer.DataBufferTestUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.http.codec;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
@XmlRootElement
|
||||
public class Pojo {
|
||||
|
||||
private String foo;
|
||||
|
||||
private String bar;
|
||||
|
||||
public Pojo() {
|
||||
}
|
||||
|
||||
public Pojo(String foo, String bar) {
|
||||
this.foo = foo;
|
||||
this.bar = bar;
|
||||
}
|
||||
|
||||
public String getFoo() {
|
||||
return this.foo;
|
||||
}
|
||||
|
||||
public void setFoo(String foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public String getBar() {
|
||||
return this.bar;
|
||||
}
|
||||
|
||||
public void setBar(String bar) {
|
||||
this.bar = bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof Pojo) {
|
||||
Pojo other = (Pojo) o;
|
||||
return this.foo.equals(other.foo) && this.bar.equals(other.bar);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * foo.hashCode() + bar.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Pojo[foo='" + this.foo + "\'" + ", bar='" + this.bar + "\']";
|
||||
}
|
||||
}
|
||||
@@ -30,14 +30,14 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.http.MediaType.TEXT_PLAIN;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get;
|
||||
import static org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest.get;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ResourceHttpMessageWriter}.
|
||||
|
||||
@@ -30,7 +30,8 @@ import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.io.buffer.AbstractLeakCheckingTests;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ import org.springframework.core.testfixture.io.buffer.DataBufferTestUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.core.ResolvableType.forClass;
|
||||
|
||||
@@ -27,9 +27,9 @@ import reactor.core.publisher.Flux;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.codec.AbstractDecoderTests;
|
||||
import org.springframework.http.codec.Pojo;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -28,10 +28,10 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.io.buffer.AbstractLeakCheckingTests;
|
||||
import org.springframework.core.testfixture.io.buffer.DataBufferTestUtils;
|
||||
import org.springframework.http.codec.Pojo;
|
||||
import org.springframework.http.codec.ServerSentEvent;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -39,10 +39,10 @@ import org.springframework.core.codec.DecodingException;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.codec.AbstractDecoderTests;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.Pojo;
|
||||
import org.springframework.http.codec.json.JacksonViewBean.MyJacksonView1;
|
||||
import org.springframework.http.codec.json.JacksonViewBean.MyJacksonView3;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
@@ -36,12 +36,12 @@ import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.testfixture.codec.AbstractEncoderTests;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.Pojo;
|
||||
import org.springframework.http.codec.ServerSentEvent;
|
||||
import org.springframework.http.codec.json.JacksonViewBean.MyJacksonView1;
|
||||
import org.springframework.http.codec.json.JacksonViewBean.MyJacksonView3;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -27,9 +27,9 @@ import reactor.core.publisher.Flux;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.codec.AbstractDecoderTests;
|
||||
import org.springframework.http.codec.Pojo;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.core.ResolvableType.forClass;
|
||||
|
||||
@@ -31,10 +31,10 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.codec.AbstractEncoderTests;
|
||||
import org.springframework.core.testfixture.io.buffer.DataBufferTestUtils;
|
||||
import org.springframework.http.codec.Pojo;
|
||||
import org.springframework.http.codec.ServerSentEvent;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.core.io.buffer.DataBufferUtils.release;
|
||||
|
||||
@@ -40,9 +40,9 @@ import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.MultipartBodyBuilder;
|
||||
import org.springframework.http.codec.ClientCodecConfigurer;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
@@ -42,9 +42,9 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.MultipartBodyBuilder;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.mock.http.client.reactive.test.MockClientHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.testfixture.http.client.reactive.MockClientHttpRequest;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
|
||||
@@ -32,13 +32,13 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.io.buffer.AbstractLeakCheckingTests;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.Pojo;
|
||||
import org.springframework.http.codec.xml.jaxb.XmlRootElement;
|
||||
import org.springframework.http.codec.xml.jaxb.XmlRootElementWithName;
|
||||
import org.springframework.http.codec.xml.jaxb.XmlRootElementWithNameAndNamespace;
|
||||
import org.springframework.http.codec.xml.jaxb.XmlType;
|
||||
import org.springframework.http.codec.xml.jaxb.XmlTypeWithName;
|
||||
import org.springframework.http.codec.xml.jaxb.XmlTypeWithNameAndNamespace;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.testfixture.codec.AbstractEncoderTests;
|
||||
import org.springframework.core.testfixture.xml.XmlContent;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.Pojo;
|
||||
import org.springframework.web.testfixture.xml.Pojo;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -31,8 +31,8 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
@@ -28,8 +28,8 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.http.server.reactive;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.time.Duration;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.http.server.reactive.bootstrap.JettyHttpServer;
|
||||
import org.springframework.http.server.reactive.bootstrap.ReactorHttpServer;
|
||||
import org.springframework.http.server.reactive.bootstrap.TomcatHttpServer;
|
||||
import org.springframework.http.server.reactive.bootstrap.UndertowHttpServer;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.HttpServerErrorException;
|
||||
|
||||
public abstract class AbstractHttpHandlerIntegrationTests {
|
||||
|
||||
/**
|
||||
* Custom JUnit Jupiter extension that handles exceptions thrown by test methods.
|
||||
*
|
||||
* <p>If the test method throws an {@link HttpServerErrorException}, this
|
||||
* extension will throw an {@link AssertionError} that wraps the
|
||||
* {@code HttpServerErrorException} using the
|
||||
* {@link HttpServerErrorException#getResponseBodyAsString() response body}
|
||||
* as the failure message.
|
||||
*
|
||||
* <p>This mechanism provides an actually meaningful failure message if the
|
||||
* test fails due to an {@code AssertionError} on the server.
|
||||
*/
|
||||
@RegisterExtension
|
||||
TestExecutionExceptionHandler serverErrorToAssertionErrorConverter = (context, throwable) -> {
|
||||
if (throwable instanceof HttpServerErrorException) {
|
||||
HttpServerErrorException ex = (HttpServerErrorException) throwable;
|
||||
String responseBody = ex.getResponseBodyAsString();
|
||||
if (StringUtils.hasText(responseBody)) {
|
||||
String prefix = AssertionError.class.getName() + ": ";
|
||||
if (responseBody.startsWith(prefix)) {
|
||||
responseBody = responseBody.substring(prefix.length());
|
||||
}
|
||||
throw new AssertionError(responseBody, ex);
|
||||
}
|
||||
}
|
||||
// Else throw as-is in order to comply with the contract of TestExecutionExceptionHandler.
|
||||
throw throwable;
|
||||
};
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected HttpServer server;
|
||||
|
||||
protected int port;
|
||||
|
||||
|
||||
protected void startServer(HttpServer httpServer) throws Exception {
|
||||
this.server = httpServer;
|
||||
this.server.setHandler(createHttpHandler());
|
||||
this.server.afterPropertiesSet();
|
||||
this.server.start();
|
||||
|
||||
// Set dynamically chosen port
|
||||
this.port = this.server.getPort();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void stopServer() {
|
||||
if (this.server != null) {
|
||||
this.server.stop();
|
||||
this.port = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected abstract HttpHandler createHttpHandler();
|
||||
|
||||
|
||||
/**
|
||||
* Return an interval stream of N number of ticks and buffer the emissions
|
||||
* to avoid back pressure failures (e.g. on slow CI server).
|
||||
*
|
||||
* <p>Use this method as follows:
|
||||
* <ul>
|
||||
* <li>Tests that verify N number of items followed by verifyOnComplete()
|
||||
* should set the number of emissions to N.
|
||||
* <li>Tests that verify N number of items followed by thenCancel() should
|
||||
* set the number of buffered to an arbitrary number greater than N.
|
||||
* </ul>
|
||||
*/
|
||||
public static Flux<Long> testInterval(Duration period, int count) {
|
||||
return Flux.interval(period).take(count).onBackpressureBuffer(count);
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@ParameterizedTest(name = "[{index}] {0}")
|
||||
@MethodSource("org.springframework.http.server.reactive.AbstractHttpHandlerIntegrationTests#httpServers()")
|
||||
// public for Kotlin
|
||||
public @interface ParameterizedHttpServerTest {
|
||||
}
|
||||
|
||||
static Stream<HttpServer> httpServers() {
|
||||
return Stream.of(
|
||||
new JettyHttpServer(),
|
||||
new ReactorHttpServer(),
|
||||
new TomcatHttpServer(),
|
||||
new UndertowHttpServer()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,8 +28,9 @@ import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
@@ -27,8 +27,9 @@ import org.springframework.http.HttpCookie;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -23,8 +23,9 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -23,9 +23,10 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import reactor.core.publisher.Flux;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.NettyDataBufferFactory;
|
||||
import org.springframework.core.testfixture.io.buffer.LeakAwareDataBufferFactory;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -32,13 +32,14 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.codec.multipart.FilePart;
|
||||
import org.springframework.http.codec.multipart.FormFieldPart;
|
||||
import org.springframework.http.codec.multipart.Part;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.HttpWebHandlerAdapter;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -28,8 +28,9 @@ import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -23,8 +23,9 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.test.DelegatingServletInputStream;
|
||||
import org.springframework.mock.web.test.MockAsyncContext;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.testfixture.servlet.DelegatingServletInputStream;
|
||||
import org.springframework.web.testfixture.servlet.MockAsyncContext;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
@@ -33,9 +33,9 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.http.server.reactive.bootstrap.ReactorHttpsServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.ReactorHttpsServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -26,8 +26,9 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -27,10 +27,11 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.ZeroCopyHttpOutputMessage;
|
||||
import org.springframework.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.http.server.reactive.bootstrap.ReactorHttpServer;
|
||||
import org.springframework.http.server.reactive.bootstrap.UndertowHttpServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.HttpServer;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.ReactorHttpServer;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.UndertowHttpServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
@@ -38,7 +39,9 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class ZeroCopyIntegrationTests extends AbstractHttpHandlerIntegrationTests {
|
||||
class ZeroCopyIntegrationTests extends AbstractHttpHandlerIntegrationTests {
|
||||
|
||||
private static final Resource springLogoResource = new ClassPathResource("/org/springframework/web/spring.png");
|
||||
|
||||
private final ZeroCopyHandler handler = new ZeroCopyHandler();
|
||||
|
||||
@@ -50,9 +53,9 @@ public class ZeroCopyIntegrationTests extends AbstractHttpHandlerIntegrationTest
|
||||
|
||||
|
||||
@ParameterizedHttpServerTest
|
||||
public void zeroCopy(HttpServer httpServer) throws Exception {
|
||||
void zeroCopy(HttpServer httpServer) throws Exception {
|
||||
assumeTrue(httpServer instanceof ReactorHttpServer || httpServer instanceof UndertowHttpServer,
|
||||
"Zero-copy only does not support servlet");
|
||||
"Zero-copy does not support Servlet");
|
||||
|
||||
startServer(httpServer);
|
||||
|
||||
@@ -60,11 +63,9 @@ public class ZeroCopyIntegrationTests extends AbstractHttpHandlerIntegrationTest
|
||||
RequestEntity<?> request = RequestEntity.get(url).build();
|
||||
ResponseEntity<byte[]> response = new RestTemplate().exchange(request, byte[].class);
|
||||
|
||||
Resource logo = new ClassPathResource("spring.png", ZeroCopyIntegrationTests.class);
|
||||
|
||||
assertThat(response.hasBody()).isTrue();
|
||||
assertThat(response.getHeaders().getContentLength()).isEqualTo(logo.contentLength());
|
||||
assertThat(response.getBody().length).isEqualTo(logo.contentLength());
|
||||
assertThat(response.getHeaders().getContentLength()).isEqualTo(springLogoResource.contentLength());
|
||||
assertThat(response.getBody().length).isEqualTo(springLogoResource.contentLength());
|
||||
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.IMAGE_PNG);
|
||||
}
|
||||
|
||||
@@ -75,8 +76,7 @@ public class ZeroCopyIntegrationTests extends AbstractHttpHandlerIntegrationTest
|
||||
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
|
||||
try {
|
||||
ZeroCopyHttpOutputMessage zeroCopyResponse = (ZeroCopyHttpOutputMessage) response;
|
||||
Resource logo = new ClassPathResource("spring.png", ZeroCopyIntegrationTests.class);
|
||||
File logoFile = logo.getFile();
|
||||
File logoFile = springLogoResource.getFile();
|
||||
zeroCopyResponse.getHeaders().setContentType(MediaType.IMAGE_PNG);
|
||||
zeroCopyResponse.getHeaders().setContentLength(logoFile.length());
|
||||
return zeroCopyResponse.writeWith(logoFile, 0, logoFile.length());
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.http.server.reactive.bootstrap;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.http.server.reactive.ContextPathCompositeHandler;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public abstract class AbstractHttpServer implements HttpServer {
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass().getName());
|
||||
|
||||
private String host = "0.0.0.0";
|
||||
|
||||
private int port = 0;
|
||||
|
||||
private HttpHandler httpHandler;
|
||||
|
||||
private Map<String, HttpHandler> handlerMap;
|
||||
|
||||
private volatile boolean running;
|
||||
|
||||
private final Object lifecycleMonitor = new Object();
|
||||
|
||||
|
||||
@Override
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHandler(HttpHandler handler) {
|
||||
this.httpHandler = handler;
|
||||
}
|
||||
|
||||
public HttpHandler getHttpHandler() {
|
||||
return this.httpHandler;
|
||||
}
|
||||
|
||||
public void registerHttpHandler(String contextPath, HttpHandler handler) {
|
||||
if (this.handlerMap == null) {
|
||||
this.handlerMap = new LinkedHashMap<>();
|
||||
}
|
||||
this.handlerMap.put(contextPath, handler);
|
||||
}
|
||||
|
||||
public Map<String, HttpHandler> getHttpHandlerMap() {
|
||||
return this.handlerMap;
|
||||
}
|
||||
|
||||
protected HttpHandler resolveHttpHandler() {
|
||||
return (getHttpHandlerMap() != null ?
|
||||
new ContextPathCompositeHandler(getHttpHandlerMap()) : getHttpHandler());
|
||||
}
|
||||
|
||||
|
||||
// InitializingBean
|
||||
|
||||
@Override
|
||||
public final void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.host, "Host must not be null");
|
||||
Assert.isTrue(this.port >= 0, "Port must not be a negative number");
|
||||
Assert.isTrue(this.httpHandler != null || this.handlerMap != null, "No HttpHandler configured");
|
||||
Assert.state(!this.running, "Cannot reconfigure while running");
|
||||
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
initServer();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void initServer() throws Exception;
|
||||
|
||||
|
||||
// Lifecycle
|
||||
|
||||
@Override
|
||||
public final void start() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
if (!isRunning()) {
|
||||
String serverName = getClass().getSimpleName();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Starting " + serverName + "...");
|
||||
}
|
||||
this.running = true;
|
||||
try {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
startInternal();
|
||||
long millis = stopWatch.getTotalTimeMillis();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Server started on port " + getPort() + "(" + millis + " millis).");
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected abstract void startInternal() throws Exception;
|
||||
|
||||
@Override
|
||||
public final void stop() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
if (isRunning()) {
|
||||
String serverName = getClass().getSimpleName();
|
||||
logger.debug("Stopping " + serverName + "...");
|
||||
this.running = false;
|
||||
try {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
stopInternal();
|
||||
logger.debug("Server stopped (" + stopWatch.getTotalTimeMillis() + " millis).");
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
finally {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void stopInternal() throws Exception;
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return this.running;
|
||||
}
|
||||
|
||||
|
||||
private void reset() {
|
||||
this.host = "0.0.0.0";
|
||||
this.port = 0;
|
||||
this.httpHandler = null;
|
||||
this.handlerMap = null;
|
||||
resetInternal();
|
||||
}
|
||||
|
||||
protected abstract void resetInternal();
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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
|
||||
*
|
||||
* https://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.http.server.reactive.bootstrap;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public interface HttpServer extends InitializingBean, Lifecycle {
|
||||
|
||||
void setHost(String host);
|
||||
|
||||
void setPort(int port);
|
||||
|
||||
int getPort();
|
||||
|
||||
void setHandler(HttpHandler handler);
|
||||
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.http.server.reactive.bootstrap;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
|
||||
import org.springframework.http.server.reactive.JettyHttpHandlerAdapter;
|
||||
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class JettyHttpServer extends AbstractHttpServer {
|
||||
|
||||
private Server jettyServer;
|
||||
|
||||
private ServletContextHandler contextHandler;
|
||||
|
||||
|
||||
@Override
|
||||
protected void initServer() throws Exception {
|
||||
|
||||
this.jettyServer = new Server();
|
||||
|
||||
ServletHttpHandlerAdapter servlet = createServletAdapter();
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
servletHolder.setAsyncSupported(true);
|
||||
|
||||
this.contextHandler = new ServletContextHandler(this.jettyServer, "", false, false);
|
||||
this.contextHandler.addServlet(servletHolder, "/");
|
||||
this.contextHandler.start();
|
||||
|
||||
ServerConnector connector = new ServerConnector(this.jettyServer);
|
||||
connector.setHost(getHost());
|
||||
connector.setPort(getPort());
|
||||
this.jettyServer.addConnector(connector);
|
||||
}
|
||||
|
||||
private ServletHttpHandlerAdapter createServletAdapter() {
|
||||
return new JettyHttpHandlerAdapter(resolveHttpHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startInternal() throws Exception {
|
||||
this.jettyServer.start();
|
||||
setPort(((ServerConnector) this.jettyServer.getConnectors()[0]).getLocalPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopInternal() throws Exception {
|
||||
try {
|
||||
if (this.contextHandler.isRunning()) {
|
||||
this.contextHandler.stop();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (this.jettyServer.isRunning()) {
|
||||
this.jettyServer.setStopTimeout(5000);
|
||||
this.jettyServer.stop();
|
||||
this.jettyServer.destroy();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetInternal() {
|
||||
try {
|
||||
if (this.jettyServer.isRunning()) {
|
||||
this.jettyServer.setStopTimeout(5000);
|
||||
this.jettyServer.stop();
|
||||
this.jettyServer.destroy();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
finally {
|
||||
this.jettyServer = null;
|
||||
this.contextHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.http.server.reactive.bootstrap;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import reactor.netty.DisposableServer;
|
||||
|
||||
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
|
||||
|
||||
/**
|
||||
* @author Stephane Maldini
|
||||
*/
|
||||
public class ReactorHttpServer extends AbstractHttpServer {
|
||||
|
||||
private ReactorHttpHandlerAdapter reactorHandler;
|
||||
|
||||
private reactor.netty.http.server.HttpServer reactorServer;
|
||||
|
||||
private AtomicReference<DisposableServer> serverRef = new AtomicReference<>();
|
||||
|
||||
|
||||
@Override
|
||||
protected void initServer() {
|
||||
this.reactorHandler = createHttpHandlerAdapter();
|
||||
this.reactorServer = reactor.netty.http.server.HttpServer.create()
|
||||
.tcpConfiguration(server -> server.host(getHost()))
|
||||
.port(getPort());
|
||||
}
|
||||
|
||||
private ReactorHttpHandlerAdapter createHttpHandlerAdapter() {
|
||||
return new ReactorHttpHandlerAdapter(resolveHttpHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startInternal() {
|
||||
DisposableServer server = this.reactorServer.handle(this.reactorHandler).bind().block();
|
||||
setPort(server.address().getPort());
|
||||
this.serverRef.set(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopInternal() {
|
||||
this.serverRef.get().dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetInternal() {
|
||||
this.reactorServer = null;
|
||||
this.reactorHandler = null;
|
||||
this.serverRef.set(null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.http.server.reactive.bootstrap;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import reactor.netty.DisposableServer;
|
||||
import reactor.netty.tcp.SslProvider.DefaultConfigurationType;
|
||||
|
||||
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
|
||||
|
||||
/**
|
||||
* @author Stephane Maldini
|
||||
*/
|
||||
public class ReactorHttpsServer extends AbstractHttpServer {
|
||||
|
||||
private ReactorHttpHandlerAdapter reactorHandler;
|
||||
|
||||
private reactor.netty.http.server.HttpServer reactorServer;
|
||||
|
||||
private AtomicReference<DisposableServer> serverRef = new AtomicReference<>();
|
||||
|
||||
|
||||
@Override
|
||||
protected void initServer() throws Exception {
|
||||
|
||||
SelfSignedCertificate cert = new SelfSignedCertificate();
|
||||
SslContextBuilder builder = SslContextBuilder.forServer(cert.certificate(), cert.privateKey());
|
||||
|
||||
this.reactorHandler = createHttpHandlerAdapter();
|
||||
this.reactorServer = reactor.netty.http.server.HttpServer.create()
|
||||
.host(getHost())
|
||||
.port(getPort())
|
||||
.secure(spec -> spec.sslContext(builder).defaultConfiguration(DefaultConfigurationType.TCP));
|
||||
}
|
||||
|
||||
private ReactorHttpHandlerAdapter createHttpHandlerAdapter() {
|
||||
return new ReactorHttpHandlerAdapter(resolveHttpHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startInternal() {
|
||||
DisposableServer server = this.reactorServer.handle(this.reactorHandler).bind().block();
|
||||
setPort(server.address().getPort());
|
||||
this.serverRef.set(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopInternal() {
|
||||
this.serverRef.get().dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetInternal() {
|
||||
this.reactorServer = null;
|
||||
this.reactorHandler = null;
|
||||
this.serverRef.set(null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.http.server.reactive.bootstrap;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
|
||||
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
|
||||
import org.springframework.http.server.reactive.TomcatHttpHandlerAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class TomcatHttpServer extends AbstractHttpServer {
|
||||
|
||||
private final String baseDir;
|
||||
|
||||
private final Class<?> wsListener;
|
||||
|
||||
private String contextPath = "";
|
||||
|
||||
private String servletMapping = "/";
|
||||
|
||||
private Tomcat tomcatServer;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Tomcat HTTP server using the {@code java.io.tmpdir} JVM
|
||||
* system property as the {@code baseDir}.
|
||||
* @since 5.2
|
||||
*/
|
||||
public TomcatHttpServer() {
|
||||
this(new File(System.getProperty("java.io.tmpdir")).getAbsolutePath());
|
||||
}
|
||||
|
||||
public TomcatHttpServer(String baseDir) {
|
||||
this(baseDir, null);
|
||||
}
|
||||
|
||||
public TomcatHttpServer(String baseDir, Class<?> wsListener) {
|
||||
Assert.notNull(baseDir, "Base dir must not be null");
|
||||
this.baseDir = baseDir;
|
||||
this.wsListener = wsListener;
|
||||
}
|
||||
|
||||
|
||||
public void setContextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
public void setServletMapping(String servletMapping) {
|
||||
this.servletMapping = servletMapping;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void initServer() throws Exception {
|
||||
this.tomcatServer = new Tomcat();
|
||||
this.tomcatServer.setBaseDir(baseDir);
|
||||
this.tomcatServer.setHostname(getHost());
|
||||
this.tomcatServer.setPort(getPort());
|
||||
|
||||
ServletHttpHandlerAdapter servlet = initServletAdapter();
|
||||
|
||||
File base = new File(System.getProperty("java.io.tmpdir"));
|
||||
Context rootContext = tomcatServer.addContext(this.contextPath, base.getAbsolutePath());
|
||||
Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet).setAsyncSupported(true);
|
||||
rootContext.addServletMappingDecoded(this.servletMapping, "httpHandlerServlet");
|
||||
if (wsListener != null) {
|
||||
rootContext.addApplicationListener(wsListener.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private ServletHttpHandlerAdapter initServletAdapter() {
|
||||
return new TomcatHttpHandlerAdapter(resolveHttpHandler());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void startInternal() throws LifecycleException {
|
||||
this.tomcatServer.start();
|
||||
setPort(this.tomcatServer.getConnector().getLocalPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopInternal() throws Exception {
|
||||
this.tomcatServer.stop();
|
||||
this.tomcatServer.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetInternal() {
|
||||
this.tomcatServer = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.http.server.reactive.bootstrap;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import io.undertow.Undertow;
|
||||
|
||||
import org.springframework.http.server.reactive.UndertowHttpHandlerAdapter;
|
||||
|
||||
/**
|
||||
* @author Marek Hawrylczak
|
||||
*/
|
||||
public class UndertowHttpServer extends AbstractHttpServer {
|
||||
|
||||
private Undertow server;
|
||||
|
||||
|
||||
@Override
|
||||
protected void initServer() throws Exception {
|
||||
this.server = Undertow.builder().addHttpListener(getPort(), getHost())
|
||||
.setHandler(initHttpHandlerAdapter())
|
||||
.build();
|
||||
}
|
||||
|
||||
private UndertowHttpHandlerAdapter initHttpHandlerAdapter() {
|
||||
return new UndertowHttpHandlerAdapter(resolveHttpHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startInternal() {
|
||||
this.server.start();
|
||||
Undertow.ListenerInfo info = this.server.getListenerInfo().get(0);
|
||||
setPort(((InetSocketAddress) info.getAddress()).getPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopInternal() {
|
||||
this.server.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetInternal() {
|
||||
this.server = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* This package contains temporary interfaces and classes for running embedded servers.
|
||||
* They are expected to be replaced by an upcoming Spring Boot support.
|
||||
*/
|
||||
package org.springframework.http.server.reactive.bootstrap;
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.http.client.reactive.test;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.reactive.AbstractClientHttpRequest;
|
||||
import org.springframework.http.client.reactive.ClientHttpRequest;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link ClientHttpRequest}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MockClientHttpRequest extends AbstractClientHttpRequest {
|
||||
|
||||
private HttpMethod httpMethod;
|
||||
|
||||
private URI url;
|
||||
|
||||
private final DataBufferFactory bufferFactory = new DefaultDataBufferFactory();
|
||||
|
||||
private Flux<DataBuffer> body = Flux.error(
|
||||
new IllegalStateException("The body is not set. " +
|
||||
"Did handling complete with success? Is a custom \"writeHandler\" configured?"));
|
||||
|
||||
private Function<Flux<DataBuffer>, Mono<Void>> writeHandler;
|
||||
|
||||
|
||||
public MockClientHttpRequest(HttpMethod httpMethod, String urlTemplate, Object... vars) {
|
||||
this(httpMethod, UriComponentsBuilder.fromUriString(urlTemplate).buildAndExpand(vars).encode().toUri());
|
||||
}
|
||||
|
||||
public MockClientHttpRequest(HttpMethod httpMethod, URI url) {
|
||||
this.httpMethod = httpMethod;
|
||||
this.url = url;
|
||||
this.writeHandler = body -> {
|
||||
this.body = body.cache();
|
||||
return this.body.then();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure a custom handler for writing the request body.
|
||||
*
|
||||
* <p>The default write handler consumes and caches the request body so it
|
||||
* may be accessed subsequently, e.g. in test assertions. Use this property
|
||||
* when the request body is an infinite stream.
|
||||
*
|
||||
* @param writeHandler the write handler to use returning {@code Mono<Void>}
|
||||
* when the body has been "written" (i.e. consumed).
|
||||
*/
|
||||
public void setWriteHandler(Function<Flux<DataBuffer>, Mono<Void>> writeHandler) {
|
||||
Assert.notNull(writeHandler, "'writeHandler' is required");
|
||||
this.writeHandler = writeHandler;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
return this.httpMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBufferFactory bufferFactory() {
|
||||
return this.bufferFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyHeaders() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyCookies() {
|
||||
getCookies().values().stream().flatMap(Collection::stream)
|
||||
.forEach(cookie -> getHeaders().add(HttpHeaders.COOKIE, cookie.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
|
||||
return doCommit(() -> Mono.defer(() -> this.writeHandler.apply(Flux.from(body))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
|
||||
return writeWith(Flux.from(body).flatMap(p -> p));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> setComplete() {
|
||||
return writeWith(Flux.empty());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the request body, or an error stream if the body was never set
|
||||
* or when {@link #setWriteHandler} is configured.
|
||||
*/
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate response data and convert to a String using the "Content-Type"
|
||||
* charset or "UTF-8" by default.
|
||||
*/
|
||||
public Mono<String> getBodyAsString() {
|
||||
|
||||
Charset charset = Optional.ofNullable(getHeaders().getContentType()).map(MimeType::getCharset)
|
||||
.orElse(StandardCharsets.UTF_8);
|
||||
|
||||
return getBody()
|
||||
.reduce(bufferFactory().allocateBuffer(), (previous, current) -> {
|
||||
previous.write(current);
|
||||
DataBufferUtils.release(current);
|
||||
return previous;
|
||||
})
|
||||
.map(buffer -> bufferToString(buffer, charset));
|
||||
}
|
||||
|
||||
private static String bufferToString(DataBuffer buffer, Charset charset) {
|
||||
Assert.notNull(charset, "'charset' must not be null");
|
||||
byte[] bytes = new byte[buffer.readableByteCount()];
|
||||
buffer.read(bytes);
|
||||
return new String(bytes, charset);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.mock.http.client.reactive.test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.client.reactive.ClientHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link ClientHttpResponse}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MockClientHttpResponse implements ClientHttpResponse {
|
||||
|
||||
private final int status;
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
private final MultiValueMap<String, ResponseCookie> cookies = new LinkedMultiValueMap<>();
|
||||
|
||||
private Flux<DataBuffer> body = Flux.empty();
|
||||
|
||||
private final DataBufferFactory bufferFactory = new DefaultDataBufferFactory();
|
||||
|
||||
|
||||
public MockClientHttpResponse(HttpStatus status) {
|
||||
Assert.notNull(status, "HttpStatus is required");
|
||||
this.status = status.value();
|
||||
}
|
||||
|
||||
public MockClientHttpResponse(int status) {
|
||||
Assert.isTrue(status > 99 && status < 1000, "Status must be between 100 and 999");
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpStatus getStatusCode() {
|
||||
return HttpStatus.valueOf(this.status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawStatusCode() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
if (!getCookies().isEmpty() && this.headers.get(HttpHeaders.SET_COOKIE) == null) {
|
||||
getCookies().values().stream().flatMap(Collection::stream)
|
||||
.forEach(cookie -> getHeaders().add(HttpHeaders.SET_COOKIE, cookie.toString()));
|
||||
}
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, ResponseCookie> getCookies() {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
public void setBody(Publisher<DataBuffer> body) {
|
||||
this.body = Flux.from(body);
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
setBody(body, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public void setBody(String body, Charset charset) {
|
||||
DataBuffer buffer = toDataBuffer(body, charset);
|
||||
this.body = Flux.just(buffer);
|
||||
}
|
||||
|
||||
private DataBuffer toDataBuffer(String body, Charset charset) {
|
||||
byte[] bytes = body.getBytes(charset);
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
||||
return this.bufferFactory.wrap(byteBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response body aggregated and converted to a String using the
|
||||
* charset of the Content-Type response or otherwise as "UTF-8".
|
||||
*/
|
||||
public Mono<String> getBodyAsString() {
|
||||
Charset charset = getCharset();
|
||||
return Flux.from(getBody())
|
||||
.reduce(this.bufferFactory.allocateBuffer(), (previous, current) -> {
|
||||
previous.write(current);
|
||||
DataBufferUtils.release(current);
|
||||
return previous;
|
||||
})
|
||||
.map(buffer -> dumpString(buffer, charset));
|
||||
}
|
||||
|
||||
private static String dumpString(DataBuffer buffer, Charset charset) {
|
||||
Assert.notNull(charset, "'charset' must not be null");
|
||||
byte[] bytes = new byte[buffer.readableByteCount()];
|
||||
buffer.read(bytes);
|
||||
return new String(bytes, charset);
|
||||
}
|
||||
|
||||
private Charset getCharset() {
|
||||
Charset charset = null;
|
||||
MediaType contentType = getHeaders().getContentType();
|
||||
if (contentType != null) {
|
||||
charset = contentType.getCharset();
|
||||
}
|
||||
return (charset != null ? charset : StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
HttpStatus code = HttpStatus.resolve(this.status);
|
||||
return (code != null ? code.name() + "(" + this.status + ")" : "Status (" + this.status + ")") + this.headers;
|
||||
}
|
||||
}
|
||||
@@ -1,595 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.mock.http.server.reactive.test;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpCookie;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.AbstractServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.SslInfo;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Mock extension of {@link AbstractServerHttpRequest} for use in tests without
|
||||
* an actual server. Use the static methods to obtain a builder.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public final class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||
|
||||
private final HttpMethod httpMethod;
|
||||
|
||||
private final MultiValueMap<String, HttpCookie> cookies;
|
||||
|
||||
@Nullable
|
||||
private final InetSocketAddress remoteAddress;
|
||||
|
||||
@Nullable
|
||||
private final InetSocketAddress localAddress;
|
||||
|
||||
@Nullable
|
||||
private final SslInfo sslInfo;
|
||||
|
||||
private final Flux<DataBuffer> body;
|
||||
|
||||
|
||||
private MockServerHttpRequest(HttpMethod httpMethod, URI uri, @Nullable String contextPath,
|
||||
HttpHeaders headers, MultiValueMap<String, HttpCookie> cookies,
|
||||
@Nullable InetSocketAddress remoteAddress, @Nullable InetSocketAddress localAddress,
|
||||
@Nullable SslInfo sslInfo, Publisher<? extends DataBuffer> body) {
|
||||
|
||||
super(uri, contextPath, headers);
|
||||
this.httpMethod = httpMethod;
|
||||
this.cookies = cookies;
|
||||
this.remoteAddress = remoteAddress;
|
||||
this.localAddress = localAddress;
|
||||
this.sslInfo = sslInfo;
|
||||
this.body = Flux.from(body);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
return this.httpMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodValue() {
|
||||
return this.httpMethod.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public InetSocketAddress getRemoteAddress() {
|
||||
return this.remoteAddress;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress() {
|
||||
return this.localAddress;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected SslInfo initSslInfo() {
|
||||
return this.sslInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MultiValueMap<String, HttpCookie> initCookies() {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getNativeRequest() {
|
||||
throw new IllegalStateException("This is a mock. No running server, no native request.");
|
||||
}
|
||||
|
||||
|
||||
// Static builder methods
|
||||
|
||||
/**
|
||||
* Create a builder with the given HTTP method and a {@link URI}.
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param url the URL
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder method(HttpMethod method, URI url) {
|
||||
return new DefaultBodyBuilder(method, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative to {@link #method(HttpMethod, URI)} that accepts a URI template.
|
||||
* The given URI may contain query parameters, or those may be added later via
|
||||
* {@link BaseBuilder#queryParam queryParam} builder methods.
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param urlTemplate the URL template
|
||||
* @param vars variables to expand into the template
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder method(HttpMethod method, String urlTemplate, Object... vars) {
|
||||
URI url = UriComponentsBuilder.fromUriString(urlTemplate).buildAndExpand(vars).encode().toUri();
|
||||
return new DefaultBodyBuilder(method, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP GET builder with the given URI template. The given URI may
|
||||
* contain query parameters, or those may be added later via
|
||||
* {@link BaseBuilder#queryParam queryParam} builder methods.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BaseBuilder<?> get(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.GET, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP HEAD variant. See {@link #get(String, Object...)} for general info.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BaseBuilder<?> head(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.HEAD, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP POST variant. See {@link #get(String, Object...)} for general info.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder post(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.POST, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP PUT variant. See {@link #get(String, Object...)} for general info.
|
||||
* {@link BaseBuilder#queryParam queryParam} builder methods.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder put(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.PUT, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP PATCH variant. See {@link #get(String, Object...)} for general info.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder patch(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.PATCH, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP DELETE variant. See {@link #get(String, Object...)} for general info.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BaseBuilder<?> delete(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.DELETE, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP OPTIONS variant. See {@link #get(String, Object...)} for general info.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BaseBuilder<?> options(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.OPTIONS, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Request builder exposing properties not related to the body.
|
||||
* @param <B> the builder sub-class
|
||||
*/
|
||||
public interface BaseBuilder<B extends BaseBuilder<B>> {
|
||||
|
||||
/**
|
||||
* Set the contextPath to return.
|
||||
*/
|
||||
B contextPath(String contextPath);
|
||||
|
||||
/**
|
||||
* Append the given query parameter to the existing query parameters.
|
||||
* If no values are given, the resulting URI will contain the query
|
||||
* parameter name only (i.e. {@code ?foo} instead of {@code ?foo=bar}).
|
||||
* <p>The provided query name and values will be encoded.
|
||||
* @param name the query parameter name
|
||||
* @param values the query parameter values
|
||||
* @return this UriComponentsBuilder
|
||||
*/
|
||||
B queryParam(String name, Object... values);
|
||||
|
||||
/**
|
||||
* Add the given query parameters and values. The provided query name
|
||||
* and corresponding values will be encoded.
|
||||
* @param params the params
|
||||
* @return this UriComponentsBuilder
|
||||
*/
|
||||
B queryParams(MultiValueMap<String, String> params);
|
||||
|
||||
/**
|
||||
* Set the remote address to return.
|
||||
*/
|
||||
B remoteAddress(InetSocketAddress remoteAddress);
|
||||
|
||||
/**
|
||||
* Set the local address to return.
|
||||
* @since 5.2.3
|
||||
*/
|
||||
B localAddress(InetSocketAddress localAddress);
|
||||
|
||||
/**
|
||||
* Set SSL session information and certificates.
|
||||
*/
|
||||
void sslInfo(SslInfo sslInfo);
|
||||
|
||||
/**
|
||||
* Add one or more cookies.
|
||||
*/
|
||||
B cookie(HttpCookie... cookie);
|
||||
|
||||
/**
|
||||
* Add the given cookies.
|
||||
* @param cookies the cookies.
|
||||
*/
|
||||
B cookies(MultiValueMap<String, HttpCookie> cookies);
|
||||
|
||||
/**
|
||||
* Add the given, single header value under the given name.
|
||||
* @param headerName the header name
|
||||
* @param headerValues the header value(s)
|
||||
* @see HttpHeaders#add(String, String)
|
||||
*/
|
||||
B header(String headerName, String... headerValues);
|
||||
|
||||
/**
|
||||
* Add the given header values.
|
||||
* @param headers the header values
|
||||
*/
|
||||
B headers(MultiValueMap<String, String> headers);
|
||||
|
||||
/**
|
||||
* Set the list of acceptable {@linkplain MediaType media types}, as
|
||||
* specified by the {@code Accept} header.
|
||||
* @param acceptableMediaTypes the acceptable media types
|
||||
*/
|
||||
B accept(MediaType... acceptableMediaTypes);
|
||||
|
||||
/**
|
||||
* Set the list of acceptable {@linkplain Charset charsets}, as specified
|
||||
* by the {@code Accept-Charset} header.
|
||||
* @param acceptableCharsets the acceptable charsets
|
||||
*/
|
||||
B acceptCharset(Charset... acceptableCharsets);
|
||||
|
||||
/**
|
||||
* Set the list of acceptable {@linkplain Locale locales}, as specified
|
||||
* by the {@code Accept-Languages} header.
|
||||
* @param acceptableLocales the acceptable locales
|
||||
*/
|
||||
B acceptLanguageAsLocales(Locale... acceptableLocales);
|
||||
|
||||
/**
|
||||
* Set the value of the {@code If-Modified-Since} header.
|
||||
* <p>The date should be specified as the number of milliseconds since
|
||||
* January 1, 1970 GMT.
|
||||
* @param ifModifiedSince the new value of the header
|
||||
*/
|
||||
B ifModifiedSince(long ifModifiedSince);
|
||||
|
||||
/**
|
||||
* Set the (new) value of the {@code If-Unmodified-Since} header.
|
||||
* <p>The date should be specified as the number of milliseconds since
|
||||
* January 1, 1970 GMT.
|
||||
* @param ifUnmodifiedSince the new value of the header
|
||||
* @see HttpHeaders#setIfUnmodifiedSince(long)
|
||||
*/
|
||||
B ifUnmodifiedSince(long ifUnmodifiedSince);
|
||||
|
||||
/**
|
||||
* Set the values of the {@code If-None-Match} header.
|
||||
* @param ifNoneMatches the new value of the header
|
||||
*/
|
||||
B ifNoneMatch(String... ifNoneMatches);
|
||||
|
||||
/**
|
||||
* Set the (new) value of the Range header.
|
||||
* @param ranges the HTTP ranges
|
||||
* @see HttpHeaders#setRange(List)
|
||||
*/
|
||||
B range(HttpRange... ranges);
|
||||
|
||||
/**
|
||||
* Builds the request with no body.
|
||||
* @return the request
|
||||
* @see BodyBuilder#body(Publisher)
|
||||
* @see BodyBuilder#body(String)
|
||||
*/
|
||||
MockServerHttpRequest build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder that adds a body to the request.
|
||||
*/
|
||||
public interface BodyBuilder extends BaseBuilder<BodyBuilder> {
|
||||
|
||||
/**
|
||||
* Set the length of the body in bytes, as specified by the
|
||||
* {@code Content-Length} header.
|
||||
* @param contentLength the content length
|
||||
* @return this builder
|
||||
* @see HttpHeaders#setContentLength(long)
|
||||
*/
|
||||
BodyBuilder contentLength(long contentLength);
|
||||
|
||||
/**
|
||||
* Set the {@linkplain MediaType media type} of the body, as specified
|
||||
* by the {@code Content-Type} header.
|
||||
* @param contentType the content type
|
||||
* @return this builder
|
||||
* @see HttpHeaders#setContentType(MediaType)
|
||||
*/
|
||||
BodyBuilder contentType(MediaType contentType);
|
||||
|
||||
/**
|
||||
* Set the body of the request and build it.
|
||||
* @param body the body
|
||||
* @return the built request entity
|
||||
*/
|
||||
MockServerHttpRequest body(Publisher<? extends DataBuffer> body);
|
||||
|
||||
/**
|
||||
* Set the body of the request and build it.
|
||||
* <p>The String is assumed to be UTF-8 encoded unless the request has a
|
||||
* "content-type" header with a charset attribute.
|
||||
* @param body the body as text
|
||||
* @return the built request entity
|
||||
*/
|
||||
MockServerHttpRequest body(String body);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class DefaultBodyBuilder implements BodyBuilder {
|
||||
|
||||
private static final DataBufferFactory BUFFER_FACTORY = new DefaultDataBufferFactory();
|
||||
|
||||
|
||||
private final HttpMethod method;
|
||||
|
||||
private final URI url;
|
||||
|
||||
@Nullable
|
||||
private String contextPath;
|
||||
|
||||
private final UriComponentsBuilder queryParamsBuilder = UriComponentsBuilder.newInstance();
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
private final MultiValueMap<String, HttpCookie> cookies = new LinkedMultiValueMap<>();
|
||||
|
||||
@Nullable
|
||||
private InetSocketAddress remoteAddress;
|
||||
|
||||
@Nullable
|
||||
private InetSocketAddress localAddress;
|
||||
|
||||
@Nullable
|
||||
private SslInfo sslInfo;
|
||||
|
||||
|
||||
public DefaultBodyBuilder(HttpMethod method, URI url) {
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder contextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder queryParam(String name, Object... values) {
|
||||
this.queryParamsBuilder.queryParam(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder queryParams(MultiValueMap<String, String> params) {
|
||||
this.queryParamsBuilder.queryParams(params);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder remoteAddress(InetSocketAddress remoteAddress) {
|
||||
this.remoteAddress = remoteAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder localAddress(InetSocketAddress localAddress) {
|
||||
this.localAddress = localAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sslInfo(SslInfo sslInfo) {
|
||||
this.sslInfo = sslInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder cookie(HttpCookie... cookies) {
|
||||
Arrays.stream(cookies).forEach(cookie -> this.cookies.add(cookie.getName(), cookie));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder cookies(MultiValueMap<String, HttpCookie> cookies) {
|
||||
this.cookies.putAll(cookies);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder header(String headerName, String... headerValues) {
|
||||
for (String headerValue : headerValues) {
|
||||
this.headers.add(headerName, headerValue);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder headers(MultiValueMap<String, String> headers) {
|
||||
this.headers.putAll(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder accept(MediaType... acceptableMediaTypes) {
|
||||
this.headers.setAccept(Arrays.asList(acceptableMediaTypes));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder acceptCharset(Charset... acceptableCharsets) {
|
||||
this.headers.setAcceptCharset(Arrays.asList(acceptableCharsets));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder acceptLanguageAsLocales(Locale... acceptableLocales) {
|
||||
this.headers.setAcceptLanguageAsLocales(Arrays.asList(acceptableLocales));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder contentLength(long contentLength) {
|
||||
this.headers.setContentLength(contentLength);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder contentType(MediaType contentType) {
|
||||
this.headers.setContentType(contentType);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder ifModifiedSince(long ifModifiedSince) {
|
||||
this.headers.setIfModifiedSince(ifModifiedSince);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder ifUnmodifiedSince(long ifUnmodifiedSince) {
|
||||
this.headers.setIfUnmodifiedSince(ifUnmodifiedSince);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder ifNoneMatch(String... ifNoneMatches) {
|
||||
this.headers.setIfNoneMatch(Arrays.asList(ifNoneMatches));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder range(HttpRange... ranges) {
|
||||
this.headers.setRange(Arrays.asList(ranges));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockServerHttpRequest build() {
|
||||
return body(Flux.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockServerHttpRequest body(String body) {
|
||||
return body(Flux.just(BUFFER_FACTORY.wrap(body.getBytes(getCharset()))));
|
||||
}
|
||||
|
||||
private Charset getCharset() {
|
||||
return Optional.ofNullable(this.headers.getContentType())
|
||||
.map(MimeType::getCharset).orElse(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockServerHttpRequest body(Publisher<? extends DataBuffer> body) {
|
||||
applyCookiesIfNecessary();
|
||||
return new MockServerHttpRequest(this.method, getUrlToUse(), this.contextPath,
|
||||
this.headers, this.cookies, this.remoteAddress, this.localAddress, this.sslInfo, body);
|
||||
}
|
||||
|
||||
private void applyCookiesIfNecessary() {
|
||||
if (this.headers.get(HttpHeaders.COOKIE) == null) {
|
||||
this.cookies.values().stream().flatMap(Collection::stream)
|
||||
.forEach(cookie -> this.headers.add(HttpHeaders.COOKIE, cookie.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private URI getUrlToUse() {
|
||||
MultiValueMap<String, String> params =
|
||||
this.queryParamsBuilder.buildAndExpand().encode().getQueryParams();
|
||||
|
||||
if (!params.isEmpty()) {
|
||||
return UriComponentsBuilder.fromUri(this.url).queryParams(params).build(true).toUri();
|
||||
}
|
||||
|
||||
return this.url;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.mock.http.server.reactive.test;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.publisher.MonoProcessor;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.server.reactive.AbstractServerHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
/**
|
||||
* Mock extension of {@link AbstractServerHttpResponse} for use in tests without
|
||||
* an actual server.
|
||||
*
|
||||
* <p>By default response content is consumed in full upon writing and cached
|
||||
* for subsequent access, however it is also possible to set a custom
|
||||
* {@link #setWriteHandler(Function) writeHandler}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MockServerHttpResponse extends AbstractServerHttpResponse {
|
||||
|
||||
private Flux<DataBuffer> body = Flux.error(new IllegalStateException(
|
||||
"No content was written nor was setComplete() called on this response."));
|
||||
|
||||
private Function<Flux<DataBuffer>, Mono<Void>> writeHandler;
|
||||
|
||||
|
||||
public MockServerHttpResponse() {
|
||||
this(new DefaultDataBufferFactory());
|
||||
}
|
||||
|
||||
public MockServerHttpResponse(DataBufferFactory dataBufferFactory) {
|
||||
super(dataBufferFactory);
|
||||
this.writeHandler = body -> {
|
||||
// Avoid .then() which causes data buffers to be released
|
||||
MonoProcessor<Void> completion = MonoProcessor.create();
|
||||
this.body = body.doOnComplete(completion::onComplete).doOnError(completion::onError).cache();
|
||||
this.body.subscribe();
|
||||
return completion;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure a custom handler to consume the response body.
|
||||
* <p>By default, response body content is consumed in full and cached for
|
||||
* subsequent access in tests. Use this option to take control over how the
|
||||
* response body is consumed.
|
||||
* @param writeHandler the write handler to use returning {@code Mono<Void>}
|
||||
* when the body has been "written" (i.e. consumed).
|
||||
*/
|
||||
public void setWriteHandler(Function<Flux<DataBuffer>, Mono<Void>> writeHandler) {
|
||||
Assert.notNull(writeHandler, "'writeHandler' is required");
|
||||
this.body = Flux.error(new IllegalStateException("Not available with custom write handler."));
|
||||
this.writeHandler = writeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getNativeResponse() {
|
||||
throw new IllegalStateException("This is a mock. No running server, no native response.");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void applyStatusCode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyHeaders() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyCookies() {
|
||||
for (List<ResponseCookie> cookies : getCookies().values()) {
|
||||
for (ResponseCookie cookie : cookies) {
|
||||
getHeaders().add(HttpHeaders.SET_COOKIE, cookie.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Void> writeWithInternal(Publisher<? extends DataBuffer> body) {
|
||||
return this.writeHandler.apply(Flux.from(body));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Void> writeAndFlushWithInternal(
|
||||
Publisher<? extends Publisher<? extends DataBuffer>> body) {
|
||||
|
||||
return this.writeHandler.apply(Flux.from(body).concatMap(Flux::from));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> setComplete() {
|
||||
return doCommit(() -> Mono.defer(() -> this.writeHandler.apply(Flux.empty())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response body or an error stream if the body was not set.
|
||||
*/
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate response data and convert to a String using the "Content-Type"
|
||||
* charset or "UTF-8" by default.
|
||||
*/
|
||||
public Mono<String> getBodyAsString() {
|
||||
|
||||
Charset charset = Optional.ofNullable(getHeaders().getContentType()).map(MimeType::getCharset)
|
||||
.orElse(StandardCharsets.UTF_8);
|
||||
|
||||
return getBody()
|
||||
.reduce(bufferFactory().allocateBuffer(), (previous, current) -> {
|
||||
previous.write(current);
|
||||
DataBufferUtils.release(current);
|
||||
return previous;
|
||||
})
|
||||
.map(buffer -> bufferToString(buffer, charset));
|
||||
}
|
||||
|
||||
private static String bufferToString(DataBuffer buffer, Charset charset) {
|
||||
Assert.notNull(charset, "'charset' must not be null");
|
||||
byte[] bytes = new byte[buffer.readableByteCount()];
|
||||
buffer.read(bytes);
|
||||
DataBufferUtils.release(buffer);
|
||||
return new String(bytes, charset);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
/**
|
||||
* For @NonNull annotations on implementation classes
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.mock.http.server.reactive.test;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Delegating implementation of {@link javax.servlet.ServletInputStream}.
|
||||
*
|
||||
* <p>Used by {@link MockHttpServletRequest}; typically not directly
|
||||
* used for testing application controllers.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.0.2
|
||||
* @see MockHttpServletRequest
|
||||
*/
|
||||
public class DelegatingServletInputStream extends ServletInputStream {
|
||||
|
||||
private final InputStream sourceStream;
|
||||
|
||||
private boolean finished = false;
|
||||
|
||||
|
||||
/**
|
||||
* Create a DelegatingServletInputStream for the given source stream.
|
||||
* @param sourceStream the source stream (never {@code null})
|
||||
*/
|
||||
public DelegatingServletInputStream(InputStream sourceStream) {
|
||||
Assert.notNull(sourceStream, "Source InputStream must not be null");
|
||||
this.sourceStream = sourceStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying source stream (never {@code null}).
|
||||
*/
|
||||
public final InputStream getSourceStream() {
|
||||
return this.sourceStream;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int data = this.sourceStream.read();
|
||||
if (data == -1) {
|
||||
this.finished = true;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return this.sourceStream.available();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Delegating implementation of {@link javax.servlet.ServletOutputStream}.
|
||||
*
|
||||
* <p>Used by {@link MockHttpServletResponse}; typically not directly
|
||||
* used for testing application controllers.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.0.2
|
||||
* @see MockHttpServletResponse
|
||||
*/
|
||||
public class DelegatingServletOutputStream extends ServletOutputStream {
|
||||
|
||||
private final OutputStream targetStream;
|
||||
|
||||
|
||||
/**
|
||||
* Create a DelegatingServletOutputStream for the given target stream.
|
||||
* @param targetStream the target stream (never {@code null})
|
||||
*/
|
||||
public DelegatingServletOutputStream(OutputStream targetStream) {
|
||||
Assert.notNull(targetStream, "Target OutputStream must not be null");
|
||||
this.targetStream = targetStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying target stream (never {@code null}).
|
||||
*/
|
||||
public final OutputStream getTargetStream() {
|
||||
return this.targetStream;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
this.targetStream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
super.flush();
|
||||
this.targetStream.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
this.targetStream.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWriteListener(WriteListener writeListener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Internal helper class that serves as value holder for request headers.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @since 2.0.1
|
||||
*/
|
||||
class HeaderValueHolder {
|
||||
|
||||
private final List<Object> values = new LinkedList<>();
|
||||
|
||||
|
||||
public void setValue(@Nullable Object value) {
|
||||
this.values.clear();
|
||||
if (value != null) {
|
||||
this.values.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void addValue(Object value) {
|
||||
this.values.add(value);
|
||||
}
|
||||
|
||||
public void addValues(Collection<?> values) {
|
||||
this.values.addAll(values);
|
||||
}
|
||||
|
||||
public void addValueArray(Object values) {
|
||||
CollectionUtils.mergeArrayIntoCollection(values, this.values);
|
||||
}
|
||||
|
||||
public List<Object> getValues() {
|
||||
return Collections.unmodifiableList(this.values);
|
||||
}
|
||||
|
||||
public List<String> getStringValues() {
|
||||
List<String> stringList = new ArrayList<>(this.values.size());
|
||||
for (Object value : this.values) {
|
||||
stringList.add(value.toString());
|
||||
}
|
||||
return Collections.unmodifiableList(stringList);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object getValue() {
|
||||
return (!this.values.isEmpty() ? this.values.get(0) : null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getStringValue() {
|
||||
return (!this.values.isEmpty() ? String.valueOf(this.values.get(0)) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.values.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find a HeaderValueHolder by name, ignoring casing.
|
||||
* @param headers the Map of header names to HeaderValueHolders
|
||||
* @param name the name of the desired header
|
||||
* @return the corresponding HeaderValueHolder, or {@code null} if none found
|
||||
*/
|
||||
@Nullable
|
||||
public static HeaderValueHolder getByName(Map<String, HeaderValueHolder> headers, String name) {
|
||||
Assert.notNull(name, "Header name must not be null");
|
||||
for (String headerName : headers.keySet()) {
|
||||
if (headerName.equalsIgnoreCase(name)) {
|
||||
return headers.get(headerName);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.AsyncListener;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link AsyncContext} interface.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class MockAsyncContext implements AsyncContext {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
@Nullable
|
||||
private final HttpServletResponse response;
|
||||
|
||||
private final List<AsyncListener> listeners = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private String dispatchedPath;
|
||||
|
||||
private long timeout = 10 * 1000L;
|
||||
|
||||
private final List<Runnable> dispatchHandlers = new ArrayList<>();
|
||||
|
||||
|
||||
public MockAsyncContext(ServletRequest request, @Nullable ServletResponse response) {
|
||||
this.request = (HttpServletRequest) request;
|
||||
this.response = (HttpServletResponse) response;
|
||||
}
|
||||
|
||||
|
||||
public void addDispatchHandler(Runnable handler) {
|
||||
Assert.notNull(handler, "Dispatch handler must not be null");
|
||||
synchronized (this) {
|
||||
if (this.dispatchedPath == null) {
|
||||
this.dispatchHandlers.add(handler);
|
||||
}
|
||||
else {
|
||||
handler.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRequest getRequest() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ServletResponse getResponse() {
|
||||
return this.response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOriginalRequestAndResponse() {
|
||||
return (this.request instanceof MockHttpServletRequest && this.response instanceof MockHttpServletResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch() {
|
||||
dispatch(this.request.getRequestURI());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch(String path) {
|
||||
dispatch(null, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch(@Nullable ServletContext context, String path) {
|
||||
synchronized (this) {
|
||||
this.dispatchedPath = path;
|
||||
this.dispatchHandlers.forEach(Runnable::run);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDispatchedPath() {
|
||||
return this.dispatchedPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete() {
|
||||
MockHttpServletRequest mockRequest = WebUtils.getNativeRequest(this.request, MockHttpServletRequest.class);
|
||||
if (mockRequest != null) {
|
||||
mockRequest.setAsyncStarted(false);
|
||||
}
|
||||
for (AsyncListener listener : this.listeners) {
|
||||
try {
|
||||
listener.onComplete(new AsyncEvent(this, this.request, this.response));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("AsyncListener failure", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Runnable runnable) {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(AsyncListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(AsyncListener listener, ServletRequest request, ServletResponse response) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public List<AsyncListener> getListeners() {
|
||||
return this.listeners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException {
|
||||
return BeanUtils.instantiateClass(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* By default this is set to 10000 (10 seconds) even though the Servlet API
|
||||
* specifies a default async request timeout of 30 seconds. Keep in mind the
|
||||
* timeout could further be impacted by global configuration through the MVC
|
||||
* Java config or the XML namespace, as well as be overridden per request on
|
||||
* {@link org.springframework.web.context.request.async.DeferredResult DeferredResult}
|
||||
* or on
|
||||
* {@link org.springframework.web.servlet.mvc.method.annotation.SseEmitter SseEmitter}.
|
||||
* @param timeout the timeout value to use.
|
||||
* @see AsyncContext#setTimeout(long)
|
||||
*/
|
||||
@Override
|
||||
public void setTimeout(long timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.Writer;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
import javax.servlet.jsp.tagext.BodyContent;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.jsp.tagext.BodyContent} class.
|
||||
* Only necessary for testing applications when testing custom JSP tags.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
*/
|
||||
public class MockBodyContent extends BodyContent {
|
||||
|
||||
private final String content;
|
||||
|
||||
|
||||
/**
|
||||
* Create a MockBodyContent for the given response.
|
||||
* @param content the body content to expose
|
||||
* @param response the servlet response to wrap
|
||||
*/
|
||||
public MockBodyContent(String content, HttpServletResponse response) {
|
||||
this(content, response, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MockBodyContent for the given response.
|
||||
* @param content the body content to expose
|
||||
* @param targetWriter the target Writer to wrap
|
||||
*/
|
||||
public MockBodyContent(String content, Writer targetWriter) {
|
||||
this(content, null, targetWriter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MockBodyContent for the given response.
|
||||
* @param content the body content to expose
|
||||
* @param response the servlet response to wrap
|
||||
* @param targetWriter the target Writer to wrap
|
||||
*/
|
||||
public MockBodyContent(String content, @Nullable HttpServletResponse response, @Nullable Writer targetWriter) {
|
||||
super(adaptJspWriter(targetWriter, response));
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
private static JspWriter adaptJspWriter(@Nullable Writer targetWriter, @Nullable HttpServletResponse response) {
|
||||
if (targetWriter instanceof JspWriter) {
|
||||
return (JspWriter) targetWriter;
|
||||
}
|
||||
else {
|
||||
return new MockJspWriter(response, targetWriter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Reader getReader() {
|
||||
return new StringReader(this.content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeOut(Writer writer) throws IOException {
|
||||
writer.write(this.content);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Delegating implementations of JspWriter's abstract methods
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void clear() throws IOException {
|
||||
getEnclosingWriter().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBuffer() throws IOException {
|
||||
getEnclosingWriter().clearBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
getEnclosingWriter().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRemaining() {
|
||||
return getEnclosingWriter().getRemaining();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newLine() throws IOException {
|
||||
getEnclosingWriter().println();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] value, int offset, int length) throws IOException {
|
||||
getEnclosingWriter().write(value, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(boolean value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(char value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(char[] value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(double value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(float value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(int value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(long value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(Object value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String value) throws IOException {
|
||||
getEnclosingWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println() throws IOException {
|
||||
getEnclosingWriter().println();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(boolean value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(char value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(char[] value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(double value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(float value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(int value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(long value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(Object value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(String value) throws IOException {
|
||||
getEnclosingWriter().println(value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.time.DateTimeException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Extension of {@code Cookie} with extra attributes, as defined in
|
||||
* <a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a>.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 5.1
|
||||
*/
|
||||
public class MockCookie extends Cookie {
|
||||
|
||||
private static final long serialVersionUID = 4312531139502726325L;
|
||||
|
||||
|
||||
@Nullable
|
||||
private ZonedDateTime expires;
|
||||
|
||||
@Nullable
|
||||
private String sameSite;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new {@link MockCookie} with the supplied name and value.
|
||||
* @param name the name
|
||||
* @param value the value
|
||||
* @see Cookie#Cookie(String, String)
|
||||
*/
|
||||
public MockCookie(String name, String value) {
|
||||
super(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the "Expires" attribute for this cookie.
|
||||
* @since 5.1.11
|
||||
*/
|
||||
public void setExpires(@Nullable ZonedDateTime expires) {
|
||||
this.expires = expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "Expires" attribute for this cookie.
|
||||
* @since 5.1.11
|
||||
* @return the "Expires" attribute for this cookie, or {@code null} if not set
|
||||
*/
|
||||
@Nullable
|
||||
public ZonedDateTime getExpires() {
|
||||
return this.expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the "SameSite" attribute for this cookie.
|
||||
* <p>This limits the scope of the cookie such that it will only be attached
|
||||
* to same-site requests if the supplied value is {@code "Strict"} or cross-site
|
||||
* requests if the supplied value is {@code "Lax"}.
|
||||
* @see <a href="https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis#section-4.1.2.7">RFC6265 bis</a>
|
||||
*/
|
||||
public void setSameSite(@Nullable String sameSite) {
|
||||
this.sameSite = sameSite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "SameSite" attribute for this cookie.
|
||||
* @return the "SameSite" attribute for this cookie, or {@code null} if not set
|
||||
*/
|
||||
@Nullable
|
||||
public String getSameSite() {
|
||||
return this.sameSite;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory method that parses the value of the supplied "Set-Cookie" header.
|
||||
* @param setCookieHeader the "Set-Cookie" value; never {@code null} or empty
|
||||
* @return the created cookie
|
||||
*/
|
||||
public static MockCookie parse(String setCookieHeader) {
|
||||
Assert.notNull(setCookieHeader, "Set-Cookie header must not be null");
|
||||
String[] cookieParts = setCookieHeader.split("\\s*=\\s*", 2);
|
||||
Assert.isTrue(cookieParts.length == 2, () -> "Invalid Set-Cookie header '" + setCookieHeader + "'");
|
||||
|
||||
String name = cookieParts[0];
|
||||
String[] valueAndAttributes = cookieParts[1].split("\\s*;\\s*", 2);
|
||||
String value = valueAndAttributes[0];
|
||||
String[] attributes =
|
||||
(valueAndAttributes.length > 1 ? valueAndAttributes[1].split("\\s*;\\s*") : new String[0]);
|
||||
|
||||
MockCookie cookie = new MockCookie(name, value);
|
||||
for (String attribute : attributes) {
|
||||
if (StringUtils.startsWithIgnoreCase(attribute, "Domain")) {
|
||||
cookie.setDomain(extractAttributeValue(attribute, setCookieHeader));
|
||||
}
|
||||
else if (StringUtils.startsWithIgnoreCase(attribute, "Max-Age")) {
|
||||
cookie.setMaxAge(Integer.parseInt(extractAttributeValue(attribute, setCookieHeader)));
|
||||
}
|
||||
else if (StringUtils.startsWithIgnoreCase(attribute, "Expires")) {
|
||||
try {
|
||||
cookie.setExpires(ZonedDateTime.parse(extractAttributeValue(attribute, setCookieHeader),
|
||||
DateTimeFormatter.RFC_1123_DATE_TIME));
|
||||
}
|
||||
catch (DateTimeException ex) {
|
||||
// ignore invalid date formats
|
||||
}
|
||||
}
|
||||
else if (StringUtils.startsWithIgnoreCase(attribute, "Path")) {
|
||||
cookie.setPath(extractAttributeValue(attribute, setCookieHeader));
|
||||
}
|
||||
else if (StringUtils.startsWithIgnoreCase(attribute, "Secure")) {
|
||||
cookie.setSecure(true);
|
||||
}
|
||||
else if (StringUtils.startsWithIgnoreCase(attribute, "HttpOnly")) {
|
||||
cookie.setHttpOnly(true);
|
||||
}
|
||||
else if (StringUtils.startsWithIgnoreCase(attribute, "SameSite")) {
|
||||
cookie.setSameSite(extractAttributeValue(attribute, setCookieHeader));
|
||||
}
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
|
||||
private static String extractAttributeValue(String attribute, String header) {
|
||||
String[] nameAndValue = attribute.split("=");
|
||||
Assert.isTrue(nameAndValue.length == 2,
|
||||
() -> "No value in attribute '" + nameAndValue[0] + "' for Set-Cookie header '" + header + "'");
|
||||
return nameAndValue[1];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
|
||||
|
||||
/**
|
||||
* Mock implementation of the JSP 2.0 {@link javax.servlet.jsp.el.ExpressionEvaluator}
|
||||
* interface, delegating to the Apache JSTL {@link ExpressionEvaluatorManager}.
|
||||
* Only necessary for testing applications when testing custom JSP tags.
|
||||
*
|
||||
* <p>Note that the Apache JSTL implementation (jstl.jar, standard.jar) has to be
|
||||
* available on the classpath to use this expression evaluator.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1.5
|
||||
* @see org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MockExpressionEvaluator extends javax.servlet.jsp.el.ExpressionEvaluator {
|
||||
|
||||
private final PageContext pageContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockExpressionEvaluator for the given PageContext.
|
||||
* @param pageContext the JSP PageContext to run in
|
||||
*/
|
||||
public MockExpressionEvaluator(PageContext pageContext) {
|
||||
this.pageContext = pageContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public javax.servlet.jsp.el.Expression parseExpression(final String expression, final Class expectedType,
|
||||
final javax.servlet.jsp.el.FunctionMapper functionMapper) throws javax.servlet.jsp.el.ELException {
|
||||
|
||||
return new javax.servlet.jsp.el.Expression() {
|
||||
@Override
|
||||
public Object evaluate(javax.servlet.jsp.el.VariableResolver variableResolver) throws javax.servlet.jsp.el.ELException {
|
||||
return doEvaluate(expression, expectedType, functionMapper);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Object evaluate(String expression, Class expectedType, javax.servlet.jsp.el.VariableResolver variableResolver,
|
||||
javax.servlet.jsp.el.FunctionMapper functionMapper) throws javax.servlet.jsp.el.ELException {
|
||||
|
||||
return doEvaluate(expression, expectedType, functionMapper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected Object doEvaluate(String expression, Class expectedType, javax.servlet.jsp.el.FunctionMapper functionMapper)
|
||||
throws javax.servlet.jsp.el.ELException {
|
||||
|
||||
try {
|
||||
return ExpressionEvaluatorManager.evaluate("JSP EL expression", expression, expectedType, this.pageContext);
|
||||
}
|
||||
catch (JspException ex) {
|
||||
throw new javax.servlet.jsp.el.ELException("Parsing of JSP EL expression \"" + expression + "\" failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.FilterChain} interface.
|
||||
*
|
||||
* <p>A {@link MockFilterChain} can be configured with one or more filters and a
|
||||
* Servlet to invoke. The first time the chain is called, it invokes all filters
|
||||
* and the Servlet, and saves the request and response. Subsequent invocations
|
||||
* raise an {@link IllegalStateException} unless {@link #reset()} is called.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Winch
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.0.3
|
||||
* @see MockFilterConfig
|
||||
* @see PassThroughFilterChain
|
||||
*/
|
||||
public class MockFilterChain implements FilterChain {
|
||||
|
||||
@Nullable
|
||||
private ServletRequest request;
|
||||
|
||||
@Nullable
|
||||
private ServletResponse response;
|
||||
|
||||
private final List<Filter> filters;
|
||||
|
||||
@Nullable
|
||||
private Iterator<Filter> iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Register a single do-nothing {@link Filter} implementation. The first
|
||||
* invocation saves the request and response. Subsequent invocations raise
|
||||
* an {@link IllegalStateException} unless {@link #reset()} is called.
|
||||
*/
|
||||
public MockFilterChain() {
|
||||
this.filters = Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FilterChain with a Servlet.
|
||||
* @param servlet the Servlet to invoke
|
||||
* @since 3.2
|
||||
*/
|
||||
public MockFilterChain(Servlet servlet) {
|
||||
this.filters = initFilterList(servlet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code FilterChain} with Filter's and a Servlet.
|
||||
* @param servlet the {@link Servlet} to invoke in this {@link FilterChain}
|
||||
* @param filters the {@link Filter}'s to invoke in this {@link FilterChain}
|
||||
* @since 3.2
|
||||
*/
|
||||
public MockFilterChain(Servlet servlet, Filter... filters) {
|
||||
Assert.notNull(filters, "filters cannot be null");
|
||||
Assert.noNullElements(filters, "filters cannot contain null values");
|
||||
this.filters = initFilterList(servlet, filters);
|
||||
}
|
||||
|
||||
private static List<Filter> initFilterList(Servlet servlet, Filter... filters) {
|
||||
Filter[] allFilters = ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet));
|
||||
return Arrays.asList(allFilters);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the request that {@link #doFilter} has been called with.
|
||||
*/
|
||||
@Nullable
|
||||
public ServletRequest getRequest() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response that {@link #doFilter} has been called with.
|
||||
*/
|
||||
@Nullable
|
||||
public ServletResponse getResponse() {
|
||||
return this.response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke registered {@link Filter Filters} and/or {@link Servlet} also saving the
|
||||
* request and response.
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
Assert.notNull(request, "Request must not be null");
|
||||
Assert.notNull(response, "Response must not be null");
|
||||
Assert.state(this.request == null, "This FilterChain has already been called!");
|
||||
|
||||
if (this.iterator == null) {
|
||||
this.iterator = this.filters.iterator();
|
||||
}
|
||||
|
||||
if (this.iterator.hasNext()) {
|
||||
Filter nextFilter = this.iterator.next();
|
||||
nextFilter.doFilter(request, response, this);
|
||||
}
|
||||
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the {@link MockFilterChain} allowing it to be invoked again.
|
||||
*/
|
||||
public void reset() {
|
||||
this.request = null;
|
||||
this.response = null;
|
||||
this.iterator = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A filter that simply delegates to a Servlet.
|
||||
*/
|
||||
private static final class ServletFilterProxy implements Filter {
|
||||
|
||||
private final Servlet delegateServlet;
|
||||
|
||||
private ServletFilterProxy(Servlet servlet) {
|
||||
Assert.notNull(servlet, "servlet cannot be null");
|
||||
this.delegateServlet = servlet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
this.delegateServlet.service(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.delegateServlet.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.FilterConfig} interface.
|
||||
*
|
||||
* <p>Used for testing the web framework; also useful for testing
|
||||
* custom {@link javax.servlet.Filter} implementations.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.0.2
|
||||
* @see MockFilterChain
|
||||
* @see PassThroughFilterChain
|
||||
*/
|
||||
public class MockFilterConfig implements FilterConfig {
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private final String filterName;
|
||||
|
||||
private final Map<String, String> initParameters = new LinkedHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockFilterConfig with a default {@link MockServletContext}.
|
||||
*/
|
||||
public MockFilterConfig() {
|
||||
this(null, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockFilterConfig with a default {@link MockServletContext}.
|
||||
* @param filterName the name of the filter
|
||||
*/
|
||||
public MockFilterConfig(String filterName) {
|
||||
this(null, filterName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockFilterConfig.
|
||||
* @param servletContext the ServletContext that the servlet runs in
|
||||
*/
|
||||
public MockFilterConfig(@Nullable ServletContext servletContext) {
|
||||
this(servletContext, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockFilterConfig.
|
||||
* @param servletContext the ServletContext that the servlet runs in
|
||||
* @param filterName the name of the filter
|
||||
*/
|
||||
public MockFilterConfig(@Nullable ServletContext servletContext, String filterName) {
|
||||
this.servletContext = (servletContext != null ? servletContext : new MockServletContext());
|
||||
this.filterName = filterName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getFilterName() {
|
||||
return this.filterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
public void addInitParameter(String name, String value) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
this.initParameters.put(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String name) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
return this.initParameters.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
return Collections.enumeration(this.initParameters.keySet());
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,826 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
|
||||
*
|
||||
* <p>As of Spring Framework 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @author Brian Clozel
|
||||
* @author Vedran Pavic
|
||||
* @author Sebastien Deleuze
|
||||
* @author Sam Brannen
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class MockHttpServletResponse implements HttpServletResponse {
|
||||
|
||||
private static final String CHARSET_PREFIX = "charset=";
|
||||
|
||||
private static final String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
||||
|
||||
private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// ServletResponse properties
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private boolean outputStreamAccessAllowed = true;
|
||||
|
||||
private boolean writerAccessAllowed = true;
|
||||
|
||||
@Nullable
|
||||
private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING;
|
||||
|
||||
private boolean charset = false;
|
||||
|
||||
private final ByteArrayOutputStream content = new ByteArrayOutputStream(1024);
|
||||
|
||||
private final ServletOutputStream outputStream = new ResponseServletOutputStream(this.content);
|
||||
|
||||
@Nullable
|
||||
private PrintWriter writer;
|
||||
|
||||
private long contentLength = 0;
|
||||
|
||||
@Nullable
|
||||
private String contentType;
|
||||
|
||||
private int bufferSize = 4096;
|
||||
|
||||
private boolean committed;
|
||||
|
||||
private Locale locale = Locale.getDefault();
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// HttpServletResponse properties
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private final List<Cookie> cookies = new ArrayList<>();
|
||||
|
||||
private final Map<String, HeaderValueHolder> headers = new LinkedCaseInsensitiveMap<>();
|
||||
|
||||
private int status = HttpServletResponse.SC_OK;
|
||||
|
||||
@Nullable
|
||||
private String errorMessage;
|
||||
|
||||
@Nullable
|
||||
private String forwardedUrl;
|
||||
|
||||
private final List<String> includedUrls = new ArrayList<>();
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// ServletResponse interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set whether {@link #getOutputStream()} access is allowed.
|
||||
* <p>Default is {@code true}.
|
||||
*/
|
||||
public void setOutputStreamAccessAllowed(boolean outputStreamAccessAllowed) {
|
||||
this.outputStreamAccessAllowed = outputStreamAccessAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether {@link #getOutputStream()} access is allowed.
|
||||
*/
|
||||
public boolean isOutputStreamAccessAllowed() {
|
||||
return this.outputStreamAccessAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether {@link #getWriter()} access is allowed.
|
||||
* <p>Default is {@code true}.
|
||||
*/
|
||||
public void setWriterAccessAllowed(boolean writerAccessAllowed) {
|
||||
this.writerAccessAllowed = writerAccessAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether {@link #getOutputStream()} access is allowed.
|
||||
*/
|
||||
public boolean isWriterAccessAllowed() {
|
||||
return this.writerAccessAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the character encoding has been set.
|
||||
* <p>If {@code false}, {@link #getCharacterEncoding()} will return a default encoding value.
|
||||
*/
|
||||
public boolean isCharset() {
|
||||
return this.charset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterEncoding(String characterEncoding) {
|
||||
this.characterEncoding = characterEncoding;
|
||||
this.charset = true;
|
||||
updateContentTypeHeader();
|
||||
}
|
||||
|
||||
private void updateContentTypeHeader() {
|
||||
if (this.contentType != null) {
|
||||
String value = this.contentType;
|
||||
if (this.charset && !this.contentType.toLowerCase().contains(CHARSET_PREFIX)) {
|
||||
value = value + ';' + CHARSET_PREFIX + this.characterEncoding;
|
||||
}
|
||||
doAddHeaderValue(HttpHeaders.CONTENT_TYPE, value, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getCharacterEncoding() {
|
||||
return this.characterEncoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() {
|
||||
Assert.state(this.outputStreamAccessAllowed, "OutputStream access not allowed");
|
||||
return this.outputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintWriter getWriter() throws UnsupportedEncodingException {
|
||||
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));
|
||||
this.writer = new ResponsePrintWriter(targetWriter);
|
||||
}
|
||||
return this.writer;
|
||||
}
|
||||
|
||||
public byte[] getContentAsByteArray() {
|
||||
return this.content.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content of the response body as a {@code String}, using the charset
|
||||
* specified for the response by the application, either through
|
||||
* {@link HttpServletResponse} methods or through a charset parameter on the
|
||||
* {@code Content-Type}.
|
||||
* @return the content as a {@code String}
|
||||
* @throws UnsupportedEncodingException if the character encoding is not supported
|
||||
* @see #getContentAsString(Charset)
|
||||
*/
|
||||
public String getContentAsString() throws UnsupportedEncodingException {
|
||||
return (this.characterEncoding != null ?
|
||||
this.content.toString(this.characterEncoding) : this.content.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content of the response body as a {@code String}, using the provided
|
||||
* {@code fallbackCharset} if no charset has been explicitly defined and otherwise
|
||||
* using the charset specified for the response by the application, either
|
||||
* through {@link HttpServletResponse} methods or through a charset parameter on the
|
||||
* {@code Content-Type}.
|
||||
* @return the content as a {@code String}
|
||||
* @throws UnsupportedEncodingException if the character encoding is not supported
|
||||
* @since 5.2
|
||||
* @see #getContentAsString()
|
||||
*/
|
||||
public String getContentAsString(Charset fallbackCharset) throws UnsupportedEncodingException {
|
||||
return (isCharset() && this.characterEncoding != null ?
|
||||
this.content.toString(this.characterEncoding) :
|
||||
this.content.toString(fallbackCharset.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLength(int contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
doAddHeaderValue(HttpHeaders.CONTENT_LENGTH, contentLength, true);
|
||||
}
|
||||
|
||||
public int getContentLength() {
|
||||
return (int) this.contentLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLengthLong(long contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
doAddHeaderValue(HttpHeaders.CONTENT_LENGTH, contentLength, true);
|
||||
}
|
||||
|
||||
public long getContentLengthLong() {
|
||||
return this.contentLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentType(@Nullable String contentType) {
|
||||
this.contentType = contentType;
|
||||
if (contentType != null) {
|
||||
try {
|
||||
MediaType mediaType = MediaType.parseMediaType(contentType);
|
||||
if (mediaType.getCharset() != null) {
|
||||
this.characterEncoding = mediaType.getCharset().name();
|
||||
this.charset = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Try to get charset value anyway
|
||||
int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
|
||||
if (charsetIndex != -1) {
|
||||
this.characterEncoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
|
||||
this.charset = true;
|
||||
}
|
||||
}
|
||||
updateContentTypeHeader();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBufferSize(int bufferSize) {
|
||||
this.bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferSize() {
|
||||
return this.bufferSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBuffer() {
|
||||
setCommitted(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetBuffer() {
|
||||
Assert.state(!isCommitted(), "Cannot reset buffer - response is already committed");
|
||||
this.content.reset();
|
||||
}
|
||||
|
||||
private void setCommittedIfBufferSizeExceeded() {
|
||||
int bufSize = getBufferSize();
|
||||
if (bufSize > 0 && this.content.size() > bufSize) {
|
||||
setCommitted(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCommitted(boolean committed) {
|
||||
this.committed = committed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommitted() {
|
||||
return this.committed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
resetBuffer();
|
||||
this.characterEncoding = null;
|
||||
this.contentLength = 0;
|
||||
this.contentType = null;
|
||||
this.locale = Locale.getDefault();
|
||||
this.cookies.clear();
|
||||
this.headers.clear();
|
||||
this.status = HttpServletResponse.SC_OK;
|
||||
this.errorMessage = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(Locale locale) {
|
||||
this.locale = locale;
|
||||
doAddHeaderValue(HttpHeaders.CONTENT_LANGUAGE, locale.toLanguageTag(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// HttpServletResponse interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void addCookie(Cookie cookie) {
|
||||
Assert.notNull(cookie, "Cookie must not be null");
|
||||
this.cookies.add(cookie);
|
||||
doAddHeaderValue(HttpHeaders.SET_COOKIE, getCookieHeader(cookie), false);
|
||||
}
|
||||
|
||||
private String getCookieHeader(Cookie cookie) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(cookie.getName()).append('=').append(cookie.getValue() == null ? "" : cookie.getValue());
|
||||
if (StringUtils.hasText(cookie.getPath())) {
|
||||
buf.append("; Path=").append(cookie.getPath());
|
||||
}
|
||||
if (StringUtils.hasText(cookie.getDomain())) {
|
||||
buf.append("; Domain=").append(cookie.getDomain());
|
||||
}
|
||||
int maxAge = cookie.getMaxAge();
|
||||
if (maxAge >= 0) {
|
||||
buf.append("; Max-Age=").append(maxAge);
|
||||
buf.append("; Expires=");
|
||||
ZonedDateTime expires = (cookie instanceof MockCookie ? ((MockCookie) cookie).getExpires() : null);
|
||||
if (expires != null) {
|
||||
buf.append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
|
||||
}
|
||||
else {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setExpires(maxAge > 0 ? System.currentTimeMillis() + 1000L * maxAge : 0);
|
||||
buf.append(headers.getFirst(HttpHeaders.EXPIRES));
|
||||
}
|
||||
}
|
||||
|
||||
if (cookie.getSecure()) {
|
||||
buf.append("; Secure");
|
||||
}
|
||||
if (cookie.isHttpOnly()) {
|
||||
buf.append("; HttpOnly");
|
||||
}
|
||||
if (cookie instanceof MockCookie) {
|
||||
MockCookie mockCookie = (MockCookie) cookie;
|
||||
if (StringUtils.hasText(mockCookie.getSameSite())) {
|
||||
buf.append("; SameSite=").append(mockCookie.getSameSite());
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public Cookie[] getCookies() {
|
||||
return this.cookies.toArray(new Cookie[0]);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Cookie getCookie(String name) {
|
||||
Assert.notNull(name, "Cookie name must not be null");
|
||||
for (Cookie cookie : this.cookies) {
|
||||
if (name.equals(cookie.getName())) {
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsHeader(String name) {
|
||||
return (this.headers.get(name) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the names of all specified headers as a Set of Strings.
|
||||
* <p>As of Servlet 3.0, this method is also defined HttpServletResponse.
|
||||
* @return the {@code Set} of header name {@code Strings}, or an empty {@code Set} if none
|
||||
*/
|
||||
@Override
|
||||
public Collection<String> getHeaderNames() {
|
||||
return this.headers.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the primary value for the given header as a String, if any.
|
||||
* Will return the first value in case of multiple values.
|
||||
* <p>As of Servlet 3.0, this method is also defined in HttpServletResponse.
|
||||
* As of Spring 3.1, it returns a stringified value for Servlet 3.0 compatibility.
|
||||
* Consider using {@link #getHeaderValue(String)} for raw Object access.
|
||||
* @param name the name of the header
|
||||
* @return the associated header value, or {@code null} if none
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getHeader(String name) {
|
||||
HeaderValueHolder header = this.headers.get(name);
|
||||
return (header != null ? header.getStringValue() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all values for the given header as a List of Strings.
|
||||
* <p>As of Servlet 3.0, this method is also defined in HttpServletResponse.
|
||||
* As of Spring 3.1, it returns a List of stringified values for Servlet 3.0 compatibility.
|
||||
* Consider using {@link #getHeaderValues(String)} for raw Object access.
|
||||
* @param name the name of the header
|
||||
* @return the associated header values, or an empty List if none
|
||||
*/
|
||||
@Override
|
||||
public List<String> getHeaders(String name) {
|
||||
HeaderValueHolder header = this.headers.get(name);
|
||||
if (header != null) {
|
||||
return header.getStringValues();
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the primary value for the given header, if any.
|
||||
* <p>Will return the first value in case of multiple values.
|
||||
* @param name the name of the header
|
||||
* @return the associated header value, or {@code null} if none
|
||||
*/
|
||||
@Nullable
|
||||
public Object getHeaderValue(String name) {
|
||||
HeaderValueHolder header = this.headers.get(name);
|
||||
return (header != null ? header.getValue() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all values for the given header as a List of value objects.
|
||||
* @param name the name of the header
|
||||
* @return the associated header values, or an empty List if none
|
||||
*/
|
||||
public List<Object> getHeaderValues(String name) {
|
||||
HeaderValueHolder header = this.headers.get(name);
|
||||
if (header != null) {
|
||||
return header.getValues();
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation returns the given URL String as-is.
|
||||
* <p>Can be overridden in subclasses, appending a session id or the like.
|
||||
*/
|
||||
@Override
|
||||
public String encodeURL(String url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation delegates to {@link #encodeURL},
|
||||
* returning the given URL String as-is.
|
||||
* <p>Can be overridden in subclasses, appending a session id or the like
|
||||
* in a redirect-specific fashion. For general URL encoding rules,
|
||||
* override the common {@link #encodeURL} method instead, applying
|
||||
* to redirect URLs as well as to general URLs.
|
||||
*/
|
||||
@Override
|
||||
public String encodeRedirectURL(String url) {
|
||||
return encodeURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String encodeUrl(String url) {
|
||||
return encodeURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String encodeRedirectUrl(String url) {
|
||||
return encodeRedirectURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int status, String errorMessage) throws IOException {
|
||||
Assert.state(!isCommitted(), "Cannot set error status - response is already committed");
|
||||
this.status = status;
|
||||
this.errorMessage = errorMessage;
|
||||
setCommitted(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int status) throws IOException {
|
||||
Assert.state(!isCommitted(), "Cannot set error status - response is already committed");
|
||||
this.status = status;
|
||||
setCommitted(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String url) throws IOException {
|
||||
Assert.state(!isCommitted(), "Cannot send redirect - response is already committed");
|
||||
Assert.notNull(url, "Redirect URL must not be null");
|
||||
setHeader(HttpHeaders.LOCATION, url);
|
||||
setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
|
||||
setCommitted(true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getRedirectedUrl() {
|
||||
return getHeader(HttpHeaders.LOCATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDateHeader(String name, long value) {
|
||||
setHeaderValue(name, formatDate(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDateHeader(String name, long value) {
|
||||
addHeaderValue(name, formatDate(value));
|
||||
}
|
||||
|
||||
public long getDateHeader(String name) {
|
||||
String headerValue = getHeader(name);
|
||||
if (headerValue == null) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return newDateFormat().parse(getHeader(name)).getTime();
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Value for header '" + name + "' is not a valid Date: " + headerValue);
|
||||
}
|
||||
}
|
||||
|
||||
private String formatDate(long date) {
|
||||
return newDateFormat().format(new Date(date));
|
||||
}
|
||||
|
||||
private DateFormat newDateFormat() {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
|
||||
dateFormat.setTimeZone(GMT);
|
||||
return dateFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value) {
|
||||
setHeaderValue(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value) {
|
||||
addHeaderValue(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIntHeader(String name, int value) {
|
||||
setHeaderValue(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIntHeader(String name, int value) {
|
||||
addHeaderValue(name, value);
|
||||
}
|
||||
|
||||
private void setHeaderValue(String name, Object value) {
|
||||
boolean replaceHeader = true;
|
||||
if (setSpecialHeader(name, value, replaceHeader)) {
|
||||
return;
|
||||
}
|
||||
doAddHeaderValue(name, value, replaceHeader);
|
||||
}
|
||||
|
||||
private void addHeaderValue(String name, Object value) {
|
||||
boolean replaceHeader = false;
|
||||
if (setSpecialHeader(name, value, replaceHeader)) {
|
||||
return;
|
||||
}
|
||||
doAddHeaderValue(name, value, replaceHeader);
|
||||
}
|
||||
|
||||
private boolean setSpecialHeader(String name, Object value, boolean replaceHeader) {
|
||||
if (HttpHeaders.CONTENT_TYPE.equalsIgnoreCase(name)) {
|
||||
setContentType(value.toString());
|
||||
return true;
|
||||
}
|
||||
else if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name)) {
|
||||
setContentLength(value instanceof Number ? ((Number) value).intValue() :
|
||||
Integer.parseInt(value.toString()));
|
||||
return true;
|
||||
}
|
||||
else if (HttpHeaders.CONTENT_LANGUAGE.equalsIgnoreCase(name)) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_LANGUAGE, value.toString());
|
||||
Locale language = headers.getContentLanguage();
|
||||
setLocale(language != null ? language : Locale.getDefault());
|
||||
return true;
|
||||
}
|
||||
else if (HttpHeaders.SET_COOKIE.equalsIgnoreCase(name)) {
|
||||
MockCookie cookie = MockCookie.parse(value.toString());
|
||||
if (replaceHeader) {
|
||||
setCookie(cookie);
|
||||
}
|
||||
else {
|
||||
addCookie(cookie);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void doAddHeaderValue(String name, Object value, boolean replace) {
|
||||
HeaderValueHolder header = this.headers.get(name);
|
||||
Assert.notNull(value, "Header value must not be null");
|
||||
if (header == null) {
|
||||
header = new HeaderValueHolder();
|
||||
this.headers.put(name, header);
|
||||
}
|
||||
if (replace) {
|
||||
header.setValue(value);
|
||||
}
|
||||
else {
|
||||
header.addValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code Set-Cookie} header to the supplied {@link Cookie},
|
||||
* overwriting any previous cookies.
|
||||
* @param cookie the {@code Cookie} to set
|
||||
* @since 5.1.10
|
||||
* @see #addCookie(Cookie)
|
||||
*/
|
||||
private void setCookie(Cookie cookie) {
|
||||
Assert.notNull(cookie, "Cookie must not be null");
|
||||
this.cookies.clear();
|
||||
this.cookies.add(cookie);
|
||||
doAddHeaderValue(HttpHeaders.SET_COOKIE, getCookieHeader(cookie), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatus(int status) {
|
||||
if (!this.isCommitted()) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void setStatus(int status, String errorMessage) {
|
||||
if (!this.isCommitted()) {
|
||||
this.status = status;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getErrorMessage() {
|
||||
return this.errorMessage;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Methods for MockRequestDispatcher
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public void setForwardedUrl(@Nullable String forwardedUrl) {
|
||||
this.forwardedUrl = forwardedUrl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getForwardedUrl() {
|
||||
return this.forwardedUrl;
|
||||
}
|
||||
|
||||
public void setIncludedUrl(@Nullable String includedUrl) {
|
||||
this.includedUrls.clear();
|
||||
if (includedUrl != null) {
|
||||
this.includedUrls.add(includedUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getIncludedUrl() {
|
||||
int count = this.includedUrls.size();
|
||||
Assert.state(count <= 1,
|
||||
() -> "More than 1 URL included - check getIncludedUrls instead: " + this.includedUrls);
|
||||
return (count == 1 ? this.includedUrls.get(0) : null);
|
||||
}
|
||||
|
||||
public void addIncludedUrl(String includedUrl) {
|
||||
Assert.notNull(includedUrl, "Included URL must not be null");
|
||||
this.includedUrls.add(includedUrl);
|
||||
}
|
||||
|
||||
public List<String> getIncludedUrls() {
|
||||
return this.includedUrls;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class that adapts the ServletOutputStream to mark the
|
||||
* response as committed once the buffer size is exceeded.
|
||||
*/
|
||||
private class ResponseServletOutputStream extends DelegatingServletOutputStream {
|
||||
|
||||
public ResponseServletOutputStream(OutputStream out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
super.write(b);
|
||||
super.flush();
|
||||
setCommittedIfBufferSizeExceeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
super.flush();
|
||||
setCommitted(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class that adapts the PrintWriter to mark the
|
||||
* response as committed once the buffer size is exceeded.
|
||||
*/
|
||||
private class ResponsePrintWriter extends PrintWriter {
|
||||
|
||||
public ResponsePrintWriter(Writer out) {
|
||||
super(out, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] buf, int off, int len) {
|
||||
super.write(buf, off, len);
|
||||
super.flush();
|
||||
setCommittedIfBufferSizeExceeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String s, int off, int len) {
|
||||
super.write(s, off, len);
|
||||
super.flush();
|
||||
setCommittedIfBufferSizeExceeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int c) {
|
||||
super.write(c);
|
||||
super.flush();
|
||||
setCommittedIfBufferSizeExceeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
super.flush();
|
||||
setCommitted(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.flush();
|
||||
super.close();
|
||||
setCommitted(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,306 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.http.HttpSession} interface.
|
||||
*
|
||||
* <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
* @author Mark Fisher
|
||||
* @author Sam Brannen
|
||||
* @author Vedran Pavic
|
||||
* @since 1.0.2
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MockHttpSession implements HttpSession {
|
||||
|
||||
/**
|
||||
* The session cookie name.
|
||||
*/
|
||||
public static final String SESSION_COOKIE_NAME = "JSESSION";
|
||||
|
||||
|
||||
private static int nextId = 1;
|
||||
|
||||
private String id;
|
||||
|
||||
private final long creationTime = System.currentTimeMillis();
|
||||
|
||||
private int maxInactiveInterval;
|
||||
|
||||
private long lastAccessedTime = System.currentTimeMillis();
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<>();
|
||||
|
||||
private boolean invalid = false;
|
||||
|
||||
private boolean isNew = true;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockHttpSession with a default {@link MockServletContext}.
|
||||
* @see MockServletContext
|
||||
*/
|
||||
public MockHttpSession() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockHttpSession.
|
||||
* @param servletContext the ServletContext that the session runs in
|
||||
*/
|
||||
public MockHttpSession(@Nullable ServletContext servletContext) {
|
||||
this(servletContext, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockHttpSession.
|
||||
* @param servletContext the ServletContext that the session runs in
|
||||
* @param id a unique identifier for this session
|
||||
*/
|
||||
public MockHttpSession(@Nullable ServletContext servletContext, @Nullable String id) {
|
||||
this.servletContext = (servletContext != null ? servletContext : new MockServletContext());
|
||||
this.id = (id != null ? id : Integer.toString(nextId++));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getCreationTime() {
|
||||
assertIsValid();
|
||||
return this.creationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* As of Servlet 3.1, the id of a session can be changed.
|
||||
* @return the new session id
|
||||
* @since 4.0.3
|
||||
*/
|
||||
public String changeSessionId() {
|
||||
this.id = Integer.toString(nextId++);
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void access() {
|
||||
this.lastAccessedTime = System.currentTimeMillis();
|
||||
this.isNew = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastAccessedTime() {
|
||||
assertIsValid();
|
||||
return this.lastAccessedTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxInactiveInterval(int interval) {
|
||||
this.maxInactiveInterval = interval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxInactiveInterval() {
|
||||
return this.maxInactiveInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public javax.servlet.http.HttpSessionContext getSessionContext() {
|
||||
throw new UnsupportedOperationException("getSessionContext");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name) {
|
||||
assertIsValid();
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(String name) {
|
||||
return getAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
assertIsValid();
|
||||
return Collections.enumeration(new LinkedHashSet<>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getValueNames() {
|
||||
assertIsValid();
|
||||
return StringUtils.toStringArray(this.attributes.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, @Nullable Object value) {
|
||||
assertIsValid();
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
if (value != null) {
|
||||
Object oldValue = this.attributes.put(name, value);
|
||||
if (value != oldValue) {
|
||||
if (oldValue instanceof HttpSessionBindingListener) {
|
||||
((HttpSessionBindingListener) oldValue).valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
|
||||
}
|
||||
if (value instanceof HttpSessionBindingListener) {
|
||||
((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(this, name, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
removeAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putValue(String name, Object value) {
|
||||
setAttribute(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
assertIsValid();
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
Object value = this.attributes.remove(name);
|
||||
if (value instanceof HttpSessionBindingListener) {
|
||||
((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeValue(String name) {
|
||||
removeAttribute(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all of this session's attributes.
|
||||
*/
|
||||
public void clearAttributes() {
|
||||
for (Iterator<Map.Entry<String, Object>> it = this.attributes.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry<String, Object> entry = it.next();
|
||||
String name = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
it.remove();
|
||||
if (value instanceof HttpSessionBindingListener) {
|
||||
((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates this session then unbinds any objects bound to it.
|
||||
* @throws IllegalStateException if this method is called on an already invalidated session
|
||||
*/
|
||||
@Override
|
||||
public void invalidate() {
|
||||
assertIsValid();
|
||||
this.invalid = true;
|
||||
clearAttributes();
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return this.invalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for asserting that this session has not been
|
||||
* {@linkplain #invalidate() invalidated}.
|
||||
* @throws IllegalStateException if this session has been invalidated
|
||||
*/
|
||||
private void assertIsValid() {
|
||||
Assert.state(!isInvalid(), "The session has already been invalidated");
|
||||
}
|
||||
|
||||
public void setNew(boolean value) {
|
||||
this.isNew = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNew() {
|
||||
assertIsValid();
|
||||
return this.isNew;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the attributes of this session into an object that can be
|
||||
* turned into a byte array with standard Java serialization.
|
||||
* @return a representation of this session's serialized state
|
||||
*/
|
||||
public Serializable serializeState() {
|
||||
HashMap<String, Serializable> state = new HashMap<>();
|
||||
for (Iterator<Map.Entry<String, Object>> it = this.attributes.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry<String, Object> entry = it.next();
|
||||
String name = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
it.remove();
|
||||
if (value instanceof Serializable) {
|
||||
state.put(name, (Serializable) value);
|
||||
}
|
||||
else {
|
||||
// Not serializable... Servlet containers usually automatically
|
||||
// unbind the attribute in this case.
|
||||
if (value instanceof HttpSessionBindingListener) {
|
||||
((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize the attributes of this session from a state object created by
|
||||
* {@link #serializeState()}.
|
||||
* @param state a representation of this session's serialized state
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void deserializeState(Serializable state) {
|
||||
Assert.isTrue(state instanceof Map, "Serialized state needs to be of type [java.util.Map]");
|
||||
this.attributes.putAll((Map<String, Object>) state);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.jsp.JspWriter} class.
|
||||
* Only necessary for testing applications when testing custom JSP tags.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
*/
|
||||
public class MockJspWriter extends JspWriter {
|
||||
|
||||
private final HttpServletResponse response;
|
||||
|
||||
@Nullable
|
||||
private PrintWriter targetWriter;
|
||||
|
||||
|
||||
/**
|
||||
* Create a MockJspWriter for the given response,
|
||||
* using the response's default Writer.
|
||||
* @param response the servlet response to wrap
|
||||
*/
|
||||
public MockJspWriter(HttpServletResponse response) {
|
||||
this(response, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MockJspWriter for the given plain Writer.
|
||||
* @param targetWriter the target Writer to wrap
|
||||
*/
|
||||
public MockJspWriter(Writer targetWriter) {
|
||||
this(null, targetWriter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MockJspWriter for the given response.
|
||||
* @param response the servlet response to wrap
|
||||
* @param targetWriter the target Writer to wrap
|
||||
*/
|
||||
public MockJspWriter(@Nullable HttpServletResponse response, @Nullable Writer targetWriter) {
|
||||
super(DEFAULT_BUFFER, true);
|
||||
this.response = (response != null ? response : new MockHttpServletResponse());
|
||||
if (targetWriter instanceof PrintWriter) {
|
||||
this.targetWriter = (PrintWriter) targetWriter;
|
||||
}
|
||||
else if (targetWriter != null) {
|
||||
this.targetWriter = new PrintWriter(targetWriter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily initialize the target Writer.
|
||||
*/
|
||||
protected PrintWriter getTargetWriter() throws IOException {
|
||||
if (this.targetWriter == null) {
|
||||
this.targetWriter = this.response.getWriter();
|
||||
}
|
||||
return this.targetWriter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() throws IOException {
|
||||
if (this.response.isCommitted()) {
|
||||
throw new IOException("Response already committed");
|
||||
}
|
||||
this.response.resetBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBuffer() throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
this.response.flushBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRemaining() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newLine() throws IOException {
|
||||
getTargetWriter().println();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(char[] value, int offset, int length) throws IOException {
|
||||
getTargetWriter().write(value, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(boolean value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(char value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(char[] value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(double value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(float value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(int value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(long value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(Object value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String value) throws IOException {
|
||||
getTargetWriter().print(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println() throws IOException {
|
||||
getTargetWriter().println();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(boolean value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(char value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(char[] value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(double value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(float value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(int value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(long value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(Object value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(String value) throws IOException {
|
||||
getTargetWriter().println(value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link org.springframework.web.multipart.MultipartFile}
|
||||
* interface.
|
||||
*
|
||||
* <p>Useful in conjunction with a {@link MockMultipartHttpServletRequest}
|
||||
* for testing application controllers that access multipart uploads.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Eric Crampton
|
||||
* @since 2.0
|
||||
* @see MockMultipartHttpServletRequest
|
||||
*/
|
||||
public class MockMultipartFile implements MultipartFile {
|
||||
|
||||
private final String name;
|
||||
|
||||
private String originalFilename;
|
||||
|
||||
@Nullable
|
||||
private String contentType;
|
||||
|
||||
private final byte[] content;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockMultipartFile with the given content.
|
||||
* @param name the name of the file
|
||||
* @param content the content of the file
|
||||
*/
|
||||
public MockMultipartFile(String name, @Nullable byte[] content) {
|
||||
this(name, "", null, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockMultipartFile with the given content.
|
||||
* @param name the name of the file
|
||||
* @param contentStream the content of the file as stream
|
||||
* @throws IOException if reading from the stream failed
|
||||
*/
|
||||
public MockMultipartFile(String name, InputStream contentStream) throws IOException {
|
||||
this(name, "", null, FileCopyUtils.copyToByteArray(contentStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockMultipartFile with the given content.
|
||||
* @param name the name of the file
|
||||
* @param originalFilename the original filename (as on the client's machine)
|
||||
* @param contentType the content type (if known)
|
||||
* @param content the content of the file
|
||||
*/
|
||||
public MockMultipartFile(
|
||||
String name, @Nullable String originalFilename, @Nullable String contentType, @Nullable byte[] content) {
|
||||
|
||||
Assert.hasLength(name, "Name must not be null");
|
||||
this.name = name;
|
||||
this.originalFilename = (originalFilename != null ? originalFilename : "");
|
||||
this.contentType = contentType;
|
||||
this.content = (content != null ? content : new byte[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockMultipartFile with the given content.
|
||||
* @param name the name of the file
|
||||
* @param originalFilename the original filename (as on the client's machine)
|
||||
* @param contentType the content type (if known)
|
||||
* @param contentStream the content of the file as stream
|
||||
* @throws IOException if reading from the stream failed
|
||||
*/
|
||||
public MockMultipartFile(
|
||||
String name, @Nullable String originalFilename, @Nullable String contentType, InputStream contentStream)
|
||||
throws IOException {
|
||||
|
||||
this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return this.originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return (this.content.length == 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return this.content.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(this.content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||
FileCopyUtils.copy(this.content, dest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
/**
|
||||
* Mock implementation of the
|
||||
* {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface.
|
||||
*
|
||||
* <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
|
||||
*
|
||||
* <p>Useful for testing application controllers that access multipart uploads.
|
||||
* {@link MockMultipartFile} can be used to populate these mock requests with files.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Eric Crampton
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
* @see MockMultipartFile
|
||||
*/
|
||||
public class MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest {
|
||||
|
||||
private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code MockMultipartHttpServletRequest} with a default
|
||||
* {@link MockServletContext}.
|
||||
* @see #MockMultipartHttpServletRequest(ServletContext)
|
||||
*/
|
||||
public MockMultipartHttpServletRequest() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MockMultipartHttpServletRequest} with the supplied {@link ServletContext}.
|
||||
* @param servletContext the ServletContext that the request runs in
|
||||
* (may be {@code null} to use a default {@link MockServletContext})
|
||||
*/
|
||||
public MockMultipartHttpServletRequest(@Nullable ServletContext servletContext) {
|
||||
super(servletContext);
|
||||
setMethod("POST");
|
||||
setContentType("multipart/form-data");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a file to this request. The parameter name from the multipart
|
||||
* form is taken from the {@link MultipartFile#getName()}.
|
||||
* @param file multipart file to be added
|
||||
*/
|
||||
public void addFile(MultipartFile file) {
|
||||
Assert.notNull(file, "MultipartFile must not be null");
|
||||
this.multipartFiles.add(file.getName(), file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> getFileNames() {
|
||||
return this.multipartFiles.keySet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartFile getFile(String name) {
|
||||
return this.multipartFiles.getFirst(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
|
||||
if (multipartFiles != null) {
|
||||
return multipartFiles;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
return this.multipartFiles.toSingleValueMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
return new LinkedMultiValueMap<>(this.multipartFiles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultipartContentType(String paramOrFileName) {
|
||||
MultipartFile file = getFile(paramOrFileName);
|
||||
if (file != null) {
|
||||
return file.getContentType();
|
||||
}
|
||||
try {
|
||||
Part part = getPart(paramOrFileName);
|
||||
if (part != null) {
|
||||
return part.getContentType();
|
||||
}
|
||||
}
|
||||
catch (ServletException | IOException ex) {
|
||||
// Should never happen (we're not actually parsing)
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpMethod getRequestMethod() {
|
||||
return HttpMethod.resolve(getMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getRequestHeaders() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Enumeration<String> headerNames = getHeaderNames();
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String headerName = headerNames.nextElement();
|
||||
headers.put(headerName, Collections.list(getHeaders(headerName)));
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getMultipartHeaders(String paramOrFileName) {
|
||||
String contentType = getMultipartContentType(paramOrFileName);
|
||||
if (contentType != null) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("Content-Type", contentType);
|
||||
return headers;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,387 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.jsp.JspWriter;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.jsp.PageContext} interface.
|
||||
* Only necessary for testing applications when testing custom JSP tags.
|
||||
*
|
||||
* <p>Note: Expects initialization via the constructor rather than via the
|
||||
* {@code PageContext.initialize} method. Does not support writing to a
|
||||
* JspWriter, request dispatching, or {@code handlePageException} calls.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class MockPageContext extends PageContext {
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
private final HttpServletResponse response;
|
||||
|
||||
private final ServletConfig servletConfig;
|
||||
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private JspWriter out;
|
||||
|
||||
|
||||
/**
|
||||
* Create new MockPageContext with a default {@link MockServletContext},
|
||||
* {@link MockHttpServletRequest}, {@link MockHttpServletResponse},
|
||||
* {@link MockServletConfig}.
|
||||
*/
|
||||
public MockPageContext() {
|
||||
this(null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new MockPageContext with a default {@link MockHttpServletRequest},
|
||||
* {@link MockHttpServletResponse}, {@link MockServletConfig}.
|
||||
* @param servletContext the ServletContext that the JSP page runs in
|
||||
* (only necessary when actually accessing the ServletContext)
|
||||
*/
|
||||
public MockPageContext(@Nullable ServletContext servletContext) {
|
||||
this(servletContext, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new MockPageContext with a MockHttpServletResponse,
|
||||
* MockServletConfig.
|
||||
* @param servletContext the ServletContext that the JSP page runs in
|
||||
* @param request the current HttpServletRequest
|
||||
* (only necessary when actually accessing the request)
|
||||
*/
|
||||
public MockPageContext(@Nullable ServletContext servletContext, @Nullable HttpServletRequest request) {
|
||||
this(servletContext, request, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new MockPageContext with a MockServletConfig.
|
||||
* @param servletContext the ServletContext that the JSP page runs in
|
||||
* @param request the current HttpServletRequest
|
||||
* @param response the current HttpServletResponse
|
||||
* (only necessary when actually writing to the response)
|
||||
*/
|
||||
public MockPageContext(@Nullable ServletContext servletContext, @Nullable HttpServletRequest request,
|
||||
@Nullable HttpServletResponse response) {
|
||||
|
||||
this(servletContext, request, response, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new MockServletConfig.
|
||||
* @param servletContext the ServletContext that the JSP page runs in
|
||||
* @param request the current HttpServletRequest
|
||||
* @param response the current HttpServletResponse
|
||||
* @param servletConfig the ServletConfig (hardly ever accessed from within a tag)
|
||||
*/
|
||||
public MockPageContext(@Nullable ServletContext servletContext, @Nullable HttpServletRequest request,
|
||||
@Nullable HttpServletResponse response, @Nullable ServletConfig servletConfig) {
|
||||
|
||||
this.servletContext = (servletContext != null ? servletContext : new MockServletContext());
|
||||
this.request = (request != null ? request : new MockHttpServletRequest(servletContext));
|
||||
this.response = (response != null ? response : new MockHttpServletResponse());
|
||||
this.servletConfig = (servletConfig != null ? servletConfig : new MockServletConfig(servletContext));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(
|
||||
Servlet servlet, ServletRequest request, ServletResponse response,
|
||||
String errorPageURL, boolean needsSession, int bufferSize, boolean autoFlush) {
|
||||
|
||||
throw new UnsupportedOperationException("Use appropriate constructor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, @Nullable Object value) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
if (value != null) {
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
else {
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, @Nullable Object value, int scope) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
switch (scope) {
|
||||
case PAGE_SCOPE:
|
||||
setAttribute(name, value);
|
||||
break;
|
||||
case REQUEST_SCOPE:
|
||||
this.request.setAttribute(name, value);
|
||||
break;
|
||||
case SESSION_SCOPE:
|
||||
this.request.getSession().setAttribute(name, value);
|
||||
break;
|
||||
case APPLICATION_SCOPE:
|
||||
this.servletContext.setAttribute(name, value);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid scope: " + scope);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getAttribute(String name) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getAttribute(String name, int scope) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
switch (scope) {
|
||||
case PAGE_SCOPE:
|
||||
return getAttribute(name);
|
||||
case REQUEST_SCOPE:
|
||||
return this.request.getAttribute(name);
|
||||
case SESSION_SCOPE:
|
||||
HttpSession session = this.request.getSession(false);
|
||||
return (session != null ? session.getAttribute(name) : null);
|
||||
case APPLICATION_SCOPE:
|
||||
return this.servletContext.getAttribute(name);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid scope: " + scope);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object findAttribute(String name) {
|
||||
Object value = getAttribute(name);
|
||||
if (value == null) {
|
||||
value = getAttribute(name, REQUEST_SCOPE);
|
||||
if (value == null) {
|
||||
value = getAttribute(name, SESSION_SCOPE);
|
||||
if (value == null) {
|
||||
value = getAttribute(name, APPLICATION_SCOPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
this.removeAttribute(name, PageContext.PAGE_SCOPE);
|
||||
this.removeAttribute(name, PageContext.REQUEST_SCOPE);
|
||||
this.removeAttribute(name, PageContext.SESSION_SCOPE);
|
||||
this.removeAttribute(name, PageContext.APPLICATION_SCOPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name, int scope) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
switch (scope) {
|
||||
case PAGE_SCOPE:
|
||||
this.attributes.remove(name);
|
||||
break;
|
||||
case REQUEST_SCOPE:
|
||||
this.request.removeAttribute(name);
|
||||
break;
|
||||
case SESSION_SCOPE:
|
||||
this.request.getSession().removeAttribute(name);
|
||||
break;
|
||||
case APPLICATION_SCOPE:
|
||||
this.servletContext.removeAttribute(name);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid scope: " + scope);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAttributesScope(String name) {
|
||||
if (getAttribute(name) != null) {
|
||||
return PAGE_SCOPE;
|
||||
}
|
||||
else if (getAttribute(name, REQUEST_SCOPE) != null) {
|
||||
return REQUEST_SCOPE;
|
||||
}
|
||||
else if (getAttribute(name, SESSION_SCOPE) != null) {
|
||||
return SESSION_SCOPE;
|
||||
}
|
||||
else if (getAttribute(name, APPLICATION_SCOPE) != null) {
|
||||
return APPLICATION_SCOPE;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return Collections.enumeration(new LinkedHashSet<>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNamesInScope(int scope) {
|
||||
switch (scope) {
|
||||
case PAGE_SCOPE:
|
||||
return getAttributeNames();
|
||||
case REQUEST_SCOPE:
|
||||
return this.request.getAttributeNames();
|
||||
case SESSION_SCOPE:
|
||||
HttpSession session = this.request.getSession(false);
|
||||
return (session != null ? session.getAttributeNames() : Collections.emptyEnumeration());
|
||||
case APPLICATION_SCOPE:
|
||||
return this.servletContext.getAttributeNames();
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid scope: " + scope);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JspWriter getOut() {
|
||||
if (this.out == null) {
|
||||
this.out = new MockJspWriter(this.response);
|
||||
}
|
||||
return this.out;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public javax.servlet.jsp.el.ExpressionEvaluator getExpressionEvaluator() {
|
||||
return new MockExpressionEvaluator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ELContext getELContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public javax.servlet.jsp.el.VariableResolver getVariableResolver() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getSession() {
|
||||
return this.request.getSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPage() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRequest getRequest() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletResponse getResponse() {
|
||||
return this.response;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Exception getException() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletConfig getServletConfig() {
|
||||
return this.servletConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forward(String path) throws ServletException, IOException {
|
||||
this.request.getRequestDispatcher(path).forward(this.request, this.response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(String path) throws ServletException, IOException {
|
||||
this.request.getRequestDispatcher(path).include(this.request, this.response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(String path, boolean flush) throws ServletException, IOException {
|
||||
this.request.getRequestDispatcher(path).include(this.request, this.response);
|
||||
if (flush) {
|
||||
this.response.flushBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getContentAsByteArray() {
|
||||
Assert.state(this.response instanceof MockHttpServletResponse, "MockHttpServletResponse required");
|
||||
return ((MockHttpServletResponse) this.response).getContentAsByteArray();
|
||||
}
|
||||
|
||||
public String getContentAsString() throws UnsupportedEncodingException {
|
||||
Assert.state(this.response instanceof MockHttpServletResponse, "MockHttpServletResponse required");
|
||||
return ((MockHttpServletResponse) this.response).getContentAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePageException(Exception ex) throws ServletException, IOException {
|
||||
throw new ServletException("Page exception", ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePageException(Throwable ex) throws ServletException, IOException {
|
||||
throw new ServletException("Page exception", ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Mock implementation of {@code javax.servlet.http.Part}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see MockHttpServletRequest#addPart
|
||||
* @see MockMultipartFile
|
||||
*/
|
||||
public class MockPart implements Part {
|
||||
|
||||
private final String name;
|
||||
|
||||
@Nullable
|
||||
private final String filename;
|
||||
|
||||
private final byte[] content;
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for a part with byte[] content only.
|
||||
* @see #getHeaders()
|
||||
*/
|
||||
public MockPart(String name, @Nullable byte[] content) {
|
||||
this(name, null, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a part with a filename and byte[] content.
|
||||
* @see #getHeaders()
|
||||
*/
|
||||
public MockPart(String name, @Nullable String filename, @Nullable byte[] content) {
|
||||
Assert.hasLength(name, "'name' must not be empty");
|
||||
this.name = name;
|
||||
this.filename = filename;
|
||||
this.content = (content != null ? content : new byte[0]);
|
||||
this.headers.setContentDispositionFormData(name, filename);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getSubmittedFileName() {
|
||||
return this.filename;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getContentType() {
|
||||
MediaType contentType = this.headers.getContentType();
|
||||
return (contentType != null ? contentType.toString() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return this.content.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(this.content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String fileName) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getHeader(String name) {
|
||||
return this.headers.getFirst(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getHeaders(String name) {
|
||||
Collection<String> headerValues = this.headers.get(name);
|
||||
return (headerValues != null ? headerValues : Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getHeaderNames() {
|
||||
return this.headers.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link HttpHeaders} backing header related accessor methods,
|
||||
* allowing for populating selected header entries.
|
||||
*/
|
||||
public final HttpHeaders getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.RequestDispatcher} interface.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 1.0.2
|
||||
* @see MockHttpServletRequest#getRequestDispatcher(String)
|
||||
*/
|
||||
public class MockRequestDispatcher implements RequestDispatcher {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final String resource;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockRequestDispatcher for the given resource.
|
||||
* @param resource the server resource to dispatch to, located at a
|
||||
* particular path or given by a particular name
|
||||
*/
|
||||
public MockRequestDispatcher(String resource) {
|
||||
Assert.notNull(resource, "Resource must not be null");
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void forward(ServletRequest request, ServletResponse response) {
|
||||
Assert.notNull(request, "Request must not be null");
|
||||
Assert.notNull(response, "Response must not be null");
|
||||
Assert.state(!response.isCommitted(), "Cannot perform forward - response is already committed");
|
||||
getMockHttpServletResponse(response).setForwardedUrl(this.resource);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("MockRequestDispatcher: forwarding to [" + this.resource + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(ServletRequest request, ServletResponse response) {
|
||||
Assert.notNull(request, "Request must not be null");
|
||||
Assert.notNull(response, "Response must not be null");
|
||||
getMockHttpServletResponse(response).addIncludedUrl(this.resource);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("MockRequestDispatcher: including [" + this.resource + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the underlying {@link MockHttpServletResponse}, unwrapping
|
||||
* {@link HttpServletResponseWrapper} decorators if necessary.
|
||||
*/
|
||||
protected MockHttpServletResponse getMockHttpServletResponse(ServletResponse response) {
|
||||
if (response instanceof MockHttpServletResponse) {
|
||||
return (MockHttpServletResponse) response;
|
||||
}
|
||||
if (response instanceof HttpServletResponseWrapper) {
|
||||
return getMockHttpServletResponse(((HttpServletResponseWrapper) response).getResponse());
|
||||
}
|
||||
throw new IllegalArgumentException("MockRequestDispatcher requires MockHttpServletResponse");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.ServletConfig} interface.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class MockServletConfig implements ServletConfig {
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private final String servletName;
|
||||
|
||||
private final Map<String, String> initParameters = new LinkedHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockServletConfig with a default {@link MockServletContext}.
|
||||
*/
|
||||
public MockServletConfig() {
|
||||
this(null, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockServletConfig with a default {@link MockServletContext}.
|
||||
* @param servletName the name of the servlet
|
||||
*/
|
||||
public MockServletConfig(String servletName) {
|
||||
this(null, servletName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockServletConfig.
|
||||
* @param servletContext the ServletContext that the servlet runs in
|
||||
*/
|
||||
public MockServletConfig(@Nullable ServletContext servletContext) {
|
||||
this(servletContext, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockServletConfig.
|
||||
* @param servletContext the ServletContext that the servlet runs in
|
||||
* @param servletName the name of the servlet
|
||||
*/
|
||||
public MockServletConfig(@Nullable ServletContext servletContext, String servletName) {
|
||||
this.servletContext = (servletContext != null ? servletContext : new MockServletContext());
|
||||
this.servletName = servletName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getServletName() {
|
||||
return this.servletName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
public void addInitParameter(String name, String value) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
this.initParameters.put(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String name) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
return this.initParameters.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
return Collections.enumeration(this.initParameters.keySet());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,747 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterRegistration;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRegistration;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.SessionTrackingMode;
|
||||
import javax.servlet.descriptor.JspConfigDescriptor;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MediaTypeFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.ServletContext} interface.
|
||||
*
|
||||
* <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
|
||||
*
|
||||
* <p>Compatible with Servlet 3.1 but can be configured to expose a specific version
|
||||
* through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.1.
|
||||
* Note that Servlet 3.1 support is limited: servlet, filter and listener
|
||||
* registration methods are not supported; neither is JSP configuration.
|
||||
* We generally do not recommend to unit test your ServletContainerInitializers and
|
||||
* WebApplicationInitializers which is where those registration methods would be used.
|
||||
*
|
||||
* <p>For setting up a full {@code WebApplicationContext} in a test environment, you can
|
||||
* use {@code AnnotationConfigWebApplicationContext}, {@code XmlWebApplicationContext},
|
||||
* or {@code GenericWebApplicationContext}, passing in a corresponding
|
||||
* {@code MockServletContext} instance. Consider configuring your
|
||||
* {@code MockServletContext} with a {@code FileSystemResourceLoader} in order to
|
||||
* interpret resource paths as relative filesystem locations.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 1.0.2
|
||||
* @see #MockServletContext(org.springframework.core.io.ResourceLoader)
|
||||
* @see org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
||||
* @see org.springframework.web.context.support.XmlWebApplicationContext
|
||||
* @see org.springframework.web.context.support.GenericWebApplicationContext
|
||||
*/
|
||||
public class MockServletContext implements ServletContext {
|
||||
|
||||
/** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish: {@value}. */
|
||||
private static final String COMMON_DEFAULT_SERVLET_NAME = "default";
|
||||
|
||||
private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir";
|
||||
|
||||
private static final Set<SessionTrackingMode> DEFAULT_SESSION_TRACKING_MODES = new LinkedHashSet<>(4);
|
||||
|
||||
static {
|
||||
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.COOKIE);
|
||||
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.URL);
|
||||
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.SSL);
|
||||
}
|
||||
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
private final String resourceBasePath;
|
||||
|
||||
private String contextPath = "";
|
||||
|
||||
private final Map<String, ServletContext> contexts = new HashMap<>();
|
||||
|
||||
private int majorVersion = 3;
|
||||
|
||||
private int minorVersion = 1;
|
||||
|
||||
private int effectiveMajorVersion = 3;
|
||||
|
||||
private int effectiveMinorVersion = 1;
|
||||
|
||||
private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<>();
|
||||
|
||||
private String defaultServletName = COMMON_DEFAULT_SERVLET_NAME;
|
||||
|
||||
private final Map<String, String> initParameters = new LinkedHashMap<>();
|
||||
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<>();
|
||||
|
||||
private String servletContextName = "MockServletContext";
|
||||
|
||||
private final Set<String> declaredRoles = new LinkedHashSet<>();
|
||||
|
||||
@Nullable
|
||||
private Set<SessionTrackingMode> sessionTrackingModes;
|
||||
|
||||
private final SessionCookieConfig sessionCookieConfig = new MockSessionCookieConfig();
|
||||
|
||||
private int sessionTimeout;
|
||||
|
||||
@Nullable
|
||||
private String requestCharacterEncoding;
|
||||
|
||||
@Nullable
|
||||
private String responseCharacterEncoding;
|
||||
|
||||
private final Map<String, MediaType> mimeTypes = new LinkedHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code MockServletContext}, using no base path and a
|
||||
* {@link DefaultResourceLoader} (i.e. the classpath root as WAR root).
|
||||
* @see org.springframework.core.io.DefaultResourceLoader
|
||||
*/
|
||||
public MockServletContext() {
|
||||
this("", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MockServletContext}, using a {@link DefaultResourceLoader}.
|
||||
* @param resourceBasePath the root directory of the WAR (should not end with a slash)
|
||||
* @see org.springframework.core.io.DefaultResourceLoader
|
||||
*/
|
||||
public MockServletContext(String resourceBasePath) {
|
||||
this(resourceBasePath, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MockServletContext}, using the specified {@link ResourceLoader}
|
||||
* and no base path.
|
||||
* @param resourceLoader the ResourceLoader to use (or null for the default)
|
||||
*/
|
||||
public MockServletContext(@Nullable ResourceLoader resourceLoader) {
|
||||
this("", resourceLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MockServletContext} using the supplied resource base
|
||||
* path and resource loader.
|
||||
* <p>Registers a {@link MockRequestDispatcher} for the Servlet named
|
||||
* {@literal 'default'}.
|
||||
* @param resourceBasePath the root directory of the WAR (should not end with a slash)
|
||||
* @param resourceLoader the ResourceLoader to use (or null for the default)
|
||||
* @see #registerNamedDispatcher
|
||||
*/
|
||||
public MockServletContext(String resourceBasePath, @Nullable ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader());
|
||||
this.resourceBasePath = resourceBasePath;
|
||||
|
||||
// Use JVM temp dir as ServletContext temp dir.
|
||||
String tempDir = System.getProperty(TEMP_DIR_SYSTEM_PROPERTY);
|
||||
if (tempDir != null) {
|
||||
this.attributes.put(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File(tempDir));
|
||||
}
|
||||
|
||||
registerNamedDispatcher(this.defaultServletName, new MockRequestDispatcher(this.defaultServletName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a full resource location for the given path, prepending the resource
|
||||
* base path of this {@code MockServletContext}.
|
||||
* @param path the path as specified
|
||||
* @return the full resource path
|
||||
*/
|
||||
protected String getResourceLocation(String path) {
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
return this.resourceBasePath + path;
|
||||
}
|
||||
|
||||
public void setContextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextPath() {
|
||||
return this.contextPath;
|
||||
}
|
||||
|
||||
public void registerContext(String contextPath, ServletContext context) {
|
||||
this.contexts.put(contextPath, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getContext(String contextPath) {
|
||||
if (this.contextPath.equals(contextPath)) {
|
||||
return this;
|
||||
}
|
||||
return this.contexts.get(contextPath);
|
||||
}
|
||||
|
||||
public void setMajorVersion(int majorVersion) {
|
||||
this.majorVersion = majorVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMajorVersion() {
|
||||
return this.majorVersion;
|
||||
}
|
||||
|
||||
public void setMinorVersion(int minorVersion) {
|
||||
this.minorVersion = minorVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinorVersion() {
|
||||
return this.minorVersion;
|
||||
}
|
||||
|
||||
public void setEffectiveMajorVersion(int effectiveMajorVersion) {
|
||||
this.effectiveMajorVersion = effectiveMajorVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEffectiveMajorVersion() {
|
||||
return this.effectiveMajorVersion;
|
||||
}
|
||||
|
||||
public void setEffectiveMinorVersion(int effectiveMinorVersion) {
|
||||
this.effectiveMinorVersion = effectiveMinorVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEffectiveMinorVersion() {
|
||||
return this.effectiveMinorVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getMimeType(String filePath) {
|
||||
String extension = StringUtils.getFilenameExtension(filePath);
|
||||
if (this.mimeTypes.containsKey(extension)) {
|
||||
return this.mimeTypes.get(extension).toString();
|
||||
}
|
||||
else {
|
||||
return MediaTypeFactory.getMediaType(filePath).
|
||||
map(MimeType::toString)
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a mime type mapping for use by {@link #getMimeType(String)}.
|
||||
* @param fileExtension a file extension, such as {@code txt}, {@code gif}
|
||||
* @param mimeType the mime type
|
||||
*/
|
||||
public void addMimeType(String fileExtension, MediaType mimeType) {
|
||||
Assert.notNull(fileExtension, "'fileExtension' must not be null");
|
||||
this.mimeTypes.put(fileExtension, mimeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Set<String> getResourcePaths(String path) {
|
||||
String actualPath = (path.endsWith("/") ? path : path + "/");
|
||||
String resourceLocation = getResourceLocation(actualPath);
|
||||
Resource resource = null;
|
||||
try {
|
||||
resource = this.resourceLoader.getResource(resourceLocation);
|
||||
File file = resource.getFile();
|
||||
String[] fileList = file.list();
|
||||
if (ObjectUtils.isEmpty(fileList)) {
|
||||
return null;
|
||||
}
|
||||
Set<String> resourcePaths = new LinkedHashSet<>(fileList.length);
|
||||
for (String fileEntry : fileList) {
|
||||
String resultPath = actualPath + fileEntry;
|
||||
if (resource.createRelative(fileEntry).getFile().isDirectory()) {
|
||||
resultPath += "/";
|
||||
}
|
||||
resourcePaths.add(resultPath);
|
||||
}
|
||||
return resourcePaths;
|
||||
}
|
||||
catch (InvalidPathException | IOException ex ) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Could not get resource paths for " +
|
||||
(resource != null ? resource : resourceLocation), ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public URL getResource(String path) throws MalformedURLException {
|
||||
String resourceLocation = getResourceLocation(path);
|
||||
Resource resource = null;
|
||||
try {
|
||||
resource = this.resourceLoader.getResource(resourceLocation);
|
||||
if (!resource.exists()) {
|
||||
return null;
|
||||
}
|
||||
return resource.getURL();
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (InvalidPathException | IOException ex) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Could not get URL for resource " +
|
||||
(resource != null ? resource : resourceLocation), ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public InputStream getResourceAsStream(String path) {
|
||||
String resourceLocation = getResourceLocation(path);
|
||||
Resource resource = null;
|
||||
try {
|
||||
resource = this.resourceLoader.getResource(resourceLocation);
|
||||
if (!resource.exists()) {
|
||||
return null;
|
||||
}
|
||||
return resource.getInputStream();
|
||||
}
|
||||
catch (InvalidPathException | IOException ex) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Could not open InputStream for resource " +
|
||||
(resource != null ? resource : resourceLocation), ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestDispatcher getRequestDispatcher(String path) {
|
||||
Assert.isTrue(path.startsWith("/"),
|
||||
() -> "RequestDispatcher path [" + path + "] at ServletContext level must start with '/'");
|
||||
return new MockRequestDispatcher(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestDispatcher getNamedDispatcher(String path) {
|
||||
return this.namedRequestDispatchers.get(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link RequestDispatcher} (typically a {@link MockRequestDispatcher})
|
||||
* that acts as a wrapper for the named Servlet.
|
||||
* @param name the name of the wrapped Servlet
|
||||
* @param requestDispatcher the dispatcher that wraps the named Servlet
|
||||
* @see #getNamedDispatcher
|
||||
* @see #unregisterNamedDispatcher
|
||||
*/
|
||||
public void registerNamedDispatcher(String name, RequestDispatcher requestDispatcher) {
|
||||
Assert.notNull(name, "RequestDispatcher name must not be null");
|
||||
Assert.notNull(requestDispatcher, "RequestDispatcher must not be null");
|
||||
this.namedRequestDispatchers.put(name, requestDispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the {@link RequestDispatcher} with the given name.
|
||||
* @param name the name of the dispatcher to unregister
|
||||
* @see #getNamedDispatcher
|
||||
* @see #registerNamedDispatcher
|
||||
*/
|
||||
public void unregisterNamedDispatcher(String name) {
|
||||
Assert.notNull(name, "RequestDispatcher name must not be null");
|
||||
this.namedRequestDispatchers.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the <em>default</em> {@code Servlet}.
|
||||
* <p>Defaults to {@literal 'default'}.
|
||||
* @see #setDefaultServletName
|
||||
*/
|
||||
public String getDefaultServletName() {
|
||||
return this.defaultServletName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the <em>default</em> {@code Servlet}.
|
||||
* <p>Also {@link #unregisterNamedDispatcher unregisters} the current default
|
||||
* {@link RequestDispatcher} and {@link #registerNamedDispatcher replaces}
|
||||
* it with a {@link MockRequestDispatcher} for the provided
|
||||
* {@code defaultServletName}.
|
||||
* @param defaultServletName the name of the <em>default</em> {@code Servlet};
|
||||
* never {@code null} or empty
|
||||
* @see #getDefaultServletName
|
||||
*/
|
||||
public void setDefaultServletName(String defaultServletName) {
|
||||
Assert.hasText(defaultServletName, "defaultServletName must not be null or empty");
|
||||
unregisterNamedDispatcher(this.defaultServletName);
|
||||
this.defaultServletName = defaultServletName;
|
||||
registerNamedDispatcher(this.defaultServletName, new MockRequestDispatcher(this.defaultServletName));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
@Nullable
|
||||
public Servlet getServlet(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Enumeration<Servlet> getServlets() {
|
||||
return Collections.enumeration(Collections.emptySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Enumeration<String> getServletNames() {
|
||||
return Collections.enumeration(Collections.emptySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String message) {
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void log(Exception ex, String message) {
|
||||
logger.info(message, ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String message, Throwable ex) {
|
||||
logger.info(message, ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getRealPath(String path) {
|
||||
String resourceLocation = getResourceLocation(path);
|
||||
Resource resource = null;
|
||||
try {
|
||||
resource = this.resourceLoader.getResource(resourceLocation);
|
||||
return resource.getFile().getAbsolutePath();
|
||||
}
|
||||
catch (InvalidPathException | IOException ex) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Could not determine real path of resource " +
|
||||
(resource != null ? resource : resourceLocation), ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerInfo() {
|
||||
return "MockServletContext";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String name) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
return this.initParameters.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
return Collections.enumeration(this.initParameters.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setInitParameter(String name, String value) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
if (this.initParameters.containsKey(name)) {
|
||||
return false;
|
||||
}
|
||||
this.initParameters.put(name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addInitParameter(String name, String value) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
this.initParameters.put(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getAttribute(String name) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return Collections.enumeration(new LinkedHashSet<>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, @Nullable Object value) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
if (value != null) {
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
else {
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
Assert.notNull(name, "Attribute name must not be null");
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
|
||||
public void setServletContextName(String servletContextName) {
|
||||
this.servletContextName = servletContextName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletContextName() {
|
||||
return this.servletContextName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassLoader getClassLoader() {
|
||||
return ClassUtils.getDefaultClassLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareRoles(String... roleNames) {
|
||||
Assert.notNull(roleNames, "Role names array must not be null");
|
||||
for (String roleName : roleNames) {
|
||||
Assert.hasLength(roleName, "Role name must not be empty");
|
||||
this.declaredRoles.add(roleName);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getDeclaredRoles() {
|
||||
return Collections.unmodifiableSet(this.declaredRoles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
|
||||
throws IllegalStateException, IllegalArgumentException {
|
||||
this.sessionTrackingModes = sessionTrackingModes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
|
||||
return DEFAULT_SESSION_TRACKING_MODES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
|
||||
return (this.sessionTrackingModes != null ?
|
||||
Collections.unmodifiableSet(this.sessionTrackingModes) : DEFAULT_SESSION_TRACKING_MODES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionCookieConfig getSessionCookieConfig() {
|
||||
return this.sessionCookieConfig;
|
||||
}
|
||||
|
||||
@Override // on Servlet 4.0
|
||||
public void setSessionTimeout(int sessionTimeout) {
|
||||
this.sessionTimeout = sessionTimeout;
|
||||
}
|
||||
|
||||
@Override // on Servlet 4.0
|
||||
public int getSessionTimeout() {
|
||||
return this.sessionTimeout;
|
||||
}
|
||||
|
||||
@Override // on Servlet 4.0
|
||||
public void setRequestCharacterEncoding(@Nullable String requestCharacterEncoding) {
|
||||
this.requestCharacterEncoding = requestCharacterEncoding;
|
||||
}
|
||||
|
||||
@Override // on Servlet 4.0
|
||||
@Nullable
|
||||
public String getRequestCharacterEncoding() {
|
||||
return this.requestCharacterEncoding;
|
||||
}
|
||||
|
||||
@Override // on Servlet 4.0
|
||||
public void setResponseCharacterEncoding(@Nullable String responseCharacterEncoding) {
|
||||
this.responseCharacterEncoding = responseCharacterEncoding;
|
||||
}
|
||||
|
||||
@Override // on Servlet 4.0
|
||||
@Nullable
|
||||
public String getResponseCharacterEncoding() {
|
||||
return this.responseCharacterEncoding;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Unsupported Servlet 3.0 registration methods
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public JspConfigDescriptor getJspConfigDescriptor() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // on Servlet 4.0
|
||||
public ServletRegistration.Dynamic addJspFile(String servletName, String jspFile) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, String className) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Servlet> T createServlet(Class<T> c) throws ServletException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always returns {@code null}.
|
||||
* @see javax.servlet.ServletContext#getServletRegistration(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public ServletRegistration getServletRegistration(String servletName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always returns an {@linkplain Collections#emptyMap empty map}.
|
||||
* @see javax.servlet.ServletContext#getServletRegistrations()
|
||||
*/
|
||||
@Override
|
||||
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, String className) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Filter> T createFilter(Class<T> c) throws ServletException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always returns {@code null}.
|
||||
* @see javax.servlet.ServletContext#getFilterRegistration(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public FilterRegistration getFilterRegistration(String filterName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always returns an {@linkplain Collections#emptyMap empty map}.
|
||||
* @see javax.servlet.ServletContext#getFilterRegistrations()
|
||||
*/
|
||||
@Override
|
||||
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(Class<? extends EventListener> listenerClass) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(String className) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends EventListener> void addListener(T t) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends EventListener> T createListener(Class<T> c) throws ServletException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVirtualServerName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.servlet.SessionCookieConfig} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
* @see javax.servlet.ServletContext#getSessionCookieConfig()
|
||||
*/
|
||||
public class MockSessionCookieConfig implements SessionCookieConfig {
|
||||
|
||||
@Nullable
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String domain;
|
||||
|
||||
@Nullable
|
||||
private String path;
|
||||
|
||||
@Nullable
|
||||
private String comment;
|
||||
|
||||
private boolean httpOnly;
|
||||
|
||||
private boolean secure;
|
||||
|
||||
private int maxAge = -1;
|
||||
|
||||
|
||||
@Override
|
||||
public void setName(@Nullable String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDomain(@Nullable String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getDomain() {
|
||||
return this.domain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPath(@Nullable String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(@Nullable String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getComment() {
|
||||
return this.comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHttpOnly(boolean httpOnly) {
|
||||
this.httpOnly = httpOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHttpOnly() {
|
||||
return this.httpOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSecure(boolean secure) {
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return this.secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxAge(int maxAge) {
|
||||
this.maxAge = maxAge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAge() {
|
||||
return this.maxAge;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link javax.servlet.FilterConfig} interface which
|
||||
* simply passes the call through to a given Filter/FilterChain combination
|
||||
* (indicating the next Filter in the chain along with the FilterChain that it is
|
||||
* supposed to work on) or to a given Servlet (indicating the end of the chain).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.3
|
||||
* @see javax.servlet.Filter
|
||||
* @see javax.servlet.Servlet
|
||||
* @see MockFilterChain
|
||||
*/
|
||||
public class PassThroughFilterChain implements FilterChain {
|
||||
|
||||
@Nullable
|
||||
private Filter filter;
|
||||
|
||||
@Nullable
|
||||
private FilterChain nextFilterChain;
|
||||
|
||||
@Nullable
|
||||
private Servlet servlet;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PassThroughFilterChain that delegates to the given Filter,
|
||||
* calling it with the given FilterChain.
|
||||
* @param filter the Filter to delegate to
|
||||
* @param nextFilterChain the FilterChain to use for that next Filter
|
||||
*/
|
||||
public PassThroughFilterChain(Filter filter, FilterChain nextFilterChain) {
|
||||
Assert.notNull(filter, "Filter must not be null");
|
||||
Assert.notNull(nextFilterChain, "'FilterChain must not be null");
|
||||
this.filter = filter;
|
||||
this.nextFilterChain = nextFilterChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PassThroughFilterChain that delegates to the given Servlet.
|
||||
* @param servlet the Servlet to delegate to
|
||||
*/
|
||||
public PassThroughFilterChain(Servlet servlet) {
|
||||
Assert.notNull(servlet, "Servlet must not be null");
|
||||
this.servlet = servlet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pass the call on to the Filter/Servlet.
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws ServletException, IOException {
|
||||
if (this.filter != null) {
|
||||
this.filter.doFilter(request, response, this.nextFilterChain);
|
||||
}
|
||||
else {
|
||||
Assert.state(this.servlet != null, "Neither a Filter not a Servlet set");
|
||||
this.servlet.service(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test.server;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.server.WebSession;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
|
||||
import org.springframework.web.server.session.DefaultWebSessionManager;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
/**
|
||||
* Extension of {@link DefaultServerWebExchange} for use in tests, along with
|
||||
* {@link MockServerHttpRequest} and {@link MockServerHttpResponse}.
|
||||
*
|
||||
* <p>See static factory methods to create an instance.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public final class MockServerWebExchange extends DefaultServerWebExchange {
|
||||
|
||||
|
||||
private MockServerWebExchange(MockServerHttpRequest request, WebSessionManager sessionManager) {
|
||||
super(request, new MockServerHttpResponse(), sessionManager,
|
||||
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MockServerHttpResponse getResponse() {
|
||||
return (MockServerHttpResponse) super.getResponse();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a {@link MockServerWebExchange} from the given mock request.
|
||||
* @param request the request to use.
|
||||
* @return the exchange
|
||||
*/
|
||||
public static MockServerWebExchange from(MockServerHttpRequest request) {
|
||||
return builder(request).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #from(MockServerHttpRequest)} with a mock request builder.
|
||||
* @param requestBuilder the builder for the mock request.
|
||||
* @return the exchange
|
||||
*/
|
||||
public static MockServerWebExchange from(MockServerHttpRequest.BaseBuilder<?> requestBuilder) {
|
||||
return builder(requestBuilder).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Builder} starting with the given mock request.
|
||||
* @param request the request to use.
|
||||
* @return the exchange builder
|
||||
* @since 5.1
|
||||
*/
|
||||
public static MockServerWebExchange.Builder builder(MockServerHttpRequest request) {
|
||||
return new MockServerWebExchange.Builder(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of {@link #builder(MockServerHttpRequest)} with a mock request builder.
|
||||
* @param requestBuilder the builder for the mock request.
|
||||
* @return the exchange builder
|
||||
* @since 5.1
|
||||
*/
|
||||
public static MockServerWebExchange.Builder builder(MockServerHttpRequest.BaseBuilder<?> requestBuilder) {
|
||||
return new MockServerWebExchange.Builder(requestBuilder.build());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builder for a {@link MockServerWebExchange}.
|
||||
* @since 5.1
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
private final MockServerHttpRequest request;
|
||||
|
||||
@Nullable
|
||||
private WebSessionManager sessionManager;
|
||||
|
||||
|
||||
public Builder(MockServerHttpRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the session to use for the exchange.
|
||||
* <p>This is mutually exclusive with {@link #sessionManager(WebSessionManager)}.
|
||||
* @param session the session to use
|
||||
*/
|
||||
public Builder session(WebSession session) {
|
||||
this.sessionManager = exchange -> Mono.just(session);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a {@code WebSessionManager} instance to use with the exchange.
|
||||
* <p>This is mutually exclusive with {@link #session(WebSession)}.
|
||||
* @param sessionManager the session manager to use
|
||||
*/
|
||||
public Builder sessionManager(WebSessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the {@code MockServerWebExchange} instance.
|
||||
*/
|
||||
public MockServerWebExchange build() {
|
||||
return new MockServerWebExchange(this.request,
|
||||
this.sessionManager != null ? this.sessionManager : new DefaultWebSessionManager());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* https://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.mock.web.test.server;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.server.WebSession;
|
||||
import org.springframework.web.server.session.InMemoryWebSessionStore;
|
||||
|
||||
/**
|
||||
* Implementation of {@code WebSession} that delegates to a session instance
|
||||
* obtained via {@link InMemoryWebSessionStore}.
|
||||
*
|
||||
* <p>This is intended for use with the
|
||||
* {@link MockServerWebExchange.Builder#session(WebSession) session(WebSession)}
|
||||
* method of the {@code MockServerWebExchange} builder, eliminating the need
|
||||
* to use {@code WebSessionManager} or {@code WebSessionStore} altogether.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.1
|
||||
*/
|
||||
public class MockWebSession implements WebSession {
|
||||
|
||||
private final WebSession delegate;
|
||||
|
||||
|
||||
public MockWebSession() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public MockWebSession(@Nullable Clock clock) {
|
||||
InMemoryWebSessionStore sessionStore = new InMemoryWebSessionStore();
|
||||
if (clock != null) {
|
||||
sessionStore.setClock(clock);
|
||||
}
|
||||
WebSession session = sessionStore.createWebSession().block();
|
||||
Assert.state(session != null, "WebSession must not be null");
|
||||
this.delegate = session;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.delegate.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAttributes() {
|
||||
return this.delegate.getAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.delegate.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
return this.delegate.isStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> changeSessionId() {
|
||||
return this.delegate.changeSessionId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> invalidate() {
|
||||
return this.delegate.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> save() {
|
||||
return this.delegate.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpired() {
|
||||
return this.delegate.isExpired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getCreationTime() {
|
||||
return this.delegate.getCreationTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getLastAccessTime() {
|
||||
return this.delegate.getLastAccessTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxIdleTime(Duration maxIdleTime) {
|
||||
this.delegate.setMaxIdleTime(maxIdleTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getMaxIdleTime() {
|
||||
return this.delegate.getMaxIdleTime();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
/**
|
||||
* For @NonNull annotations on implementation classes
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.mock.web.test.server;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
@@ -39,13 +39,13 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.remoting.RemoteAccessException;
|
||||
import org.springframework.remoting.support.DefaultRemoteInvocationExecutor;
|
||||
import org.springframework.remoting.support.RemoteInvocation;
|
||||
import org.springframework.remoting.support.RemoteInvocationFactory;
|
||||
import org.springframework.remoting.support.RemoteInvocationResult;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -26,12 +26,12 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -21,10 +21,10 @@ import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -24,10 +24,10 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.HttpMediaTypeNotAcceptableException;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ package org.springframework.web.bind;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.testfixture.EnabledForTestGroups;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -34,12 +34,12 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.FormHttpMessageWriter;
|
||||
import org.springframework.http.codec.multipart.FilePart;
|
||||
import org.springframework.http.codec.multipart.MultipartHttpMessageWriter;
|
||||
import org.springframework.mock.http.client.reactive.test.MockClientHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.test.server.MockServerWebExchange;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.testfixture.http.client.reactive.MockClientHttpRequest;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.core.ResolvableType.forClass;
|
||||
@@ -198,7 +198,7 @@ public class WebExchangeDataBinderTests {
|
||||
data.add("someArray", "456");
|
||||
data.add("part", new ClassPathResource("org/springframework/http/codec/multipart/foo.txt"));
|
||||
data.add("somePartList", new ClassPathResource("org/springframework/http/codec/multipart/foo.txt"));
|
||||
data.add("somePartList", new ClassPathResource("org/springframework/http/server/reactive/spring.png"));
|
||||
data.add("somePartList", new ClassPathResource("/org/springframework/web/spring.png"));
|
||||
binder.bind(exchangeMultipart(data)).block(Duration.ofMillis(5000));
|
||||
|
||||
assertThat(bean.getName()).isEqualTo("bar");
|
||||
|
||||
@@ -29,12 +29,12 @@ import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockMultipartFile;
|
||||
import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
|
||||
import org.springframework.web.bind.ServletRequestParameterPropertyValues;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.multipart.support.StringMultipartFileEditor;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockMultipartFile;
|
||||
import org.springframework.web.testfixture.servlet.MockMultipartHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@ import javax.servlet.ServletException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -21,8 +21,8 @@ import javax.servlet.ServletRequestEvent;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.task.MockRunnable;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.beans.testfixture.beans.DerivedTestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.context.expression.StandardBeanExpressionResolver;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.beans.testfixture.beans.factory.DummyFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpSession;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpSession;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
@@ -26,8 +26,8 @@ import java.util.Date;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -29,9 +29,9 @@ import javax.servlet.http.HttpServletResponseWrapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ import org.springframework.beans.testfixture.beans.DerivedTestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.testfixture.io.SerializationTestUtils;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpSession;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpSession;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.testfixture.beans.DerivedTestBean;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.web.context.ContextCleanupListener;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import javax.servlet.AsyncEvent;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.web.test.MockAsyncContext;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.web.testfixture.servlet.MockAsyncContext;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
@@ -25,10 +25,10 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.mock.web.test.MockAsyncContext;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockAsyncContext;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -25,10 +25,10 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.mock.web.test.MockAsyncContext;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockAsyncContext;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.io.IOException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ import javax.servlet.ServletContextEvent;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.web.context.ContextLoader;
|
||||
import org.springframework.web.context.ContextLoaderListener;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.testfixture.servlet.MockServletContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user