[java-shib-shared] branch main updated: JSSH-8 - Servlet filter that implements its own filter-mapping layer

Scott Cantor cantor.2 at osu.edu
Thu Sep 29 18:26:42 UTC 2022


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository java-shib-shared.

View the commit online:
http://git.shibboleth.net/view/?p=java-shib-shared.git;a=commit;h=df261659bfa2a5d26381a96f239718978ba0f484

The following commit(s) were added to refs/heads/main by this push:
     new df261659 JSSH-8 - Servlet filter that implements its own filter-mapping layer
df261659 is described below

commit df261659bfa2a5d26381a96f239718978ba0f484
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Sep 29 14:26:40 2022 -0400

    JSSH-8 - Servlet filter that implements its own filter-mapping layer
    
    https://shibboleth.atlassian.net/browse/JSSH-8
    
    Reorg servlet and filter classes.
    Added initial support for Spring-based filter config/mapping
    Added ChainingFilter and supporting code to auto-inject filters to run
---
 shib-networking-spring/pom.xml                     |   5 +
 .../shared/spring/servlet/ChainableFilter.java     |  71 +++++++++++
 .../shared/spring/servlet/impl/ChainingFilter.java | 124 +++++++++++++++++++
 .../servlet/impl}/CookieBufferingFilter.java       |  20 +++-
 .../servlet/impl}/DynamicResponseHeaderFilter.java |  17 ++-
 .../impl}/RequestResponseContextFilter.java        |  20 +++-
 .../servlet/impl}/SameSiteCookieHeaderFilter.java  |  47 +++-----
 .../shared/spring/servlet/impl}/package-info.java  |   7 +-
 .../shared/spring/servlet}/package-info.java       |   7 +-
 .../HttpServletRequestResponseContextTest.java     |   3 +-
 .../impl}/RequestResponseContextFilterTest.java    |   5 +-
 .../impl}/SameSiteCookieHeaderFilterTest.java      |   7 +-
 .../shared/servlet/AbstractConditionalFilter.java  | 103 ++++++++++++++++
 .../{net => servlet}/HttpServletSupport.java       |   3 +-
 .../impl/HttpServletRequestResponseContext.java    |   9 +-
 .../servlet/impl/RequestURLPrefixPredicate.java    |  77 ++++++++++++
 .../shared/servlet/impl/StubbedFilter.java         |  74 ++++++++++++
 .../impl/ThreadLocalHttpServletRequestProxy.java   |   2 +-
 .../ThreadLocalHttpServletRequestSupplier.java     |   2 +-
 .../impl/ThreadLocalHttpServletResponseProxy.java  |   2 +-
 .../ThreadLocalHttpServletResponseSupplier.java    |   2 +-
 .../net => shared/servlet/impl}/package-info.java  |   7 +-
 .../net => shared/servlet}/package-info.java       |   7 +-
 .../java/support/net/CookieBufferingFilter.java    | 133 +--------------------
 .../support/net/RequestResponseContextFilter.java  |  51 +-------
 .../utilities/java/support/net/package-info.java   |   5 +-
 .../impl}/HttpServletSupportTest.java              |   4 +-
 .../ThreadLocalHttpServletRequestProxyTest.java    |   2 +-
 .../ThreadLocalHttpServletResponseProxyTest.java   |   2 +-
 .../shared/security/impl/IPRangeAccessControl.java |   2 +-
 .../shared/spring/util/SpringSupport.java          |   2 +-
 31 files changed, 562 insertions(+), 260 deletions(-)

diff --git a/shib-networking-spring/pom.xml b/shib-networking-spring/pom.xml
index 05da921d..81366753 100644
--- a/shib-networking-spring/pom.xml
+++ b/shib-networking-spring/pom.xml
@@ -60,6 +60,11 @@
         </dependency>
 
         <!-- Provided dependencies -->
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
 
         <!-- Runtime Dependencies -->
 
diff --git a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/ChainableFilter.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/ChainableFilter.java
new file mode 100644
index 00000000..9fbed6f9
--- /dev/null
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/ChainableFilter.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.shared.spring.servlet;
+
+import org.springframework.core.Ordered;
+
+import jakarta.servlet.Filter;
+
+/**
+ * Marker interface for filters to be automatically installed via implementation-specific means.
+ */
+public interface ChainableFilter extends Filter, Ordered {
+
+    /**
+     * An abstraction for modeling filter order.
+     */
+    public enum FilterOrder {
+    
+        /** Run as early as possible. */
+        EARLIEST(Integer.MIN_VALUE),
+        
+        /** Run early but not the earliest. */
+        EARLY(Integer.MIN_VALUE + 1000),
+        
+        /** Run whenever. */
+        NEUTRAL(0),
+        
+        /** Run later but not the latest. */
+        LATE(Integer.MAX_VALUE - 1000),
+        
+        /** Run as late as possible. */
+        LATEST(Integer.MAX_VALUE);
+    
+        /** Store integer value. */
+        private final int intValue;
+        
+        /**
+         * Constructor.
+         *
+         * @param value value to use
+         */
+        private FilterOrder(int value) {
+            intValue = value;
+        }
+        
+        /**
+         * Get the integral equivalent of the enum.
+         * 
+         * @return integral value
+         */
+        public int getValue() {
+            return intValue;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/ChainingFilter.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/ChainingFilter.java
new file mode 100644
index 00000000..b8c40aac
--- /dev/null
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/ChainingFilter.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.shared.spring.servlet.impl;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.servlet.AbstractConditionalFilter;
+import net.shibboleth.shared.spring.servlet.ChainableFilter;
+
+
+/**
+ * Implementation of {@link Filter} that encapsulates and runs a chain of embedded filters in a defined
+ * order.
+ * 
+ * <p>This is provided to deal with the problem of filter order when programmatic registration is done.
+ * Good or bad, some filters are order-sensitive and wishing that wasn't true doesn't change it.</p> 
+ */
+public class ChainingFilter implements Filter {
+
+    /** Embedded chain. */
+    @Nullable @NonnullElements List<ChainableFilter> filters;
+    
+    /**
+     * Constructor.
+     *  
+     * @param filterChain auto-wired chain of filters to run
+     */
+    @Autowired
+    public ChainingFilter(@Nullable @NonnullElements Collection<ChainableFilter> filterChain) {
+        if (filterChain != null) {
+            filters = List.copyOf(filterChain);
+        } else {
+            filters = null;
+        }
+    }
+    
+    /** {@inheritDoc} */
+    public void init(final FilterConfig filterConfig) throws ServletException {
+    }
+
+    /** {@inheritDoc} */
+    public void destroy() {
+    }
+
+    /** {@inheritDoc} */
+    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+            throws IOException, ServletException {
+        
+        if (filters == null || filters.isEmpty()) {
+            chain.doFilter(request, response);
+        } else {
+            new Chain(chain).doFilter(request, response);
+        }
+    }
+
+    /** Internal iteration of chain. */
+    private class Chain implements FilterChain {
+
+        /** Tracked iterator. */
+        @Nonnull private Iterator<ChainableFilter> iterator;
+        
+        /** Chain of top-level filters. */
+        @Nonnull private FilterChain outerChain;
+        
+        /**
+         * Constructor.
+         * 
+         * @param outer outer filter chain
+         */
+        public Chain(@Nonnull final FilterChain outer) {
+            iterator = filters.iterator();
+            outerChain = outer;
+        }
+        
+        /** {@inheritDoc} */
+        @Override
+        public void doFilter(final ServletRequest request, final ServletResponse response)
+                throws IOException, ServletException {
+            if (iterator.hasNext()) {
+                final ChainableFilter filter = iterator.next();
+                if (filter instanceof AbstractConditionalFilter &&
+                        !((AbstractConditionalFilter) filter).getActivationCondition().test(request)) {
+                    doFilter(request, response);
+                    return;
+                }
+                
+                filter.doFilter(request, response, this);
+            } else {
+                outerChain.doFilter(request, response);
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/CookieBufferingFilter.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/CookieBufferingFilter.java
similarity index 87%
copy from shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/CookieBufferingFilter.java
copy to shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/CookieBufferingFilter.java
index d9d82985..d9182b51 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/CookieBufferingFilter.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/CookieBufferingFilter.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.utilities.java.support.net;
+package net.shibboleth.shared.spring.servlet.impl;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -37,12 +37,14 @@ import jakarta.servlet.http.HttpServletResponse;
 import jakarta.servlet.http.HttpServletResponseWrapper;
 import net.shibboleth.shared.annotation.constraint.Live;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.servlet.AbstractConditionalFilter;
+import net.shibboleth.shared.spring.servlet.ChainableFilter;
 
 /**
- * Implementation of an HTTP servlet {@link Filter} which wraps the {@link HttpServletResponse} via
- * {@link CookieBufferingHttpServletResponseProxy} to ensure that only a single cookie of a given name is set.
+ * Implementation of {@link Filter} which wraps the {@link HttpServletResponse} to ensure
+ * that only a single cookie of a given name is set.
  */
-public class CookieBufferingFilter implements Filter {
+public class CookieBufferingFilter extends AbstractConditionalFilter implements ChainableFilter {
 
     /** {@inheritDoc} */
     public void init(final FilterConfig filterConfig) throws ServletException {
@@ -53,7 +55,13 @@ public class CookieBufferingFilter implements Filter {
     }
 
     /** {@inheritDoc} */
-    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+    public int getOrder() {
+        return FilterOrder.NEUTRAL.getValue();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void runFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
             throws IOException,
             ServletException {
 
@@ -149,4 +157,4 @@ public class CookieBufferingFilter implements Filter {
         }
     }
     
-}
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/DynamicResponseHeaderFilter.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/DynamicResponseHeaderFilter.java
similarity index 92%
rename from shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/DynamicResponseHeaderFilter.java
rename to shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/DynamicResponseHeaderFilter.java
index e25c4d4a..9c15e0da 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/DynamicResponseHeaderFilter.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/DynamicResponseHeaderFilter.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.utilities.java.support.net;
+package net.shibboleth.shared.spring.servlet.impl;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -42,12 +42,15 @@ import jakarta.servlet.http.HttpServletResponseWrapper;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.servlet.AbstractConditionalFilter;
+import net.shibboleth.shared.spring.servlet.ChainableFilter;
+
 
 /**
  * Implementation of an HTTP servlet {@link Filter} which supports configurable response header
  * injection, including via injected functions that can conditionally attach headers.
  */
-public class DynamicResponseHeaderFilter implements Filter {
+public class DynamicResponseHeaderFilter extends AbstractConditionalFilter implements ChainableFilter {
     
     /** Statically defined headers to return. */
     @Nonnull @NonnullElements private Map<String,String> headers;
@@ -105,7 +108,13 @@ public class DynamicResponseHeaderFilter implements Filter {
     }
 
     /** {@inheritDoc} */
-    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+    public int getOrder() {
+        return FilterOrder.NEUTRAL.getValue();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void runFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
             throws IOException,
             ServletException {
         
@@ -196,4 +205,4 @@ public class DynamicResponseHeaderFilter implements Filter {
         }
     }
     
-}
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/RequestResponseContextFilter.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/RequestResponseContextFilter.java
similarity index 76%
copy from shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/RequestResponseContextFilter.java
copy to shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/RequestResponseContextFilter.java
index 0d60f2d1..e044afdb 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/RequestResponseContextFilter.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/RequestResponseContextFilter.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.utilities.java.support.net;
+package net.shibboleth.shared.spring.servlet.impl;
 
 import java.io.IOException;
 
@@ -27,15 +27,17 @@ import jakarta.servlet.ServletRequest;
 import jakarta.servlet.ServletResponse;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
-import net.shibboleth.shared.net.impl.HttpServletRequestResponseContext;
+import net.shibboleth.shared.servlet.AbstractConditionalFilter;
+import net.shibboleth.shared.servlet.impl.HttpServletRequestResponseContext;
+import net.shibboleth.shared.spring.servlet.ChainableFilter;
 
 
 /**
- * Implementation of an HTTP servlet {@link Filter} which stores the current {@link HttpServletRequest} and
+ * Implementation of {@link Filter} which stores the current {@link HttpServletRequest} and
  * {@link HttpServletResponse} being serviced on thread-local storage via the use of holder class
  * {@link HttpServletRequestResponseContext}.
  */
-public class RequestResponseContextFilter implements Filter {
+public class RequestResponseContextFilter extends AbstractConditionalFilter implements ChainableFilter {
 
     /** {@inheritDoc} */
     public void init(final FilterConfig filterConfig) throws ServletException {
@@ -46,7 +48,13 @@ public class RequestResponseContextFilter implements Filter {
     }
 
     /** {@inheritDoc} */
-    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+    public int getOrder() {
+        return FilterOrder.LATEST.getValue();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void runFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
             throws IOException,
             ServletException {
 
@@ -67,4 +75,4 @@ public class RequestResponseContextFilter implements Filter {
 
     }
 
-}
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/SameSiteCookieHeaderFilter.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/SameSiteCookieHeaderFilter.java
similarity index 90%
rename from shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/SameSiteCookieHeaderFilter.java
rename to shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/SameSiteCookieHeaderFilter.java
index b0cfeff4..bfa39fb0 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/SameSiteCookieHeaderFilter.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/SameSiteCookieHeaderFilter.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.utilities.java.support.net;
+package net.shibboleth.shared.spring.servlet.impl;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -25,7 +25,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -33,7 +32,6 @@ import javax.annotation.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Predicates;
 import com.google.common.net.HttpHeaders;
 
 import jakarta.servlet.Filter;
@@ -49,17 +47,19 @@ import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.servlet.AbstractConditionalFilter;
+import net.shibboleth.shared.spring.servlet.ChainableFilter;
 
 
 /**
- * Implementation of an HTTP servlet {@link Filter} which adds the SameSite attribute to cookies, until
- * the Java API supports it natively, if ever.
+ * Implementation of {@link Filter} which adds the SameSite attribute to cookies, until the Java API supports it
+ * natively, if ever.
  * 
  * <p>Explicitly named cookies are configured and placed into a Map of cookie name to same-site attribute value.</p>
  * 
  * <p>All other cookies may be assigned a default value.</p>
  * 
- * <p>Cookies with an existing same-site cookie flag are  left unaltered - copied back into the response
+ * <p>Cookies with an existing same-site cookie flag are left unaltered - copied back into the response
  * without modification.</p>
  * 
  * <p>A single cookie can only have at most one same-site value set. Attempts in the configuration to 
@@ -67,7 +67,7 @@ import net.shibboleth.shared.primitive.StringSupport;
  * {@link IllegalArgumentException}.</p>
  * 
  */
-public class SameSiteCookieHeaderFilter implements Filter {
+public class SameSiteCookieHeaderFilter extends AbstractConditionalFilter implements ChainableFilter {
     
     /** The name of the same-site cookie attribute.*/
     @Nonnull @NotEmpty private static final String SAMESITE_ATTRIBITE_NAME="SameSite";
@@ -118,9 +118,6 @@ public class SameSiteCookieHeaderFilter implements Filter {
         }
         
     }
-
-    /** Condition on filter running. */
-    @Nonnull private Predicate<ServletRequest> activationCondition;
     
     /** Optional default value to apply. */
     @Nullable private SameSiteValue defaultValue;
@@ -131,18 +128,6 @@ public class SameSiteCookieHeaderFilter implements Filter {
     /** Constructor. */
     public SameSiteCookieHeaderFilter() {
         sameSiteCookies = Collections.emptyMap();
-        activationCondition = Predicates.alwaysTrue();
-    }
-    
-    /**
-     * Set a condition on execution of the filter.
-     * 
-     * <p>This is typically for conditional User-Agent detection to deal with the Apple bug.</p>
-     * 
-     * @param condition condition to set
-     */
-    public void setActivationCondition(@Nonnull final Predicate<ServletRequest> condition) {
-        activationCondition = Constraint.isNotNull(condition, "Activation condition cannot be null"); 
     }
     
     /**
@@ -194,17 +179,17 @@ public class SameSiteCookieHeaderFilter implements Filter {
     /** {@inheritDoc} */
     public void destroy() {
     }
-    
+
     /** {@inheritDoc} */
-    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+    public int getOrder() {
+        return FilterOrder.EARLIEST.getValue();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void runFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
             throws IOException, ServletException {
 
-        if (!activationCondition.test(request)) {
-            log.trace("Filter not active for request");
-            chain.doFilter(request, response);
-            return;
-        }
-        
         if (!(response instanceof HttpServletResponse)) {
             throw new ServletException("Response is not an instance of HttpServletResponse");
         }
@@ -354,4 +339,4 @@ public class SameSiteCookieHeaderFilter implements Filter {
         } 
     }
     
-}
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/package-info.java
similarity index 85%
copy from shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
copy to shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/package-info.java
index deb616a2..2f01a21a 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/impl/package-info.java
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
-/** Classes for working with HTTP URLs and the protocol. */
-
-package net.shibboleth.utilities.java.support.net;
\ No newline at end of file
+/**
+ * Spring-aware implementation classes related to Java Servlet and Filter behavior.
+ */
+package net.shibboleth.shared.spring.servlet.impl;
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/package-info.java
similarity index 87%
copy from shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
copy to shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/package-info.java
index deb616a2..e7931cec 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
+++ b/shib-networking-spring/src/main/java/net/shibboleth/shared/spring/servlet/package-info.java
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
-/** Classes for working with HTTP URLs and the protocol. */
-
-package net.shibboleth.utilities.java.support.net;
\ No newline at end of file
+/**
+ * Spring-aware APIs relating to Java Servlets, Filters, etc.
+ */
+package net.shibboleth.shared.spring.servlet;
\ No newline at end of file
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/net/impl/HttpServletRequestResponseContextTest.java b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/HttpServletRequestResponseContextTest.java
similarity index 96%
rename from shib-networking/src/test/java/net/shibboleth/shared/net/impl/HttpServletRequestResponseContextTest.java
rename to shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/HttpServletRequestResponseContextTest.java
index 208836b4..e57dabac 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/net/impl/HttpServletRequestResponseContextTest.java
+++ b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/HttpServletRequestResponseContextTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net.impl;
+package net.shibboleth.shared.spring.servlet.impl;
 
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
@@ -26,6 +26,7 @@ import org.testng.annotations.Test;
 
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+import net.shibboleth.shared.servlet.impl.HttpServletRequestResponseContext;
 
 /**
  * Tests for {@link HttpServletRequestResponseContext}.
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/net/RequestResponseContextFilterTest.java b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/RequestResponseContextFilterTest.java
similarity index 95%
rename from shib-networking/src/test/java/net/shibboleth/shared/net/RequestResponseContextFilterTest.java
rename to shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/RequestResponseContextFilterTest.java
index 4bdae85d..feb42185 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/net/RequestResponseContextFilterTest.java
+++ b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/RequestResponseContextFilterTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net;
+package net.shibboleth.shared.spring.servlet.impl;
 
 import java.io.IOException;
 
@@ -37,8 +37,7 @@ import jakarta.servlet.ServletRequest;
 import jakarta.servlet.ServletResponse;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
-import net.shibboleth.shared.net.impl.HttpServletRequestResponseContext;
-import net.shibboleth.utilities.java.support.net.RequestResponseContextFilter;
+import net.shibboleth.shared.servlet.impl.HttpServletRequestResponseContext;
 
 /**
  * Tests for {@link RequestResponseContextFilter}.
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/net/SameSiteCookieHeaderFilterTest.java b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/SameSiteCookieHeaderFilterTest.java
similarity index 98%
rename from shib-networking/src/test/java/net/shibboleth/shared/net/SameSiteCookieHeaderFilterTest.java
rename to shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/SameSiteCookieHeaderFilterTest.java
index 6de59750..5d81d525 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/net/SameSiteCookieHeaderFilterTest.java
+++ b/shib-networking-spring/src/test/java/net/shibboleth/shared/spring/servlet/impl/SameSiteCookieHeaderFilterTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net;
+package net.shibboleth.shared.spring.servlet.impl;
 
 import java.io.IOException;
 import java.io.OutputStreamWriter;
@@ -49,9 +49,8 @@ import jakarta.servlet.ServletRequest;
 import jakarta.servlet.ServletResponse;
 import jakarta.servlet.http.Cookie;
 import jakarta.servlet.http.HttpServletResponse;
-import net.shibboleth.shared.net.impl.HttpServletRequestResponseContext;
-import net.shibboleth.utilities.java.support.net.SameSiteCookieHeaderFilter;
-import net.shibboleth.utilities.java.support.net.SameSiteCookieHeaderFilter.SameSiteValue;
+import net.shibboleth.shared.servlet.impl.HttpServletRequestResponseContext;
+import net.shibboleth.shared.spring.servlet.impl.SameSiteCookieHeaderFilter.SameSiteValue;
 
 /**
  * Tests for {@link SameSiteCookieHeaderFilter}.
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/servlet/AbstractConditionalFilter.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/AbstractConditionalFilter.java
new file mode 100644
index 00000000..9c5a5f97
--- /dev/null
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/AbstractConditionalFilter.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.shared.servlet;
+
+import java.io.IOException;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import net.shibboleth.shared.logic.Constraint;
+
+import com.google.common.base.Predicates;
+
+/**
+ * Base class for HTTP servlet {@link Filter} that determines whether to run dynamically
+ * based on a supplied {@link Predicate} instead of based on mapping rules defined in web.xml.
+ * 
+ * @since 9.0.0
+ */
+public abstract class AbstractConditionalFilter implements Filter {
+    
+    /** Whether filter should run or not. */
+    @Nonnull private Predicate<ServletRequest> activationCondition;
+    
+    /** Constructor. */
+    public AbstractConditionalFilter() {
+        activationCondition = Predicates.alwaysTrue();
+    }
+    
+    /**
+     * Get the condition to control activation of this filter.
+     * 
+     * @return condition
+     */
+    @Nonnull public Predicate<ServletRequest> getActivationCondition() {
+        return activationCondition;
+    }
+    
+    /**
+     * Set the condition to control activation of this filter.
+     * 
+     * @param condition run condition
+     */
+    public void setActivationCondition(@Nonnull Predicate<ServletRequest> condition) {
+        activationCondition = Constraint.isNotNull(condition, "Run condition cannot be null");
+    }
+    
+    /** {@inheritDoc} */
+    public void init(final FilterConfig filterConfig) throws ServletException {
+    }
+
+    /** {@inheritDoc} */
+    public void destroy() {
+    }
+
+    /** {@inheritDoc} */
+    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+            throws IOException, ServletException {
+        
+        if (activationCondition.test(request)) {
+            runFilter(request, response, chain);
+            return;
+        }
+
+        chain.doFilter(request, response);
+        return;
+    }
+    
+    /**
+     * Subclasses should override this method to be called when the filter is directed to activate.
+     * 
+     * @param request servlet request
+     * @param response servlet response
+     * @param chain filter chain
+     * 
+     * @throws ServletException on error 
+     * @throws IOException on error
+     */
+    protected abstract void runFilter(@Nonnull final ServletRequest request, @Nonnull final ServletResponse response,
+            @Nonnull final FilterChain chain) throws IOException, ServletException;
+    
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/net/HttpServletSupport.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/HttpServletSupport.java
similarity index 98%
rename from shib-networking/src/main/java/net/shibboleth/shared/net/HttpServletSupport.java
rename to shib-networking/src/main/java/net/shibboleth/shared/servlet/HttpServletSupport.java
index b5240253..fabe4a71 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/net/HttpServletSupport.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/HttpServletSupport.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net;
+package net.shibboleth.shared.servlet;
 
 import java.net.URI;
 import java.util.Collections;
@@ -36,6 +36,7 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.net.MediaTypeSupport;
 import net.shibboleth.shared.primitive.StringSupport;
 
 /** Utilities for working with HTTP Servlet requests and responses. */
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/HttpServletRequestResponseContext.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/HttpServletRequestResponseContext.java
similarity index 90%
rename from shib-networking/src/main/java/net/shibboleth/shared/net/impl/HttpServletRequestResponseContext.java
rename to shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/HttpServletRequestResponseContext.java
index 9e846037..60bccef1 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/HttpServletRequestResponseContext.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/HttpServletRequestResponseContext.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net.impl;
+package net.shibboleth.shared.servlet.impl;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -23,14 +23,13 @@ import javax.annotation.Nullable;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.utilities.java.support.net.RequestResponseContextFilter;
 
 /**
  * Class which holds and makes available the current HTTP servlet request and response via ThreadLocal storage.
  * 
  * <p>
- * See also {@link RequestResponseContextFilter}, which is a Java Servlet {@link jakarta.servlet.Filter}-based way
- * to populate and clean up this context in a servlet container.
+ * See also net.shibboleth.shared.spring.servlet.impl.RequestResponseContextFilter, a Java Servlet
+ * {@link jakarta.servlet.Filter}-based way to populate and clean up this context in a servlet container.
  * </p>
  */
 public final class HttpServletRequestResponseContext {
@@ -86,4 +85,4 @@ public final class HttpServletRequestResponseContext {
         return currentResponse.get();
     }
 
-}
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/RequestURLPrefixPredicate.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/RequestURLPrefixPredicate.java
new file mode 100644
index 00000000..380b252a
--- /dev/null
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/RequestURLPrefixPredicate.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.shared.servlet.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.component.AbstractInitializableComponent;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * Predicate based on comparing a request URL to a set of matching prefixes. 
+ */
+public class RequestURLPrefixPredicate extends AbstractInitializableComponent implements Predicate<ServletRequest> {
+
+    /** Prefixes to check for. */
+    @Nonnull @NonnullElements public Collection<String> matchingPrefixes;
+
+    /** Constructor. */
+    public RequestURLPrefixPredicate() {
+        matchingPrefixes = Collections.emptyList();
+    }
+    
+    /**
+     * Set matching URL prefixes.
+     * 
+     * @param prefixes URL prefixes
+     */
+    public void setMatchingPrefixes(@Nullable @NonnullElements Collection<String> prefixes) {
+        checkSetterPreconditions();
+        
+        if (prefixes != null) {
+            matchingPrefixes = StringSupport.normalizeStringCollection(prefixes);
+        } else {
+            matchingPrefixes = Collections.emptyList();
+        }
+    }
+    
+    /** {@inheritDoc} */
+    public boolean test(@Nullable final ServletRequest input) {
+        checkComponentActive();
+
+        if (input instanceof HttpServletRequest) {
+            final String uri = ((HttpServletRequest) input).getRequestURI();
+            for (final String s : matchingPrefixes) {
+                if (uri.startsWith(input.getServletContext().getContextPath() +  s)) {
+                    return true;
+                }
+            }
+        }
+        
+        return false;
+    }
+
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/StubbedFilter.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/StubbedFilter.java
new file mode 100644
index 00000000..7c60e97e
--- /dev/null
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/StubbedFilter.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.shared.servlet.impl;
+
+import java.io.IOException;
+
+import javax.annotation.Nullable;
+
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import net.shibboleth.shared.annotation.ParameterName;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.primitive.DeprecationSupport;
+import net.shibboleth.shared.primitive.DeprecationSupport.ObjectType;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * Legacy stub for compatibility.
+ */
+public class StubbedFilter implements Filter {
+    
+    @Nullable @NotEmpty String className;
+    
+    /** Constructor. */
+    public StubbedFilter() {
+        this(null);
+    }
+    
+    /**
+     * Constructor.
+     *
+     * @param name overrides class name for warning messages
+     */
+    public StubbedFilter(@Nullable @NotEmpty @ParameterName(name="name") final String name) {
+        className = StringSupport.trimOrNull(name);
+        if (className == null) {
+            className = "Servlet Filter '" + getClass().getName() + "'";
+        }
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        DeprecationSupport.warn(ObjectType.CONFIGURATION, className, "edit-webapp/WEB-INF/web.xml", null);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException {
+        DeprecationSupport.warnOnce(ObjectType.CONFIGURATION, className, "edit-webapp/WEB-INF/web.xml", null);
+        chain.doFilter(request, response);
+    }
+
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestProxy.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestProxy.java
similarity index 99%
rename from shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestProxy.java
rename to shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestProxy.java
index 7504f356..0d684b09 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestProxy.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestProxy.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net.impl;
+package net.shibboleth.shared.servlet.impl;
 
 import java.io.BufferedReader;
 import java.io.IOException;
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestSupplier.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestSupplier.java
similarity index 97%
rename from shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestSupplier.java
rename to shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestSupplier.java
index 45901d08..6a5a2ebb 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestSupplier.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestSupplier.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net.impl;
+package net.shibboleth.shared.servlet.impl;
 
 import java.util.function.Supplier;
 
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseProxy.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseProxy.java
similarity index 99%
rename from shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseProxy.java
rename to shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseProxy.java
index 572682b7..2952c110 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseProxy.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseProxy.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net.impl;
+package net.shibboleth.shared.servlet.impl;
 
 import java.io.IOException;
 import java.io.PrintWriter;
diff --git a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseSupplier.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseSupplier.java
similarity index 97%
rename from shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseSupplier.java
rename to shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseSupplier.java
index e6bd43e9..2d6f4d75 100644
--- a/shib-networking/src/main/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseSupplier.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseSupplier.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net.impl;
+package net.shibboleth.shared.servlet.impl;
 
 import java.util.function.Supplier;
 
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/package-info.java
similarity index 88%
copy from shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
copy to shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/package-info.java
index deb616a2..868a1bb7 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/impl/package-info.java
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
-/** Classes for working with HTTP URLs and the protocol. */
-
-package net.shibboleth.utilities.java.support.net;
\ No newline at end of file
+/**
+ * Java Servlet specification implementation classes.
+ */
+package net.shibboleth.shared.servlet.impl;
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java b/shib-networking/src/main/java/net/shibboleth/shared/servlet/package-info.java
similarity index 88%
copy from shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
copy to shib-networking/src/main/java/net/shibboleth/shared/servlet/package-info.java
index deb616a2..0d9e7aae 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
+++ b/shib-networking/src/main/java/net/shibboleth/shared/servlet/package-info.java
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
-/** Classes for working with HTTP URLs and the protocol. */
-
-package net.shibboleth.utilities.java.support.net;
\ No newline at end of file
+/**
+ * Java servlet specification APIs.
+ */
+package net.shibboleth.shared.servlet;
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/CookieBufferingFilter.java b/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/CookieBufferingFilter.java
index d9d82985..1b81e380 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/CookieBufferingFilter.java
+++ b/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/CookieBufferingFilter.java
@@ -17,136 +17,11 @@
 
 package net.shibboleth.utilities.java.support.net;
 
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
-import jakarta.servlet.Filter;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.FilterConfig;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.ServletOutputStream;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.ServletResponse;
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpServletResponseWrapper;
-import net.shibboleth.shared.annotation.constraint.Live;
-import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.servlet.impl.StubbedFilter;
 
 /**
- * Implementation of an HTTP servlet {@link Filter} which wraps the {@link HttpServletResponse} via
- * {@link CookieBufferingHttpServletResponseProxy} to ensure that only a single cookie of a given name is set.
+ * Legacy stub for compatibility.
  */
-public class CookieBufferingFilter implements Filter {
-
-    /** {@inheritDoc} */
-    public void init(final FilterConfig filterConfig) throws ServletException {
-    }
-
-    /** {@inheritDoc} */
-    public void destroy() {
-    }
-
-    /** {@inheritDoc} */
-    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
-            throws IOException,
-            ServletException {
-
-        if (!(request instanceof HttpServletRequest)) {
-            throw new ServletException("Request is not an instance of HttpServletRequest");
-        }
-
-        if (!(response instanceof HttpServletResponse)) {
-            throw new ServletException("Response is not an instance of HttpServletResponse");
-        }
-
-        chain.doFilter(request, new CookieBufferingHttpServletResponseProxy((HttpServletResponse) response));
-    }
-
-    /**
-     * An implementation of {@link HttpServletResponse} which buffers added cookies to
-     * ensure only a single cookie of a given name is eventually set.
-     */
-    private class CookieBufferingHttpServletResponseProxy extends HttpServletResponseWrapper {
-
-        /** Map of delayed cookie additions. */
-        @Nonnull @NonnullElements private Map<String,Cookie> cookieMap;
-        
-        /**
-         * Constructor.
-         *
-         * @param response the response to delegate to
-         */
-        public CookieBufferingHttpServletResponseProxy(@Nonnull final HttpServletResponse response) {
-            super(response);
-            cookieMap = new HashMap<>();
-        }
-    
-        /** {@inheritDoc} */
-        @Override
-        public void addCookie(final Cookie cookie) {
-            // Guarantees any existing cookie by this name is replaced.
-            cookieMap.put(cookie.getName(), cookie);
-        }
-    
-        /**
-         * Get the map of cookies that will be set.
-         * 
-         * @return map of cookies to be set
-         */
-        @Nonnull @NonnullElements @Live protected Map<String,Cookie> getCookies() {
-            return cookieMap;
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public ServletOutputStream getOutputStream() throws IOException {
-            dumpCookies();
-            return super.getOutputStream();
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public PrintWriter getWriter() throws IOException {
-            dumpCookies();
-            return super.getWriter();
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public void sendError(final int sc, final String msg) throws IOException {
-            dumpCookies();
-            super.sendError(sc, msg);
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public void sendError(final int sc) throws IOException {
-            dumpCookies();
-            super.sendError(sc);
-        }
+public class CookieBufferingFilter extends StubbedFilter {
 
-        /** {@inheritDoc} */
-        @Override
-        public void sendRedirect(final String location) throws IOException {
-            dumpCookies();
-            super.sendRedirect(location);
-        }
-        
-        /**
-         * Transfer cookies added into the real response.
-         */
-        protected void dumpCookies() {
-            for (final Cookie cookie : cookieMap.values()) {
-                ((HttpServletResponse) getResponse()).addCookie(cookie);
-            }
-            cookieMap.clear();
-        }
-    }
-    
-}
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/RequestResponseContextFilter.java b/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/RequestResponseContextFilter.java
index 0d60f2d1..dc6f67dd 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/RequestResponseContextFilter.java
+++ b/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/RequestResponseContextFilter.java
@@ -17,54 +17,11 @@
 
 package net.shibboleth.utilities.java.support.net;
 
-import java.io.IOException;
-
-import jakarta.servlet.Filter;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.FilterConfig;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.ServletResponse;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import net.shibboleth.shared.net.impl.HttpServletRequestResponseContext;
-
+import net.shibboleth.shared.servlet.impl.StubbedFilter;
 
 /**
- * Implementation of an HTTP servlet {@link Filter} which stores the current {@link HttpServletRequest} and
- * {@link HttpServletResponse} being serviced on thread-local storage via the use of holder class
- * {@link HttpServletRequestResponseContext}.
+ * Legacy stub for compatibility.
  */
-public class RequestResponseContextFilter implements Filter {
-
-    /** {@inheritDoc} */
-    public void init(final FilterConfig filterConfig) throws ServletException {
-    }
-
-    /** {@inheritDoc} */
-    public void destroy() {
-    }
-
-    /** {@inheritDoc} */
-    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
-            throws IOException,
-            ServletException {
-
-        if (!(request instanceof HttpServletRequest)) {
-            throw new ServletException("Request is not an instance of HttpServletRequest");
-        }
-
-        if (!(response instanceof HttpServletResponse)) {
-            throw new ServletException("Response is not an instance of HttpServletResponse");
-        }
-
-        try {
-            HttpServletRequestResponseContext.loadCurrent((HttpServletRequest) request, (HttpServletResponse) response);
-            chain.doFilter(request, response);
-        } finally {
-            HttpServletRequestResponseContext.clearCurrent();
-        }
-
-    }
+public class RequestResponseContextFilter extends StubbedFilter {
 
-}
+}
\ No newline at end of file
diff --git a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java b/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
index deb616a2..4fe250e0 100644
--- a/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
+++ b/shib-networking/src/main/java/net/shibboleth/utilities/java/support/net/package-info.java
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
-/** Classes for working with HTTP URLs and the protocol. */
-
+/**
+ * Legacy stubs for compatibility.
+ */
 package net.shibboleth.utilities.java.support.net;
\ No newline at end of file
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/net/HttpServletSupportTest.java b/shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/HttpServletSupportTest.java
similarity index 98%
rename from shib-networking/src/test/java/net/shibboleth/shared/net/HttpServletSupportTest.java
rename to shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/HttpServletSupportTest.java
index 32acba74..0695a1f4 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/net/HttpServletSupportTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/HttpServletSupportTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net;
+package net.shibboleth.shared.servlet.impl;
 
 import java.util.Collections;
 import java.util.List;
@@ -29,6 +29,8 @@ import org.testng.annotations.Test;
 
 import com.google.common.net.MediaType;
 
+import net.shibboleth.shared.servlet.HttpServletSupport;
+
 
 /** {@link HttpServletSupport} unit test. */
 @SuppressWarnings("javadoc")
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestProxyTest.java b/shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestProxyTest.java
similarity index 98%
rename from shib-networking/src/test/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestProxyTest.java
rename to shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestProxyTest.java
index b427a530..5a5183a3 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletRequestProxyTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletRequestProxyTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net.impl;
+package net.shibboleth.shared.servlet.impl;
 
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
diff --git a/shib-networking/src/test/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseProxyTest.java b/shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseProxyTest.java
similarity index 98%
rename from shib-networking/src/test/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseProxyTest.java
rename to shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseProxyTest.java
index 11cb1c8c..aafe0106 100644
--- a/shib-networking/src/test/java/net/shibboleth/shared/net/impl/ThreadLocalHttpServletResponseProxyTest.java
+++ b/shib-networking/src/test/java/net/shibboleth/shared/servlet/impl/ThreadLocalHttpServletResponseProxyTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.shared.net.impl;
+package net.shibboleth.shared.servlet.impl;
 
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/impl/IPRangeAccessControl.java b/shib-security/src/main/java/net/shibboleth/shared/security/impl/IPRangeAccessControl.java
index 56528e73..eb1a87c4 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/impl/IPRangeAccessControl.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/impl/IPRangeAccessControl.java
@@ -33,9 +33,9 @@ import jakarta.servlet.ServletRequest;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
 import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.net.HttpServletSupport;
 import net.shibboleth.shared.net.IPRange;
 import net.shibboleth.shared.security.AccessControl;
+import net.shibboleth.shared.servlet.HttpServletSupport;
 
 /**
  * Simple access control implementation based on IP address checking.
diff --git a/shib-spring/src/main/java/net/shibboleth/shared/spring/util/SpringSupport.java b/shib-spring/src/main/java/net/shibboleth/shared/spring/util/SpringSupport.java
index bdb37cf0..0e97aba6 100644
--- a/shib-spring/src/main/java/net/shibboleth/shared/spring/util/SpringSupport.java
+++ b/shib-spring/src/main/java/net/shibboleth/shared/spring/util/SpringSupport.java
@@ -52,8 +52,8 @@ import jakarta.servlet.http.HttpServletRequest;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.Unmodifiable;
 import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.net.HttpServletSupport;
 import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.servlet.HttpServletSupport;
 import net.shibboleth.shared.spring.context.FilesystemGenericApplicationContext;
 import net.shibboleth.shared.xml.SerializeSupport;
 import net.shibboleth.shared.xml.XMLConstants;

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list