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 79a0e29a61 Fix BZ 68119 - Refactor for improved performance during 
type conversion
79a0e29a61 is described below

commit 79a0e29a611d582135ebfb3740c060363c13f877
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Nov 27 14:01:49 2023 +0000

    Fix BZ 68119 - Refactor for improved performance during type conversion
    
    https://bz.apache.org/bugzilla/show_bug.cgi?id=68119
---
 java/jakarta/el/CompositeELResolver.java | 49 ++++++++++++++++++++++++++++++--
 webapps/docs/changelog.xml               |  8 ++++++
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/java/jakarta/el/CompositeELResolver.java 
b/java/jakarta/el/CompositeELResolver.java
index 5c931dfe05..f8050c5809 100644
--- a/java/jakarta/el/CompositeELResolver.java
+++ b/java/jakarta/el/CompositeELResolver.java
@@ -16,11 +16,14 @@
  */
 package jakarta.el;
 
+import java.util.HashSet;
 import java.util.Objects;
+import java.util.Set;
 
 public class CompositeELResolver extends ELResolver {
 
     private static final Class<?> SCOPED_ATTRIBUTE_EL_RESOLVER;
+    private static final Set<String> KNOWN_NON_TYPE_CONVERTING_RESOLVERS = new 
HashSet<>();
     static {
         Class<?> clazz = null;
         try {
@@ -29,15 +32,43 @@ public class CompositeELResolver extends ELResolver {
             // Ignore. This is expected if using the EL stand-alone
         }
         SCOPED_ATTRIBUTE_EL_RESOLVER = clazz;
+
+        // EL API Resolvers
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(ArrayELResolver.class.getName());
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(BeanELResolver.class.getName());
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(BeanNameELResolver.class.getName());
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(ListELResolver.class.getName());
+        KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(MapELResolver.class.getName());
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(OptionalELResolver.class.getName());
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(RecordELResolver.class.getName());
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(ResourceBundleELResolver.class.getName());
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add(StaticFieldELResolver.class.getName());
+        // JSP API Resolvers - referenced by name to avoid creating dependency
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add("jakarta.servlet.jsp.el.ImplicitObjectELResolver");
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add("jakarta.servlet.jsp.el.ImportELResolver");
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add("jakarta.servlet.jsp.el.NotFoundELResolver");
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add("jakarta.servlet.jsp.el.ScopedAttributeELResolver");
+        // Tomcat internal resolvers - referenced by name to avoid creating 
dependency
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add("org.apache.jasper.el.JasperELResolver");
+        
KNOWN_NON_TYPE_CONVERTING_RESOLVERS.add("org.apache.el.stream.StreamELResolverImpl");
     }
 
     private int resolversSize;
-
     private ELResolver[] resolvers;
 
+    /*
+     * Use a separate array for ELResolvers that might implement type 
conversion as a performance optimisation. See
+     * https://bz.apache.org/bugzilla/show_bug.cgi?id=68119
+     */
+    private int typeConvertersSize;
+    private ELResolver[] typeConverters;
+
     public CompositeELResolver() {
         resolversSize = 0;
         resolvers = new ELResolver[8];
+
+        typeConvertersSize = 0;
+        typeConverters = new ELResolver[0];
     }
 
     public void add(ELResolver elResolver) {
@@ -53,6 +84,20 @@ public class CompositeELResolver extends ELResolver {
             resolvers = nr;
         }
         resolvers[resolversSize++] = elResolver;
+
+        if 
(KNOWN_NON_TYPE_CONVERTING_RESOLVERS.contains(elResolver.getClass().getName())) 
{
+            // Performance optimisation. ELResolver known not to perform type 
conversion
+            return;
+        }
+
+        if (typeConvertersSize == 0) {
+            typeConverters = new ELResolver[1];
+        } else if (typeConvertersSize == typeConverters.length) {
+            ELResolver[] expandedTypeConverters = new 
ELResolver[typeConvertersSize * 2];
+            System.arraycopy(typeConverters, 0, expandedTypeConverters, 0, 
typeConvertersSize);
+            typeConverters = expandedTypeConverters;
+        }
+        typeConverters[typeConvertersSize++] = elResolver;
     }
 
     @Override
@@ -145,7 +190,7 @@ public class CompositeELResolver extends ELResolver {
     @Override
     public <T> T convertToType(ELContext context, Object obj, Class<T> type) {
         context.setPropertyResolved(false);
-        int sz = this.resolversSize;
+        int sz = typeConvertersSize;
         for (int i = 0; i < sz; i++) {
             T result = this.resolvers[i].convertToType(context, obj, type);
             if (context.isPropertyResolved()) {
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index e4f507a131..4099b3aa04 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -132,6 +132,14 @@
       </fix>
     </changelog>
   </subsection>
+  <subsection name="Jasper">
+    <changelog>
+      <scode>
+        <bug>68119</bug>: Refactor the <code>CompositeELResolver</code> to
+        improve performance during type conversion operations. (markt)
+      </scode>
+    </changelog>
+  </subsection>
   <subsection name="Other">
     <changelog>
       <update>


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

Reply via email to