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 2021/07/08 21:05:03 UTC

[tomcat] branch main updated (35bd877 -> 2fcb104)

This is an automated email from the ASF dual-hosted git repository.

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


    from 35bd877  Add more generics to EL API to align with spec project
     new c57c361  ELSupport is a utility class. Refactor so it is accessed as one.
     new a37f7a1  Rename so strings get picked up by POEditor import/export code
     new 2fcb104  Add support for coercing LambdaExpression to any functional interface

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 ...Messages.properties => LocalStrings.properties} |  2 +
 ...es_es.properties => LocalStrings_es.properties} |  0
 java/org/apache/el/lang/ELSupport.java             | 36 ++++++++--
 java/org/apache/el/parser/AstAnd.java              |  5 +-
 java/org/apache/el/parser/AstChoice.java           |  3 +-
 java/org/apache/el/parser/AstConcatenation.java    |  5 +-
 java/org/apache/el/parser/AstEqual.java            |  3 +-
 java/org/apache/el/parser/AstFunction.java         |  5 +-
 java/org/apache/el/parser/AstGreaterThan.java      |  3 +-
 java/org/apache/el/parser/AstGreaterThanEqual.java |  3 +-
 java/org/apache/el/parser/AstLessThan.java         |  3 +-
 java/org/apache/el/parser/AstLessThanEqual.java    |  3 +-
 java/org/apache/el/parser/AstNegative.java         |  5 +-
 java/org/apache/el/parser/AstNot.java              |  3 +-
 java/org/apache/el/parser/AstNotEqual.java         |  3 +-
 java/org/apache/el/parser/AstOr.java               |  5 +-
 java/org/apache/el/parser/SimpleNode.java          |  3 +-
 java/org/apache/el/util/MessageFactory.java        |  3 +-
 test/org/apache/el/lang/TestELSupport.java         | 76 ++++++++++++++++++++++
 webapps/docs/changelog.xml                         |  5 ++
 20 files changed, 146 insertions(+), 28 deletions(-)
 rename java/org/apache/el/{Messages.properties => LocalStrings.properties} (96%)
 rename java/org/apache/el/{Messages_es.properties => LocalStrings_es.properties} (100%)

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


[tomcat] 02/03: Rename so strings get picked up by POEditor import/export code

Posted by ma...@apache.org.
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

commit a37f7a11a1b644c4e9e965da730824ea656d3a3a
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 8 21:50:04 2021 +0100

    Rename so strings get picked up by POEditor import/export code
    
    Because of the non-standard name, these strings were not exported so
    contributors providing translations have not been able to translate
    these strings.
---
 java/org/apache/el/{Messages.properties => LocalStrings.properties}    | 0
 .../apache/el/{Messages_es.properties => LocalStrings_es.properties}   | 0
 java/org/apache/el/util/MessageFactory.java                            | 3 +--
 3 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/java/org/apache/el/Messages.properties b/java/org/apache/el/LocalStrings.properties
similarity index 100%
rename from java/org/apache/el/Messages.properties
rename to java/org/apache/el/LocalStrings.properties
diff --git a/java/org/apache/el/Messages_es.properties b/java/org/apache/el/LocalStrings_es.properties
similarity index 100%
rename from java/org/apache/el/Messages_es.properties
rename to java/org/apache/el/LocalStrings_es.properties
diff --git a/java/org/apache/el/util/MessageFactory.java b/java/org/apache/el/util/MessageFactory.java
index 9222204..40f2dde 100644
--- a/java/org/apache/el/util/MessageFactory.java
+++ b/java/org/apache/el/util/MessageFactory.java
@@ -25,8 +25,7 @@ import java.util.ResourceBundle;
  */
 public final class MessageFactory {
 
-    static final ResourceBundle bundle =
-            ResourceBundle.getBundle("org.apache.el.Messages");
+    static final ResourceBundle bundle = ResourceBundle.getBundle("org.apache.el.LocalStrings");
 
     public MessageFactory() {
         super();

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


Re: [tomcat] 03/03: Add support for coercing LambdaExpression to any functional interface

Posted by Mark Thomas <ma...@apache.org>.
On 09/07/2021 11:40, Konstantin Kolinko wrote:
> пт, 9 июл. 2021 г. в 12:19, Mark Thomas <ma...@apache.org>:
>>
>> On 09/07/2021 09:58, Konstantin Kolinko wrote:
>>
>> Thanks Konstantin. This is good feedback.
>>
>> [...]
>>
>>> I wonder how Java itself (a java compiler) deals with coercion of
>>> lambdas to interfaces. Either it generates calls to some helper API,
>>> or it just repeats the same boilerplate code over and over.
>>
>> I'm not sure. I did look to see if there was anything in the public API
>> around this I could use to help but didn't find anything.
> 
> I found some info:
> 
> https://blogs.oracle.com/javamagazine/behind-the-scenes-how-do-lambda-expressions-really-work-in-java
> "Behind the scenes: How do lambda expressions really work in Java?"
> 
> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html
> 
>  From a quick read, it looks like it does not use reflection API, but a
> newer invocation API.
> I am not sure whether it is useful at this point. Just sharing.

I looked at that but the parsed lambda expression from the EL isn't in 
the same form as a lambda expression in Java code would be in. You'd 
need to convert it. You might be able to use something like 
https://github.com/greenjoe/lambdaFromString to do this conversion.

After looking at things like this for a while, I couldn't see a way to 
use them to create a solution that was an improvement on the Proxy approach.

Mark

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


Re: [tomcat] 03/03: Add support for coercing LambdaExpression to any functional interface

Posted by Konstantin Kolinko <kn...@gmail.com>.
пт, 9 июл. 2021 г. в 12:19, Mark Thomas <ma...@apache.org>:
>
> On 09/07/2021 09:58, Konstantin Kolinko wrote:
>
> Thanks Konstantin. This is good feedback.
>
> [...]
>
> > I wonder how Java itself (a java compiler) deals with coercion of
> > lambdas to interfaces. Either it generates calls to some helper API,
> > or it just repeats the same boilerplate code over and over.
>
> I'm not sure. I did look to see if there was anything in the public API
> around this I could use to help but didn't find anything.

I found some info:

https://blogs.oracle.com/javamagazine/behind-the-scenes-how-do-lambda-expressions-really-work-in-java
"Behind the scenes: How do lambda expressions really work in Java?"

https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html

From a quick read, it looks like it does not use reflection API, but a
newer invocation API.
I am not sure whether it is useful at this point. Just sharing.

Best regards,
Konstantin Kolinko

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


Re: [tomcat] 03/03: Add support for coercing LambdaExpression to any functional interface

Posted by Mark Thomas <ma...@apache.org>.
On 09/07/2021 09:58, Konstantin Kolinko wrote:

Thanks Konstantin. This is good feedback.

> пт, 9 июл. 2021 г. в 00:07, Mark Thomas <ma...@apache.org>:

<snip/>

>>>       Add support for coercing LambdaExpression to any functional interface
>>
>> The implementation for this turned out to be a lot simpler than I
>> initially thought. I can;t help be think I've missed something. Please
>> try and find ways to break this. If you do, feel free to add a disabled
>> out test case and I'll take a look.
> 
> Re: " if (obj instanceof LambdaExpression &&
> type.getAnnotation(FunctionalInterface.class) != null) "
> 
> 1. IIRC, using @FunctionalInterface annotation is a hint, not a requirement.
> 
> E.g. at https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html
> "the compiler will treat any interface meeting the definition"...
> 
> E.g. lambdas can be used with legacy code that does not use that annotation.

I'll look into how easy it would be to handle the case where the 
annotation isn't present. I'm a little concerned about the overhead of 
determining if the functional interface definition is met but if that 
turns out to be an issue then some form of caching is likely to help.

> 2. Inheritance? If the annotation is applied not on this class or
> interface, but on some of its parents.
> 
> Docs for "AnnotatedElement.getAnnotation(...)" - reading their
> definition of "present", I think that that method goes up a hierarchy
> of classes, but it does not go up a hierarchy of interfaces.
> https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AnnotatedElement.html
> 
> Example: a "SerializablePredicate" interface,
> https://vaadin.com/api/framework/8.13.2/com/vaadin/server/SerializablePredicate.html
> https://github.com/vaadin/framework/blob/master/server/src/main/java/com/vaadin/server/SerializablePredicate.java
> 
> The SerializablePredicate interface does not redeclare
> @FunctionalInterface, but it is a functional interface.

I'll look into that too.

>> Re: "if (!Modifier.isAbstract(method.getModifiers())) { throw...."
> 
> 3. While only one method is abstract, other methods may be called:
> (a) methods defined by Object -  equals(), hashCode() and toString(),
> (b) default methods defined in an interface.
> 
> The current code throws an ELException.
> 
> There is some sample code (though maybe not best) to deal with (a) at
> https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html
> 
> I do not know how people deal with (b). It may be that
> InvocationHandler won't see those calls to default methods. (When I
> studied java proxies, that feature did not exist yet.)

My thinking was that the proxy is only ever going to be used to map the 
LambdaExpression to the functional interface call. I couldn't see any 
way for any of those other methods to be called. Am I missing something?

> I wonder how Java itself (a java compiler) deals with coercion of
> lambdas to interfaces. Either it generates calls to some helper API,
> or it just repeats the same boilerplate code over and over.

I'm not sure. I did look to see if there was anything in the public API 
around this I could use to help but didn't find anything.

Thanks,

Mark

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


Re: [tomcat] 03/03: Add support for coercing LambdaExpression to any functional interface

Posted by Konstantin Kolinko <kn...@gmail.com>.
пт, 9 июл. 2021 г. в 00:07, Mark Thomas <ma...@apache.org>:
>
> On 08/07/2021 22:05, markt@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
> >
> > commit 2fcb104294b2676154cb08f00d5665d668792280
> > Author: Mark Thomas <ma...@apache.org>
> > AuthorDate: Thu Jul 8 22:02:26 2021 +0100
> >
> >      Add support for coercing LambdaExpression to any functional interface
>
> The implementation for this turned out to be a lot simpler than I
> initially thought. I can;t help be think I've missed something. Please
> try and find ways to break this. If you do, feel free to add a disabled
> out test case and I'll take a look.

Re: " if (obj instanceof LambdaExpression &&
type.getAnnotation(FunctionalInterface.class) != null) "

1. IIRC, using @FunctionalInterface annotation is a hint, not a requirement.

E.g. at https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html
"the compiler will treat any interface meeting the definition"...

E.g. lambdas can be used with legacy code that does not use that annotation.


2. Inheritance? If the annotation is applied not on this class or
interface, but on some of its parents.

Docs for "AnnotatedElement.getAnnotation(...)" - reading their
definition of "present", I think that that method goes up a hierarchy
of classes, but it does not go up a hierarchy of interfaces.
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AnnotatedElement.html

Example: a "SerializablePredicate" interface,
https://vaadin.com/api/framework/8.13.2/com/vaadin/server/SerializablePredicate.html
https://github.com/vaadin/framework/blob/master/server/src/main/java/com/vaadin/server/SerializablePredicate.java

The SerializablePredicate interface does not redeclare
@FunctionalInterface, but it is a functional interface.

> Re: "if (!Modifier.isAbstract(method.getModifiers())) { throw...."

3. While only one method is abstract, other methods may be called:
(a) methods defined by Object -  equals(), hashCode() and toString(),
(b) default methods defined in an interface.

The current code throws an ELException.

There is some sample code (though maybe not best) to deal with (a) at
https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html

I do not know how people deal with (b). It may be that
InvocationHandler won't see those calls to default methods. (When I
studied java proxies, that feature did not exist yet.)

I wonder how Java itself (a java compiler) deals with coercion of
lambdas to interfaces. Either it generates calls to some helper API,
or it just repeats the same boilerplate code over and over.

Best regards,
Konstantin Kolinko

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


Re: [tomcat] 03/03: Add support for coercing LambdaExpression to any functional interface

Posted by Mark Thomas <ma...@apache.org>.
On 08/07/2021 22:05, markt@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
> 
> commit 2fcb104294b2676154cb08f00d5665d668792280
> Author: Mark Thomas <ma...@apache.org>
> AuthorDate: Thu Jul 8 22:02:26 2021 +0100
> 
>      Add support for coercing LambdaExpression to any functional interface

The implementation for this turned out to be a lot simpler than I 
initially thought. I can;t help be think I've missed something. Please 
try and find ways to break this. If you do, feel free to add a disabled 
out test case and I'll take a look.

Thanks,

Mark

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


[tomcat] 03/03: Add support for coercing LambdaExpression to any functional interface

Posted by ma...@apache.org.
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

commit 2fcb104294b2676154cb08f00d5665d668792280
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 8 22:02:26 2021 +0100

    Add support for coercing LambdaExpression to any functional interface
    
    This addresses this currently open issue against the EL spec
    https://github.com/eclipse-ee4j/el-ri/issues/45
    This is an initial implementation so users can provide feedback
    The implementation was inspired by rmuller's suggestion for an
    ELResolver that performs a similar function:
    https://stackoverflow.com/questions/46573761
---
 java/org/apache/el/LocalStrings.properties |  2 +
 java/org/apache/el/lang/ELSupport.java     | 27 +++++++++++
 test/org/apache/el/lang/TestELSupport.java | 76 ++++++++++++++++++++++++++++++
 webapps/docs/changelog.xml                 |  5 ++
 4 files changed, 110 insertions(+)

diff --git a/java/org/apache/el/LocalStrings.properties b/java/org/apache/el/LocalStrings.properties
index 1bf600d..d9f5503 100644
--- a/java/org/apache/el/LocalStrings.properties
+++ b/java/org/apache/el/LocalStrings.properties
@@ -13,6 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+elSupport.coerce.nonAbstract=Unable to coerce a LambdaExpression to the functional interface [{0}] because the method [{1}] is not abstract
+
 # General Errors
 error.cannotSetVariables=Cannot set variables on factory
 error.convert=Cannot convert [{0}] of type [{1}] to [{2}]
diff --git a/java/org/apache/el/lang/ELSupport.java b/java/org/apache/el/lang/ELSupport.java
index 808ad79..c37fbac 100644
--- a/java/org/apache/el/lang/ELSupport.java
+++ b/java/org/apache/el/lang/ELSupport.java
@@ -19,6 +19,9 @@ package org.apache.el.lang;
 import java.beans.PropertyEditor;
 import java.beans.PropertyEditorManager;
 import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.security.AccessController;
@@ -29,6 +32,7 @@ import java.util.Set;
 
 import jakarta.el.ELContext;
 import jakarta.el.ELException;
+import jakarta.el.LambdaExpression;
 
 import org.apache.el.util.MessageFactory;
 
@@ -588,6 +592,11 @@ public class ELSupport {
             return result;
         }
 
+        if (obj instanceof LambdaExpression && type.getAnnotation(FunctionalInterface.class) != null) {
+            T result = coerceToFunctionalInterface(ctx, (LambdaExpression) obj, type);
+            return result;
+        }
+
         throw new ELException(MessageFactory.get("error.convert",
                 obj, obj.getClass(), type));
     }
@@ -613,6 +622,24 @@ public class ELSupport {
         return result;
     }
 
+
+    private static <T> T coerceToFunctionalInterface(final ELContext ctx, final LambdaExpression lambdaExpression,
+            final Class<T> type) {
+        // Create a dynamic proxy for the functional interface
+        @SuppressWarnings("unchecked")
+        T result = (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type },
+                (Object obj, Method method, Object[] args) -> {
+            // Functional interfaces have a single, abstract method
+            if (!Modifier.isAbstract(method.getModifiers())) {
+                // TODO
+                throw new ELException(MessageFactory.get("elSupport.coerce.nonAbstract", type, method));
+            }
+            return lambdaExpression.invoke(ctx, args);
+        });
+        return result;
+    }
+
+
     public static final boolean isBigDecimalOp(final Object obj0,
             final Object obj1) {
         return (obj0 instanceof BigDecimal || obj1 instanceof BigDecimal);
diff --git a/test/org/apache/el/lang/TestELSupport.java b/test/org/apache/el/lang/TestELSupport.java
index 84d3ed4..672afd5 100644
--- a/test/org/apache/el/lang/TestELSupport.java
+++ b/test/org/apache/el/lang/TestELSupport.java
@@ -19,9 +19,11 @@ package org.apache.el.lang;
 import java.beans.PropertyEditorManager;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.function.Predicate;
 
 import jakarta.el.ELException;
 import jakarta.el.ELManager;
+import jakarta.el.ELProcessor;
 
 import org.junit.Assert;
 import org.junit.Test;
@@ -276,4 +278,78 @@ public class TestELSupport {
         VALB1,
         VALB2
     }
+
+
+    @Test
+    public void testCoercetoFunctionalInterface01() throws Exception {
+        final ELProcessor elp = new ELProcessor();
+        elp.defineFunction("", "", "org.apache.el.lang.TestELSupport", "testPredicateA");
+        Object result = elp.eval("testPredicateA(x -> x.equals('data'))");
+        Assert.assertEquals("PASS", result);
+    }
+
+
+    @Test
+    public void testCoercetoFunctionalInterface02() throws Exception {
+        final ELProcessor elp = new ELProcessor();
+        elp.defineFunction("", "", "org.apache.el.lang.TestELSupport", "testPredicateA");
+        Object result = elp.eval("testPredicateA(x -> !x.equals('data'))");
+        Assert.assertEquals("BLOCK", result);
+    }
+
+
+    @Test
+    public void testCoercetoFunctionalInterface03() throws Exception {
+        final ELProcessor elp = new ELProcessor();
+        elp.defineFunction("", "", "org.apache.el.lang.TestELSupport", "testPredicateB");
+        Object result = elp.eval("testPredicateB(x -> x > 50)");
+        Assert.assertEquals("PASS", result);
+    }
+
+
+    @Test
+    public void testCoercetoFunctionalInterface04() throws Exception {
+        final ELProcessor elp = new ELProcessor();
+        elp.defineFunction("", "", "org.apache.el.lang.TestELSupport", "testPredicateB");
+        Object result = elp.eval("testPredicateB(x -> x < 50)");
+        Assert.assertEquals("BLOCK", result);
+    }
+
+
+    @Test(expected = ELException.class)
+    public void testCoercetoFunctionalInterface05() throws Exception {
+        final ELProcessor elp = new ELProcessor();
+        elp.defineFunction("", "", "org.apache.el.lang.TestELSupport", "testPredicateC");
+        elp.eval("testPredicateC(x -> x > 50)");
+    }
+
+
+    public static String testPredicateA(Predicate<String> filter) {
+        String s = "data";
+        if (filter.test(s)) {
+            return "PASS";
+        } else {
+            return "BLOCK";
+        }
+    }
+
+
+    public static String testPredicateB(Predicate<Long> filter) {
+        Long l = Long.valueOf(100);
+        if (filter.test(l)) {
+            return "PASS";
+        } else {
+            return "BLOCK";
+        }
+    }
+
+
+    public static String testPredicateC(Predicate<String> filter) {
+        String s = "text";
+        if (filter.test(s)) {
+            return "PASS";
+        } else {
+            return "BLOCK";
+        }
+    }
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 2e78aa9..4cec1f7 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -148,6 +148,11 @@
         Add additional generics to the EL API to align with the latest changes
         in the EL specification project. (markt)
       </scode>
+      <add>
+        Enable EL lambda expressions to be coerced to functional interfaces.
+        This is an implementation of a proposed extension to the Jakarta
+        Expression Language specification. (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Web applications">

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


[tomcat] 01/03: ELSupport is a utility class. Refactor so it is accessed as one.

Posted by ma...@apache.org.
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

commit c57c3619f75f5ddc21d79f58bdda1d0866da46cb
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jul 8 20:55:20 2021 +0100

    ELSupport is a utility class. Refactor so it is accessed as one.
---
 java/org/apache/el/lang/ELSupport.java             | 9 +++------
 java/org/apache/el/parser/AstAnd.java              | 5 +++--
 java/org/apache/el/parser/AstChoice.java           | 3 ++-
 java/org/apache/el/parser/AstConcatenation.java    | 5 +++--
 java/org/apache/el/parser/AstEqual.java            | 3 ++-
 java/org/apache/el/parser/AstFunction.java         | 5 +++--
 java/org/apache/el/parser/AstGreaterThan.java      | 3 ++-
 java/org/apache/el/parser/AstGreaterThanEqual.java | 3 ++-
 java/org/apache/el/parser/AstLessThan.java         | 3 ++-
 java/org/apache/el/parser/AstLessThanEqual.java    | 3 ++-
 java/org/apache/el/parser/AstNegative.java         | 5 +++--
 java/org/apache/el/parser/AstNot.java              | 3 ++-
 java/org/apache/el/parser/AstNotEqual.java         | 3 ++-
 java/org/apache/el/parser/AstOr.java               | 5 +++--
 java/org/apache/el/parser/SimpleNode.java          | 3 +--
 15 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/java/org/apache/el/lang/ELSupport.java b/java/org/apache/el/lang/ELSupport.java
index 7a81015..808ad79 100644
--- a/java/org/apache/el/lang/ELSupport.java
+++ b/java/org/apache/el/lang/ELSupport.java
@@ -660,11 +660,8 @@ public class ELSupport {
         return false;
     }
 
-    /**
-     *
-     */
-    public ELSupport() {
-        super();
-    }
 
+    private ELSupport() {
+        // Uility class - hide default constructor;
+    }
 }
diff --git a/java/org/apache/el/parser/AstAnd.java b/java/org/apache/el/parser/AstAnd.java
index b65c731..85d268e 100644
--- a/java/org/apache/el/parser/AstAnd.java
+++ b/java/org/apache/el/parser/AstAnd.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -34,12 +35,12 @@ public final class AstAnd extends BooleanNode {
     public Object getValue(EvaluationContext ctx)
             throws ELException {
         Object obj = children[0].getValue(ctx);
-        Boolean b = coerceToBoolean(ctx, obj, true);
+        Boolean b = ELSupport.coerceToBoolean(ctx, obj, true);
         if (!b.booleanValue()) {
             return b;
         }
         obj = children[1].getValue(ctx);
-        b = coerceToBoolean(ctx, obj, true);
+        b = ELSupport.coerceToBoolean(ctx, obj, true);
         return b;
     }
 }
diff --git a/java/org/apache/el/parser/AstChoice.java b/java/org/apache/el/parser/AstChoice.java
index 5819ead..173ea22 100644
--- a/java/org/apache/el/parser/AstChoice.java
+++ b/java/org/apache/el/parser/AstChoice.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -41,7 +42,7 @@ public final class AstChoice extends SimpleNode {
     public Object getValue(EvaluationContext ctx)
             throws ELException {
         Object obj0 = this.children[0].getValue(ctx);
-        Boolean b0 = coerceToBoolean(ctx, obj0, true);
+        Boolean b0 = ELSupport.coerceToBoolean(ctx, obj0, true);
         return this.children[((b0.booleanValue() ? 1 : 2))].getValue(ctx);
     }
 }
diff --git a/java/org/apache/el/parser/AstConcatenation.java b/java/org/apache/el/parser/AstConcatenation.java
index f26e0a3..ae83893 100644
--- a/java/org/apache/el/parser/AstConcatenation.java
+++ b/java/org/apache/el/parser/AstConcatenation.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 public class AstConcatenation extends SimpleNode {
@@ -31,8 +32,8 @@ public class AstConcatenation extends SimpleNode {
     @Override
     public Object getValue(EvaluationContext ctx) throws ELException {
         // Coerce the two child nodes to string and then concatenate
-        String s1 = coerceToString(ctx, children[0].getValue(ctx));
-        String s2 = coerceToString(ctx, children[1].getValue(ctx));
+        String s1 = ELSupport.coerceToString(ctx, children[0].getValue(ctx));
+        String s2 = ELSupport.coerceToString(ctx, children[1].getValue(ctx));
         return s1 + s2;
     }
 
diff --git a/java/org/apache/el/parser/AstEqual.java b/java/org/apache/el/parser/AstEqual.java
index a5a45cf..4a9b53e 100644
--- a/java/org/apache/el/parser/AstEqual.java
+++ b/java/org/apache/el/parser/AstEqual.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -35,6 +36,6 @@ public final class AstEqual extends BooleanNode {
             throws ELException {
         Object obj0 = this.children[0].getValue(ctx);
         Object obj1 = this.children[1].getValue(ctx);
-        return Boolean.valueOf(equals(ctx, obj0, obj1));
+        return Boolean.valueOf(ELSupport.equals(ctx, obj0, obj1));
     }
 }
diff --git a/java/org/apache/el/parser/AstFunction.java b/java/org/apache/el/parser/AstFunction.java
index 9c58d96..3ce652f 100644
--- a/java/org/apache/el/parser/AstFunction.java
+++ b/java/org/apache/el/parser/AstFunction.java
@@ -27,6 +27,7 @@ import jakarta.el.LambdaExpression;
 import jakarta.el.ValueExpression;
 import jakarta.el.VariableMapper;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 import org.apache.el.util.MessageFactory;
 
@@ -180,14 +181,14 @@ public final class AstFunction extends SimpleNode {
                             Class<?> target = paramTypes[i].getComponentType();
                             for (int j = i; j < inputParameterCount; j++) {
                                 varargs[j-i] = parameters.jjtGetChild(j).getValue(ctx);
-                                varargs[j-i] = coerceToType(ctx, varargs[j-i], target);
+                                varargs[j-i] = ELSupport.coerceToType(ctx, varargs[j-i], target);
                             }
                             params[i] = varargs;
                         }
                     } else {
                         params[i] = parameters.jjtGetChild(i).getValue(ctx);
                     }
-                    params[i] = coerceToType(ctx, params[i], paramTypes[i]);
+                    params[i] = ELSupport.coerceToType(ctx, params[i], paramTypes[i]);
                 }
             } catch (ELException ele) {
                 throw new ELException(MessageFactory.get("error.function", this
diff --git a/java/org/apache/el/parser/AstGreaterThan.java b/java/org/apache/el/parser/AstGreaterThan.java
index 2ba8f78..953947c 100644
--- a/java/org/apache/el/parser/AstGreaterThan.java
+++ b/java/org/apache/el/parser/AstGreaterThan.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -41,6 +42,6 @@ public final class AstGreaterThan extends BooleanNode {
         if (obj1 == null) {
             return Boolean.FALSE;
         }
-        return (compare(ctx, obj0, obj1) > 0) ? Boolean.TRUE : Boolean.FALSE;
+        return (ELSupport.compare(ctx, obj0, obj1) > 0) ? Boolean.TRUE : Boolean.FALSE;
     }
 }
diff --git a/java/org/apache/el/parser/AstGreaterThanEqual.java b/java/org/apache/el/parser/AstGreaterThanEqual.java
index 624fc5e..3095546 100644
--- a/java/org/apache/el/parser/AstGreaterThanEqual.java
+++ b/java/org/apache/el/parser/AstGreaterThanEqual.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -41,6 +42,6 @@ public final class AstGreaterThanEqual extends BooleanNode {
         if (obj0 == null || obj1 == null) {
             return Boolean.FALSE;
         }
-        return (compare(ctx, obj0, obj1) >= 0) ? Boolean.TRUE : Boolean.FALSE;
+        return (ELSupport.compare(ctx, obj0, obj1) >= 0) ? Boolean.TRUE : Boolean.FALSE;
     }
 }
diff --git a/java/org/apache/el/parser/AstLessThan.java b/java/org/apache/el/parser/AstLessThan.java
index 7c20e53..f7882dd 100644
--- a/java/org/apache/el/parser/AstLessThan.java
+++ b/java/org/apache/el/parser/AstLessThan.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -41,6 +42,6 @@ public final class AstLessThan extends BooleanNode {
         if (obj1 == null) {
             return Boolean.FALSE;
         }
-        return (compare(ctx, obj0, obj1) < 0) ? Boolean.TRUE : Boolean.FALSE;
+        return (ELSupport.compare(ctx, obj0, obj1) < 0) ? Boolean.TRUE : Boolean.FALSE;
     }
 }
diff --git a/java/org/apache/el/parser/AstLessThanEqual.java b/java/org/apache/el/parser/AstLessThanEqual.java
index 4b1463b..2baadb6 100644
--- a/java/org/apache/el/parser/AstLessThanEqual.java
+++ b/java/org/apache/el/parser/AstLessThanEqual.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -41,6 +42,6 @@ public final class AstLessThanEqual extends BooleanNode {
         if (obj0 == null || obj1 == null) {
             return Boolean.FALSE;
         }
-        return (compare(ctx, obj0, obj1) <= 0) ? Boolean.TRUE : Boolean.FALSE;
+        return (ELSupport.compare(ctx, obj0, obj1) <= 0) ? Boolean.TRUE : Boolean.FALSE;
     }
 }
diff --git a/java/org/apache/el/parser/AstNegative.java b/java/org/apache/el/parser/AstNegative.java
index 9a24415..c2a540c 100644
--- a/java/org/apache/el/parser/AstNegative.java
+++ b/java/org/apache/el/parser/AstNegative.java
@@ -22,6 +22,7 @@ import java.math.BigInteger;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -54,7 +55,7 @@ public final class AstNegative extends SimpleNode {
             return ((BigInteger) obj).negate();
         }
         if (obj instanceof String) {
-            if (isStringFloat((String) obj)) {
+            if (ELSupport.isStringFloat((String) obj)) {
                 return Double.valueOf(-Double.parseDouble((String) obj));
             }
             return Long.valueOf(-Long.parseLong((String) obj));
@@ -77,7 +78,7 @@ public final class AstNegative extends SimpleNode {
         if (obj instanceof Byte) {
             return Byte.valueOf((byte) -((Byte) obj).byteValue());
         }
-        Long num = (Long) coerceToNumber(ctx, obj, Long.class);
+        Long num = (Long) ELSupport.coerceToNumber(ctx, obj, Long.class);
         return Long.valueOf(-num.longValue());
     }
 }
diff --git a/java/org/apache/el/parser/AstNot.java b/java/org/apache/el/parser/AstNot.java
index 75178d3..1a16180 100644
--- a/java/org/apache/el/parser/AstNot.java
+++ b/java/org/apache/el/parser/AstNot.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -40,7 +41,7 @@ public final class AstNot extends SimpleNode {
     public Object getValue(EvaluationContext ctx)
             throws ELException {
         Object obj = this.children[0].getValue(ctx);
-        Boolean b = coerceToBoolean(ctx, obj, true);
+        Boolean b = ELSupport.coerceToBoolean(ctx, obj, true);
         return Boolean.valueOf(!b.booleanValue());
     }
 }
diff --git a/java/org/apache/el/parser/AstNotEqual.java b/java/org/apache/el/parser/AstNotEqual.java
index e484d60..5f19904 100644
--- a/java/org/apache/el/parser/AstNotEqual.java
+++ b/java/org/apache/el/parser/AstNotEqual.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -35,6 +36,6 @@ public final class AstNotEqual extends BooleanNode {
             throws ELException {
         Object obj0 = this.children[0].getValue(ctx);
         Object obj1 = this.children[1].getValue(ctx);
-        return Boolean.valueOf(!equals(ctx, obj0, obj1));
+        return Boolean.valueOf(!ELSupport.equals(ctx, obj0, obj1));
     }
 }
diff --git a/java/org/apache/el/parser/AstOr.java b/java/org/apache/el/parser/AstOr.java
index 618cd0b..a16a04c 100644
--- a/java/org/apache/el/parser/AstOr.java
+++ b/java/org/apache/el/parser/AstOr.java
@@ -19,6 +19,7 @@ package org.apache.el.parser;
 
 import jakarta.el.ELException;
 
+import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 
 
@@ -34,12 +35,12 @@ public final class AstOr extends BooleanNode {
     public Object getValue(EvaluationContext ctx)
             throws ELException {
         Object obj = this.children[0].getValue(ctx);
-        Boolean b = coerceToBoolean(ctx, obj, true);
+        Boolean b = ELSupport.coerceToBoolean(ctx, obj, true);
         if (b.booleanValue()) {
             return b;
         }
         obj = this.children[1].getValue(ctx);
-        b = coerceToBoolean(ctx, obj, true);
+        b = ELSupport.coerceToBoolean(ctx, obj, true);
         return b;
     }
 }
diff --git a/java/org/apache/el/parser/SimpleNode.java b/java/org/apache/el/parser/SimpleNode.java
index ad3375b..b50645a 100644
--- a/java/org/apache/el/parser/SimpleNode.java
+++ b/java/org/apache/el/parser/SimpleNode.java
@@ -24,7 +24,6 @@ import jakarta.el.MethodInfo;
 import jakarta.el.PropertyNotWritableException;
 import jakarta.el.ValueReference;
 
-import org.apache.el.lang.ELSupport;
 import org.apache.el.lang.EvaluationContext;
 import org.apache.el.util.MessageFactory;
 
@@ -32,7 +31,7 @@ import org.apache.el.util.MessageFactory;
 /**
  * @author Jacob Hookom [jacob@hookom.net]
  */
-public abstract class SimpleNode extends ELSupport implements Node {
+public abstract class SimpleNode implements Node {
     protected Node parent;
 
     protected Node[] children;

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