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

markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new 65bb847e56 Treat all URLs and URL patterns in web.xml, annotations, 
etc as decoded
65bb847e56 is described below

commit 65bb847e56c09a6767aac440e63ee177255e10e1
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Aug 11 11:14:52 2026 +0100

    Treat all URLs and URL patterns in web.xml, annotations, etc as decoded
    
    This removes the option to choose to treat them as URL-Encoded or
    URL-Decoded along with all of the supporting code for that feature.
---
 java/org/apache/catalina/Context.java              | 75 +----------------
 .../core/ApplicationFilterRegistration.java        |  8 +-
 .../core/ApplicationServletRegistration.java       | 25 ++----
 java/org/apache/catalina/core/StandardContext.java | 38 +--------
 .../org/apache/catalina/startup/ContextConfig.java | 17 +---
 .../org/apache/catalina/startup/FailedContext.java |  6 --
 .../tomcat/util/descriptor/web/ErrorPage.java      | 19 +----
 .../tomcat/util/descriptor/web/FilterMap.java      | 17 +---
 .../descriptor/web/FragmentJarScannerCallback.java |  6 +-
 .../util/descriptor/web/JspPropertyGroup.java      | 18 +----
 .../tomcat/util/descriptor/web/LoginConfig.java    | 31 +------
 .../util/descriptor/web/SecurityCollection.java    | 18 +----
 .../util/descriptor/web/SecurityConstraint.java    | 21 +----
 .../tomcat/util/descriptor/web/WebRuleSet.java     | 59 ++------------
 .../apache/tomcat/util/descriptor/web/WebXml.java  | 73 ++---------------
 .../tomcat/util/descriptor/web/WebXmlParser.java   | 38 +--------
 .../util/descriptor/web/XmlEncodingBase.java       | 62 --------------
 java/org/apache/tomcat/util/digester/Digester.java | 16 ----
 .../tomcat/util/digester/DocumentProperties.java   | 36 ---------
 .../tomcat/util/digester/LocalStrings.properties   |  1 -
 .../util/digester/LocalStrings_es.properties       |  1 -
 .../util/digester/LocalStrings_fr.properties       |  1 -
 .../util/digester/LocalStrings_ja.properties       |  1 -
 .../util/digester/LocalStrings_ko.properties       |  1 -
 .../util/digester/LocalStrings_ru.properties       | 19 -----
 .../util/digester/LocalStrings_zh_CN.properties    |  1 -
 .../core/TestApplicationFilterRegistration.java    | 15 +---
 .../core/TestApplicationServletRegistration.java   | 15 +---
 .../startup/TestContextConfigAnnotation.java       | 19 +----
 .../apache/catalina/startup/TestUrlPatterns.java   | 65 +++++++++++++++
 .../TestUrlPatternsProvidedInDecodedForm.java      | 94 ----------------------
 test/org/apache/tomcat/unittest/TesterContext.java |  7 --
 .../tomcat/util/descriptor/web/TestWebXml.java     | 43 ----------
 .../util/descriptor/web/TestWebXmlParser.java      | 30 +++----
 test/webapp-url-patterns/WEB-INF/web.xml           |  7 +-
 webapps/docs/changelog.xml                         | 24 +++---
 webapps/docs/config/context.xml                    | 16 ----
 37 files changed, 141 insertions(+), 802 deletions(-)

diff --git a/java/org/apache/catalina/Context.java 
b/java/org/apache/catalina/Context.java
index 1f8a96740b..c403dad8f3 100644
--- a/java/org/apache/catalina/Context.java
+++ b/java/org/apache/catalina/Context.java
@@ -920,53 +920,12 @@ public interface Context extends Container, ContextBind {
      * Add a new servlet mapping, replacing any existing mapping for the 
specified pattern.
      * <p>
      * No URL-decoding of the pattern will be performed.
-     * <p>
-     * Implementation Note: As of Tomcat 12 this default implementation will 
be removed. Implementors are encouraged to
-     * provide their own implementation of this method before then.
      *
      * @param pattern     URL pattern to be mapped
      * @param name        Name of the corresponding servlet to execute
      * @param jspWildcard true if name identifies the JspServlet and pattern 
contains a wildcard; false otherwise
      */
-    default void addServletMapping(String pattern, String name, boolean 
jspWildcard) {
-        addServletMappingDecoded(pattern, name, jspWildcard);
-    }
-
-
-    /**
-     * Add a new servlet mapping, replacing any existing mapping for the 
specified pattern.
-     * <p>
-     * No URL-decoding of the pattern will be performed.
-     *
-     * @param pattern URL pattern to be mapped
-     * @param name    Name of the corresponding servlet to execute
-     *
-     * @deprecated Will be removed in Tomcat 12 onwards.
-     */
-    @Deprecated
-    default void addServletMappingDecoded(String pattern, String name) {
-        addServletMappingDecoded(pattern, name, false);
-    }
-
-
-    /**
-     * Add a new servlet mapping, replacing any existing mapping for the 
specified pattern.
-     * <p>
-     * No URL-decoding of the pattern will be performed.
-     *
-     * @param pattern     URL pattern to be mapped
-     * @param name        Name of the corresponding servlet to execute
-     * @param jspWildcard true if name identifies the JspServlet and pattern 
contains a wildcard; false otherwise
-     *
-     * @deprecated This method will be removed in Tomcat 12. Implementors are 
expected to implement this method without
-     *                 delegating the implementation to one of the other 
{@code addServletMapping*} methods as that may
-     *                 trigger infinite loops. Once this method has been 
removed from the interface, implementors may
-     *                 wish to move their implementation of this method to
-     *                 {@link Context#addServletMapping(String, String, 
boolean)} and remove their implementation of
-     *                 this method.
-     */
-    @Deprecated
-    void addServletMappingDecoded(String pattern, String name, boolean 
jspWildcard);
+    void addServletMapping(String pattern, String name, boolean jspWildcard);
 
 
     /**
@@ -2090,36 +2049,4 @@ public interface Context extends Container, ContextBind {
     default EncodedSolidusHandling getEncodedSolidusHandlingEnum() {
         return EncodedSolidusHandling.REJECT;
     }
-
-
-    /**
-     * Configures whether the Context expects URLs and URL patterns provided 
in web.xml, annotations and their
-     * programmatic equivalents to be in URL-decoded form.
-     *
-     * @param urlPatternsProvidedInDecodedForm {@code true} if URLs and URL 
patterns are expected to be decoded.
-     *                                             {@code false} if they are 
expected to be URL-encoded (i.e.
-     *                                             {@code %nn} encoding)
-     *
-     * @deprecated This is a transitional setting that will be removed in 
Tomcat 12 where it will be hard-coded to
-     *                 {@code true}
-     */
-    @Deprecated
-    default void setUrlPatternsProvidedInDecodedForm(boolean 
urlPatternsProvidedInDecodedForm) {
-        throw new UnsupportedOperationException();
-    }
-
-
-    /**
-     * Does this Context expect URLs and URL patterns provided in web.xml, 
annotations and their programmatic
-     * equivalents to be in URL-decoded form?
-     *
-     * @return This default implementation returns {@code false}
-     *
-     * @deprecated This is a transitional setting that will be removed in 
Tomcat 12 where it will be hard-coded to
-     *                 {@code true}
-     */
-    @Deprecated
-    default boolean getUrlPatternsProvidedInDecodedForm() {
-        return false;
-    }
 }
diff --git a/java/org/apache/catalina/core/ApplicationFilterRegistration.java 
b/java/org/apache/catalina/core/ApplicationFilterRegistration.java
index d824574ca8..af4c548b08 100644
--- a/java/org/apache/catalina/core/ApplicationFilterRegistration.java
+++ b/java/org/apache/catalina/core/ApplicationFilterRegistration.java
@@ -89,7 +89,6 @@ public class ApplicationFilterRegistration implements 
FilterRegistration.Dynamic
         }
     }
 
-    @SuppressWarnings("deprecation")
     @Override
     public void addMappingForUrlPatterns(EnumSet<DispatcherType> 
dispatcherTypes, boolean isMatchAfter,
             String... urlPatterns) {
@@ -109,12 +108,7 @@ public class ApplicationFilterRegistration implements 
FilterRegistration.Dynamic
                 if (urlPattern == null) {
                     throw new 
IllegalArgumentException(sm.getString("applicationFilterRegistration.nullUrlPattern"));
                 }
-                if (context.getUrlPatternsProvidedInDecodedForm()) {
-                    filterMap.addURLPatternDecoded(urlPattern);
-                } else {
-                    // % decoded (if required) using UTF-8
-                    filterMap.addURLPattern(urlPattern);
-                }
+                filterMap.addURLPattern(urlPattern);
             }
 
             if (isMatchAfter) {
diff --git a/java/org/apache/catalina/core/ApplicationServletRegistration.java 
b/java/org/apache/catalina/core/ApplicationServletRegistration.java
index 981ce6f50e..56fe2b5d2b 100644
--- a/java/org/apache/catalina/core/ApplicationServletRegistration.java
+++ b/java/org/apache/catalina/core/ApplicationServletRegistration.java
@@ -16,7 +16,6 @@
  */
 package org.apache.catalina.core;
 
-import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -31,7 +30,6 @@ import org.apache.catalina.Context;
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.Wrapper;
 import org.apache.catalina.util.ParameterMap;
-import org.apache.tomcat.util.buf.UDecoder;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -167,30 +165,20 @@ public class ApplicationServletRegistration implements 
ServletRegistration.Dynam
     }
 
 
-    @SuppressWarnings("deprecation")
     @Override
     public Set<String> addMapping(String... urlPatterns) {
         if (urlPatterns == null) {
             return Collections.emptySet();
         }
 
-        String[] decodedUrlPatterns = new String[urlPatterns.length];
+        Set<String> conflicts = new HashSet<>();
+        Set<String> overrides = new HashSet<>();
+
         for (int i = 0; i < urlPatterns.length; i++) {
             if (urlPatterns[i] == null) {
                 throw new 
IllegalArgumentException(sm.getString("applicationServletRegistration.nullUrlPattern"));
             }
-            if (context.getUrlPatternsProvidedInDecodedForm()) {
-                decodedUrlPatterns[i] = urlPatterns[i];
-            } else {
-                decodedUrlPatterns[i] = UDecoder.URLDecode(urlPatterns[i], 
StandardCharsets.UTF_8);
-            }
-        }
-
-        Set<String> conflicts = new HashSet<>();
-        Set<String> overrides = new HashSet<>();
-
-        for (int i = 0; i < decodedUrlPatterns.length; i++) {
-            String wrapperName = 
context.findServletMapping(decodedUrlPatterns[i]);
+            String wrapperName = context.findServletMapping(urlPatterns[i]);
             if (wrapperName != null) {
                 Wrapper wrapper = (Wrapper) context.findChild(wrapperName);
                 if (wrapper.isOverridable()) {
@@ -199,9 +187,8 @@ public class ApplicationServletRegistration implements 
ServletRegistration.Dynam
                      * Changes as a result of this method should be all or 
nothing so note the overrides until the check
                      * for conflicts has completed.
                      */
-                    overrides.add(decodedUrlPatterns[i]);
+                    overrides.add(urlPatterns[i]);
                 } else {
-                    // The conflicts list the original URL patterns passed
                     conflicts.add(urlPatterns[i]);
                 }
             }
@@ -214,7 +201,7 @@ public class ApplicationServletRegistration implements 
ServletRegistration.Dynam
         // No conflicts, remove the mappings that are about to be overridden
         overrides.forEach(p -> context.removeServletMapping(p));
 
-        for (String urlPattern : decodedUrlPatterns) {
+        for (String urlPattern : urlPatterns) {
             context.addServletMapping(urlPattern, wrapper.getName());
         }
 
diff --git a/java/org/apache/catalina/core/StandardContext.java 
b/java/org/apache/catalina/core/StandardContext.java
index bce91cf716..58e3c48618 100644
--- a/java/org/apache/catalina/core/StandardContext.java
+++ b/java/org/apache/catalina/core/StandardContext.java
@@ -810,29 +810,9 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
 
     private EncodedSolidusHandling encodedSolidusHandling = 
EncodedSolidusHandling.REJECT;
 
-    // Defaults to false for backwards compatibility but will be hard-coded to 
true for Tomcat 12 onwards.
-    private boolean urlPatternsProvidedInDecodedForm = false;
-
 
     // ----------------------------------------------------- Context Properties
 
-    @Override
-    public void setUrlPatternsProvidedInDecodedForm(boolean 
urlPatternsProvidedInDecodedForm) {
-        this.urlPatternsProvidedInDecodedForm = 
urlPatternsProvidedInDecodedForm;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     *
-     * @return {@code true} if URLs and URL patterns are expected in 
URL-decoded form, otherwise {@code false}
-     */
-    @Override
-    public boolean getUrlPatternsProvidedInDecodedForm() {
-        return urlPatternsProvidedInDecodedForm;
-    }
-
-
     @Override
     public String getEncodedReverseSolidusHandling() {
         return encodedReverseSolidusHandling.getValue();
@@ -2012,7 +1992,6 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
     }
 
 
-    @SuppressWarnings("deprecation")
     @Override
     public void setLoginConfig(LoginConfig config) {
 
@@ -2026,8 +2005,7 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
                 if (log.isDebugEnabled()) {
                     
log.debug(sm.getString("standardContext.loginConfig.loginWarning", loginPage));
                 }
-                // Use decoded variant to avoid double decoding
-                config.setLoginPageDecoded("/" + loginPage);
+                config.setLoginPage("/" + loginPage);
             } else {
                 throw new 
IllegalArgumentException(sm.getString("standardContext.loginConfig.loginPage", 
loginPage));
             }
@@ -2038,8 +2016,7 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
                 if (log.isDebugEnabled()) {
                     
log.debug(sm.getString("standardContext.loginConfig.errorWarning", errorPage));
                 }
-                // Use decoded variant to avoid double decoding
-                config.setErrorPageDecoded("/" + errorPage);
+                config.setErrorPage("/" + errorPage);
             } else {
                 throw new 
IllegalArgumentException(sm.getString("standardContext.loginConfig.errorPage", 
errorPage));
             }
@@ -2873,7 +2850,6 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
     }
 
 
-    @SuppressWarnings("deprecation")
     @Override
     public void addErrorPage(ErrorPage errorPage) {
         // Validate the input parameters
@@ -2886,8 +2862,7 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
                 if (log.isDebugEnabled()) {
                     
log.debug(sm.getString("standardContext.errorPage.warning", location));
                 }
-                // Error page is already decoded, so don't decode a second time
-                errorPage.setLocationDecoded("/" + location);
+                errorPage.setLocation("/" + location);
             } else {
                 throw new 
IllegalArgumentException(sm.getString("standardContext.errorPage.error", 
location));
             }
@@ -3025,13 +3000,6 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
 
     @Override
     public void addServletMapping(String pattern, String name, boolean 
jspWildCard) {
-        addServletMappingDecoded(pattern, name, jspWildCard);
-    }
-
-
-    @Override
-    @Deprecated
-    public void addServletMappingDecoded(String pattern, String name, boolean 
jspWildCard) {
         // Validate the proposed mapping
         if (findChild(name) == null) {
             throw new 
IllegalArgumentException(sm.getString("standardContext.servletMap.name", name));
diff --git a/java/org/apache/catalina/startup/ContextConfig.java 
b/java/org/apache/catalina/startup/ContextConfig.java
index 08e3b5b1c1..660c9473f9 100644
--- a/java/org/apache/catalina/startup/ContextConfig.java
+++ b/java/org/apache/catalina/startup/ContextConfig.java
@@ -1311,9 +1311,8 @@ public class ContextConfig implements LifecycleListener {
          * - If an SCI has a @HandlesType annotation then all classes (except 
those in JARs excluded from an absolute
          * ordering) need to be scanned to check if they match.
          */
-        @SuppressWarnings("deprecation")
         WebXmlParser webXmlParser = new 
WebXmlParser(context.getXmlNamespaceAware(), context.getXmlValidation(),
-                context.getXmlBlockExternal(), 
context.getUrlPatternsProvidedInDecodedForm());
+                context.getXmlBlockExternal());
 
         Set<WebXml> defaults = new HashSet<>();
         defaults.add(getDefaultWebXmlFragment(webXmlParser));
@@ -1825,9 +1824,8 @@ public class ContextConfig implements LifecycleListener {
      *
      * @return a new WebXml instance
      */
-    @SuppressWarnings("deprecation")
     protected WebXml createWebXml() {
-        return new WebXml(context.getUrlPatternsProvidedInDecodedForm());
+        return new WebXml();
     }
 
     /**
@@ -2154,8 +2152,7 @@ public class ContextConfig implements LifecycleListener {
         // - this fragment has metadata-complete="true"
         boolean htOnly = handlesTypesOnly || !fragment.getWebappJar() || 
fragment.isMetadataComplete();
 
-        @SuppressWarnings("deprecation")
-        WebXml annotations = new 
WebXml(context.getUrlPatternsProvidedInDecodedForm());
+        WebXml annotations = new WebXml();
         // no impact on distributable
         annotations.setDistributable(true);
         URL url = fragment.getURL();
@@ -2702,7 +2699,6 @@ public class ContextConfig implements LifecycleListener {
      * @param ae        The filter annotation
      * @param fragment  The corresponding fragment
      */
-    @SuppressWarnings("deprecation")
     protected void processAnnotationWebFilter(String className, 
AnnotationEntry ae, WebXml fragment) {
         String filterName = null;
         // must search for name s. Spec Servlet API 3.0 - 8.2.3.3.n.ii page 81
@@ -2746,12 +2742,7 @@ public class ContextConfig implements LifecycleListener {
                 urlPatterns = processAnnotationsStringArray(evp.getValue());
                 urlPatternsSet = urlPatterns.length > 0;
                 for (String urlPattern : urlPatterns) {
-                    if (fragment.getUrlPatternsProvidedInDecodedForm()) {
-                        filterMap.addURLPatternDecoded(urlPattern);
-                    } else {
-                        // % decoded (if required) using UTF-8
-                        filterMap.addURLPattern(urlPattern);
-                    }
+                    filterMap.addURLPattern(urlPattern);
                 }
             } else if ("servletNames".equals(name)) {
                 String[] servletNames = 
processAnnotationsStringArray(evp.getValue());
diff --git a/java/org/apache/catalina/startup/FailedContext.java 
b/java/org/apache/catalina/startup/FailedContext.java
index 65511d5d06..4782b2fee3 100644
--- a/java/org/apache/catalina/startup/FailedContext.java
+++ b/java/org/apache/catalina/startup/FailedContext.java
@@ -982,12 +982,6 @@ public class FailedContext extends LifecycleMBeanBase 
implements Context {
         // NO-OP
     }
 
-    @Override
-    @Deprecated
-    public void addServletMappingDecoded(String pattern, String name, boolean 
jspWildcard) {
-        // NO-OP
-    }
-
     @Override
     public String findServletMapping(String pattern) {
         return null;
diff --git a/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java 
b/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java
index a1db5fbb4d..d2fb728ef0 100644
--- a/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java
+++ b/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java
@@ -20,14 +20,11 @@ import java.io.Serial;
 import java.io.Serializable;
 import java.util.Objects;
 
-import org.apache.tomcat.util.buf.UDecoder;
-
 /**
  * Representation of an error page element for a web application, as 
represented in a <code>&lt;error-page&gt;</code>
  * element in the deployment descriptor.
  */
-@SuppressWarnings("deprecation")
-public class ErrorPage extends XmlEncodingBase implements Serializable {
+public class ErrorPage implements Serializable {
 
     /**
      * Default constructor for ErrorPage.
@@ -135,26 +132,12 @@ public class ErrorPage extends XmlEncodingBase implements 
Serializable {
      * @param location The new location
      */
     public void setLocation(String location) {
-        this.location = UDecoder.URLDecode(location, getCharset());
-    }
-
-
-    /**
-     * Set the already URL decoded location.
-     *
-     * @param location The new location
-     *
-     * @deprecated This method will be removed in Tomcat 12
-     */
-    @Deprecated
-    public void setLocationDecoded(String location) {
         this.location = location;
     }
 
 
     // --------------------------------------------------------- Public Methods
 
-
     /**
      * Render a String representation of this object.
      */
diff --git a/java/org/apache/tomcat/util/descriptor/web/FilterMap.java 
b/java/org/apache/tomcat/util/descriptor/web/FilterMap.java
index 07d703f992..f6c147fb7d 100644
--- a/java/org/apache/tomcat/util/descriptor/web/FilterMap.java
+++ b/java/org/apache/tomcat/util/descriptor/web/FilterMap.java
@@ -24,15 +24,12 @@ import java.util.Locale;
 
 import jakarta.servlet.DispatcherType;
 
-import org.apache.tomcat.util.buf.UDecoder;
-
 /**
  * Representation of a filter mapping for a web application, as represented in 
a <code>&lt;filter-mapping&gt;</code>
  * element in the deployment descriptor. Each filter mapping must contain a 
filter name plus either a URL pattern or a
  * servlet name.
  */
-@SuppressWarnings("deprecation")
-public class FilterMap extends XmlEncodingBase implements Serializable {
+public class FilterMap implements Serializable {
 
     /**
      * Default constructor for FilterMap.
@@ -191,18 +188,6 @@ public class FilterMap extends XmlEncodingBase implements 
Serializable {
      * @param urlPattern The URL pattern to add
      */
     public void addURLPattern(String urlPattern) {
-        addURLPatternDecoded(UDecoder.URLDecode(urlPattern, getCharset()));
-    }
-
-    /**
-     * Adds a decoded URL pattern to the set of URL patterns this mapping 
matches.
-     *
-     * @param urlPattern The decoded URL pattern to add
-     *
-     * @deprecated This method will be removed in Tomcat 12 onwards
-     */
-    @Deprecated
-    public void addURLPatternDecoded(String urlPattern) {
         if ("*".equals(urlPattern)) {
             this.matchAllUrlPatterns = true;
         } else {
diff --git 
a/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java 
b/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java
index 117a12df47..78eb1d9c76 100644
--- a/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java
+++ b/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java
@@ -58,8 +58,7 @@ public class FragmentJarScannerCallback implements 
JarScannerCallback {
     public void scan(Jar jar, String webappPath, boolean isWebapp) throws 
IOException {
 
         InputStream is = null;
-        @SuppressWarnings("deprecation")
-        WebXml fragment = new 
WebXml(webXmlParser.getUrlPatternsProvidedInDecodedForm());
+        WebXml fragment = new WebXml();
         fragment.setWebappJar(isWebapp);
         fragment.setDelegate(delegate);
 
@@ -105,8 +104,7 @@ public class FragmentJarScannerCallback implements 
JarScannerCallback {
     @Override
     public void scan(File file, String webappPath, boolean isWebapp) throws 
IOException {
 
-        @SuppressWarnings("deprecation")
-        WebXml fragment = new 
WebXml(webXmlParser.getUrlPatternsProvidedInDecodedForm());
+        WebXml fragment = new WebXml();
         fragment.setWebappJar(isWebapp);
         fragment.setDelegate(delegate);
 
diff --git a/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java 
b/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java
index 42b4c0bb58..cc806a69c4 100644
--- a/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java
+++ b/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java
@@ -21,13 +21,10 @@ import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
-import org.apache.tomcat.util.buf.UDecoder;
-
 /**
  * Representation of a jsp-property-group element in web.xml.
  */
-@SuppressWarnings("deprecation")
-public class JspPropertyGroup extends XmlEncodingBase {
+public class JspPropertyGroup {
 
     /**
      * Creates a new JspPropertyGroup instance with default settings.
@@ -219,22 +216,11 @@ public class JspPropertyGroup extends XmlEncodingBase {
     private final LinkedHashSet<String> urlPattern = new LinkedHashSet<>();
 
     /**
-     * Adds a URL pattern (URL-decoded) to this property group.
+     * Adds a URL pattern to this property group.
      *
      * @param urlPattern the URL pattern to add
      */
     public void addUrlPattern(String urlPattern) {
-        addUrlPatternDecoded(UDecoder.URLDecode(urlPattern, getCharset()));
-    }
-
-    /**
-     * Adds a pre-decoded URL pattern to this property group.
-     *
-     * @param urlPattern the decoded URL pattern to add
-     * @deprecated This method will be removed in Tomcat 12
-     */
-    @Deprecated
-    public void addUrlPatternDecoded(String urlPattern) {
         this.urlPattern.add(urlPattern);
     }
 
diff --git a/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java 
b/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java
index bd3f09310f..4d8bef7e71 100644
--- a/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java
+++ b/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java
@@ -19,14 +19,11 @@ package org.apache.tomcat.util.descriptor.web;
 import java.io.Serial;
 import java.io.Serializable;
 
-import org.apache.tomcat.util.buf.UDecoder;
-
 /**
  * Representation of a login configuration element for a web application, as 
represented in a
  * <code>&lt;login-config&gt;</code> element in the deployment descriptor.
  */
-@SuppressWarnings("deprecation")
-public class LoginConfig extends XmlEncodingBase implements Serializable {
+public class LoginConfig implements Serializable {
 
 
     @Serial
@@ -111,19 +108,6 @@ public class LoginConfig extends XmlEncodingBase 
implements Serializable {
      * @param errorPage the errorPage to set
      */
     public void setErrorPage(String errorPage) {
-        this.errorPage = UDecoder.URLDecode(errorPage, getCharset());
-    }
-
-
-    /**
-     * Set the already decoded error page URI.
-     *
-     * @param errorPage the decoded errorPage to set
-     *
-     * @deprecated Will be removed in Tomcat 12 onwards
-     */
-    @Deprecated
-    public void setErrorPageDecoded(String errorPage) {
         this.errorPage = errorPage;
     }
 
@@ -148,19 +132,6 @@ public class LoginConfig extends XmlEncodingBase 
implements Serializable {
      * @param loginPage the loginPage to set
      */
     public void setLoginPage(String loginPage) {
-        this.loginPage = UDecoder.URLDecode(loginPage, getCharset());
-    }
-
-
-    /**
-     * Set the already decoded login page URI.
-     *
-     * @param loginPage the decoded loginPage to set
-     *
-     * @deprecated Will be removed in Tomcat 12 onwards
-     */
-    @Deprecated
-    public void setLoginPageDecoded(String loginPage) {
         this.loginPage = loginPage;
     }
 
diff --git a/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java 
b/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java
index 97642b73aa..7fdadc92f1 100644
--- a/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java
+++ b/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java
@@ -20,8 +20,6 @@ import java.io.Serial;
 import java.io.Serializable;
 import java.util.Arrays;
 
-import org.apache.tomcat.util.buf.UDecoder;
-
 
 /**
  * Representation of a web resource collection for a web application's 
security constraint, as represented in a
@@ -31,8 +29,7 @@ import org.apache.tomcat.util.buf.UDecoder;
  * single thread, before the instance is made visible to the remainder of the 
application. After that, only read access
  * is expected. Therefore, none of the read and write access within this class 
is synchronized.
  */
-@SuppressWarnings("deprecation")
-public class SecurityCollection extends XmlEncodingBase implements 
Serializable {
+public class SecurityCollection implements Serializable {
 
     @Serial
     private static final long serialVersionUID = 1L;
@@ -205,19 +202,6 @@ public class SecurityCollection extends XmlEncodingBase 
implements Serializable
      * @param pattern The pattern
      */
     public void addPattern(String pattern) {
-        addPatternDecoded(UDecoder.URLDecode(pattern, getCharset()));
-    }
-
-    /**
-     * Add a URL pattern (already decoded) to be part of this web resource 
collection.
-     *
-     * @param pattern The decoded pattern
-     *
-     * @deprecated Will be removed in Tomcat 12 onwards
-     */
-    @Deprecated
-    public void addPatternDecoded(String pattern) {
-
         if (pattern == null) {
             return;
         }
diff --git a/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java 
b/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java
index 10c6069947..0e734dad47 100644
--- a/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java
+++ b/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java
@@ -18,7 +18,6 @@ package org.apache.tomcat.util.descriptor.web;
 
 import java.io.Serial;
 import java.io.Serializable;
-import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -46,8 +45,7 @@ import org.apache.tomcat.util.res.StringManager;
  * single thread, before the instance is made visible to the remainder of the 
application. After that, only read access
  * is expected. Therefore, none of the read and write access within this class 
is synchronized.
  */
-@SuppressWarnings("deprecation")
-public class SecurityConstraint extends XmlEncodingBase implements 
Serializable {
+public class SecurityConstraint implements Serializable {
 
     @Serial
     private static final long serialVersionUID = 1L;
@@ -270,15 +268,6 @@ public class SecurityConstraint extends XmlEncodingBase 
implements Serializable
     }
 
 
-    @Override
-    public void setCharset(Charset charset) {
-        super.setCharset(charset);
-        for (SecurityCollection collection : collections) {
-            collection.setCharset(getCharset());
-        }
-    }
-
-
     /**
      * Add a new web resource collection to those protected by this security 
constraint.
      *
@@ -290,8 +279,6 @@ public class SecurityConstraint extends XmlEncodingBase 
implements Serializable
             return;
         }
 
-        collection.setCharset(getCharset());
-
         SecurityCollection[] results = Arrays.copyOf(collections, 
collections.length + 1);
         results[collections.length] = collection;
         collections = results;
@@ -611,7 +598,7 @@ public class SecurityConstraint extends XmlEncodingBase 
implements Serializable
         }
 
         if (create) {
-            collection.addPatternDecoded(urlPattern);
+            collection.addPattern(urlPattern);
             constraint.addCollection(collection);
             return constraint;
         }
@@ -705,7 +692,7 @@ public class SecurityConstraint extends XmlEncodingBase 
implements Serializable
                     for (String method : methods) {
                         collection.addOmittedMethod(method);
                     }
-                    collection.addPatternDecoded(pattern);
+                    collection.addPattern(pattern);
                     collection.setName("deny-uncovered-http-methods");
                     SecurityConstraint constraint = new SecurityConstraint();
                     constraint.setAuthConstraint(true);
@@ -752,7 +739,7 @@ public class SecurityConstraint extends XmlEncodingBase 
implements Serializable
                 for (String method : omittedMethods) {
                     collection.addMethod(method);
                 }
-                collection.addPatternDecoded(pattern);
+                collection.addPattern(pattern);
                 collection.setName("deny-uncovered-http-methods");
                 SecurityConstraint constraint = new SecurityConstraint();
                 constraint.setAuthConstraint(true);
diff --git a/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java 
b/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java
index 3f5da0c700..3fcce66220 100644
--- a/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java
+++ b/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java
@@ -96,9 +96,6 @@ public class WebRuleSet implements RuleSet {
     protected final RelativeOrderingRule relativeOrdering;
 
 
-    private final boolean urlPatternsProvidedInDecodedForm;
-
-
     // ------------------------------------------------------------ Constructor
 
     /**
@@ -131,22 +128,6 @@ public class WebRuleSet implements RuleSet {
      * @param fragment <code>true</code> if this is a web fragment
      */
     public WebRuleSet(String prefix, boolean fragment) {
-        this(prefix, fragment, false);
-    }
-
-
-    /**
-     * Construct an instance of this <code>RuleSet</code> with the specified 
matching pattern prefix.
-     *
-     * @param prefix                           Prefix for matching pattern 
rules (including the trailing slash
-     *                                             character)
-     * @param fragment                         <code>true</code> if this is a 
web fragment
-     * @param urlPatternsProvidedInDecodedForm Whether URL and URL patterns 
will be provided in decoded form
-     *
-     * @deprecated This constructor will be removed in Tomcat 12
-     */
-    @Deprecated
-    public WebRuleSet(String prefix, boolean fragment, boolean 
urlPatternsProvidedInDecodedForm) {
         this.prefix = prefix;
         this.fragment = fragment;
 
@@ -158,7 +139,6 @@ public class WebRuleSet implements RuleSet {
 
         absoluteOrdering = new AbsoluteOrderingRule(fragment);
         relativeOrdering = new RelativeOrderingRule(fragment);
-        this.urlPatternsProvidedInDecodedForm = 
urlPatternsProvidedInDecodedForm;
     }
 
 
@@ -214,11 +194,7 @@ public class WebRuleSet implements RuleSet {
 
         digester.addCallMethod(fullPrefix + "/error-page/error-code", 
"setErrorCode", 0);
         digester.addCallMethod(fullPrefix + "/error-page/exception-type", 
"setExceptionType", 0);
-        if (urlPatternsProvidedInDecodedForm) {
-            digester.addCallMethod(fullPrefix + "/error-page/location", 
"setLocationDecoded", 0);
-        } else {
-            digester.addCallMethod(fullPrefix + "/error-page/location", 
"setLocation", 0);
-        }
+        digester.addCallMethod(fullPrefix + "/error-page/location", 
"setLocation", 0);
 
         digester.addObjectCreate(fullPrefix + "/filter", 
"org.apache.tomcat.util.descriptor.web.FilterDef");
         digester.addSetNext(fullPrefix + "/filter", "addFilter", 
"org.apache.tomcat.util.descriptor.web.FilterDef");
@@ -241,11 +217,7 @@ public class WebRuleSet implements RuleSet {
 
         digester.addCallMethod(fullPrefix + "/filter-mapping/filter-name", 
"setFilterName", 0);
         digester.addCallMethod(fullPrefix + "/filter-mapping/servlet-name", 
"addServletName", 0);
-        if (urlPatternsProvidedInDecodedForm) {
-            digester.addCallMethod(fullPrefix + "/filter-mapping/url-pattern", 
"addURLPatternDecoded", 0);
-        } else {
-            digester.addCallMethod(fullPrefix + "/filter-mapping/url-pattern", 
"addURLPattern", 0);
-        }
+        digester.addCallMethod(fullPrefix + "/filter-mapping/url-pattern", 
"addURLPattern", 0);
 
         digester.addCallMethod(fullPrefix + "/filter-mapping/dispatcher", 
"setDispatcher", 0);
 
@@ -270,12 +242,7 @@ public class WebRuleSet implements RuleSet {
                 0);
         digester.addCallMethod(fullPrefix + 
"/jsp-config/jsp-property-group/trim-directive-whitespaces",
                 "setTrimWhitespace", 0);
-        if (urlPatternsProvidedInDecodedForm) {
-            digester.addCallMethod(fullPrefix + 
"/jsp-config/jsp-property-group/url-pattern", "addUrlPatternDecoded",
-                    0);
-        } else {
-            digester.addCallMethod(fullPrefix + 
"/jsp-config/jsp-property-group/url-pattern", "addUrlPattern", 0);
-        }
+        digester.addCallMethod(fullPrefix + 
"/jsp-config/jsp-property-group/url-pattern", "addUrlPattern", 0);
         digester.addCallMethod(fullPrefix + 
"/jsp-config/jsp-property-group/default-content-type",
                 "setDefaultContentType", 0);
         digester.addCallMethod(fullPrefix + 
"/jsp-config/jsp-property-group/buffer", "setBuffer", 0);
@@ -291,15 +258,8 @@ public class WebRuleSet implements RuleSet {
         digester.addCallMethod(fullPrefix + "/login-config/auth-method", 
"setAuthMethod", 0);
         digester.addCallMethod(fullPrefix + "/login-config/realm-name", 
"setRealmName", 0);
 
-        if (urlPatternsProvidedInDecodedForm) {
-            digester.addCallMethod(fullPrefix + 
"/login-config/form-login-config/form-error-page",
-                    "setErrorPageDecoded", 0);
-            digester.addCallMethod(fullPrefix + 
"/login-config/form-login-config/form-login-page",
-                    "setLoginPageDecoded", 0);
-        } else {
-            digester.addCallMethod(fullPrefix + 
"/login-config/form-login-config/form-error-page", "setErrorPage", 0);
-            digester.addCallMethod(fullPrefix + 
"/login-config/form-login-config/form-login-page", "setLoginPage", 0);
-        }
+        digester.addCallMethod(fullPrefix + 
"/login-config/form-login-config/form-error-page", "setErrorPage", 0);
+        digester.addCallMethod(fullPrefix + 
"/login-config/form-login-config/form-login-page", "setLoginPage", 0);
 
         digester.addCallMethod(fullPrefix + "/mime-mapping", "addMimeMapping", 
2);
         digester.addCallParam(fullPrefix + "/mime-mapping/extension", 0);
@@ -324,13 +284,8 @@ public class WebRuleSet implements RuleSet {
         digester.addCallMethod(fullPrefix + 
"/security-constraint/web-resource-collection/http-method", "addMethod", 0);
         digester.addCallMethod(fullPrefix + 
"/security-constraint/web-resource-collection/http-method-omission",
                 "addOmittedMethod", 0);
-        if (urlPatternsProvidedInDecodedForm) {
-            digester.addCallMethod(fullPrefix + 
"/security-constraint/web-resource-collection/url-pattern",
-                    "addPatternDecoded", 0);
-        } else {
-            digester.addCallMethod(fullPrefix + 
"/security-constraint/web-resource-collection/url-pattern",
-                    "addPattern", 0);
-        }
+        digester.addCallMethod(fullPrefix + 
"/security-constraint/web-resource-collection/url-pattern", "addPattern",
+                0);
         digester.addCallMethod(fullPrefix + 
"/security-constraint/web-resource-collection/web-resource-name", "setName",
                 0);
 
diff --git a/java/org/apache/tomcat/util/descriptor/web/WebXml.java 
b/java/org/apache/tomcat/util/descriptor/web/WebXml.java
index cb98721820..75007b98d6 100644
--- a/java/org/apache/tomcat/util/descriptor/web/WebXml.java
+++ b/java/org/apache/tomcat/util/descriptor/web/WebXml.java
@@ -44,11 +44,9 @@ import jakarta.servlet.descriptor.TaglibDescriptor;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.buf.B2CConverter;
-import org.apache.tomcat.util.buf.UDecoder;
 import org.apache.tomcat.util.buf.UEncoder;
 import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet;
 import org.apache.tomcat.util.descriptor.XmlIdentifiers;
-import org.apache.tomcat.util.digester.DocumentProperties;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.util.security.Escape;
 
@@ -58,28 +56,12 @@ import org.apache.tomcat.util.security.Escape;
  * (e.g. single login-config) This class checks for invalid duplicates (e.g. 
filter/servlet names) StandardContext will
  * check validity of values (e.g. URL formats etc)
  */
-@SuppressWarnings("deprecation")
-public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charset {
+public class WebXml {
 
     /**
      * Constructs a new WebXml.
      */
     public WebXml() {
-        this(false);
-    }
-
-    /**
-     * Constructs a new WebXml with configurable behaviour for URL and URL 
pattern decoding.
-     *
-     * @param urlPatternsProvidedInDecodedForm {@code true} if URLs and URL 
patterns are expected to be decoded.
-     *                                             {@code false} if they are 
expected to be URL-encoded (i.e.
-     *                                             {@code %nn} encoding)
-     *
-     * @deprecated This constructor will be removed in Tomcat 12
-     */
-    @Deprecated
-    public WebXml(boolean urlPatternsProvidedInDecodedForm) {
-        this.urlPatternsProvidedInDecodedForm = 
urlPatternsProvidedInDecodedForm;
     }
 
     /**
@@ -93,25 +75,6 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
 
     private final UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH);
 
-    private final boolean urlPatternsProvidedInDecodedForm;
-
-
-    /**
-     * Does this Context expect URLs and URL patterns provided in web.xml, 
annotations and their programmatic
-     * equivalents to be in URL-decoded form?
-     * <p>
-     * As per the Servlet specification, "URI paths specified in the 
deployment descriptor are assumed to be in
-     * URL-decoded form.".
-     *
-     * @return {@code true} if URLs and URL patterns are expected in 
URL-decoded form, otherwise {@code false}
-     *
-     * @deprecated This method will be removed in Tomcat 12 where the field 
will be effectively hard-coded to
-     *                 {@code true}
-     */
-    @Deprecated
-    public boolean getUrlPatternsProvidedInDecodedForm() {
-        return urlPatternsProvidedInDecodedForm;
-    }
 
     /**
      * Global defaults are overridable but Servlets and Servlet mappings need 
to be unique. Duplicates normally trigger
@@ -585,7 +548,6 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
      * @param filterMap The filter mapping
      */
     public void addFilterMapping(FilterMap filterMap) {
-        filterMap.setCharset(getCharset());
         filterMaps.add(filterMap);
         filterMappingNames.add(filterMap.getFilterName());
     }
@@ -652,9 +614,10 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
         return servlets;
     }
 
-    // servlet-mapping
-    // Note: URLPatterns from web.xml may be URL encoded
-    // (https://svn.apache.org/r285186)
+    /*
+     * The Servlet specification states that URLs and URL patterns provided in 
web.xml (and by extension annotations
+     * and the programmatic equivalents to web.xml) must be in URL-decoded 
form.
+     */
     private final Map<String,String> servletMappings = new HashMap<>();
     private final Set<String> servletMappingNames = new HashSet<>();
 
@@ -663,26 +626,10 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
      *
      * @param urlPattern  The URL pattern
      * @param servletName The servlet name
-     */
-    public void addServletMapping(String urlPattern, String servletName) {
-        if (!urlPatternsProvidedInDecodedForm) {
-            urlPattern = UDecoder.URLDecode(urlPattern, getCharset());
-        }
-        addServletMappingDecoded(urlPattern, servletName);
-    }
-
-    /**
-     * Adds a servlet URL mapping (already decoded).
-     *
-     * @param urlPattern  The URL pattern
-     * @param servletName The servlet name
      *
      * @throws IllegalArgumentException If a duplicate mapping exists
-     *
-     * @deprecated Will be removed in Tomcat 12 onwards
      */
-    @Deprecated
-    public void addServletMappingDecoded(String urlPattern, String 
servletName) {
+    public void addServletMapping(String urlPattern, String servletName) {
         String oldServletName = servletMappings.put(urlPattern, servletName);
         if (oldServletName != null) {
             // Duplicate mapping. As per clarification from the Servlet EG,
@@ -803,7 +750,6 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
      * @param errorPage The error page
      */
     public void addErrorPage(ErrorPage errorPage) {
-        errorPage.setCharset(getCharset());
         errorPages.put(errorPage.getName(), errorPage);
     }
 
@@ -852,7 +798,6 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
      * @param propertyGroup The JSP property group
      */
     public void addJspPropertyGroup(JspPropertyGroup propertyGroup) {
-        propertyGroup.setCharset(getCharset());
         jspPropertyGroups.add(propertyGroup);
     }
 
@@ -876,7 +821,6 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
      * @param securityConstraint The security constraint
      */
     public void addSecurityConstraint(SecurityConstraint securityConstraint) {
-        securityConstraint.setCharset(getCharset());
         securityConstraints.add(securityConstraint);
     }
 
@@ -899,7 +843,6 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
      * @param loginConfig The login configuration
      */
     public void setLoginConfig(LoginConfig loginConfig) {
-        loginConfig.setCharset(getCharset());
         this.loginConfig = loginConfig;
     }
 
@@ -2135,7 +2078,7 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
 
         // Merge rules vary from element to element. See SRV.8.2.3
 
-        WebXml temp = new WebXml(urlPatternsProvidedInDecodedForm);
+        WebXml temp = new WebXml();
 
         for (WebXml fragment : fragments) {
             if (!mergeMap(fragment.getContextParams(), contextParams, 
temp.getContextParams(), fragment,
@@ -2374,7 +2317,7 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
 
         // Add fragment mappings
         for (Map.Entry<String,String> mapping : servletMappingsToAdd) {
-            addServletMappingDecoded(mapping.getKey(), mapping.getValue());
+            addServletMapping(mapping.getKey(), mapping.getValue());
         }
 
         for (WebXml fragment : fragments) {
diff --git a/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java 
b/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java
index 4806442d23..87c3b95d1d 100644
--- a/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java
+++ b/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java
@@ -52,7 +52,6 @@ public class WebXmlParser {
      */
     private final Digester webFragmentDigester;
     private final WebRuleSet webFragmentRuleSet;
-    private final boolean urlPatternsProvidedInDecodedForm;
 
     /**
      * Constructs a new WebXmlParser.
@@ -62,33 +61,14 @@ public class WebXmlParser {
      * @param blockExternal  Whether external entities are blocked
      */
     public WebXmlParser(boolean namespaceAware, boolean validation, boolean 
blockExternal) {
-        this(namespaceAware, validation, blockExternal, false);
-    }
-
-
-    /**
-     * Constructs a new WebXmlParser.
-     *
-     * @param namespaceAware                   Whether the parser is namespace 
aware
-     * @param validation                       Whether validation is enabled
-     * @param blockExternal                    Whether external entities are 
blocked
-     * @param urlPatternsProvidedInDecodedForm Whether URL and URL patterns 
will be provided in decoded form
-     *
-     * @deprecated This constructor will be removed in Tomcat 12
-     */
-    @Deprecated
-    public WebXmlParser(boolean namespaceAware, boolean validation, boolean 
blockExternal,
-            boolean urlPatternsProvidedInDecodedForm) {
-
-        webRuleSet = new WebRuleSet("",  false, 
urlPatternsProvidedInDecodedForm);
+        webRuleSet = new WebRuleSet(false);
         webDigester = DigesterFactory.newDigester(validation, namespaceAware, 
webRuleSet, blockExternal);
         webDigester.getParser();
 
-        webFragmentRuleSet = new WebRuleSet("", true, 
urlPatternsProvidedInDecodedForm);
+        webFragmentRuleSet = new WebRuleSet(true);
         webFragmentDigester =
                 DigesterFactory.newDigester(validation, namespaceAware, 
webFragmentRuleSet, blockExternal);
         webFragmentDigester.getParser();
-        this.urlPatternsProvidedInDecodedForm = 
urlPatternsProvidedInDecodedForm;
     }
 
     /**
@@ -182,18 +162,4 @@ public class WebXmlParser {
         webDigester.setClassLoader(classLoader);
         webFragmentDigester.setClassLoader(classLoader);
     }
-
-
-    /**
-     * Does this parser expect URLs and URL patterns provided in web.xml, 
annotations and their programmatic
-     * equivalents to be in URL-decoded form?
-     *
-     * @return {@code true} if URLs and URL patterns are expected in 
URL-decoded form, otherwise {@code false}
-     *
-     * @deprecated This method will be removed in Tomcat 12 where it will 
effectively be hard-coded to {@code true}
-     */
-    @Deprecated
-    public boolean getUrlPatternsProvidedInDecodedForm() {
-        return urlPatternsProvidedInDecodedForm;
-    }
 }
diff --git a/java/org/apache/tomcat/util/descriptor/web/XmlEncodingBase.java 
b/java/org/apache/tomcat/util/descriptor/web/XmlEncodingBase.java
deleted file mode 100644
index 666f7c2525..0000000000
--- a/java/org/apache/tomcat/util/descriptor/web/XmlEncodingBase.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.tomcat.util.descriptor.web;
-
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-
-/**
- * Base class for those elements that need to track the encoding used in the 
source XML.
- *
- * @deprecated This abstract class will be removed in Tomcat 12 onwards
- */
-@Deprecated
-public abstract class XmlEncodingBase {
-
-    private Charset charset = StandardCharsets.UTF_8;
-
-
-    /**
-     * Default constructor.
-     */
-    @Deprecated
-    public XmlEncodingBase() {
-    }
-
-
-    /**
-     * Set the character encoding of the XML source used to populate this 
object.
-     *
-     * @param charset The character encoding
-     */
-    @Deprecated
-    public void setCharset(Charset charset) {
-        this.charset = charset;
-    }
-
-
-    /**
-     * Obtain the character encoding of the XML source that was used to 
populate this object.
-     *
-     * @return The character encoding of the associated XML source or 
<code>UTF-8</code> if the encoding could not be
-     *             determined
-     */
-    @Deprecated
-    public Charset getCharset() {
-        return charset;
-    }
-}
diff --git a/java/org/apache/tomcat/util/digester/Digester.java 
b/java/org/apache/tomcat/util/digester/Digester.java
index bff710ae52..ede0f03395 100644
--- a/java/org/apache/tomcat/util/digester/Digester.java
+++ b/java/org/apache/tomcat/util/digester/Digester.java
@@ -20,7 +20,6 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
 import java.lang.reflect.InvocationTargetException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -43,7 +42,6 @@ import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.IntrospectionUtils;
 import org.apache.tomcat.util.IntrospectionUtils.PropertySource;
-import org.apache.tomcat.util.buf.B2CConverter;
 import org.apache.tomcat.util.buf.ToStringUtil;
 import org.apache.tomcat.util.res.StringManager;
 import org.xml.sax.Attributes;
@@ -58,7 +56,6 @@ import org.xml.sax.SAXParseException;
 import org.xml.sax.XMLReader;
 import org.xml.sax.ext.DefaultHandler2;
 import org.xml.sax.ext.EntityResolver2;
-import org.xml.sax.ext.Locator2;
 import org.xml.sax.helpers.AttributesImpl;
 
 
@@ -1277,19 +1274,6 @@ public class Digester extends DefaultHandler2 {
             saxLog.trace("startDocument()");
         }
 
-        if (locator instanceof Locator2) {
-            if (root instanceof DocumentProperties.Charset) {
-                String enc = ((Locator2) locator).getEncoding();
-                if (enc != null) {
-                    try {
-                        ((DocumentProperties.Charset) 
root).setCharset(B2CConverter.getCharset(enc));
-                    } catch (UnsupportedEncodingException e) {
-                        log.warn(sm.getString("digester.encodingInvalid", 
enc), e);
-                    }
-                }
-            }
-        }
-
         // ensure that the digester is properly configured, as
         // the digester could be used as a SAX ContentHandler
         // rather than via the parse() methods.
diff --git a/java/org/apache/tomcat/util/digester/DocumentProperties.java 
b/java/org/apache/tomcat/util/digester/DocumentProperties.java
deleted file mode 100644
index b73019ccb6..0000000000
--- a/java/org/apache/tomcat/util/digester/DocumentProperties.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.tomcat.util.digester;
-
-/**
- * A collection of interfaces, one per property, that enables the object being 
populated by the digester to signal to
- * the digester that it supports the given property and that the digester 
should populate that property if available.
- */
-public interface DocumentProperties {
-
-    /**
-     * Interface for objects that can receive the character encoding used by 
the source XML document.
-     */
-    interface Charset {
-        /**
-         * Set the character encoding used by the source XML document.
-         *
-         * @param charset The character encoding
-         */
-        void setCharset(java.nio.charset.Charset charset);
-    }
-}
diff --git a/java/org/apache/tomcat/util/digester/LocalStrings.properties 
b/java/org/apache/tomcat/util/digester/LocalStrings.properties
index f833ab873b..2d1aa37789 100644
--- a/java/org/apache/tomcat/util/digester/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/digester/LocalStrings.properties
@@ -16,7 +16,6 @@
 digester.createParserError=Error creating SAX parser
 digester.emptyStack=Empty stack, returning null
 digester.emptyStackError=Empty stack
-digester.encodingInvalid=The encoding [{0}] is not recognized by the JRE and 
will be ignored
 digester.error.begin=Begin event threw exception
 digester.error.body=Body event threw exception
 digester.error.end=End event threw exception
diff --git a/java/org/apache/tomcat/util/digester/LocalStrings_es.properties 
b/java/org/apache/tomcat/util/digester/LocalStrings_es.properties
index 18070eecf4..a5d279e40b 100644
--- a/java/org/apache/tomcat/util/digester/LocalStrings_es.properties
+++ b/java/org/apache/tomcat/util/digester/LocalStrings_es.properties
@@ -16,5 +16,4 @@
 # Do not edit this file directly.
 # To edit translations see: 
https://tomcat.apache.org/getinvolved.html#Translations
 
-digester.encodingInvalid=La codificación [{0}] no es reconocida por JRE y será 
ignorada
 digester.failedToUpdateAttributes=El tribunto [{0}]  falló la actualización y 
permanece [{1}]\n
diff --git a/java/org/apache/tomcat/util/digester/LocalStrings_fr.properties 
b/java/org/apache/tomcat/util/digester/LocalStrings_fr.properties
index 332eb287d8..932fff736b 100644
--- a/java/org/apache/tomcat/util/digester/LocalStrings_fr.properties
+++ b/java/org/apache/tomcat/util/digester/LocalStrings_fr.properties
@@ -19,7 +19,6 @@
 digester.createParserError=Erreur lors de la création de l'analyseur SAX
 digester.emptyStack=La pile est vide, retourne null
 digester.emptyStackError=La pile est vide
-digester.encodingInvalid=L''encodage [{0}] n''est pas reconnu par le JRE and 
sera ignoré
 digester.error.begin=L'évènement début a renvoyé une exception
 digester.error.body=L'évènement corps a renvoyé une exception
 digester.error.end=L'évènement fin a renvoyé une exception
diff --git a/java/org/apache/tomcat/util/digester/LocalStrings_ja.properties 
b/java/org/apache/tomcat/util/digester/LocalStrings_ja.properties
index 4b54624b7c..dbff3d31ff 100644
--- a/java/org/apache/tomcat/util/digester/LocalStrings_ja.properties
+++ b/java/org/apache/tomcat/util/digester/LocalStrings_ja.properties
@@ -19,7 +19,6 @@
 digester.createParserError=SAX パーサー生成中のエラー
 digester.emptyStack=空のスタックです。null を返却します。
 digester.emptyStackError=空のスタック
-digester.encodingInvalid=エンコーディング [{0}] はJREによって認識されないため、無視されます
 digester.error.begin=Begin イベントで例外を送出しました。
 digester.error.body=Body イベントで例外を送出しました。
 digester.error.end=End イベントで例外を送出しました。
diff --git a/java/org/apache/tomcat/util/digester/LocalStrings_ko.properties 
b/java/org/apache/tomcat/util/digester/LocalStrings_ko.properties
index ef391b9d88..ec39e0eda9 100644
--- a/java/org/apache/tomcat/util/digester/LocalStrings_ko.properties
+++ b/java/org/apache/tomcat/util/digester/LocalStrings_ko.properties
@@ -19,7 +19,6 @@
 digester.createParserError=SAX 파서를 생성하는 중 오류 발생
 digester.emptyStack=스택이 비어 있어, 널을 반환합니다.
 digester.emptyStackError=스택이 비어 있습니다.
-digester.encodingInvalid=인코딩 [{0}]이(가) JRE에 의해 인식되지 않아서 무시될 것입니다.
 digester.error.begin=Begin 이벤트가 예외를 발생시켰습니다.
 digester.error.body=Body 이벤트가 예외를 발생시켰습니다.
 digester.error.end=End 이벤트가 예외를 발생시켰습니다.
diff --git a/java/org/apache/tomcat/util/digester/LocalStrings_ru.properties 
b/java/org/apache/tomcat/util/digester/LocalStrings_ru.properties
deleted file mode 100644
index f66dffa131..0000000000
--- a/java/org/apache/tomcat/util/digester/LocalStrings_ru.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-# Do not edit this file directly.
-# To edit translations see: 
https://tomcat.apache.org/getinvolved.html#Translations
-
-digester.encodingInvalid=Кодировка [{0}] не распознана JRE и будет 
проигнорирована
diff --git a/java/org/apache/tomcat/util/digester/LocalStrings_zh_CN.properties 
b/java/org/apache/tomcat/util/digester/LocalStrings_zh_CN.properties
index 7ffb487978..e9c32dbb71 100644
--- a/java/org/apache/tomcat/util/digester/LocalStrings_zh_CN.properties
+++ b/java/org/apache/tomcat/util/digester/LocalStrings_zh_CN.properties
@@ -19,7 +19,6 @@
 digester.createParserError=创建SAX分析器时出错
 digester.emptyStack=空堆栈,返回空值
 digester.emptyStackError=空堆栈
-digester.encodingInvalid=JRE无法识别 [{0}]编码,将被忽略
 digester.error.begin=开始事件引发异常
 digester.error.body=正文事件引发异常
 digester.error.end=结束事件引发异常
diff --git 
a/test/org/apache/catalina/core/TestApplicationFilterRegistration.java 
b/test/org/apache/catalina/core/TestApplicationFilterRegistration.java
index 5f73fe6aff..547d721918 100644
--- a/test/org/apache/catalina/core/TestApplicationFilterRegistration.java
+++ b/test/org/apache/catalina/core/TestApplicationFilterRegistration.java
@@ -25,18 +25,8 @@ import org.apache.tomcat.util.descriptor.web.FilterMap;
 public class TestApplicationFilterRegistration {
 
     @Test
-    public void testUrlPatternEncoded() {
-        doTestUrlPattern(false, "/filter%");
-    }
-
-    @Test
-    public void testUrlPatternDecoded() {
-        doTestUrlPattern(true, "/filter%25");
-    }
-
-    private void doTestUrlPattern(boolean urlPatternsProvidedInDecodedForm, 
String expectedPattern) {
+    public void testUrlPatternsAreTreatedAsUrlDecoded() {
         StandardContext context = new StandardContext();
-        
context.setUrlPatternsProvidedInDecodedForm(urlPatternsProvidedInDecodedForm);
 
         FilterDef filterDef = new FilterDef();
         filterDef.setFilterName("filter");
@@ -47,6 +37,7 @@ public class TestApplicationFilterRegistration {
 
         FilterMap[] filterMaps = context.findFilterMaps();
         Assert.assertEquals(1, filterMaps.length);
-        Assert.assertArrayEquals(new String[] { expectedPattern }, 
filterMaps[0].getURLPatterns());
+        // Ensure pattern has not been decoded
+        Assert.assertArrayEquals(new String[] { "/filter%25" }, 
filterMaps[0].getURLPatterns());
     }
 }
diff --git 
a/test/org/apache/catalina/core/TestApplicationServletRegistration.java 
b/test/org/apache/catalina/core/TestApplicationServletRegistration.java
index 4452a0baf9..c7362b899a 100644
--- a/test/org/apache/catalina/core/TestApplicationServletRegistration.java
+++ b/test/org/apache/catalina/core/TestApplicationServletRegistration.java
@@ -24,18 +24,8 @@ import org.apache.catalina.Wrapper;
 public class TestApplicationServletRegistration {
 
     @Test
-    public void testUrlPatternEncoded() {
-        doTestUrlPattern(false, "/servlet%");
-    }
-
-    @Test
-    public void testUrlPatternDecoded() {
-        doTestUrlPattern(true, "/servlet%25");
-    }
-
-    private void doTestUrlPattern(boolean urlPatternsProvidedInDecodedForm, 
String expectedPattern) {
+    public void testUrlPatternsAreTreatedAsUrlDecoded() {
         StandardContext context = new StandardContext();
-        
context.setUrlPatternsProvidedInDecodedForm(urlPatternsProvidedInDecodedForm);
 
         Wrapper wrapper = context.createWrapper();
         wrapper.setName("servlet");
@@ -43,6 +33,7 @@ public class TestApplicationServletRegistration {
 
         ApplicationServletRegistration registration = new 
ApplicationServletRegistration(wrapper, context);
         Assert.assertTrue(registration.addMapping("/servlet%25").isEmpty());
-        Assert.assertEquals("servlet", 
context.findServletMapping(expectedPattern));
+        // Ensure pattern has not been decoded
+        Assert.assertEquals("servlet", 
context.findServletMapping("/servlet%25"));
     }
 }
diff --git a/test/org/apache/catalina/startup/TestContextConfigAnnotation.java 
b/test/org/apache/catalina/startup/TestContextConfigAnnotation.java
index 585a19a4f8..f52b8a4f3e 100644
--- a/test/org/apache/catalina/startup/TestContextConfigAnnotation.java
+++ b/test/org/apache/catalina/startup/TestContextConfigAnnotation.java
@@ -269,30 +269,19 @@ public class TestContextConfigAnnotation {
     }
 
     @Test
-    public void testUrlPatternsEncoded() throws Exception {
-        doTestUrlPatterns(false, "%");
-    }
-
-    @Test
-    public void testUrlPatternsDecoded() throws Exception {
-        doTestUrlPatterns(true, "%25");
-    }
-
-    @SuppressWarnings("deprecation")
-    private void doTestUrlPatterns(boolean urlPatternsProvidedInDecodedForm, 
String expectedSuffix) throws Exception {
-        WebXml webXml = new WebXml(urlPatternsProvidedInDecodedForm);
+    public void testUrlPatternsExpectDecoded() throws Exception {
+        WebXml webXml = new WebXml();
         Map<String,JavaClassCacheEntry> javaClassCache = new HashMap<>();
         ContextConfig config = new ContextConfig();
 
         File servletFile = 
paramClassResource("org/apache/catalina/startup/UrlPatternServlet");
         config.processAnnotationsFile(servletFile, webXml, false, 
javaClassCache);
-        Assert.assertEquals("urlPatternServlet",
-                webXml.getServletMappings().get("/servlet" + expectedSuffix));
+        Assert.assertEquals("urlPatternServlet", 
webXml.getServletMappings().get("/servlet%25"));
 
         File filterFile = 
paramClassResource("org/apache/catalina/startup/UrlPatternFilter");
         config.processAnnotationsFile(filterFile, webXml, false, 
javaClassCache);
         FilterMap filterMap = webXml.getFilterMappings().iterator().next();
-        Assert.assertArrayEquals(new String[] { "/filter" + expectedSuffix }, 
filterMap.getURLPatterns());
+        Assert.assertArrayEquals(new String[] { "/filter%25" }, 
filterMap.getURLPatterns());
     }
 
     @Test
diff --git a/test/org/apache/catalina/startup/TestUrlPatterns.java 
b/test/org/apache/catalina/startup/TestUrlPatterns.java
new file mode 100644
index 0000000000..4d77c15453
--- /dev/null
+++ b/test/org/apache/catalina/startup/TestUrlPatterns.java
@@ -0,0 +1,65 @@
+/*
+ * 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.catalina.startup;
+
+import java.io.File;
+
+import jakarta.servlet.http.HttpServletResponse;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.tomcat.util.buf.ByteChunk;
+
+/**
+ * End to end tests to ensure URLs and URL patterns are treated as URL-decoded 
values. The web application maps a
+ * Servlet at <code>/servlet%25</code> and protects <code>/secure%25</code> 
with a security constraint that denies all
+ * access.
+ */
+public class TestUrlPatterns extends TomcatBaseTest {
+
+    @Test
+    public void testPatternsAreTreatedAsUrlDecoded() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp-url-patterns");
+        tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+        tomcat.start();
+
+        /*
+         * The Servlet mapping is only reachable via the URI that decodes to 
the configured pattern.
+         *
+         * Note: The request URI needs to be provided in URI-Encoded form
+         */
+        ByteChunk body = new ByteChunk();
+        Assert.assertEquals(HttpServletResponse.SC_OK, 
getUrl(uri("/test/servlet%2525"), body, null));
+        Assert.assertEquals("OK", body.toString());
+
+        Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, 
getUrl(uri("/test/servlet%25"), new ByteChunk(), null));
+
+        // The security constraint follows the same pattern so it only 
protects the matching URI
+        Assert.assertEquals(HttpServletResponse.SC_FORBIDDEN, 
getUrl(uri("/test/secure%2525"), new ByteChunk(), null));
+
+        Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, 
getUrl(uri("/test/secure%25"), new ByteChunk(), null));
+    }
+
+
+    private String uri(String path) {
+        return "http://localhost:"; + getPort() + path;
+    }
+}
diff --git 
a/test/org/apache/catalina/startup/TestUrlPatternsProvidedInDecodedForm.java 
b/test/org/apache/catalina/startup/TestUrlPatternsProvidedInDecodedForm.java
deleted file mode 100644
index ff3a2c5d7e..0000000000
--- a/test/org/apache/catalina/startup/TestUrlPatternsProvidedInDecodedForm.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.catalina.startup;
-
-import java.io.File;
-
-import jakarta.servlet.http.HttpServletResponse;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.catalina.Context;
-import org.apache.tomcat.util.buf.ByteChunk;
-
-/**
- * End to end tests for the <code>urlPatternsProvidedInDecodedForm</code> 
Context attribute. The web application maps a
- * Servlet at <code>/servlet%25</code> and protects <code>/secure%25</code> 
with a security constraint that denies all
- * access. Whether those patterns are stored as <code>%</code> or as 
<code>%25</code> determines which request URI
- * reaches them once the URI has been decoded.
- */
-public class TestUrlPatternsProvidedInDecodedForm extends TomcatBaseTest {
-
-    /*
-     * The URI that decodes to "%".
-     */
-    private static final String ENCODED_FORM_URI_SUFFIX = "%25";
-
-    /*
-     * The URI that decodes to "%25".
-     */
-    private static final String DECODED_FORM_URI_SUFFIX = "%2525";
-
-
-    @Test
-    public void testEncodedForm() throws Exception {
-        // Patterns are decoded when read so the Servlet is mapped at 
"/servlet%"
-        doTestUrlPatterns(false, ENCODED_FORM_URI_SUFFIX, 
DECODED_FORM_URI_SUFFIX);
-    }
-
-
-    @Test
-    public void testDecodedForm() throws Exception {
-        // Patterns are used as provided so the Servlet is mapped at 
"/servlet%25"
-        doTestUrlPatterns(true, DECODED_FORM_URI_SUFFIX, 
ENCODED_FORM_URI_SUFFIX);
-    }
-
-
-    @SuppressWarnings("deprecation")
-    private void doTestUrlPatterns(boolean urlPatternsProvidedInDecodedForm, 
String matchingSuffix,
-            String nonMatchingSuffix) throws Exception {
-
-        Tomcat tomcat = getTomcatInstance();
-
-        File appDir = new File("test/webapp-url-patterns");
-        Context ctx = tomcat.addWebapp(null, "/test", 
appDir.getAbsolutePath());
-        
ctx.setUrlPatternsProvidedInDecodedForm(urlPatternsProvidedInDecodedForm);
-
-        tomcat.start();
-
-        // The Servlet mapping is only reachable via the URI that decodes to 
the configured pattern
-        ByteChunk body = new ByteChunk();
-        Assert.assertEquals(HttpServletResponse.SC_OK, 
getUrl(uri("/test/servlet", matchingSuffix), body, null));
-        Assert.assertEquals("OK", body.toString());
-
-        Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND,
-                getUrl(uri("/test/servlet", nonMatchingSuffix), new 
ByteChunk(), null));
-
-        // The security constraint follows the same pattern so it only 
protects the matching URI
-        Assert.assertEquals(HttpServletResponse.SC_FORBIDDEN,
-                getUrl(uri("/test/secure", matchingSuffix), new ByteChunk(), 
null));
-
-        Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND,
-                getUrl(uri("/test/secure", nonMatchingSuffix), new 
ByteChunk(), null));
-    }
-
-
-    private String uri(String path, String suffix) {
-        return "http://localhost:"; + getPort() + path + suffix;
-    }
-}
diff --git a/test/org/apache/tomcat/unittest/TesterContext.java 
b/test/org/apache/tomcat/unittest/TesterContext.java
index 5badf1c1fd..29e6f2ae6b 100644
--- a/test/org/apache/tomcat/unittest/TesterContext.java
+++ b/test/org/apache/tomcat/unittest/TesterContext.java
@@ -788,13 +788,6 @@ public class TesterContext implements Context {
         // NO-OP
     }
 
-    @Override
-    @Deprecated
-    public void addServletMappingDecoded(String pattern, String name,
-            boolean jspWildcard) {
-        // NO-OP
-    }
-
     @Override
     public void addWatchedResource(String name) {
         // NO-OP
diff --git a/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java 
b/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java
index ab33f8c049..e92235d87b 100644
--- a/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java
+++ b/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java
@@ -19,8 +19,6 @@ package org.apache.tomcat.util.descriptor.web;
 import java.io.File;
 import java.io.IOException;
 import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
-import java.util.Collection;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -533,47 +531,6 @@ public class TestWebXml {
     }
 
 
-    @SuppressWarnings("deprecation")
-    @Test
-    public void testEncoding() {
-        WebXml webXml = new WebXml();
-        webXml.setCharset(StandardCharsets.ISO_8859_1);
-
-        webXml.addErrorPage(new ErrorPage());
-        Collection<ErrorPage> errorPages = webXml.getErrorPages().values();
-        for (ErrorPage errorPage : errorPages) {
-            Assert.assertEquals(StandardCharsets.ISO_8859_1, 
errorPage.getCharset());
-        }
-
-        webXml.addFilterMapping(new FilterMap());
-        Set<FilterMap> filterMaps = webXml.getFilterMappings();
-        for (FilterMap filterMap : filterMaps) {
-            Assert.assertEquals(StandardCharsets.ISO_8859_1, 
filterMap.getCharset());
-        }
-
-        webXml.addJspPropertyGroup(new JspPropertyGroup());
-        Set<JspPropertyGroup> jspPropertyGroups = 
webXml.getJspPropertyGroups();
-        for (JspPropertyGroup jspPropertyGroup : jspPropertyGroups) {
-            Assert.assertEquals(StandardCharsets.ISO_8859_1, 
jspPropertyGroup.getCharset());
-        }
-
-        webXml.setLoginConfig(new LoginConfig());
-        LoginConfig loginConfig = webXml.getLoginConfig();
-        Assert.assertEquals(StandardCharsets.ISO_8859_1, 
loginConfig.getCharset());
-
-        SecurityConstraint constraint = new SecurityConstraint();
-        constraint.addCollection(new SecurityCollection());
-        webXml.addSecurityConstraint(constraint);
-        Set<SecurityConstraint> securityConstraints = 
webXml.getSecurityConstraints();
-        for (SecurityConstraint securityConstraint : securityConstraints) {
-            Assert.assertEquals(StandardCharsets.ISO_8859_1, 
securityConstraint.getCharset());
-            for (SecurityCollection securityCollection : 
securityConstraint.findCollections()) {
-                Assert.assertEquals(StandardCharsets.ISO_8859_1, 
securityCollection.getCharset());
-            }
-        }
-    }
-
-
     @Test
     public void testMergeSessionCookieConfig01() {
         WebXml main = new WebXml();
diff --git a/test/org/apache/tomcat/util/descriptor/web/TestWebXmlParser.java 
b/test/org/apache/tomcat/util/descriptor/web/TestWebXmlParser.java
index 5bcf23a10a..a5ad64a279 100644
--- a/test/org/apache/tomcat/util/descriptor/web/TestWebXmlParser.java
+++ b/test/org/apache/tomcat/util/descriptor/web/TestWebXmlParser.java
@@ -27,41 +27,31 @@ public class TestWebXmlParser {
     private static final String WEB_XML = "TestWebXmlParser-web.xml";
 
     @Test
-    public void testUrlPatternsEncoded() throws Exception {
-        doTestUrlPatterns(false, "%");
-    }
-
-    @Test
-    public void testUrlPatternsDecoded() throws Exception {
-        doTestUrlPatterns(true, "%25");
-    }
-
-    @SuppressWarnings("deprecation")
-    private void doTestUrlPatterns(boolean urlPatternsProvidedInDecodedForm, 
String expectedSuffix) throws Exception {
+    public void testUrlPatterns() throws Exception {
         URL webXmlUrl = TestWebXmlParser.class.getResource(WEB_XML);
         Assert.assertNotNull("Could not locate " + WEB_XML, webXmlUrl);
 
-        WebXml webXml = new WebXml(urlPatternsProvidedInDecodedForm);
-        WebXmlParser parser = new WebXmlParser(false, false, true, 
urlPatternsProvidedInDecodedForm);
+        WebXml webXml = new WebXml();
+        WebXmlParser parser = new WebXmlParser(false, false, true);
         Assert.assertTrue(parser.parseWebXml(webXmlUrl, webXml, false));
 
-        Assert.assertEquals("servlet", 
webXml.getServletMappings().get("/servlet" + expectedSuffix));
+        Assert.assertEquals("servlet", 
webXml.getServletMappings().get("/servlet%25"));
 
         FilterMap filterMap = webXml.getFilterMappings().iterator().next();
-        Assert.assertArrayEquals(new String[] { "/filter" + expectedSuffix }, 
filterMap.getURLPatterns());
+        Assert.assertArrayEquals(new String[] { "/filter%25" }, 
filterMap.getURLPatterns());
 
         JspPropertyGroup jspPropertyGroup = 
webXml.getJspPropertyGroups().iterator().next();
-        Assert.assertEquals(Set.of("/jsp" + expectedSuffix), 
jspPropertyGroup.getUrlPatterns());
+        Assert.assertEquals(Set.of("/jsp%25"), 
jspPropertyGroup.getUrlPatterns());
 
         LoginConfig loginConfig = webXml.getLoginConfig();
-        Assert.assertEquals("/login" + expectedSuffix, 
loginConfig.getLoginPage());
-        Assert.assertEquals("/login-error" + expectedSuffix, 
loginConfig.getErrorPage());
+        Assert.assertEquals("/login%25", loginConfig.getLoginPage());
+        Assert.assertEquals("/login-error%25", loginConfig.getErrorPage());
 
         ErrorPage errorPage = 
webXml.getErrorPages().values().iterator().next();
-        Assert.assertEquals("/error" + expectedSuffix, 
errorPage.getLocation());
+        Assert.assertEquals("/error%25", errorPage.getLocation());
 
         SecurityConstraint securityConstraint = 
webXml.getSecurityConstraints().iterator().next();
         SecurityCollection securityCollection = 
securityConstraint.findCollection("resource");
-        Assert.assertArrayEquals(new String[] { "/secure" + expectedSuffix }, 
securityCollection.findPatterns());
+        Assert.assertArrayEquals(new String[] { "/secure%25" }, 
securityCollection.findPatterns());
     }
 }
diff --git a/test/webapp-url-patterns/WEB-INF/web.xml 
b/test/webapp-url-patterns/WEB-INF/web.xml
index f1a64bcdab..bf90a8d317 100644
--- a/test/webapp-url-patterns/WEB-INF/web.xml
+++ b/test/webapp-url-patterns/WEB-INF/web.xml
@@ -23,11 +23,8 @@
   metadata-complete="true">
 
   <!--
-    Used by TestUrlPatternsProvidedInDecodedForm. The %25 in the URL patterns
-    is decoded to "%" if the patterns are treated as being provided in encoded
-    form and left as "%25" if they are treated as being provided in decoded
-    form. The request URI required to reach each mapping therefore differs
-    between the two modes.
+    Used by TestUrlPatterns. URL patterns in web.xml are in URL-decoded form so
+    the %25 in the URL patterns should not be decoded.
   -->
 
   <servlet>
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 3363570a7b..ba9d2ca321 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -230,6 +230,16 @@
         10008. Based on pull request <pr>1026</pr> by Mario Daniel Ruiz
         Saavedra. (markt)
       </add>
+      <fix>
+        Remove the <code>Context</code> attribute
+        <code>urlPatternsProvidedInDecodedForm</code> and all supporting code.
+        The attribute is now effectively hard-coded to <code>true</code> for 
all
+        web applications which is a change from the default of
+        <code>false</code> in Tomcat 11 and earlier. The default implementation
+        of <code>Context.addServletMapping(String,String,boolean)</code> has
+        been removed so classes that implement the <code>Context</code>
+        interface must implement this method. (markt)
+      </fix>
       <!-- Entries for backport and removal before 12.0.0-M1 below this line 
-->
       <fix>
         Ensure that a <code>login-config</code> conflict when merging web.xml
@@ -296,20 +306,6 @@
         of particular not for attributes that implement
         <code>HttpSessionBindingListener</code>. (markt)
       </fix>
-      <fix>
-        Add a new attribute to the <code>Context</code>,
-        <code>urlPatternsProvidedInDecodedForm</code>. This attribute controls
-        whether URLs and URL patterns provided in the deployment descriptor
-        (web.xml), annotations and/or their programmatic equivalents are 
treated
-        as being provided in URL-encoded form (i.e. using %nn encoding) or in
-        decoded form. The Servlet specification requires that they are provided
-        in decoded form. However, Tomcat has historically treated them as if
-        they are provided in encoded form. In Tomcat 12, they will always be
-        treated as if they are provided in decoded form. This setting enables
-        migration from encoded form to decoded form on an application by
-        application basis. This attribute will be removed in Tomcat 12 where it
-        will effectively be hard-coded to <code>true</code>. (markt)
-      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">
diff --git a/webapps/docs/config/context.xml b/webapps/docs/config/context.xml
index a9e08265c3..bb4a82d651 100644
--- a/webapps/docs/config/context.xml
+++ b/webapps/docs/config/context.xml
@@ -704,22 +704,6 @@
         penalty.</p>
       </attribute>
 
-      <attribute name="urlPatternsProvidedInDecodedForm" required="false">
-        <p>This attribute controls whether URLs and URL patterns provided in
-        the deployment descriptor (web.xml), annotations and/or their
-        programmatic equivalents are treated as being provided in URL-encoded
-        form (i.e. using %nn encoding) or in decoded form. The Servlet
-        specification requires that they are provided in decoded form. However,
-        Tomcat has historically treated them as if they are provided in encoded
-        form. In Tomcat 12, they will always be treated as if they are provided
-        in decoded form. This setting enables migration from encoded form to
-        decoded form on an application by application basis.</p>
-        <p>If not specified, the default value of <code>false</code> will be
-        used.</p>
-        <p>This attribute will be removed in Tomcat 12 where it will 
effectively
-        be hard-coded to <code>true</code>.</p>
-      </attribute>
-
       <attribute name="useHttpOnly" required="false">
        <p>Should the HttpOnly flag be set on session cookies to prevent client
           side script from accessing the session ID? Defaults to


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to