You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by lh...@apache.org on 2009/09/12 01:00:26 UTC

svn commit: r814073 - in /incubator/shiro/trunk: ./ core/src/main/java/org/apache/shiro/mgt/ core/src/main/java/org/apache/shiro/util/ samples/spring-hibernate/ samples/spring/ samples/web/ support/ support/groovy/ support/groovy/src/ support/groovy/sr...

Author: lhazlewood
Date: Fri Sep 11 23:00:25 2009
New Revision: 814073

URL: http://svn.apache.org/viewvc?rev=814073&view=rev
Log:
Began initial 'composition over inheritance' support for configuration.  None of the additions are used in existing code yet - they are there as placeholders only at the moment to be used later when refactoring existing components (e.g. IniWebConfiguration)

Added:
    incubator/shiro/trunk/support/groovy/   (with props)
    incubator/shiro/trunk/support/groovy/pom.xml
    incubator/shiro/trunk/support/groovy/src/
    incubator/shiro/trunk/support/groovy/src/main/
    incubator/shiro/trunk/support/groovy/src/main/java/
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/DefaultFilterChainManager.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainManager.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainResolver.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/NamedFilterList.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilterChainResolver.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/SimpleNamedFilterList.java
Modified:
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/CollectionUtils.java
    incubator/shiro/trunk/pom.xml
    incubator/shiro/trunk/samples/spring-hibernate/pom.xml
    incubator/shiro/trunk/samples/spring/pom.xml
    incubator/shiro/trunk/samples/web/pom.xml
    incubator/shiro/trunk/support/pom.xml
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebConfiguration.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/AbstractWebSecurityManagerTest.java

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java Fri Sep 11 23:00:25 2009
@@ -18,14 +18,14 @@
  */
 package org.apache.shiro.mgt;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
 import org.apache.shiro.cache.CacheManager;
 import org.apache.shiro.cache.CacheManagerAware;
 import org.apache.shiro.realm.Realm;
 import org.apache.shiro.util.LifecycleUtils;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 
 /**
  * Shiro support of a {@link SecurityManager} class hierarchy based around a collection of
@@ -110,7 +110,7 @@
     protected void applyCacheManagerToRealms() {
         CacheManager cacheManager = getCacheManager();
         Collection<Realm> realms = getRealms();
-        if (realms != null && !realms.isEmpty()) {
+        if (cacheManager != null && realms != null && !realms.isEmpty()) {
             for (Realm realm : realms) {
                 if (realm instanceof CacheManagerAware) {
                     ((CacheManagerAware) realm).setCacheManager(cacheManager);

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/CollectionUtils.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/CollectionUtils.java?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/CollectionUtils.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/util/CollectionUtils.java Fri Sep 11 23:00:25 2009
@@ -18,12 +18,7 @@
  */
 package org.apache.shiro.util;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  * Static helper class for use dealing with Arrays.
@@ -59,6 +54,24 @@
         return set;
     }
 
+    /**
+     * @param c
+     * @return
+     * @since 1.0
+     */
+    public static boolean isEmpty(Collection c) {
+        return c == null || c.isEmpty();
+    }
+
+    /**
+     * @param m
+     * @return
+     * @since 1.0
+     */
+    public static boolean isEmpty(Map m) {
+        return m == null || m.isEmpty();
+    }
+
     @SuppressWarnings({"unchecked"})
     public static <E> List<E> asList(E... elements) {
         if (elements == null || elements.length == 0) {

Modified: incubator/shiro/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/pom.xml?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/pom.xml (original)
+++ incubator/shiro/trunk/pom.xml Fri Sep 11 23:00:25 2009
@@ -59,9 +59,10 @@
     <properties>
         <jdk.version>1.5</jdk.version>
         <slf4j.version>1.5.6</slf4j.version>
-        <hsqldbVersion>1.8.0.7</hsqldbVersion>
-        <jettyVersion>6.1.20</jettyVersion>
-        <springframeworkVersion>2.5.6</springframeworkVersion>
+        <hsqldb.version>1.8.0.7</hsqldb.version>
+        <jetty.version>6.1.20</jetty.version>
+        <spring.version>2.5.6</spring.version>
+        <groovy.version>1.6.2</groovy.version>
     </properties>
 
     <modules>
@@ -176,7 +177,7 @@
             <dependency>
                 <groupId>hsqldb</groupId>
                 <artifactId>hsqldb</artifactId>
-                <version>${hsqldbVersion}</version>
+                <version>${hsqldb.version}</version>
                 <scope>runtime</scope>
                 <optional>true</optional>
             </dependency>
@@ -218,6 +219,11 @@
                 </exclusions>
             </dependency>
             <dependency>
+                <groupId>org.codehaus.groovy</groupId>
+                <artifactId>groovy-all</artifactId>
+                <version>${groovy.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>net.sf.ehcache</groupId>
                 <artifactId>ehcache</artifactId>
                 <version>1.4.1</version>
@@ -302,7 +308,7 @@
             <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring</artifactId>
-                <version>${springframeworkVersion}</version>
+                <version>${spring.version}</version>
                 <optional>true</optional>
                 <exclusions>
                     <exclusion>
@@ -314,7 +320,7 @@
             <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring-webmvc</artifactId>
-                <version>${springframeworkVersion}</version>
+                <version>${spring.version}</version>
                 <optional>true</optional>
                 <exclusions>
                     <exclusion>

Modified: incubator/shiro/trunk/samples/spring-hibernate/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/samples/spring-hibernate/pom.xml?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/samples/spring-hibernate/pom.xml (original)
+++ incubator/shiro/trunk/samples/spring-hibernate/pom.xml Fri Sep 11 23:00:25 2009
@@ -37,7 +37,7 @@
             <plugin>
                 <groupId>org.mortbay.jetty</groupId>
                 <artifactId>maven-jetty-plugin</artifactId>
-                <version>${jettyVersion}</version>
+                <version>${jetty.version}</version>
                 <!-- <configuration>
                     <contextPath>/shirosprhib</contextPath>
                     <connectors>
@@ -68,7 +68,7 @@
                     <dependency>
                         <groupId>hsqldb</groupId>
                         <artifactId>hsqldb</artifactId>
-                        <version>${hsqldbVersion}</version>
+                        <version>${hsqldb.version}</version>
                     </dependency>
                 </dependencies> -->
             </plugin>

Modified: incubator/shiro/trunk/samples/spring/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/samples/spring/pom.xml?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/samples/spring/pom.xml (original)
+++ incubator/shiro/trunk/samples/spring/pom.xml Fri Sep 11 23:00:25 2009
@@ -37,7 +37,7 @@
             <plugin>
                 <groupId>org.mortbay.jetty</groupId>
                 <artifactId>maven-jetty-plugin</artifactId>
-                <version>${jettyVersion}</version>
+                <version>${jetty.version}</version>
                 <configuration>
                     <contextPath>/shiro</contextPath>
                     <connectors>
@@ -58,7 +58,7 @@
                     <dependency>
                         <groupId>hsqldb</groupId>
                         <artifactId>hsqldb</artifactId>
-                        <version>${hsqldbVersion}</version>
+                        <version>${hsqldb.version}</version>
                     </dependency>
                 </dependencies>
             </plugin>
@@ -109,7 +109,7 @@
         <dependency>
             <groupId>hsqldb</groupId>
             <artifactId>hsqldb</artifactId>
-            <version>${hsqldbVersion}</version>
+            <version>${hsqldb.version}</version>
             <scope>runtime</scope>
         </dependency>
         <dependency>

Modified: incubator/shiro/trunk/samples/web/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/samples/web/pom.xml?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/samples/web/pom.xml (original)
+++ incubator/shiro/trunk/samples/web/pom.xml Fri Sep 11 23:00:25 2009
@@ -43,7 +43,7 @@
             <plugin>
                 <groupId>org.mortbay.jetty</groupId>
                 <artifactId>maven-jetty-plugin</artifactId>
-                <version>${jettyVersion}</version>
+                <version>${jetty.version}</version>
                 <configuration>
                     <contextPath>/</contextPath>
                     <connectors>
@@ -101,13 +101,13 @@
         <dependency>
             <groupId>org.mortbay.jetty</groupId>
             <artifactId>jetty</artifactId>
-            <version>${jettyVersion}</version>
+            <version>${jetty.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.mortbay.jetty</groupId>
             <artifactId>jsp-2.1-jetty</artifactId>
-            <version>${jettyVersion}</version>
+            <version>${jetty.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>

Propchange: incubator/shiro/trunk/support/groovy/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Sep 11 23:00:25 2009
@@ -0,0 +1 @@
+*.iml

Added: incubator/shiro/trunk/support/groovy/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/groovy/pom.xml?rev=814073&view=auto
==============================================================================
--- incubator/shiro/trunk/support/groovy/pom.xml (added)
+++ incubator/shiro/trunk/support/groovy/pom.xml Fri Sep 11 23:00:25 2009
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<!--suppress osmorcNonOsgiMavenDependency -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <parent>
+        <groupId>org.apache.shiro</groupId>
+        <artifactId>shiro-root</artifactId>
+        <version>1.0-incubating-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>shiro-groovy</artifactId>
+    <name>Apache Shiro :: Support :: Groovy</name>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-all</artifactId>
+        </dependency>
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

Modified: incubator/shiro/trunk/support/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/pom.xml?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/support/pom.xml (original)
+++ incubator/shiro/trunk/support/pom.xml Fri Sep 11 23:00:25 2009
@@ -33,6 +33,7 @@
 
     <modules>
         <module>ehcache</module>
+        <module>groovy</module>
         <module>quartz</module>
         <module>spring</module>
     </modules>

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebConfiguration.java?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebConfiguration.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebConfiguration.java Fri Sep 11 23:00:25 2009
@@ -19,40 +19,16 @@
 package org.apache.shiro.web.config;
 
 import org.apache.shiro.config.Configuration;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import org.apache.shiro.web.filter.FilterChainResolver;
 
 /**
- * A <code>WebConfiguration</code> configures Shiro components in a web-enabled application.
- * <p/>
- * In addition to enabling configuration of a <code>SecurityManager</code>, as required by the parent interface,
- * it also allows configuration of arbitrary filter chains to be executed for any given request or URI/URL.
+ * A {@code WebConfiguration} configures Shiro components in a web-enabled application.
  * <p/>
- * This is incredibly powerful and <em>much</em> more flexible than normal servlet filter definitions or Servlet
- * security: it allows arbitrary filter chains to be defined per URL in a much more concise and easy to read manner,
- * and even allows filter chains to be dynamically resolved or construtected at runtime if the underlying implementation
- * supports it.
+ * In addition to enabling configuration of a <code>SecurityManager</code>, as required by the parent
+ * {@link Configuration} interface, it also allows configuration of arbitrary filter chains to be executed for any
+ * given request or URI/URL by sub-interfacing the {@link FilterChainResolver} interface.
  *
- * @author Les Hazlewood
- * @since Jun 1, 2008 11:13:32 PM
+ * @since 0.9
  */
-public interface WebConfiguration extends Configuration {
-
-    /**
-     * Returns the filter chain that should be executed for the given request, or <code>null</code> if the
-     * original chain should be used.
-     *
-     * <p>This method allows a Configuration implementation to define arbitrary security {@link Filter Filter}
-     * chains for any given request or URL pattern.
-     *
-     * @param request       the incoming ServletRequest
-     * @param response      the outgoing ServletResponse
-     * @param originalChain the original <code>FilterChain</code> intercepted by the ShiroFilter.
-     * @return the filter chain that should be executed for the given request, or <code>null</code> if the
-     *         original chain should be used.
-     */
-    FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain);
+public interface WebConfiguration extends Configuration, FilterChainResolver {
 }

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/DefaultFilterChainManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/DefaultFilterChainManager.java?rev=814073&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/DefaultFilterChainManager.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/DefaultFilterChainManager.java Fri Sep 11 23:00:25 2009
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.web.filter;
+
+import org.apache.shiro.ShiroException;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.util.CollectionUtils;
+import org.apache.shiro.util.Initializable;
+import org.apache.shiro.util.Nameable;
+import org.apache.shiro.util.StringUtils;
+import org.apache.shiro.web.filter.authc.AnonymousFilter;
+import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
+import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
+import org.apache.shiro.web.filter.authc.UserFilter;
+import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
+import org.apache.shiro.web.filter.authz.PortFilter;
+import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter;
+import org.apache.shiro.web.filter.authz.SslFilter;
+import org.apache.shiro.web.servlet.ProxiedFilterChain;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import java.util.*;
+
+/**
+ * @since 1.0
+ */
+public class DefaultFilterChainManager implements FilterChainManager, Initializable {
+
+    private static transient final Logger log = LoggerFactory.getLogger(DefaultFilterChainManager.class);
+
+    private FilterConfig filterConfig;
+
+    private Map<String, Filter> filters; //pool of filters available for creating filters
+
+    private Map<String, NamedFilterList> filterChains; //name to filter chain mapping
+
+    public DefaultFilterChainManager() {
+        this.filters = new LinkedHashMap<String, Filter>();
+        this.filterChains = new LinkedHashMap<String, NamedFilterList>();
+    }
+
+    public DefaultFilterChainManager(FilterConfig filterConfig) {
+        this();
+        init(filterConfig);
+    }
+
+    /**
+     * Returns the {@code FilterConfig} provided by the Servlet container at webapp startup.
+     *
+     * @return the {@code FilterConfig} provided by the Servlet container at webapp startup.
+     */
+    public FilterConfig getFilterConfig() {
+        return filterConfig;
+    }
+
+    /**
+     * Sets the {@code FilterConfig} provided by the Servlet container at webapp startup.
+     *
+     * @param filterConfig the {@code FilterConfig} provided by the Servlet container at webapp startup.
+     */
+    public void setFilterConfig(FilterConfig filterConfig) {
+        this.filterConfig = filterConfig;
+    }
+
+    public Map<String, Filter> getFilters() {
+        return filters;
+    }
+
+    public void setFilters(Map<String, Filter> filters) {
+        this.filters = filters;
+    }
+
+    public Map<String, NamedFilterList> getFilterChains() {
+        return filterChains;
+    }
+
+    public void setFilterChains(Map<String, NamedFilterList> filterChains) {
+        this.filterChains = filterChains;
+    }
+
+    public void init() throws ShiroException {
+        if (this.filterConfig == null) {
+            throw new IllegalStateException("filterConfig attribute must be set.");
+        }
+        addDefaultFilters();
+    }
+
+    public void init(FilterConfig filterConfig) throws ShiroException {
+        setFilterConfig(filterConfig);
+        init();
+    }
+
+    public Filter getFilter(String name) {
+        return this.filters.get(name);
+    }
+
+    public void addFilter(String name, Filter filter) {
+        addFilter(name, filter, true);
+    }
+
+    public void addFilter(String name, Filter filter, boolean init) {
+        addFilter(name, filter, init, true);
+    }
+
+    protected void addFilter(String name, Filter filter, boolean init, boolean overwrite) {
+        Filter existing = getFilter(name);
+        if (existing == null || overwrite) {
+            if (init) {
+                initFilter(filter);
+            }
+            this.filters.put(name, filter);
+        }
+    }
+
+    public void addToChain(String chainName, String filterName) {
+        addToChain(chainName, filterName, null);
+    }
+
+    protected void applyChainConfig(String chainName, Filter filter, String chainSpecificFilterConfig) {
+        if (filter instanceof PathConfigProcessor) {
+            ((PathConfigProcessor) filter).processPathConfig(chainName, chainSpecificFilterConfig);
+        } else {
+            String msg = "chainSpecificFilterConfig was specified as a method argument, but the underlying " +
+                    "Filter instance is not an 'instanceof' " +
+                    PathConfigProcessor.class.getName() + ".  This is required if the filter is to accept " +
+                    "chain-specific configuration.";
+            throw new IllegalArgumentException(msg);
+        }
+    }
+
+    protected NamedFilterList ensureChain(String chainName) {
+        NamedFilterList chain = getChain(chainName);
+        if (chain == null) {
+            chain = new SimpleNamedFilterList(chainName);
+            this.filterChains.put(chainName, chain);
+        }
+        return chain;
+    }
+
+    public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig) {
+        Filter filter = getFilter(filterName);
+        if (filter == null) {
+            throw new IllegalArgumentException("There is no filter with name '" + filterName +
+                    "' to apply to chain [" + chainName + "]");
+        }
+        if (StringUtils.hasText(chainSpecificFilterConfig)) {
+            applyChainConfig(chainName, filter, chainSpecificFilterConfig);
+        }
+
+        NamedFilterList chain = ensureChain(chainName);
+        chain.add(filter);
+    }
+
+    public NamedFilterList getChain(String chainName) {
+        return this.filterChains.get(chainName);
+    }
+
+    public boolean hasChains() {
+        return !CollectionUtils.isEmpty(this.filterChains);
+    }
+
+    public Set<String> getChainNames() {
+        //noinspection unchecked
+        return this.filterChains != null ? this.filterChains.keySet() : Collections.EMPTY_SET;
+    }
+
+    public FilterChain proxy(FilterChain original, String chainName) {
+        NamedFilterList configured = getChain(chainName);
+        if (configured == null) {
+            String msg = "There is no configured chain under the name/key [" + chainName + "].";
+            throw new IllegalArgumentException(msg);
+        }
+        return configured.proxy(original);
+    }
+
+    /**
+     * Returns the {@code FilterChain} to use for the specified application path, or {@code null} if there
+     * was not a configured chain for the specified path.
+     * <p/>
+     * The default implementation simply calls <code>this.chains.get(chainUrl)</code> to acquire the configured
+     * {@code List&lt;Filter&gt;} filter chain.  If that configured chain is non-null and not empty, it is
+     * returned, otherwise {@code null} is returned to indicate that the {@code originalChain} should be
+     * used instead.
+     *
+     * @param chainUrl      the configured filter chain url
+     * @param originalChain the original FilterChain given by the Servlet container.
+     * @return the {@code FilterChain} to use for the specified application path, or {@code null} if the
+     *         original {@code FilterChain} should be used.
+     */
+    public FilterChain getChain(String chainUrl, FilterChain originalChain) {
+        Map<String, NamedFilterList> filterChains = getFilterChains();
+        List<Filter> pathFilters = filterChains != null ? filterChains.get(chainUrl) : null;
+        if (!CollectionUtils.isEmpty(pathFilters)) {
+            return createChain(pathFilters, originalChain);
+        }
+        return null;
+    }
+
+    /**
+     * Creates a new FilterChain based on the specified configured url filter chain and original chain.
+     * <p/>
+     * The input arguments are expected be be non-null and non-empty, since these conditions are accounted for in the
+     * {@link #getChain(String, javax.servlet.FilterChain) getChain(chainUrl,originalChain)} implementation that
+     * calls this method.
+     * <p/>
+     * The default implementation merely returns
+     * <code>new {@link org.apache.shiro.web.servlet.ProxiedFilterChain FilterChainWrapper(filters, originalChain)}</code>,
+     * and can be overridden by subclasses for custom creation.
+     *
+     * @param filters       the configured filter chain for the incoming request application path
+     * @param originalChain the original FilterChain given by the Servlet container.
+     * @return a new FilterChain based on the specified configured url filter chain and original chain.
+     */
+    protected FilterChain createChain(List<Filter> filters, FilterChain originalChain) {
+        return new ProxiedFilterChain(originalChain, filters);
+    }
+
+    /**
+     * Initializes the filter by calling <code>filter.init( {@link #getFilterConfig() getFilterConfig()} );</code>.
+     *
+     * @param filter the filter to initialize with the <code>FilterConfig</code>.
+     */
+    protected void initFilter(Filter filter) {
+        FilterConfig filterConfig = getFilterConfig();
+        if (filterConfig == null) {
+            throw new IllegalStateException("FilterConfig attribute has not been set.  This must occur before filter " +
+                    "initialization can occur.");
+        }
+        try {
+            filter.init(filterConfig);
+        } catch (ServletException e) {
+            throw new ConfigurationException(e);
+        }
+    }
+
+    protected void createFilters() {
+        addDefaultFilters();
+    }
+
+    protected void addFilterIfNecessary(String name, Filter filter) {
+        if (getFilter(name) == null) {
+            //has not been added yet, so add it now:
+            if (filter instanceof Nameable) {
+                ((Nameable) filter).setName(name);
+            }
+            addFilter(name, filter);
+        }
+    }
+
+    protected void addDefaultFilters() {
+        addFilter("anon", new AnonymousFilter(), true, false);
+        addFilter("user", new UserFilter(), true, false);
+        addFilter("authc", new FormAuthenticationFilter(), true, false);
+        addFilter("authcBasic", new BasicHttpAuthenticationFilter(), true, false);
+        addFilter("roles", new RolesAuthorizationFilter(), true, false);
+        addFilter("perms", new PermissionsAuthorizationFilter(), true, false);
+        addFilter("port", new PortFilter(), true, false);
+        addFilter("ssl", new SslFilter(), true, false);
+    }
+}

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainManager.java?rev=814073&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainManager.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainManager.java Fri Sep 11 23:00:25 2009
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.web.filter;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import java.util.Set;
+
+/**
+ * @since 1.0
+ */
+public interface FilterChainManager {
+
+    /**
+     * Returns the filter chain identified by the specified {@code chainName} or {@code null} if there is no chain with
+     * that name.
+     *
+     * @param chainName the name identifying the filter chain.
+     * @return the filter chain identified by the specified {@code chainName} or {@code null} if there is no chain with
+     *         that name.
+     */
+    NamedFilterList getChain(String chainName);
+
+    /**
+     * Returns {@code true} if one or more configured chains are available, {@code false} if none are configured.
+     *
+     * @return {@code true} if one or more configured chains are available, {@code false} if none are configured.
+     */
+    boolean hasChains();
+
+    /**
+     * Returns the names of all configured chains or an empty {@code Set} if no chains have been configured.
+     *
+     * @return the names of all configured chains or an empty {@code Set} if no chains have been configured.
+     */
+    Set<String> getChainNames();
+
+    /**
+     * Proxies the specified {@code original} FilterChain with the named chain.  The returned
+     * {@code FilterChain} instance will first execute the configured named chain and then lastly invoke the given
+     * {@code original} chain.
+     *
+     * @param original  the original FilterChain to proxy
+     * @param chainName the name of the internal configured filter chain that should 'sit in front' of the specified
+     *                  original chain.
+     * @return a {@code FilterChain} instance that will execute the named chain and then finally the
+     *         specified {@code original} FilterChain instance.
+     * @throws IllegalArgumentException if there is no configured chain with the given {@code chainName}.
+     */
+    FilterChain proxy(FilterChain original, String chainName);
+
+    /**
+     * Adds a filter to the 'pool' of available filters that can be used when
+     * {@link #addToChain(String, String, String) creating filter chains}.
+     * <p/>
+     * Calling this method is effectively the same as calling
+     * <code>{@link #addFilter(String, javax.servlet.Filter, boolean) addFilter}(name, filter, <b>true</b>);</code>
+     *
+     * @param name   the name to assign to the filter, used to reference the filter in chain definitions
+     * @param filter the filter to initialize and then add to the pool of available filters that can be used
+     */
+    void addFilter(String name, Filter filter);
+
+    /**
+     * Adds a filter to the 'pool' of available filters that can be used when
+     * {@link #addToChain(String, String, String) creating filter chains}.
+     *
+     * @param name   the name to assign to the filter, used to reference the filter in chain definitions
+     * @param filter the filter to assign to the filter pool
+     * @param init   whether or not the {@code Filter} should be
+     *               {@link Filter#init(javax.servlet.FilterConfig) initialized} first before being added to the pool.
+     */
+    void addFilter(String name, Filter filter, boolean init);
+
+    /**
+     * Adds (appends) a filter to the filter chain identified by the given {@code chainName}.  If there is no chain
+     * with the given name, a new one is created and the filter will be the first in the chain.
+     *
+     * @param chainName  the name of the chain where the filter will be appended.
+     * @param filterName the name of the {@link #addFilter registered} filter to add to the chain.
+     * @throws IllegalArgumentException if there is not a {@link #addFilter(String, javax.servlet.Filter) registered}
+     *                                  filter under the given {@code filterName}
+     */
+    void addToChain(String chainName, String filterName);
+
+    /**
+     * Adds (appends) a filter to the filter chain identified by the given {@code chainName}.  If there is no chain
+     * with the given name, a new one is created and the filter will be the first in the chain.
+     * <p/>
+     * Note that the final argument expects the associated filter to be an instance of
+     * a {@link org.apache.shiro.web.filter.PathConfigProcessor PathConfigProcessor} to accept per-chain configuration.
+     * If it is not, a {@link IllegalArgumentException} will be thrown.
+     *
+     * @param chainName                 the name of the chain where the filter will be appended.
+     * @param filterName                the name of the {@link #addFilter registered} filter to add to the chain.
+     * @param chainSpecificFilterConfig the filter-specific configuration that should be applied for only the specified
+     *                                  filter chain.
+     * @throws IllegalArgumentException if there is not a {@link #addFilter(String, javax.servlet.Filter) registered}
+     *                                  filter under the given {@code filterName}
+     */
+    void addToChain(String chainName, String filterName, String chainSpecificFilterConfig);
+}

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainResolver.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainResolver.java?rev=814073&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainResolver.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/FilterChainResolver.java Fri Sep 11 23:00:25 2009
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.web.filter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * A {@code FilterChainResolver} can resolve an appropriate {@link FilterChain} to execute during a
+ * {@code ServletRequest}.  It allows resolution of arbitrary filter chains which can be executed for any given
+ * request or URI/URL.
+ * <p/>
+ * This mechanism allows for a much more flexible FilterChain resolution than normal {@code web.xml} servlet filter
+ * definitions:  it allows arbitrary filter chains to be defined per URL in a much more concise and easy to read manner,
+ * and even allows filter chains to be dynamically resolved or constructed at runtime if the underlying implementation
+ * supports it.
+ *
+ * @since 1.0
+ */
+public interface FilterChainResolver {
+
+    /**
+     * Returns the filter chain that should be executed for the given request, or <code>null</code> if the
+     * original chain should be used.
+     * <p/>
+     * <p>This method allows a implementation to define arbitrary security {@link javax.servlet.Filter Filter}
+     * chains for any given request or URL pattern.
+     *
+     * @param request       the incoming ServletRequest
+     * @param response      the outgoing ServletResponse
+     * @param originalChain the original <code>FilterChain</code> intercepted by the ShiroFilter.
+     * @return the filter chain that should be executed for the given request, or <code>null</code> if the
+     *         original chain should be used.
+     */
+    FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain);
+
+}

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/NamedFilterList.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/NamedFilterList.java?rev=814073&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/NamedFilterList.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/NamedFilterList.java Fri Sep 11 23:00:25 2009
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.web.filter;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import java.util.List;
+
+/**
+ * @since 1.0
+ */
+public interface NamedFilterList extends List<Filter> {
+
+    String getName();
+
+    FilterChain proxy(FilterChain filterChain);
+}

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilterChainResolver.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilterChainResolver.java?rev=814073&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilterChainResolver.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilterChainResolver.java Fri Sep 11 23:00:25 2009
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.web.filter;
+
+import org.apache.shiro.util.AntPathMatcher;
+import org.apache.shiro.util.PatternMatcher;
+import org.apache.shiro.web.WebUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * @since 1.0
+ */
+public class PathMatchingFilterChainResolver implements FilterChainResolver {
+
+    private static transient final Logger log = LoggerFactory.getLogger(PathMatchingFilterChainResolver.class);
+
+    private FilterChainManager filterChainManager;
+
+    protected PatternMatcher pathMatcher;
+
+    public PathMatchingFilterChainResolver() {
+        this.pathMatcher = new AntPathMatcher();
+    }
+
+    public PathMatchingFilterChainResolver(FilterConfig filterConfig) {
+        this();
+        this.filterChainManager = new DefaultFilterChainManager(filterConfig);
+    }
+
+    /**
+     * Returns the {@code PatternMatcher} used when determining if an incoming request's path
+     * matches a configured filter chain.  Unless overridden, the
+     * default implementation is an {@link org.apache.shiro.util.AntPathMatcher AntPathMatcher}.
+     *
+     * @return the {@code PatternMatcher} used when determining if an incoming request's path
+     *         matches a configured filter chain.
+     */
+    public PatternMatcher getPathMatcher() {
+        return pathMatcher;
+    }
+
+    /**
+     * Sets the {@code PatternMatcher} used when determining if an incoming request's path
+     * matches a configured filter chain.  Unless overridden, the
+     * default implementation is an {@link org.apache.shiro.util.AntPathMatcher AntPathMatcher}.
+     *
+     * @param pathMatcher the {@code PatternMatcher} used when determining if an incoming request's path
+     *                    matches a configured filter chain.
+     */
+    public void setPathMatcher(PatternMatcher pathMatcher) {
+        this.pathMatcher = pathMatcher;
+    }
+
+    public FilterChainManager getFilterChainManager() {
+        return filterChainManager;
+    }
+
+    public void setFilterChainManager(FilterChainManager filterChainManager) {
+        this.filterChainManager = filterChainManager;
+    }
+
+    public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
+        FilterChainManager filterChainManager = getFilterChainManager();
+        if (!filterChainManager.hasChains()) {
+            return null;
+        }
+
+        String requestURI = getPathWithinApplication(request);
+
+        //the 'chain names' in this implementation are actually path patterns defined by the user.  We just use them
+        //as the chain name for the FilterChainManager's requirements
+        for (String pathPattern : filterChainManager.getChainNames()) {
+
+            // If the path does match, then pass on to the subclass implementation for specific checks:
+            if (pathMatches(pathPattern, requestURI)) {
+                if (log.isTraceEnabled()) {
+                    log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "].  " +
+                            "Utilizing corresponding filter chain...");
+                }
+                return filterChainManager.proxy(originalChain, pathPattern);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns {@code true} if an incoming request's path (the {@code path} argument)
+     * matches a configured filter chain path in the {@code [urls]} section (the {@code pattern} argument),
+     * {@code false} otherwise.
+     * <p/>
+     * Simply delegates to
+     * <b><code>{@link #getPathMatcher() getPathMatcher()}.{@link org.apache.shiro.util.PatternMatcher#matches(String, String) matches(pattern,path)}</code></b>,
+     * but can be overridden by subclasses for custom matching behavior.
+     *
+     * @param pattern the pattern to match against
+     * @param path    the value to match with the specified {@code pattern}
+     * @return {@code true} if the request {@code path} matches the specified filter chain url {@code pattern},
+     *         {@code false} otherwise.
+     */
+    protected boolean pathMatches(String pattern, String path) {
+        PatternMatcher pathMatcher = getPathMatcher();
+        return pathMatcher.matches(pattern, path);
+    }
+
+    /**
+     * Merely returns
+     * <code>WebUtils.{@link org.apache.shiro.web.WebUtils#getPathWithinApplication(javax.servlet.http.HttpServletRequest) getPathWithinApplication(request)}</code>
+     * and can be overridden by subclasses for custom request-to-application-path resolution behavior.
+     *
+     * @param request the incoming {@code ServletRequest}
+     * @return the request's path within the appliation.
+     */
+    protected String getPathWithinApplication(ServletRequest request) {
+        return WebUtils.getPathWithinApplication(WebUtils.toHttp(request));
+    }
+}

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/SimpleNamedFilterList.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/SimpleNamedFilterList.java?rev=814073&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/SimpleNamedFilterList.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/SimpleNamedFilterList.java Fri Sep 11 23:00:25 2009
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.web.filter;
+
+import org.apache.shiro.util.StringUtils;
+import org.apache.shiro.web.servlet.ProxiedFilterChain;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import java.util.*;
+
+/**
+ * @since 1.0
+ */
+public class SimpleNamedFilterList implements NamedFilterList {
+
+    private String name;
+    private List<Filter> backingList;
+
+    public SimpleNamedFilterList(String name) {
+        this.backingList = new ArrayList<Filter>();
+        setName(name);
+    }
+
+    protected void setName(String name) {
+        if (!StringUtils.hasText(name)) {
+            throw new IllegalArgumentException("Cannot specify an empty name.");
+        }
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public FilterChain proxy(FilterChain orig) {
+        return new ProxiedFilterChain(orig, this);
+    }
+
+    public boolean add(Filter filter) {
+        return this.backingList.add(filter);
+    }
+
+    public void add(int index, Filter filter) {
+        this.backingList.add(index, filter);
+    }
+
+    public boolean addAll(Collection<? extends Filter> c) {
+        return this.backingList.addAll(c);
+    }
+
+    public boolean addAll(int index, Collection<? extends Filter> c) {
+        return this.backingList.addAll(index, c);
+    }
+
+    public void clear() {
+        this.backingList.clear();
+    }
+
+    public boolean contains(Object o) {
+        return this.backingList.contains(o);
+    }
+
+    public boolean containsAll(Collection<?> c) {
+        return this.backingList.containsAll(c);
+    }
+
+    public Filter get(int index) {
+        return this.backingList.get(index);
+    }
+
+    public int indexOf(Object o) {
+        return this.backingList.indexOf(o);
+    }
+
+    public boolean isEmpty() {
+        return this.backingList.isEmpty();
+    }
+
+    public Iterator<Filter> iterator() {
+        return this.backingList.iterator();
+    }
+
+    public int lastIndexOf(Object o) {
+        return this.backingList.lastIndexOf(o);
+    }
+
+    public ListIterator<Filter> listIterator() {
+        return this.backingList.listIterator();
+    }
+
+    public ListIterator<Filter> listIterator(int index) {
+        return this.backingList.listIterator(index);
+    }
+
+    public Filter remove(int index) {
+        return this.backingList.remove(index);
+    }
+
+    public boolean remove(Object o) {
+        return this.backingList.remove(o);
+    }
+
+    public boolean removeAll(Collection<?> c) {
+        return this.backingList.removeAll(c);
+    }
+
+    public boolean retainAll(Collection<?> c) {
+        return this.backingList.retainAll(c);
+    }
+
+    public Filter set(int index, Filter filter) {
+        return this.backingList.set(index, filter);
+    }
+
+    public int size() {
+        return this.backingList.size();
+    }
+
+    public List<Filter> subList(int fromIndex, int toIndex) {
+        return this.backingList.subList(fromIndex, toIndex);
+    }
+
+    public Object[] toArray() {
+        return this.backingList.toArray();
+    }
+
+    public <T> T[] toArray(T[] a) {
+        //noinspection SuspiciousToArrayCall
+        return this.backingList.toArray(a);
+    }
+}

Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/AbstractWebSecurityManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/AbstractWebSecurityManagerTest.java?rev=814073&r1=814072&r2=814073&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/AbstractWebSecurityManagerTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/AbstractWebSecurityManagerTest.java Fri Sep 11 23:00:25 2009
@@ -39,6 +39,7 @@
     }
 
     protected Subject newSubject(SecurityManager sm, ServletRequest request, ServletResponse response) {
+        ThreadContext.bind(sm);
         WebUtils.bind(request);
         WebUtils.bind(response);
         WebSubject subject = new WebSubject.Builder(sm, request, response).buildWebSubject();