    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 }