Skip to content

Commit c92a06f

Browse files
rwinchrstoyanchev
authored andcommitted
Support Filters/Servlet invocation in MockFilterChain
This commit adds the ability to allow the MockFilterChain to invoke a List of Filter's and/or a Servlet. Issue: SPR-9745
1 parent 6bce098 commit c92a06f

File tree

5 files changed

+558
-12
lines changed

5 files changed

+558
-12
lines changed

spring-orm/src/test/java/org/springframework/mock/web/MockFilterChain.java

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@
1616

1717
package org.springframework.mock.web;
1818

19+
import java.io.IOException;
20+
import java.util.Arrays;
21+
import java.util.Iterator;
22+
23+
import javax.servlet.Filter;
1924
import javax.servlet.FilterChain;
25+
import javax.servlet.FilterConfig;
26+
import javax.servlet.Servlet;
27+
import javax.servlet.ServletException;
2028
import javax.servlet.ServletRequest;
2129
import javax.servlet.ServletResponse;
2230

2331
import org.springframework.util.Assert;
32+
import org.springframework.util.ObjectUtils;
2433

2534
/**
2635
* Mock implementation of the {@link javax.servlet.FilterChain} interface.
@@ -29,6 +38,8 @@
2938
* custom {@link javax.servlet.Filter} implementations.
3039
*
3140
* @author Juergen Hoeller
41+
* @author Rob Winch
42+
*
3243
* @since 2.0.3
3344
* @see MockFilterConfig
3445
* @see PassThroughFilterChain
@@ -39,16 +50,69 @@ public class MockFilterChain implements FilterChain {
3950

4051
private ServletResponse response;
4152

53+
private final Iterator<Filter> iterator;
54+
55+
56+
/**
57+
* Register a single do-nothing {@link Filter} implementation. The first
58+
* invocation saves the request and response. Subsequent invocations raise
59+
* an {@link IllegalStateException}.
60+
*/
61+
public MockFilterChain() {
62+
this.iterator = null;
63+
}
64+
65+
/**
66+
* Create a FilterChain with a {@link Servlet} but without filters.
67+
*
68+
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
69+
* @since 3.2
70+
*/
71+
public MockFilterChain(Servlet servlet) {
72+
this(new ServletFilterProxy(servlet));
73+
}
74+
75+
/**
76+
* Create a FilterChain with one or more {@link Filter} instances and a {@link Servlet}.
77+
*
78+
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
79+
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
80+
* @since 3.2
81+
*/
82+
public MockFilterChain(Servlet servlet, Filter... filters) {
83+
this(ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet)));
84+
}
85+
86+
/**
87+
* Create a {@link FilterChain} with one or more {@link Filter} instances.
88+
*
89+
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
90+
* @since 3.2
91+
*/
92+
private MockFilterChain(Filter... filters) {
93+
Assert.notNull(filters, "filters cannot be null");
94+
Assert.notEmpty(filters, "filters cannot be empty");
95+
Assert.noNullElements(filters, "filters cannot contain null values");
96+
this.iterator = Arrays.asList(filters).iterator();
97+
}
4298

4399
/**
44-
* Records the request and response.
100+
* Invoke registered {@link Filter}s and/or {@link Servlet} also saving the
101+
* request and response.
45102
*/
46-
public void doFilter(ServletRequest request, ServletResponse response) {
103+
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
47104
Assert.notNull(request, "Request must not be null");
48105
Assert.notNull(response, "Response must not be null");
106+
49107
if (this.request != null) {
50-
throw new IllegalStateException("This FilterChain has already been called!");
108+
throw new IllegalStateException("This FilterChain has already been called!");
51109
}
110+
111+
if ((this.iterator != null) && (this.iterator.hasNext())) {
112+
Filter nextFilter = this.iterator.next();
113+
nextFilter.doFilter(request, response, this);
114+
}
115+
52116
this.request = request;
53117
this.response = response;
54118
}
@@ -67,4 +131,35 @@ public ServletResponse getResponse() {
67131
return this.response;
68132
}
69133

134+
135+
/**
136+
* A filter that simply delegates to a Servlet.
137+
*/
138+
private static class ServletFilterProxy implements Filter {
139+
140+
private final Servlet delegateServlet;
141+
142+
private ServletFilterProxy(Servlet servlet) {
143+
Assert.notNull(servlet, "servlet cannot be null");
144+
this.delegateServlet = servlet;
145+
}
146+
147+
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
148+
throws IOException, ServletException {
149+
150+
this.delegateServlet.service(request, response);
151+
}
152+
153+
public void init(FilterConfig filterConfig) throws ServletException {
154+
}
155+
156+
public void destroy() {
157+
}
158+
159+
@Override
160+
public String toString() {
161+
return this.delegateServlet.toString();
162+
}
163+
}
164+
70165
}

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

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@
1616

1717
package org.springframework.mock.web;
1818

19+
import java.io.IOException;
20+
import java.util.Arrays;
21+
import java.util.Iterator;
22+
23+
import javax.servlet.Filter;
1924
import javax.servlet.FilterChain;
25+
import javax.servlet.FilterConfig;
26+
import javax.servlet.Servlet;
27+
import javax.servlet.ServletException;
2028
import javax.servlet.ServletRequest;
2129
import javax.servlet.ServletResponse;
2230

2331
import org.springframework.util.Assert;
32+
import org.springframework.util.ObjectUtils;
2433

2534
/**
2635
* Mock implementation of the {@link javax.servlet.FilterChain} interface.
@@ -29,6 +38,8 @@
2938
* custom {@link javax.servlet.Filter} implementations.
3039
*
3140
* @author Juergen Hoeller
41+
* @author Rob Winch
42+
*
3243
* @since 2.0.3
3344
* @see MockFilterConfig
3445
* @see PassThroughFilterChain
@@ -39,16 +50,69 @@ public class MockFilterChain implements FilterChain {
3950

4051
private ServletResponse response;
4152

53+
private final Iterator<Filter> iterator;
54+
55+
56+
/**
57+
* Register a single do-nothing {@link Filter} implementation. The first
58+
* invocation saves the request and response. Subsequent invocations raise
59+
* an {@link IllegalStateException}.
60+
*/
61+
public MockFilterChain() {
62+
this.iterator = null;
63+
}
64+
65+
/**
66+
* Create a FilterChain with a {@link Servlet} but without filters.
67+
*
68+
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
69+
* @since 3.2
70+
*/
71+
public MockFilterChain(Servlet servlet) {
72+
this(new ServletFilterProxy(servlet));
73+
}
74+
75+
/**
76+
* Create a FilterChain with one or more {@link Filter} instances and a {@link Servlet}.
77+
*
78+
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
79+
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
80+
* @since 3.2
81+
*/
82+
public MockFilterChain(Servlet servlet, Filter... filters) {
83+
this(ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet)));
84+
}
85+
86+
/**
87+
* Create a {@link FilterChain} with one or more {@link Filter} instances.
88+
*
89+
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
90+
* @since 3.2
91+
*/
92+
private MockFilterChain(Filter... filters) {
93+
Assert.notNull(filters, "filters cannot be null");
94+
Assert.notEmpty(filters, "filters cannot be empty");
95+
Assert.noNullElements(filters, "filters cannot contain null values");
96+
this.iterator = Arrays.asList(filters).iterator();
97+
}
4298

4399
/**
44-
* Records the request and response.
100+
* Invoke registered {@link Filter}s and/or {@link Servlet} also saving the
101+
* request and response.
45102
*/
46-
public void doFilter(ServletRequest request, ServletResponse response) {
103+
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
47104
Assert.notNull(request, "Request must not be null");
48105
Assert.notNull(response, "Response must not be null");
106+
49107
if (this.request != null) {
50-
throw new IllegalStateException("This FilterChain has already been called!");
108+
throw new IllegalStateException("This FilterChain has already been called!");
51109
}
110+
111+
if ((this.iterator != null) && (this.iterator.hasNext())) {
112+
Filter nextFilter = this.iterator.next();
113+
nextFilter.doFilter(request, response, this);
114+
}
115+
52116
this.request = request;
53117
this.response = response;
54118
}
@@ -67,4 +131,35 @@ public ServletResponse getResponse() {
67131
return this.response;
68132
}
69133

134+
135+
/**
136+
* A filter that simply delegates to a Servlet.
137+
*/
138+
private static class ServletFilterProxy implements Filter {
139+
140+
private final Servlet delegateServlet;
141+
142+
private ServletFilterProxy(Servlet servlet) {
143+
Assert.notNull(servlet, "servlet cannot be null");
144+
this.delegateServlet = servlet;
145+
}
146+
147+
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
148+
throws IOException, ServletException {
149+
150+
this.delegateServlet.service(request, response);
151+
}
152+
153+
public void init(FilterConfig filterConfig) throws ServletException {
154+
}
155+
156+
public void destroy() {
157+
}
158+
159+
@Override
160+
public String toString() {
161+
return this.delegateServlet.toString();
162+
}
163+
}
164+
70165
}

0 commit comments

Comments
 (0)