Skip to content

Commit

Permalink
GRAILS-10448 - introduce our own ExpressionEvaluationUtils for now
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff Scott Brown committed Sep 16, 2013
1 parent 2cc0bc6 commit 1be0fd3
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 13 deletions.
@@ -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);
}

}
Expand Up @@ -48,7 +48,6 @@
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.context.ApplicationContext;
//import org.springframework.web.util.ExpressionEvaluationUtils;

/**
* A tag that invokes a tag defined in a the Grails dynamic tag library. Authors of Grails tags
Expand All @@ -65,7 +64,6 @@
* @since 16-Jan-2006
*/
public class JspInvokeGrailsTagLibTag extends BodyTagSupport implements DynamicAttributes {

private static final long serialVersionUID = 4688821761801666631L;
private static final String ZERO_ARGUMENTS = "zeroArgumentsFlag";
private static final String GROOVY_DEFAULT_ARGUMENT = "it";
Expand Down Expand Up @@ -112,9 +110,9 @@ public final int doStartTag() throws JspException {
while (m.find()) {
String attributeName = m.group(1);
String attributeValue = m.group(2);
if (false /*ExpressionEvaluationUtils.isExpressionLanguage(attributeValue)*/) {
// attributeMap.put(attributeName, ExpressionEvaluationUtils.evaluate(
// attributeName, attributeValue, Object.class, pageContext));
if (ExpressionEvaluationUtils.isExpressionLanguage(attributeValue)) {
attributeMap.put(attributeName, ExpressionEvaluationUtils.evaluate(
attributeName, attributeValue, Object.class, pageContext));
}
else {
attributeMap.put(attributeName, attributeValue);
Expand All @@ -123,9 +121,9 @@ public final int doStartTag() throws JspException {
attributes.put(pd.getName(), attributeMap);
}
else {
if (false /*ExpressionEvaluationUtils.isExpressionLanguage(propertyValue)*/) {
// attributes.put(pd.getName(), ExpressionEvaluationUtils.evaluate(
// pd.getName(), propertyValue, Object.class, pageContext));
if (ExpressionEvaluationUtils.isExpressionLanguage(propertyValue)) {
attributes.put(pd.getName(), ExpressionEvaluationUtils.evaluate(
pd.getName(), propertyValue, Object.class, pageContext));
}
else {
attributes.put(pd.getName(), propertyValue);
Expand Down Expand Up @@ -339,9 +337,9 @@ public final void setDynamicAttribute(String uri, String localName, Object value
while (m.find()) {
String attributeName = m.group(1);
String attributeValue = m.group(2);
if (false /*ExpressionEvaluationUtils.isExpressionLanguage(attributeValue)*/) {
// attributeMap.put(attributeName, ExpressionEvaluationUtils.evaluate(
// attributeName, attributeValue, Object.class, pageContext));
if (ExpressionEvaluationUtils.isExpressionLanguage(attributeValue)) {
attributeMap.put(attributeName, ExpressionEvaluationUtils.evaluate(
attributeName, attributeValue, Object.class, pageContext));
}
else {
attributeMap.put(attributeName, attributeValue);
Expand All @@ -350,8 +348,8 @@ public final void setDynamicAttribute(String uri, String localName, Object value
attributes.put(localName, attributeMap);
}
else {
if (false /*ExpressionEvaluationUtils.isExpressionLanguage(stringValue)*/) {
// attributes.put(localName,ExpressionEvaluationUtils.evaluate(localName,stringValue,Object.class,pageContext));
if (ExpressionEvaluationUtils.isExpressionLanguage(stringValue)) {
attributes.put(localName,ExpressionEvaluationUtils.evaluate(localName,stringValue,Object.class,pageContext));
}
else {
attributes.put(localName,value);
Expand Down

0 comments on commit 1be0fd3

Please sign in to comment.