Author: markt
Date: Wed Jun 18 10:33:26 2014
New Revision: 1603402

URL: http://svn.apache.org/r1603402
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56636
Correct various issues in method signature matching

Added:
    tomcat/trunk/test/javax/el/TesterFunctions.java   (with props)
Modified:
    tomcat/trunk/java/javax/el/ELProcessor.java
    tomcat/trunk/test/javax/el/TestELProcessor.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/javax/el/ELProcessor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/javax/el/ELProcessor.java?rev=1603402&r1=1603401&r2=1603402&view=diff
==============================================================================
--- tomcat/trunk/java/javax/el/ELProcessor.java (original)
+++ tomcat/trunk/java/javax/el/ELProcessor.java Wed Jun 18 10:33:26 2014
@@ -18,12 +18,28 @@ package javax.el;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * @since EL 3.0
  */
 public class ELProcessor {
 
+    private static final Set<String> PRIMITIVES = new HashSet<>();
+    static {
+        PRIMITIVES.add("boolean");
+        PRIMITIVES.add("byte");
+        PRIMITIVES.add("char");
+        PRIMITIVES.add("double");
+        PRIMITIVES.add("float");
+        PRIMITIVES.add("int");
+        PRIMITIVES.add("long");
+        PRIMITIVES.add("short");
+    }
+
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
     private final ELManager manager = new ELManager();
     private final ELContext context = manager.getELContext();
     private final ExpressionFactory factory = ELManager.getExpressionFactory();
@@ -97,6 +113,15 @@ public class ELProcessor {
             }
             if (method.getName().equals(sig.getName())) {
                 if (sig.getParamTypeNames() == null) {
+                    // Only a name provided, no signature so map the first
+                    // method declared
+                    manager.mapFunction(prefix, function, method);
+                    return;
+                }
+                if (sig.getParamTypeNames().length != 
method.getParameterTypes().length) {
+                    continue;
+                }
+                if (sig.getParamTypeNames().length == 0) {
                     manager.mapFunction(prefix, function, method);
                     return;
                 } else {
@@ -174,7 +199,22 @@ public class ELProcessor {
                 name = methodName.trim();
                 parameterTypeNames = null;
             } else {
-                name = methodName.substring(0, paramIndex -1).trim();
+                String returnTypeAndName = methodName.substring(0, 
paramIndex).trim();
+                // Assume that the return type and the name are separated by
+                // whitespace. Given the use of trim() above, there should only
+                // be one sequence of whitespace characters.
+                int wsPos = -1;
+                for (int i = 0; i < returnTypeAndName.length(); i++) {
+                    if (Character.isWhitespace(returnTypeAndName.charAt(i))) {
+                        wsPos = i;
+                        break;
+                    }
+                }
+                if (wsPos == -1) {
+                    throw new NoSuchMethodException();
+                }
+                name = returnTypeAndName.substring(wsPos).trim();
+
                 String paramString = methodName.substring(paramIndex).trim();
                 // We know the params start with '(', check they end with ')'
                 if (!paramString.endsWith(")")) {
@@ -183,26 +223,31 @@ public class ELProcessor {
                             paramString, methodName, className));
                 }
                 // Trim '(' and ')'
-                paramString =
-                        paramString.substring(1, paramString.length() - 1);
-                parameterTypeNames = paramString.split(",");
-                ImportHandler importHandler = context.getImportHandler();
-                for (int i = 0; i < parameterTypeNames.length; i++) {
-                    parameterTypeNames[i] = parameterTypeNames[i].trim();
-                    if (!parameterTypeNames[i].contains(".")) {
-                        Class<?> clazz = importHandler.resolveClass(
-                                parameterTypeNames[i]);
-                        if (clazz == null) {
-                            throw new NoSuchMethodException(Util.message(
-                                    context,
-                                    
"elProcessor.defineFunctionInvalidParameterTypeName",
-                                    parameterTypeNames[i], methodName,
-                                    className));
+                paramString = paramString.substring(1, paramString.length() - 
1).trim();
+                if (paramString.length() == 0) {
+                    parameterTypeNames = EMPTY_STRING_ARRAY;
+                } else {
+                    parameterTypeNames = paramString.split(",");
+                    ImportHandler importHandler = context.getImportHandler();
+                    for (int i = 0; i < parameterTypeNames.length; i++) {
+                        String parameterTypeName = 
parameterTypeNames[i].trim();
+                        if (!PRIMITIVES.contains(parameterTypeName) &&
+                                !parameterTypeName.contains(".")) {
+                            Class<?> clazz = importHandler.resolveClass(
+                                    parameterTypeName);
+                            if (clazz == null) {
+                                throw new NoSuchMethodException(Util.message(
+                                        context,
+                                        
"elProcessor.defineFunctionInvalidParameterTypeName",
+                                        parameterTypeNames[i], methodName,
+                                        className));
+                            }
+                            parameterTypeNames[i] = clazz.getName();
                         }
-                        parameterTypeNames[i] = clazz.getName();
                     }
                 }
             }
+
         }
 
         public String getName() {

Modified: tomcat/trunk/test/javax/el/TestELProcessor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/javax/el/TestELProcessor.java?rev=1603402&r1=1603401&r2=1603402&view=diff
==============================================================================
--- tomcat/trunk/test/javax/el/TestELProcessor.java (original)
+++ tomcat/trunk/test/javax/el/TestELProcessor.java Wed Jun 18 10:33:26 2014
@@ -63,6 +63,44 @@ public class TestELProcessor {
 
 
     @Test
+    public void testDefineFunctionMethod02() throws Exception {
+        ELProcessor elp = new ELProcessor();
+        elp.defineFunction("fn", "test", "java.lang.Integer", "Integer 
valueOf(int)");
+        Assert.assertEquals(Integer.valueOf(1), elp.eval("fn:test(1)"));
+    }
+
+
+    @Test
+    public void testDefineFunctionMethod03() throws Exception {
+        TesterFunctions.resetCallList();
+        ELProcessor elp = new ELProcessor();
+        elp.defineFunction("fn", "test", "javax.el.TesterFunctions", "void 
doIt()");
+        elp.eval("fn:test()");
+        Assert.assertEquals("A", TesterFunctions.getCallList());
+    }
+
+
+    @Test
+    public void testDefineFunctionMethod04() throws Exception {
+        TesterFunctions.resetCallList();
+        ELProcessor elp = new ELProcessor();
+        elp.defineFunction("fn", "test", "javax.el.TesterFunctions", "void 
doIt(int)");
+        elp.eval("fn:test(5)");
+        Assert.assertEquals("B", TesterFunctions.getCallList());
+    }
+
+
+    @Test
+    public void testDefineFunctionMethod05() throws Exception {
+        TesterFunctions.resetCallList();
+        ELProcessor elp = new ELProcessor();
+        elp.defineFunction("fn", "test", "javax.el.TesterFunctions", "void 
doIt(Integer)");
+        elp.eval("fn:test(null)");
+        Assert.assertEquals("C", TesterFunctions.getCallList());
+    }
+
+
+    @Test
     public void testDefineFunctionName01() throws Exception {
         ELProcessor elp = new ELProcessor();
         // java.lang should be automatically imported so no need for full class

Added: tomcat/trunk/test/javax/el/TesterFunctions.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/javax/el/TesterFunctions.java?rev=1603402&view=auto
==============================================================================
--- tomcat/trunk/test/javax/el/TesterFunctions.java (added)
+++ tomcat/trunk/test/javax/el/TesterFunctions.java Wed Jun 18 10:33:26 2014
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package javax.el;
+
+public class TesterFunctions {
+
+    private static StringBuilder calls = new StringBuilder();
+
+    public static String getCallList() {
+        return calls.toString();
+    }
+
+    public static void resetCallList() {
+        calls = new StringBuilder();
+    }
+
+    public static void doIt() {
+        calls.append('A');
+    }
+
+    public static void doIt(@SuppressWarnings("unused") int a) {
+        calls.append('B');
+    }
+
+    public static void doIt(@SuppressWarnings("unused") Integer a) {
+        calls.append('C');
+    }
+}

Propchange: tomcat/trunk/test/javax/el/TesterFunctions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1603402&r1=1603401&r2=1603402&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Wed Jun 18 10:33:26 2014
@@ -241,6 +241,11 @@
         <code>Parser</code> to <code>JspReader</code> class for better
         performance. (kkolinko)
       </update>
+      <fix>
+        <bug>56636</bug>: Correctly identify the required method when specified
+        via 
<code>ELProcessor.defineFunction(String,String,String,String)</code>
+        when using Expression Langauge. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="WebSocket">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to