You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2015/01/22 14:53:27 UTC

svn commit: r1653857 - in /tomcat/trunk: java/org/apache/jasper/compiler/ java/org/apache/jasper/resources/ java/org/apache/jasper/runtime/ test/org/apache/el/ test/webapp/bug5nnnn/

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=\'&lt;\', when appears in the body of &lt;jsp:text&gt;, 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 = '&lt;', cuando aparece en el cuerpo de &lt;jsp\:text&gt;, 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=\'&lt;\'\u304c&lt;jsp:text&gt;\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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org