import org.apache.el.ExpressionFactoryImpl;
import org.apache.el.lang.ELSupport;
+import org.apache.jasper.compiler.TestAttributeParser;
import org.apache.jasper.el.ELContextImpl;
import junit.framework.TestCase;
/**
- * Tests for EL parsing and evaluation.
+ * Tests the EL engine directly. Similar tests may be found in
+ * {@link TestAttributeParser} and {@link TestELInJsp}.
*/
public class TestELEvaluation extends TestCase {
+ /**
+ * Test use of spaces in ternary expressions. This was primarily an EL
+ * parser bug.
+ */
+ public void testBug42565() {
+ assertEquals("false", evaluateExpression("${false?true:false}"));
+ assertEquals("false", evaluateExpression("${false?true: false}"));
+ assertEquals("false", evaluateExpression("${false?true :false}"));
+ assertEquals("false", evaluateExpression("${false?true : false}"));
+ assertEquals("false", evaluateExpression("${false? true:false}"));
+ assertEquals("false", evaluateExpression("${false? true: false}"));
+ assertEquals("false", evaluateExpression("${false? true :false}"));
+ assertEquals("false", evaluateExpression("${false? true : false}"));
+ assertEquals("false", evaluateExpression("${false ?true:false}"));
+ assertEquals("false", evaluateExpression("${false ?true: false}"));
+ assertEquals("false", evaluateExpression("${false ?true :false}"));
+ assertEquals("false", evaluateExpression("${false ?true : false}"));
+ assertEquals("false", evaluateExpression("${false ? true:false}"));
+ assertEquals("false", evaluateExpression("${false ? true: false}"));
+ assertEquals("false", evaluateExpression("${false ? true :false}"));
+ assertEquals("false", evaluateExpression("${false ? true : false}"));
+ }
+
+
+ /**
+ * Test use nested ternary expressions. This was primarily an EL parser bug.
+ */
+ public void testBug44994() {
+ assertEquals("none", evaluateExpression(
+ "${0 lt 0 ? 1 lt 0 ? 'many': 'one': 'none'}"));
+ assertEquals("one", evaluateExpression(
+ "${0 lt 1 ? 1 lt 1 ? 'many': 'one': 'none'}"));
+ assertEquals("many", evaluateExpression(
+ "${0 lt 2 ? 1 lt 2 ? 'many': 'one': 'none'}"));
+ }
+
+
public void testParserBug45511() {
// Test cases provided by OP
assertEquals("true", evaluateExpression("${empty ('')}"));
assertEquals("false", evaluateExpression("${(true)and(false)}"));
}
- public void testParserBug42565() {
- // Test cases provided by OP
- assertEquals("false", evaluateExpression("${false?true:false}"));
- }
-
public void testParserLiteralExpression() {
// Inspired by work on bug 45451, comments from kkolinko on the dev
// list and looking at the spec to find some edge cases
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.jasper.compiler.TestAttributeParser;
import org.apache.tomcat.util.buf.ByteChunk;
+/**
+ * Tests EL with an without JSP attributes using a test web application. Similar
+ * tests may be found in {@link TestELEvaluation} and {@link TestAttributeParser}.
+ */
public class TestELInJsp extends TomcatBaseTest {
public void testBug42565() throws Exception {
Tomcat tomcat = getTomcatInstance();
- File appDir =
- new File("test/webapp");
+ File appDir = new File("test/webapp");
// app dir is relative to server home
tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
res = getUrl("http://localhost:" + getPort() + "/test/bug45451b.jsp");
result = res.toString();
- System.out.println(result);
// Warning: JSP attribute escaping != Java String escaping
// Warning: Attributes are always unescaped before passing to the EL
// processor
assertTrue(result.indexOf("03-\\\\${1+1}") > 0);
assertTrue(result.indexOf("04-2") > 0);
assertTrue(result.indexOf("05-${1+1}") > 0);
- assertTrue(result.indexOf("06-\\2") > 0); // TODO Fails (bug)
+ assertTrue(result.indexOf("06-\\2") > 0);
assertTrue(result.indexOf("07-\\${1+1}") > 0);
- assertTrue(result.indexOf("08-\\\\2") > 0); // TODO Fails (bug)
+ assertTrue(result.indexOf("08-\\\\2") > 0);
res = getUrl("http://localhost:" + getPort() + "/test/bug45451c.jsp");
result = res.toString();
String result = res.toString();
assertTrue(result.indexOf("00-\\\\\\\"${'hello world'}") > 0);
assertTrue(result.indexOf("01-\\\\\\\"\\${'hello world'}") > 0);
- assertTrue(result.indexOf("02-\\\"\\${'hello world'}") > 0); // TODO - bug
- assertTrue(result.indexOf("03-\\\"\\hello world") > 0); // TODO - bug
+ assertTrue(result.indexOf("02-\\\"${'hello world'}") > 0);
+ assertTrue(result.indexOf("03-\\\"\\hello world") > 0);
assertTrue(result.indexOf("2az-04") > 0);
assertTrue(result.indexOf("05-a2z") > 0);
assertTrue(result.indexOf("06-az2") > 0);
assertTrue(result.indexOf("11-\"}") > 0);
}
+ public void testScriptingExpression() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ File appDir =
+ new File("test/webapp");
+ // app dir is relative to server home
+ tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());
+
+ tomcat.start();
+
+ ByteChunk res = getUrl("http://localhost:" + getPort() +
+ "/test/script-expr.jsp");
+ String result = res.toString();
+ System.out.println(result);
+ assertTrue(result.indexOf("00-hello world") > 0);
+ assertTrue(result.indexOf("01-hello \"world") > 0);
+ assertTrue(result.indexOf("02-hello \\\"world") > 0);
+ assertTrue(result.indexOf("03-hello ${world") > 0);
+ assertTrue(result.indexOf("04-hello \\${world") > 0);
+ assertTrue(result.indexOf("05-hello world") > 0);
+ assertTrue(result.indexOf("06-hello \"world") > 0);
+ assertTrue(result.indexOf("07-hello \\\"world") > 0);
+ assertTrue(result.indexOf("08-hello ${world") > 0);
+ assertTrue(result.indexOf("09-hello \\${world") > 0);
+ assertTrue(result.indexOf("10-hello <% world") > 0);
+ assertTrue(result.indexOf("11-hello %> world") > 0);
+ }
}
--- /dev/null
+/*
+ * 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.lang.reflect.Method;
+
+import javax.el.FunctionMapper;
+import javax.el.ValueExpression;
+
+import org.apache.el.ExpressionFactoryImpl;
+import org.apache.el.TestELEvaluation;
+import org.apache.el.TestELInJsp;
+import org.apache.el.TesterFunctions;
+import org.apache.jasper.el.ELContextImpl;
+
+import junit.framework.TestCase;
+
+/**
+ * Test the EL processing from JSP attributes. Similar tests may be found in
+ * {@link TestELEvaluation} and {@link TestELInJsp}.
+ */
+public class TestAttributeParser extends TestCase {
+
+ /**
+ * Test use of spaces in ternary expressions. This was primarily an EL
+ * parser bug.
+ */
+ public void testBug42565() {
+ assertEquals("false", evalAttr("${false?true:false}", '\"'));
+ assertEquals("false", evalAttr("${false?true: false}", '\"'));
+ assertEquals("false", evalAttr("${false?true :false}", '\"'));
+ assertEquals("false", evalAttr("${false?true : false}", '\"'));
+ assertEquals("false", evalAttr("${false? true:false}", '\"'));
+ assertEquals("false", evalAttr("${false? true: false}", '\"'));
+ assertEquals("false", evalAttr("${false? true :false}", '\"'));
+ assertEquals("false", evalAttr("${false? true : false}", '\"'));
+ assertEquals("false", evalAttr("${false ?true:false}", '\"'));
+ assertEquals("false", evalAttr("${false ?true: false}", '\"'));
+ assertEquals("false", evalAttr("${false ?true :false}", '\"'));
+ assertEquals("false", evalAttr("${false ?true : false}", '\"'));
+ assertEquals("false", evalAttr("${false ? true:false}", '\"'));
+ assertEquals("false", evalAttr("${false ? true: false}", '\"'));
+ assertEquals("false", evalAttr("${false ? true :false}", '\"'));
+ assertEquals("false", evalAttr("${false ? true : false}", '\"'));
+ }
+
+
+ /**
+ * Test use nested ternary expressions. Full tests in
+ * {@link TestELEvaluation}. This is just a smoke test to ensure JSP
+ * attribute processing doesn't cause any additional issues.
+ */
+ public void testBug44994() {
+ assertEquals("none",
+ evalAttr("${0 lt 0 ? 1 lt 0 ? 'many': 'one': 'none'}", '\"'));
+ assertEquals("one",
+ evalAttr("${0 lt 1 ? 1 lt 1 ? 'many': 'one': 'none'}", '\"'));
+ assertEquals("many",
+ evalAttr("${0 lt 2 ? 1 lt 2 ? 'many': 'one': 'none'}", '\"'));
+ }
+
+
+ /**
+ * Test the quoting requirements of JSP attributes. This doesn't make use of
+ * EL. See {@link #testBug45451()} for a test that combines JSP attribute
+ * quoting and EL quoting.
+ */
+ public void testBug45015() {
+ // Warning: Java String quoting vs. JSP attribute quoting
+ assertEquals("hello 'world'", evalAttr("hello 'world'", '\"'));
+ assertEquals("hello 'world", evalAttr("hello 'world", '\"'));
+ assertEquals("hello world'", evalAttr("hello world'", '\"'));
+ assertEquals("hello world'", evalAttr("hello world\\'", '\"'));
+ assertEquals("hello world\"", evalAttr("hello world\\\"", '\"'));
+ assertEquals("hello \"world\"", evalAttr("hello \"world\"", '\"'));
+ assertEquals("hello \"world", evalAttr("hello \"world", '\"'));
+ assertEquals("hello world\"", evalAttr("hello world\"", '\"'));
+ assertEquals("hello world'", evalAttr("hello world\\'", '\"'));
+ assertEquals("hello world\"", evalAttr("hello world\\\"", '\"'));
+
+ assertEquals("hello 'world'", evalAttr("hello 'world'", '\''));
+ assertEquals("hello 'world", evalAttr("hello 'world", '\''));
+ assertEquals("hello world'", evalAttr("hello world'", '\''));
+ assertEquals("hello world'", evalAttr("hello world\\'", '\''));
+ assertEquals("hello world\"", evalAttr("hello world\\\"", '\''));
+ assertEquals("hello \"world\"", evalAttr("hello \"world\"", '\''));
+ assertEquals("hello \"world", evalAttr("hello \"world", '\''));
+ assertEquals("hello world\"", evalAttr("hello world\"", '\''));
+ assertEquals("hello world'", evalAttr("hello world\\'", '\''));
+ assertEquals("hello world\"", evalAttr("hello world\\\"", '\''));
+
+ }
+
+
+ public void testBug45451() {
+ assertEquals("2", evalAttr("${1+1}", '\"'));
+ assertEquals("${1+1}", evalAttr("\\${1+1}", '\"'));
+ assertEquals("\\2", evalAttr("\\\\${1+1}", '\"'));
+ }
+
+ public void testLiteral() {
+ // Inspired by work on bug 45451, comments from kkolinko on the dev
+ // list and looking at the spec to find some edge cases
+
+ // '\' is only an escape character inside a StringLiteral
+ assertEquals("\\", evalAttr("${'\\\\\\\\'}", '\"'));
+ assertEquals("\\", evalAttr("${\"\\\\\\\\\"}", '\"'));
+
+ // Can use ''' inside '"' when quoting with '"' and vice versa without
+ // escaping
+ assertEquals("\\\"", evalAttr("${'\\\\\\\\\\\"'}", '\"'));
+ assertEquals("\"\\", evalAttr("${'\\\"\\\\\\\\'}", '\"'));
+ assertEquals("\\'", evalAttr("${'\\\\\\\\\\\\''}", '\"'));
+ assertEquals("'\\", evalAttr("${'\\\\'\\\\\\\\'}", '\"'));
+ assertEquals("\\'", evalAttr("${\\\"\\\\\\\\'\\\"}", '\"'));
+ assertEquals("'\\", evalAttr("${\\\"'\\\\\\\\\\\"}", '\"'));
+ assertEquals("\\\"", evalAttr("${\\\"\\\\\\\\\\\\\\\"\\\"}", '\"'));
+ assertEquals("\"\\", evalAttr("${\\\"\\\\\\\"\\\\\\\\\\\"}", '\"'));
+
+ // Quoting <% and %>
+ assertEquals("hello <% world", evalAttr("hello <\\% world", '\"'));
+ assertEquals("hello %> world", evalAttr("hello %> world", '\"'));
+ }
+
+ public void testScriptExpressiinLiterals() {
+ assertEquals(" \"hello world\" ", parseScriptExpression(
+ " \"hello world\" ", (char) 0));
+ assertEquals(" \"hello \\\"world\" ", parseScriptExpression(
+ " \"hello \\\\\"world\" ", (char) 0));
+ }
+
+ private String evalAttr(String expression, char quote) {
+
+ ELContextImpl ctx = new ELContextImpl();
+ ctx.setFunctionMapper(new FMapper());
+ ExpressionFactoryImpl exprFactory = new ExpressionFactoryImpl();
+ ValueExpression ve = exprFactory.createValueExpression(ctx,
+ AttributeParser.getUnquoted(expression, quote, false, false),
+ String.class);
+ return (String) ve.getValue(ctx);
+ }
+
+ private String parseScriptExpression(String expression, char quote) {
+ return AttributeParser.getUnquoted(expression, quote, false, false);
+ }
+
+ public static class FMapper extends FunctionMapper {
+
+ @Override
+ public Method resolveFunction(String prefix, String localName) {
+ if ("trim".equals(localName)) {
+ Method m;
+ try {
+ m = TesterFunctions.class.getMethod("trim", String.class);
+ return m;
+ } catch (SecurityException e) {
+ // Ignore
+ } catch (NoSuchMethodException e) {
+ // Ignore
+ }
+ }
+ return null;
+ }
+ }
+}