You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2021/01/22 12:50:49 UTC
[tomcat] branch 9.0.x updated: BZ 64872 Optimised StringInterpreter
for Enum Values
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new 6fc94f2 BZ 64872 Optimised StringInterpreter for Enum Values
6fc94f2 is described below
commit 6fc94f243c4a5890b2d679acd5b7fa0611d7985d
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 5d8dd82..5efee11 100644
--- a/webapps/docs/jasper-howto.xml
+++ b/webapps/docs/jasper-howto.xml
@@ -420,6 +420,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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org