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 ec2a86518d Fix xml output of webxml
ec2a86518d is described below

commit ec2a86518dff26326462d5cee8b33330565c4619
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 a599b8bf16..42c103427e 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.
@@ -1352,6 +1356,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.
@@ -1452,7 +1457,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) {
@@ -1475,7 +1482,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");
@@ -1505,7 +1514,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
@@ -1515,7 +1526,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()) {
@@ -1566,7 +1579,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");
@@ -1574,21 +1589,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());
                 }
@@ -1602,7 +1640,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");
@@ -1626,10 +1666,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
@@ -1687,7 +1729,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()) {
@@ -1710,7 +1754,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");
@@ -1733,12 +1779,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");
@@ -1747,7 +1801,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");
@@ -1755,8 +1811,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");
@@ -1784,7 +1840,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");
@@ -1804,7 +1862,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) {
@@ -1826,7 +1886,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
@@ -1874,7 +1936,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()) {
@@ -1917,7 +1981,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");
@@ -1928,7 +1994,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
@@ -1964,12 +2032,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;
         }
@@ -1983,14 +2060,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 3b0ab38e23..811cc91e46 100644
--- a/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java
+++ b/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java
@@ -662,4 +662,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 8e608ffe22..de1f7ca3d8 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -392,6 +392,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