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

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

commit c5b1afb2923a0365c56b3de58b1b0e4e9c4fff30
Author: opencode <[email protected]>
AuthorDate: Mon Oct 19 11:15:49 2026 +0200

    Use the canonical enum name in the optimized string interpreter
    
    StringInterpreterEnum converts static (non-EL) tag attribute values
    into enum constant references in generated JSP Java source. It
    referenced the enum type by Class.getName(), which for a nested enum
    returns the binary name with '$' separators, e.g.
    com.example.Tags$Status, so a static attribute value for a setter
    taking a nested enum type made the generated JSP class fail to compile
    on first request.
    
    Use getCanonicalName() instead, matching the dot-separated name the
    DefaultStringInterpreter fallback already uses.
    
    Found by code review.
---
 .../optimizations/StringInterpreterEnum.java       |  5 +++-
 .../optimizations/TestStringInterpreterEnum.java   | 20 +++++++++++++++
 .../TestStringInterpreterTagSetters.java           |  6 +++++
 test/webapp/bug6nnnn/bug64872b-nested-timeunit.jsp | 29 ++++++++++++++++++++++
 4 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/jasper/optimizations/StringInterpreterEnum.java 
b/java/org/apache/jasper/optimizations/StringInterpreterEnum.java
index ff52b6b1ac..8c21ede54f 100644
--- a/java/org/apache/jasper/optimizations/StringInterpreterEnum.java
+++ b/java/org/apache/jasper/optimizations/StringInterpreterEnum.java
@@ -42,7 +42,10 @@ public class StringInterpreterEnum extends 
DefaultStringInterpreter {
             try {
                 @SuppressWarnings({ "unchecked", "rawtypes" })
                 Enum<?> enumValue = Enum.valueOf((Class<? extends Enum>) c, s);
-                return c.getName() + "." + enumValue.name();
+                // The canonical name (dot-separated) must be used here. The
+                // binary name returned by getName() contains '$' separators
+                // for nested types and is not valid Java source.
+                return c.getCanonicalName() + "." + enumValue.name();
             } catch (IllegalArgumentException iae) {
                 if (log.isDebugEnabled()) {
                     log.debug(Localizer.getMessage("jsp.error.typeConversion", 
s, "Enum[" + c.getName() + "]"), iae);
diff --git 
a/test/org/apache/jasper/optimizations/TestStringInterpreterEnum.java 
b/test/org/apache/jasper/optimizations/TestStringInterpreterEnum.java
index b22cd36581..459e7c81fe 100644
--- a/test/org/apache/jasper/optimizations/TestStringInterpreterEnum.java
+++ b/test/org/apache/jasper/optimizations/TestStringInterpreterEnum.java
@@ -18,6 +18,7 @@ package org.apache.jasper.optimizations;
 
 import java.util.concurrent.TimeUnit;
 
+import org.junit.Assert;
 import org.junit.Test;
 
 public class TestStringInterpreterEnum {
@@ -30,6 +31,15 @@ public class TestStringInterpreterEnum {
     }
 
 
+    /*
+     * Enum nested in a class so the binary name differs from the canonical
+     * name by a '$' separator.
+     */
+    public enum NestedEnum {
+        VALUE
+    }
+
+
     @Test
     public void testBadTerms() {
         String[] badTerms = new String[] { "", "mis format", "fudge", ";", 
".", "\"", " " };
@@ -37,4 +47,14 @@ public class TestStringInterpreterEnum {
             new TestInterpreter().evaluate(TimeUnit.class, badTerm);
         }
     }
+
+
+    @Test
+    public void testNestedEnumUsesCanonicalName() {
+        // The generated code must reference the canonical name (dot
+        // separated). The binary name contains '$' and is not valid Java
+        // source.
+        String result = new TestInterpreter().evaluate(NestedEnum.class, 
"VALUE");
+        Assert.assertEquals(NestedEnum.class.getCanonicalName() + ".VALUE", 
result);
+    }
 }
\ No newline at end of file
diff --git 
a/test/org/apache/jasper/optimizations/TestStringInterpreterTagSetters.java 
b/test/org/apache/jasper/optimizations/TestStringInterpreterTagSetters.java
index ca6db5864e..fca4d3560f 100644
--- a/test/org/apache/jasper/optimizations/TestStringInterpreterTagSetters.java
+++ b/test/org/apache/jasper/optimizations/TestStringInterpreterTagSetters.java
@@ -73,6 +73,12 @@ public class TestStringInterpreterTagSetters extends 
TomcatBaseTest {
         String actual = bc.toString();
 
         Assert.assertTrue(actual, actual.contains("01 The value of foo is 
[SECONDS]"));
+
+        bc = getUrl("http://localhost:"; + getPort() + 
"/test/bug6nnnn/bug64872b-nested-timeunit.jsp");
+
+        actual = bc.toString();
+
+        Assert.assertTrue(actual, actual.contains("01 The value of foo is 
[SECONDS]"));
     }
 
 
diff --git a/test/webapp/bug6nnnn/bug64872b-nested-timeunit.jsp 
b/test/webapp/bug6nnnn/bug64872b-nested-timeunit.jsp
new file mode 100644
index 0000000000..3f0bc21baf
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872b-nested-timeunit.jsp
@@ -0,0 +1,29 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters"; prefix="ts" %>
+<html>
+  <head><title>Bug 64872b nested enum test case</title></head>
+  <body>
+  <%
+  for (int i=0; i < 5000; i++) {
+  %>
+    <p>01 The value of foo is [<ts:tagNestedTimeUnit foo="SECONDS" />]</p>
+  <%
+  }
+  %>
+  </body>
+</html>


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

Reply via email to