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/11/01 01:05:36 UTC

svn commit: r831623 - in /incubator/shiro/trunk: ./ core/src/main/java/org/apache/shiro/config/ core/src/main/java/org/apache/shiro/crypto/hash/ core/src/main/java/org/apache/shiro/io/ core/src/main/java/org/apache/shiro/mgt/ core/src/main/java/org/apa...

Author: lhazlewood
Date: Sun Nov  1 00:05:33 2009
New Revision: 831623

URL: http://svn.apache.org/viewvc?rev=831623&view=rev
Log:
- Finished initial change to configuration infrastructure to use the new IniShiroFilter and supporting classes.  The existing ShiroFilter class and all of its supporting *Resource and *Configurtion classes still exist and have not been changed, but they are now deprecated in favor of the new AbstractShiroFilter and IniShiroFilter mechanisms.  
- Updated the sample web application's web.xml to use the new IniShiroFilter.
- Added or modified unit tests for 99-100% line coverage for IniShiroFilter, IniFilterChainResolverFactory, DefaultFilterChainManager, and PathMatchingFilterChainResolver.

Added:
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebTest.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/authc/AnonymousFilterTest.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolverTest.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/IniShiroFilterTest.java
      - copied, changed from r831582, incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java
    incubator/shiro/trunk/web/src/test/resources/IniShiroFilterTest.ini
Removed:
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java
Modified:
    incubator/shiro/trunk/README-runtime-requirements.txt
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Configuration.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniConfiguration.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/ResourceConfiguration.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/TextConfiguration.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Md2Hash.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/AbstractResource.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/IniResource.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/ResourceException.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/TextResource.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManagerFactory.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
    incubator/shiro/trunk/samples/web/src/main/webapp/WEB-INF/web.xml
    incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringIniWebConfiguration.java
    incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringShiroFilter.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniWebConfiguration.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebConfiguration.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebIniSecurityManagerFactory.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/AnonymousFilter.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainResolver.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManagerTest.java

Modified: incubator/shiro/trunk/README-runtime-requirements.txt
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/README-runtime-requirements.txt?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/README-runtime-requirements.txt (original)
+++ incubator/shiro/trunk/README-runtime-requirements.txt Sun Nov  1 00:05:33 2009
@@ -15,5 +15,5 @@
 
 Feature-based dependencies
 --------------------------
-* .ini based configuration, either for a shiro.ini file in the classpath or embedded .ini in the ShiroFilter in web.xml:
+* .ini based configuration, either for a shiro.ini file in the classpath or embedded .ini in the IniShiroFilter in web.xml:
   - include Jakarta commons-beanutils-core.jar

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Configuration.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Configuration.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Configuration.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Configuration.java Sun Nov  1 00:05:33 2009
@@ -28,9 +28,15 @@
  * <p/>
  * Once the SecurityManager is built by the <code>Configuration</code> it is then consulted for all security
  * operations during the application's lifetime.
- * 
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
+ *
  * @author Les Hazlewood
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public interface Configuration extends SecurityManagerFactory {
 }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java Sun Nov  1 00:05:33 2009
@@ -49,6 +49,9 @@
 
     public Ini(Ini defaults) {
         this();
+        if (defaults == null) {
+            throw new NullPointerException("Defaults cannot be null.");
+        }
         for (Section section : defaults.getSections()) {
             Section copy = new Section(section);
             this.sections.put(section.getName(), copy);

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniConfiguration.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniConfiguration.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniConfiguration.java Sun Nov  1 00:05:33 2009
@@ -37,11 +37,18 @@
 
 /**
  * A Configuration based on the <a href="http://en.wikipedia.org/wiki/INI_file">.ini format</a>.
+ * <p/>
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public class IniConfiguration extends TextConfiguration {
 
     //TODO - complete JavaDoc

Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java?rev=831623&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java Sun Nov  1 00:05:33 2009
@@ -0,0 +1,140 @@
+/*
+ * 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.config;
+
+import org.apache.shiro.io.ResourceUtils;
+import org.apache.shiro.util.Factory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base support class for {@link Factory} implementations that generate their instance(s) based on
+ * {@link Ini} configuration.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public abstract class IniFactorySupport<T> implements Factory<T> {
+
+    public static final String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";
+
+    private static transient final Logger log = LoggerFactory.getLogger(IniFactorySupport.class);
+
+    private Ini ini;
+
+    protected IniFactorySupport() {
+    }
+
+    protected IniFactorySupport(Ini ini) {
+        this.ini = ini;
+    }
+
+    public Ini getIni() {
+        return ini;
+    }
+
+    public void setIni(Ini ini) {
+        this.ini = ini;
+    }
+
+    protected static boolean isEmpty(Ini ini) {
+        return ini == null || ini.isEmpty();
+    }
+
+    /**
+     * Returns a new Ini instance created from the default {@code classpath:shiro.ini} file, or {@code null} if
+     * the file does not exist.
+     *
+     * @return a new Ini instance created from the default {@code classpath:shiro.ini} file, or {@code null} if
+     *         the file does not exist.
+     */
+    public static Ini loadDefaultClassPathIni() {
+        Ini ini = null;
+        if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) {
+            log.debug("Found shiro.ini at the root of the classpath.");
+            ini = new Ini();
+            ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH);
+            if (isEmpty(ini)) {
+                log.warn("shiro.ini found at the root of the classpath, but it did not contain any data.");
+            }
+        }
+        return ini;
+    }
+
+    /**
+     * Tries to resolve the Ini instance to use for configuration.  This implementation functions as follows:
+     * <ol>
+     * <li>The {@code Ini} instance returned from {@link #getIni()} will be returned if it is not null or empty.</li>
+     * <li>If {@link #getIni()} is {@code null} or empty, this implementation will attempt to find and load the
+     * {@link #loadDefaultClassPathIni() default class path Ini}.</li>
+     * <li>If neither of the two attempts above returns an instance, {@code null} is returned</li>
+     * </ol>
+     *
+     * @return the Ini instance to use for configuration.
+     */
+    protected Ini resolveIni() {
+        Ini ini = getIni();
+        if (isEmpty(ini)) {
+            log.debug("Null or empty Ini instance.  Falling back to the default {} file.", DEFAULT_INI_RESOURCE_PATH);
+            ini = loadDefaultClassPathIni();
+        }
+        return ini;
+    }
+
+    /**
+     * Creates a new object instance by using a configured INI source.  This implementation functions as follows:
+     * <ol>
+     * <li>{@link #resolveIni() Resolve} the {@code Ini} source to use for configuration.</li>
+     * <li>If there was no resolved Ini source, create and return a simple default instance via the
+     * {@link #createDefaultInstance()} method.</li>
+     * </ol>
+     *
+     * @return a new {@code SecurityManager} instance by using a configured INI source.
+     */
+    public T createInstance() {
+        Ini ini = resolveIni();
+
+        T instance;
+
+        if (!isEmpty(ini)) {
+            log.debug("Creating instance from Ini [" + ini + "]");
+            instance = createInstance(ini);
+            if (instance == null) {
+                String msg = getClass().getName() + " implementation did not return a constructed instance from " +
+                        "the createInstance(Ini) method implementation.";
+                throw new IllegalStateException(msg);
+            }
+        } else {
+            log.debug("No populated Ini available.  Creating a default instance.");
+            instance = createDefaultInstance();
+            if (instance == null) {
+                String msg = getClass().getName() + " implementation did not return a default instance in " +
+                        "the event of a null/empty Ini configuration.  This is required to support the " +
+                        "Factory interface.  Please check your implementation.";
+                throw new IllegalStateException(msg);
+            }
+        }
+
+        return instance;
+    }
+
+    protected abstract T createInstance(Ini ini);
+
+    protected abstract T createDefaultInstance();
+}

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java Sun Nov  1 00:05:33 2009
@@ -18,7 +18,6 @@
  */
 package org.apache.shiro.config;
 
-import org.apache.shiro.io.ResourceUtils;
 import org.apache.shiro.mgt.DefaultSecurityManager;
 import org.apache.shiro.mgt.RealmSecurityManager;
 import org.apache.shiro.mgt.SecurityManager;
@@ -33,87 +32,30 @@
 import java.util.*;
 
 /**
- * A {@link Factory} that creates {@link SecurityManager} instances based on
- * {@link Ini} configuration.
+ * A {@link Factory} that creates {@link SecurityManager} instances based on {@link Ini} configuration.
  *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
  * @since 1.0
  */
-public class IniSecurityManagerFactory implements Factory<SecurityManager> {
-
-    public static final String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";
+public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
 
     public static final String MAIN_SECTION_NAME = "main";
 
     private static transient final Logger log = LoggerFactory.getLogger(IniSecurityManagerFactory.class);
 
-    private Ini ini;
-
     /**
      * Creates a new instance.  See the {@link #createInstance()} JavaDoc for detailed explaination of how an INI
      * source will be resolved to use to build the instance.
      */
     public IniSecurityManagerFactory() {
+        super();
     }
 
     public IniSecurityManagerFactory(Ini config) {
-        this.ini = config;
-    }
-
-    public Ini getIni() {
-        return ini;
+        super(config);
     }
 
-    public void setIni(Ini ini) {
-        this.ini = ini;
-    }
-
-    private static boolean isEmpty(Ini ini) {
-        return ini == null || ini.isEmpty();
-    }
-
-    /**
-     * Creates a new {@code SecurityManager} instance by using a configured INI source.  This implementation
-     * functions as follows:
-     * <ol>
-     * <li>The {@code Ini} instance available via the {@link #getIni()} method will be used if available.</li>
-     * <li>If {@link #getIni()} is {@code null} empty, this implementation will attempt to find and load a
-     * {@code shiro.ini} file at the root of the classpath (i.e. {@code classpath:shiro.ini}) and use the resulting
-     * {@link Ini} instance constructed based on that file.</li>
-     * <li>If neither of the above two mechanisms result in an {@code Ini} instance, a simple default
-     * {@code SecurityManager} instance is returned via the
-     * {@link #createDefaultSecurityManager()} method.</li>
-     * </ol>
-     *
-     * @return a new {@code SecurityManager} instance by using a configured INI source.
-     */
-    public SecurityManager createInstance() {
-        Ini ini = getIni();
-        if (isEmpty(ini)) {
-            log.debug("Null or empty Ini.  Falling back to classpath:/shiro.ini");
-            if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) {
-                log.debug("Found shiro.ini at the root of the classpath.");
-                ini = new Ini();
-                ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH);
-                if (isEmpty(ini)) {
-                    log.warn("shiro.ini found at the root of the classpath, but it did not contain any data.");
-                }
-            }
-        }
-
-        SecurityManager securityManager;
-
-        if (!isEmpty(ini)) {
-            log.debug("Creating SecurityManager from Ini instance.");
-            securityManager = createSecurityManager(ini);
-        } else {
-            log.debug("No populated Ini instance available.  Creating a default SecurityManager instance.");
-            securityManager = createDefaultSecurityManager();
-        }
-
-        return securityManager;
-    }
-
-    protected final SecurityManager createSecurityManager(Ini ini) {
+    protected SecurityManager createInstance(Ini ini) {
         if (isEmpty(ini)) {
             throw new NullPointerException("Ini argument cannot be null or empty.");
         }
@@ -125,11 +67,7 @@
         return securityManager;
     }
 
-    protected SecurityManager createDefaultSecurityManager() {
-        return newSecurityManagerInstance();
-    }
-
-    protected RealmSecurityManager newSecurityManagerInstance() {
+    protected SecurityManager createDefaultInstance() {
         return new DefaultSecurityManager();
     }
 
@@ -145,7 +83,7 @@
                 log.info("No main/default section was found in INI resource [" + ini + "].  A simple default " +
                         "SecurityManager instance will be created automatically.");
             }
-            securityManager = createDefaultSecurityManager();
+            securityManager = createDefaultInstance();
         } else {
             securityManager = createSecurityManager(mainSection);
         }
@@ -157,7 +95,7 @@
 
         Map<String, Object> defaults = new LinkedHashMap<String, Object>();
 
-        SecurityManager securityManager = createDefaultSecurityManager();
+        SecurityManager securityManager = createDefaultInstance();
         defaults.put("securityManager", securityManager);
 
         ReflectionBuilder builder = new ReflectionBuilder(defaults);
@@ -188,6 +126,7 @@
                     try {
                         builder.applyProperty(realm, "name", name);
                     } catch (Exception ignored) {
+                        log.debug("Unable to apply 'name' property value {} to realm {}.", name, realm);
                     }
                 }
                 realms.add(realm);

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/ResourceConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/ResourceConfiguration.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/ResourceConfiguration.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/ResourceConfiguration.java Sun Nov  1 00:05:33 2009
@@ -18,17 +18,23 @@
  */
 package org.apache.shiro.config;
 
+import org.apache.shiro.mgt.SecurityManager;
+
 import java.io.InputStream;
 import java.io.Serializable;
 
-import org.apache.shiro.mgt.SecurityManager;
-
 
 /**
- * //TODO - complete JavaDoc
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
+ *
  * @author Les Hazlewood
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public abstract class ResourceConfiguration implements Configuration, Serializable {
 
     protected transient org.apache.shiro.mgt.SecurityManager securityManager;

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/TextConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/TextConfiguration.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/TextConfiguration.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/TextConfiguration.java Sun Nov  1 00:05:33 2009
@@ -31,11 +31,16 @@
 
 
 /**
- * //TODO - complete JavaDoc
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @author Les Hazlewood
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public abstract class TextConfiguration extends ResourceConfiguration implements Initializable {
 
     private static final Logger log = LoggerFactory.getLogger(TextConfiguration.class);

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/AbstractHash.java Sun Nov  1 00:05:33 2009
@@ -285,4 +285,69 @@
     public int hashCode() {
         return toHex().hashCode();
     }
+
+    private static void printMainUsage(Class<? extends AbstractHash> clazz, String type) {
+        System.out.println("Prints an " + type + " hash value.");
+        System.out.println("Usage: java " + clazz.getName() + " [-base64] [-salt <saltValue>] [-times <N>] <valueToHash>");
+        System.out.println("Options:");
+        System.out.println("\t-base64\t\tPrints the hash value as a base64 String instead of the default hex.");
+        System.out.println("\t-salt\t\tSalts the hash with the specified <saltValue>");
+        System.out.println("\t-times\t\tHashes the input <N> number of times");
+    }
+
+    private static boolean isReserved(String arg) {
+        return "-base64".equals(arg) || "-times".equals(arg) || "-salt".equals(arg);
+    }
+
+    static int doMain(Class<? extends AbstractHash> clazz, String[] args) {
+        String simple = clazz.getSimpleName();
+        int index = simple.indexOf("Hash");
+        String type = simple.substring(0, index).toUpperCase();
+
+        if (args == null || args.length < 1 || args.length > 7) {
+            printMainUsage(clazz, type);
+            return -1;
+        }
+        boolean hex = true;
+        String salt = null;
+        int times = 1;
+        String text = args[args.length - 1];
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.equals("-base64")) {
+                hex = false;
+            } else if (arg.equals("-salt")) {
+                if ((i + 1) >= (args.length - 1)) {
+                    String msg = "Salt argument must be followed by a salt value.  The final argument is " +
+                            "reserved for the value to hash.";
+                    System.out.println(msg);
+                    printMainUsage(clazz, type);
+                    return -1;
+                }
+                salt = args[i + 1];
+            } else if (arg.equals("-times")) {
+                if ((i + 1) >= (args.length - 1)) {
+                    String msg = "Times argument must be followed by an integer value.  The final argument is " +
+                            "reserved for the value to hash";
+                    System.out.println(msg);
+                    printMainUsage(clazz, type);
+                    return -1;
+                }
+                try {
+                    times = Integer.valueOf(args[i + 1]);
+                } catch (NumberFormatException e) {
+                    String msg = "Times argument must be followed by an integer value.";
+                    System.out.println(msg);
+                    printMainUsage(clazz, type);
+                    return -1;
+                }
+            }
+        }
+
+        Hash hash = new Md2Hash(text, salt, times);
+        String hashed = hex ? hash.toHex() : hash.toBase64();
+        System.out.print(hex ? "Hex: " : "Base64: ");
+        System.out.println(hashed);
+        return 0;
+    }
 }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Md2Hash.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Md2Hash.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Md2Hash.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/crypto/hash/Md2Hash.java Sun Nov  1 00:05:33 2009
@@ -25,8 +25,8 @@
 /**
  * Generates an MD2 Hash (RFC 1319) from a given input <tt>source</tt> with an optional <tt>salt</tt> and
  * hash iterations.
- *
- * <p>See the {@link AbstractHash AbstractHash} parent class JavaDoc for a detailed explanation of Hashing
+ * <p/>
+ * See the {@link AbstractHash AbstractHash} parent class JavaDoc for a detailed explanation of Hashing
  * techniques and how the overloaded constructors function.
  *
  * @author Les Hazlewood

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/AbstractResource.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/AbstractResource.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/AbstractResource.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/AbstractResource.java Sun Nov  1 00:05:33 2009
@@ -23,10 +23,14 @@
 import java.io.Serializable;
 
 /**
- * //TODO - complete JavaDoc
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @author Les Hazlewood
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
 public abstract class AbstractResource implements Serializable {
 

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/IniResource.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/IniResource.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/IniResource.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/IniResource.java Sun Nov  1 00:05:33 2009
@@ -18,6 +18,11 @@
  */
 package org.apache.shiro.io;
 
+import static org.apache.shiro.util.StringUtils.clean;
+import static org.apache.shiro.util.StringUtils.splitKeyValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.InputStream;
 import java.io.Reader;
 import java.text.ParseException;
@@ -25,18 +30,17 @@
 import java.util.Map;
 import java.util.Scanner;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.shiro.util.StringUtils.clean;
-import static org.apache.shiro.util.StringUtils.splitKeyValue;
-
 /**
- * //TODO - complete JavaDoc
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @author Les Hazlewood
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public class IniResource extends TextResource {
 
     private static final Logger log = LoggerFactory.getLogger(IniResource.class);

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/ResourceException.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/ResourceException.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/ResourceException.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/ResourceException.java Sun Nov  1 00:05:33 2009
@@ -23,12 +23,18 @@
 
 /**
  * Root exception when a problem occurs acquiring or processing a resource.
+ * <p/>
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @author Les Hazlewood
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
-public class ResourceException extends ShiroException
-{
+@Deprecated
+public class ResourceException extends ShiroException {
 
     /**
      * Creates a new ResourceException.

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/TextResource.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/TextResource.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/TextResource.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/io/TextResource.java Sun Nov  1 00:05:33 2009
@@ -18,21 +18,23 @@
  */
 package org.apache.shiro.io;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.Scanner;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.*;
+import java.util.Scanner;
+
 /**
- * //TODO complete JavaDoc
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
+ *
  * @author Les Hazlewood
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public abstract class TextResource extends AbstractResource {
 
     private static final Logger log = LoggerFactory.getLogger(TextResource.class);
@@ -78,7 +80,7 @@
         try {
             super.load(resourcePath);
         } catch (Exception e) {
-            String msg = "Unable to load text resource from the resource path [" + resourcePath +"]";
+            String msg = "Unable to load text resource from the resource path [" + resourcePath + "]";
             throw new ResourceException(msg, e);
         }
     }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java Sun Nov  1 00:05:33 2009
@@ -307,6 +307,7 @@
             throw ae; //propagate
         }
         Subject replaced = createSubject(token, info, subject);
+        //TODO - is binding necessary anymore?  Shouldn't the Builders or Builder callers do this now?
         bind(replaced);
         return replaced;
     }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManagerFactory.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManagerFactory.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManagerFactory.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManagerFactory.java Sun Nov  1 00:05:33 2009
@@ -22,11 +22,15 @@
  * Allows implementations to create and return an application's SecurityManager instance in any manner necessary.
  *
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
  */
+@Deprecated
 public interface SecurityManagerFactory {
 
     /**
      * Returns a fully configured and initialized <code>SecurityManager</code>.
+     *
      * @return a fully configured and initialized <code>SecurityManager</code>.
      */
     SecurityManager getSecurityManager();

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java Sun Nov  1 00:05:33 2009
@@ -53,10 +53,6 @@
  * <li>The <code>Subject</code> instance wold be 'unbound' from the application/thread and garbage collected at the
  * end of request/thread execution, and a new one is created on the next request/method invocation as per step #1.</li>
  * </ol>
- * <p/>
- * Indeed this is exactly how Shiro's default behavior works in enterprise server and web-based environments.  It is
- * enabled in the <code>ShiroFilter</code> for web-based environments as well as remote-method-invocation-based
- * components for non-web environments.
  *
  * @author Les Hazlewood
  * @since 1.0

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java Sun Nov  1 00:05:33 2009
@@ -18,6 +18,9 @@
  */
 package org.apache.shiro.subject;
 
+import org.apache.shiro.util.CollectionUtils;
+import org.apache.shiro.util.StringUtils;
+
 import java.util.*;
 
 
@@ -35,6 +38,8 @@
 
     private Map<String, Set> realmPrincipals;
 
+    private String cachedToString; //cached toString() result, as this can be printed many times in logging
+
     public SimplePrincipalCollection() {
     }
 
@@ -89,6 +94,7 @@
         if (principal == null) {
             throw new IllegalArgumentException("principal argument cannot be null.");
         }
+        this.cachedToString = null;
         getPrincipalsLazy(realmName).add(principal);
     }
 
@@ -102,6 +108,7 @@
         if (principals.isEmpty()) {
             throw new IllegalArgumentException("principals argument cannot be an empty collection.");
         }
+        this.cachedToString = null;
         getPrincipalsLazy(realmName).addAll(principals);
     }
 
@@ -196,6 +203,7 @@
     }
 
     public void clear() {
+        this.cachedToString = null;
         if (realmPrincipals != null) {
             realmPrincipals.clear();
             realmPrincipals = null;
@@ -223,4 +231,22 @@
         }
         return super.hashCode();
     }
+
+    /**
+     * Returns a simple string representation suitable for printing.
+     *
+     * @return a simple string representation suitable for printing.
+     * @since 1.0
+     */
+    public String toString() {
+        if (this.cachedToString == null) {
+            Set<Object> principals = asSet();
+            if (!CollectionUtils.isEmpty(principals)) {
+                this.cachedToString = StringUtils.toString(principals.toArray());
+            } else {
+                this.cachedToString = "empty";
+            }
+        }
+        return this.cachedToString;
+    }
 }

Modified: incubator/shiro/trunk/samples/web/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/samples/web/src/main/webapp/WEB-INF/web.xml?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/samples/web/src/main/webapp/WEB-INF/web.xml (original)
+++ incubator/shiro/trunk/samples/web/src/main/webapp/WEB-INF/web.xml Sun Nov  1 00:05:33 2009
@@ -24,18 +24,16 @@
 
     <filter>
         <filter-name>ShiroFilter</filter-name>
-        <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
+        <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
         <init-param>
             <param-name>config</param-name>
             <param-value>
 
-                # The ShiroFilter configuration is very powerful and flexible, while still remaining succinct.
-                # Please read the comprehensive example, with full comments and explanations, in the JavaDoc:
-                #
-                # http://shiro.apache.org/api/org/apache/shiro/web/servlet/ShiroFilter.html
+                # The IniShiroFilter configuration is very powerful and flexible, while still remaining succinct.
+                # Please read the comprehensive example, with full comments and explanations, in the
+                # org.apache.shiro.web.servlet.IniShiroFilter JavaDoc
 
                 [main]
-
                 demoRealm = org.apache.shiro.realm.text.PropertiesRealm
 
                 [filters]

Modified: incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringIniWebConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringIniWebConfiguration.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringIniWebConfiguration.java (original)
+++ incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringIniWebConfiguration.java Sun Nov  1 00:05:33 2009
@@ -59,11 +59,17 @@
  * <li>If none of the above, throw an exception that explains the options.</li>
  * <ol>
  * </p>
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @author Jeremy Haile
  * @see IniWebConfiguration
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public class SpringIniWebConfiguration extends IniWebConfiguration {
 
     //TODO - complete JavaDoc

Modified: incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringShiroFilter.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringShiroFilter.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringShiroFilter.java (original)
+++ incubator/shiro/trunk/support/spring/src/main/java/org/apache/shiro/spring/SpringShiroFilter.java Sun Nov  1 00:05:33 2009
@@ -39,16 +39,17 @@
  *     ... normal .ini config ...
  *     &lt;param-value&gt;
  * &lt;/init-param&gt;
-&lt;filter&gt;</pre>
+ * &lt;filter&gt;</pre>
  * <p/>
  * That is, you don't have to specify the additional <code>configClassName</code> <code>init-param</code>.
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
  * @since 0.2
+ * @deprecated Will be removed before 1.0 final!
  */
-public class SpringShiroFilter extends ShiroFilter
-{
+@Deprecated
+public class SpringShiroFilter extends ShiroFilter {
 
     //TODO - complete JavaDoc
 

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java Sun Nov  1 00:05:33 2009
@@ -61,7 +61,7 @@
      * Message displayed when a servlet request or response is not bound to the current thread context when expected.
      */
     private static final String NOT_BOUND_ERROR_MESSAGE =
-            "Make sure WebUtils.bind() is being called. (typically called by ShiroFilter)  " +
+            "Make sure WebUtils.bind() is being called. (typically called by AbstractShiroFilter)  " +
                     "This could also happen when running integration tests that don't properly call WebUtils.bind().";
 
     public static final String SERVLET_REQUEST_KEY = ServletRequest.class.getName() + "_SHIRO_THREAD_CONTEXT_KEY";

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java?rev=831623&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java Sun Nov  1 00:05:33 2009
@@ -0,0 +1,163 @@
+/*
+ * 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.config;
+
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.config.IniFactorySupport;
+import org.apache.shiro.config.ReflectionBuilder;
+import org.apache.shiro.util.CollectionUtils;
+import org.apache.shiro.util.Factory;
+import org.apache.shiro.web.filter.mgt.FilterChainManager;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import java.util.Map;
+
+/**
+ * A {@link Factory} that creates {@link FilterChainResolver} instances based on {@link Ini} configuration.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public class IniFilterChainResolverFactory extends IniFactorySupport<FilterChainResolver> {
+
+    public static final String FILTERS = "filters";
+    public static final String URLS = "urls";
+
+    private static transient final Logger log = LoggerFactory.getLogger(IniFilterChainResolverFactory.class);
+
+    private FilterConfig filterConfig;
+
+    public IniFilterChainResolverFactory() {
+        super();
+    }
+
+    public IniFilterChainResolverFactory(Ini ini) {
+        super(ini);
+    }
+
+    public FilterConfig getFilterConfig() {
+        return filterConfig;
+    }
+
+    public void setFilterConfig(FilterConfig filterConfig) {
+        this.filterConfig = filterConfig;
+    }
+
+    protected FilterChainResolver createInstance(Ini ini) {
+        FilterChainResolver filterChainResolver = createDefaultInstance();
+        if (filterChainResolver instanceof PathMatchingFilterChainResolver) {
+            PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver) filterChainResolver;
+            FilterChainManager manager = resolver.getFilterChainManager();
+            buildChains(manager, ini);
+        }
+        return filterChainResolver;
+    }
+
+    protected FilterChainResolver createDefaultInstance() {
+        FilterConfig filterConfig = getFilterConfig();
+        if (filterConfig != null) {
+            return new PathMatchingFilterChainResolver(filterConfig);
+        } else {
+            return new PathMatchingFilterChainResolver();
+        }
+    }
+
+    protected void buildChains(FilterChainManager manager, Ini ini) {
+        //filters section:
+        Ini.Section section = ini.getSection(FILTERS);
+        Map<String, Filter> filters = getFilters(section, manager.getFilters());
+
+        //add the filters to the manager:
+        registerFilters(filters, manager);
+
+        //urls section:
+        section = ini.getSection(URLS);
+        createChains(section, manager);
+    }
+
+    protected void registerFilters(Map<String, Filter> filters, FilterChainManager manager) {
+        if (!CollectionUtils.isEmpty(filters)) {
+            boolean init = getFilterConfig() != null; //only call filter.init if there is a FilterConfig available
+            for (Map.Entry<String, Filter> entry : filters.entrySet()) {
+                String name = entry.getKey();
+                Filter filter = entry.getValue();
+                manager.addFilter(name, filter, init);
+            }
+        }
+    }
+
+    @SuppressWarnings({"unchecked"})
+    protected Map<String, Filter> getFilters(Map<String, String> section, Map<String, Filter> defaultFilters) {
+
+        Map<String, Filter> filters = defaultFilters;
+
+        if (!CollectionUtils.isEmpty(section)) {
+            ReflectionBuilder builder = new ReflectionBuilder(defaultFilters);
+            Map<String, ?> built = builder.buildObjects(section);
+            assertFilters(built);
+            filters = (Map<String, Filter>) built;
+        }
+
+        return filters;
+    }
+
+    protected void assertFilters(Map<String, ?> map) {
+        if (!CollectionUtils.isEmpty(map)) {
+            for (Map.Entry<String, ?> entry : map.entrySet()) {
+                String key = entry.getKey();
+                Object value = entry.getValue();
+                assertFilter(key, value);
+            }
+        }
+    }
+
+    protected void assertFilter(String name, Object o) throws ConfigurationException {
+        if (!(o instanceof Filter)) {
+            String msg = "[" + FILTERS + "] section specified a filter named '" + name + "', which does not " +
+                    "implement the " + Filter.class.getName() + " interface.  Only Filter implementations may be " +
+                    "defined.";
+            throw new ConfigurationException(msg);
+        }
+    }
+
+    protected void createChains(Map<String, String> urls, FilterChainManager manager) {
+        if (CollectionUtils.isEmpty(urls)) {
+            if (log.isDebugEnabled()) {
+                log.debug("No urls to process.");
+            }
+            return;
+        }
+
+        if (log.isTraceEnabled()) {
+            log.trace("Before url processing.");
+        }
+
+        for (Map.Entry<String, String> entry : urls.entrySet()) {
+            String path = entry.getKey();
+            String value = entry.getValue();
+            manager.createChain(path, value);
+        }
+    }
+}

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniWebConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniWebConfiguration.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniWebConfiguration.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/IniWebConfiguration.java Sun Nov  1 00:05:33 2009
@@ -39,10 +39,17 @@
 /**
  * A <code>WebConfiguration</code> that supports configuration via the
  * <a href="http://en.wikipedia.org/wiki/INI_file">.ini format</a>.
+ * <p/>
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @author Les Hazlewood
  * @since Jun 1, 2008 11:02:44 PM
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public class IniWebConfiguration extends IniConfiguration implements WebConfiguration {
 
     //TODO - complete JavaDoc

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=831623&r1=831622&r2=831623&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 Sun Nov  1 00:05:33 2009
@@ -31,9 +31,16 @@
  * 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.
+ * <p/>
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @since 0.9
+ * @deprecated use {@link org.apache.shiro.util.Factory} implementations to generate the Shiro
+ *             components. See {@link org.apache.shiro.config.IniSecurityManagerFactory} as an example.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public interface WebConfiguration extends Configuration {
 
     /**

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebIniSecurityManagerFactory.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebIniSecurityManagerFactory.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebIniSecurityManagerFactory.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/config/WebIniSecurityManagerFactory.java Sun Nov  1 00:05:33 2009
@@ -20,13 +20,14 @@
 
 import org.apache.shiro.config.Ini;
 import org.apache.shiro.config.IniSecurityManagerFactory;
-import org.apache.shiro.mgt.RealmSecurityManager;
+import org.apache.shiro.mgt.SecurityManager;
 import org.apache.shiro.web.DefaultWebSecurityManager;
 
 /**
- * Differs from the parent class only in the {@link #newSecurityManagerInstance()} method, to
+ * Differs from the parent class only in the {@link #createDefaultInstance()} method, to
  * ensure a web-capable {@code SecurityManager} instance is created by default.
  *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
  * @since 1.0
  */
 public class WebIniSecurityManagerFactory extends IniSecurityManagerFactory {
@@ -57,7 +58,7 @@
      * @return a new web-capable {@code SecurityManager} instance.
      */
     @Override
-    protected RealmSecurityManager newSecurityManagerInstance() {
+    protected SecurityManager createDefaultInstance() {
         return new DefaultWebSecurityManager();
     }
 }

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/AnonymousFilter.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/AnonymousFilter.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/AnonymousFilter.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/AnonymousFilter.java Sun Nov  1 00:05:33 2009
@@ -32,7 +32,7 @@
  * For example, if you had a user-only section of a website, you might want to require that access to
  * any url in that section must be from an authenticated user.
  * <p/>
- * Here is how that would look in the ShiroFilter configuration:
+ * Here is how that would look in the IniShiroFilter configuration:
  * <p/>
  * <code>[urls]<br/>
  * /user/** = authc</code>
@@ -59,7 +59,7 @@
      * @return <code>true</code> always, allowing unchecked access to the underlying path or resource.
      */
     @Override
-    public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
+    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
         // Always return true since we allow access to anyone
         return true;
     }

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainResolver.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainResolver.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainResolver.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainResolver.java Sun Nov  1 00:05:33 2009
@@ -45,7 +45,7 @@
      *
      * @param request       the incoming ServletRequest
      * @param response      the outgoing ServletResponse
-     * @param originalChain the original {@code FilterChain} intercepted by the ShiroFilter.
+     * @param originalChain the original {@code FilterChain} intercepted by the ShiroFilter implementation.
      * @return the filter chain that should be executed for the given request, or {@code null} if the
      *         original chain should be used.
      */

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/IniShiroFilter.java Sun Nov  1 00:05:33 2009
@@ -19,18 +19,15 @@
 package org.apache.shiro.web.servlet;
 
 import org.apache.shiro.config.Ini;
-import org.apache.shiro.config.IniSecurityManagerFactory;
-import org.apache.shiro.io.IniResource;
-import org.apache.shiro.io.ResourceUtils;
+import org.apache.shiro.config.IniFactorySupport;
 import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.util.Factory;
+import org.apache.shiro.web.config.IniFilterChainResolverFactory;
 import org.apache.shiro.web.config.WebIniSecurityManagerFactory;
 import org.apache.shiro.web.filter.mgt.FilterChainResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.io.InputStream;
-
 /**
  * Main Servlet Filter that configures and enables all Shiro functions within a web application by using the
  * <a href="http://en.wikipedia.org/wiki/INI_file">INI</a> configuration format.
@@ -213,7 +210,7 @@
 public class IniShiroFilter extends AbstractShiroFilter {
 
     public static final String CONFIG_INIT_PARAM_NAME = "config";
-    public static final String CONFIG_URL_INIT_PARAM_NAME = "configPath";
+    public static final String CONFIG_PATH_INIT_PARAM_NAME = "configPath";
 
     private static final Logger log = LoggerFactory.getLogger(IniShiroFilter.class);
 
@@ -296,32 +293,81 @@
         if (config != null) {
             setConfig(config);
         }
-        String configPath = getInitParam(CONFIG_URL_INIT_PARAM_NAME);
+        String configPath = getInitParam(CONFIG_PATH_INIT_PARAM_NAME);
         if (configPath != null) {
             setConfigPath(configPath);
         }
-        setConfigPath(configPath);
     }
 
     protected void configure() throws Exception {
+        Ini ini = loadIniFromConfig();
+
+        if (ini == null || ini.isEmpty()) {
+            log.info("Null or empty configuration specified via 'config' init-param.  " +
+                    "Checking path-based configuration.");
+            ini = loadIniFromPath();
+        }
+        if (ini == null || ini.isEmpty()) {
+            log.info("Null or empty configuration specified via '" + CONFIG_INIT_PARAM_NAME + "' or '" +
+                    CONFIG_PATH_INIT_PARAM_NAME + "' filter parameters.  Trying the default " +
+                    IniFactorySupport.DEFAULT_INI_RESOURCE_PATH + " file.");
+            ini = IniFactorySupport.loadDefaultClassPathIni();
+        }
+
+        applySecurityManager(ini);
+        applyFilterChainResolver(ini);
+    }
+
+    protected Ini loadIniFromConfig() {
         Ini ini = null;
         String config = getConfig();
         if (config != null) {
             ini = convertConfigToIni(config);
         }
-        if (ini == null) {
-            log.debug("No configuration specified via 'config' init-param.  Checking path-based configuration.");
-            String path = getConfigPath();
-            if (path != null) {
-                ini = convertPathToIni(path);
-            }
+        return ini;
+    }
+
+    protected Ini loadIniFromPath() {
+        Ini ini = null;
+        String path = getConfigPath();
+        if (path != null) {
+            ini = convertPathToIni(path);
         }
+        return ini;
+    }
 
-        IniSecurityManagerFactory factory = new WebIniSecurityManagerFactory(ini);
+    protected void applySecurityManager(Ini ini) {
+        Factory<SecurityManager> factory;
+        if (ini == null || ini.isEmpty()) {
+            factory = new WebIniSecurityManagerFactory();
+        } else {
+            factory = new WebIniSecurityManagerFactory(ini);
+        }
         SecurityManager securityManager = factory.createInstance();
         setSecurityManager(securityManager);
     }
 
+    protected void applyFilterChainResolver(Ini ini) {
+        if (ini == null || ini.isEmpty()) {
+            //nothing to use to create the resolver, just return
+            //(the AbstractShiroFilter allows a null resolver, in which case the original FilterChain is
+            // always used).
+            return;
+        }
+
+        //only create a resolver if the 'filters' or 'urls' sections are defined:
+        Ini.Section urls = ini.getSection(IniFilterChainResolverFactory.URLS);
+        Ini.Section filters = ini.getSection(IniFilterChainResolverFactory.FILTERS);
+        if ((urls != null && !urls.isEmpty()) || (filters != null && !filters.isEmpty())) {
+            //either the urls section or the filters section was defined.  Go ahead and create the resolver
+            //and set it:
+            IniFilterChainResolverFactory filterChainResolverFactory = new IniFilterChainResolverFactory(ini);
+            filterChainResolverFactory.setFilterConfig(getFilterConfig());
+            FilterChainResolver resolver = filterChainResolverFactory.createInstance();
+            setFilterChainResolver(resolver);
+        }
+    }
+
     protected Ini convertConfigToIni(String config) {
         Ini ini = new Ini();
         ini.load(config);
@@ -333,9 +379,4 @@
         ini.loadFromPath(path);
         return ini;
     }
-
-    private void configureByUrl(String configUrl) throws IOException {
-        InputStream is = ResourceUtils.getInputStreamForPath(configUrl);
-        IniResource ini = new IniResource(is);
-    }
 }

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java Sun Nov  1 00:05:33 2009
@@ -225,13 +225,18 @@
  * &lt;filter-name&gt;ShiroFilter&lt;/filter-name&gt;
  * &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  * &lt;/filter-mapping&gt;</pre>
+ * <p/>
+ * <p/>
+ * <b>Do not use this! It will be removed prior to 1.0 final!</b>
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
- * @--deprecated use the {@link org.apache.shiro.web.servlet.IniShiroFilter} instead.
  * @see IniShiroFilter
  * @since 0.1
+ * @deprecated use {@link org.apache.shiro.web.servlet.IniShiroFilter} instead.
+ *             <b>Will be removed prior to 1.0 final!</b>
  */
+@Deprecated
 public class ShiroFilter extends OncePerRequestFilter {
 
     //TODO - complete JavaDoc

Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java Sun Nov  1 00:05:33 2009
@@ -25,7 +25,7 @@
 import org.apache.shiro.subject.SimplePrincipalCollection;
 import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
 import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertTrue;
 import org.junit.Test;
 
 import javax.servlet.http.Cookie;
@@ -73,12 +73,14 @@
         //The following base64 string was determined from the log output of the above 'onSuccessfulLogin' test.
         //This will have to change any time the PrincipalCollection implementation changes:
         final String userPCBlowfishBase64 = "UwP13UzjVUceLBNWh+sYM01JWOSbBOwc1ZLySIws0Idnkc" +
-                "WeD/yWeH0eIycwHaI8MRKPyenBr76EoLkEZnXSz4i27cTTUps5qOgU/ZQLdvIOxlZxmT9RlUvK" +
-                "T6zopnQrSpdsCNaruG/Op/XEoJcdNLI9rJCCyMKN3em5wl8GrWTIzKS4hzHombGBEW4EPS9jv4" +
-                "0HV4mIS2sUFXm5MlOptr99e1A6eKYxlLrldk2/yqw29nWohE0sIjO7tRF9mOAZUeC/Fem6K4S8" +
-                "2LbXAJ6p0oNg3MP7dbFSkeeDF2CwFJvvi5xVrGyF0RnTzjwKZdTcvg4bx9ifQpKyPayQgsjCjd" +
-                "3pucJfBq1kuw/IyiPdSREnzWAEXOQi9o9II4jNvOJik+VI3QkwWdBBekzEKCACn8uvjlLKSiR8" +
-                "tCs9vbycs5N0FrODxMQ5FDvhV+rZLHtP/KP1puAwmeo=";
+                "WeD/yWeH0eIycwHaI8MRKPyenBr77dBdt3S7KTKzzt47bdseNbEI7TbTKPY5VfnJLqGVglQr+O" +
+                "mTgH1vpCQ/PAw3XnrQ4FWSXe9/KkfcAfteY5iw7qea1zZJq5jC4dOU3HLlhL7+BtlFMOrSzP2i" +
+                "ijwEZGFoNASMTpLxTpiiTHhVmB9Hf4s7N2rTthK18+uTyJwC1KoK3Fw82Wxl7BZb5aFoc5BoJb" +
+                "lWyZVHV3hEIIIS9/2smrjrCdu0NRC31c/+IelggTG3jTMA1wQ0oq2jTZSjctlcknV90jxNJfbf" +
+                "/Uzk679TmgyrHJgRrQ+kqJ+94rafqFWEcaG82yT3LkQEjE6S8U6Yokx4VZgfR3+Nnhgfb36EfU" +
+                "BXytFPop+38q1ssgLNxj3TPPOMj/QfGHVX6lM6loW8zA3VIEtDyqXN0LAQzqnbC8zqb1CJhXaJ" +
+                "owmdO9LV7XzouBN+l/ER8I";
+
         Cookie[] cookies = new Cookie[]{
                 new Cookie(WebRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCBlowfishBase64)
         };

Added: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebTest.java?rev=831623&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebTest.java (added)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebTest.java Sun Nov  1 00:05:33 2009
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+
+/**
+ * @since 1.0
+ */
+public abstract class WebTest {
+
+    protected FilterConfig createNiceMockFilterConfig() {
+        FilterConfig mock = createNiceMock(FilterConfig.class);
+        ServletContext mockServletContext = createNiceMock(ServletContext.class);
+        expect(mock.getServletContext()).andReturn(mockServletContext);
+        return mock;
+    }
+
+
+}

Added: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java?rev=831623&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java (added)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java Sun Nov  1 00:05:33 2009
@@ -0,0 +1,116 @@
+/*
+ * 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.config;
+
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.web.WebTest;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import java.util.Map;
+
+/**
+ * Tests for the {@link IniFilterChainResolverFactory}.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public class IniFilterChainResolverFactoryTest extends WebTest {
+
+    private IniFilterChainResolverFactory factory;
+
+    @Before
+    public void setUp() {
+        this.factory = new IniFilterChainResolverFactory();
+    }
+
+    @Test
+    public void testNewInstance() {
+        assertNull(factory.getFilterConfig());
+        factory.setFilterConfig(null);
+        assertNull(factory.getFilterConfig());
+    }
+
+    @Test
+    public void testCreateInstanceNoIni() {
+        FilterChainResolver resolver = factory.createInstance();
+        assertNotNull(resolver);
+    }
+
+    @Test
+    public void testNewInstanceWithIni() {
+        Ini ini = new Ini();
+        String config =
+                "[urls]\n" +
+                        "/index.html = anon";
+        ini.load(config);
+        factory = new IniFilterChainResolverFactory(ini);
+        FilterChainResolver resolver = factory.createInstance();
+        assertNotNull(resolver);
+    }
+
+    @Test
+    public void testGetFiltersWithNullOrEmptySection() {
+        Map<String, Filter> filters = factory.getFilters(null, null);
+        assertNull(filters);
+    }
+
+    @Test
+    public void testCreateChainsWithNullUrlsSection() {
+        //should do nothing (return immediately, no exceptions):
+        factory.createChains(null, null);
+    }
+
+    @Test(expected = ConfigurationException.class)
+    public void testNewInstanceWithNonFilter() {
+        Ini ini = new Ini();
+        String config =
+                "[filters]\n" +
+                        "test = org.apache.shiro.web.attr.CookieAttribute\n" + //any non-Filter will do
+                        "[urls]\n" +
+                        "/index.html = anon";
+        ini.load(config);
+        factory = new IniFilterChainResolverFactory(ini);
+        factory.createInstance();
+    }
+
+    @Test
+    public void testNewInstanceWithFilterConfig() {
+        Ini ini = new Ini();
+        String text =
+                "[urls]\n" +
+                        "/index.html = anon";
+        ini.load(text);
+        factory = new IniFilterChainResolverFactory(ini);
+        FilterConfig config = createNiceMockFilterConfig();
+        factory.setFilterConfig(config);
+        replay(config);
+        FilterChainResolver resolver = factory.createInstance();
+        assertNotNull(resolver);
+        verify(config);
+    }
+}

Added: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/authc/AnonymousFilterTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/authc/AnonymousFilterTest.java?rev=831623&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/authc/AnonymousFilterTest.java (added)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/authc/AnonymousFilterTest.java Sun Nov  1 00:05:33 2009
@@ -0,0 +1,38 @@
+/*
+ * 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.authc;
+
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+/**
+ * Test for {@link org.apache.shiro.web.filter.authc.AnonymousFilter}.
+ *
+ * @since 1.0
+ */
+public class AnonymousFilterTest {
+
+    @Test
+    public void test() {
+        AnonymousFilter filter = new AnonymousFilter();
+        boolean allow = filter.onPreHandle(null, null, null);
+        assertTrue(allow);
+    }
+
+}

Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManagerTest.java?rev=831623&r1=831622&r2=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManagerTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManagerTest.java Sun Nov  1 00:05:33 2009
@@ -20,7 +20,7 @@
 
 import org.apache.shiro.config.ConfigurationException;
 import org.apache.shiro.web.filter.authz.SslFilter;
-import org.apache.shiro.web.servlet.ShiroFilter;
+import org.apache.shiro.web.servlet.IniShiroFilter;
 import static org.easymock.EasyMock.*;
 import static org.junit.Assert.*;
 import org.junit.Before;
@@ -185,7 +185,7 @@
         replay(mockFilterConfig);
         this.manager = new DefaultFilterChainManager(mockFilterConfig);
 
-        manager.addFilter("nonPathProcessor", new ShiroFilter());
+        manager.addFilter("nonPathProcessor", new IniShiroFilter());
         manager.createChain("test", "nonPathProcessor");
 
         try {

Added: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolverTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolverTest.java?rev=831623&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolverTest.java (added)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolverTest.java Sun Nov  1 00:05:33 2009
@@ -0,0 +1,127 @@
+/*
+ * 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.mgt;
+
+import org.apache.shiro.util.AntPathMatcher;
+import org.apache.shiro.web.WebTest;
+import org.apache.shiro.web.WebUtils;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Tests for {@link org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver}.
+ *
+ * @since 1.0
+ */
+public class PathMatchingFilterChainResolverTest extends WebTest {
+
+    private PathMatchingFilterChainResolver resolver;
+
+    @Before
+    public void setUp() {
+        resolver = new PathMatchingFilterChainResolver();
+    }
+
+    @Test
+    public void testNewInstance() {
+        assertNotNull(resolver.getPathMatcher());
+        assertTrue(resolver.getPathMatcher() instanceof AntPathMatcher);
+        assertNotNull(resolver.getFilterChainManager());
+        assertTrue(resolver.getFilterChainManager() instanceof DefaultFilterChainManager);
+    }
+
+    @Test
+    public void testNewInstanceWithFilterConfig() {
+        FilterConfig mock = createNiceMockFilterConfig();
+        replay(mock);
+        resolver = new PathMatchingFilterChainResolver(mock);
+        assertNotNull(resolver.getPathMatcher());
+        assertTrue(resolver.getPathMatcher() instanceof AntPathMatcher);
+        assertNotNull(resolver.getFilterChainManager());
+        assertTrue(resolver.getFilterChainManager() instanceof DefaultFilterChainManager);
+        assertEquals(((DefaultFilterChainManager) resolver.getFilterChainManager()).getFilterConfig(), mock);
+        verify(mock);
+    }
+
+    @Test
+    public void testSetters() {
+        resolver.setPathMatcher(new AntPathMatcher());
+        assertNotNull(resolver.getPathMatcher());
+        assertTrue(resolver.getPathMatcher() instanceof AntPathMatcher);
+        resolver.setFilterChainManager(new DefaultFilterChainManager());
+        assertNotNull(resolver.getFilterChainManager());
+        assertTrue(resolver.getFilterChainManager() instanceof DefaultFilterChainManager);
+    }
+
+    @Test
+    public void testGetChainsWithoutChains() {
+        ServletRequest request = createNiceMock(HttpServletRequest.class);
+        ServletResponse response = createNiceMock(HttpServletResponse.class);
+        FilterChain chain = createNiceMock(FilterChain.class);
+        FilterChain resolved = resolver.getChain(request, response, chain);
+        assertNull(resolved);
+    }
+
+    @Test
+    public void testGetChainsWithMatch() {
+        HttpServletRequest request = createNiceMock(HttpServletRequest.class);
+        HttpServletResponse response = createNiceMock(HttpServletResponse.class);
+        FilterChain chain = createNiceMock(FilterChain.class);
+
+        //ensure at least one chain is defined:
+        resolver.getFilterChainManager().addToChain("/index.html", "authcBasic");
+
+        expect(request.getAttribute(WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE)).andReturn(null).anyTimes();
+        expect(request.getContextPath()).andReturn("");
+        expect(request.getRequestURI()).andReturn("/index.html");
+        replay(request);
+
+        FilterChain resolved = resolver.getChain(request, response, chain);
+        assertNotNull(resolved);
+        verify(request);
+    }
+
+    @Test
+    public void testGetChainsWithoutMatch() {
+        HttpServletRequest request = createNiceMock(HttpServletRequest.class);
+        HttpServletResponse response = createNiceMock(HttpServletResponse.class);
+        FilterChain chain = createNiceMock(FilterChain.class);
+
+        //ensure at least one chain is defined:
+        resolver.getFilterChainManager().addToChain("/index.html", "authcBasic");
+
+        expect(request.getAttribute(WebUtils.INCLUDE_CONTEXT_PATH_ATTRIBUTE)).andReturn(null).anyTimes();
+        expect(request.getContextPath()).andReturn("");
+        expect(request.getRequestURI()).andReturn("/");
+        replay(request);
+
+        FilterChain resolved = resolver.getChain(request, response, chain);
+        assertNull(resolved);
+        verify(request);
+    }
+}

Copied: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/IniShiroFilterTest.java (from r831582, incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java)
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/IniShiroFilterTest.java?p2=incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/IniShiroFilterTest.java&p1=incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java&r1=831582&r2=831623&rev=831623&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/IniShiroFilterTest.java Sun Nov  1 00:05:33 2009
@@ -26,13 +26,15 @@
 
 
 /**
+ * Tests for {@link IniShiroFilter}.
+ *
  * @author Les Hazlewood
  * @since 0.9
  */
-public class ShiroFilterTest {
+public class IniShiroFilterTest {
 
     @SuppressWarnings({"FieldCanBeLocal"})
-    private ShiroFilter filter;
+    private IniShiroFilter filter;
     private FilterConfig mockFilterConfig;
     private ServletContext mockServletContext;
 
@@ -41,9 +43,17 @@
         mockServletContext = createMock(ServletContext.class);
 
         expect(mockFilterConfig.getServletContext()).andReturn(mockServletContext).anyTimes();
-        expect(mockFilterConfig.getInitParameter(ShiroFilter.CONFIG_CLASS_NAME_INIT_PARAM_NAME)).andReturn(null).once();
-        expect(mockFilterConfig.getInitParameter(ShiroFilter.CONFIG_INIT_PARAM_NAME)).andReturn(config).once();
-        expect(mockFilterConfig.getInitParameter(ShiroFilter.CONFIG_URL_INIT_PARAM_NAME)).andReturn(null).once();
+        expect(mockFilterConfig.getInitParameter(IniShiroFilter.CONFIG_INIT_PARAM_NAME)).andReturn(config).once();
+        expect(mockFilterConfig.getInitParameter(IniShiroFilter.CONFIG_PATH_INIT_PARAM_NAME)).andReturn(null).once();
+    }
+
+    protected void setUpWithPathConfig(String path) {
+        mockFilterConfig = createMock(FilterConfig.class);
+        mockServletContext = createMock(ServletContext.class);
+
+        expect(mockFilterConfig.getServletContext()).andReturn(mockServletContext).anyTimes();
+        expect(mockFilterConfig.getInitParameter(IniShiroFilter.CONFIG_INIT_PARAM_NAME)).andReturn(null).anyTimes();
+        expect(mockFilterConfig.getInitParameter(IniShiroFilter.CONFIG_PATH_INIT_PARAM_NAME)).andReturn(path).anyTimes();
     }
 
     public void tearDown() throws Exception {
@@ -52,7 +62,7 @@
 
         replay(mockServletContext);
 
-        //this.filter.destroy();
+        this.filter.destroy();
 
         verify(mockServletContext);
         verify(mockFilterConfig);
@@ -62,7 +72,7 @@
         replay(mockServletContext);
         replay(mockFilterConfig);
 
-        this.filter = new ShiroFilter();
+        this.filter = new IniShiroFilter();
         this.filter.init(mockFilterConfig);
 
         verify(mockFilterConfig);
@@ -81,4 +91,10 @@
         setUp("[filters]\nauthc.successUrl = /index.jsp");
         replayAndVerify();
     }
+
+    @Test
+    public void testSimplePathConfig() throws Exception {
+        setUpWithPathConfig("classpath:IniShiroFilterTest.ini");
+        replayAndVerify();
+    }
 }

Added: incubator/shiro/trunk/web/src/test/resources/IniShiroFilterTest.ini
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/resources/IniShiroFilterTest.ini?rev=831623&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/test/resources/IniShiroFilterTest.ini (added)
+++ incubator/shiro/trunk/web/src/test/resources/IniShiroFilterTest.ini Sun Nov  1 00:05:33 2009
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+[filters]
+authc.successUrl = /index.jsp
+