blob: ec4a3cb94101ef3e179b4cd414d1f3fed8159b9b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.compiler;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELManager;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import org.junit.Assert;
import org.junit.Test;
import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.ELNode.Nodes;
import org.apache.jasper.compiler.ELParser.TextBuilder;
/**
* You will need to keep your wits about you when working with this class. Keep
* in mind the following:
* <ul>
* <li>If in doubt, read the EL and JSP specifications. Twice.</li>
* <li>The escaping rules are complex and subtle. The explanation below (as well
* as the tests and the implementation) may have missed an edge case despite
* trying hard not to.
* <li>The strings passed to {@link #doTestParser(String,String)} are Java
* escaped in the source code and will be unescaped before being used.</li>
* <li>LiteralExpressions always occur outside of "${...}" and "#{...}". Literal
* expressions escape '$' and '#' with '\\'</li>
* <li>LiteralStrings always occur inside "${...}" or "#{...}". Literal strings
* escape '\'', '\"' and '\\' with '\\'. Escaping '\"' is optional if the
* literal string is delimited by '\''. Escaping '\'' is optional if the
* literal string is delimited by '\"'.</li>
* </ul>
*/
public class TestELParser {
@Test
public void testText() throws JasperException {
doTestParser("foo", "foo");
}
@Test
public void testLiteral() throws JasperException {
doTestParser("${'foo'}", "foo");
}
@Test
public void testVariable() throws JasperException {
doTestParser("${test}", null);
}
@Test
public void testFunction01() throws JasperException {
doTestParser("${do(x)}", null);
}
@Test
public void testFunction02() throws JasperException {
doTestParser("${do:it(x)}", null);
}
@Test
public void testFunction03() throws JasperException {
doTestParser("${do:it(x,y)}", null);
}
@Test
public void testFunction04() throws JasperException {
doTestParser("${do:it(x,y,z)}", null);
}
@Test
public void testFunction05() throws JasperException {
doTestParser("${do:it(x, '\\\\y',z)}", null);
}
@Test
public void testCompound01() throws JasperException {
doTestParser("1${'foo'}1", "1foo1");
}
@Test
public void testCompound02() throws JasperException {
doTestParser("1${test}1", null);
}
@Test
public void testCompound03() throws JasperException {
doTestParser("${foo}${bar}", null);
}
@Test
public void testTernary01() throws JasperException {
doTestParser("${true?true:false}", "true");
}
@Test
public void testTernary02() throws JasperException {
doTestParser("${a==1?true:false}", null);
}
@Test
public void testTernary03() throws JasperException {
doTestParser("${a eq1?true:false}", null);
}
@Test
public void testTernary04() throws JasperException {
doTestParser(" ${ a eq 1 ? true : false } ", null);
}
@Test
public void testTernary05() throws JasperException {
// Note this is invalid EL
doTestParser("${aeq1?true:false}", null);
}
@Test
public void testTernary06() throws JasperException {
doTestParser("${do:it(a eq1?true:false,y)}", null);
}
@Test
public void testTernary07() throws JasperException {
doTestParser(" ${ do:it( a eq 1 ? true : false, y ) } ", null);
}
@Test
public void testTernary08() throws JasperException {
doTestParser(" ${ do:it ( a eq 1 ? true : false, y ) } ", null);
}
@Test
public void testTernary09() throws JasperException {
doTestParser(" ${ do : it ( a eq 1 ? true : false, y ) } ", null);
}
@Test
public void testTernary10() throws JasperException {
doTestParser(" ${!empty my:link(foo)} ", null);
}
@Test
public void testTernary11() throws JasperException {
doTestParser("${true?'true':'false'}", "true");
}
@Test
public void testTernary12() throws JasperException {
doTestParser("${true?'tr\"ue':'false'}", "tr\"ue");
}
@Test
public void testTernary13() throws JasperException {
doTestParser("${true?'tr\\'ue':'false'}", "tr'ue");
}
@Test
public void testTernaryBug56031() throws JasperException {
doTestParser("${my:link(!empty registration ? registration : '/test/registration')}", null);
}
@Test
public void testQuotes01() throws JasperException {
doTestParser("'", "'");
}
@Test
public void testQuotes02() throws JasperException {
doTestParser("'${foo}'", null);
}
@Test
public void testQuotes03() throws JasperException {
doTestParser("'${'foo'}'", "'foo'");
}
@Test
public void testEscape01() throws JasperException {
doTestParser("${'\\\\'}", "\\");
}
@Test
public void testEscape02() throws JasperException {
doTestParser("\\\\x${'\\\\'}", "\\\\x\\");
}
@Test
public void testEscape03() throws JasperException {
doTestParser("\\\\", "\\\\");
}
@Test
public void testEscape04() throws JasperException {
// When parsed as EL in JSP the escaping of $ as \$ is optional
doTestParser("\\$", "\\$", "$");
}
@Test
public void testEscape05() throws JasperException {
// When parsed as EL in JSP the escaping of # as \# is optional
doTestParser("\\#", "\\#", "#");
}
@Test
public void testEscape07() throws JasperException {
doTestParser("${'\\\\$'}", "\\$");
}
@Test
public void testEscape08() throws JasperException {
doTestParser("${'\\\\#'}", "\\#");
}
@Test
public void testEscape09() throws JasperException {
doTestParser("\\${", "${");
}
@Test
public void testEscape10() throws JasperException {
doTestParser("\\#{", "#{");
}
@Test
public void testEscape11() throws JasperException {
// Bug 56612
doTestParser("${'\\'\\''}", "''");
}
private void doTestParser(String input, String expected) throws JasperException {
doTestParser(input, expected, input);
}
private void doTestParser(String input, String expectedResult, String expectedBuilderOutput) throws JasperException {
ELException elException = null;
String elResult = null;
// Don't try and evaluate expressions that depend on variables or functions
if (expectedResult != null) {
try {
ELManager manager = new ELManager();
ELContext context = manager.getELContext();
ExpressionFactory factory = ELManager.getExpressionFactory();
ValueExpression ve = factory.createValueExpression(context, input, String.class);
elResult = ve.getValue(context).toString();
Assert.assertEquals(expectedResult, elResult);
} catch (ELException ele) {
elException = ele;
}
}
Nodes nodes = null;
try {
nodes = ELParser.parse(input, false);
Assert.assertNull(elException);
} catch (IllegalArgumentException iae) {
Assert.assertNotNull(elResult, elException);
// Not strictly true but enables us to report both
iae.initCause(elException);
throw iae;
}
TextBuilder textBuilder = new TextBuilder(false);
nodes.visit(textBuilder);
Assert.assertEquals(expectedBuilderOutput, textBuilder.getText());
}
}