removed outdated "cacheJspExpressions" feature from ExpressionEvaluationUtils

This commit is contained in:
Juergen Hoeller 2009-09-24 15:56:00 +00:00
parent c761082eea
commit 8eca898d44
2 changed files with 12 additions and 163 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 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,14 +16,9 @@
package org.springframework.web.util; package org.springframework.web.util;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
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;
import javax.servlet.jsp.el.Expression;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -31,12 +26,6 @@ import org.springframework.util.Assert;
* Convenience methods for accessing JSP 2.0's * Convenience methods for accessing JSP 2.0's
* {@link javax.servlet.jsp.el.ExpressionEvaluator}. * {@link javax.servlet.jsp.el.ExpressionEvaluator}.
* *
* <p>This class will by default use standard <code>evaluate</code> calls.
* If your application server happens to be inefficient in that respect,
* consider setting Spring's "cacheJspExpressions" context-param in
* <code>web.xml</code> to "true", which will use <code>parseExpression</code>
* calls with cached Expression objects instead.
*
* <p>The evaluation methods check if the value contains "${" before * <p>The evaluation methods check if the value contains "${" before
* 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.
@ -45,28 +34,14 @@ import org.springframework.util.Assert;
* @author Alef Arendsen * @author Alef Arendsen
* @since 11.07.2003 * @since 11.07.2003
* @see javax.servlet.jsp.el.ExpressionEvaluator#evaluate * @see javax.servlet.jsp.el.ExpressionEvaluator#evaluate
* @see javax.servlet.jsp.el.ExpressionEvaluator#parseExpression
*/ */
public abstract class ExpressionEvaluationUtils { public abstract class ExpressionEvaluationUtils {
/**
* JSP 2.0 expression cache parameter at the servlet context level
* (i.e. a context-param in <code>web.xml</code>): "cacheJspExpressions".
*/
public static final String EXPRESSION_CACHE_CONTEXT_PARAM = "cacheJspExpressions";
public static final String EXPRESSION_PREFIX = "${"; public static final String EXPRESSION_PREFIX = "${";
public static final String EXPRESSION_SUFFIX = "}"; public static final String EXPRESSION_SUFFIX = "}";
private static final String EXPRESSION_CACHE_FLAG_CONTEXT_ATTR =
ExpressionEvaluationUtils.class.getName() + ".CACHE_JSP_EXPRESSIONS";
private static final String EXPRESSION_CACHE_MAP_CONTEXT_ATTR =
ExpressionEvaluationUtils.class.getName() + ".JSP_EXPRESSION_CACHE";
/** /**
* 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
@ -90,7 +65,7 @@ public abstract class ExpressionEvaluationUtils {
* the result class * the result class
*/ */
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 (isExpressionLanguage(attrValue)) {
return doEvaluate(attrName, attrValue, resultClass, pageContext); return doEvaluate(attrName, attrValue, resultClass, pageContext);
@ -113,7 +88,7 @@ public abstract class ExpressionEvaluationUtils {
* @throws JspException in case of parsing errors * @throws JspException in case of parsing errors
*/ */
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 (isExpressionLanguage(attrValue)) {
return doEvaluate(attrName, attrValue, Object.class, pageContext); return doEvaluate(attrName, attrValue, Object.class, pageContext);
@ -132,7 +107,7 @@ public abstract class ExpressionEvaluationUtils {
* @throws JspException in case of parsing errors * @throws JspException in case of parsing errors
*/ */
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 (isExpressionLanguage(attrValue)) {
return (String) doEvaluate(attrName, attrValue, String.class, pageContext); return (String) doEvaluate(attrName, attrValue, String.class, pageContext);
@ -170,7 +145,7 @@ public abstract class ExpressionEvaluationUtils {
* @throws JspException in case of parsing errors * @throws JspException in case of parsing errors
*/ */
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 (isExpressionLanguage(attrValue)) {
return (Boolean) doEvaluate(attrName, attrValue, Boolean.class, pageContext); return (Boolean) doEvaluate(attrName, attrValue, Boolean.class, pageContext);
@ -202,14 +177,14 @@ public abstract class ExpressionEvaluationUtils {
try { try {
if (resultClass.isAssignableFrom(String.class)) { if (resultClass.isAssignableFrom(String.class)) {
StringBuilder resultValue = null; StringBuilder resultValue = null;
int exprPrefixIndex = -1; int exprPrefixIndex;
int exprSuffixIndex = 0; int exprSuffixIndex = 0;
do { do {
exprPrefixIndex = attrValue.indexOf(EXPRESSION_PREFIX, exprSuffixIndex); exprPrefixIndex = attrValue.indexOf(EXPRESSION_PREFIX, exprSuffixIndex);
if (exprPrefixIndex != -1) { if (exprPrefixIndex != -1) {
int prevExprSuffixIndex = exprSuffixIndex; int prevExprSuffixIndex = exprSuffixIndex;
exprSuffixIndex = attrValue.indexOf(EXPRESSION_SUFFIX, exprPrefixIndex + EXPRESSION_PREFIX.length()); exprSuffixIndex = attrValue.indexOf(EXPRESSION_SUFFIX, exprPrefixIndex + EXPRESSION_PREFIX.length());
String expr = null; String expr;
if (exprSuffixIndex != -1) { if (exprSuffixIndex != -1) {
exprSuffixIndex += EXPRESSION_SUFFIX.length(); exprSuffixIndex += EXPRESSION_SUFFIX.length();
expr = attrValue.substring(exprPrefixIndex, exprSuffixIndex); expr = attrValue.substring(exprPrefixIndex, exprSuffixIndex);
@ -253,79 +228,8 @@ public abstract class ExpressionEvaluationUtils {
private static Object evaluateExpression(String exprValue, Class resultClass, PageContext pageContext) private static Object evaluateExpression(String exprValue, Class resultClass, PageContext pageContext)
throws ELException { throws ELException {
Map<ExpressionCacheKey, Expression> expressionCache = getJspExpressionCache(pageContext); return pageContext.getExpressionEvaluator().evaluate(
if (expressionCache != null) { exprValue, resultClass, pageContext.getVariableResolver(), null);
// We are supposed to explicitly create and cache JSP Expression objects.
ExpressionCacheKey cacheKey = new ExpressionCacheKey(exprValue, resultClass);
Expression expr = expressionCache.get(cacheKey);
if (expr == null) {
expr = pageContext.getExpressionEvaluator().parseExpression(exprValue, resultClass, null);
expressionCache.put(cacheKey, expr);
}
return expr.evaluate(pageContext.getVariableResolver());
}
else {
// We're simply calling the JSP 2.0 evaluate method straight away.
return pageContext.getExpressionEvaluator().evaluate(
exprValue, resultClass, pageContext.getVariableResolver(), null);
}
}
/**
* Determine whether JSP 2.0 expressions are supposed to be cached
* and return the corresponding cache Map, or <code>null</code> if
* caching is not enabled.
* @param pageContext current JSP PageContext
* @return the cache Map, or <code>null</code> if caching is disabled
*/
@SuppressWarnings("unchecked")
private static Map<ExpressionCacheKey, Expression> getJspExpressionCache(PageContext pageContext) {
ServletContext servletContext = pageContext.getServletContext();
Map<ExpressionCacheKey, Expression> cacheMap =
(Map<ExpressionCacheKey, Expression>) servletContext.getAttribute(EXPRESSION_CACHE_MAP_CONTEXT_ATTR);
if (cacheMap == null) {
Boolean cacheFlag = (Boolean) servletContext.getAttribute(EXPRESSION_CACHE_FLAG_CONTEXT_ATTR);
if (cacheFlag == null) {
cacheFlag = Boolean.valueOf(servletContext.getInitParameter(EXPRESSION_CACHE_CONTEXT_PARAM));
servletContext.setAttribute(EXPRESSION_CACHE_FLAG_CONTEXT_ATTR, cacheFlag);
}
if (cacheFlag) {
cacheMap = Collections.synchronizedMap(new HashMap<ExpressionCacheKey, Expression>());
servletContext.setAttribute(EXPRESSION_CACHE_MAP_CONTEXT_ATTR, cacheMap);
}
}
return cacheMap;
}
/**
* Cache key class for JSP 2.0 Expression objects.
*/
private static class ExpressionCacheKey {
private final String value;
private final Class resultClass;
private final int hashCode;
public ExpressionCacheKey(String value, Class resultClass) {
this.value = value;
this.resultClass = resultClass;
this.hashCode = this.value.hashCode() * 29 + this.resultClass.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ExpressionCacheKey)) {
return false;
}
ExpressionCacheKey other = (ExpressionCacheKey) obj;
return (this.value.equals(other.value) && this.resultClass.equals(other.resultClass));
}
@Override
public int hashCode() {
return this.hashCode;
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2006 the original author or authors. * Copyright 2002-2009 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.
@ -26,17 +26,14 @@ import javax.servlet.jsp.el.VariableResolver;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.junit.Ignore;
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;
/** /**
* @author Aled Arendsen * @author Aled Arendsen
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 16.09.2003 * @since 16.09.2003
*/ */
@Ignore // calls to deprecated getVariableResolver() are throwing UOEs
public class ExpressionEvaluationUtilsTests extends TestCase { public class ExpressionEvaluationUtilsTests extends TestCase {
public void testIsExpressionLanguage() { public void testIsExpressionLanguage() {
@ -156,7 +153,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
assertTrue(ExpressionEvaluationUtils.evaluateBoolean("test", "true", ctx)); assertTrue(ExpressionEvaluationUtils.evaluateBoolean("test", "true", ctx));
} }
public void testEvaluateWithoutCaching() 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();
ctx.setAttribute("bla", "blie"); ctx.setAttribute("bla", "blie");
@ -175,29 +172,7 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
assertEquals(4, eval.evaluateCount); assertEquals(4, eval.evaluateCount);
} }
public void testEvaluateWithCaching() throws Exception { public void testEvaluateWithComplexConcatenation() throws Exception {
PageContext ctx = new CountingMockPageContext();
CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator();
ctx.setAttribute("bla", "blie");
ctx.setAttribute("blo", "blue");
MockServletContext sc = (MockServletContext) ctx.getServletContext();
sc.addInitParameter(ExpressionEvaluationUtils.EXPRESSION_CACHE_CONTEXT_PARAM, "true");
assertEquals("blie", ExpressionEvaluationUtils.evaluate("test", "${bla}", String.class, ctx));
assertEquals(1, eval.parseExpressionCount);
assertEquals("blue", ExpressionEvaluationUtils.evaluate("test", "${blo}", String.class, ctx));
assertEquals(2, eval.parseExpressionCount);
assertEquals("blie", ExpressionEvaluationUtils.evaluate("test", "${bla}", String.class, ctx));
assertEquals(2, eval.parseExpressionCount);
assertEquals("blue", ExpressionEvaluationUtils.evaluate("test", "${blo}", String.class, ctx));
assertEquals(2, eval.parseExpressionCount);
}
public void testEvaluateWithConcatenationWithoutCaching() throws Exception {
PageContext ctx = new CountingMockPageContext(); PageContext ctx = new CountingMockPageContext();
CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator(); CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator();
ctx.setAttribute("bla", "blie"); ctx.setAttribute("bla", "blie");
@ -224,36 +199,6 @@ public class ExpressionEvaluationUtilsTests extends TestCase {
assertEquals(8, eval.evaluateCount); assertEquals(8, eval.evaluateCount);
} }
public void testEvaluateWithConcatenationWithCaching() throws Exception {
PageContext ctx = new CountingMockPageContext();
CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator();
ctx.setAttribute("bla", "blie");
ctx.setAttribute("blo", "blue");
MockServletContext sc = (MockServletContext) ctx.getServletContext();
sc.addInitParameter(ExpressionEvaluationUtils.EXPRESSION_CACHE_CONTEXT_PARAM, "true");
String expr = "text${bla}text${blo}text";
Object o = ExpressionEvaluationUtils.evaluate("test", expr, String.class, ctx);
assertEquals("textblietextbluetext", o);
assertEquals(2, eval.parseExpressionCount);
expr = "${bla}text${blo}text";
o = ExpressionEvaluationUtils.evaluate("test", expr, String.class, ctx);
assertEquals("blietextbluetext", o);
assertEquals(2, eval.parseExpressionCount);
expr = "${bla}text${blo}";
o = ExpressionEvaluationUtils.evaluate("test", expr, String.class, ctx);
assertEquals("blietextblue", o);
assertEquals(2, eval.parseExpressionCount);
expr = "${bla}text${blo}";
o = ExpressionEvaluationUtils.evaluate("test", expr, Object.class, ctx);
assertEquals("blietextblue", o);
assertEquals(2, eval.parseExpressionCount);
}
private static class CountingMockPageContext extends MockPageContext { private static class CountingMockPageContext extends MockPageContext {