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

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

commit 6c3ae6cf4cb1caabb7f19e1f27a861ed97a0de91
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Nov 10 17:44:05 2026 +0000

    Improve search of existing methods when defining functions
---
 java/javax/el/ELProcessor.java     |   2 +-
 test/javax/el/TestELProcessor.java | 154 +++++++++++++++++++++++++++++++++++++
 test/javax/el/TesterFunctions.java |   4 +
 webapps/docs/changelog.xml         |   8 ++
 4 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/java/javax/el/ELProcessor.java b/java/javax/el/ELProcessor.java
index 15afc9920e..e9611af413 100644
--- a/java/javax/el/ELProcessor.java
+++ b/java/javax/el/ELProcessor.java
@@ -239,7 +239,7 @@ public class ELProcessor {
                 if (paramString.length() == 0) {
                     parameterTypeNames = EMPTY_STRING_ARRAY;
                 } else {
-                    parameterTypeNames = paramString.split(",");
+                    parameterTypeNames = paramString.split(",", -1);
                     ImportHandler importHandler = context.getImportHandler();
                     for (int i = 0; i < parameterTypeNames.length; i++) {
                         String parameterTypeName = 
JreCompat.getInstance().strip(parameterTypeNames[i]);
diff --git a/test/javax/el/TestELProcessor.java 
b/test/javax/el/TestELProcessor.java
index b46cbe68ab..c88da850d5 100644
--- a/test/javax/el/TestELProcessor.java
+++ b/test/javax/el/TestELProcessor.java
@@ -190,6 +190,160 @@ public class TestELProcessor {
     }
 
 
+    /*
+     * Tests based on 
https://github.com/jakartaee/expression-language/issues/492 and variants.
+     */
+
+    private void doDefineFunctionSignature(String function, String signature, 
String expectedName, String expr,
+            String expectedCalls) throws Exception {
+        TesterFunctions.resetCallList();
+        ELProcessor elp = new ELProcessor();
+        elp.defineFunction("fn", function, "jakarta.el.TesterFunctions", 
signature);
+        Assert.assertNotNull(
+                
elp.getELManager().getELContext().getFunctionMapper().resolveFunction("fn", 
expectedName));
+        elp.eval(expr);
+        Assert.assertEquals(expectedCalls, TesterFunctions.getCallList());
+    }
+
+
+    @Test
+    public void testDefineFunctionNoParams01() throws Exception {
+        doDefineFunctionSignature("test", "void doIt()", "test", "fn:test()", 
"A");
+    }
+
+
+    @Test
+    public void testDefineFunctionNoParams02() throws Exception {
+        doDefineFunctionSignature("test", "void doIt( )", "test", "fn:test()", 
"A");
+    }
+
+
+    @Test
+    public void testDefineFunctionTwoParamsWithSpace() throws Exception {
+        doDefineFunctionSignature("test", "void doIt(int, int)", "test", 
"fn:test(1,2)", "J");
+    }
+
+
+    @Test
+    public void testDefineFunctionTwoParamsNoSpace() throws Exception {
+        doDefineFunctionSignature("test", "void doIt(int,int)", "test", 
"fn:test(1,2)", "J");
+    }
+
+
+    @Test
+    public void testDefineFunctionTwoParamsExtraSpace() throws Exception {
+        doDefineFunctionSignature("test", "void doIt( int ,  int )", "test", 
"fn:test(1,2)", "J");
+    }
+
+
+    @Test
+    public void testDefineFunctionTwoParamsTab() throws Exception {
+        doDefineFunctionSignature("test", "void doIt(int,\tint)", "test", 
"fn:test(1,2)", "J");
+    }
+
+
+    @Test
+    public void testDefineFunctionEmptyNameNoParams() throws Exception {
+        doDefineFunctionSignature("", "void doIt()", "doIt", "fn:doIt()", "A");
+    }
+
+
+    @Test
+    public void testDefineFunctionEmptyNameTwoParams() throws Exception {
+        doDefineFunctionSignature("", "void doIt(int,int)", "doIt", 
"fn:doIt(1,2)", "J");
+    }
+
+
+    @Test
+    public void testDefineFunctionEmptyNameTwoParamsWithSpace() throws 
Exception {
+        doDefineFunctionSignature("", "void doIt(int, int)", "doIt", 
"fn:doIt(1,2)", "J");
+    }
+
+
+    @Test
+    public void testDefineFunctionLeadingTrailingSpace() throws Exception {
+        doDefineFunctionSignature("", "  void  doIt ( int , int )  ", "doIt", 
"fn:doIt(1,2)", "J");
+    }
+
+
+    @Test
+    public void testDefineFunctionArraySpaceBetweenBrackets() throws Exception 
{
+        doDefineFunctionSignature("test", "void doIt(Integer[] [])", "test", 
"fn:test([[1].stream().toArray()].stream().toArray())", "G");
+    }
+
+
+    @Test
+    public void testDefineFunctionVarArgsWithSpace() throws Exception {
+        doDefineFunctionSignature("test", "void doIt( long ... )", "test", 
"fn:test(1,2)", "H");
+    }
+
+
+    private void doDefineFunctionInvalidSignature(String signature) {
+        ELProcessor elp = new ELProcessor();
+        try {
+            elp.defineFunction("fn", "test", "jakarta.el.TesterFunctions", 
signature);
+        } catch (ClassNotFoundException | NoSuchMethodException e) {
+            // Expected
+            return;
+        }
+        Assert.fail("Invalid signature [" + signature + "] was accepted");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidTrailingComma() {
+        doDefineFunctionInvalidSignature("void doIt(int,)");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidTrailingCommaSpace() {
+        doDefineFunctionInvalidSignature("void doIt(int, )");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidLeadingComma() {
+        doDefineFunctionInvalidSignature("void doIt(,int)");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidOnlyComma() {
+        doDefineFunctionInvalidSignature("void doIt(,)");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidDoubleComma() {
+        doDefineFunctionInvalidSignature("void doIt(int,,int)");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidTrailingCommaTwoParams() {
+        doDefineFunctionInvalidSignature("void doIt(int,int,)");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidMissingCloseParen() {
+        doDefineFunctionInvalidSignature("void doIt(int,int");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidMissingReturnType() {
+        doDefineFunctionInvalidSignature("doIt(int,int)");
+    }
+
+
+    @Test
+    public void testDefineFunctionInvalidUnknownType() {
+        doDefineFunctionInvalidSignature("void doIt(int,NoSuchType)");
+    }
+
+
     @Test
     public void testPrimitiveArray01() {
         ELProcessor elp = new ELProcessor();
diff --git a/test/javax/el/TesterFunctions.java 
b/test/javax/el/TesterFunctions.java
index 565a49587d..c406c5ccbe 100644
--- a/test/javax/el/TesterFunctions.java
+++ b/test/javax/el/TesterFunctions.java
@@ -63,4 +63,8 @@ public class TesterFunctions {
     public static void doIt(@SuppressWarnings("unused") Object... a) {
         calls.append('I');
     }
+
+    public static void doIt(@SuppressWarnings("unused") int a, 
@SuppressWarnings("unused") int b) {
+        calls.append('J');
+    }
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index dfa4a23496..a4a325a347 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -108,6 +108,14 @@
   issues do not "pop up" wrt. others).
 -->
 <section name="Tomcat 9.0.125 (remm)" rtext="in development">
+  <subsection name="Jasper">
+    <changelog>
+      <fix>
+        Improve search of existing methods when defining functions using an
+        <code>ELProcressor</code>. (markt)
+      </fix>
+    </changelog>
+  </subsection>
 </section>
 <section name="Tomcat 9.0.124 (remm)" rtext="release in progress">
   <subsection name="General">


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

Reply via email to