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

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


The following commit(s) were added to refs/heads/11.0.x by this push:
     new f844614c6d Fix xml output of webxml
f844614c6d is described below

commit f844614c6d92eeb11e81e179606bf4c390f642dd
Author: Mark Thomas <[email protected]>
AuthorDate: Mon Jun 8 17:22:18 2026 +0100

    Fix xml output of webxml
    
    Missing entries, formatting, correct URI encoding
---
 .../apache/tomcat/util/descriptor/web/WebXml.java  | 157 ++++++++++++++-----
 .../tomcat/util/descriptor/web/TestWebXml.java     | 172 +++++++++++++++++++++
 webapps/docs/changelog.xml                         |   6 +
 3 files changed, 297 insertions(+), 38 deletions(-)

diff --git a/java/org/apache/tomcat/util/descriptor/web/WebXml.java 
b/java/org/apache/tomcat/util/descriptor/web/WebXml.java
index 8f488da5e2..25f0899fad 100644
--- a/java/org/apache/tomcat/util/descriptor/web/WebXml.java
+++ b/java/org/apache/tomcat/util/descriptor/web/WebXml.java
@@ -16,10 +16,9 @@
  */
 package org.apache.tomcat.util.descriptor.web;
 
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URL;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.EnumSet;
@@ -29,6 +28,7 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -45,6 +45,8 @@ 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;
@@ -73,6 +75,8 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
 
     private final Log log = LogFactory.getLog(WebXml.class); // must not be 
static
 
+    private final UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH);
+
     /**
      * Global defaults are overridable but Servlets and Servlet mappings need 
to be unique. Duplicates normally trigger
      * an error. This flag indicates if newly added Servlet elements are 
marked as overridable.
@@ -1348,6 +1352,7 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
     private static final String INDENT2 = "  ";
     private static final String INDENT4 = "    ";
     private static final String INDENT6 = "      ";
+    private static final String INDENT8 = "        ";
 
     /**
      * Generate a web.xml in String form that matches the representation 
stored in this object.
@@ -1445,7 +1450,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             appendElement(sb, INDENT4, "param-value", entry.getValue());
             sb.append("  </context-param>\n");
         }
-        sb.append('\n');
+        if (!contextParams.isEmpty()) {
+            sb.append('\n');
+        }
 
         // Filters were introduced in Servlet 2.3
         if (getMajorVersion() > 2 || getMinorVersion() > 2) {
@@ -1468,7 +1475,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 }
                 sb.append("  </filter>\n");
             }
-            sb.append('\n');
+            if (!filters.isEmpty()) {
+                sb.append('\n');
+            }
 
             for (FilterMap filterMap : filterMaps) {
                 sb.append("  <filter-mapping>\n");
@@ -1498,7 +1507,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 }
                 sb.append("  </filter-mapping>\n");
             }
-            sb.append('\n');
+            if (!filterMaps.isEmpty()) {
+                sb.append('\n');
+            }
         }
 
         // Listeners were introduced in Servlet 2.3
@@ -1508,7 +1519,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 appendElement(sb, INDENT4, "listener-class", listener);
                 sb.append("  </listener>\n");
             }
-            sb.append('\n');
+            if (!listeners.isEmpty()) {
+                sb.append('\n');
+            }
         }
 
         for (Map.Entry<String,ServletDef> entry : servlets.entrySet()) {
@@ -1559,7 +1572,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             }
             sb.append("  </servlet>\n");
         }
-        sb.append('\n');
+        if (!servlets.isEmpty()) {
+            sb.append('\n');
+        }
 
         for (Map.Entry<String,String> entry : servletMappings.entrySet()) {
             sb.append("  <servlet-mapping>\n");
@@ -1567,21 +1582,44 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             appendElement(sb, INDENT4, "url-pattern", 
encodeUrl(entry.getKey()));
             sb.append("  </servlet-mapping>\n");
         }
-        sb.append('\n');
+        if (!servletMappings.isEmpty()) {
+            sb.append('\n');
+        }
 
-        if (sessionConfig != null) {
+        if (sessionConfig.getSessionTimeout() != null || 
sessionConfig.getCookieName() != null ||
+                !sessionConfig.getCookieAttributes().isEmpty() || 
!sessionConfig.getSessionTrackingModes().isEmpty()) {
             sb.append("  <session-config>\n");
             appendElement(sb, INDENT4, "session-timeout", 
sessionConfig.getSessionTimeout());
             if (majorVersion >= 3) {
-                sb.append("    <cookie-config>\n");
-                appendElement(sb, INDENT6, "name", 
sessionConfig.getCookieName());
-                appendElement(sb, INDENT6, "domain", 
sessionConfig.getCookieDomain());
-                appendElement(sb, INDENT6, "path", 
sessionConfig.getCookiePath());
-                appendElement(sb, INDENT6, "comment", 
sessionConfig.getCookieComment());
-                appendElement(sb, INDENT6, "http-only", 
sessionConfig.getCookieHttpOnly());
-                appendElement(sb, INDENT6, "secure", 
sessionConfig.getCookieSecure());
-                appendElement(sb, INDENT6, "max-age", 
sessionConfig.getCookieMaxAge());
-                sb.append("    </cookie-config>\n");
+                if (sessionConfig.getCookieName() != null || 
!sessionConfig.getCookieAttributes().isEmpty()) {
+                    sb.append("    <cookie-config>\n");
+                    appendElement(sb, INDENT6, "name", 
sessionConfig.getCookieName());
+                    appendElement(sb, INDENT6, "domain", 
sessionConfig.getCookieDomain());
+                    appendElement(sb, INDENT6, "path", 
sessionConfig.getCookiePath());
+                    appendElement(sb, INDENT6, "comment", 
sessionConfig.getCookieComment());
+                    appendElement(sb, INDENT6, "http-only", 
sessionConfig.getCookieHttpOnly());
+                    appendElement(sb, INDENT6, "secure", 
sessionConfig.getCookieSecure());
+                    appendElement(sb, INDENT6, "max-age", 
sessionConfig.getCookieMaxAge());
+                    for (Map.Entry<String,String> entry : 
sessionConfig.getCookieAttributes().entrySet()) {
+                        switch (entry.getKey().toLowerCase(Locale.ROOT)) {
+                            case "domain":
+                            case "path":
+                            case "comment":
+                            case "http-only":
+                            case "secure":
+                            case "max-age":
+                                // NO-OP - handled above
+                                break;
+                            default: {
+                                sb.append("      <attribute>\n");
+                                appendElement(sb, INDENT8, "attribute-name", 
entry.getKey());
+                                appendElement(sb, INDENT8, "attribute-value", 
entry.getValue());
+                                sb.append("      </attribute>\n");
+                            }
+                        }
+                    }
+                    sb.append("    </cookie-config>\n");
+                }
                 for (SessionTrackingMode stm : 
sessionConfig.getSessionTrackingModes()) {
                     appendElement(sb, INDENT4, "tracking-mode", stm.name());
                 }
@@ -1595,7 +1633,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             appendElement(sb, INDENT4, "mime-type", entry.getValue());
             sb.append("  </mime-mapping>\n");
         }
-        sb.append('\n');
+        if (!mimeMappings.isEmpty()) {
+            sb.append('\n');
+        }
 
         if (!welcomeFiles.isEmpty()) {
             sb.append("  <welcome-file-list>\n");
@@ -1619,10 +1659,12 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             } else if (errorPage.getErrorCode() > 0) {
                 appendElement(sb, INDENT4, "error-code", 
Integer.toString(errorCode));
             }
-            appendElement(sb, INDENT4, "location", errorPage.getLocation());
+            appendElement(sb, INDENT4, "location", errorPage.getLocation(), 
true);
             sb.append("  </error-page>\n");
         }
-        sb.append('\n');
+        if (!errorPages.isEmpty()) {
+            sb.append('\n');
+        }
 
         // jsp-config was added in Servlet 2.4. Prior to that, tag-libs was 
used
         // directly and jsp-property-group did not exist
@@ -1680,7 +1722,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 appendElement(sb, INDENT4, "lookup-name", 
resourceEnvRef.getLookupName());
                 sb.append("  </resource-env-ref>\n");
             }
-            sb.append('\n');
+            if (!resourceEnvRefs.isEmpty()) {
+                sb.append('\n');
+            }
         }
 
         for (ContextResource resourceRef : resourceRefs.values()) {
@@ -1703,7 +1747,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             appendElement(sb, INDENT4, "lookup-name", 
resourceRef.getLookupName());
             sb.append("  </resource-ref>\n");
         }
-        sb.append('\n');
+        if (!resourceRefs.isEmpty()) {
+            sb.append('\n');
+        }
 
         for (SecurityConstraint constraint : securityConstraints) {
             sb.append("  <security-constraint>\n");
@@ -1726,12 +1772,20 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 }
                 sb.append("    </web-resource-collection>\n");
             }
-            if (constraint.findAuthRoles().length > 0) {
+            if (constraint.findAuthRoles().length > 0 || 
constraint.getAllRoles() || constraint.getAuthenticatedUsers()) {
                 sb.append("    <auth-constraint>\n");
                 for (String role : constraint.findAuthRoles()) {
                     appendElement(sb, INDENT6, "role-name", role);
                 }
+                if (constraint.getAllRoles()) {
+                    appendElement(sb, INDENT6, "role-name", 
SecurityConstraint.ROLE_ALL_ROLES);
+                }
+                if (constraint.getAuthenticatedUsers()) {
+                    appendElement(sb, INDENT6, "role-name", 
SecurityConstraint.ROLE_ALL_AUTHENTICATED_USERS);
+                }
                 sb.append("    </auth-constraint>\n");
+            } else if (constraint.getAuthConstraint()) {
+                sb.append("    <auth-constraint/>\n");
             }
             if (constraint.getUserConstraint() != null) {
                 sb.append("    <user-data-constraint>\n");
@@ -1740,7 +1794,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             }
             sb.append("  </security-constraint>\n");
         }
-        sb.append('\n');
+        if (!securityConstraints.isEmpty()) {
+            sb.append('\n');
+        }
 
         if (loginConfig != null) {
             sb.append("  <login-config>\n");
@@ -1748,8 +1804,8 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             appendElement(sb, INDENT4, "realm-name", 
loginConfig.getRealmName());
             if (loginConfig.getErrorPage() != null || 
loginConfig.getLoginPage() != null) {
                 sb.append("    <form-login-config>\n");
-                appendElement(sb, INDENT6, "form-login-page", 
loginConfig.getLoginPage());
-                appendElement(sb, INDENT6, "form-error-page", 
loginConfig.getErrorPage());
+                appendElement(sb, INDENT6, "form-login-page", 
loginConfig.getLoginPage(), true);
+                appendElement(sb, INDENT6, "form-error-page", 
loginConfig.getErrorPage(), true);
                 sb.append("    </form-login-config>\n");
             }
             sb.append("  </login-config>\n\n");
@@ -1777,7 +1833,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             appendElement(sb, INDENT4, "lookup-name", 
envEntry.getLookupName());
             sb.append("  </env-entry>\n");
         }
-        sb.append('\n');
+        if (!envEntries.isEmpty()) {
+            sb.append('\n');
+        }
 
         for (ContextEjb ejbRef : ejbRefs.values()) {
             sb.append("  <ejb-ref>\n");
@@ -1797,7 +1855,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             appendElement(sb, INDENT4, "lookup-name", ejbRef.getLookupName());
             sb.append("  </ejb-ref>\n");
         }
-        sb.append('\n');
+        if (!ejbRefs.isEmpty()) {
+            sb.append('\n');
+        }
 
         // ejb-local-ref was introduced in Servlet 2.3
         if (getMajorVersion() > 2 || getMinorVersion() > 2) {
@@ -1819,7 +1879,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 appendElement(sb, INDENT4, "lookup-name", 
ejbLocalRef.getLookupName());
                 sb.append("  </ejb-local-ref>\n");
             }
-            sb.append('\n');
+            if (!ejbLocalRefs.isEmpty()) {
+                sb.append('\n');
+            }
         }
 
         // service-ref was introduced in Servlet 2.4
@@ -1867,7 +1929,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 appendElement(sb, INDENT4, "lookup-name", 
serviceRef.getLookupName());
                 sb.append("  </service-ref>\n");
             }
-            sb.append('\n');
+            if (!serviceRefs.isEmpty()) {
+                sb.append('\n');
+            }
         }
 
         if (!postConstructMethods.isEmpty()) {
@@ -1910,7 +1974,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 appendElement(sb, INDENT4, "lookup-name", mdr.getLookupName());
                 sb.append("  </message-destination-ref>\n");
             }
-            sb.append('\n');
+            if (!messageDestinationRefs.isEmpty()) {
+                sb.append('\n');
+            }
 
             for (MessageDestination md : messageDestinations.values()) {
                 sb.append("  <message-destination>\n");
@@ -1921,7 +1987,9 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
                 appendElement(sb, INDENT4, "lookup-name", md.getLookupName());
                 sb.append("  </message-destination>\n");
             }
-            sb.append('\n');
+            if (!messageDestinations.isEmpty()) {
+                sb.append('\n');
+            }
         }
 
         // locale-encoding-mapping-list was introduced in Servlet 2.4
@@ -1957,12 +2025,21 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
     }
 
 
-    private String encodeUrl(String input) {
-        return URLEncoder.encode(input, StandardCharsets.UTF_8);
+    private synchronized String encodeUrl(String input) {
+        try {
+            return urlEncoder.encodeURL(input, 0, input.length()).toString();
+        } catch (IOException e) {
+            throw new IllegalArgumentException(input, e);
+        }
     }
 
 
-    private static void appendElement(StringBuilder sb, String indent, String 
elementName, String value) {
+    private void appendElement(StringBuilder sb, String indent, String 
elementName, String value) {
+        appendElement(sb, indent, elementName, value, false);
+    }
+
+    private void appendElement(StringBuilder sb, String indent, String 
elementName, String value, boolean encodeValue) {
+
         if (value == null) {
             return;
         }
@@ -1976,14 +2053,18 @@ public class WebXml extends XmlEncodingBase implements 
DocumentProperties.Charse
             sb.append('<');
             sb.append(elementName);
             sb.append('>');
-            sb.append(Escape.xml(value));
+            if (encodeValue) {
+                sb.append(Escape.xml(encodeUrl(value)));
+            } else {
+                sb.append(Escape.xml(value));
+            }
             sb.append("</");
             sb.append(elementName);
             sb.append(">\n");
         }
     }
 
-    private static void appendElement(StringBuilder sb, String indent, String 
elementName, Object value) {
+    private void appendElement(StringBuilder sb, String indent, String 
elementName, Object value) {
         if (value == null) {
             return;
         }
diff --git a/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java 
b/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java
index 2a71b6aefb..bf1920a2fd 100644
--- a/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java
+++ b/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java
@@ -657,4 +657,176 @@ public class TestWebXml {
 
         Assert.assertFalse(main.merge(fragments));
     }
+
+
+    @Test
+    public void testToXml01() throws Exception {
+        // Empty web.xml
+        doTestToXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+                "<web-app xmlns=\"https://jakarta.ee/xml/ns/jakartaee\"\n"; +
+                "         
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; +
+                "         
xsi:schemaLocation=\"https://jakarta.ee/xml/ns/jakartaee"; +
+                " https://jakarta.ee/xml/ns/jakartaee/web-app_6_2.xsd\"\n"; +
+                "         version=\"6.2\"\n" +
+                "         metadata-complete=\"true\">\n" +
+                "\n" +
+                "</web-app>");
+    }
+
+
+    @Test
+    public void testToXml02() throws Exception {
+        // Deny all
+        doTestToXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+                "<web-app xmlns=\"https://jakarta.ee/xml/ns/jakartaee\"\n"; +
+                "         
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; +
+                "         
xsi:schemaLocation=\"https://jakarta.ee/xml/ns/jakartaee"; +
+                " https://jakarta.ee/xml/ns/jakartaee/web-app_6_2.xsd\"\n"; +
+                "         version=\"6.2\"\n" +
+                "         metadata-complete=\"true\">\n" +
+                "\n" +
+                "  <security-constraint>\n" +
+                "    <web-resource-collection>\n" +
+                "      <web-resource-name>Test</web-resource-name>\n" +
+                "      <url-pattern>/deny-all</url-pattern>\n" +
+                "    </web-resource-collection>\n" +
+                "    <auth-constraint/>\n" +
+                "    <user-data-constraint>\n" +
+                "      <transport-guarantee>NONE</transport-guarantee>\n" +
+                "    </user-data-constraint>\n" +
+                "  </security-constraint>\n" +
+                "\n" +
+                "</web-app>");
+    }
+
+
+    @Test
+    public void testToXml03() throws Exception {
+        // other role plus all roles
+        doTestToXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+                "<web-app xmlns=\"https://jakarta.ee/xml/ns/jakartaee\"\n"; +
+                "         
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; +
+                "         
xsi:schemaLocation=\"https://jakarta.ee/xml/ns/jakartaee"; +
+                " https://jakarta.ee/xml/ns/jakartaee/web-app_6_2.xsd\"\n"; +
+                "         version=\"6.2\"\n" +
+                "         metadata-complete=\"true\">\n" +
+                "\n" +
+                "  <security-constraint>\n" +
+                "    <web-resource-collection>\n" +
+                "      <web-resource-name>Test</web-resource-name>\n" +
+                "      <url-pattern>/deny-all</url-pattern>\n" +
+                "    </web-resource-collection>\n" +
+                "    <auth-constraint>\n" +
+                "      <role-name>other</role-name>\n" +
+                "      <role-name>*</role-name>\n" +
+                "    </auth-constraint>\n" +
+                "    <user-data-constraint>\n" +
+                "      <transport-guarantee>NONE</transport-guarantee>\n" +
+                "    </user-data-constraint>\n" +
+                "  </security-constraint>\n" +
+                "\n" +
+                "</web-app>");
+    }
+
+
+    @Test
+    public void testToXml04() throws Exception {
+        // all roles
+        doTestToXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+                "<web-app xmlns=\"https://jakarta.ee/xml/ns/jakartaee\"\n"; +
+                "         
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; +
+                "         
xsi:schemaLocation=\"https://jakarta.ee/xml/ns/jakartaee"; +
+                " https://jakarta.ee/xml/ns/jakartaee/web-app_6_2.xsd\"\n"; +
+                "         version=\"6.2\"\n" +
+                "         metadata-complete=\"true\">\n" +
+                "\n" +
+                "  <security-constraint>\n" +
+                "    <web-resource-collection>\n" +
+                "      <web-resource-name>Test</web-resource-name>\n" +
+                "      <url-pattern>/deny-all</url-pattern>\n" +
+                "    </web-resource-collection>\n" +
+                "    <auth-constraint>\n" +
+                "      <role-name>*</role-name>\n" +
+                "    </auth-constraint>\n" +
+                "    <user-data-constraint>\n" +
+                "      <transport-guarantee>NONE</transport-guarantee>\n" +
+                "    </user-data-constraint>\n" +
+                "  </security-constraint>\n" +
+                "\n" +
+                "</web-app>");
+    }
+
+
+    @Test
+    public void testToXml05() throws Exception {
+        // other role plus authenticated users
+        doTestToXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+                "<web-app xmlns=\"https://jakarta.ee/xml/ns/jakartaee\"\n"; +
+                "         
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; +
+                "         
xsi:schemaLocation=\"https://jakarta.ee/xml/ns/jakartaee"; +
+                " https://jakarta.ee/xml/ns/jakartaee/web-app_6_2.xsd\"\n"; +
+                "         version=\"6.2\"\n" +
+                "         metadata-complete=\"true\">\n" +
+                "\n" +
+                "  <security-constraint>\n" +
+                "    <web-resource-collection>\n" +
+                "      <web-resource-name>Test</web-resource-name>\n" +
+                "      <url-pattern>/deny-all</url-pattern>\n" +
+                "    </web-resource-collection>\n" +
+                "    <auth-constraint>\n" +
+                "      <role-name>other</role-name>\n" +
+                "      <role-name>**</role-name>\n" +
+                "    </auth-constraint>\n" +
+                "    <user-data-constraint>\n" +
+                "      <transport-guarantee>NONE</transport-guarantee>\n" +
+                "    </user-data-constraint>\n" +
+                "  </security-constraint>\n" +
+                "\n" +
+                "</web-app>");
+    }
+
+
+    @Test
+    public void testToXml06() throws Exception {
+        // authenticated users
+        doTestToXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+                "<web-app xmlns=\"https://jakarta.ee/xml/ns/jakartaee\"\n"; +
+                "         
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; +
+                "         
xsi:schemaLocation=\"https://jakarta.ee/xml/ns/jakartaee"; +
+                " https://jakarta.ee/xml/ns/jakartaee/web-app_6_2.xsd\"\n"; +
+                "         version=\"6.2\"\n" +
+                "         metadata-complete=\"true\">\n" +
+                "\n" +
+                "  <security-constraint>\n" +
+                "    <web-resource-collection>\n" +
+                "      <web-resource-name>Test</web-resource-name>\n" +
+                "      <url-pattern>/deny-all</url-pattern>\n" +
+                "    </web-resource-collection>\n" +
+                "    <auth-constraint>\n" +
+                "      <role-name>**</role-name>\n" +
+                "    </auth-constraint>\n" +
+                "    <user-data-constraint>\n" +
+                "      <transport-guarantee>NONE</transport-guarantee>\n" +
+                "    </user-data-constraint>\n" +
+                "  </security-constraint>\n" +
+                "\n" +
+                "</web-app>");
+    }
+
+
+    private void doTestToXml(String input) throws Exception {
+        Digester digester = DigesterFactory.newDigester(true, true, new 
WebRuleSet(), true);
+
+        XmlErrorHandler handler = new XmlErrorHandler();
+        digester.setErrorHandler(handler);
+
+        InputSource is = new InputSource(new StringReader(input));
+        WebXml webxml = new WebXml();
+        digester.push(webxml);
+        digester.parse(is);
+
+        String output = webxml.toXml();
+
+        Assert.assertEquals(input, output);
+    }
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index f7f3fb500e..03dd82160a 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -296,6 +296,12 @@
         (according to the examples in the RFC). Use the first acceptable value.
         (remm)
       </fix>
+      <fix>
+        Fix various issues when logging the effective web.xml for a web
+        application. Empty sections are no longer logged. Special roles and
+        empty authorisation constraints are included. All session cookie
+        attributes are included. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


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

Reply via email to