Author: markt Date: Thu Jan 22 13:53:26 2015 New Revision: 1653857 URL: http://svn.apache.org/r1653857 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=57441 Fix error when defining functions using lambda expressions in JSPs.
Added: tomcat/trunk/test/webapp/bug5nnnn/bug57441.jsp (with props) Modified: tomcat/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java tomcat/trunk/java/org/apache/jasper/compiler/Validator.java tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties tomcat/trunk/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java tomcat/trunk/test/org/apache/el/TestELInJsp.java Modified: tomcat/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java?rev=1653857&r1=1653856&r2=1653857&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java Thu Jan 22 13:53:26 2015 @@ -220,40 +220,46 @@ public class ELFunctionMapper { ELNode.Function f = functions.get(i); FunctionInfo funcInfo = f.getFunctionInfo(); String key = f.getPrefix()+ ":" + f.getName(); - ds.append(funcMethod + "(\"" + key + "\", " + - getCanonicalName(funcInfo.getFunctionClass()) + - ".class, " + '\"' + f.getMethodName() + "\", " + - "new Class[] {"); - String params[] = f.getParameters(); - for (int k = 0; k < params.length; k++) { - if (k != 0) { - ds.append(", "); - } - int iArray = params[k].indexOf('['); - if (iArray < 0) { - ds.append(params[k] + ".class"); - } - else { - String baseType = params[k].substring(0, iArray); - ds.append("java.lang.reflect.Array.newInstance("); - ds.append(baseType); - ds.append(".class,"); + if (funcInfo == null) { + // Added via Lambda or ImportHandler. EL will expect a + // function mapper even if one isn't used so just pass null + ds.append(funcMethod + "(null, null, null, null);\n"); + } else { + ds.append(funcMethod + "(\"" + key + "\", " + + getCanonicalName(funcInfo.getFunctionClass()) + + ".class, " + '\"' + f.getMethodName() + "\", " + + "new Class[] {"); + String params[] = f.getParameters(); + for (int k = 0; k < params.length; k++) { + if (k != 0) { + ds.append(", "); + } + int iArray = params[k].indexOf('['); + if (iArray < 0) { + ds.append(params[k] + ".class"); + } + else { + String baseType = params[k].substring(0, iArray); + ds.append("java.lang.reflect.Array.newInstance("); + ds.append(baseType); + ds.append(".class,"); - // Count the number of array dimension - int aCount = 0; - for (int jj = iArray; jj < params[k].length(); jj++ ) { - if (params[k].charAt(jj) == '[') { - aCount++; + // Count the number of array dimension + int aCount = 0; + for (int jj = iArray; jj < params[k].length(); jj++ ) { + if (params[k].charAt(jj) == '[') { + aCount++; + } + } + if (aCount == 1) { + ds.append("0).getClass()"); + } else { + ds.append("new int[" + aCount + "]).getClass()"); } - } - if (aCount == 1) { - ds.append("0).getClass()"); - } else { - ds.append("new int[" + aCount + "]).getClass()"); } } + ds.append("});\n"); } - ds.append("});\n"); // Put the current name in the global function map gMap.put(f.getPrefix() + ':' + f.getName() + ':' + f.getUri(), decName); Modified: tomcat/trunk/java/org/apache/jasper/compiler/Validator.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/Validator.java?rev=1653857&r1=1653856&r2=1653857&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/Validator.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/Validator.java Thu Jan 22 13:53:26 2015 @@ -1582,8 +1582,10 @@ class Validator { if (uri == null) { if (prefix == null) { - err.jspError(n, "jsp.error.noFunctionPrefix", - function); + // This can occur when lambda expressions define + // functions and when functions are imported. No + // longer able to be sure this is an error. + return; } else { err.jspError(n, "jsp.error.attribute.invalidPrefix", prefix); @@ -1716,6 +1718,11 @@ class Validator { @Override public void visit(ELNode.Function n) throws JasperException { + // Lambda / ImportHandler defined fucntion + if (n.getFunctionInfo() == null) { + return; + } + Class<?> c = null; Method method = null; try { Modified: tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties?rev=1653857&r1=1653856&r2=1653857&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties Thu Jan 22 13:53:26 2015 @@ -338,7 +338,6 @@ jsp.error.variable.alias=Both or none of jsp.error.attribute.null_name=Null attribute name jsp.error.jsptext.badcontent=\'<\', when appears in the body of <jsp:text>, must be encapsulated within a CDATA jsp.error.jsproot.version.invalid=Invalid version number: \"{0}\", must be \"1.2\", \"2.0\", \"2.1\", \"2.2\" or \"2.3\" -jsp.error.noFunctionPrefix=The function {0} must be used with a prefix when a default namespace is not specified jsp.error.noFunction=The function {0} cannot be located with the specified prefix jsp.error.noFunctionMethod=Method \"{0}\" for function \"{1}\" not found in class \"{2}\" jsp.error.function.classnotfound=The class {0} specified in TLD for the function {1} cannot be found: {2} Modified: tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties?rev=1653857&r1=1653856&r2=1653857&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties (original) +++ tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties Thu Jan 22 13:53:26 2015 @@ -332,7 +332,6 @@ jsp.error.variable.alias = Ambos atribut jsp.error.attribute.null_name = Nombre de atributo nulo jsp.error.jsptext.badcontent = '<', cuando aparece en el cuerpo de <jsp\:text>, debe de estar encapsulado dentro de un CDATA jsp.error.jsproot.version.invalid = N\u00FAmero incorrecto de versi\u00F3n\: "{0}", debe de ser "1.2" o "2.0" o "2.1" o "2.2" o "2.3" -jsp.error.noFunctionPrefix = La funci\u00F3n {0} debe de usarse con un prefijo cuando no se especifica un espacio de nombres por defecto jsp.error.noFunction = La funci\u00F3n {0} no puede ser localizada mediante el prefijo especificado jsp.error.noFunctionMethod = El m\u00E9todo "{0}" para la funci\u00F3n "{1}" no se pudo hallar en la clase "{2}" jsp.error.function.classnotfound = La clase {0} especificada en el TLD para la funci\u00F3n {1} no se puede hallar\: {2} Modified: tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties?rev=1653857&r1=1653856&r2=1653857&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties (original) +++ tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties Thu Jan 22 13:53:26 2015 @@ -297,7 +297,6 @@ jsp.error.variable.alias=name-from-attri jsp.error.attribute.null_name=\u7a7a\u306e\u5c5e\u6027\u540d\u3067\u3059 jsp.error.jsptext.badcontent=\'<\'\u304c<jsp:text>\u306e\u30dc\u30c7\u30a3\u306e\u4e2d\u306b\u73fe\u308c\u308b\u6642\u306f\u3001CDATA\u306e\u4e2d\u306b\u96a0\u853d\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093 jsp.error.jsproot.version.invalid=\u7121\u52b9\u306a\u30d0\u30fc\u30b8\u30e7\u30f3\u756a\u53f7\u3067\u3059: \"{0}\"\u3001\"1.2\"\u3000\"2.0\"\u3000\"2.1\"\u3000\"2.2\" \u53c8\u306f \"2.3\"\u3000\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093 -jsp.error.noFunctionPrefix=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u540d\u524d\u7a7a\u9593\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u306a\u3044\u6642\u306b\u306f\u3001\u95a2\u6570 {0} \u306f\u30d7\u30ea\u30d5\u30a3\u30af\u30b9\u4ed8\u304d\u3067\u4f7f\u7528\u3057\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093 jsp.error.noFunction=\u95a2\u6570 {0} \u3092\u6307\u5b9a\u3055\u308c\u305f\u30d7\u30ea\u30d5\u30a3\u30af\u30b9\u3067\u914d\u7f6e\u3067\u304d\u307e\u305b\u3093 jsp.error.noFunctionMethod=\u95a2\u6570 \"{1}\" \u306e\u30e1\u30bd\u30c3\u30c9 \"{0}\" \u304c \"{2}\" \u4e2d\u3067\u898b\u3064\u304b\u308a\u307e\u305b\u3093 jsp.error.function.classnotfound=TLD\u306e\u4e2d\u3067\u95a2\u6570 {1} \u306b\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u30af\u30e9\u30b9 {0} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093: {2} Modified: tomcat/trunk/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java?rev=1653857&r1=1653856&r2=1653857&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java (original) +++ tomcat/trunk/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java Thu Jan 22 13:53:26 2015 @@ -97,6 +97,12 @@ public final class ProtectedFunctionMapp */ public void mapFunction(String fnQName, final Class<?> c, final String methodName, final Class<?>[] args) { + // Skip if null values were passed in. They indicate a function + // added via a lambda or ImportHandler; nether of which need to be + // placed in the Map. + if (fnQName == null) { + return; + } java.lang.reflect.Method method; if (SecurityUtil.isPackageProtectionEnabled()) { try { @@ -143,7 +149,7 @@ public final class ProtectedFunctionMapp */ public static ProtectedFunctionMapper getMapForFunction(String fnQName, final Class<?> c, final String methodName, final Class<?>[] args) { - java.lang.reflect.Method method; + java.lang.reflect.Method method = null; ProtectedFunctionMapper funcMapper; if (SecurityUtil.isPackageProtectionEnabled()) { funcMapper = AccessController.doPrivileged( @@ -153,28 +159,37 @@ public final class ProtectedFunctionMapp return new ProtectedFunctionMapper(); } }); - - try { - method = AccessController.doPrivileged( - new PrivilegedExceptionAction<Method>() { - @Override - public Method run() throws Exception { - return c.getDeclaredMethod(methodName, args); - } - }); - } catch (PrivilegedActionException ex) { - throw new RuntimeException( - "Invalid function mapping - no such method: " - + ex.getException().getMessage()); + // Skip if null values were passed in. They indicate a function + // added via a lambda or ImportHandler; nether of which need to be + // placed in the Map. + if (fnQName != null) { + try { + method = AccessController.doPrivileged( + new PrivilegedExceptionAction<Method>() { + @Override + public Method run() throws Exception { + return c.getDeclaredMethod(methodName, args); + } + }); + } catch (PrivilegedActionException ex) { + throw new RuntimeException( + "Invalid function mapping - no such method: " + + ex.getException().getMessage()); + } } } else { funcMapper = new ProtectedFunctionMapper(); - try { - method = c.getDeclaredMethod(methodName, args); - } catch (NoSuchMethodException e) { - throw new RuntimeException( - "Invalid function mapping - no such method: " - + e.getMessage()); + // Skip if null values were passed in. They indicate a function + // added via a lambda or ImportHandler; nether of which need to be + // placed in the Map. + if (fnQName != null) { + try { + method = c.getDeclaredMethod(methodName, args); + } catch (NoSuchMethodException e) { + throw new RuntimeException( + "Invalid function mapping - no such method: " + + e.getMessage()); + } } } funcMapper.theMethod = method; Modified: tomcat/trunk/test/org/apache/el/TestELInJsp.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/el/TestELInJsp.java?rev=1653857&r1=1653856&r2=1653857&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/el/TestELInJsp.java (original) +++ tomcat/trunk/test/org/apache/el/TestELInJsp.java Thu Jan 22 13:53:26 2015 @@ -430,6 +430,22 @@ public class TestELInJsp extends TomcatB } + /* + * BZ https://issues.apache.org/bugzilla/show_bug.cgi?id=57441 + * Can't validate function names defined in lambdas (or via imports) + */ + @Test + public void testBug57441() throws Exception { + getTomcatInstanceTestWebapp(false, true); + + ByteChunk res = getUrl("http://localhost:" + getPort() + + "/test/bug5nnnn/bug57441.jsp"); + + String result = res.toString(); + assertEcho(result, "00-11"); + } + + // Assertion for text contained with <p></p>, e.g. printed by tags:echo private static void assertEcho(String result, String expected) { Assert.assertTrue(result, result.indexOf("<p>" + expected + "</p>") > 0); Added: tomcat/trunk/test/webapp/bug5nnnn/bug57441.jsp URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp/bug5nnnn/bug57441.jsp?rev=1653857&view=auto ============================================================================== --- tomcat/trunk/test/webapp/bug5nnnn/bug57441.jsp (added) +++ tomcat/trunk/test/webapp/bug5nnnn/bug57441.jsp Thu Jan 22 13:53:26 2015 @@ -0,0 +1,22 @@ +<%-- + 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. +--%> +<%@page import="java.math.*, java.util.Collections" %> +<html> + <body> + <p>00-${incr = x->x+1; incr(10)}</p> + </body> +</html> \ No newline at end of file Propchange: tomcat/trunk/test/webapp/bug5nnnn/bug57441.jsp ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org