Mark,

On 3/21/23 11:19, ma...@apache.org wrote:
This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/main by this push:
      new 0bc6e4f4c9 Fix LambdaExpression to functional interface coercion
0bc6e4f4c9 is described below

commit 0bc6e4f4c91804f1d2dd3102947393e928f5d58e
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Mar 21 15:19:07 2023 +0000

     Fix LambdaExpression to functional interface coercion
---
  java/jakarta/el/ELContext.java                  | 67 +++++++++++++++++++
  java/org/apache/el/lang/ELSupport.java          | 12 +++-
  test/org/apache/el/TestValueExpressionImpl.java | 86 +++++++++++++++++++++++++
  test/org/apache/el/TesterBeanJ.java             | 50 ++++++++++++++
  webapps/docs/changelog.xml                      |  9 +++
  5 files changed, 223 insertions(+), 1 deletion(-)

diff --git a/java/jakarta/el/ELContext.java b/java/jakarta/el/ELContext.java
index 0f6d221cc9..0e80de277f 100644
--- a/java/jakarta/el/ELContext.java
+++ b/java/jakarta/el/ELContext.java
@@ -16,6 +16,8 @@
   */
  package jakarta.el;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
  import java.util.ArrayDeque;
  import java.util.ArrayList;
  import java.util.Collections;
@@ -310,6 +312,71 @@ public abstract class ELContext {
              setPropertyResolved(originalResolved);
          }
+ if (obj instanceof LambdaExpression && isFunctionalInterface(type)) {
+            ((LambdaExpression) obj).setELContext(this);
+        }
+
          return ELManager.getExpressionFactory().coerceToType(obj, type);
      }
+
+
+    /*
+     * Copied from org.apache.el.lang.ELSupport - keep in sync
+     */
+    static boolean isFunctionalInterface(Class<?> type) {
+
+        if (!type.isInterface()) {
+            return false;
+        }
+
+        boolean foundAbstractMethod = false;
+        Method[] methods = type.getMethods();
+        for (Method method : methods) {
+            if (Modifier.isAbstract(method.getModifiers())) {
+                // Abstract methods that override one of the public methods
+                // of Object don't count
+                if (overridesObjectMethod(method)) {
+                    continue;
+                }
+                if (foundAbstractMethod) {
+                    // Found more than one
+                    return false;
+                } else {
+                    foundAbstractMethod = true;
+                }
+            }
+        }
+        return foundAbstractMethod;
+    }
+
+
+    /*
+     * Copied from org.apache.el.lang.ELSupport - keep in sync
+     */
+    private static boolean overridesObjectMethod(Method method) {
+        // There are three methods that can be overridden
+        if ("equals".equals(method.getName())) {
+            if (method.getReturnType().equals(boolean.class)) {
+                if (method.getParameterCount() == 1) {
+                    if (method.getParameterTypes()[0].equals(Object.class)) {
+                        return true;
+                    }
+                }
+            }
+        } else if ("hashCode".equals(method.getName())) {
+            if (method.getReturnType().equals(int.class)) {
+                if (method.getParameterCount() == 0) {
+                    return true;
+                }
+            }
+        } else if ("toString".equals(method.getName())) {
+            if (method.getReturnType().equals(String.class)) {
+                if (method.getParameterCount() == 0) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
  }

I'm curious about this.

How is a "functional interface" (i.e. all methods are abstract, except for those which were originally-defined in java.lang.Object and for some reason overridden to be abstract in this functional-interface) different from an actual interface, and why does JSP care?

I can't tell what the use-case is from reading the unit tests.

-chris

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

Reply via email to