This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 616949edde000602ba52368bc935207f85f07af7 Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Nov 25 12:15:23 2020 +0000 BZ 64872 Optimised StringInterpreter for Enum Values This is not strictly spec compliant hence it isn't enabled by default but it should work for many applicaitons. https://bz.apache.org/bugzilla/show_bug.cgi?id=64872 --- .../optimizations/StringInterpreterEnum.java | 37 +++++++ .../optimizations/TestELInterpreterTagSetters.java | 3 + .../TestStringInterpreterTagSetters.java | 120 +++++++++++++++++++++ test/webapp/bug6nnnn/bug64872-timeunit.jsp | 3 - ...ug64872-timeunit.jsp => bug64872b-timeunit.jsp} | 10 +- webapps/docs/jasper-howto.xml | 7 ++ 6 files changed, 170 insertions(+), 10 deletions(-) diff --git a/java/org/apache/jasper/optimizations/StringInterpreterEnum.java b/java/org/apache/jasper/optimizations/StringInterpreterEnum.java new file mode 100644 index 0000000..b85f339 --- /dev/null +++ b/java/org/apache/jasper/optimizations/StringInterpreterEnum.java @@ -0,0 +1,37 @@ +/* + * 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.optimizations; + +import org.apache.jasper.compiler.StringInterpreterFactory.DefaultStringInterpreter; + +/** + * Provides an optimised conversion of string values to Enums. It bypasses the + * check for registered PropertyEditor. + */ +public class StringInterpreterEnum extends DefaultStringInterpreter { + + @Override + protected String coerceToOtherType(Class<?> c, String s, boolean isNamedAttribute) { + if (c.isEnum() && !isNamedAttribute) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + Enum<?> enumValue = Enum.valueOf((Class<? extends Enum>) c, s); + return c.getName() + "." + enumValue.name(); + } + + return null; + } +} diff --git a/test/org/apache/jasper/optimizations/TestELInterpreterTagSetters.java b/test/org/apache/jasper/optimizations/TestELInterpreterTagSetters.java index 5a6cf8f..ac66ddd 100644 --- a/test/org/apache/jasper/optimizations/TestELInterpreterTagSetters.java +++ b/test/org/apache/jasper/optimizations/TestELInterpreterTagSetters.java @@ -40,6 +40,7 @@ import org.apache.catalina.startup.TomcatBaseTest; import org.apache.jasper.JspCompilationContext; import org.apache.jasper.compiler.ELInterpreter; import org.apache.jasper.compiler.ELInterpreterFactory; +import org.apache.jasper.compiler.StringInterpreter; import org.apache.tomcat.util.buf.ByteChunk; @RunWith(Parameterized.class) @@ -112,6 +113,8 @@ public class TestELInterpreterTagSetters extends TomcatBaseTest { Context ctxt = (Context) tomcat.getHost().findChild("/test"); ctxt.getServletContext().setAttribute(ELInterpreter.class.getCanonicalName(), elInterpreter); + ctxt.getServletContext().setAttribute(StringInterpreter.class.getCanonicalName(), new StringInterpreterEnum()); + ByteChunk bc = getUrl("http://localhost:" + getPort() + "/test/bug6nnnn/bug64872-" + target + ".jsp"); String actual = bc.toString(); diff --git a/test/org/apache/jasper/optimizations/TestStringInterpreterTagSetters.java b/test/org/apache/jasper/optimizations/TestStringInterpreterTagSetters.java new file mode 100644 index 0000000..3a75b75 --- /dev/null +++ b/test/org/apache/jasper/optimizations/TestStringInterpreterTagSetters.java @@ -0,0 +1,120 @@ +/* + * 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.optimizations; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import org.apache.catalina.Context; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.jasper.compiler.StringInterpreter; +import org.apache.jasper.compiler.StringInterpreterFactory; +import org.apache.tomcat.util.buf.ByteChunk; + +@RunWith(Parameterized.class) +public class TestStringInterpreterTagSetters extends TomcatBaseTest { + + @Parameters(name="{index}: {0}") + public static Collection<Object[]> parameters() { + List<Object[]> parameterSets = new ArrayList<>(); + + StringInterpreter[] stringInterpreters = new StringInterpreter[] { + // Warm-up + // First call will trigger compilation (and therefore be slower) + // Call both to ensure both are warmed up + new StringInterpreterWrapper(true, "Enum"), + new StringInterpreterWrapper(false, "Default"), + // Compare times of these test runs + new StringInterpreterWrapper(true, "Enum"), + new StringInterpreterWrapper(false, "Default"), + }; + + for (StringInterpreter stringInterpreter : stringInterpreters) { + parameterSets.add(new Object[] { stringInterpreter }); + } + return parameterSets; + } + + + @Parameter(0) + public StringInterpreter stringInterpreter; + + @Test + public void testTag() throws Exception { + Tomcat tomcat = getTomcatInstanceTestWebapp(false, true); + Context ctxt = (Context) tomcat.getHost().findChild("/test"); + ctxt.getServletContext().setAttribute(StringInterpreter.class.getCanonicalName(), stringInterpreter); + + ByteChunk bc = getUrl("http://localhost:" + getPort() + "/test/bug6nnnn/bug64872b-timeunit.jsp"); + + String actual = bc.toString(); + + Assert.assertTrue(actual, actual.contains("01 The value of foo is [SECONDS]")); + } + + + /* + * Wrapper so we can use sensible names in the test labels + */ + private static class StringInterpreterWrapper implements StringInterpreter { + + private final boolean optimised; + private final String name; + private volatile StringInterpreter stringInterpreter = null; + + public StringInterpreterWrapper(boolean optimised, String name) { + this.optimised = optimised; + this.name = name; + } + + @Override + public String convertString(Class<?> c, String s, String attrName, Class<?> propEditorClass, + boolean isNamedAttribute) { + return getStringInterpreter().convertString(c, s, attrName, propEditorClass, isNamedAttribute) ; + } + + @Override + public String toString() { + return name; + } + + // Lazy init to avoid LogManager init issues when running parameterized tests + private StringInterpreter getStringInterpreter() { + if (stringInterpreter == null) { + synchronized (this) { + if (stringInterpreter == null) { + if (optimised) { + stringInterpreter = new StringInterpreterEnum(); + } else { + stringInterpreter = new StringInterpreterFactory.DefaultStringInterpreter(); + } + } + } + } + return stringInterpreter; + } + } +} diff --git a/test/webapp/bug6nnnn/bug64872-timeunit.jsp b/test/webapp/bug6nnnn/bug64872-timeunit.jsp index e21bc2d..00b71ba 100644 --- a/test/webapp/bug6nnnn/bug64872-timeunit.jsp +++ b/test/webapp/bug6nnnn/bug64872-timeunit.jsp @@ -23,9 +23,6 @@ %> <p>01 The value of foo is [<ts:tagTimeUnit foo="${'SECONDS'}" />]</p> <p>02 The value of foo is [<ts:tagTimeUnit foo='${"SECONDS"}' />]</p> - <%-- - <p>03 The value of foo is [<ts:tagTimeUnit foo="SECONDS" />]</p> - --%> <% } %> diff --git a/test/webapp/bug6nnnn/bug64872-timeunit.jsp b/test/webapp/bug6nnnn/bug64872b-timeunit.jsp similarity index 73% copy from test/webapp/bug6nnnn/bug64872-timeunit.jsp copy to test/webapp/bug6nnnn/bug64872b-timeunit.jsp index e21bc2d..679925f 100644 --- a/test/webapp/bug6nnnn/bug64872-timeunit.jsp +++ b/test/webapp/bug6nnnn/bug64872b-timeunit.jsp @@ -16,16 +16,12 @@ --%> <%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %> <html> - <head><title>Bug 64872 TimeUnit test case</title></head> + <head><title>Bug 64872b TimeUnit test case</title></head> <body> <% - for (int i=0; i < 1000000; i++) { + for (int i=0; i < 100000; i++) { %> - <p>01 The value of foo is [<ts:tagTimeUnit foo="${'SECONDS'}" />]</p> - <p>02 The value of foo is [<ts:tagTimeUnit foo='${"SECONDS"}' />]</p> - <%-- - <p>03 The value of foo is [<ts:tagTimeUnit foo="SECONDS" />]</p> - --%> + <p>01 The value of foo is [<ts:tagTimeUnit foo="SECONDS" />]</p> <% } %> diff --git a/webapps/docs/jasper-howto.xml b/webapps/docs/jasper-howto.xml index aea993c..850d0d3 100644 --- a/webapps/docs/jasper-howto.xml +++ b/webapps/docs/jasper-howto.xml @@ -406,6 +406,13 @@ javadoc for details of the optimisations and the impact they have on specification compliance. </p> +<p> +An extension point is also provided for coercion of String values to Enums. It +is provided at +<code>org.apache.jasper.optimizations.StringInterpreterEnum</code>. See the +javadoc for details of the optimisations and the impact they have on +specification compliance. +</p> </section> </body> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org