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