diff --git a/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java b/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java index 4c948e87fe..ba365ed376 100644 --- a/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java +++ b/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,111 +15,113 @@ package net.sf.acegisecurity.util; -import java.io.IOException; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; - import net.sf.acegisecurity.ConfigAttribute; import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.intercept.web.FilterInvocation; import net.sf.acegisecurity.intercept.web.FilterInvocationDefinitionSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.BeanFactoryUtils; + +import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.config.BeanPostProcessor; + import org.springframework.context.ApplicationContext; -import org.springframework.web.context.support.WebApplicationContextUtils; +import org.springframework.context.ApplicationContextAware; + +import java.io.IOException; + +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.Vector; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + /** - * Delegates Filter requests to a Spring-managed bean. + * Delegates Filter requests to a list of Spring-managed beans. + * *

- * This class acts as a proxy on behalf of a target Filter that - * is defined in the Spring bean context. It is necessary to specify which - * target Filter should be proxied as a filter initialization - * parameter. - *

- *

- * On filter initialisation, the class will use Spring's {@link - * WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)} - * method to obtain an ApplicationContext instance. It will - * expect to find the target Filter in this - * ApplicationContext. - *

- *

- * To use this filter, it is necessary to specify one of the following - * filter initialization parameters: - *

- * - * If both initialization parameters are specified, targetBean - * takes priority. - *

- * An additional initialization parameter, init, is also - * supported. If set to "lazy" the initialization will take - * place on the first HTTP request, rather than at filter creation time. This - * makes it possible to use FilterToBeanProxy with the Spring - * ContextLoaderServlet. Where possible you should not use this - * initialization parameter, instead using ContextLoaderListener. + * The FilterChainProxy is loaded via a standard {@link + * net.sf.acegisecurity.util.FilterToBeanProxy} declaration in + * web.xml. FilterChainProxy will then pass {@link + * #init(FilterConfig)}, {@link #destroy()}, {@link #doInit()} and {@link + * #doFilter(ServletRequest, ServletResponse, FilterChain)} invocations + * through to each Filter defined against + * FilterChainProxy. *

* -// *
-// * <bean id="filterChain" class="net.sf.acegisecurity.FilterChain">
-// *   <property name="filters">
-// *   <value>
-// *     channelProcessingFilter=/*
-// *     authenticationProcessingFilter=/*
-// *     basicProcessingFilter=/*
-// *     sessionIntegrationFilter=/*
-// *     securityEnforcementFilter=/*
-// *   </value>
-// *   </property>
-// * </bean>
-// * 
+ *

+ * FilterChainProxy is configured using a standard {@link + * net.sf.acegisecurity.intercept.web.FilterInvocationDefinitionSource}. Each + * possible URI pattern that FilterChainProxy should service must + * be entered. The first matching URI pattern located by + * FilterInvocationDefinitionSource for a given request will be + * used to define all of the Filters that apply to that request. + * NB: This means you must put most specific URI patterns at the top of the + * list, and ensure all Filters that should apply for a given URI + * pattern are entered against the respective entry. The + * FilterChainProxy will not iterate the remainder of the URI + * patterns to locate additional Filters. The + * FilterInvocationDefinitionSource described the applicable URI + * pattern to fire the filter chain, followed by a list of configuration + * attributes. Each configuration attribute's {@link + * net.sf.acegisecurity.ConfigAttribute#getAttribute()} corresponds to a bean + * name that is available from the application context. + *

* + *

+ * FilterChainProxy respects normal handling of + * Filters that elect not to call {@link + * javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, + * javax.servlet.ServletResponse, javax.servlet.FilterChain)}, in that the + * remainder of the origial or FilterChainProxy-declared filter + * chain will not be called. + *

+ * + *

+ * It is particularly noted the Filter lifecycle mismatch between + * the servlet container and IoC container. As per {@link + * net.sf.acegisecurity.util.FilterToBeanProxy} JavaDocs, we recommend you + * allow the IoC container to manage lifecycle instead of the servlet + * container. By default the FilterToBeanProxy will never call + * this class' {@link #init(FilterConfig)} and {@link #destroy()} methods, + * meaning each of the filters defined against + * FilterInvocationDefinitionSource will not be called. If you do + * need your filters to be initialized and destroyed, please set the + * lifecycle initialization parameter against the + * FilterToBeanProxy to specify servlet container lifecycle + * management. + *

+ * * @author Carlos Sanchez + * @author Ben Alex * @version $Id$ */ -public class FilterChainProxy - implements Filter, InitializingBean -{ +public class FilterChainProxy implements Filter, InitializingBean, + ApplicationContextAware { //~ Static fields/initializers ============================================= private static final Log logger = LogFactory.getLog(FilterChainProxy.class); - //~ Instance fields - // ======================================================== - - private Filter delegate; - - private List filters; - - private FilterConfig filterConfig; - - private boolean initialized = false; + //~ Instance fields ======================================================== + private ApplicationContext applicationContext; private FilterInvocationDefinitionSource filterInvocationDefinitionSource; - //~ Methods - // ================================================================ + //~ Methods ================================================================ + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } public void setFilterInvocationDefinitionSource( FilterInvocationDefinitionSource filterInvocationDefinitionSource) { @@ -130,119 +132,185 @@ public class FilterChainProxy return filterInvocationDefinitionSource; } - public void destroy() - { - Iterator it = filters.iterator(); - while ( it.hasNext() ) - { - Filter filter = (Filter) it.next(); - if ( filter != null ) - { - filter.destroy(); - } - } - } - - public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, - ServletException - { - if ( !initialized ) - { - doInit(); - } - - Iterator it = filters.iterator(); - while ( it.hasNext() ) - { - Filter filter = (Filter) it.next(); - filter.doFilter( request, response, chain ); - } - } - - public void init( FilterConfig filterConfig ) throws ServletException - { - this.filterConfig = filterConfig; - - String strategy = filterConfig.getInitParameter( "init" ); - - if ( (strategy != null) && strategy.toLowerCase().equals( "lazy" ) ) - { - return; - } - - doInit(); - } - - /** - * Allows test cases to override where application context obtained from. - * - * @param filterConfig - * which can be used to find the ServletContext - * @return the Spring application context - */ - protected ApplicationContext getContext( FilterConfig filterConfig ) - { - return WebApplicationContextUtils.getRequiredWebApplicationContext( filterConfig.getServletContext() ); - } - - private void doInit() throws ServletException - { - initialized = true; - - Iterator it = filters.iterator(); - while ( it.hasNext() ) - { - Filter filter = (Filter) it.next(); - filter.init( filterConfig ); - } - - } - public void afterPropertiesSet() throws Exception { if (filterInvocationDefinitionSource == null) { throw new IllegalArgumentException( "filterInvocationDefinitionSource must be specified"); } - Iterator iter = this.filterInvocationDefinitionSource - .getConfigAttributeDefinitions(); - - if (iter == null) { - if (logger.isWarnEnabled()) { - logger.warn( - "Could not validate configuration attributes as the FilterInvocationDefinitionSource did not return a ConfigAttributeDefinition Iterator"); - } - - return; - } - - Set set = new HashSet(); - - while (iter.hasNext()) { - ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter - .next(); - Iterator attributes = def.getConfigAttributes(); - - while (attributes.hasNext()) { - ConfigAttribute attr = (ConfigAttribute) attributes.next(); - } - } - - if (set.size() == 0) { - if (logger.isInfoEnabled()) { - logger.info("Validated configuration attributes"); - } - } else { + if (this.filterInvocationDefinitionSource.getConfigAttributeDefinitions() == null) { throw new IllegalArgumentException( - "Unsupported configuration attributes: " + set.toString()); - } - - iter = filterInvocationDefinitionSource.getConfigAttributeDefinitions(); - while ( iter.hasNext() ) - { - ConfigAttributeDefinition element = (ConfigAttributeDefinition) iter.next(); - Iterator configAttributes = element.getConfigAttributes(); + "FilterChainProxy requires the FitlerInvocationDefinitionSource to return a non-null response to getConfigAttributeDefinitions()"); } } -} \ No newline at end of file + public void destroy() { + Filter[] filters = obtainAllDefinedFilters(); + + for (int i = 0; i < filters.length; i++) { + if (logger.isDebugEnabled()) { + logger.debug( + "Destroying Filter defined in ApplicationContext: '" + + filters[i].toString() + "'"); + } + + filters[i].destroy(); + } + } + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + FilterInvocation fi = new FilterInvocation(request, response, chain); + + ConfigAttributeDefinition cad = this.filterInvocationDefinitionSource + .getAttributes(fi); + + if (cad == null) { + if (logger.isDebugEnabled()) { + logger.debug(fi.getRequestUrl() + " has no matching filters"); + } + + chain.doFilter(request, response); + } else { + Filter[] filters = obtainAllDefinedFilters(cad); + + VirtualFilterChain virtualFilterChain = new VirtualFilterChain(fi, + filters); + virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse()); + } + } + + public void init(FilterConfig filterConfig) throws ServletException { + Filter[] filters = obtainAllDefinedFilters(); + + for (int i = 0; i < filters.length; i++) { + if (logger.isDebugEnabled()) { + logger.debug( + "Initializing Filter defined in ApplicationContext: '" + + filters[i].toString() + "'"); + } + + filters[i].init(filterConfig); + } + } + + /** + * Obtains all of the uniqueFilter instances registered + * against the FilterInvocationDefinitionSource. + * + *

+ * This is useful in ensuring a Filter is not initialized or + * destroyed twice. + *

+ * + * @return all of the Filter instances in the application + * context for which there has been an entry against the + * FilterInvocationDefinitionSource (only one entry + * is included in the array for each Filter that + * actually exists in application context, even if a given + * Filter is defined multiples times by the + * FilterInvocationDefinitionSource) + */ + private Filter[] obtainAllDefinedFilters() { + Iterator cads = this.filterInvocationDefinitionSource + .getConfigAttributeDefinitions(); + Set list = new LinkedHashSet(); + + while (cads.hasNext()) { + ConfigAttributeDefinition attribDef = (ConfigAttributeDefinition) cads + .next(); + Filter[] filters = obtainAllDefinedFilters(attribDef); + + for (int i = 0; i < filters.length; i++) { + list.add(filters[i]); + } + } + + return (Filter[]) list.toArray(new Filter[] {null}); + } + + /** + * Obtains all of the Filter instances registered against the + * specified ConfigAttributeDefinition. + * + * @param configAttributeDefinition for which we want to obtain associated + * Filters + * + * @return the Filters against the specified + * ConfigAttributeDefinition + * + * @throws IllegalArgumentException if a configuration attribute provides a + * null return value from the {@link + * ConfigAttribute#getAttribute()} method + */ + private Filter[] obtainAllDefinedFilters( + ConfigAttributeDefinition configAttributeDefinition) { + List list = new Vector(); + Iterator attributes = configAttributeDefinition.getConfigAttributes(); + + while (attributes.hasNext()) { + ConfigAttribute attr = (ConfigAttribute) attributes.next(); + String filterName = attr.getAttribute(); + + if (filterName == null) { + throw new IllegalArgumentException("Configuration attribute: '" + + attr + + "' returned null to the getAttribute() method, which is invalid when used with FilterChainProxy"); + } + + list.add(this.applicationContext.getBean(filterName, Filter.class)); + } + + return (Filter[]) list.toArray(new Filter[] {null}); + } + + //~ Inner Classes ========================================================== + + /** + * A FilterChain that records whether or not {@link + * FilterChain#doFilter(javax.servlet.ServletRequest, + * javax.servlet.ServletResponse)} is called. + * + *

+ * This FilterChain is used by FilterChainProxy + * to determine if the next Filter should be called or not. + *

+ */ + private class VirtualFilterChain implements FilterChain { + private FilterInvocation fi; + private Filter[] additionalFilters; + private int currentPosition = 0; + + public VirtualFilterChain(FilterInvocation filterInvocation, + Filter[] additionalFilters) { + this.fi = filterInvocation; + this.additionalFilters = additionalFilters; + } + + private VirtualFilterChain() {} + + public void doFilter(ServletRequest arg0, ServletResponse arg1) + throws IOException, ServletException { + if (currentPosition == additionalFilters.length) { + if (logger.isDebugEnabled()) { + logger.debug(fi.getRequestUrl() + + " reached end of additional filter chain; proceeding with original chain"); + } + + fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); + } else { + currentPosition++; + + if (logger.isDebugEnabled()) { + logger.debug(fi.getRequestUrl() + " at position " + + currentPosition + " of " + additionalFilters.length + + " in additional filter chain; firing Filter: '" + + additionalFilters[currentPosition - 1] + "'"); + } + + additionalFilters[currentPosition - 1].doFilter(fi.getRequest(), + fi.getResponse(), this); + } + } + } +} diff --git a/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java b/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java index 90342528ca..a9a03f2106 100644 --- a/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java +++ b/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,15 @@ package net.sf.acegisecurity.util; import junit.framework.TestCase; +import net.sf.acegisecurity.ConfigAttribute; +import net.sf.acegisecurity.ConfigAttributeDefinition; +import net.sf.acegisecurity.MockApplicationContext; import net.sf.acegisecurity.MockFilterConfig; import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpServletResponse; +import net.sf.acegisecurity.intercept.web.FilterInvocationDefinitionSource; +import net.sf.acegisecurity.intercept.web.MockFilterInvocationDefinitionSource; +import net.sf.acegisecurity.intercept.web.PathBasedFilterInvocationDefinitionMap; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -33,229 +39,138 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; + /** * Tests {@link FilterChainProxy}. - * + * * @author Carlos Sanchez + * @author Ben Alex * @version $Id$ */ -public class FilterChainProxyTests - extends TestCase -{ - //~ Constructors - // =========================================================== +public class FilterChainProxyTests extends TestCase { + //~ Constructors =========================================================== - public FilterChainProxyTests() - { + // =========================================================== + public FilterChainProxyTests() { super(); } - public FilterChainProxyTests( String arg0 ) - { - super( arg0 ); + public FilterChainProxyTests(String arg0) { + super(arg0); } - //~ Methods + //~ Methods ================================================================ + // ================================================================ - - public final void setUp() throws Exception - { - super.setUp(); -// ApplicationContext applicationContext = new ClassPathXmlApplicationContext( -// "net/sf/acegisecurity/util/filtertest-valid.xml" ); -// FilterChainProxy filterChainProxy = (FilterChainProxy)applicationContext.getBean("filterChain"); -// System.out.println(filterChainProxy); + public static void main(String[] args) { + junit.textui.TestRunner.run(FilterChainProxyTests.class); } - public static void main( String[] args ) - { - junit.textui.TestRunner.run( FilterChainProxyTests.class ); - } + public void testDetectsFilterInvocationDefinitionSourceThatDoesNotReturnAllConfigAttributes() + throws Exception { + FilterChainProxy filterChainProxy = new FilterChainProxy(); + filterChainProxy.setApplicationContext(MockApplicationContext + .getContext()); + filterChainProxy.setFilterInvocationDefinitionSource(new MockFilterInvocationDefinitionSource( + false, false)); - public void testDetectsTargetBeanIsNotAFilter() throws Exception - { - // Setup our filter - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter( "targetClass", "net.sf.acegisecurity.util.MockNotAFilter" ); - - FilterToBeanProxy filter = new MockFilterToBeanProxy( "net/sf/acegisecurity/util/filtertest-valid.xml" ); - - try - { - filter.init( config ); - fail( "Should have thrown ServletException" ); - } - catch ( ServletException expected ) - { - assertEquals( "Bean 'mockNotAFilter' does not implement javax.servlet.Filter", expected.getMessage() ); + try { + filterChainProxy.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("FilterChainProxy requires the FitlerInvocationDefinitionSource to return a non-null response to getConfigAttributeDefinitions()", + expected.getMessage()); } } - public void testDetectsTargetBeanNotInBeanContext() throws Exception - { - // Setup our filter - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter( "targetBean", "WRONG_NAME" ); + public void testDetectsIfConfigAttributeDoesNotReturnValueForGetAttributeMethod() + throws Exception { + FilterChainProxy filterChainProxy = new FilterChainProxy(); + filterChainProxy.setApplicationContext(MockApplicationContext + .getContext()); - FilterToBeanProxy filter = new MockFilterToBeanProxy( "net/sf/acegisecurity/util/filtertest-valid.xml" ); + ConfigAttributeDefinition cad = new ConfigAttributeDefinition(); + cad.addConfigAttribute(new MockConfigAttribute()); - try - { - filter.init( config ); - fail( "Should have thrown ServletException" ); - } - catch ( ServletException expected ) - { - assertEquals( "targetBean 'WRONG_NAME' not found in context", expected.getMessage() ); + PathBasedFilterInvocationDefinitionMap fids = new PathBasedFilterInvocationDefinitionMap(); + fids.addSecureUrl("/**", cad); + + filterChainProxy.setFilterInvocationDefinitionSource(fids); + filterChainProxy.afterPropertiesSet(); + + try { + filterChainProxy.init(new MockFilterConfig()); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertTrue(expected.getMessage().endsWith("returned null to the getAttribute() method, which is invalid when used with FilterChainProxy")); } } - public void testIgnoresEmptyTargetBean() throws Exception - { - // Setup our filter - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter( "targetClass", "net.sf.acegisecurity.util.FilterChainProxy" ); - config.setInitParmeter( "targetBean", "" ); + public void testDetectsMissingFilterInvocationDefinitionSource() + throws Exception { + FilterChainProxy filterChainProxy = new FilterChainProxy(); + filterChainProxy.setApplicationContext(MockApplicationContext + .getContext()); - // Setup our expectation that the filter chain will be invoked - MockFilterChain chain = new MockFilterChain( true ); + try { + filterChainProxy.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + assertEquals("filterInvocationDefinitionSource must be specified", + expected.getMessage()); + } + } + + public void testGettersSetters() { + FilterChainProxy filterChainProxy = new FilterChainProxy(); + FilterInvocationDefinitionSource fids = new MockFilterInvocationDefinitionSource(false, + false); + filterChainProxy.setFilterInvocationDefinitionSource(fids); + assertEquals(fids, + filterChainProxy.getFilterInvocationDefinitionSource()); + } + + public void testNormalOperation() throws Exception { + ApplicationContext appCtx = new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/util/filtertest-valid.xml"); + FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain", + FilterChainProxy.class); + MockFilter filter = (MockFilter) appCtx.getBean("mockFilter", + MockFilter.class); + assertFalse(filter.isWasInitialized()); + assertFalse(filter.isWasDoFiltered()); + assertFalse(filter.isWasDestroyed()); + + filterChainProxy.init(new MockFilterConfig()); + assertTrue(filter.isWasInitialized()); + assertFalse(filter.isWasDoFiltered()); + assertFalse(filter.isWasDestroyed()); + + MockHttpServletRequest request = new MockHttpServletRequest(null); + request.setServletPath("/foo/secure/super/somefile.html"); MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest( "/go" ); + MockFilterChain chain = new MockFilterChain(true); - FilterToBeanProxy filter = new MockFilterToBeanProxy( "net/sf/acegisecurity/util/filtertest-valid.xml" ); + filterChainProxy.doFilter(request, response, chain); + assertTrue(filter.isWasInitialized()); + assertTrue(filter.isWasDoFiltered()); + assertFalse(filter.isWasDestroyed()); - executeFilterInContainerSimulator( config, filter, request, response, chain ); + request.setServletPath("/a/path/which/doesnt/match/any/filter.html"); + filterChainProxy.doFilter(request, response, chain); + + filterChainProxy.destroy(); + assertTrue(filter.isWasInitialized()); + assertTrue(filter.isWasDoFiltered()); + assertTrue(filter.isWasDestroyed()); } - public void testNormalOperationWithLazyTrue() throws Exception - { - // Setup our filter - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter( "targetBean", "filterChain" ); - config.setInitParmeter( "init", "lazy" ); + //~ Inner Classes ========================================================== - // Setup our expectation that the filter chain will be invoked - MockFilterChain chain = new MockFilterChain( true ); - - MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest( "/go" ); - - FilterToBeanProxy filter = new MockFilterToBeanProxy( "net/sf/acegisecurity/util/filtertest-valid.xml" ); - - executeFilterInContainerSimulator( config, filter, request, response, chain ); - } - - public void testNormalOperationWithSpecificBeanName() throws Exception - { - // Setup our filter - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter( "targetBean", "filterChain" ); - - // Setup our expectation that the filter chain will be invoked - MockFilterChain chain = new MockFilterChain( true ); - - MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest( "/go" ); - - FilterToBeanProxy filter = new MockFilterToBeanProxy( "net/sf/acegisecurity/util/filtertest-valid.xml" ); - - executeFilterInContainerSimulator( config, filter, request, response, chain ); - } - - public void testNormalOperationWithTargetClass() throws Exception - { - // Setup our filter - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter( "targetClass", "net.sf.acegisecurity.util.FilterChainProxy" ); - - // Setup our expectation that the filter chain will be invoked - MockFilterChain chain = new MockFilterChain( true ); - - MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest( "/go" ); - - FilterToBeanProxy filter = new MockFilterToBeanProxy( "net/sf/acegisecurity/util/filtertest-valid.xml" ); - - executeFilterInContainerSimulator( config, filter, request, response, chain ); - } - - public void testNullDelegateDoesNotCauseNullPointerException() throws Exception - { - // Setup our filter - MockFilterConfig config = new MockFilterConfig(); - config.setInitParmeter( "targetBean", "aFilterThatDoesntExist" ); - config.setInitParmeter( "init", "lazy" ); - - // Setup our expectation that the filter chain will be invoked - MockFilterChain chain = new MockFilterChain( true ); - - MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest( "/go" ); - - FilterToBeanProxy filter = new MockFilterToBeanProxy( "net/sf/acegisecurity/util/filtertest-valid.xml" ); - - // do not init (which would hapen if called .doFilter) - filter.destroy(); - } - - private void executeFilterInContainerSimulator( FilterConfig filterConfig, Filter filter, ServletRequest request, - ServletResponse response, FilterChain filterChain ) throws ServletException, IOException - { - filter.init( filterConfig ); - filter.doFilter( request, response, filterChain ); - filter.destroy(); - } - - //~ Inner Classes - // ========================================================== - - private class MockFilterChain - implements FilterChain - { - private boolean expectToProceed; - - public MockFilterChain( boolean expectToProceed ) - { - this.expectToProceed = expectToProceed; - } - - private MockFilterChain() - { - super(); - } - - public void doFilter( ServletRequest request, ServletResponse response ) throws IOException, ServletException - { - if ( expectToProceed ) - { - assertTrue( true ); - } - else - { - fail( "Did not expect filter chain to proceed" ); - } + private class MockConfigAttribute implements ConfigAttribute { + public String getAttribute() { + return null; } } - - private class MockFilterToBeanProxy - extends FilterToBeanProxy - { - private String appContextLocation; - - public MockFilterToBeanProxy( String appContextLocation ) - { - this.appContextLocation = appContextLocation; - } - - private MockFilterToBeanProxy() - { - super(); - } - - protected ApplicationContext getContext( FilterConfig filterConfig ) - { - return new ClassPathXmlApplicationContext( appContextLocation ); - } - } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/acegisecurity/util/MockFilter.java b/core/src/test/java/org/acegisecurity/util/MockFilter.java index 8a25614254..0bab8dd06e 100644 --- a/core/src/test/java/org/acegisecurity/util/MockFilter.java +++ b/core/src/test/java/org/acegisecurity/util/MockFilter.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,14 +32,37 @@ import javax.servlet.ServletResponse; * @version $Id$ */ public class MockFilter implements Filter { + //~ Instance fields ======================================================== + + private boolean wasDestroyed = false; + private boolean wasDoFiltered = false; + private boolean wasInitialized = false; + //~ Methods ================================================================ - public void destroy() {} + public boolean isWasDestroyed() { + return wasDestroyed; + } + + public boolean isWasDoFiltered() { + return wasDoFiltered; + } + + public boolean isWasInitialized() { + return wasInitialized; + } + + public void destroy() { + wasDestroyed = true; + } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + wasDoFiltered = true; chain.doFilter(request, response); } - public void init(FilterConfig config) throws ServletException {} + public void init(FilterConfig config) throws ServletException { + wasInitialized = true; + } } diff --git a/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml b/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml index ccb388a6e1..9dec34f55e 100644 --- a/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml +++ b/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml @@ -23,21 +23,19 @@ + + - /*=mockFilter + CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON + PATTERN_TYPE_APACHE_ANT + /foo/**=mockFilter + /some/other/path/**=mockFilter -