diff --git a/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java b/core/src/main/java/org/acegisecurity/util/FilterChainProxy.java index eb40f62cab..20f8888bd4 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, 2005 Acegi Technology Pty Limited +/* Copyright 2004, 2005, 2006 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,6 +17,7 @@ package org.acegisecurity.util; import org.acegisecurity.ConfigAttribute; import org.acegisecurity.ConfigAttributeDefinition; + import org.acegisecurity.intercept.web.FilterInvocation; import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource; @@ -28,6 +29,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; + import org.springframework.util.Assert; import java.io.IOException; @@ -90,16 +92,20 @@ import javax.servlet.ServletResponse; *
* It is particularly noted the Filter lifecycle mismatch between
* the servlet container and IoC container. As per {@link
- * org.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.
+ * org.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.
+ *
+ * If a filter name of {@link #TOKEN_NONE} is used, this allows specification + * of a filter pattern which should never cause any filters to fire. *
* * @author Carlos Sanchez @@ -111,6 +117,7 @@ public class FilterChainProxy implements Filter, InitializingBean, //~ Static fields/initializers ============================================= private static final Log logger = LogFactory.getLog(FilterChainProxy.class); + public static final String TOKEN_NONE = "#NONE#"; //~ Instance fields ======================================================== @@ -119,36 +126,27 @@ public class FilterChainProxy implements Filter, InitializingBean, //~ Methods ================================================================ - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - - public void setFilterInvocationDefinitionSource( - FilterInvocationDefinitionSource filterInvocationDefinitionSource) { - this.filterInvocationDefinitionSource = filterInvocationDefinitionSource; - } - - public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() { - return filterInvocationDefinitionSource; - } - public void afterPropertiesSet() throws Exception { - Assert.notNull(filterInvocationDefinitionSource, "filterInvocationDefinitionSource must be specified"); - Assert.notNull(this.filterInvocationDefinitionSource.getConfigAttributeDefinitions(), "FilterChainProxy requires the FilterInvocationDefinitionSource to return a non-null response to getConfigAttributeDefinitions()"); + Assert.notNull(filterInvocationDefinitionSource, + "filterInvocationDefinitionSource must be specified"); + Assert.notNull(this.filterInvocationDefinitionSource + .getConfigAttributeDefinitions(), + "FilterChainProxy requires the FilterInvocationDefinitionSource to return a non-null response to getConfigAttributeDefinitions()"); } 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() + "'"); - } + if (filters[i] != null) { + if (logger.isDebugEnabled()) { + logger.debug( + "Destroying Filter defined in ApplicationContext: '" + + filters[i].toString() + "'"); + } - filters[i].destroy(); + filters[i].destroy(); + } } } @@ -174,17 +172,23 @@ public class FilterChainProxy implements Filter, InitializingBean, } } + public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() { + return filterInvocationDefinitionSource; + } + 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() + "'"); - } + if (filters[i] != null) { + if (logger.isDebugEnabled()) { + logger.debug( + "Initializing Filter defined in ApplicationContext: '" + + filters[i].toString() + "'"); + } - filters[i].init(filterConfig); + filters[i].init(filterConfig); + } } } @@ -231,11 +235,8 @@ public class FilterChainProxy implements Filter, InitializingBean, *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
+ * ConfigAttributeDefinition (never
+ * null)
*/
private Filter[] obtainAllDefinedFilters(
ConfigAttributeDefinition configAttributeDefinition) {
@@ -246,16 +247,29 @@ public class FilterChainProxy implements Filter, InitializingBean,
ConfigAttribute attr = (ConfigAttribute) attributes.next();
String filterName = attr.getAttribute();
- Assert.notNull(filterName, "Configuration attribute: '"
- + attr
- + "' returned null to the getAttribute() method, which is invalid when used with FilterChainProxy");
+ Assert.notNull(filterName,
+ "Configuration attribute: '" + attr
+ + "' returned null to the getAttribute() method, which is invalid when used with FilterChainProxy");
- list.add(this.applicationContext.getBean(filterName, Filter.class));
+ if (!filterName.equals(TOKEN_NONE)) {
+ list.add(this.applicationContext.getBean(filterName,
+ Filter.class));
+ }
}
return (Filter[]) list.toArray(new Filter[] {null});
}
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ public void setFilterInvocationDefinitionSource(
+ FilterInvocationDefinitionSource filterInvocationDefinitionSource) {
+ this.filterInvocationDefinitionSource = filterInvocationDefinitionSource;
+ }
+
//~ Inner Classes ==========================================================
/**
diff --git a/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java b/core/src/test/java/org/acegisecurity/util/FilterChainProxyTests.java
index d40f5fac34..738063e730 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, 2005 Acegi Technology Pty Limited
+/* Copyright 2004, 2005, 2006 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.
@@ -21,12 +21,14 @@ import org.acegisecurity.ConfigAttribute;
import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.MockApplicationContext;
import org.acegisecurity.MockFilterConfig;
+
import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource;
import org.acegisecurity.intercept.web.MockFilterInvocationDefinitionSource;
import org.acegisecurity.intercept.web.PathBasedFilterInvocationDefinitionMap;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -60,8 +62,7 @@ public class FilterChainProxyTests extends TestCase {
public void testDetectsFilterInvocationDefinitionSourceThatDoesNotReturnAllConfigAttributes()
throws Exception {
FilterChainProxy filterChainProxy = new FilterChainProxy();
- filterChainProxy.setApplicationContext(MockApplicationContext
- .getContext());
+ filterChainProxy.setApplicationContext(MockApplicationContext.getContext());
filterChainProxy.setFilterInvocationDefinitionSource(new MockFilterInvocationDefinitionSource(
false, false));
@@ -77,8 +78,7 @@ public class FilterChainProxyTests extends TestCase {
public void testDetectsIfConfigAttributeDoesNotReturnValueForGetAttributeMethod()
throws Exception {
FilterChainProxy filterChainProxy = new FilterChainProxy();
- filterChainProxy.setApplicationContext(MockApplicationContext
- .getContext());
+ filterChainProxy.setApplicationContext(MockApplicationContext.getContext());
ConfigAttributeDefinition cad = new ConfigAttributeDefinition();
cad.addConfigAttribute(new MockConfigAttribute());
@@ -93,15 +93,15 @@ public class FilterChainProxyTests extends TestCase {
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"));
+ assertTrue(expected.getMessage()
+ .endsWith("returned null to the getAttribute() method, which is invalid when used with FilterChainProxy"));
}
}
public void testDetectsMissingFilterInvocationDefinitionSource()
throws Exception {
FilterChainProxy filterChainProxy = new FilterChainProxy();
- filterChainProxy.setApplicationContext(MockApplicationContext
- .getContext());
+ filterChainProxy.setApplicationContext(MockApplicationContext.getContext());
try {
filterChainProxy.afterPropertiesSet();
@@ -112,6 +112,26 @@ public class FilterChainProxyTests extends TestCase {
}
}
+ public void testDoNotFilter() throws Exception {
+ ApplicationContext appCtx = new ClassPathXmlApplicationContext(
+ "org/acegisecurity/util/filtertest-valid.xml");
+ FilterChainProxy filterChainProxy = (FilterChainProxy) appCtx.getBean("filterChain",
+ FilterChainProxy.class);
+ MockFilter filter = (MockFilter) appCtx.getBean("mockFilter",
+ MockFilter.class);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setServletPath("/do/not/filter/somefile.html");
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterChain chain = new MockFilterChain(true);
+
+ filterChainProxy.doFilter(request, response, chain);
+ assertFalse(filter.isWasInitialized());
+ assertFalse(filter.isWasDoFiltered());
+ assertFalse(filter.isWasDestroyed());
+ }
+
public void testGettersSetters() {
FilterChainProxy filterChainProxy = new FilterChainProxy();
FilterInvocationDefinitionSource fids = new MockFilterInvocationDefinitionSource(false,
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 5e312a5dab..6e8bf3c132 100644
--- a/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml
+++ b/core/src/test/resources/org/acegisecurity/util/filtertest-valid.xml
@@ -34,6 +34,7 @@
PATTERN_TYPE_APACHE_ANT
/foo/**=mockFilter
/some/other/path/**=mockFilter
+ /do/not/filter=#NONE#