Author: markt
Date: Tue Feb 12 14:50:39 2013
New Revision: 1445190

URL: http://svn.apache.org/r1445190
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=54239
Enable applications to use a custom EL interpreter.
Based on a patch by Sheldon Shao.

Added:
    tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreter.java   (with 
props)
    tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreterFactory.java   
(with props)
    tomcat/trunk/test/org/apache/jasper/compiler/TestELInterpreterFactory.java  
 (with props)
Modified:
    tomcat/trunk/java/org/apache/jasper/compiler/Generator.java
    tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties
    tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties
    tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_fr.properties
    tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties
    tomcat/trunk/webapps/docs/jasper-howto.xml

Added: tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreter.java?rev=1445190&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreter.java (added)
+++ tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreter.java Tue Feb 12 
14:50:39 2013
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jasper.compiler;
+
+import org.apache.jasper.JspCompilationContext;
+
+/**
+ * Defines the interface for the expression language interpreter. This allows
+ * users to provide custom EL interpreter implementations that can optimise
+ * EL processing for an application by , for example, performing code 
generation
+ * for simple expressions.
+ */
+public interface ELInterpreter {
+
+    /**
+     * Returns the string representing the code that will be inserted into the
+     * servlet generated for JSP. The default implementation creates a call to
+     * {@link org.apache.jasper.runtime.PageContextImpl#proprietaryEvaluate(
+     * String, Class, javax.servlet.jsp.PageContext,
+     * org.apache.jasper.runtime.ProtectedFunctionMapper, boolean)} but other
+     * implementations may produce more optimised code.
+     *
+     * @param expression a String containing zero or more "${}" expressions
+     * @param expectedType the expected type of the interpreted result
+     * @param fnmapvar Variable pointing to a function map.
+     * @param xmlEscape True if the result should do XML escaping
+     * @return a String representing a call to the EL interpreter.
+     */
+    public String interpreterCall(JspCompilationContext context,
+            boolean isTagFile, String expression,
+            Class<?> expectedType, String fnmapvar, boolean xmlEscape);
+}

Propchange: tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreterFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreterFactory.java?rev=1445190&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreterFactory.java 
(added)
+++ tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreterFactory.java Tue 
Feb 12 14:50:39 2013
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jasper.compiler;
+
+import javax.servlet.ServletContext;
+
+import org.apache.jasper.JspCompilationContext;
+
+/**
+ * Provides {@link ELInterpreter} instances for JSP compilation.
+ *
+ * The search order is as follows:
+ * <ol>
+ * <li>ELInterpreter instance or implementation class name provided as a
+ *     ServletContext attribute</li>
+ * <li>Implementation class named in a ServletContext initialisation parameter
+ *     </li>
+ * <li>Default implementation</li>
+ * </ol>
+ */
+public class ELInterpreterFactory {
+
+    public static final String EL_INTERPRETER_CLASS_NAME =
+            ELInterpreter.class.getName();
+
+    private static final ELInterpreter DEFAULT_INSTANCE =
+            new DefaultELInterpreter();
+
+
+    /**
+     * Obtain the correct EL Interpreter for the given web application.
+     */
+    public static ELInterpreter getELInterpreter(ServletContext context)
+            throws Exception {
+
+        ELInterpreter result = null;
+
+        // Search for an implementation
+        // 1. ServletContext attribute (set by application or cached by a
+        //    previous call to this method).
+        Object attribute = context.getAttribute(EL_INTERPRETER_CLASS_NAME);
+        if (attribute instanceof ELInterpreter) {
+            return (ELInterpreter) attribute;
+        } else if (attribute instanceof String) {
+            result = createInstance(context, (String) attribute);
+        }
+
+        // 2. ServletContext init parameter
+        if (result == null) {
+            String className =
+                    context.getInitParameter(EL_INTERPRETER_CLASS_NAME);
+            if (className != null) {
+                result = createInstance(context, className);
+            }
+        }
+
+        // 3. Default
+        if (result == null) {
+            result = DEFAULT_INSTANCE;
+        }
+
+        // Cache the result for next time
+        context.setAttribute(EL_INTERPRETER_CLASS_NAME, result);
+        return result;
+    }
+
+
+    private static ELInterpreter createInstance(ServletContext context,
+            String className) throws Exception {
+        return (ELInterpreter) context.getClassLoader().loadClass(
+                    className).newInstance();
+    }
+
+
+    private ELInterpreterFactory() {
+        // Utility class. Hide default constructor.
+    }
+
+
+    public static class DefaultELInterpreter implements ELInterpreter {
+
+        @Override
+        public String interpreterCall(JspCompilationContext context,
+                boolean isTagFile, String expression,
+                Class<?> expectedType, String fnmapvar, boolean xmlEscape) {
+            return JspUtil.interpreterCall(isTagFile, expression, expectedType,
+                    fnmapvar, xmlEscape);
+        }
+    }
+}

Propchange: 
tomcat/trunk/java/org/apache/jasper/compiler/ELInterpreterFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/java/org/apache/jasper/compiler/Generator.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/Generator.java?rev=1445190&r1=1445189&r2=1445190&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/Generator.java (original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/Generator.java Tue Feb 12 
14:50:39 2013
@@ -125,6 +125,8 @@ class Generator {
 
     private final DateFormat timestampFormat;
 
+    private final ELInterpreter elInterpreter;
+
     /**
      * @param s
      *            the input string
@@ -830,8 +832,8 @@ class Generator {
                 }
                 return v;
             } else if (attr.isELInterpreterInput()) {
-                v = JspUtil.interpreterCall(this.isTagFile, v, expectedType,
-                        attr.getEL().getMapName(), false);
+                v = elInterpreter.interpreterCall(ctxt, this.isTagFile, v,
+                        expectedType, attr.getEL().getMapName(), false);
                 if (encode) {
                     return 
"org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("
                             + v + ", request.getCharacterEncoding())";
@@ -916,9 +918,10 @@ class Generator {
             n.setBeginJavaLine(out.getJavaLine());
             if (!pageInfo.isELIgnored() && (n.getEL() != null)) {
                 out.printil("out.write("
-                        + JspUtil.interpreterCall(this.isTagFile, n.getType() +
-                                "{" + n.getText() + "}", String.class,
-                                n.getEL().getMapName(), false) + ");");
+                        + elInterpreter.interpreterCall(ctxt, this.isTagFile,
+                                n.getType() + "{" + n.getText() + "}",
+                                String.class, n.getEL().getMapName(), false) +
+                        ");");
             } else {
                 out.printil("out.write("
                         + quote(n.getType() + "{" + n.getText() + "}") + ");");
@@ -2975,8 +2978,8 @@ class Generator {
                     // run attrValue through the expression interpreter
                     String mapName = (attr.getEL() != null) ? attr.getEL()
                             .getMapName() : null;
-                    attrValue = JspUtil.interpreterCall(this.isTagFile, 
attrValue,
-                            c[0], mapName, false);
+                    attrValue = elInterpreter.interpreterCall(ctxt,
+                            this.isTagFile, attrValue, c[0], mapName, false);
                 }
             } else {
                 attrValue = convertString(c[0], attrValue, localName,
@@ -3414,7 +3417,7 @@ class Generator {
     /**
      * Constructor.
      */
-    Generator(ServletWriter out, Compiler compiler) {
+    Generator(ServletWriter out, Compiler compiler) throws JasperException {
         this.out = out;
         methodsBuffered = new ArrayList<>();
         charArrayBuffer = null;
@@ -3423,6 +3426,16 @@ class Generator {
         fragmentHelperClass = new FragmentHelperClass("Helper");
         pageInfo = compiler.getPageInfo();
 
+        ELInterpreter elInterpreter = null;
+        try {
+            elInterpreter = ELInterpreterFactory.getELInterpreter(
+                    compiler.getCompilationContext().getServletContext());
+        } catch (Exception e) {
+            err.jspError("jsp.error.el_interpreter_class.instantiation",
+                    e.getMessage());
+        }
+        this.elInterpreter = elInterpreter;
+
         /*
          * Temporary hack. If a JSP page uses the "extends" attribute of the
          * page directive, the _jspInit() method of the generated servlet class

Modified: tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties?rev=1445190&r1=1445189&r2=1445190&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/jasper/resources/LocalStrings.properties Tue 
Feb 12 14:50:39 2013
@@ -387,3 +387,6 @@ xmlParser.skipBomFail=Failed to skip BOM
 
 jsp.tldCache.noTldInJar=No TLD files were found in [{0}]. Consider adding the 
JAR to the tomcat.util.scan.DefaultJarScanner.jarsToSkip or 
org.apache.catalina.startup.TldConfig.jarsToSkip property in 
CATALINA_BASE/conf/catalina.properties file.
 jsp.tldCache.noTldSummary=At least one JAR was scanned for TLDs yet contained 
no TLDs. Enable debug logging for this logger for a complete list of JARs that 
were scanned but no TLDs were found in them. Skipping unneeded JARs during 
scanning can improve startup time and JSP compilation time.
+
+#ELInterpreter
+jsp.error.el_interpreter_class.instantiation=Failed to load or instantiate 
ELInterpreter class [{0}]
\ No newline at end of file

Modified: 
tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties?rev=1445190&r1=1445189&r2=1445190&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties 
(original)
+++ tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_es.properties 
Tue Feb 12 14:50:39 2013
@@ -370,3 +370,6 @@ jsp.message.jsp_unload_check = Revisando
 xmlParser.skipBomFail = No pude saltar BOM al analizar flujo de entrada XML
 jsp.tldCache.noTldInJar = No se han hallado ficheros TLD en [{0}]. Considera 
a\u00F1adir el JAR a la propiedad tomcat.util.scan.DefaultJarScanner.jarsToSkip 
en el fichero  CATALINA_BASE/conf/catalina.propeperties.
 jsp.tldCache.noTldSummary = Al menos un JAR, que se ha explorado buscando 
TLDs, a\u00FAn no conten\u00EDa TLDs. Activar historial de depuraci\u00F3n para 
este historiador para una completa lista de los JARs que fueron explorados y de 
los que nos se hall\u00F3 TLDs. Saltarse JARs no necesarios durante la 
exploraci\u00F3n puede dar lugar a una mejora de tiempo significativa en el 
arranque y compilaci\u00F3n de JSP .
+
+#ELInterpreter
+jsp.error.el_interpreter_class.instantiation=No se puede cargar la clase 
ELInterpreter llamada [{0}]
\ No newline at end of file

Modified: 
tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_fr.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_fr.properties?rev=1445190&r1=1445189&r2=1445190&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_fr.properties 
(original)
+++ tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_fr.properties 
Tue Feb 12 14:50:39 2013
@@ -211,3 +211,6 @@ jsp.error.attributes.not.allowed = {0} n
 #jsp.error.jspoutput.nonemptybody=
 #jsp.error.jspoutput.invalidUse=
 #jsp.error.invalid.bean=
+
+#ELInterpreter
+jsp.error.el_interpreter_class.instantiation=Impossible de charger ou 
d''instancier la classe ELInterpreter [{0}]
\ No newline at end of file

Modified: 
tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties?rev=1445190&r1=1445189&r2=1445190&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties 
(original)
+++ tomcat/trunk/java/org/apache/jasper/resources/LocalStrings_ja.properties 
Tue Feb 12 14:50:39 2013
@@ -313,3 +313,5 @@ jsp.error.unbalanced.endtag=\u7d42\u4e86
 jsp.error.invalid.bean=useBean\u306e\u30af\u30e9\u30b9\u5c5e\u6027 {0} 
\u306e\u5024\u304c\u7121\u52b9\u3067\u3059
 
jsp.error.prefix.use_before_dcl=\u3053\u306e\u30bf\u30b0\u6307\u793a\u5b50\u3067\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u30d7\u30ea\u30d5\u30a3\u30c3\u30af\u30b9
 {0} \u306f\u3001\u3059\u3067\u306b\u30d5\u30a1\u30a4\u30eb {1} \u306e {2} 
\u884c\u76ee\u306e\u30a2\u30af\u30b7\u30e7\u30f3\u3067\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059
 
+#ELInterpreter
+jsp.error.el_interpreter_class.instantiation=ELInterpreter 
class\u306e\u30ed\u30fc\u30c9\u53c8\u306f\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u306b\u5931\u6557\u3057\u307e\u3057\u305f
 [{0}]
\ No newline at end of file

Added: 
tomcat/trunk/test/org/apache/jasper/compiler/TestELInterpreterFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/jasper/compiler/TestELInterpreterFactory.java?rev=1445190&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/jasper/compiler/TestELInterpreterFactory.java 
(added)
+++ tomcat/trunk/test/org/apache/jasper/compiler/TestELInterpreterFactory.java 
Tue Feb 12 14:50:39 2013
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jasper.compiler;
+
+import java.io.File;
+
+import javax.servlet.ServletContext;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.jasper.JspCompilationContext;
+import org.apache.jasper.compiler.ELInterpreterFactory.DefaultELInterpreter;
+
+public class TestELInterpreterFactory extends TomcatBaseTest {
+
+    public static class SimpleELInterpreter implements ELInterpreter {
+
+        @Override
+        public String interpreterCall(JspCompilationContext context,
+                boolean isTagFile, String expression, Class<?> expectedType,
+                String fnmapvar, boolean xmlEscape) {
+            return expression;
+        }
+    }
+
+    @Test
+    public void testBug54239() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+
+        File appDir = new File("test/webapp-3.0");
+        Context ctx = tomcat.addWebapp(null, "/test", 
appDir.getAbsolutePath());
+        tomcat.start();
+
+        ServletContext context = ctx.getServletContext();
+
+        ELInterpreter interpreter =
+                ELInterpreterFactory.getELInterpreter(context);
+        Assert.assertNotNull(interpreter);
+        Assert.assertTrue(interpreter instanceof DefaultELInterpreter);
+
+        context.removeAttribute(ELInterpreter.class.getName());
+
+        context.setAttribute(ELInterpreter.class.getName(),
+                SimpleELInterpreter.class.getName());
+        interpreter = ELInterpreterFactory.getELInterpreter(context);
+        Assert.assertNotNull(interpreter);
+        Assert.assertTrue(interpreter instanceof SimpleELInterpreter);
+
+        context.removeAttribute(ELInterpreter.class.getName());
+
+        SimpleELInterpreter simpleInterpreter = new SimpleELInterpreter();
+        context.setAttribute(ELInterpreter.class.getName(), simpleInterpreter);
+        interpreter = ELInterpreterFactory.getELInterpreter(context);
+        Assert.assertNotNull(interpreter);
+        Assert.assertTrue(interpreter instanceof SimpleELInterpreter);
+        Assert.assertTrue(interpreter == simpleInterpreter);
+
+        context.removeAttribute(ELInterpreter.class.getName());
+
+
+        context.setInitParameter(ELInterpreter.class.getName(),
+                SimpleELInterpreter.class.getName());
+
+        interpreter = ELInterpreterFactory.getELInterpreter(context);
+        Assert.assertNotNull(interpreter);
+        Assert.assertTrue(interpreter instanceof SimpleELInterpreter);
+
+        context.removeAttribute(ELInterpreter.class.getName());
+    }
+}

Propchange: 
tomcat/trunk/test/org/apache/jasper/compiler/TestELInterpreterFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/jasper-howto.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/jasper-howto.xml?rev=1445190&r1=1445189&r2=1445190&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/jasper-howto.xml (original)
+++ tomcat/trunk/webapps/docs/jasper-howto.xml Tue Feb 12 14:50:39 2013
@@ -380,6 +380,28 @@ depending on the application.</li>
 </p>
 </section>
 
+<section name="Optimisation">
+<p>
+There are a number of extension points provided within Jasper that enable the
+user to optimise the behaviour for their environment.
+</p>
+
+<p>
+The first of these extension points is the tag plug-in mechanism. This allows
+alternative implementations of tag handlers to be provided for a web 
application
+to use. Tag plug-ins are registered via a <code>tagPlugins.xml</code> file
+located under <code>WEB-INF</code>. A sample plug-in for the JSTL is included
+with Jasper. 
+</p>
+
+<p>
+The second extension point is the Expression Language interpreter. Alternative
+interpreters may be configured through the <code>ServletContext</code>. See the
+<code>ELInterpreterFactory</code> javadoc for details of how to configure an
+alternative EL interpreter. 
+</p>
+</section> 
+
 </body>
 
 </document>



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

Reply via email to