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:51:30 UTC
[tomcat] 01/02: BZ 64872 Optimised ELInterpreter for literal
booleans & strings
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 faa236fab5f93f8bbb93dd20e6dfd25907cd2ebb
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Nov 16 17:27:27 2020 +0000
BZ 64872 Optimised ELInterpreter for literal booleans & strings
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/ELInterpreterTagSetters.java | 268 ++++++++++
.../optimizations/TestELInterpreterTagSetters.java | 547 +++++++++++++++++++++
test/webapp/WEB-INF/tag-setters.tld | 245 +++++++++
test/webapp/bug6nnnn/bug64872-bigdecimal.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-biginteger.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-boolean.jsp | 37 ++
test/webapp/bug6nnnn/bug64872-byte.jsp | 32 ++
test/webapp/bug6nnnn/bug64872-character.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-double.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-float.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-integer.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-long.jsp | 30 ++
.../webapp/bug6nnnn/bug64872-primitive-boolean.jsp | 37 ++
test/webapp/bug6nnnn/bug64872-primitive-byte.jsp | 32 ++
.../bug6nnnn/bug64872-primitive-character.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-primitive-double.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-primitive-float.jsp | 30 ++
.../webapp/bug6nnnn/bug64872-primitive-integer.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-primitive-long.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-primitive-short.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-short.jsp | 30 ++
test/webapp/bug6nnnn/bug64872-string.jsp | 33 ++
test/webapp/bug6nnnn/bug64872-timeunit.jsp | 33 ++
webapps/docs/jasper-howto.xml | 7 +-
24 files changed, 1690 insertions(+), 1 deletion(-)
diff --git a/java/org/apache/jasper/optimizations/ELInterpreterTagSetters.java b/java/org/apache/jasper/optimizations/ELInterpreterTagSetters.java
new file mode 100644
index 0000000..38feb96
--- /dev/null
+++ b/java/org/apache/jasper/optimizations/ELInterpreterTagSetters.java
@@ -0,0 +1,268 @@
+/*
+ * 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.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.el.ELResolver;
+
+import org.apache.jasper.JspCompilationContext;
+import org.apache.jasper.compiler.ELInterpreter;
+import org.apache.jasper.compiler.JspUtil;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+/**
+ * A non-specification compliant {@link ELInterpreter} that optimizes a subset
+ * of setters for tag attributes.
+ * <p>
+ * The cases optimized by this implementation are:
+ * <ul>
+ * <li>expressions that are solely a literal boolean</li>
+ * <li>expressions that are solely a constant string used (with coercion where
+ * necessary) with a setter that accepts:</li>
+ * <ul>
+ * <li>boolean / Boolean</li>
+ * <li>char / Character</li>
+ * <li>BigDecimal</li>
+ * <li>long / Long</li>
+ * <li>int / Integer</li>
+ * <li>short / Short</li>
+ * <li>byte / Byte</li>
+ * <li>double / Double</li>
+ * <li>float / Float</li>
+ * <li>BigInteger</li>
+ * <li>Enum</li>
+ * <li>String</li>
+ * </ul>
+ * </ul>
+ * The specification compliance issue is that it essentially skips the first
+ * three {@link ELResolver}s listed in section JSP.2.9 and effectively hard
+ * codes the use of the 4th {@link ELResolver} in that list.
+ *
+ * @see "https://bz.apache.org/bugzilla/show_bug.cgi?id=64872"
+ */
+public class ELInterpreterTagSetters implements ELInterpreter {
+
+ // Can't be static
+ private final Log log = LogFactory.getLog(ELInterpreterTagSetters.class);
+
+ private final Pattern PATTERN_BOOLEAN = Pattern.compile("[$][{]([\"']?)(true|false)\\1[}]");
+ private final Pattern PATTERN_STRING_CONSTANT = Pattern.compile("[$][{]([\"'])(\\w+)\\1[}]");
+ private final Pattern PATTERN_NUMERIC = Pattern.compile("[$][{]([\"'])([+-]?\\d+(\\.\\d+)?)\\1[}]");
+
+ @Override
+ public String interpreterCall(JspCompilationContext context,
+ boolean isTagFile, String expression,
+ Class<?> expectedType, String fnmapvar) {
+
+ String result = null;
+
+ // Boolean
+ if (Boolean.TYPE == expectedType) {
+ Matcher m = PATTERN_BOOLEAN.matcher(expression);
+ if (m.matches()) {
+ result = m.group(2);
+ }
+ } else if (Boolean.class == expectedType) {
+ Matcher m = PATTERN_BOOLEAN.matcher(expression);
+ if (m.matches()) {
+ if ("true".equals(m.group(2))) {
+ result = "Boolean.TRUE";
+ } else {
+ result = "Boolean.FALSE";
+ }
+ }
+ // Character
+ } else if (Character.TYPE == expectedType) {
+ Matcher m = PATTERN_STRING_CONSTANT.matcher(expression);
+ if (m.matches()) {
+ return "\'" + m.group(2).charAt(0) + "\'";
+ }
+ } else if (Character.class == expectedType) {
+ Matcher m = PATTERN_STRING_CONSTANT.matcher(expression);
+ if (m.matches()) {
+ return "Character.valueOf(\'" + m.group(2).charAt(0) + "\')";
+ }
+ // Numeric - BigDecimal
+ } else if (BigDecimal.class == expectedType) {
+ Matcher m = PATTERN_NUMERIC.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings("unused")
+ BigDecimal unused = new BigDecimal(m.group(2));
+ result = "new java.math.BigDecimal(\"" + m.group(2) + "\")";
+ } catch (NumberFormatException e) {
+ log.debug("Failed to convert [" + m.group(2) + "] to BigDecimal", e);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // Numeric - long/Long
+ } else if (Long.TYPE == expectedType || Long.class == expectedType) {
+ Matcher m = PATTERN_NUMERIC.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings("unused")
+ Long unused = Long.valueOf(m.group(2));
+ if (expectedType.isPrimitive()) {
+ // Long requires explicit declaration as a long literal
+ result = m.group(2) + "L";
+ } else {
+ result = "Long.valueOf(\"" + m.group(2) + "\")";
+ }
+ } catch (NumberFormatException e) {
+ log.debug("Failed to convert [" + m.group(2) + "] to Long", e);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // Numeric - int/Integer
+ } else if (Integer.TYPE == expectedType || Integer.class == expectedType) {
+ Matcher m = PATTERN_NUMERIC.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings("unused")
+ Integer unused = Integer.valueOf(m.group(2));
+ if (expectedType.isPrimitive()) {
+ result = m.group(2);
+ } else {
+ result = "Integer.valueOf(\"" + m.group(2) + "\")";
+ }
+ } catch (NumberFormatException e) {
+ log.debug("Failed to convert [" + m.group(2) + "] to Integer", e);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // Numeric - short/Short
+ } else if (Short.TYPE == expectedType || Short.class == expectedType) {
+ Matcher m = PATTERN_NUMERIC.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings("unused")
+ Short unused = Short.valueOf(m.group(2));
+ if (expectedType.isPrimitive()) {
+ // short requires a downcast
+ result = "(short) " + m.group(2);
+ } else {
+ result = "Short.valueOf(\"" + m.group(2) + "\")";
+ }
+ } catch (NumberFormatException e) {
+ log.debug("Failed to convert [" + m.group(2) + "] to Short", e);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // Numeric - byte/Byte
+ } else if (Byte.TYPE == expectedType || Byte.class == expectedType) {
+ Matcher m = PATTERN_NUMERIC.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings("unused")
+ Byte unused = Byte.valueOf(m.group(2));
+ if (expectedType.isPrimitive()) {
+ // byte requires a downcast
+ result = "(byte) " + m.group(2);
+ } else {
+ result = "Byte.valueOf(\"" + m.group(2) + "\")";
+ }
+ } catch (NumberFormatException e) {
+ log.debug("Failed to convert [" + m.group(2) + "] to Byte", e);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // Numeric - double/Double
+ } else if (Double.TYPE == expectedType || Double.class == expectedType) {
+ Matcher m = PATTERN_NUMERIC.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings("unused")
+ Double unused = Double.valueOf(m.group(2));
+ if (expectedType.isPrimitive()) {
+ result = m.group(2);
+ } else {
+ result = "Double.valueOf(\"" + m.group(2) + "\")";
+ }
+ } catch (NumberFormatException e) {
+ log.debug("Failed to convert [" + m.group(2) + "] to Double", e);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // Numeric - float/Float
+ } else if (Float.TYPE == expectedType || Float.class == expectedType) {
+ Matcher m = PATTERN_NUMERIC.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings("unused")
+ Float unused = Float.valueOf(m.group(2));
+ if (expectedType.isPrimitive()) {
+ // Float requires explicit declaration as a float literal
+ result = m.group(2) + "f";
+ } else {
+ result = "Float.valueOf(\"" + m.group(2) + "\")";
+ }
+ } catch (NumberFormatException e) {
+ log.debug("Failed to convert [" + m.group(2) + "] to Float", e);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // Numeric - BigInteger
+ } else if (BigInteger.class == expectedType) {
+ Matcher m = PATTERN_NUMERIC.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings("unused")
+ BigInteger unused = new BigInteger(m.group(2));
+ result = "new java.math.BigInteger(\"" + m.group(2) + "\")";
+ } catch (NumberFormatException e) {
+ log.debug("Failed to convert [" + m.group(2) + "] to BigInteger", e);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // Enum
+ } else if (expectedType.isEnum()){
+ Matcher m = PATTERN_STRING_CONSTANT.matcher(expression);
+ if (m.matches()) {
+ try {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Enum<?> enumValue = Enum.valueOf((Class<? extends Enum>) expectedType, m.group(2));
+ result = expectedType.getName() + "." + enumValue.name();
+ } catch (IllegalArgumentException iae) {
+ log.debug("Failed to convert [" + m.group(2) + "] to Enum type [" + expectedType.getName() + "]", iae);
+ // Continue and resolve the value at runtime
+ }
+ }
+ // String
+ } else if (String.class == expectedType) {
+ Matcher m = PATTERN_STRING_CONSTANT.matcher(expression);
+ if (m.matches()) {
+ result = "\"" + m.group(2) + "\"";
+ }
+ }
+
+ if (result == null) {
+ result = JspUtil.interpreterCall(isTagFile, expression, expectedType,
+ fnmapvar);
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Expression [" + expression + "], type [" + expectedType.getName() + "], returns [" + result + "]");
+ }
+
+ return result;
+ }
+}
diff --git a/test/org/apache/jasper/optimizations/TestELInterpreterTagSetters.java b/test/org/apache/jasper/optimizations/TestELInterpreterTagSetters.java
new file mode 100644
index 0000000..5a6cf8f
--- /dev/null
+++ b/test/org/apache/jasper/optimizations/TestELInterpreterTagSetters.java
@@ -0,0 +1,547 @@
+/*
+ * 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.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.SimpleTagSupport;
+
+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.JspCompilationContext;
+import org.apache.jasper.compiler.ELInterpreter;
+import org.apache.jasper.compiler.ELInterpreterFactory;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+@RunWith(Parameterized.class)
+public class TestELInterpreterTagSetters extends TomcatBaseTest {
+
+ private static final Integer ZERO = Integer.valueOf(0);
+ private static final Integer TWO = Integer.valueOf(2);
+ private static final Integer THREE = Integer.valueOf(3);
+
+ @Parameters(name="{index}: {0} {1} {3},{4}")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<>();
+
+ ELInterpreter[] elInterpreters = new ELInterpreter[] {
+ // Warm-up
+ // First call will trigger compilation (and therefore be slower)
+ // Call both to ensure both are warmed up
+ new ELInterpreterWrapper(true, "TagSetters"),
+ new ELInterpreterWrapper(false, "Default"),
+ // Compare times of these test runs
+ new ELInterpreterWrapper(true, "TagSetters"),
+ new ELInterpreterWrapper(false, "Default"),
+ };
+
+ for (ELInterpreter elInterpreter : elInterpreters) {
+ parameterSets.add(new Object[] { elInterpreter, "boolean", "false", ZERO, THREE });
+ parameterSets.add(new Object[] { elInterpreter, "boolean", "true", THREE, THREE });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-boolean", "false", ZERO, THREE });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-boolean", "true", THREE, THREE });
+ parameterSets.add(new Object[] { elInterpreter, "character", "b", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-character", "b", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "bigdecimal", "12.34", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "biginteger", "1234", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "long", "1234", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-long", "1234", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "integer", "1234", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-integer", "1234", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "short", "1234", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-short", "1234", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "byte", "12", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "byte", "-12", TWO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-byte", "12", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-byte", "-12", TWO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "double", "12.34", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-double", "12.34", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "float", "12.34", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "primitive-float", "12.34", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "timeunit", "SECONDS", ZERO, TWO });
+ parameterSets.add(new Object[] { elInterpreter, "string", "bar", ZERO, TWO });
+ }
+ return parameterSets;
+ }
+
+
+ @Parameter(0)
+ public ELInterpreter elInterpreter;
+ @Parameter(1)
+ public String target;
+ @Parameter(2)
+ public String expectedValue;
+ @Parameter(3)
+ public int offset;
+ @Parameter(4)
+ public int len;
+
+
+ @Test
+ public void testTag() throws Exception {
+ Tomcat tomcat = getTomcatInstanceTestWebapp(false, true);
+ Context ctxt = (Context) tomcat.getHost().findChild("/test");
+ ctxt.getServletContext().setAttribute(ELInterpreter.class.getCanonicalName(), elInterpreter);
+
+ ByteChunk bc = getUrl("http://localhost:" + getPort() + "/test/bug6nnnn/bug64872-" + target + ".jsp");
+
+ String actual = bc.toString();
+
+ for (int i = offset; i < offset + len; i++) {
+ String expected = String.format("%02d The value of foo is [%s]", Integer.valueOf(i+1), expectedValue);
+ Assert.assertTrue(actual, actual.contains(expected));
+ }
+ }
+
+
+ public static class TagPrimitiveBoolean extends SimpleTagSupport {
+
+ private boolean foo;
+
+ public boolean getFoo() {
+ return foo;
+ }
+
+ public void setFoo(boolean foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagBoolean extends SimpleTagSupport {
+
+ private Boolean foo;
+
+ public Boolean getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Boolean foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagPrimitiveCharacter extends SimpleTagSupport {
+
+ private char foo;
+
+ public char getFoo() {
+ return foo;
+ }
+
+ public void setFoo(char foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagCharacter extends SimpleTagSupport {
+
+ private Character foo;
+
+ public Character getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Character foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagPrimitiveLong extends SimpleTagSupport {
+
+ private long foo;
+
+ public long getFoo() {
+ return foo;
+ }
+
+ public void setFoo(long foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagLong extends SimpleTagSupport {
+
+ private Long foo;
+
+ public Long getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Long foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagPrimitiveInteger extends SimpleTagSupport {
+
+ private int foo;
+
+ public int getFoo() {
+ return foo;
+ }
+
+ public void setFoo(int foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagInteger extends SimpleTagSupport {
+
+ private Integer foo;
+
+ public Integer getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Integer foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagPrimitiveShort extends SimpleTagSupport {
+
+ private short foo;
+
+ public short getFoo() {
+ return foo;
+ }
+
+ public void setFoo(short foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagShort extends SimpleTagSupport {
+
+ private Short foo;
+
+ public Short getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Short foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagPrimitiveByte extends SimpleTagSupport {
+
+ private byte foo;
+
+ public byte getFoo() {
+ return foo;
+ }
+
+ public void setFoo(byte foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagByte extends SimpleTagSupport {
+
+ private Byte foo;
+
+ public Byte getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Byte foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagPrimitiveDouble extends SimpleTagSupport {
+
+ private double foo;
+
+ public double getFoo() {
+ return foo;
+ }
+
+ public void setFoo(double foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagDouble extends SimpleTagSupport {
+
+ private Double foo;
+
+ public Double getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Double foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagPrimitiveFloat extends SimpleTagSupport {
+
+ private float foo;
+
+ public float getFoo() {
+ return foo;
+ }
+
+ public void setFoo(float foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagFloat extends SimpleTagSupport {
+
+ private Float foo;
+
+ public Float getFoo() {
+ return foo;
+ }
+
+ public void setFoo(Float foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagString extends SimpleTagSupport {
+
+ private String foo;
+
+ public String getFoo() {
+ return foo;
+ }
+
+ public void setFoo(String foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagTimeUnit extends SimpleTagSupport {
+
+ private TimeUnit foo;
+
+ public TimeUnit getFoo() {
+ return foo;
+ }
+
+ public void setFoo(TimeUnit foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagBigDecimal extends SimpleTagSupport {
+
+ private BigDecimal foo;
+
+ public BigDecimal getFoo() {
+ return foo;
+ }
+
+ public void setFoo(BigDecimal foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ public static class TagBigInteger extends SimpleTagSupport {
+
+ private BigInteger foo;
+
+ public BigInteger getFoo() {
+ return foo;
+ }
+
+ public void setFoo(BigInteger foo) {
+ this.foo = foo;
+ }
+
+ @Override
+ public void doTag() throws JspException, IOException {
+ getJspContext().getOut().print(foo);
+ }
+ }
+
+
+ /*
+ * Wrapper so we can use sensible names in the test labels
+ */
+ private static class ELInterpreterWrapper implements ELInterpreter {
+
+ private final boolean optimised;
+ private final String name;
+ private volatile ELInterpreter elInterpreter = null;
+
+ public ELInterpreterWrapper(boolean optimised, String name) {
+ this.optimised = optimised;
+ this.name = name;
+ }
+
+ @Override
+ public String interpreterCall(JspCompilationContext context, boolean isTagFile,
+ String expression, Class<?> expectedType, String fnmapvar) {
+ return getElInterpreter().interpreterCall(context, isTagFile, expression, expectedType, fnmapvar);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ // Lazy init to avoid LogManager init issues when running parameterized tests
+ private ELInterpreter getElInterpreter() {
+ if (elInterpreter == null) {
+ synchronized (this) {
+ if (elInterpreter == null) {
+ if (optimised) {
+ elInterpreter = new ELInterpreterTagSetters();
+ } else {
+ elInterpreter = new ELInterpreterFactory.DefaultELInterpreter();
+ }
+ }
+ }
+ }
+ return elInterpreter;
+ }
+ }
+}
diff --git a/test/webapp/WEB-INF/tag-setters.tld b/test/webapp/WEB-INF/tag-setters.tld
new file mode 100644
index 0000000..e02ae14
--- /dev/null
+++ b/test/webapp/WEB-INF/tag-setters.tld
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
+ version="2.0">
+ <tlib-version>1.0</tlib-version>
+ <short-name>tag-setters</short-name>
+ <uri>http://tomcat.apache.org/tag-setters</uri>
+ <tag>
+ <name>tagPrimitiveBoolean</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagPrimitiveBoolean</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagBoolean</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagBoolean</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>Boolean</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagPrimitiveCharacter</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagPrimitiveCharacter</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>char</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagCharacter</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagCharacter</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>Character</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagPrimitiveLong</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagPrimitiveLong</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>long</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagLong</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagLong</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>Long</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagPrimitiveInteger</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagPrimitiveInteger</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagInteger</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagInteger</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>Integer</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagPrimitiveShort</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagPrimitiveShort</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>short</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagShort</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagShort</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>Short</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagPrimitiveByte</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagPrimitiveByte</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>byte</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagByte</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagByte</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>Byte</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagPrimitiveDouble</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagPrimitiveDouble</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>double</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagDouble</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagDouble</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>Double</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagPrimitiveFloat</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagPrimitiveFloat</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>float</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagFloat</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagFloat</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>Float</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagBigDecimal</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagBigDecimal</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>BigDecimal</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagBigInteger</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagBigInteger</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>BigInteger</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagString</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagString</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>String</type>
+ </attribute>
+ </tag>
+ <tag>
+ <name>tagTimeUnit</name>
+ <tag-class>org.apache.jasper.optimizations.TestELInterpreterTagSetters$TagTimeUnit</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <name>foo</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.util.concurrent.TimeUnit</type>
+ </attribute>
+ </tag>
+</taglib>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-bigdecimal.jsp b/test/webapp/bug6nnnn/bug64872-bigdecimal.jsp
new file mode 100644
index 0000000..9bd18ed
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-bigdecimal.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 BigDecimal test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagBigDecimal foo="${'12.34'}" />]</p>
+ <p>02 The value of foo is [<ts:tagBigDecimal foo='${"12.34"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-biginteger.jsp b/test/webapp/bug6nnnn/bug64872-biginteger.jsp
new file mode 100644
index 0000000..0fcd1c6
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-biginteger.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 BigInteger test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagBigInteger foo="${'1234'}" />]</p>
+ <p>02 The value of foo is [<ts:tagBigInteger foo='${"1234"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-boolean.jsp b/test/webapp/bug6nnnn/bug64872-boolean.jsp
new file mode 100644
index 0000000..7bdc126
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-boolean.jsp
@@ -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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 Boolean.TRUE test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagBoolean foo="${false}" />]</p>
+ <p>02 The value of foo is [<ts:tagBoolean foo="${'false'}" />]</p>
+ <p>03 The value of foo is [<ts:tagBoolean foo='${"false"}' />]</p>
+ <p>04 The value of foo is [<ts:tagBoolean foo="${true}" />]</p>
+ <p>05 The value of foo is [<ts:tagBoolean foo="${'true'}" />]</p>
+ <p>06 The value of foo is [<ts:tagBoolean foo='${"true"}' />]</p>
+ <%--
+ <p>04 The value of foo is [<ts:tagBoolean foo="true" />]</p>
+ --%>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-byte.jsp b/test/webapp/bug6nnnn/bug64872-byte.jsp
new file mode 100644
index 0000000..8696a0a
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-byte.jsp
@@ -0,0 +1,32 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 Byte test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagByte foo="${'12'}" />]</p>
+ <p>02 The value of foo is [<ts:tagByte foo='${"12"}' />]</p>
+ <p>03 The value of foo is [<ts:tagByte foo="${'-12'}" />]</p>
+ <p>04 The value of foo is [<ts:tagByte foo='${"-12"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-character.jsp b/test/webapp/bug6nnnn/bug64872-character.jsp
new file mode 100644
index 0000000..0f6ec23
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-character.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 Character test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagCharacter foo="${'bar'}" />]</p>
+ <p>02 The value of foo is [<ts:tagCharacter foo='${"bar"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-double.jsp b/test/webapp/bug6nnnn/bug64872-double.jsp
new file mode 100644
index 0000000..799a0c0
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-double.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 Double test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagDouble foo="${'12.34'}" />]</p>
+ <p>02 The value of foo is [<ts:tagDouble foo='${"12.34"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-float.jsp b/test/webapp/bug6nnnn/bug64872-float.jsp
new file mode 100644
index 0000000..19d6226
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-float.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 Float test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagFloat foo="${'12.34'}" />]</p>
+ <p>02 The value of foo is [<ts:tagFloat foo='${"12.34"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-integer.jsp b/test/webapp/bug6nnnn/bug64872-integer.jsp
new file mode 100644
index 0000000..255d716
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-integer.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 Integer test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagInteger foo="${'1234'}" />]</p>
+ <p>02 The value of foo is [<ts:tagInteger foo='${"1234"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-long.jsp b/test/webapp/bug6nnnn/bug64872-long.jsp
new file mode 100644
index 0000000..2b7b4c8
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-long.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 Long test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagLong foo="${'1234'}" />]</p>
+ <p>02 The value of foo is [<ts:tagLong foo='${"1234"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-primitive-boolean.jsp b/test/webapp/bug6nnnn/bug64872-primitive-boolean.jsp
new file mode 100644
index 0000000..1f0073a
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-primitive-boolean.jsp
@@ -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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 boolean false test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagPrimitiveBoolean foo="${false}" />]</p>
+ <p>02 The value of foo is [<ts:tagPrimitiveBoolean foo="${'false'}" />]</p>
+ <p>03 The value of foo is [<ts:tagPrimitiveBoolean foo='${"false"}' />]</p>
+ <p>04 The value of foo is [<ts:tagPrimitiveBoolean foo="${true}" />]</p>
+ <p>05 The value of foo is [<ts:tagPrimitiveBoolean foo="${'true'}" />]</p>
+ <p>06 The value of foo is [<ts:tagPrimitiveBoolean foo='${"true"}' />]</p>
+ <%--
+ <p>04 The value of foo is [<ts:tagBoolean foo="false" />]</p>
+ --%>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-primitive-byte.jsp b/test/webapp/bug6nnnn/bug64872-primitive-byte.jsp
new file mode 100644
index 0000000..aed0705
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-primitive-byte.jsp
@@ -0,0 +1,32 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 byte test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagPrimitiveByte foo="${'12'}" />]</p>
+ <p>02 The value of foo is [<ts:tagPrimitiveByte foo='${"12"}' />]</p>
+ <p>03 The value of foo is [<ts:tagPrimitiveByte foo="${'-12'}" />]</p>
+ <p>04 The value of foo is [<ts:tagPrimitiveByte foo='${"-12"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-primitive-character.jsp b/test/webapp/bug6nnnn/bug64872-primitive-character.jsp
new file mode 100644
index 0000000..03762a6
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-primitive-character.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 char test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagPrimitiveCharacter foo="${'bar'}" />]</p>
+ <p>02 The value of foo is [<ts:tagPrimitiveCharacter foo='${"bar"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-primitive-double.jsp b/test/webapp/bug6nnnn/bug64872-primitive-double.jsp
new file mode 100644
index 0000000..b1cd64b
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-primitive-double.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 double test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagPrimitiveDouble foo="${'12.34'}" />]</p>
+ <p>02 The value of foo is [<ts:tagPrimitiveDouble foo='${"12.34"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-primitive-float.jsp b/test/webapp/bug6nnnn/bug64872-primitive-float.jsp
new file mode 100644
index 0000000..c574a845
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-primitive-float.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 float test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagPrimitiveFloat foo="${'12.34'}" />]</p>
+ <p>02 The value of foo is [<ts:tagPrimitiveFloat foo='${"12.34"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-primitive-integer.jsp b/test/webapp/bug6nnnn/bug64872-primitive-integer.jsp
new file mode 100644
index 0000000..059f217
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-primitive-integer.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 int test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagPrimitiveInteger foo="${'1234'}" />]</p>
+ <p>02 The value of foo is [<ts:tagPrimitiveInteger foo='${"1234"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-primitive-long.jsp b/test/webapp/bug6nnnn/bug64872-primitive-long.jsp
new file mode 100644
index 0000000..bf900f2
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-primitive-long.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 long test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagPrimitiveLong foo="${'1234'}" />]</p>
+ <p>02 The value of foo is [<ts:tagPrimitiveLong foo='${"1234"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-primitive-short.jsp b/test/webapp/bug6nnnn/bug64872-primitive-short.jsp
new file mode 100644
index 0000000..275ca58
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-primitive-short.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 short test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagPrimitiveShort foo="${'1234'}" />]</p>
+ <p>02 The value of foo is [<ts:tagPrimitiveShort foo='${"1234"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-short.jsp b/test/webapp/bug6nnnn/bug64872-short.jsp
new file mode 100644
index 0000000..cd4e19e
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-short.jsp
@@ -0,0 +1,30 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 Short test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagShort foo="${'1234'}" />]</p>
+ <p>02 The value of foo is [<ts:tagShort foo='${"1234"}' />]</p>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-string.jsp b/test/webapp/bug6nnnn/bug64872-string.jsp
new file mode 100644
index 0000000..4dfa711
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-string.jsp
@@ -0,0 +1,33 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 String test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; i++) {
+ %>
+ <p>01 The value of foo is [<ts:tagString foo="${'bar'}" />]</p>
+ <p>02 The value of foo is [<ts:tagString foo='${"bar"}' />]</p>
+ <%--
+ <p>03 The value of foo is [<ts:tagString foo="bar" />]</p>
+ --%>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/webapp/bug6nnnn/bug64872-timeunit.jsp b/test/webapp/bug6nnnn/bug64872-timeunit.jsp
new file mode 100644
index 0000000..e21bc2d
--- /dev/null
+++ b/test/webapp/bug6nnnn/bug64872-timeunit.jsp
@@ -0,0 +1,33 @@
+<%--
+ 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.
+--%>
+<%@ taglib uri="http://tomcat.apache.org/tag-setters" prefix="ts" %>
+<html>
+ <head><title>Bug 64872 TimeUnit test case</title></head>
+ <body>
+ <%
+ for (int i=0; i < 1000000; 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>
+ --%>
+ <%
+ }
+ %>
+ </body>
+</html>
\ No newline at end of file
diff --git a/webapps/docs/jasper-howto.xml b/webapps/docs/jasper-howto.xml
index 56e731f..aea993c 100644
--- a/webapps/docs/jasper-howto.xml
+++ b/webapps/docs/jasper-howto.xml
@@ -399,8 +399,13 @@ with Jasper.
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.
+alternative EL interpreter. A alternative interpreter primarily targetting tag
+settings is provided at
+<code>org.apache.jasper.optimizations.ELInterpreterTagSetters</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