From d95cbe23ee462245c5c2482e175f7b2a921b31c2 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 28 Jul 2011 20:26:07 +0000 Subject: [PATCH] added support for web.xml context-param "springJspExpressionSupport" (explicit "true"/"false") --- .../web/util/ExpressionEvaluationUtils.java | 49 ++++++++++++++++--- .../util/ExpressionEvaluationUtilsTests.java | 27 ++++++++-- 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/ExpressionEvaluationUtils.java b/org.springframework.web/src/main/java/org/springframework/web/util/ExpressionEvaluationUtils.java index 11fd01e475..150f74346c 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/util/ExpressionEvaluationUtils.java +++ b/org.springframework.web/src/main/java/org/springframework/web/util/ExpressionEvaluationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.web.util; +import javax.servlet.ServletContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.el.ELException; @@ -30,6 +31,10 @@ import org.springframework.util.Assert; * invoking the EL evaluator, treating the value as "normal" expression * (i.e. a literal String value) else. * + *

See {@link #isSpringJspExpressionSupportActive} for guidelines + * on when to use Spring's JSP expression support as opposed to the + * built-in expression support in JSP 2.0+ containers. + * * @author Juergen Hoeller * @author Alef Arendsen * @since 11.07.2003 @@ -37,11 +42,42 @@ import org.springframework.util.Assert; */ public abstract class ExpressionEvaluationUtils { + /** + * Expression support parameter at the servlet context level + * (i.e. a context-param in web.xml): "springJspExpressionSupport". + */ + public static final String EXPRESSION_SUPPORT_CONTEXT_PARAM = "springJspExpressionSupport"; + public static final String EXPRESSION_PREFIX = "${"; public static final String EXPRESSION_SUFFIX = "}"; + /** + * Check whether Spring's JSP expression support is actually active. + *

Note that JSP 2.0+ containers come with expression support themselves: + * However, it will only be active for web applications declaring Servlet 2.4 + * or higher in their web.xml deployment descriptor. + *

If a web.xml context-param named "springJspExpressionSupport" is + * found, its boolean value will be taken to decide whether this support is active. + * If not found, for backwards compatibility with Servlet 2.3 applications, + * Spring's expression support will remain active by default. + *

Recommendations: Explicitly set "springJspExpressionSupport" to "false" + * in order to prevent double evaluation for Servlet 2.4+ based applications. + * @param pageContext current JSP PageContext + * @return true if active (ExpressionEvaluationUtils will actually evaluate expressions); + * false if not active (ExpressionEvaluationUtils will return given values as-is, + * relying on the JSP container pre-evaluating values before passing them to JSP tag attributes) + */ + public static boolean isSpringJspExpressionSupportActive(PageContext pageContext) { + ServletContext sc = pageContext.getServletContext(); + String springJspExpressionSupport = sc.getInitParameter(EXPRESSION_SUPPORT_CONTEXT_PARAM); + if (springJspExpressionSupport != null) { + return Boolean.valueOf(springJspExpressionSupport); + } + return true; + } + /** * Check if the given expression value is an EL expression. * @param value the expression to check @@ -67,7 +103,7 @@ public abstract class ExpressionEvaluationUtils { public static Object evaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext) throws JspException { - if (isExpressionLanguage(attrValue)) { + if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) { return doEvaluate(attrName, attrValue, resultClass, pageContext); } else if (attrValue != null && resultClass != null && !resultClass.isInstance(attrValue)) { @@ -90,7 +126,7 @@ public abstract class ExpressionEvaluationUtils { public static Object evaluate(String attrName, String attrValue, PageContext pageContext) throws JspException { - if (isExpressionLanguage(attrValue)) { + if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) { return doEvaluate(attrName, attrValue, Object.class, pageContext); } else { @@ -109,7 +145,7 @@ public abstract class ExpressionEvaluationUtils { public static String evaluateString(String attrName, String attrValue, PageContext pageContext) throws JspException { - if (isExpressionLanguage(attrValue)) { + if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) { return (String) doEvaluate(attrName, attrValue, String.class, pageContext); } else { @@ -128,7 +164,7 @@ public abstract class ExpressionEvaluationUtils { public static int evaluateInteger(String attrName, String attrValue, PageContext pageContext) throws JspException { - if (isExpressionLanguage(attrValue)) { + if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) { return (Integer) doEvaluate(attrName, attrValue, Integer.class, pageContext); } else { @@ -147,7 +183,7 @@ public abstract class ExpressionEvaluationUtils { public static boolean evaluateBoolean(String attrName, String attrValue, PageContext pageContext) throws JspException { - if (isExpressionLanguage(attrValue)) { + if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) { return (Boolean) doEvaluate(attrName, attrValue, Boolean.class, pageContext); } else { @@ -155,7 +191,6 @@ public abstract class ExpressionEvaluationUtils { } } - /** * Actually evaluate the given expression (be it EL or a literal String value) * to an Object of a given type. Supports concatenated expressions, diff --git a/org.springframework.web/src/test/java/org/springframework/web/util/ExpressionEvaluationUtilsTests.java b/org.springframework.web/src/test/java/org/springframework/web/util/ExpressionEvaluationUtilsTests.java index ab38e51888..5f030dd0e1 100644 --- a/org.springframework.web/src/test/java/org/springframework/web/util/ExpressionEvaluationUtilsTests.java +++ b/org.springframework.web/src/test/java/org/springframework/web/util/ExpressionEvaluationUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,18 +24,31 @@ import javax.servlet.jsp.el.ExpressionEvaluator; import javax.servlet.jsp.el.FunctionMapper; import javax.servlet.jsp.el.VariableResolver; -import junit.framework.TestCase; +import org.junit.Test; import org.springframework.mock.web.MockExpressionEvaluator; import org.springframework.mock.web.MockPageContext; +import org.springframework.mock.web.MockServletContext; + +import static org.junit.Assert.*; /** * @author Aled Arendsen * @author Juergen Hoeller * @since 16.09.2003 */ -public class ExpressionEvaluationUtilsTests extends TestCase { +public class ExpressionEvaluationUtilsTests { + @Test + public void testIsSpringJspExpressionSupportActive() { + MockServletContext sc = new MockServletContext(); + PageContext pc = new MockPageContext(sc); + assertTrue(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc)); + sc.addInitParameter("springJspExpressionSupport", "false"); + assertFalse(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc)); + } + + @Test public void testIsExpressionLanguage() { assertTrue(ExpressionEvaluationUtils.isExpressionLanguage("${bla}")); assertTrue(ExpressionEvaluationUtils.isExpressionLanguage("bla${bla}")); @@ -43,6 +56,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase { assertFalse(ExpressionEvaluationUtils.isExpressionLanguage("bla$b{")); } + @Test public void testEvaluate() throws Exception { PageContext ctx = new MockPageContext(); ctx.setAttribute("bla", "blie"); @@ -59,6 +73,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase { } } + @Test public void testEvaluateWithConcatenation() throws Exception { PageContext ctx = new MockPageContext(); ctx.setAttribute("bla", "blie"); @@ -98,6 +113,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase { } } + @Test public void testEvaluateString() throws Exception { PageContext ctx = new MockPageContext(); ctx.setAttribute("bla", "blie"); @@ -106,6 +122,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase { assertEquals("blie", ExpressionEvaluationUtils.evaluateString("test", "blie", ctx)); } + @Test public void testEvaluateStringWithConcatenation() throws Exception { PageContext ctx = new MockPageContext(); ctx.setAttribute("bla", "blie"); @@ -137,6 +154,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase { } + @Test public void testEvaluateInteger() throws Exception { PageContext ctx = new MockPageContext(); ctx.setAttribute("bla", new Integer(1)); @@ -145,6 +163,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase { assertEquals(21, ExpressionEvaluationUtils.evaluateInteger("test", "21", ctx)); } + @Test public void testEvaluateBoolean() throws Exception { PageContext ctx = new MockPageContext(); ctx.setAttribute("bla", new Boolean(true)); @@ -153,6 +172,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase { assertTrue(ExpressionEvaluationUtils.evaluateBoolean("test", "true", ctx)); } + @Test public void testRepeatedEvaluate() throws Exception { PageContext ctx = new CountingMockPageContext(); CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator(); @@ -172,6 +192,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase { assertEquals(4, eval.evaluateCount); } + @Test public void testEvaluateWithComplexConcatenation() throws Exception { PageContext ctx = new CountingMockPageContext(); CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator();