This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.1.x by this push: new 28dff349f7 Improve performance of scope lookups 28dff349f7 is described below commit 28dff349f7b826e9c040e8a5d2f6857d5ffb33e3 Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Sep 21 15:11:02 2023 +0100 Improve performance of scope lookups --- .../servlet/jsp/el/ImplicitObjectELResolver.java | 172 +++++++++++++-------- webapps/docs/changelog.xml | 9 ++ 2 files changed, 115 insertions(+), 66 deletions(-) diff --git a/java/jakarta/servlet/jsp/el/ImplicitObjectELResolver.java b/java/jakarta/servlet/jsp/el/ImplicitObjectELResolver.java index 2d6a632492..b1338ca2b3 100644 --- a/java/jakarta/servlet/jsp/el/ImplicitObjectELResolver.java +++ b/java/jakarta/servlet/jsp/el/ImplicitObjectELResolver.java @@ -19,9 +19,9 @@ package jakarta.servlet.jsp.el; import java.beans.FeatureDescriptor; import java.util.AbstractMap; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -45,31 +45,6 @@ import jakarta.servlet.jsp.PageContext; */ public class ImplicitObjectELResolver extends ELResolver { - private static final String[] SCOPE_NAMES = new String[] { "applicationScope", "cookie", "header", "headerValues", - "initParam", "pageContext", "pageScope", "param", "paramValues", "requestScope", "sessionScope" }; - - private static final int APPLICATIONSCOPE = 0; - - private static final int COOKIE = 1; - - private static final int HEADER = 2; - - private static final int HEADERVALUES = 3; - - private static final int INITPARAM = 4; - - private static final int PAGECONTEXT = 5; - - private static final int PAGESCOPE = 6; - - private static final int PARAM = 7; - - private static final int PARAM_VALUES = 8; - - private static final int REQUEST_SCOPE = 9; - - private static final int SESSION_SCOPE = 10; - /** * Creates an instance of the implicit object resolver for EL. */ @@ -82,35 +57,9 @@ public class ImplicitObjectELResolver extends ELResolver { Objects.requireNonNull(context); if (base == null && property != null) { - int idx = Arrays.binarySearch(SCOPE_NAMES, property.toString()); - - if (idx >= 0) { - PageContext page = (PageContext) context.getContext(JspContext.class); - context.setPropertyResolved(base, property); - switch (idx) { - case APPLICATIONSCOPE: - return ScopeManager.get(page).getApplicationScope(); - case COOKIE: - return ScopeManager.get(page).getCookie(); - case HEADER: - return ScopeManager.get(page).getHeader(); - case HEADERVALUES: - return ScopeManager.get(page).getHeaderValues(); - case INITPARAM: - return ScopeManager.get(page).getInitParam(); - case PAGECONTEXT: - return ScopeManager.get(page).getPageContext(); - case PAGESCOPE: - return ScopeManager.get(page).getPageScope(); - case PARAM: - return ScopeManager.get(page).getParam(); - case PARAM_VALUES: - return ScopeManager.get(page).getParamValues(); - case REQUEST_SCOPE: - return ScopeManager.get(page).getRequestScope(); - case SESSION_SCOPE: - return ScopeManager.get(page).getSessionScope(); - } + Scope scope = Scope.lookupMap.get(property.toString()); + if (scope != null) { + return scope.getScopeValue(context, base, property); } } return null; @@ -121,8 +70,7 @@ public class ImplicitObjectELResolver extends ELResolver { Objects.requireNonNull(context); if (base == null && property != null) { - int idx = Arrays.binarySearch(SCOPE_NAMES, property.toString()); - if (idx >= 0) { + if (Scope.lookupMap.containsKey(property.toString())) { context.setPropertyResolved(base, property); } } @@ -134,8 +82,7 @@ public class ImplicitObjectELResolver extends ELResolver { Objects.requireNonNull(context); if (base == null && property != null) { - int idx = Arrays.binarySearch(SCOPE_NAMES, property.toString()); - if (idx >= 0) { + if (Scope.lookupMap.containsKey(property.toString())) { context.setPropertyResolved(base, property); throw new PropertyNotWritableException(); } @@ -147,8 +94,7 @@ public class ImplicitObjectELResolver extends ELResolver { Objects.requireNonNull(context); if (base == null && property != null) { - int idx = Arrays.binarySearch(SCOPE_NAMES, property.toString()); - if (idx >= 0) { + if (Scope.lookupMap.containsKey(property.toString())) { context.setPropertyResolved(base, property); return true; } @@ -159,14 +105,14 @@ public class ImplicitObjectELResolver extends ELResolver { @Deprecated(forRemoval = true, since = "JSP 3.1") @Override public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) { - List<FeatureDescriptor> feats = new ArrayList<>(SCOPE_NAMES.length); + List<FeatureDescriptor> feats = new ArrayList<>(Scope.values().length); FeatureDescriptor feat; - for (String scopeName : SCOPE_NAMES) { + for (Scope scope : Scope.values()) { feat = new FeatureDescriptor(); - feat.setDisplayName(scopeName); + feat.setDisplayName(scope.implicitName); feat.setExpert(false); feat.setHidden(false); - feat.setName(scopeName); + feat.setName(scope.implicitName); feat.setPreferred(true); feat.setValue(RESOLVABLE_AT_DESIGN_TIME, Boolean.TRUE); feat.setValue(TYPE, String.class); @@ -183,6 +129,7 @@ public class ImplicitObjectELResolver extends ELResolver { return null; } + private static class ScopeManager { private static final String MNGR_KEY = ScopeManager.class.getName(); @@ -473,6 +420,7 @@ public class ImplicitObjectELResolver extends ELResolver { } } + private abstract static class ScopeMap<V> extends AbstractMap<String,V> { protected abstract Enumeration<String> getAttributeNames(); @@ -560,7 +508,7 @@ public class ImplicitObjectELResolver extends ELResolver { @Override public boolean equals(Object obj) { - return (obj != null && this.hashCode() == obj.hashCode()); + return obj != null && this.hashCode() == obj.hashCode(); } @Override @@ -596,4 +544,96 @@ public class ImplicitObjectELResolver extends ELResolver { return null; } } + + + private enum Scope { + APPLICATION_SCOPE("applicationScope") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getApplicationScope(); + } + }, + COOKIE("cookie") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getCookie(); + } + }, + HEADER("header") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getHeader(); + } + }, + HEADER_VALUES("headerValues") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getHeaderValues(); + } + }, + INIT_PARAM("initParam") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getInitParam(); + } + }, + PAGE_CONTEXT("pageContext") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getPageContext(); + } + }, + PAGE_SCOPE("pageScope") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getPageScope(); + } + }, + PARAM("param") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getParam(); + } + }, + PARAM_VALUES("paramValues") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getParamValues(); + } + }, + REQUEST_SCOPE("requestScope") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getRequestScope(); + } + }, + SESSION_SCOPE("sessionScope") { + @Override + Object getScopeValue(ELContext context, Object base, Object property) { + return getScopeManager(context, base, property).getSessionScope(); + } + }; + + private static final Map<String,Scope> lookupMap = new HashMap<>(); + + static { + for (Scope scope : Scope.values()) { + lookupMap.put(scope.implicitName, scope); + } + } + + private static ScopeManager getScopeManager(ELContext context, Object base, Object property) { + PageContext page = (PageContext) context.getContext(JspContext.class); + context.setPropertyResolved(base, property); + return ScopeManager.get(page); + } + + private final String implicitName; + + Scope(String implicitName) { + this.implicitName = implicitName; + } + + abstract Object getScopeValue(ELContext context, Object base, Object property); + } } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 379f23e47d..d1f65c6115 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -142,6 +142,15 @@ </fix> </changelog> </subsection> + <subsection name="Jasper"> + <changelog> + <fix> + <bug>67080</bug>: Improve performance of EL expressions in JSPs that use + implicit objects. Based on suggestions by John Engebretson, Anurag Dubey + and Christopher Schultz. (markt) + </fix> + </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