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

remm pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new cfe38ddecf Make dependent ordering predictable
cfe38ddecf is described below

commit cfe38ddecf1c85e167e472aa6c76b8c708cc0b74
Author: remm <[email protected]>
AuthorDate: Tue Apr 7 11:10:59 2026 +0200

    Make dependent ordering predictable
    
    Patch submitted by Jan Luehe.
---
 java/org/apache/jasper/compiler/Generator.java     |  2 +-
 java/org/apache/jasper/compiler/PageInfo.java      |  3 +-
 test/org/apache/jasper/compiler/TestGenerator.java | 43 ++++++++++++++++++++++
 test/webapp/jsp/generator/dependants-order-a.jspf  | 17 +++++++++
 test/webapp/jsp/generator/dependants-order-b.jspf  | 17 +++++++++
 test/webapp/jsp/generator/dependants-order-c.jspf  | 17 +++++++++
 test/webapp/jsp/generator/dependants-order.jsp     | 19 ++++++++++
 webapps/docs/changelog.xml                         |  8 ++++
 8 files changed, 124 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/jasper/compiler/Generator.java 
b/java/org/apache/jasper/compiler/Generator.java
index eec7eecca7..1bbe54e8e6 100644
--- a/java/org/apache/jasper/compiler/Generator.java
+++ b/java/org/apache/jasper/compiler/Generator.java
@@ -567,7 +567,7 @@ class Generator {
         if (!dependants.isEmpty()) {
             out.printil("static {");
             out.pushIndent();
-            out.printin("_jspx_dependants = new 
java.util.HashMap<java.lang.String,java.lang.Long>(");
+            out.printin("_jspx_dependants = new 
java.util.LinkedHashMap<java.lang.String,java.lang.Long>(");
             out.print("" + dependants.size());
             out.println(");");
             for (Entry<String,Long> entry : dependants.entrySet()) {
diff --git a/java/org/apache/jasper/compiler/PageInfo.java 
b/java/org/apache/jasper/compiler/PageInfo.java
index 8bb483a8e1..91ba94b5db 100644
--- a/java/org/apache/jasper/compiler/PageInfo.java
+++ b/java/org/apache/jasper/compiler/PageInfo.java
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -107,7 +108,7 @@ public class PageInfo {
         this.jspPrefixMapper = new HashMap<>();
         this.xmlPrefixMapper = new HashMap<>();
         this.nonCustomTagPrefixMap = new HashMap<>();
-        this.dependants = new HashMap<>();
+        this.dependants = new LinkedHashMap<>();
         this.includePrelude = new ArrayList<>();
         this.includeCoda = new ArrayList<>();
         this.pluginDcls = new ArrayList<>();
diff --git a/test/org/apache/jasper/compiler/TestGenerator.java 
b/test/org/apache/jasper/compiler/TestGenerator.java
index 01d70ae8b6..e53320c455 100644
--- a/test/org/apache/jasper/compiler/TestGenerator.java
+++ b/test/org/apache/jasper/compiler/TestGenerator.java
@@ -22,8 +22,12 @@ import java.beans.PropertyDescriptor;
 import java.beans.PropertyEditorSupport;
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Field;
 import java.nio.charset.CodingErrorAction;
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
 import java.util.Scanner;
 
 import javax.servlet.http.HttpServletResponse;
@@ -48,6 +52,7 @@ import org.apache.catalina.Wrapper;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.catalina.startup.TomcatBaseTest;
 import org.apache.jasper.servlet.JasperInitializer;
+import org.apache.jasper.servlet.JspServlet;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.compat.JreCompat;
 
@@ -776,6 +781,44 @@ public class TestGenerator extends TomcatBaseTest {
         doTestJsp("include-01.jsp");
     }
 
+    /*
+     * Verify that _jspx_dependants entries appear in the same order as the
+     * <%@ include file="..." %> directives in the source JSP, ensuring
+     * reproducible builds (LinkedHashMap preserves insertion order).
+     */
+    @Test
+    public void testDependantsOrder() throws Exception {
+        Tomcat tomcat = getTomcatInstanceTestWebapp(false, true);
+
+        ByteChunk body = new ByteChunk();
+        int rc = getUrl("http://localhost:"; + getPort() +
+                "/test/jsp/generator/dependants-order.jsp", body, null);
+        Assert.assertEquals(body.toString(), HttpServletResponse.SC_OK, rc);
+
+        // JSP classes are loaded by a per-JSP JasperLoader child classloader,
+        // not by the webapp classloader. Retrieve the dependants map through
+        // the JspServletWrapper, which calls getDependants() on the live
+        // servlet instance via the JspSourceDependent interface.
+        Context ctx = (Context) tomcat.getHost().findChild("/test");
+        Wrapper jspWrapper = (Wrapper) ctx.findChild("jsp");
+        JspServlet jspServlet = (JspServlet) jspWrapper.getServlet();
+        Field rctxtField = JspServlet.class.getDeclaredField("rctxt");
+        rctxtField.setAccessible(true);
+        JspRuntimeContext rctxt = (JspRuntimeContext) 
rctxtField.get(jspServlet);
+        Map<String,Long> dependants = rctxt.getWrapper(
+                "/jsp/generator/dependants-order.jsp").getDependants();
+
+        // Expect exactly the three fragments, in directive order: a, b, c.
+        List<String> keys = new ArrayList<>(dependants.keySet());
+        Assert.assertEquals(3, keys.size());
+        Assert.assertTrue("a.jspf should precede b.jspf in _jspx_dependants",
+                keys.indexOf("/jsp/generator/dependants-order-a.jspf") <
+                keys.indexOf("/jsp/generator/dependants-order-b.jspf"));
+        Assert.assertTrue("b.jspf should precede c.jspf in _jspx_dependants",
+                keys.indexOf("/jsp/generator/dependants-order-b.jspf") <
+                keys.indexOf("/jsp/generator/dependants-order-c.jspf"));
+    }
+
     @Test
     public void testSetProperty01() throws Exception {
         doTestJsp("setproperty-01.jsp");
diff --git a/test/webapp/jsp/generator/dependants-order-a.jspf 
b/test/webapp/jsp/generator/dependants-order-a.jspf
new file mode 100644
index 0000000000..34633181f6
--- /dev/null
+++ b/test/webapp/jsp/generator/dependants-order-a.jspf
@@ -0,0 +1,17 @@
+<%--
+  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.
+  --%>
+a
\ No newline at end of file
diff --git a/test/webapp/jsp/generator/dependants-order-b.jspf 
b/test/webapp/jsp/generator/dependants-order-b.jspf
new file mode 100644
index 0000000000..740112ad77
--- /dev/null
+++ b/test/webapp/jsp/generator/dependants-order-b.jspf
@@ -0,0 +1,17 @@
+<%--
+  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.
+  --%>
+b
\ No newline at end of file
diff --git a/test/webapp/jsp/generator/dependants-order-c.jspf 
b/test/webapp/jsp/generator/dependants-order-c.jspf
new file mode 100644
index 0000000000..983395058d
--- /dev/null
+++ b/test/webapp/jsp/generator/dependants-order-c.jspf
@@ -0,0 +1,17 @@
+<%--
+  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.
+  --%>
+c
\ No newline at end of file
diff --git a/test/webapp/jsp/generator/dependants-order.jsp 
b/test/webapp/jsp/generator/dependants-order.jsp
new file mode 100644
index 0000000000..aa3b60a95a
--- /dev/null
+++ b/test/webapp/jsp/generator/dependants-order.jsp
@@ -0,0 +1,19 @@
+<%--
+  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.
+  --%>
+<%@ include file="dependants-order-a.jspf" %>
+<%@ include file="dependants-order-b.jspf" %>
+<%@ include file="dependants-order-c.jspf" %>
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 260f37f8d9..1f5e40dc4c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -182,6 +182,14 @@
       </fix>
     </changelog>
   </subsection>
+  <subsection name="Jasper">
+    <changelog>
+      <fix>
+        <bug>69995</bug>: Make dependent ordering predictable. Patch submitted
+        by Jan Luehe. (remm)
+      </fix>
+    </changelog>
+  </subsection>
   <subsection name="Cluster">
     <changelog>
       <fix>


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

Reply via email to