1   /* Copyright 2004 Acegi Technology Pty Limited
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    *     http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  package org.acegisecurity.securechannel;
17  
18  import junit.framework.TestCase;
19  
20  import org.acegisecurity.ConfigAttribute;
21  import org.acegisecurity.ConfigAttributeDefinition;
22  
23  
24  import org.acegisecurity.SecurityConfig;
25  
26  import org.acegisecurity.intercept.web.FilterInvocation;
27  import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource;
28  
29  import java.io.IOException;
30  
31  import java.util.Iterator;
32  import java.util.List;
33  import java.util.Vector;
34  
35  import javax.servlet.FilterChain;
36  import javax.servlet.ServletException;
37  import javax.servlet.ServletRequest;
38  import javax.servlet.ServletResponse;
39  
40  import org.springframework.mock.web.MockHttpServletRequest;
41  import org.springframework.mock.web.MockHttpServletResponse;
42  
43  
44  /***
45   * Tests {@link ChannelProcessingFilter}.
46   *
47   * @author Ben Alex
48   * @version $Id: ChannelProcessingFilterTests.java,v 1.4 2005/11/17 00:55:48 benalex Exp $
49   */
50  public class ChannelProcessingFilterTests extends TestCase {
51      //~ Methods ================================================================
52  
53      public final void setUp() throws Exception {
54          super.setUp();
55      }
56  
57      public static void main(String[] args) {
58          junit.textui.TestRunner.run(ChannelProcessingFilterTests.class);
59      }
60  
61      public void testDetectsMissingChannelDecisionManager()
62          throws Exception {
63          ChannelProcessingFilter filter = new ChannelProcessingFilter();
64  
65          ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
66          attr.addConfigAttribute(new SecurityConfig("MOCK"));
67  
68          MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
69                  attr, true);
70          filter.setFilterInvocationDefinitionSource(fids);
71  
72          try {
73              filter.afterPropertiesSet();
74              fail("Should have thrown IllegalArgumentException");
75          } catch (IllegalArgumentException expected) {
76              assertEquals("channelDecisionManager must be specified",
77                  expected.getMessage());
78          }
79      }
80  
81      public void testDetectsMissingFilterInvocationDefinitionSource()
82          throws Exception {
83          ChannelProcessingFilter filter = new ChannelProcessingFilter();
84          filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
85                  "MOCK"));
86  
87          try {
88              filter.afterPropertiesSet();
89              fail("Should have thrown IllegalArgumentException");
90          } catch (IllegalArgumentException expected) {
91              assertEquals("filterInvocationDefinitionSource must be specified",
92                  expected.getMessage());
93          }
94      }
95  
96      public void testDetectsSupportedConfigAttribute() throws Exception {
97          ChannelProcessingFilter filter = new ChannelProcessingFilter();
98          filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
99                  "SUPPORTS_MOCK_ONLY"));
100 
101         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
102         attr.addConfigAttribute(new SecurityConfig("SUPPORTS_MOCK_ONLY"));
103 
104         MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
105                 attr, true);
106 
107         filter.setFilterInvocationDefinitionSource(fids);
108 
109         filter.afterPropertiesSet();
110         assertTrue(true);
111     }
112 
113     public void testDetectsUnsupportedConfigAttribute()
114         throws Exception {
115         ChannelProcessingFilter filter = new ChannelProcessingFilter();
116         filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
117                 "SUPPORTS_MOCK_ONLY"));
118 
119         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
120         attr.addConfigAttribute(new SecurityConfig("SUPPORTS_MOCK_ONLY"));
121         attr.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE"));
122 
123         MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
124                 attr, true);
125 
126         filter.setFilterInvocationDefinitionSource(fids);
127 
128         try {
129             filter.afterPropertiesSet();
130             fail("Should have thrown IllegalArgumentException");
131         } catch (IllegalArgumentException expected) {
132             assertTrue(expected.getMessage().startsWith("Unsupported configuration attributes:"));
133         }
134     }
135 
136     public void testDoFilterWhenManagerDoesCommitResponse()
137         throws Exception {
138         ChannelProcessingFilter filter = new ChannelProcessingFilter();
139         filter.setChannelDecisionManager(new MockChannelDecisionManager(true,
140                 "SOME_ATTRIBUTE"));
141 
142         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
143         attr.addConfigAttribute(new SecurityConfig("SOME_ATTRIBUTE"));
144 
145         MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
146                 attr, true);
147 
148         filter.setFilterInvocationDefinitionSource(fids);
149 
150         MockHttpServletRequest request = new MockHttpServletRequest();
151         request.setQueryString("info=now");
152         request.setServletPath("/path");
153 
154         MockHttpServletResponse response = new MockHttpServletResponse();
155         MockFilterChain chain = new MockFilterChain(false);
156 
157         filter.doFilter(request, response, chain);
158         assertTrue(true);
159     }
160 
161     public void testDoFilterWhenManagerDoesNotCommitResponse()
162         throws Exception {
163         ChannelProcessingFilter filter = new ChannelProcessingFilter();
164         filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
165                 "SOME_ATTRIBUTE"));
166 
167         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
168         attr.addConfigAttribute(new SecurityConfig("SOME_ATTRIBUTE"));
169 
170         MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
171                 attr, true);
172 
173         filter.setFilterInvocationDefinitionSource(fids);
174 
175         MockHttpServletRequest request = new MockHttpServletRequest();
176         request.setQueryString("info=now");
177         request.setServletPath("/path");
178 
179         MockHttpServletResponse response = new MockHttpServletResponse();
180         MockFilterChain chain = new MockFilterChain(true);
181 
182         filter.doFilter(request, response, chain);
183         assertTrue(true);
184     }
185 
186     public void testDoFilterWhenNullConfigAttributeReturned()
187         throws Exception {
188         ChannelProcessingFilter filter = new ChannelProcessingFilter();
189         filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
190                 "NOT_USED"));
191 
192         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
193         attr.addConfigAttribute(new SecurityConfig("NOT_USED"));
194 
195         MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
196                 attr, true);
197 
198         filter.setFilterInvocationDefinitionSource(fids);
199 
200         MockHttpServletRequest request = new MockHttpServletRequest();
201         request.setQueryString("info=now");
202         request.setServletPath("/PATH_NOT_MATCHING_CONFIG_ATTRIBUTE");
203 
204         MockHttpServletResponse response = new MockHttpServletResponse();
205         MockFilterChain chain = new MockFilterChain(true);
206 
207         filter.doFilter(request, response, chain);
208         assertTrue(true);
209     }
210 
211     public void testDoFilterWithNonHttpServletRequestDetected()
212         throws Exception {
213         ChannelProcessingFilter filter = new ChannelProcessingFilter();
214 
215         try {
216             filter.doFilter(null, new MockHttpServletResponse(),
217                 new MockFilterChain());
218             fail("Should have thrown ServletException");
219         } catch (ServletException expected) {
220             assertEquals("HttpServletRequest required", expected.getMessage());
221         }
222     }
223 
224     public void testDoFilterWithNonHttpServletResponseDetected()
225         throws Exception {
226         ChannelProcessingFilter filter = new ChannelProcessingFilter();
227 
228         try {
229             filter.doFilter(new MockHttpServletRequest(null, null), null,
230                 new MockFilterChain());
231             fail("Should have thrown ServletException");
232         } catch (ServletException expected) {
233             assertEquals("HttpServletResponse required", expected.getMessage());
234         }
235     }
236 
237     public void testGetterSetters() throws Exception {
238         ChannelProcessingFilter filter = new ChannelProcessingFilter();
239         filter.setChannelDecisionManager(new MockChannelDecisionManager(false,
240                 "MOCK"));
241         assertTrue(filter.getChannelDecisionManager() != null);
242 
243         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
244         attr.addConfigAttribute(new SecurityConfig("MOCK"));
245 
246         MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path",
247                 attr, false);
248 
249         filter.setFilterInvocationDefinitionSource(fids);
250         assertTrue(filter.getFilterInvocationDefinitionSource() != null);
251 
252         filter.init(null);
253         filter.afterPropertiesSet();
254         filter.destroy();
255     }
256 
257     //~ Inner Classes ==========================================================
258 
259     private class MockChannelDecisionManager implements ChannelDecisionManager {
260         private String supportAttribute;
261         private boolean commitAResponse;
262 
263         public MockChannelDecisionManager(boolean commitAResponse,
264             String supportAttribute) {
265             this.commitAResponse = commitAResponse;
266             this.supportAttribute = supportAttribute;
267         }
268 
269         private MockChannelDecisionManager() {
270             super();
271         }
272 
273         public void decide(FilterInvocation invocation,
274             ConfigAttributeDefinition config)
275             throws IOException, ServletException {
276             if (commitAResponse) {
277                 invocation.getHttpResponse().sendRedirect("/redirected");
278             }
279         }
280 
281         public boolean supports(ConfigAttribute attribute) {
282             if (attribute.getAttribute().equals(supportAttribute)) {
283                 return true;
284             } else {
285                 return false;
286             }
287         }
288     }
289 
290     private class MockFilterChain implements FilterChain {
291         private boolean expectToProceed;
292 
293         public MockFilterChain(boolean expectToProceed) {
294             this.expectToProceed = expectToProceed;
295         }
296 
297         private MockFilterChain() {
298             super();
299         }
300 
301         public void doFilter(ServletRequest request, ServletResponse response)
302             throws IOException, ServletException {
303             if (expectToProceed) {
304                 assertTrue(true);
305             } else {
306                 fail("Did not expect filter chain to proceed");
307             }
308         }
309     }
310 
311     private class MockFilterInvocationDefinitionMap
312         implements FilterInvocationDefinitionSource {
313         private ConfigAttributeDefinition toReturn;
314         private String servletPath;
315         private boolean provideIterator;
316 
317         public MockFilterInvocationDefinitionMap(String servletPath,
318             ConfigAttributeDefinition toReturn, boolean provideIterator) {
319             this.servletPath = servletPath;
320             this.toReturn = toReturn;
321             this.provideIterator = provideIterator;
322         }
323 
324         private MockFilterInvocationDefinitionMap() {
325             super();
326         }
327 
328         public ConfigAttributeDefinition getAttributes(Object object)
329             throws IllegalArgumentException {
330             FilterInvocation fi = (FilterInvocation) object;
331 
332             if (servletPath.equals(fi.getHttpRequest().getServletPath())) {
333                 return toReturn;
334             } else {
335                 return null;
336             }
337         }
338 
339         public Iterator getConfigAttributeDefinitions() {
340             if (!provideIterator) {
341                 return null;
342             }
343 
344             List list = new Vector();
345             list.add(toReturn);
346 
347             return list.iterator();
348         }
349 
350         public boolean supports(Class clazz) {
351             return true;
352         }
353     }
354 }