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