Skip to content

Commit deba32c

Browse files
committedMar 20, 2013
Upgraded all Servlet API mocks to Servlet 3.0 (with a little bit of Servlet 3.1 support in MockHttpServletResponse)
·
v7.0.0-M7v4.0.0.M1
1 parent d03de21 commit deba32c

File tree

16 files changed

+799
-274
lines changed

16 files changed

+799
-274
lines changed
 

‎build.gradle

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,7 @@ project("spring-orm") {
484484
optional("org.hibernate:hibernate-entitymanager:3.6.9.Final")
485485
optional("org.apache.openjpa:openjpa:2.2.1")
486486
optional("javax.jdo:jdo-api:3.0")
487-
provided("javax.servlet:servlet-api:2.5")
488-
testCompile("javax.servlet:javax.servlet-api:3.0.1")
487+
provided("javax.servlet:javax.servlet-api:3.0.1")
489488
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
490489
testCompile("commons-dbcp:commons-dbcp:1.2.2")
491490
testCompile("hsqldb:hsqldb:${hsqldbVersion}")
@@ -508,7 +507,7 @@ project("spring-orm-hibernate4") {
508507
optional("org.hibernate:hibernate-core:4.1.9.Final")
509508
optional("org.hibernate:hibernate-entitymanager:4.1.9.Final")
510509
optional(project(":spring-web"))
511-
optional("javax.servlet:servlet-api:2.5")
510+
optional("javax.servlet:javax.servlet-api:3.0.1")
512511
}
513512
}
514513

@@ -648,7 +647,7 @@ project("spring-test") {
648647
optional(project(":spring-webmvc-portlet"), )
649648
optional("junit:junit:${junitVersion}")
650649
optional("org.testng:testng:6.5.2")
651-
optional("javax.servlet:servlet-api:2.5")
650+
optional("javax.servlet:javax.servlet-api:3.0.1")
652651
optional("javax.servlet.jsp:jsp-api:2.1")
653652
optional("javax.portlet:portlet-api:2.0")
654653
optional("org.eclipse.persistence:javax.persistence:2.0.0")

‎spring-test-mvc/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
1717
package org.springframework.test.web.servlet.request;
1818

1919
import java.io.UnsupportedEncodingException;
20-
import java.lang.reflect.Constructor;
2120
import java.security.Principal;
2221
import java.util.ArrayList;
2322
import java.util.Arrays;
@@ -26,12 +25,10 @@
2625
import java.util.Locale;
2726
import java.util.Map;
2827
import java.util.Map.Entry;
29-
3028
import javax.servlet.ServletContext;
3129
import javax.servlet.ServletRequest;
3230
import javax.servlet.http.Cookie;
3331

34-
import org.springframework.beans.BeanUtils;
3532
import org.springframework.beans.Mergeable;
3633
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3734
import org.springframework.http.HttpHeaders;
@@ -44,7 +41,6 @@
4441
import org.springframework.test.web.servlet.RequestBuilder;
4542
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
4643
import org.springframework.util.Assert;
47-
import org.springframework.util.ClassUtils;
4844
import org.springframework.util.LinkedMultiValueMap;
4945
import org.springframework.util.MultiValueMap;
5046
import org.springframework.util.ObjectUtils;
@@ -69,12 +65,10 @@
6965
*
7066
* @author Rossen Stoyanchev
7167
* @author Arjen Poutsma
72-
* @since 3.2
73-
*/
68+
* @since 3.2
69+
*/
7470
public class MockHttpServletRequestBuilder implements RequestBuilder, Mergeable {
7571

76-
static final boolean servlet3Present = ClassUtils.hasMethod(ServletRequest.class, "startAsync");
77-
7872
private final UriComponents uriComponents;
7973

8074
private final HttpMethod method;
@@ -547,7 +541,6 @@ private boolean containsCookie(Cookie cookie) {
547541
* Build a {@link MockHttpServletRequest}.
548542
*/
549543
public final MockHttpServletRequest buildRequest(ServletContext servletContext) {
550-
551544
MockHttpServletRequest request = createServletRequest(servletContext);
552545

553546
String requestUri = this.uriComponents.getPath();
@@ -645,23 +638,11 @@ public final MockHttpServletRequest buildRequest(ServletContext servletContext)
645638
}
646639

647640
/**
648-
* Creates a new {@link MockHttpServletRequest} based on the given
649-
* {@link ServletContext}. Can be overridden in sub-classes.
641+
* Create a new {@link MockHttpServletRequest} based on the given
642+
* {@link ServletContext}. Can be overridden in subclasses.
650643
*/
651644
protected MockHttpServletRequest createServletRequest(ServletContext servletContext) {
652-
return servlet3Present ? createServlet3Request(servletContext) : new MockHttpServletRequest(servletContext);
653-
}
654-
655-
private MockHttpServletRequest createServlet3Request(ServletContext servletContext) {
656-
try {
657-
String className = "org.springframework.test.web.servlet.request.Servlet3MockHttpServletRequest";
658-
Class<?> clazz = ClassUtils.forName(className, MockHttpServletRequestBuilder.class.getClassLoader());
659-
Constructor<?> constructor = clazz.getConstructor(ServletContext.class);
660-
return (MockHttpServletRequest) BeanUtils.instantiateClass(constructor, servletContext);
661-
}
662-
catch (Throwable t) {
663-
throw new IllegalStateException("Failed to instantiate MockHttpServletRequest", t);
664-
}
645+
return new MockHttpServletRequest(servletContext);
665646
}
666647

667648
/**

‎spring-test-mvc/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,19 +16,15 @@
1616

1717
package org.springframework.test.web.servlet.request;
1818

19-
import java.lang.reflect.Constructor;
2019
import java.util.ArrayList;
2120
import java.util.List;
22-
2321
import javax.servlet.ServletContext;
2422

25-
import org.springframework.beans.BeanUtils;
2623
import org.springframework.http.HttpMethod;
2724
import org.springframework.http.MediaType;
2825
import org.springframework.mock.web.MockHttpServletRequest;
2926
import org.springframework.mock.web.MockMultipartFile;
3027
import org.springframework.mock.web.MockMultipartHttpServletRequest;
31-
import org.springframework.util.ClassUtils;
3228

3329
/**
3430
* Default builder for {@link MockMultipartHttpServletRequest}.
@@ -99,24 +95,11 @@ public Object merge(Object parent) {
9995

10096
@Override
10197
protected final MockHttpServletRequest createServletRequest(ServletContext servletContext) {
102-
MockMultipartHttpServletRequest request = servlet3Present ?
103-
createServlet3Request() : new MockMultipartHttpServletRequest();
98+
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest(servletContext);
10499
for (MockMultipartFile file : this.files) {
105100
request.addFile(file);
106101
}
107102
return request;
108103
}
109104

110-
private MockMultipartHttpServletRequest createServlet3Request() {
111-
try {
112-
String className = "org.springframework.test.web.servlet.request.Servlet3MockMultipartHttpServletRequest";
113-
Class<?> clazz = ClassUtils.forName(className, MockMultipartHttpServletRequestBuilder.class.getClassLoader());
114-
Constructor<?> constructor = clazz.getDeclaredConstructor();
115-
return (MockMultipartHttpServletRequest) BeanUtils.instantiateClass(constructor);
116-
}
117-
catch (Throwable t) {
118-
throw new IllegalStateException("Failed to instantiate MockHttpServletRequest", t);
119-
}
120-
}
121-
122105
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2002-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.mock.web;
17+
18+
import java.io.IOException;
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import javax.servlet.AsyncContext;
22+
import javax.servlet.AsyncEvent;
23+
import javax.servlet.AsyncListener;
24+
import javax.servlet.ServletContext;
25+
import javax.servlet.ServletException;
26+
import javax.servlet.ServletRequest;
27+
import javax.servlet.ServletResponse;
28+
import javax.servlet.http.HttpServletRequest;
29+
import javax.servlet.http.HttpServletResponse;
30+
31+
import org.springframework.beans.BeanUtils;
32+
import org.springframework.web.util.WebUtils;
33+
34+
/**
35+
* Mock implementation of the {@link AsyncContext} interface.
36+
*
37+
* @author Rossen Stoyanchev
38+
* @since 3.2
39+
*/
40+
public class MockAsyncContext implements AsyncContext {
41+
42+
private final HttpServletRequest request;
43+
44+
private final HttpServletResponse response;
45+
46+
private final List<AsyncListener> listeners = new ArrayList<AsyncListener>();
47+
48+
private String dispatchedPath;
49+
50+
private long timeout = 10 * 1000L; // 10 seconds is Tomcat's default
51+
52+
53+
public MockAsyncContext(ServletRequest request, ServletResponse response) {
54+
this.request = (HttpServletRequest) request;
55+
this.response = (HttpServletResponse) response;
56+
}
57+
58+
59+
public ServletRequest getRequest() {
60+
return this.request;
61+
}
62+
63+
public ServletResponse getResponse() {
64+
return this.response;
65+
}
66+
67+
public boolean hasOriginalRequestAndResponse() {
68+
return (this.request instanceof MockHttpServletRequest) && (this.response instanceof MockHttpServletResponse);
69+
}
70+
71+
public void dispatch() {
72+
dispatch(this.request.getRequestURI());
73+
}
74+
75+
public void dispatch(String path) {
76+
dispatch(null, path);
77+
}
78+
79+
public void dispatch(ServletContext context, String path) {
80+
this.dispatchedPath = path;
81+
}
82+
83+
public String getDispatchedPath() {
84+
return this.dispatchedPath;
85+
}
86+
87+
public void complete() {
88+
MockHttpServletRequest mockRequest = WebUtils.getNativeRequest(request, MockHttpServletRequest.class);
89+
if (mockRequest != null) {
90+
mockRequest.setAsyncStarted(false);
91+
}
92+
for (AsyncListener listener : this.listeners) {
93+
try {
94+
listener.onComplete(new AsyncEvent(this, this.request, this.response));
95+
}
96+
catch (IOException e) {
97+
throw new IllegalStateException("AsyncListener failure", e);
98+
}
99+
}
100+
}
101+
102+
public void start(Runnable runnable) {
103+
runnable.run();
104+
}
105+
106+
public void addListener(AsyncListener listener) {
107+
this.listeners.add(listener);
108+
}
109+
110+
public void addListener(AsyncListener listener, ServletRequest request, ServletResponse response) {
111+
this.listeners.add(listener);
112+
}
113+
114+
public List<AsyncListener> getListeners() {
115+
return this.listeners;
116+
}
117+
118+
public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException {
119+
return BeanUtils.instantiateClass(clazz);
120+
}
121+
122+
public void setTimeout(long timeout) {
123+
this.timeout = timeout;
124+
}
125+
126+
public long getTimeout() {
127+
return this.timeout;
128+
}
129+
130+
}

‎spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,33 @@
3636
import java.util.Locale;
3737
import java.util.Map;
3838
import java.util.Set;
39+
import javax.servlet.AsyncContext;
40+
import javax.servlet.DispatcherType;
3941
import javax.servlet.RequestDispatcher;
4042
import javax.servlet.ServletContext;
4143
import javax.servlet.ServletException;
4244
import javax.servlet.ServletInputStream;
45+
import javax.servlet.ServletRequest;
46+
import javax.servlet.ServletResponse;
4347
import javax.servlet.http.Cookie;
4448
import javax.servlet.http.HttpServletRequest;
4549
import javax.servlet.http.HttpServletResponse;
4650
import javax.servlet.http.HttpSession;
51+
import javax.servlet.http.Part;
4752

4853
import org.springframework.util.Assert;
4954
import org.springframework.util.LinkedCaseInsensitiveMap;
5055

5156
/**
5257
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest} interface.
5358
*
54-
* <p>Compatible with Servlet 2.5 and partially with Servlet 3.0 (notable exceptions:
55-
* the {@code getPart(s)} and {@code startAsync} families of methods).
59+
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline.
5660
*
5761
* @author Juergen Hoeller
5862
* @author Rod Johnson
5963
* @author Rick Evans
6064
* @author Mark Fisher
65+
* @author Chris Beams
6166
* @author Sam Brannen
6267
* @since 1.0.2
6368
*/
@@ -142,6 +147,14 @@ public class MockHttpServletRequest implements HttpServletRequest {
142147

143148
private int localPort = DEFAULT_SERVER_PORT;
144149

150+
private boolean asyncStarted = false;
151+
152+
private boolean asyncSupported = false;
153+
154+
private MockAsyncContext asyncContext;
155+
156+
private DispatcherType dispatcherType = DispatcherType.REQUEST;
157+
145158

146159
// ---------------------------------------------------------------------
147160
// HttpServletRequest properties
@@ -181,6 +194,8 @@ public class MockHttpServletRequest implements HttpServletRequest {
181194

182195
private boolean requestedSessionIdFromURL = false;
183196

197+
private final Map<String, Part> parts = new LinkedHashMap<String, Part>();
198+
184199

185200
// ---------------------------------------------------------------------
186201
// Constructors
@@ -210,8 +225,8 @@ public MockHttpServletRequest(String method, String requestURI) {
210225

211226
/**
212227
* Create a new {@code MockHttpServletRequest} with the supplied {@link ServletContext}.
213-
* @param servletContext the ServletContext that the request runs in (may be
214-
* {@code null} to use a default {@link MockServletContext})
228+
* @param servletContext the ServletContext that the request runs in
229+
* (may be {@code null} to use a default {@link MockServletContext})
215230
* @see #MockHttpServletRequest(ServletContext, String, String)
216231
*/
217232
public MockHttpServletRequest(ServletContext servletContext) {
@@ -640,6 +655,51 @@ public int getLocalPort() {
640655
return this.localPort;
641656
}
642657

658+
public AsyncContext startAsync() {
659+
return startAsync(this, null);
660+
}
661+
662+
public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
663+
if (!this.asyncSupported) {
664+
throw new IllegalStateException("Async not supported");
665+
}
666+
this.asyncStarted = true;
667+
this.asyncContext = new MockAsyncContext(request, response);
668+
return this.asyncContext;
669+
}
670+
671+
public void setAsyncStarted(boolean asyncStarted) {
672+
this.asyncStarted = asyncStarted;
673+
}
674+
675+
public boolean isAsyncStarted() {
676+
return this.asyncStarted;
677+
}
678+
679+
public void setAsyncSupported(boolean asyncSupported) {
680+
this.asyncSupported = asyncSupported;
681+
}
682+
683+
public boolean isAsyncSupported() {
684+
return this.asyncSupported;
685+
}
686+
687+
public void setAsyncContext(MockAsyncContext asyncContext) {
688+
this.asyncContext = asyncContext;
689+
}
690+
691+
public AsyncContext getAsyncContext() {
692+
return this.asyncContext;
693+
}
694+
695+
public void setDispatcherType(DispatcherType dispatcherType) {
696+
this.dispatcherType = dispatcherType;
697+
}
698+
699+
public DispatcherType getDispatcherType() {
700+
return this.dispatcherType;
701+
}
702+
643703

644704
// ---------------------------------------------------------------------
645705
// HttpServletRequest interface
@@ -715,8 +775,8 @@ else if (value instanceof Number) {
715775
return ((Number) value).longValue();
716776
}
717777
else if (value != null) {
718-
throw new IllegalArgumentException("Value for header '" + name + "' is neither a Date nor a Number: "
719-
+ value);
778+
throw new IllegalArgumentException(
779+
"Value for header '" + name + "' is neither a Date nor a Number: " + value);
720780
}
721781
else {
722782
return -1L;
@@ -900,11 +960,11 @@ public boolean isRequestedSessionIdFromUrl() {
900960
}
901961

902962
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
903-
return (this.userPrincipal != null && this.remoteUser != null && this.authType != null);
963+
throw new UnsupportedOperationException();
904964
}
905965

906966
public void login(String username, String password) throws ServletException {
907-
throw new ServletException("Username-password authentication not supported - override the login method");
967+
throw new UnsupportedOperationException();
908968
}
909969

910970
public void logout() throws ServletException {
@@ -913,4 +973,16 @@ public void logout() throws ServletException {
913973
this.authType = null;
914974
}
915975

976+
public void addPart(Part part) {
977+
this.parts.put(part.getName(), part);
978+
}
979+
980+
public Part getPart(String name) throws IOException, IllegalStateException, ServletException {
981+
return this.parts.get(name);
982+
}
983+
984+
public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
985+
return this.parts.values();
986+
}
987+
916988
}

‎spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
/**
4141
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
4242
*
43-
* <p>Compatible with Servlet 2.5 as well as Servlet 3.0.
43+
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline. Beyond that,
44+
* this MockHttpServletResponse is also compatible with Servlet 3.1's setContentLengthLong.
4445
*
4546
* @author Juergen Hoeller
4647
* @author Rod Johnson
@@ -75,7 +76,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
7576

7677
private PrintWriter writer;
7778

78-
private int contentLength = 0;
79+
private long contentLength = 0;
7980

8081
private String contentType;
8182

@@ -193,6 +194,15 @@ public void setContentLength(int contentLength) {
193194
}
194195

195196
public int getContentLength() {
197+
return (int) this.contentLength;
198+
}
199+
200+
public void setContentLengthLong(long contentLength) {
201+
this.contentLength = contentLength;
202+
doAddHeaderValue(CONTENT_LENGTH_HEADER, contentLength, true);
203+
}
204+
205+
public long getContentLengthLong() {
196206
return this.contentLength;
197207
}
198208

‎spring-test/src/main/java/org/springframework/mock/web/MockMultipartHttpServletRequest.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import java.util.Iterator;
2222
import java.util.List;
2323
import java.util.Map;
24+
import javax.servlet.ServletContext;
2425

2526
import org.springframework.http.HttpHeaders;
2627
import org.springframework.http.HttpMethod;
@@ -50,7 +51,22 @@ public class MockMultipartHttpServletRequest extends MockHttpServletRequest impl
5051
new LinkedMultiValueMap<String, MultipartFile>();
5152

5253

54+
/**
55+
* Create a new {@code MockMultipartHttpServletRequest} with a default
56+
* {@link MockServletContext}.
57+
* @see #MockMultipartHttpServletRequest(ServletContext)
58+
*/
5359
public MockMultipartHttpServletRequest() {
60+
this(null);
61+
}
62+
63+
/**
64+
* Create a new {@code MockMultipartHttpServletRequest} with the supplied {@link ServletContext}.
65+
* @param servletContext the ServletContext that the request runs in
66+
* (may be {@code null} to use a default {@link MockServletContext})
67+
*/
68+
public MockMultipartHttpServletRequest(ServletContext servletContext) {
69+
super(servletContext);
5470
setMethod("POST");
5571
setContentType("multipart/form-data");
5672
}

‎spring-test/src/main/java/org/springframework/mock/web/MockServletContext.java

Lines changed: 133 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,24 @@
2323
import java.net.URL;
2424
import java.util.Collections;
2525
import java.util.Enumeration;
26+
import java.util.EventListener;
2627
import java.util.HashMap;
2728
import java.util.HashSet;
2829
import java.util.LinkedHashMap;
2930
import java.util.LinkedHashSet;
3031
import java.util.Map;
3132
import java.util.Set;
3233
import javax.activation.FileTypeMap;
34+
import javax.servlet.Filter;
35+
import javax.servlet.FilterRegistration;
3336
import javax.servlet.RequestDispatcher;
3437
import javax.servlet.Servlet;
3538
import javax.servlet.ServletContext;
39+
import javax.servlet.ServletException;
40+
import javax.servlet.ServletRegistration;
41+
import javax.servlet.SessionCookieConfig;
42+
import javax.servlet.SessionTrackingMode;
43+
import javax.servlet.descriptor.JspConfigDescriptor;
3644

3745
import org.apache.commons.logging.Log;
3846
import org.apache.commons.logging.LogFactory;
@@ -48,10 +56,10 @@
4856
/**
4957
* Mock implementation of the {@link javax.servlet.ServletContext} interface.
5058
*
51-
* <p>Compatible with Servlet 2.5 and partially with Servlet 3.0. Can be configured to
52-
* expose a specific version through {@link #setMajorVersion}/{@link #setMinorVersion};
53-
* default is 2.5. Note that Servlet 3.0 support is limited: servlet, filter and listener
54-
* registration methods are not supported; neither is cookie or JSP configuration.
59+
* <p>Compatible with Servlet 3.0. Can be configured to expose a specific version
60+
* through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.0.
61+
* Note that Servlet 3.0 support is limited: servlet, filter and listener
62+
* registration methods are not supported; neither is JSP configuration.
5563
* We generally do not recommend to unit-test your ServletContainerInitializers and
5664
* WebApplicationInitializers which is where those registration methods would be used.
5765
*
@@ -96,36 +104,50 @@ public class MockServletContext implements ServletContext {
96104

97105
private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir";
98106

99-
private final Log logger = LogFactory.getLog(getClass());
100-
101-
private final Map<String, ServletContext> contexts = new HashMap<String, ServletContext>();
102-
103-
private final Map<String, String> initParameters = new LinkedHashMap<String, String>();
107+
private static final Set<SessionTrackingMode> DEFAULT_SESSION_TRACKING_MODES =
108+
new LinkedHashSet<SessionTrackingMode>(3);
104109

105-
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
110+
static {
111+
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.COOKIE);
112+
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.URL);
113+
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.SSL);
114+
}
106115

107-
private final Set<String> declaredRoles = new HashSet<String>();
108116

109-
private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<String, RequestDispatcher>();
117+
private final Log logger = LogFactory.getLog(getClass());
110118

111119
private final ResourceLoader resourceLoader;
112120

113121
private final String resourceBasePath;
114122

115123
private String contextPath = "";
116124

117-
private int majorVersion = 2;
125+
private final Map<String, ServletContext> contexts = new HashMap<String, ServletContext>();
126+
127+
private int majorVersion = 3;
118128

119-
private int minorVersion = 5;
129+
private int minorVersion = 0;
120130

121-
private int effectiveMajorVersion = 2;
131+
private int effectiveMajorVersion = 3;
122132

123-
private int effectiveMinorVersion = 5;
133+
private int effectiveMinorVersion = 0;
124134

125-
private String servletContextName = "MockServletContext";
135+
private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<String, RequestDispatcher>();
126136

127137
private String defaultServletName = COMMON_DEFAULT_SERVLET_NAME;
128138

139+
private final Map<String, String> initParameters = new LinkedHashMap<String, String>();
140+
141+
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
142+
143+
private String servletContextName = "MockServletContext";
144+
145+
private final Set<String> declaredRoles = new HashSet<String>();
146+
147+
private Set<SessionTrackingMode> sessionTrackingModes;
148+
149+
private final SessionCookieConfig sessionCookieConfig = new MockSessionCookieConfig();
150+
129151

130152
/**
131153
* Create a new MockServletContext, using no base path and a
@@ -158,12 +180,11 @@ public MockServletContext(ResourceLoader resourceLoader) {
158180
* Create a new MockServletContext using the supplied resource base path and
159181
* resource loader.
160182
* <p>Registers a {@link MockRequestDispatcher} for the Servlet named
161-
* {@linkplain #COMMON_DEFAULT_SERVLET_NAME "default"}.
183+
* {@value #COMMON_DEFAULT_SERVLET_NAME}.
162184
* @param resourceBasePath the root directory of the WAR (should not end with a slash)
163185
* @param resourceLoader the ResourceLoader to use (or null for the default)
164186
* @see #registerNamedDispatcher
165187
*/
166-
@SuppressWarnings("javadoc")
167188
public MockServletContext(String resourceBasePath, ResourceLoader resourceLoader) {
168189
this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader());
169190
this.resourceBasePath = (resourceBasePath != null ? resourceBasePath : "");
@@ -194,7 +215,6 @@ public void setContextPath(String contextPath) {
194215
this.contextPath = (contextPath != null ? contextPath : "");
195216
}
196217

197-
/* This is a Servlet API 2.5 method. */
198218
public String getContextPath() {
199219
return this.contextPath;
200220
}
@@ -251,7 +271,7 @@ public int getEffectiveMinorVersion() {
251271
*/
252272
public String getMimeType(String filePath) {
253273
String mimeType = MimeTypeResolver.getMimeType(filePath);
254-
return ("application/octet-stream".equals(mimeType)) ? null : mimeType;
274+
return ("application/octet-stream".equals(mimeType) ? null : mimeType);
255275
}
256276

257277
public Set<String> getResourcePaths(String path) {
@@ -350,10 +370,9 @@ public void unregisterNamedDispatcher(String name) {
350370

351371
/**
352372
* Get the name of the <em>default</em> {@code Servlet}.
353-
* <p>Defaults to {@linkplain #COMMON_DEFAULT_SERVLET_NAME "default"}.
373+
* <p>Defaults to {@value #COMMON_DEFAULT_SERVLET_NAME}.
354374
* @see #setDefaultServletName
355375
*/
356-
@SuppressWarnings("javadoc")
357376
public String getDefaultServletName() {
358377
return this.defaultServletName;
359378
}
@@ -485,6 +504,97 @@ public Set<String> getDeclaredRoles() {
485504
return Collections.unmodifiableSet(this.declaredRoles);
486505
}
487506

507+
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
508+
throws IllegalStateException, IllegalArgumentException {
509+
this.sessionTrackingModes = sessionTrackingModes;
510+
}
511+
512+
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
513+
return DEFAULT_SESSION_TRACKING_MODES;
514+
}
515+
516+
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
517+
return (this.sessionTrackingModes != null ?
518+
Collections.unmodifiableSet(this.sessionTrackingModes) : DEFAULT_SESSION_TRACKING_MODES);
519+
}
520+
521+
public SessionCookieConfig getSessionCookieConfig() {
522+
return this.sessionCookieConfig;
523+
}
524+
525+
526+
//---------------------------------------------------------------------
527+
// Unsupported Servlet 3.0 registration methods
528+
//---------------------------------------------------------------------
529+
530+
public JspConfigDescriptor getJspConfigDescriptor() {
531+
throw new UnsupportedOperationException();
532+
}
533+
534+
public ServletRegistration.Dynamic addServlet(String servletName, String className) {
535+
throw new UnsupportedOperationException();
536+
}
537+
538+
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
539+
throw new UnsupportedOperationException();
540+
}
541+
542+
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
543+
throw new UnsupportedOperationException();
544+
}
545+
546+
public <T extends Servlet> T createServlet(Class<T> c) throws ServletException {
547+
throw new UnsupportedOperationException();
548+
}
549+
550+
public ServletRegistration getServletRegistration(String servletName) {
551+
throw new UnsupportedOperationException();
552+
}
553+
554+
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
555+
throw new UnsupportedOperationException();
556+
}
557+
558+
public FilterRegistration.Dynamic addFilter(String filterName, String className) {
559+
throw new UnsupportedOperationException();
560+
}
561+
562+
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
563+
throw new UnsupportedOperationException();
564+
}
565+
566+
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
567+
throw new UnsupportedOperationException();
568+
}
569+
570+
public <T extends Filter> T createFilter(Class<T> c) throws ServletException {
571+
throw new UnsupportedOperationException();
572+
}
573+
574+
public FilterRegistration getFilterRegistration(String filterName) {
575+
throw new UnsupportedOperationException();
576+
}
577+
578+
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
579+
throw new UnsupportedOperationException();
580+
}
581+
582+
public void addListener(Class<? extends EventListener> listenerClass) {
583+
throw new UnsupportedOperationException();
584+
}
585+
586+
public void addListener(String className) {
587+
throw new UnsupportedOperationException();
588+
}
589+
590+
public <T extends EventListener> void addListener(T t) {
591+
throw new UnsupportedOperationException();
592+
}
593+
594+
public <T extends EventListener> T createListener(Class<T> c) throws ServletException {
595+
throw new UnsupportedOperationException();
596+
}
597+
488598

489599
/**
490600
* Inner factory class used to introduce a Java Activation Framework
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2002-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.mock.web;
18+
19+
import javax.servlet.SessionCookieConfig;
20+
21+
/**
22+
* Mock implementation of the {@link javax.servlet.SessionCookieConfig} interface.
23+
*
24+
* @author Juergen Hoeller
25+
* @since 4.0
26+
* @see javax.servlet.ServletContext#getSessionCookieConfig()
27+
*/
28+
public class MockSessionCookieConfig implements SessionCookieConfig {
29+
30+
private String name;
31+
32+
private String domain;
33+
34+
private String path;
35+
36+
private String comment;
37+
38+
private boolean httpOnly;
39+
40+
private boolean secure;
41+
42+
private int maxAge;
43+
44+
45+
public void setName(String name) {
46+
this.name = name;
47+
}
48+
49+
public String getName() {
50+
return this.name;
51+
}
52+
53+
public void setDomain(String domain) {
54+
this.domain = domain;
55+
}
56+
57+
public String getDomain() {
58+
return this.domain;
59+
}
60+
61+
public void setPath(String path) {
62+
this.path = path;
63+
}
64+
65+
public String getPath() {
66+
return this.path;
67+
}
68+
69+
public void setComment(String comment) {
70+
this.comment = comment;
71+
}
72+
73+
public String getComment() {
74+
return this.comment;
75+
}
76+
77+
public void setHttpOnly(boolean httpOnly) {
78+
this.httpOnly = httpOnly;
79+
}
80+
81+
public boolean isHttpOnly() {
82+
return this.httpOnly;
83+
}
84+
85+
public void setSecure(boolean secure) {
86+
this.secure = secure;
87+
}
88+
89+
public boolean isSecure() {
90+
return this.secure;
91+
}
92+
93+
public void setMaxAge(int maxAge) {
94+
this.maxAge = maxAge;
95+
}
96+
97+
public int getMaxAge() {
98+
return this.maxAge;
99+
}
100+
101+
}

‎spring-test/src/test/java/org/springframework/mock/web/MockServletContextTests.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,14 +16,13 @@
1616

1717
package org.springframework.mock.web;
1818

19-
import static org.junit.Assert.*;
20-
2119
import java.util.Set;
22-
2320
import javax.servlet.RequestDispatcher;
2421

2522
import org.junit.Test;
2623

24+
import static org.junit.Assert.*;
25+
2726
/**
2827
* @author Juergen Hoeller
2928
* @author Chris Beams
@@ -77,10 +76,11 @@ public void getMimeType() {
7776
}
7877

7978
@Test
80-
public void minorVersion() {
81-
assertEquals(5, sc.getMinorVersion());
82-
sc.setMinorVersion(4);
83-
assertEquals(4, sc.getMinorVersion());
79+
public void servletVersion() {
80+
assertEquals(3, sc.getMajorVersion());
81+
assertEquals(0, sc.getMinorVersion());
82+
sc.setMinorVersion(1);
83+
assertEquals(1, sc.getMinorVersion());
8484
}
8585

8686
@Test

‎spring-web/src/test/java/org/springframework/mock/web/test/MockAsyncContext.java

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
1818
import java.io.IOException;
1919
import java.util.ArrayList;
2020
import java.util.List;
21-
2221
import javax.servlet.AsyncContext;
2322
import javax.servlet.AsyncEvent;
2423
import javax.servlet.AsyncListener;
@@ -56,6 +55,7 @@ public MockAsyncContext(ServletRequest request, ServletResponse response) {
5655
this.response = (HttpServletResponse) response;
5756
}
5857

58+
5959
@Override
6060
public ServletRequest getRequest() {
6161
return this.request;
@@ -71,11 +71,6 @@ public boolean hasOriginalRequestAndResponse() {
7171
return (this.request instanceof MockHttpServletRequest) && (this.response instanceof MockHttpServletResponse);
7272
}
7373

74-
public String getDispatchedPath() {
75-
return this.dispatchedPath;
76-
}
77-
78-
@Override
7974
public void dispatch() {
8075
dispatch(this.request.getRequestURI());
8176
}
@@ -90,7 +85,10 @@ public void dispatch(ServletContext context, String path) {
9085
this.dispatchedPath = path;
9186
}
9287

93-
@Override
88+
public String getDispatchedPath() {
89+
return this.dispatchedPath;
90+
}
91+
9492
public void complete() {
9593
MockHttpServletRequest mockRequest = WebUtils.getNativeRequest(request, MockHttpServletRequest.class);
9694
if (mockRequest != null) {
@@ -111,11 +109,6 @@ public void start(Runnable runnable) {
111109
runnable.run();
112110
}
113111

114-
public List<AsyncListener> getListeners() {
115-
return this.listeners;
116-
}
117-
118-
@Override
119112
public void addListener(AsyncListener listener) {
120113
this.listeners.add(listener);
121114
}
@@ -125,19 +118,20 @@ public void addListener(AsyncListener listener, ServletRequest request, ServletR
125118
this.listeners.add(listener);
126119
}
127120

128-
@Override
129-
public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException {
130-
return BeanUtils.instantiateClass(clazz);
121+
public List<AsyncListener> getListeners() {
122+
return this.listeners;
131123
}
132124

133-
@Override
134-
public long getTimeout() {
135-
return this.timeout;
125+
public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException {
126+
return BeanUtils.instantiateClass(clazz);
136127
}
137128

138-
@Override
139129
public void setTimeout(long timeout) {
140130
this.timeout = timeout;
141131
}
142132

133+
public long getTimeout() {
134+
return this.timeout;
135+
}
136+
143137
}

‎spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java

Lines changed: 87 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
import java.util.Collections;
2929
import java.util.Date;
3030
import java.util.Enumeration;
31-
import java.util.HashMap;
3231
import java.util.HashSet;
3332
import java.util.LinkedHashMap;
33+
import java.util.LinkedHashSet;
3434
import java.util.LinkedList;
3535
import java.util.List;
3636
import java.util.Locale;
@@ -54,12 +54,9 @@
5454
import org.springframework.util.LinkedCaseInsensitiveMap;
5555

5656
/**
57-
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
58-
* interface. Supports the Servlet 2.5 API level; throws
59-
* {@link UnsupportedOperationException} for some methods introduced in Servlet 3.0.
57+
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest} interface.
6058
*
61-
* <p>Used for testing the web framework; also useful for testing
62-
* application controllers.
59+
* <p>As of Spring 4.0, this set of mocks is entirely based on Servlet 3.0.
6360
*
6461
* @author Juergen Hoeller
6562
* @author Rod Johnson
@@ -150,7 +147,13 @@ public class MockHttpServletRequest implements HttpServletRequest {
150147

151148
private int localPort = DEFAULT_SERVER_PORT;
152149

153-
private final Map<String, Part> parts = new HashMap<String, Part>();
150+
private boolean asyncStarted = false;
151+
152+
private boolean asyncSupported = false;
153+
154+
private MockAsyncContext asyncContext;
155+
156+
private DispatcherType dispatcherType = DispatcherType.REQUEST;
154157

155158

156159
// ---------------------------------------------------------------------
@@ -191,13 +194,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
191194

192195
private boolean requestedSessionIdFromURL = false;
193196

194-
private boolean asyncSupported = false;
195-
196-
private boolean asyncStarted = false;
197-
198-
private MockAsyncContext asyncContext;
199-
200-
private DispatcherType dispatcherType = DispatcherType.REQUEST;
197+
private final Map<String, Part> parts = new LinkedHashMap<String, Part>();
201198

202199

203200
// ---------------------------------------------------------------------
@@ -228,8 +225,8 @@ public MockHttpServletRequest(String method, String requestURI) {
228225

229226
/**
230227
* Create a new {@code MockHttpServletRequest} with the supplied {@link ServletContext}.
231-
* @param servletContext the ServletContext that the request runs in (may be
232-
* {@code null} to use a default {@link MockServletContext})
228+
* @param servletContext the ServletContext that the request runs in
229+
* (may be {@code null} to use a default {@link MockServletContext})
233230
* @see #MockHttpServletRequest(ServletContext, String, String)
234231
*/
235232
public MockHttpServletRequest(ServletContext servletContext) {
@@ -688,10 +685,61 @@ public int getLocalPort() {
688685
return this.localPort;
689686
}
690687

688+
@Override
689+
public AsyncContext startAsync() {
690+
return startAsync(this, null);
691+
}
692+
693+
@Override
694+
public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
695+
if (!this.asyncSupported) {
696+
throw new IllegalStateException("Async not supported");
697+
}
698+
this.asyncStarted = true;
699+
this.asyncContext = new MockAsyncContext(request, response);
700+
return this.asyncContext;
701+
}
691702

692-
//---------------------------------------------------------------------
703+
public void setAsyncStarted(boolean asyncStarted) {
704+
this.asyncStarted = asyncStarted;
705+
}
706+
707+
@Override
708+
public boolean isAsyncStarted() {
709+
return this.asyncStarted;
710+
}
711+
712+
public void setAsyncSupported(boolean asyncSupported) {
713+
this.asyncSupported = asyncSupported;
714+
}
715+
716+
@Override
717+
public boolean isAsyncSupported() {
718+
return this.asyncSupported;
719+
}
720+
721+
public void setAsyncContext(MockAsyncContext asyncContext) {
722+
this.asyncContext = asyncContext;
723+
}
724+
725+
@Override
726+
public AsyncContext getAsyncContext() {
727+
return this.asyncContext;
728+
}
729+
730+
public void setDispatcherType(DispatcherType dispatcherType) {
731+
this.dispatcherType = dispatcherType;
732+
}
733+
734+
@Override
735+
public DispatcherType getDispatcherType() {
736+
return this.dispatcherType;
737+
}
738+
739+
740+
// ---------------------------------------------------------------------
693741
// HttpServletRequest interface
694-
//---------------------------------------------------------------------
742+
// ---------------------------------------------------------------------
695743

696744
public void setAuthType(String authType) {
697745
this.authType = authType;
@@ -713,15 +761,15 @@ public Cookie[] getCookies() {
713761

714762
/**
715763
* Add a header entry for the given name.
716-
* <p>If there was no entry for that header name before,
717-
* the value will be used as-is. In case of an existing entry,
718-
* a String array will be created, adding the given value (more
719-
* specifically, its toString representation) as further element.
720-
* <p>Multiple values can only be stored as list of Strings,
721-
* following the Servlet spec (see {@code getHeaders} accessor).
722-
* As alternative to repeated {@code addHeader} calls for
723-
* individual elements, you can use a single call with an entire
724-
* array or Collection of values as parameter.
764+
* <p>If there was no entry for that header name before, the value will be used
765+
* as-is. In case of an existing entry, a String array will be created,
766+
* adding the given value (more specifically, its toString representation)
767+
* as further element.
768+
* <p>Multiple values can only be stored as list of Strings, following the
769+
* Servlet spec (see {@code getHeaders} accessor). As alternative to
770+
* repeated {@code addHeader} calls for individual elements, you can
771+
* use a single call with an entire array or Collection of values as
772+
* parameter.
725773
* @see #getHeaderNames
726774
* @see #getHeader
727775
* @see #getHeaders
@@ -972,89 +1020,35 @@ public boolean isRequestedSessionIdFromUrl() {
9721020
return isRequestedSessionIdFromURL();
9731021
}
9741022

975-
976-
//---------------------------------------------------------------------
977-
// Methods introduced in Servlet 3.0
978-
//---------------------------------------------------------------------
979-
980-
@Override
981-
public AsyncContext getAsyncContext() {
982-
return this.asyncContext;
983-
}
984-
985-
public void setAsyncContext(MockAsyncContext asyncContext) {
986-
this.asyncContext = asyncContext;
987-
}
988-
989-
@Override
990-
public DispatcherType getDispatcherType() {
991-
return this.dispatcherType;
992-
}
993-
994-
public void setDispatcherType(DispatcherType dispatcherType) {
995-
this.dispatcherType = dispatcherType;
996-
}
997-
998-
public void setAsyncSupported(boolean asyncSupported) {
999-
this.asyncSupported = asyncSupported;
1000-
}
1001-
1002-
@Override
1003-
public boolean isAsyncSupported() {
1004-
return this.asyncSupported;
1005-
}
1006-
1007-
@Override
1008-
public AsyncContext startAsync() {
1009-
return startAsync(this, null);
1010-
}
1011-
10121023
@Override
1013-
public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
1014-
if (!this.asyncSupported) {
1015-
throw new IllegalStateException("Async not supported");
1016-
}
1017-
this.asyncStarted = true;
1018-
this.asyncContext = new MockAsyncContext(request, response);
1019-
return this.asyncContext;
1020-
}
1021-
1022-
public void setAsyncStarted(boolean asyncStarted) {
1023-
this.asyncStarted = asyncStarted;
1024+
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
1025+
throw new UnsupportedOperationException();
10241026
}
10251027

10261028
@Override
1027-
public boolean isAsyncStarted() {
1028-
return this.asyncStarted;
1029+
public void login(String username, String password) throws ServletException {
1030+
throw new UnsupportedOperationException();
10291031
}
10301032

10311033
@Override
1032-
public boolean authenticate(HttpServletResponse arg0) throws IOException, ServletException {
1033-
throw new UnsupportedOperationException();
1034+
public void logout() throws ServletException {
1035+
this.userPrincipal = null;
1036+
this.remoteUser = null;
1037+
this.authType = null;
10341038
}
10351039

10361040
public void addPart(Part part) {
1037-
parts.put(part.getName(), part);
1041+
this.parts.put(part.getName(), part);
10381042
}
10391043

10401044
@Override
1041-
public Part getPart(String key) throws IOException, IllegalStateException, ServletException {
1042-
return parts.get(key);
1045+
public Part getPart(String name) throws IOException, IllegalStateException, ServletException {
1046+
return this.parts.get(name);
10431047
}
10441048

10451049
@Override
10461050
public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
1047-
return parts.values();
1048-
}
1049-
1050-
@Override
1051-
public void login(String arg0, String arg1) throws ServletException {
1052-
throw new UnsupportedOperationException();
1053-
}
1054-
1055-
@Override
1056-
public void logout() throws ServletException {
1057-
throw new UnsupportedOperationException();
1051+
return this.parts.values();
10581052
}
10591053

10601054
}

‎spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
/**
4141
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
4242
*
43-
* <p>Compatible with Servlet 2.5 as well as Servlet 3.0.
43+
* <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline. Beyond that,
44+
* this MockHttpServletResponse is also compatible with Servlet 3.1's setContentLengthLong.
4445
*
4546
* @author Juergen Hoeller
4647
* @author Rod Johnson
@@ -75,7 +76,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
7576

7677
private PrintWriter writer;
7778

78-
private int contentLength = 0;
79+
private long contentLength = 0;
7980

8081
private String contentType;
8182

@@ -198,6 +199,15 @@ public void setContentLength(int contentLength) {
198199
}
199200

200201
public int getContentLength() {
202+
return (int) this.contentLength;
203+
}
204+
205+
public void setContentLengthLong(long contentLength) {
206+
this.contentLength = contentLength;
207+
doAddHeaderValue(CONTENT_LENGTH_HEADER, contentLength, true);
208+
}
209+
210+
public long getContentLengthLong() {
201211
return this.contentLength;
202212
}
203213

‎spring-web/src/test/java/org/springframework/mock/web/test/MockMultipartHttpServletRequest.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import java.util.Iterator;
2222
import java.util.List;
2323
import java.util.Map;
24+
import javax.servlet.ServletContext;
2425

2526
import org.springframework.http.HttpHeaders;
2627
import org.springframework.http.HttpMethod;
@@ -50,7 +51,22 @@ public class MockMultipartHttpServletRequest extends MockHttpServletRequest impl
5051
new LinkedMultiValueMap<String, MultipartFile>();
5152

5253

54+
/**
55+
* Create a new {@code MockMultipartHttpServletRequest} with a default
56+
* {@link MockServletContext}.
57+
* @see #MockMultipartHttpServletRequest(ServletContext)
58+
*/
5359
public MockMultipartHttpServletRequest() {
60+
this(null);
61+
}
62+
63+
/**
64+
* Create a new {@code MockMultipartHttpServletRequest} with the supplied {@link ServletContext}.
65+
* @param servletContext the ServletContext that the request runs in
66+
* (may be {@code null} to use a default {@link MockServletContext})
67+
*/
68+
public MockMultipartHttpServletRequest(ServletContext servletContext) {
69+
super(servletContext);
5470
setMethod("POST");
5571
setContentType("multipart/form-data");
5672
}

‎spring-web/src/test/java/org/springframework/mock/web/test/MockServletContext.java

Lines changed: 76 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,7 +30,6 @@
3030
import java.util.LinkedHashSet;
3131
import java.util.Map;
3232
import java.util.Set;
33-
3433
import javax.activation.FileTypeMap;
3534
import javax.servlet.Filter;
3635
import javax.servlet.FilterRegistration;
@@ -45,6 +44,7 @@
4544

4645
import org.apache.commons.logging.Log;
4746
import org.apache.commons.logging.LogFactory;
47+
4848
import org.springframework.core.io.DefaultResourceLoader;
4949
import org.springframework.core.io.Resource;
5050
import org.springframework.core.io.ResourceLoader;
@@ -56,13 +56,11 @@
5656
/**
5757
* Mock implementation of the {@link javax.servlet.ServletContext} interface.
5858
*
59-
* <p>Compatible with Servlet 2.5 and partially with Servlet 3.0 but throws
60-
* {@link UnsupportedOperationException} for most methods introduced in Servlet
61-
* 3.0. Can be configured to expose a specific version through
62-
* {@link #setMajorVersion}/{@link #setMinorVersion}; default is 2.5. Note that
63-
* Servlet 3.0 support is limited: servlet, filter and listener registration
64-
* methods are not supported; neither is cookie or JSP configuration. We generally
65-
* do not recommend to unit-test your ServletContainerInitializers and
59+
* <p>Compatible with Servlet 3.0. Can be configured to expose a specific version
60+
* through {@link #setMajorVersion}/{@link #setMinorVersion}; default is 3.0.
61+
* Note that Servlet 3.0 support is limited: servlet, filter and listener
62+
* registration methods are not supported; neither is JSP configuration.
63+
* We generally do not recommend to unit-test your ServletContainerInitializers and
6664
* WebApplicationInitializers which is where those registration methods would be used.
6765
*
6866
* <p>Used for testing the Spring web framework; only rarely necessary for testing
@@ -106,36 +104,50 @@ public class MockServletContext implements ServletContext {
106104

107105
private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir";
108106

109-
private final Log logger = LogFactory.getLog(getClass());
110-
111-
private final Map<String, ServletContext> contexts = new HashMap<String, ServletContext>();
112-
113-
private final Map<String, String> initParameters = new LinkedHashMap<String, String>();
107+
private static final Set<SessionTrackingMode> DEFAULT_SESSION_TRACKING_MODES =
108+
new LinkedHashSet<SessionTrackingMode>(3);
114109

115-
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
110+
static {
111+
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.COOKIE);
112+
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.URL);
113+
DEFAULT_SESSION_TRACKING_MODES.add(SessionTrackingMode.SSL);
114+
}
116115

117-
private final Set<String> declaredRoles = new HashSet<String>();
118116

119-
private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<String, RequestDispatcher>();
117+
private final Log logger = LogFactory.getLog(getClass());
120118

121119
private final ResourceLoader resourceLoader;
122120

123121
private final String resourceBasePath;
124122

125123
private String contextPath = "";
126124

127-
private int majorVersion = 2;
125+
private final Map<String, ServletContext> contexts = new HashMap<String, ServletContext>();
128126

129-
private int minorVersion = 5;
127+
private int majorVersion = 3;
130128

131-
private int effectiveMajorVersion = 2;
129+
private int minorVersion = 0;
132130

133-
private int effectiveMinorVersion = 5;
131+
private int effectiveMajorVersion = 3;
134132

135-
private String servletContextName = "MockServletContext";
133+
private int effectiveMinorVersion = 0;
134+
135+
private final Map<String, RequestDispatcher> namedRequestDispatchers = new HashMap<String, RequestDispatcher>();
136136

137137
private String defaultServletName = COMMON_DEFAULT_SERVLET_NAME;
138138

139+
private final Map<String, String> initParameters = new LinkedHashMap<String, String>();
140+
141+
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
142+
143+
private String servletContextName = "MockServletContext";
144+
145+
private final Set<String> declaredRoles = new HashSet<String>();
146+
147+
private Set<SessionTrackingMode> sessionTrackingModes;
148+
149+
private final SessionCookieConfig sessionCookieConfig = new MockSessionCookieConfig();
150+
139151

140152
/**
141153
* Create a new MockServletContext, using no base path and a
@@ -203,7 +215,6 @@ public void setContextPath(String contextPath) {
203215
this.contextPath = (contextPath != null ? contextPath : "");
204216
}
205217

206-
/* This is a Servlet API 2.5 method. */
207218
@Override
208219
public String getContextPath() {
209220
return this.contextPath;
@@ -476,7 +487,7 @@ public Object getAttribute(String name) {
476487

477488
@Override
478489
public Enumeration<String> getAttributeNames() {
479-
return Collections.enumeration(this.attributes.keySet());
490+
return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
480491
}
481492

482493
@Override
@@ -523,94 +534,85 @@ public Set<String> getDeclaredRoles() {
523534
return Collections.unmodifiableSet(this.declaredRoles);
524535
}
525536

526-
527-
/**
528-
* Inner factory class used to introduce a Java Activation Framework
529-
* dependency when actually asked to resolve a MIME type.
530-
*/
531-
private static class MimeTypeResolver {
532-
533-
public static String getMimeType(String filePath) {
534-
return FileTypeMap.getDefaultFileTypeMap().getContentType(filePath);
535-
}
537+
@Override
538+
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
539+
throws IllegalStateException, IllegalArgumentException {
540+
this.sessionTrackingModes = sessionTrackingModes;
536541
}
537542

538-
539-
//---------------------------------------------------------------------
540-
// Methods introduced in Servlet 3.0
541-
//---------------------------------------------------------------------
542-
543543
@Override
544-
public FilterRegistration.Dynamic addFilter(String filterName, String className) {
545-
throw new UnsupportedOperationException();
544+
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
545+
return DEFAULT_SESSION_TRACKING_MODES;
546546
}
547547

548548
@Override
549-
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
550-
throw new UnsupportedOperationException();
549+
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
550+
return (this.sessionTrackingModes != null ?
551+
Collections.unmodifiableSet(this.sessionTrackingModes) : DEFAULT_SESSION_TRACKING_MODES);
551552
}
552553

553554
@Override
554-
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
555-
throw new UnsupportedOperationException();
555+
public SessionCookieConfig getSessionCookieConfig() {
556+
return this.sessionCookieConfig;
556557
}
557558

559+
560+
//---------------------------------------------------------------------
561+
// Unsupported Servlet 3.0 registration methods
562+
//---------------------------------------------------------------------
563+
558564
@Override
559-
public void addListener(Class<? extends EventListener> listenerClass) {
565+
public JspConfigDescriptor getJspConfigDescriptor() {
560566
throw new UnsupportedOperationException();
561567
}
562568

563569
@Override
564-
public void addListener(String className) {
570+
public ServletRegistration.Dynamic addServlet(String servletName, String className) {
565571
throw new UnsupportedOperationException();
566572
}
567573

568574
@Override
569-
public <T extends EventListener> void addListener(T t) {
575+
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
570576
throw new UnsupportedOperationException();
571577
}
572578

573579
@Override
574-
public ServletRegistration.Dynamic addServlet(String servletName, String className) {
580+
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
575581
throw new UnsupportedOperationException();
576582
}
577583

578584
@Override
579-
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
585+
public <T extends Servlet> T createServlet(Class<T> c) throws ServletException {
580586
throw new UnsupportedOperationException();
581587
}
582588

583589
@Override
584-
public ServletRegistration.Dynamic addServlet(String servletName,
585-
Class<? extends Servlet> servletClass) {
590+
public ServletRegistration getServletRegistration(String servletName) {
586591
throw new UnsupportedOperationException();
587592
}
588593

589594
@Override
590-
public <T extends Filter> T createFilter(Class<T> c)
591-
throws ServletException {
595+
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
592596
throw new UnsupportedOperationException();
593597
}
594598

595599
@Override
596-
public <T extends EventListener> T createListener(Class<T> c)
597-
throws ServletException {
600+
public FilterRegistration.Dynamic addFilter(String filterName, String className) {
598601
throw new UnsupportedOperationException();
599602
}
600603

601604
@Override
602-
public <T extends Servlet> T createServlet(Class<T> c)
603-
throws ServletException {
605+
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
604606
throw new UnsupportedOperationException();
605607
}
606608

607609
@Override
608-
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
610+
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
609611
throw new UnsupportedOperationException();
610612
}
611613

612614
@Override
613-
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
615+
public <T extends Filter> T createFilter(Class<T> c) throws ServletException {
614616
throw new UnsupportedOperationException();
615617
}
616618

@@ -625,29 +627,35 @@ public FilterRegistration getFilterRegistration(String filterName) {
625627
}
626628

627629
@Override
628-
public JspConfigDescriptor getJspConfigDescriptor() {
630+
public void addListener(Class<? extends EventListener> listenerClass) {
629631
throw new UnsupportedOperationException();
630632
}
631633

632634
@Override
633-
public ServletRegistration getServletRegistration(String servletName) {
635+
public void addListener(String className) {
634636
throw new UnsupportedOperationException();
635637
}
636638

637639
@Override
638-
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
640+
public <T extends EventListener> void addListener(T t) {
639641
throw new UnsupportedOperationException();
640642
}
641643

642644
@Override
643-
public SessionCookieConfig getSessionCookieConfig() {
645+
public <T extends EventListener> T createListener(Class<T> c) throws ServletException {
644646
throw new UnsupportedOperationException();
645647
}
646648

647-
@Override
648-
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
649-
throws IllegalStateException, IllegalArgumentException {
650-
throw new UnsupportedOperationException();
649+
650+
/**
651+
* Inner factory class used to introduce a Java Activation Framework
652+
* dependency when actually asked to resolve a MIME type.
653+
*/
654+
private static class MimeTypeResolver {
655+
656+
public static String getMimeType(String filePath) {
657+
return FileTypeMap.getDefaultFileTypeMap().getContentType(filePath);
658+
}
651659
}
652660

653661
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2002-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.mock.web.test;
18+
19+
import javax.servlet.SessionCookieConfig;
20+
21+
/**
22+
* Mock implementation of the {@link javax.servlet.SessionCookieConfig} interface.
23+
*
24+
* @author Juergen Hoeller
25+
* @since 4.0
26+
* @see javax.servlet.ServletContext#getSessionCookieConfig()
27+
*/
28+
public class MockSessionCookieConfig implements SessionCookieConfig {
29+
30+
private String name;
31+
32+
private String domain;
33+
34+
private String path;
35+
36+
private String comment;
37+
38+
private boolean httpOnly;
39+
40+
private boolean secure;
41+
42+
private int maxAge;
43+
44+
45+
public void setName(String name) {
46+
this.name = name;
47+
}
48+
49+
public String getName() {
50+
return this.name;
51+
}
52+
53+
public void setDomain(String domain) {
54+
this.domain = domain;
55+
}
56+
57+
public String getDomain() {
58+
return this.domain;
59+
}
60+
61+
public void setPath(String path) {
62+
this.path = path;
63+
}
64+
65+
public String getPath() {
66+
return this.path;
67+
}
68+
69+
public void setComment(String comment) {
70+
this.comment = comment;
71+
}
72+
73+
public String getComment() {
74+
return this.comment;
75+
}
76+
77+
public void setHttpOnly(boolean httpOnly) {
78+
this.httpOnly = httpOnly;
79+
}
80+
81+
public boolean isHttpOnly() {
82+
return this.httpOnly;
83+
}
84+
85+
public void setSecure(boolean secure) {
86+
this.secure = secure;
87+
}
88+
89+
public boolean isSecure() {
90+
return this.secure;
91+
}
92+
93+
public void setMaxAge(int maxAge) {
94+
this.maxAge = maxAge;
95+
}
96+
97+
public int getMaxAge() {
98+
return this.maxAge;
99+
}
100+
101+
}

0 commit comments

Comments
 (0)
Please sign in to comment.