Browse Source

Spring JSP tags do not use their own expression support on Servlet 3.0 containers by default; added support for web.xml context-param "springJspExpressionSupport" (explicit "true"/"false")

pull/7/head
Juergen Hoeller 14 years ago
parent
commit
c864908779
  1. 64
      org.springframework.web/src/main/java/org/springframework/web/util/ExpressionEvaluationUtils.java
  2. 43
      org.springframework.web/src/test/java/org/springframework/mock/web/MockServletContext.java
  3. 51
      org.springframework.web/src/test/java/org/springframework/web/util/ExpressionEvaluationUtilsTests.java

64
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
package org.springframework.web.util; package org.springframework.web.util;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext; import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.el.ELException; 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 * invoking the EL evaluator, treating the value as "normal" expression
* (i.e. a literal String value) else. * (i.e. a literal String value) else.
* *
* <p><b>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.</b>
*
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Alef Arendsen * @author Alef Arendsen
* @since 11.07.2003 * @since 11.07.2003
@ -37,11 +42,57 @@ import org.springframework.util.Assert;
*/ */
public abstract class ExpressionEvaluationUtils { public abstract class ExpressionEvaluationUtils {
/**
* Expression support parameter at the servlet context level
* (i.e. a context-param in <code>web.xml</code>): "springJspExpressionSupport".
*/
public static final String EXPRESSION_SUPPORT_CONTEXT_PARAM = "springJspExpressionSupport";
public static final String EXPRESSION_PREFIX = "${"; public static final String EXPRESSION_PREFIX = "${";
public static final String EXPRESSION_SUFFIX = "}"; public static final String EXPRESSION_SUFFIX = "}";
/**
* Check whether Spring's JSP expression support is actually active.
* <p>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 <code>web.xml</code> deployment descriptor.
* <p>If a <code>web.xml</code> context-param named "springJspExpressionSupport" is
* found, its boolean value will be taken to decide whether this support is active.
* If not found, the default is for expression support to be inactive on Servlet 3.0
* containers with web applications declaring Servlet 2.4 or higher in their
* <code>web.xml</code>. For backwards compatibility, Spring's expression support
* will remain active for applications declaring Servlet 2.3 or earlier. However,
* on Servlet 2.4/2.5 containers, we can't find out what the application has declared,
* so we'll also fall back to keeping expression support active in such a case.
* <p><b>Recommendations:</b> Explicitly set "springJspExpressionSupport" to "false"
* in order to prevent double evaluation for Servlet 2.4+ based applications.
* On Servlet 3.0 containers, this will be done for you by default by the framework.
* If for some reason you nevertheless want Spring's JSP expression support to be
* active, explicitly set the "springJspExpressionSupport" context-param to "true".
* @param pageContext current JSP PageContext
* @return <code>true</code> if active (ExpressionEvaluationUtils will actually evaluate expressions);
* <code>false</code> 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);
}
if (sc.getMajorVersion() >= 3) {
// We're on a Servlet 3.0+ container: Let's check what the application declares...
if (sc.getEffectiveMajorVersion() > 2 || sc.getEffectiveMinorVersion() > 3) {
// Application declares Servlet 2.4+ in its web.xml: JSP 2.0 expressions active.
// Skip our own expression support in order to prevent double evaluation.
return false;
}
}
return true;
}
/** /**
* Check if the given expression value is an EL expression. * Check if the given expression value is an EL expression.
* @param value the expression to check * @param value the expression to check
@ -67,7 +118,7 @@ public abstract class ExpressionEvaluationUtils {
public static Object evaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext) public static Object evaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext)
throws JspException { throws JspException {
if (isExpressionLanguage(attrValue)) { if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) {
return doEvaluate(attrName, attrValue, resultClass, pageContext); return doEvaluate(attrName, attrValue, resultClass, pageContext);
} }
else if (attrValue != null && resultClass != null && !resultClass.isInstance(attrValue)) { else if (attrValue != null && resultClass != null && !resultClass.isInstance(attrValue)) {
@ -90,7 +141,7 @@ public abstract class ExpressionEvaluationUtils {
public static Object evaluate(String attrName, String attrValue, PageContext pageContext) public static Object evaluate(String attrName, String attrValue, PageContext pageContext)
throws JspException { throws JspException {
if (isExpressionLanguage(attrValue)) { if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) {
return doEvaluate(attrName, attrValue, Object.class, pageContext); return doEvaluate(attrName, attrValue, Object.class, pageContext);
} }
else { else {
@ -109,7 +160,7 @@ public abstract class ExpressionEvaluationUtils {
public static String evaluateString(String attrName, String attrValue, PageContext pageContext) public static String evaluateString(String attrName, String attrValue, PageContext pageContext)
throws JspException { throws JspException {
if (isExpressionLanguage(attrValue)) { if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) {
return (String) doEvaluate(attrName, attrValue, String.class, pageContext); return (String) doEvaluate(attrName, attrValue, String.class, pageContext);
} }
else { else {
@ -128,7 +179,7 @@ public abstract class ExpressionEvaluationUtils {
public static int evaluateInteger(String attrName, String attrValue, PageContext pageContext) public static int evaluateInteger(String attrName, String attrValue, PageContext pageContext)
throws JspException { throws JspException {
if (isExpressionLanguage(attrValue)) { if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) {
return (Integer) doEvaluate(attrName, attrValue, Integer.class, pageContext); return (Integer) doEvaluate(attrName, attrValue, Integer.class, pageContext);
} }
else { else {
@ -147,7 +198,7 @@ public abstract class ExpressionEvaluationUtils {
public static boolean evaluateBoolean(String attrName, String attrValue, PageContext pageContext) public static boolean evaluateBoolean(String attrName, String attrValue, PageContext pageContext)
throws JspException { throws JspException {
if (isExpressionLanguage(attrValue)) { if (isSpringJspExpressionSupportActive(pageContext) && isExpressionLanguage(attrValue)) {
return (Boolean) doEvaluate(attrName, attrValue, Boolean.class, pageContext); return (Boolean) doEvaluate(attrName, attrValue, Boolean.class, pageContext);
} }
else { else {
@ -155,7 +206,6 @@ public abstract class ExpressionEvaluationUtils {
} }
} }
/** /**
* Actually evaluate the given expression (be it EL or a literal String value) * Actually evaluate the given expression (be it EL or a literal String value)
* to an Object of a given type. Supports concatenated expressions, * to an Object of a given type. Supports concatenated expressions,

43
org.springframework.web/src/test/java/org/springframework/mock/web/MockServletContext.java

@ -76,8 +76,8 @@ import org.springframework.web.util.WebUtils;
* and XmlWebApplicationContext with an underlying MockServletContext (as long as * and XmlWebApplicationContext with an underlying MockServletContext (as long as
* the MockServletContext has been configured with a FileSystemResourceLoader). * the MockServletContext has been configured with a FileSystemResourceLoader).
* *
* Supports the Servlet 3.0 API level, but throws {@link UnsupportedOperationException} * <p>Supports Servlet 3.0 API level, but throws {@link UnsupportedOperationException}
* for all methods introduced in Servlet 3.0. * for most methods introduced in Servlet 3.0.
* *
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
@ -102,8 +102,14 @@ public class MockServletContext implements ServletContext {
private String contextPath = ""; private String contextPath = "";
private int majorVersion = 2;
private int minorVersion = 5; private int minorVersion = 5;
private int effectiveMajorVersion = 2;
private int effectiveMinorVersion = 5;
private final Map<String, ServletContext> contexts = new HashMap<String, ServletContext>(); private final Map<String, ServletContext> contexts = new HashMap<String, ServletContext>();
private final Map<String, String> initParameters = new LinkedHashMap<String, String>(); private final Map<String, String> initParameters = new LinkedHashMap<String, String>();
@ -191,14 +197,15 @@ public class MockServletContext implements ServletContext {
return this.contexts.get(contextPath); return this.contexts.get(contextPath);
} }
public void setMajorVersion(int majorVersion) {
this.majorVersion = majorVersion;
}
public int getMajorVersion() { public int getMajorVersion() {
return 2; return this.majorVersion;
} }
public void setMinorVersion(int minorVersion) { public void setMinorVersion(int minorVersion) {
if (minorVersion < 3 || minorVersion > 5) {
throw new IllegalArgumentException("Only Servlet minor versions between 3 and 5 are supported");
}
this.minorVersion = minorVersion; this.minorVersion = minorVersion;
} }
@ -206,6 +213,22 @@ public class MockServletContext implements ServletContext {
return this.minorVersion; return this.minorVersion;
} }
public void setEffectiveMajorVersion(int effectiveMajorVersion) {
this.effectiveMajorVersion = effectiveMajorVersion;
}
public int getEffectiveMajorVersion() {
return this.effectiveMajorVersion;
}
public void setEffectiveMinorVersion(int effectiveMinorVersion) {
this.effectiveMinorVersion = effectiveMinorVersion;
}
public int getEffectiveMinorVersion() {
return this.effectiveMinorVersion;
}
public String getMimeType(String filePath) { public String getMimeType(String filePath) {
return MimeTypeResolver.getMimeType(filePath); return MimeTypeResolver.getMimeType(filePath);
} }
@ -444,14 +467,6 @@ public class MockServletContext implements ServletContext {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public int getEffectiveMajorVersion() {
throw new UnsupportedOperationException();
}
public int getEffectiveMinorVersion() {
throw new UnsupportedOperationException();
}
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() { public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

51
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,18 +24,55 @@ import javax.servlet.jsp.el.ExpressionEvaluator;
import javax.servlet.jsp.el.FunctionMapper; import javax.servlet.jsp.el.FunctionMapper;
import javax.servlet.jsp.el.VariableResolver; 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.MockExpressionEvaluator;
import org.springframework.mock.web.MockPageContext; import org.springframework.mock.web.MockPageContext;
import org.springframework.mock.web.MockServletContext;
import static org.junit.Assert.*;
/** /**
* @author Aled Arendsen * @author Aled Arendsen
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 16.09.2003 * @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 testIsSpringJspExpressionSupportActiveOnServlet30() {
MockServletContext sc = new MockServletContext();
sc.setMajorVersion(3);
sc.setMinorVersion(0);
PageContext pc = new MockPageContext(sc);
assertFalse(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc));
sc.addInitParameter("springJspExpressionSupport", "true");
assertTrue(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc));
}
@Test
public void testIsSpringJspExpressionSupportActiveOnServlet30WithServlet23Application() {
MockServletContext sc = new MockServletContext();
sc.setMajorVersion(3);
sc.setMinorVersion(0);
sc.setEffectiveMajorVersion(2);
sc.setEffectiveMinorVersion(3);
PageContext pc = new MockPageContext(sc);
assertTrue(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc));
sc.addInitParameter("springJspExpressionSupport", "false");
assertFalse(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc));
}
@Test
public void testIsExpressionLanguage() { public void testIsExpressionLanguage() {
assertTrue(ExpressionEvaluationUtils.isExpressionLanguage("${bla}")); assertTrue(ExpressionEvaluationUtils.isExpressionLanguage("${bla}"));
assertTrue(ExpressionEvaluationUtils.isExpressionLanguage("bla${bla}")); assertTrue(ExpressionEvaluationUtils.isExpressionLanguage("bla${bla}"));
@ -43,6 +80,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
assertFalse(ExpressionEvaluationUtils.isExpressionLanguage("bla$b{")); assertFalse(ExpressionEvaluationUtils.isExpressionLanguage("bla$b{"));
} }
@Test
public void testEvaluate() throws Exception { public void testEvaluate() throws Exception {
PageContext ctx = new MockPageContext(); PageContext ctx = new MockPageContext();
ctx.setAttribute("bla", "blie"); ctx.setAttribute("bla", "blie");
@ -59,6 +97,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
} }
} }
@Test
public void testEvaluateWithConcatenation() throws Exception { public void testEvaluateWithConcatenation() throws Exception {
PageContext ctx = new MockPageContext(); PageContext ctx = new MockPageContext();
ctx.setAttribute("bla", "blie"); ctx.setAttribute("bla", "blie");
@ -98,6 +137,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
} }
} }
@Test
public void testEvaluateString() throws Exception { public void testEvaluateString() throws Exception {
PageContext ctx = new MockPageContext(); PageContext ctx = new MockPageContext();
ctx.setAttribute("bla", "blie"); ctx.setAttribute("bla", "blie");
@ -106,6 +146,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
assertEquals("blie", ExpressionEvaluationUtils.evaluateString("test", "blie", ctx)); assertEquals("blie", ExpressionEvaluationUtils.evaluateString("test", "blie", ctx));
} }
@Test
public void testEvaluateStringWithConcatenation() throws Exception { public void testEvaluateStringWithConcatenation() throws Exception {
PageContext ctx = new MockPageContext(); PageContext ctx = new MockPageContext();
ctx.setAttribute("bla", "blie"); ctx.setAttribute("bla", "blie");
@ -137,6 +178,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
} }
@Test
public void testEvaluateInteger() throws Exception { public void testEvaluateInteger() throws Exception {
PageContext ctx = new MockPageContext(); PageContext ctx = new MockPageContext();
ctx.setAttribute("bla", new Integer(1)); ctx.setAttribute("bla", new Integer(1));
@ -145,6 +187,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
assertEquals(21, ExpressionEvaluationUtils.evaluateInteger("test", "21", ctx)); assertEquals(21, ExpressionEvaluationUtils.evaluateInteger("test", "21", ctx));
} }
@Test
public void testEvaluateBoolean() throws Exception { public void testEvaluateBoolean() throws Exception {
PageContext ctx = new MockPageContext(); PageContext ctx = new MockPageContext();
ctx.setAttribute("bla", new Boolean(true)); ctx.setAttribute("bla", new Boolean(true));
@ -153,6 +196,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
assertTrue(ExpressionEvaluationUtils.evaluateBoolean("test", "true", ctx)); assertTrue(ExpressionEvaluationUtils.evaluateBoolean("test", "true", ctx));
} }
@Test
public void testRepeatedEvaluate() throws Exception { public void testRepeatedEvaluate() throws Exception {
PageContext ctx = new CountingMockPageContext(); PageContext ctx = new CountingMockPageContext();
CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator(); CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator();
@ -172,6 +216,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
assertEquals(4, eval.evaluateCount); assertEquals(4, eval.evaluateCount);
} }
@Test
public void testEvaluateWithComplexConcatenation() throws Exception { public void testEvaluateWithComplexConcatenation() throws Exception {
PageContext ctx = new CountingMockPageContext(); PageContext ctx = new CountingMockPageContext();
CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator(); CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator();

Loading…
Cancel
Save