Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GRAILS-10448 - introduce our own ExpressionEvaluationUtils for now
- Loading branch information
Jeff Scott Brown
committed
Sep 16, 2013
1 parent
2cc0bc6
commit 1be0fd3
Showing
2 changed files
with
214 additions
and
13 deletions.
There are no files selected for viewing
203 changes: 203 additions & 0 deletions
203
.../src/main/groovy/org/codehaus/groovy/grails/web/taglib/jsp/ExpressionEvaluationUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
/* | ||
* Copyright 2013 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. | ||
* 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.codehaus.groovy.grails.web.taglib.jsp; | ||
|
||
import javax.servlet.ServletContext; | ||
import javax.servlet.jsp.JspException; | ||
import javax.servlet.jsp.PageContext; | ||
import javax.servlet.jsp.el.ELException; | ||
|
||
import org.spockframework.util.Assert; | ||
|
||
/** | ||
* IMPORTANT: This source code has been copied from org.springframework.web.util.ExpressionEvaluationUtils | ||
* which was removed in Spring 4. This is here as a placeholder and will likely be removed | ||
* before Grails 2.4 is released, never being included in a release. | ||
* | ||
* Convenience methods for accessing JSP 2.0's | ||
* {@link javax.servlet.jsp.el.ExpressionEvaluator}. | ||
* | ||
* <p>The evaluation methods check if the value contains "${" before | ||
* invoking the EL evaluator, treating the value as "normal" expression | ||
* (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 Alef Arendsen | ||
* @since 11.07.2003 | ||
* @see javax.servlet.jsp.el.ExpressionEvaluator#evaluate | ||
* @deprecated as of Spring 3.2, in favor of the JSP 2.0+ native support | ||
* for embedded expressions in JSP pages (also applying to tag attributes) | ||
*/ | ||
public class ExpressionEvaluationUtils { | ||
|
||
/** | ||
* Evaluate the given expression (be it EL or a literal String value) | ||
* to an Object of a given type, | ||
* @param attrName name of the attribute (typically a JSP tag attribute) | ||
* @param attrValue value of the attribute | ||
* @param resultClass class that the result should have (String, Integer, Boolean) | ||
* @param pageContext current JSP PageContext | ||
* @return the result of the evaluation | ||
* @throws JspException in case of parsing errors, also in case of type mismatch | ||
* if the passed-in literal value is not an EL expression and not assignable to | ||
* the result class | ||
*/ | ||
public static Object evaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext) | ||
throws JspException { | ||
|
||
if (ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pageContext) && ExpressionEvaluationUtils.isExpressionLanguage(attrValue)) { | ||
return ExpressionEvaluationUtils.doEvaluate(attrName, attrValue, resultClass, pageContext); | ||
} | ||
else if (attrValue != null && resultClass != null && !resultClass.isInstance(attrValue)) { | ||
throw new JspException("Attribute value \"" + attrValue + "\" is neither a JSP EL expression nor " + | ||
"assignable to result class [" + resultClass.getName() + "]"); | ||
} | ||
else { | ||
return attrValue; | ||
} | ||
} | ||
|
||
public static final String EXPRESSION_PREFIX = "${"; | ||
public static final String EXPRESSION_SUFFIX = "}"; | ||
/** | ||
* Expression support parameter at the servlet context level | ||
* (i.e. a context-param in {@code web.xml}): "springJspExpressionSupport". | ||
*/ | ||
public static final String EXPRESSION_SUPPORT_CONTEXT_PARAM = "springJspExpressionSupport"; | ||
/** | ||
* Check if the given expression value is an EL expression. | ||
* @param value the expression to check | ||
* @return {@code true} if the expression is an EL expression, | ||
* {@code false} otherwise | ||
*/ | ||
public static boolean isExpressionLanguage(String value) { | ||
return (value != null && value.contains(EXPRESSION_PREFIX)); | ||
} | ||
/** | ||
* 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} deployment descriptor. | ||
* <p>If a {@code web.xml} 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}. 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; | ||
* as of Spring 3.2, we won't activate Spring's expression support at all then since | ||
* it got deprecated and will be removed in the next iteration of the framework. | ||
* @param pageContext current JSP PageContext | ||
* @return {@code true} if active (ExpressionEvaluationUtils will actually evaluate expressions); | ||
* {@code 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); | ||
} | ||
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() < 4) { | ||
// Application declares Servlet 2.3- in its web.xml: JSP 2.0 expressions not active. | ||
// Activate our own expression support. | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
/** | ||
* Actually evaluate the given expression (be it EL or a literal String value) | ||
* to an Object of a given type. Supports concatenated expressions, | ||
* for example: "${var1}text${var2}" | ||
* @param attrName name of the attribute | ||
* @param attrValue value of the attribute | ||
* @param resultClass class that the result should have | ||
* @param pageContext current JSP PageContext | ||
* @return the result of the evaluation | ||
* @throws JspException in case of parsing errors | ||
*/ | ||
static Object doEvaluate(String attrName, String attrValue, Class resultClass, PageContext pageContext) | ||
throws JspException { | ||
|
||
Assert.notNull(attrValue, "Attribute value must not be null"); | ||
Assert.notNull(resultClass, "Result class must not be null"); | ||
Assert.notNull(pageContext, "PageContext must not be null"); | ||
|
||
try { | ||
if (resultClass.isAssignableFrom(String.class)) { | ||
StringBuilder resultValue = null; | ||
int exprPrefixIndex; | ||
int exprSuffixIndex = 0; | ||
do { | ||
exprPrefixIndex = attrValue.indexOf(EXPRESSION_PREFIX, exprSuffixIndex); | ||
if (exprPrefixIndex != -1) { | ||
int prevExprSuffixIndex = exprSuffixIndex; | ||
exprSuffixIndex = attrValue.indexOf(EXPRESSION_SUFFIX, exprPrefixIndex + EXPRESSION_PREFIX.length()); | ||
String expr; | ||
if (exprSuffixIndex != -1) { | ||
exprSuffixIndex += EXPRESSION_SUFFIX.length(); | ||
expr = attrValue.substring(exprPrefixIndex, exprSuffixIndex); | ||
} | ||
else { | ||
expr = attrValue.substring(exprPrefixIndex); | ||
} | ||
if (expr.length() == attrValue.length()) { | ||
// A single expression without static prefix or suffix -> | ||
// parse it with the specified result class rather than String. | ||
return ExpressionEvaluationUtils.evaluateExpression(attrValue, resultClass, pageContext); | ||
} | ||
else { | ||
// We actually need to concatenate partial expressions into a String. | ||
if (resultValue == null) { | ||
resultValue = new StringBuilder(); | ||
} | ||
resultValue.append(attrValue.substring(prevExprSuffixIndex, exprPrefixIndex)); | ||
resultValue.append(ExpressionEvaluationUtils.evaluateExpression(expr, String.class, pageContext)); | ||
} | ||
} | ||
else { | ||
if (resultValue == null) { | ||
resultValue = new StringBuilder(); | ||
} | ||
resultValue.append(attrValue.substring(exprSuffixIndex)); | ||
} | ||
} | ||
while (exprPrefixIndex != -1 && exprSuffixIndex != -1); | ||
return resultValue.toString(); | ||
} | ||
else { | ||
return ExpressionEvaluationUtils.evaluateExpression(attrValue, resultClass, pageContext); | ||
} | ||
} | ||
catch (ELException ex) { | ||
throw new JspException("Parsing of JSP EL expression failed for attribute '" + attrName + "'", ex); | ||
} | ||
} | ||
static Object evaluateExpression(String exprValue, Class resultClass, PageContext pageContext) | ||
throws ELException { | ||
|
||
return pageContext.getExpressionEvaluator().evaluate( | ||
exprValue, resultClass, pageContext.getVariableResolver(), null); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters