Author: markt
Date: Thu Mar 10 14:22:51 2016
New Revision: 1734418

URL: http://svn.apache.org/viewvc?rev=1734418&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=57583
Improve long standing performance issue with EL and undefined attributes.

Modified:
    tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java
    tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java?rev=1734418&r1=1734417&r2=1734418&view=diff
==============================================================================
--- tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java 
(original)
+++ tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java Thu 
Mar 10 14:22:51 2016
@@ -35,6 +35,20 @@ import javax.servlet.jsp.PageContext;
 */
 public class ScopedAttributeELResolver extends ELResolver {
 
+    // Indicates if a performance short-cut is available
+    private static final Class<?> AST_IDENTIFIER_KEY;
+
+    static {
+        Class<?> key = null;
+        try {
+            key = Class.forName("org.apache.el.parser.AstIdentifier");
+        } catch (Exception e) {
+            // Ignore: Expected if not running on Tomcat. Not a problem since
+            //         this just allows a short-cut.
+        }
+        AST_IDENTIFIER_KEY = key;
+    }
+
     @Override
     public Object getValue(ELContext context, Object base, Object property) {
         if (context == null) {
@@ -51,10 +65,26 @@ public class ScopedAttributeELResolver e
                 result = page.findAttribute(key);
 
                 if (result == null) {
+                    boolean resolveClass = true;
+                    // Performance short-cut available when running on Tomcat
+                    if (AST_IDENTIFIER_KEY != null) {
+                        // Tomcat will set this key to Boolean.TRUE if the
+                        // identifier is a stand-alone identifier (i.e.
+                        // identifier) rather than part of an AstValue (i.e.
+                        // identifier.something). Imports do not need to be
+                        // checked if this is a stand-alone identifier
+                        Boolean value = (Boolean) 
context.getContext(AST_IDENTIFIER_KEY);
+                        if (value != null && value.booleanValue()) {
+                            resolveClass = false;
+                        }
+                    }
                     // This might be the name of an imported class
                     ImportHandler importHandler = context.getImportHandler();
                     if (importHandler != null) {
-                        Class<?> clazz = importHandler.resolveClass(key);
+                        Class<?> clazz = null;
+                        if (resolveClass) {
+                            clazz = importHandler.resolveClass(key);
+                        }
                         if (clazz != null) {
                             result = new ELClass(clazz);
                         }

Modified: tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java?rev=1734418&r1=1734417&r2=1734418&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java (original)
+++ tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java Thu Mar 10 
14:22:51 2016
@@ -77,7 +77,27 @@ public final class AstIdentifier extends
 
         // EL Resolvers
         ctx.setPropertyResolved(false);
-        Object result = ctx.getELResolver().getValue(ctx, null, this.image);
+        Object result;
+        /* Putting the Boolean into the ELContext is part of a performance
+         * optimisation for ScopedAttributeELResolver. When looking up "foo",
+         * the resolver can't differentiate between ${ foo } and ${ foo.bar }.
+         * This is important because the expensive class lookup only needs to
+         * be performed in the later case. This flag tells the resolver if the
+         * lookup can be skipped.
+         */
+        if (parent instanceof AstValue) {
+            ctx.putContext(this.getClass(), Boolean.FALSE);
+        } else {
+            ctx.putContext(this.getClass(), Boolean.TRUE);
+        }
+        try {
+            result = ctx.getELResolver().getValue(ctx, null, this.image);
+        } finally {
+            // Always reset the flag to false so the optimisation is not 
applied
+            // inappropriately
+            ctx.putContext(this.getClass(), Boolean.FALSE);
+        }
+
         if (ctx.isPropertyResolved()) {
             return result;
         }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1734418&r1=1734417&r2=1734418&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Mar 10 14:22:51 2016
@@ -222,6 +222,12 @@
       <update>
         Update to the Eclipse JDT Compiler 4.5.1. (markt)
       </update>
+      <fix>
+        <bug>57583</bug>: Improve the performance of
+        <code>javax.servlet.jsp.el.ScopedAttributeELResolver</code> when
+        resolving attributes that do not exist. This improvement only works 
when
+        Jasper is used with with Tomcat's EL implementation. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="WebSocket">



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

Reply via email to