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:
- *
- *
- * targetClass
indicates the class of the target
- * Filter
defined in the bean context. The only requirements are
- * that this target class implements the javax.servlet.Filter
- * interface and at least one instance is available in the
- * ApplicationContext
.
- * targetBean
indicates the bean name of the target class.
- *
- *
- * 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 Filter
s that apply to that request.
+ * NB: This means you must put most specific URI patterns at the top of the
+ * list, and ensure all Filter
s 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 Filter
s. 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
+ * Filter
s 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
+ * Filter
s
+ *
+ * @return the Filter
s 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
-