Skip to content

Commit 306713d

Browse files
Add CompositeFilter to group all new filters
1 parent d6bdfae commit 306713d

File tree

2 files changed

+180
-0
lines changed

2 files changed

+180
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.sap.hcp.cf.logging.servlet.filter;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.Arrays;
6+
import java.util.Collections;
7+
import java.util.Iterator;
8+
import java.util.List;
9+
10+
import javax.servlet.Filter;
11+
import javax.servlet.FilterChain;
12+
import javax.servlet.FilterConfig;
13+
import javax.servlet.ServletException;
14+
import javax.servlet.ServletRequest;
15+
import javax.servlet.ServletResponse;
16+
17+
/**
18+
* <p>
19+
* The {@link CompositeFilter} allows to group several servlet {@link Filter}
20+
* into one. This is used to allow customizable filters and provide a backwards
21+
* compatible {@link RequestLoggingFilter}.
22+
* </p>
23+
*
24+
* <p>
25+
* You can easily create a subclass of {@link CompositeFilter} and add all the
26+
* filters from com.sap.hcp.cf.logging.servlet.filter you wish. You can even
27+
* bring your own filters.
28+
* </p>
29+
*/
30+
public class CompositeFilter implements Filter {
31+
32+
private List<? extends Filter> filters;
33+
34+
public CompositeFilter(Filter... filters) {
35+
this.filters = Arrays.asList(filters);
36+
}
37+
38+
public void setFilters(List<? extends Filter> filters) {
39+
this.filters = new ArrayList<>(filters);
40+
}
41+
42+
public List<? extends Filter> getFilters() {
43+
return Collections.unmodifiableList(filters);
44+
}
45+
46+
@Override
47+
public void init(FilterConfig config) throws ServletException {
48+
for (Filter filter: this.filters) {
49+
filter.init(config);
50+
}
51+
}
52+
53+
@Override
54+
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
55+
ServletException {
56+
new InternalFilterChain(chain, this.filters).doFilter(request, response);
57+
}
58+
59+
@Override
60+
public void destroy() {
61+
for (int i = this.filters.size() - 1; i >= 0; i--) {
62+
Filter filter = this.filters.get(i);
63+
filter.destroy();
64+
}
65+
}
66+
67+
private static class InternalFilterChain implements FilterChain {
68+
69+
private final FilterChain originalChain;
70+
private final Iterator<? extends Filter> current;
71+
72+
public InternalFilterChain(FilterChain chain, List<? extends Filter> additionalFilters) {
73+
this.originalChain = chain;
74+
this.current = additionalFilters.iterator();
75+
}
76+
77+
@Override
78+
public void doFilter(final ServletRequest request, final ServletResponse response) throws IOException,
79+
ServletException {
80+
if (current.hasNext()) {
81+
current.next().doFilter(request, response, this);
82+
} else {
83+
originalChain.doFilter(request, response);
84+
}
85+
}
86+
}
87+
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.sap.hcp.cf.logging.servlet.filter;
2+
3+
import static org.mockito.Matchers.any;
4+
import static org.mockito.Matchers.eq;
5+
import static org.mockito.Mockito.inOrder;
6+
import static org.mockito.Mockito.mock;
7+
8+
import java.io.IOException;
9+
10+
import javax.servlet.Filter;
11+
import javax.servlet.FilterChain;
12+
import javax.servlet.FilterConfig;
13+
import javax.servlet.ServletException;
14+
import javax.servlet.ServletRequest;
15+
import javax.servlet.ServletResponse;
16+
17+
import org.junit.Before;
18+
import org.junit.Test;
19+
import org.junit.runner.RunWith;
20+
import org.mockito.InOrder;
21+
import org.mockito.Mock;
22+
import org.mockito.Mockito;
23+
import org.mockito.runners.MockitoJUnitRunner;
24+
25+
@RunWith(MockitoJUnitRunner.class)
26+
public class CompositeFilterTest {
27+
28+
@Mock
29+
private Filter filter1;
30+
@Mock
31+
private Filter filter2;
32+
33+
@Before
34+
public void setUp() throws Exception {
35+
Mockito.doAnswer(inv -> {
36+
doFilter(inv.getArguments());
37+
return null;
38+
}).when(filter1).doFilter(any(), any(), any());
39+
Mockito.doAnswer(inv -> {
40+
doFilter(inv.getArguments());
41+
return null;
42+
}).when(filter2).doFilter(any(), any(), any());
43+
}
44+
45+
private void doFilter(Object... arguments) throws IOException, ServletException {
46+
ServletRequest request = (ServletRequest) arguments[0];
47+
ServletResponse response = (ServletResponse) arguments[1];
48+
FilterChain filterChain = (FilterChain) arguments[2];
49+
filterChain.doFilter(request, response);
50+
}
51+
52+
@Test
53+
public void forwardsInitConfig() throws Exception {
54+
CompositeFilter filter = new CompositeFilter(filter1, filter2);
55+
FilterConfig config = mock(FilterConfig.class);
56+
57+
filter.init(config);
58+
59+
InOrder inOrder = inOrder(filter1, filter2);
60+
inOrder.verify(filter1).init(config);
61+
inOrder.verify(filter2).init(config);
62+
}
63+
64+
@Test
65+
public void destroysInCorrectOrder() throws Exception {
66+
CompositeFilter filter = new CompositeFilter(filter1, filter2);
67+
68+
filter.destroy();
69+
70+
InOrder inOrder = inOrder(filter1, filter2);
71+
inOrder.verify(filter2).destroy();
72+
inOrder.verify(filter1).destroy();
73+
}
74+
75+
@Test
76+
public void callsFiltersInOrder() throws Exception {
77+
CompositeFilter filter = new CompositeFilter(filter1, filter2);
78+
79+
ServletRequest request = mock(ServletRequest.class);
80+
ServletResponse response = mock(ServletResponse.class);
81+
FilterChain chain = mock(FilterChain.class);
82+
83+
filter.doFilter(request, response, chain);
84+
85+
InOrder inOrder = inOrder(filter1, filter2, chain);
86+
inOrder.verify(filter1).doFilter(eq(request), eq(response), any());
87+
inOrder.verify(filter2).doFilter(eq(request), eq(response), any());
88+
inOrder.verify(chain).doFilter(request, response);
89+
90+
}
91+
92+
}

0 commit comments

Comments
 (0)