This is an automated email from the ASF dual-hosted git repository.

lprimak pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/shiro.git


The following commit(s) were added to refs/heads/main by this push:
     new 3b9638b95 enh: added case-insensitive path filtering
3b9638b95 is described below

commit 3b9638b957495004599aeaf24ba8949e309f26e8
Author: lprimak <[email protected]>
AuthorDate: Sat Jan 31 14:15:08 2026 -0600

    enh: added case-insensitive path filtering
---
 .../java/org/apache/shiro/util/AntPathMatcher.java | 47 +++++++++++---------
 .../java/org/apache/shiro/util/PatternMatcher.java | 15 +++++++
 .../org/apache/shiro/util/RegExPatternMatcher.java |  2 +
 .../org/apache/shiro/util/AntPathMatcherTests.java |  8 ++++
 .../shiro/spring/web/ShiroFilterFactoryBean.java   | 19 +++++++-
 .../AbstractShiroWebFilterConfiguration.java       |  4 ++
 .../config/ShiroWebFilterConfigurationTest.groovy  | 50 +++++++++++++++++++++-
 .../web/config/IniFilterChainResolverFactory.java  | 14 +++++-
 .../shiro/web/filter/PathConfigProcessor.java      |  6 +++
 .../shiro/web/filter/PathMatchingFilter.java       |  7 +++
 .../web/filter/mgt/DefaultFilterChainManager.java  |  8 ++++
 .../shiro/web/filter/mgt/FilterChainManager.java   |  6 +++
 .../mgt/PathMatchingFilterChainResolver.java       | 18 ++++++++
 13 files changed, 180 insertions(+), 24 deletions(-)

diff --git a/core/src/main/java/org/apache/shiro/util/AntPathMatcher.java 
b/core/src/main/java/org/apache/shiro/util/AntPathMatcher.java
index 0c31e306e..15bb00079 100644
--- a/core/src/main/java/org/apache/shiro/util/AntPathMatcher.java
+++ b/core/src/main/java/org/apache/shiro/util/AntPathMatcher.java
@@ -69,6 +69,7 @@ public class AntPathMatcher implements PatternMatcher {
     public static final String DEFAULT_PATH_SEPARATOR = "/";
 
     private String pathSeparator = DEFAULT_PATH_SEPARATOR;
+    private boolean caseInsensitive;
 
 
     /**
@@ -79,6 +80,16 @@ public class AntPathMatcher implements PatternMatcher {
         this.pathSeparator = (pathSeparator != null ? pathSeparator : 
DEFAULT_PATH_SEPARATOR);
     }
 
+    @Override
+    public boolean isCaseInsensitive() {
+        return caseInsensitive;
+    }
+
+    @Override
+    public void setCaseInsensitive(boolean caseInsensitive) {
+        this.caseInsensitive = caseInsensitive;
+    }
+
     /**
      * Checks if {@code path} is a pattern (i.e. contains a '*', or '?').
      * For example the {@code /foo/**} would return {@code true}, while {@code 
/bar/} would return {@code false}.
@@ -281,11 +292,9 @@ public class AntPathMatcher implements PatternMatcher {
             }
             for (int i = 0; i <= patIdxEnd; i++) {
                 ch = patArr[i];
-                if (ch != '?') {
-                    if (ch != strArr[i]) {
-                        // Character mismatch
-                        return false;
-                    }
+                if (ch != '?' && checkCase(ch) != checkCase(strArr[i])) {
+                    // Character mismatch
+                    return false;
                 }
             }
             // String matches against pattern
@@ -300,12 +309,11 @@ public class AntPathMatcher implements PatternMatcher {
 
         // Process characters before first star
         while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
-            if (ch != '?') {
-                if (ch != strArr[strIdxStart]) {
-                    // Character mismatch
-                    return false;
-                }
+            if (ch != '?' && checkCase(ch) != checkCase(strArr[strIdxStart])) {
+                // Character mismatch
+                return false;
             }
+
             patIdxStart++;
             strIdxStart++;
         }
@@ -322,12 +330,11 @@ public class AntPathMatcher implements PatternMatcher {
 
         // Process characters after last star
         while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
-            if (ch != '?') {
-                if (ch != strArr[strIdxEnd]) {
-                    // Character mismatch
-                    return false;
-                }
+            if (ch != '?' && checkCase(ch) != checkCase(strArr[strIdxEnd])) {
+                // Character mismatch
+                return false;
             }
+
             patIdxEnd--;
             strIdxEnd--;
         }
@@ -366,10 +373,8 @@ public class AntPathMatcher implements PatternMatcher {
             for (int i = 0; i <= strLength - patLength; i++) {
                 for (int j = 0; j < patLength; j++) {
                     ch = patArr[patIdxStart + j + 1];
-                    if (ch != '?') {
-                        if (ch != strArr[strIdxStart + i + j]) {
-                            continue strLoop;
-                        }
+                    if (ch != '?' && checkCase(ch) != 
checkCase(strArr[strIdxStart + i + j])) {
+                        continue strLoop;
                     }
                 }
 
@@ -434,5 +439,7 @@ public class AntPathMatcher implements PatternMatcher {
         return builder.toString();
     }
 
-
+    private char checkCase(char ch) {
+        return isCaseInsensitive() ? Character.toLowerCase(ch) : ch;
+    }
 }
diff --git a/core/src/main/java/org/apache/shiro/util/PatternMatcher.java 
b/core/src/main/java/org/apache/shiro/util/PatternMatcher.java
index ac2d7a764..d72ffdc23 100644
--- a/core/src/main/java/org/apache/shiro/util/PatternMatcher.java
+++ b/core/src/main/java/org/apache/shiro/util/PatternMatcher.java
@@ -39,4 +39,19 @@ public interface PatternMatcher {
      * <code>false</code> otherwise.
      */
     boolean matches(String pattern, String source);
+
+    /**
+     * Returns {@code true} if pattern matching should be case-insensitive.
+     */
+    default boolean isCaseInsensitive() {
+        return false;
+    }
+
+    /**
+     * Sets whether pattern matching should be case-insensitive.
+     *
+     * @param caseInsensitive {@code true} if pattern matching should be 
case-insensitive.
+     */
+    default void setCaseInsensitive(boolean caseInsensitive) {
+    }
 }
diff --git a/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java 
b/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java
index b03d96b3d..3109d57d9 100644
--- a/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java
+++ b/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java
@@ -62,6 +62,7 @@ public class RegExPatternMatcher implements PatternMatcher {
      *
      * @return true if regex match should be case-insensitive.
      */
+    @Override
     public boolean isCaseInsensitive() {
         return caseInsensitive;
     }
@@ -71,6 +72,7 @@ public class RegExPatternMatcher implements PatternMatcher {
      *
      * @param caseInsensitive true if patterns should match case-insensitive.
      */
+    @Override
     public void setCaseInsensitive(boolean caseInsensitive) {
         this.caseInsensitive = caseInsensitive;
     }
diff --git a/core/src/test/java/org/apache/shiro/util/AntPathMatcherTests.java 
b/core/src/test/java/org/apache/shiro/util/AntPathMatcherTests.java
index b065a89cb..d682343f8 100644
--- a/core/src/test/java/org/apache/shiro/util/AntPathMatcherTests.java
+++ b/core/src/test/java/org/apache/shiro/util/AntPathMatcherTests.java
@@ -332,4 +332,12 @@ public class AntPathMatcherTests {
     void isPatternWithNullPath() {
         assertFalse(pathMatcher.isPattern(null));
     }
+
+    @Test
+    void caseInsensitiveMatch() {
+        pathMatcher.setCaseInsensitive(true);
+        assertTrue(pathMatcher.match("/Test/Path", "/test/path"));
+        assertTrue(pathMatcher.match("/TEST/PATH/*", "/test/path/extra"));
+        assertFalse(pathMatcher.match("/TEST/PATH", "/different/path"));
+    }
 }
diff --git 
a/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java
 
b/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java
index f02fdd4b7..c4e2ea5ee 100644
--- 
a/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java
+++ 
b/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java
@@ -135,6 +135,7 @@ public class ShiroFilterFactoryBean implements FactoryBean, 
BeanPostProcessor {
     private String loginUrl;
     private String successUrl;
     private String unauthorizedUrl;
+    private boolean caseInsensitive;
 
     private AbstractShiroFilter instance;
 
@@ -283,6 +284,21 @@ public class ShiroFilterFactoryBean implements 
FactoryBean, BeanPostProcessor {
         this.unauthorizedUrl = unauthorizedUrl;
     }
 
+    /**
+     * @return true if filter chain matching should be case insensitive.
+     */
+    public boolean isCaseInsensitive() {
+        return caseInsensitive;
+    }
+
+    /**
+     * Sets whether filter chain matching should be case insensitive.
+     * @param caseInsensitive true if filter chain matching should be case 
insensitive.
+     */
+    public void setCaseInsensitive(boolean caseInsensitive) {
+        this.caseInsensitive = caseInsensitive;
+    }
+
     /**
      * Returns the filterName-to-Filter map of filters available for reference 
when defining filter chain definitions.
      * All filter chain definitions will reference filters by the names in 
this map (i.e. the keys).
@@ -409,6 +425,7 @@ public class ShiroFilterFactoryBean implements FactoryBean, 
BeanPostProcessor {
     protected FilterChainManager createFilterChainManager() {
 
         DefaultFilterChainManager manager = new DefaultFilterChainManager();
+        manager.setCaseInsensitive(caseInsensitive);
         Map<String, Filter> defaultFilters = manager.getFilters();
         //apply global settings if necessary:
         for (Filter filter : defaultFilters.values()) {
@@ -489,7 +506,7 @@ public class ShiroFilterFactoryBean implements FactoryBean, 
BeanPostProcessor {
         //Expose the constructed FilterChainManager by first wrapping it in a
         // FilterChainResolver implementation. The AbstractShiroFilter 
implementations
         // do not know about FilterChainManagers - only resolvers:
-        PathMatchingFilterChainResolver chainResolver = new 
PathMatchingFilterChainResolver();
+        PathMatchingFilterChainResolver chainResolver = new 
PathMatchingFilterChainResolver().caseInsensitive(caseInsensitive);
         chainResolver.setFilterChainManager(manager);
 
         //Now create a concrete ShiroFilter instance and apply the acquired 
SecurityManager and built
diff --git 
a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
 
b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
index ff9df7a0b..2a62cdc0f 100644
--- 
a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
+++ 
b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
@@ -56,6 +56,9 @@ public class AbstractShiroWebFilterConfiguration {
     @Value("#{ @environment['shiro.unauthorizedUrl'] ?: null }")
     protected String unauthorizedUrl;
 
+    @Value("#{ @environment['shiro.caseInsensitive'] ?: false }")
+    protected boolean caseInsensitive;
+
     protected List<String> globalFilters() {
         return Collections.singletonList(DefaultFilter.invalidRequest.name());
     }
@@ -72,6 +75,7 @@ public class AbstractShiroWebFilterConfiguration {
         filterFactoryBean.setLoginUrl(loginUrl);
         filterFactoryBean.setSuccessUrl(successUrl);
         filterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
+        filterFactoryBean.setCaseInsensitive(caseInsensitive);
 
         filterFactoryBean.setSecurityManager(securityManager);
         
filterFactoryBean.setShiroFilterConfiguration(shiroFilterConfiguration());
diff --git 
a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroWebFilterConfigurationTest.groovy
 
b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroWebFilterConfigurationTest.groovy
index 5c6ee9f50..04f7e6377 100644
--- 
a/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroWebFilterConfigurationTest.groovy
+++ 
b/support/spring/src/test/groovy/org/apache/shiro/spring/config/ShiroWebFilterConfigurationTest.groovy
@@ -25,7 +25,12 @@ import 
org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition
 import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition
 import org.apache.shiro.spring.web.config.ShiroWebFilterConfiguration
 import org.apache.shiro.web.filter.InvalidRequestFilter
+import org.apache.shiro.web.filter.PathConfigProcessor
 import org.apache.shiro.web.filter.mgt.FilterChainManager
+import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager
+import org.apache.shiro.web.servlet.AbstractShiroFilter
+import org.junit.jupiter.api.AfterEach
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.extension.ExtendWith
 import org.springframework.beans.factory.annotation.Autowired
@@ -47,6 +52,7 @@ import static org.hamcrest.Matchers.contains
 import static org.hamcrest.Matchers.instanceOf
 import static org.hamcrest.Matchers.notNullValue
 import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.is;
 
 /**
  * Test ShiroWebFilterConfiguration creates a ShiroFilterFactoryBean that 
contains Servlet filters that are available for injection.
@@ -62,6 +68,13 @@ class ShiroWebFilterConfigurationTest extends 
AbstractJUnit4SpringContextTests {
     @Autowired
     private ShiroFilterFactoryBean shiroFilterFactoryBean
 
+    private static final ThreadLocal<Boolean> caseInsensitiveCalled = 
ThreadLocal.withInitial { false }
+
+    @AfterEach
+    void tearDown() {
+        caseInsensitiveCalled.remove()
+    }
+
     @Test
     void testShiroFilterFactoryBeanContainsSpringFilters() {
 
@@ -73,6 +86,31 @@ class ShiroWebFilterConfigurationTest extends 
AbstractJUnit4SpringContextTests {
         assertThat filterChainManager.getChain("/test-me"), 
contains(instanceOf(InvalidRequestFilter), instanceOf(ExpectedTestFilter))
     }
 
+    @Test
+    void caseInsensitiveChainManager() {
+        shiroFilterFactoryBean.setCaseInsensitive true
+        FilterChainManager filterChainManager = 
shiroFilterFactoryBean.createFilterChainManager()
+        assertThat filterChainManager.caseInsensitive, is(true)
+    }
+
+    @Test
+    void caseInsensitiveResolverAndPathMatcher() {
+        shiroFilterFactoryBean.setCaseInsensitive true
+        shiroFilterFactoryBean.setSecurityManager new 
DefaultWebSecurityManager()
+        AbstractShiroFilter filter = shiroFilterFactoryBean.getObject()
+        PathMatchingFilterChainResolver resolver = filter.filterChainResolver;
+        assertThat resolver.caseInsensitive, is(true)
+        assertThat resolver.pathMatcher.caseInsensitive, is(true)
+        assertThat caseInsensitiveCalled.get(), is(true)
+    }
+
+    @Test
+    void caseInsensitivePathConfigProcessor() {
+        shiroFilterFactoryBean.setCaseInsensitive true
+        shiroFilterFactoryBean.createFilterChainManager()
+        assertThat caseInsensitiveCalled.get(), is(true)
+    }
+
     @Configuration
     static class FilterConfiguration {
 
@@ -91,7 +129,7 @@ class ShiroWebFilterConfigurationTest extends 
AbstractJUnit4SpringContextTests {
         }
     }
 
-    static class ExpectedTestFilter implements Filter {
+    static class ExpectedTestFilter implements Filter, PathConfigProcessor {
         @Override
         void init(FilterConfig filterConfig) throws ServletException {}
 
@@ -100,5 +138,15 @@ class ShiroWebFilterConfigurationTest extends 
AbstractJUnit4SpringContextTests {
 
         @Override
         void destroy() {}
+
+        @Override
+        Filter processPathConfig(String path, String config) {
+            return null
+        }
+
+        @Override
+        void setCaseInsensitive(boolean caseInsensitive) {
+            caseInsensitiveCalled.set caseInsensitive
+        }
     }
 }
diff --git 
a/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java
 
b/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java
index 07dfbbad6..c57fec54d 100644
--- 
a/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java
+++ 
b/web/src/main/java/org/apache/shiro/web/config/IniFilterChainResolverFactory.java
@@ -61,6 +61,8 @@ public class IniFilterChainResolverFactory extends 
IniFactorySupport<FilterChain
 
     private List<String> globalFilters = 
Collections.singletonList(DefaultFilter.invalidRequest.name());
 
+    private boolean caseInsensitive;
+
     public IniFilterChainResolverFactory() {
         super();
     }
@@ -90,6 +92,14 @@ public class IniFilterChainResolverFactory extends 
IniFactorySupport<FilterChain
         this.globalFilters = globalFilters;
     }
 
+    public boolean isCaseInsensitive() {
+        return caseInsensitive;
+    }
+
+    public void setCaseInsensitive(boolean caseInsensitive) {
+        this.caseInsensitive = caseInsensitive;
+    }
+
     protected FilterChainResolver createInstance(Ini ini) {
         FilterChainResolver filterChainResolver = createDefaultInstance();
         if (filterChainResolver instanceof PathMatchingFilterChainResolver) {
@@ -103,9 +113,9 @@ public class IniFilterChainResolverFactory extends 
IniFactorySupport<FilterChain
     protected FilterChainResolver createDefaultInstance() {
         FilterConfig filterConfig = getFilterConfig();
         if (filterConfig != null) {
-            return new PathMatchingFilterChainResolver(filterConfig);
+            return new 
PathMatchingFilterChainResolver(filterConfig).caseInsensitive(caseInsensitive);
         } else {
-            return new PathMatchingFilterChainResolver();
+            return new 
PathMatchingFilterChainResolver().caseInsensitive(caseInsensitive);
         }
     }
 
diff --git 
a/web/src/main/java/org/apache/shiro/web/filter/PathConfigProcessor.java 
b/web/src/main/java/org/apache/shiro/web/filter/PathConfigProcessor.java
index aa5be8169..7eae3150e 100644
--- a/web/src/main/java/org/apache/shiro/web/filter/PathConfigProcessor.java
+++ b/web/src/main/java/org/apache/shiro/web/filter/PathConfigProcessor.java
@@ -36,4 +36,10 @@ public interface PathConfigProcessor {
      * @return the {@code Filter} that should execute for the given 
path/config combination.
      */
     Filter processPathConfig(String path, String config);
+
+    /**
+     * Sets whether the path matching performed by this processor is case 
insensitive.
+     * @param caseInsensitive true if case insensitive, false otherwise
+     */
+    default void setCaseInsensitive(boolean caseInsensitive) { }
 }
diff --git 
a/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilter.java 
b/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilter.java
index 4ac41845c..0d252b57b 100644
--- a/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilter.java
+++ b/web/src/main/java/org/apache/shiro/web/filter/PathMatchingFilter.java
@@ -91,6 +91,13 @@ public abstract class PathMatchingFilter extends 
AdviceFilter implements PathCon
         return this;
     }
 
+    @Override
+    public void setCaseInsensitive(boolean caseInsensitive) {
+        if (pathMatcher != null) {
+            pathMatcher.setCaseInsensitive(caseInsensitive);
+        }
+    }
+
     /**
      * Returns the context path within the application based on the specified 
<code>request</code>.
      * <p/>
diff --git 
a/web/src/main/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManager.java
 
b/web/src/main/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManager.java
index 59893db95..00443da6b 100644
--- 
a/web/src/main/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManager.java
+++ 
b/web/src/main/java/org/apache/shiro/web/filter/mgt/DefaultFilterChainManager.java
@@ -66,6 +66,8 @@ public class DefaultFilterChainManager implements 
FilterChainManager {
      */
     private Map<String, NamedFilterList> filterChains;
 
+    private boolean caseInsensitive;
+
     public DefaultFilterChainManager() {
         this.filters = new LinkedHashMap<String, Filter>();
         this.filterChains = new LinkedHashMap<String, NamedFilterList>();
@@ -121,6 +123,11 @@ public class DefaultFilterChainManager implements 
FilterChainManager {
         return this.filters.get(name);
     }
 
+    @Override
+    public void setCaseInsensitive(boolean caseInsensitive) {
+        this.caseInsensitive = caseInsensitive;
+    }
+
     public void addFilter(String name, Filter filter) {
         addFilter(name, filter, false);
     }
@@ -327,6 +334,7 @@ public class DefaultFilterChainManager implements 
FilterChainManager {
         }
         if (filter instanceof PathConfigProcessor) {
             ((PathConfigProcessor) filter).processPathConfig(chainName, 
chainSpecificFilterConfig);
+            ((PathConfigProcessor) filter).setCaseInsensitive(caseInsensitive);
         } else {
             if (StringUtils.hasText(chainSpecificFilterConfig)) {
                 //they specified a filter configuration, but the Filter 
doesn't implement PathConfigProcessor
diff --git 
a/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainManager.java 
b/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainManager.java
index 980235206..fa57fa767 100644
--- a/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainManager.java
+++ b/web/src/main/java/org/apache/shiro/web/filter/mgt/FilterChainManager.java
@@ -220,4 +220,10 @@ public interface FilterChainManager {
      * @since 1.6
      */
     void setGlobalFilters(List<String> globalFilterNames) throws 
ConfigurationException;
+
+    /**
+     * Sets whether or not path matching should be case insensitive.
+     * @param caseInsensitive boolean value indicating whether path matching 
should be case insensitive.
+     */
+    default void setCaseInsensitive(boolean caseInsensitive) { }
 }
diff --git 
a/web/src/main/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolver.java
 
b/web/src/main/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolver.java
index 052ccaa50..11c15ebe0 100644
--- 
a/web/src/main/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolver.java
+++ 
b/web/src/main/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolver.java
@@ -61,6 +61,11 @@ public class PathMatchingFilterChainResolver implements 
FilterChainResolver {
         this.filterChainManager = new DefaultFilterChainManager(filterConfig);
     }
 
+    public PathMatchingFilterChainResolver caseInsensitive(boolean 
caseInsensitive) {
+        setCaseInsensitive(caseInsensitive);
+        return this;
+    }
+
     /**
      * Returns the {@code PatternMatcher} used when determining if an incoming 
request's path
      * matches a configured filter chain.  Unless overridden, the
@@ -85,6 +90,19 @@ public class PathMatchingFilterChainResolver implements 
FilterChainResolver {
         this.pathMatcher = pathMatcher;
     }
 
+    public boolean isCaseInsensitive() {
+        return pathMatcher != null && pathMatcher.isCaseInsensitive();
+    }
+
+    public void setCaseInsensitive(boolean caseInsensitive) {
+        if (pathMatcher != null) {
+            pathMatcher.setCaseInsensitive(caseInsensitive);
+        }
+        if (filterChainManager != null) {
+            filterChainManager.setCaseInsensitive(caseInsensitive);
+        }
+    }
+
     public FilterChainManager getFilterChainManager() {
         return filterChainManager;
     }

Reply via email to