revised expression parser API design
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@619 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
b8b836ca43
commit
793bf07941
|
|
@ -3,9 +3,11 @@ SPRING FRAMEWORK CHANGELOG
|
||||||
http://www.springsource.org
|
http://www.springsource.org
|
||||||
|
|
||||||
|
|
||||||
Changes in version 3.0.0.M2 (2009-02-11)
|
Changes in version 3.0.0.M2 (2009-02-16)
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
|
* revised expression parser API design
|
||||||
|
* added SimpleThreadScope implementation
|
||||||
* "systemProperties" bean is not considered a default match for type Properties anymore
|
* "systemProperties" bean is not considered a default match for type Properties anymore
|
||||||
* registered plain singletons will be fully matched according to their qualifiers
|
* registered plain singletons will be fully matched according to their qualifiers
|
||||||
* all "taskExecutor" bean properties now accept any "java.util.concurrent.Executor"
|
* all "taskExecutor" bean properties now accept any "java.util.concurrent.Executor"
|
||||||
|
|
@ -28,6 +30,8 @@ Changes in version 3.0.0.M2 (2009-02-11)
|
||||||
* Spring-created EntityManagers support JPA 2.0 draft API ("unwrap", "getQueryBuilder")
|
* Spring-created EntityManagers support JPA 2.0 draft API ("unwrap", "getQueryBuilder")
|
||||||
* Spring initiates JPA 2.0 query timeout with remaining Spring transaction timeout
|
* Spring initiates JPA 2.0 query timeout with remaining Spring transaction timeout
|
||||||
* added support for WebSphere's ResourceAdapter-managed messaging transactions
|
* added support for WebSphere's ResourceAdapter-managed messaging transactions
|
||||||
|
* made SpringBeanAutowiringInterceptor callback signature compatible with WebSphere
|
||||||
|
* fixed JmsException/JmsUtils to fully avoid NPEs in case of cause messages being null
|
||||||
* introduced OXM support package (originating from Spring Web Services)
|
* introduced OXM support package (originating from Spring Web Services)
|
||||||
* introduced OXM-based MarshallingMessageConverter for JMS
|
* introduced OXM-based MarshallingMessageConverter for JMS
|
||||||
* introduced OXM-based MarshallingView for Spring MVC
|
* introduced OXM-based MarshallingView for Spring MVC
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.beans.factory.config;
|
package org.springframework.beans.factory.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context object for evaluating an expression within a bean definition.
|
* Context object for evaluating an expression within a bean definition.
|
||||||
|
|
@ -32,6 +33,7 @@ public class BeanExpressionContext {
|
||||||
|
|
||||||
|
|
||||||
public BeanExpressionContext(BeanFactory beanFactory, Scope scope) {
|
public BeanExpressionContext(BeanFactory beanFactory, Scope scope) {
|
||||||
|
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||||
this.beanFactory = beanFactory;
|
this.beanFactory = beanFactory;
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
}
|
}
|
||||||
|
|
@ -47,16 +49,37 @@ public class BeanExpressionContext {
|
||||||
|
|
||||||
public boolean containsObject(String key) {
|
public boolean containsObject(String key) {
|
||||||
return (this.beanFactory.containsBean(key) ||
|
return (this.beanFactory.containsBean(key) ||
|
||||||
this.scope.resolveContextualObject(key) != null);
|
(this.scope != null && this.scope.resolveContextualObject(key) != null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getObject(String key) {
|
public Object getObject(String key) {
|
||||||
if (this.beanFactory.containsBean(key)) {
|
if (this.beanFactory.containsBean(key)) {
|
||||||
return this.beanFactory.getBean(key);
|
return this.beanFactory.getBean(key);
|
||||||
}
|
}
|
||||||
else {
|
else if (this.scope != null){
|
||||||
return this.scope.resolveContextualObject(key);
|
return this.scope.resolveContextualObject(key);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (this == other) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(other instanceof BeanExpressionContext)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BeanExpressionContext otherContext = (BeanExpressionContext) other;
|
||||||
|
return (this.beanFactory == otherContext.beanFactory && this.scope == otherContext.scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.beanFactory.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2008 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.springframework.context.expression;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
|
||||||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract implementation of the {@link BeanExpressionResolver} interface.
|
|
||||||
* Handles the common mixing of expression parts with literal parts.
|
|
||||||
*
|
|
||||||
* <p>Subclasses need to implement the {@link #evaluateExpression} template
|
|
||||||
* method for actual expression evaluation.
|
|
||||||
*
|
|
||||||
* @author Juergen Hoeller
|
|
||||||
* @since 3.0
|
|
||||||
* @see #setExpressionPrefix
|
|
||||||
* @see #setExpressionSuffix
|
|
||||||
*/
|
|
||||||
public abstract class AbstractBeanExpressionResolver implements BeanExpressionResolver {
|
|
||||||
|
|
||||||
/** Default expression prefix: "#{" */
|
|
||||||
public static final String DEFAULT_EXPRESSION_PREFIX = "#{";
|
|
||||||
|
|
||||||
/** Default expression suffix: "}" */
|
|
||||||
public static final String DEFAULT_EXPRESSION_SUFFIX = "}";
|
|
||||||
|
|
||||||
|
|
||||||
private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
|
|
||||||
|
|
||||||
private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the prefix that an expression string starts with.
|
|
||||||
* The default is "#{".
|
|
||||||
* @see #DEFAULT_EXPRESSION_PREFIX
|
|
||||||
*/
|
|
||||||
public void setExpressionPrefix(String expressionPrefix) {
|
|
||||||
Assert.hasText(expressionPrefix, "Expression prefix must not be empty");
|
|
||||||
this.expressionPrefix = expressionPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the suffix that an expression string ends with.
|
|
||||||
* The default is "}".
|
|
||||||
* @see #DEFAULT_EXPRESSION_SUFFIX
|
|
||||||
*/
|
|
||||||
public void setExpressionSuffix(String expressionSuffix) {
|
|
||||||
Assert.hasText(expressionSuffix, "Expression suffix must not be empty");
|
|
||||||
this.expressionSuffix = expressionSuffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Object evaluate(String value, BeanExpressionContext evalContext) {
|
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Object result = "";
|
|
||||||
int prefixIndex = value.indexOf(this.expressionPrefix);
|
|
||||||
int endIndex = 0;
|
|
||||||
while (prefixIndex != -1) {
|
|
||||||
int exprStart = prefixIndex + this.expressionPrefix.length();
|
|
||||||
int suffixIndex = value.indexOf(this.expressionSuffix, exprStart);
|
|
||||||
if (suffixIndex != -1) {
|
|
||||||
if (prefixIndex > 0) {
|
|
||||||
result = result + value.substring(endIndex, prefixIndex);
|
|
||||||
}
|
|
||||||
endIndex = suffixIndex + this.expressionSuffix.length();
|
|
||||||
String expr = value.substring(exprStart, suffixIndex);
|
|
||||||
Object exprResult = evaluateExpression(expr, evalContext);
|
|
||||||
if (result != null && !"".equals(result)) {
|
|
||||||
result = result.toString() + exprResult.toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = exprResult;
|
|
||||||
}
|
|
||||||
prefixIndex = value.indexOf(this.expressionPrefix, suffixIndex);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
prefixIndex = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (endIndex < value.length()) {
|
|
||||||
return result + value.substring(endIndex);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate the given expression.
|
|
||||||
* @param exprString the expression String to evaluate
|
|
||||||
* @param evalContext the context to evaluate the expression within
|
|
||||||
* @return the evaluation result
|
|
||||||
*/
|
|
||||||
protected abstract Object evaluateExpression(String exprString, BeanExpressionContext evalContext);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -30,19 +30,19 @@ import org.springframework.expression.PropertyAccessor;
|
||||||
*/
|
*/
|
||||||
public class BeanExpressionContextAccessor implements PropertyAccessor {
|
public class BeanExpressionContextAccessor implements PropertyAccessor {
|
||||||
|
|
||||||
public boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException {
|
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return (((BeanExpressionContext) target).containsObject(name.toString()));
|
return (((BeanExpressionContext) target).containsObject(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object read(EvaluationContext context, Object target, Object name) throws AccessException {
|
public Object read(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return ((BeanExpressionContext) target).getObject(name.toString());
|
return ((BeanExpressionContext) target).getObject(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException {
|
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(EvaluationContext context, Object target, Object name, Object newValue) throws AccessException {
|
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
|
||||||
throw new AccessException("Beans in a BeanFactory are read-only");
|
throw new AccessException("Beans in a BeanFactory are read-only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -30,19 +30,19 @@ import org.springframework.expression.PropertyAccessor;
|
||||||
*/
|
*/
|
||||||
public class BeanFactoryAccessor implements PropertyAccessor {
|
public class BeanFactoryAccessor implements PropertyAccessor {
|
||||||
|
|
||||||
public boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException {
|
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return (((BeanFactory) target).containsBean(name.toString()));
|
return (((BeanFactory) target).containsBean(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object read(EvaluationContext context, Object target, Object name) throws AccessException {
|
public Object read(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return ((BeanFactory) target).getBean(name.toString());
|
return ((BeanFactory) target).getBean(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException {
|
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(EvaluationContext context, Object target, Object name, Object newValue) throws AccessException {
|
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
|
||||||
throw new AccessException("Beans in a BeanFactory are read-only");
|
throw new AccessException("Beans in a BeanFactory are read-only");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -31,19 +31,20 @@ import org.springframework.expression.PropertyAccessor;
|
||||||
*/
|
*/
|
||||||
public class MapAccessor implements PropertyAccessor {
|
public class MapAccessor implements PropertyAccessor {
|
||||||
|
|
||||||
public boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException {
|
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return (((Map) target).containsKey(name));
|
return (((Map) target).containsKey(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object read(EvaluationContext context, Object target, Object name) throws AccessException {
|
public Object read(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return ((Map) target).get(name);
|
return ((Map) target).get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException {
|
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(EvaluationContext context, Object target, Object name, Object newValue) throws AccessException {
|
@SuppressWarnings("unchecked")
|
||||||
|
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
|
||||||
((Map) target).put(name, newValue);
|
((Map) target).put(name, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,12 +16,18 @@
|
||||||
|
|
||||||
package org.springframework.context.expression;
|
package org.springframework.context.expression;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.BeanExpressionException;
|
import org.springframework.beans.factory.BeanExpressionException;
|
||||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||||
|
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.ExpressionParser;
|
import org.springframework.expression.ExpressionParser;
|
||||||
import org.springframework.expression.spel.SpelExpressionParser;
|
import org.springframework.expression.ParserContext;
|
||||||
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -32,13 +38,61 @@ import org.springframework.util.Assert;
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see org.springframework.expression.ExpressionParser
|
* @see org.springframework.expression.ExpressionParser
|
||||||
* @see org.springframework.expression.spel.SpelExpressionParser
|
* @see org.springframework.expression.spel.antlr.SpelAntlrExpressionParser
|
||||||
* @see org.springframework.expression.spel.standard.StandardEvaluationContext
|
* @see org.springframework.expression.spel.support.StandardEvaluationContext
|
||||||
*/
|
*/
|
||||||
public class StandardBeanExpressionResolver extends AbstractBeanExpressionResolver {
|
public class StandardBeanExpressionResolver implements BeanExpressionResolver {
|
||||||
|
|
||||||
private ExpressionParser expressionParser = new SpelExpressionParser();
|
/** Default expression prefix: "#{" */
|
||||||
|
public static final String DEFAULT_EXPRESSION_PREFIX = "#{";
|
||||||
|
|
||||||
|
/** Default expression suffix: "}" */
|
||||||
|
public static final String DEFAULT_EXPRESSION_SUFFIX = "}";
|
||||||
|
|
||||||
|
|
||||||
|
private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
|
||||||
|
|
||||||
|
private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
|
||||||
|
|
||||||
|
private ExpressionParser expressionParser = new SpelAntlrExpressionParser();
|
||||||
|
|
||||||
|
private final Map<String, Expression> expressionCache = new ConcurrentHashMap<String, Expression>();
|
||||||
|
|
||||||
|
private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache =
|
||||||
|
new ConcurrentHashMap<BeanExpressionContext, StandardEvaluationContext>();
|
||||||
|
|
||||||
|
private final ParserContext beanExpressionParserContext = new ParserContext() {
|
||||||
|
public boolean isTemplate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public String getExpressionPrefix() {
|
||||||
|
return expressionPrefix;
|
||||||
|
}
|
||||||
|
public String getExpressionSuffix() {
|
||||||
|
return expressionSuffix;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the prefix that an expression string starts with.
|
||||||
|
* The default is "#{".
|
||||||
|
* @see #DEFAULT_EXPRESSION_PREFIX
|
||||||
|
*/
|
||||||
|
public void setExpressionPrefix(String expressionPrefix) {
|
||||||
|
Assert.hasText(expressionPrefix, "Expression prefix must not be empty");
|
||||||
|
this.expressionPrefix = expressionPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the suffix that an expression string ends with.
|
||||||
|
* The default is "}".
|
||||||
|
* @see #DEFAULT_EXPRESSION_SUFFIX
|
||||||
|
*/
|
||||||
|
public void setExpressionSuffix(String expressionSuffix) {
|
||||||
|
Assert.hasText(expressionSuffix, "Expression suffix must not be empty");
|
||||||
|
this.expressionSuffix = expressionSuffix;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the EL parser to use for expression parsing.
|
* Specify the EL parser to use for expression parsing.
|
||||||
|
|
@ -51,14 +105,24 @@ public class StandardBeanExpressionResolver extends AbstractBeanExpressionResolv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected Object evaluateExpression(String exprString, BeanExpressionContext evalContext) {
|
public Object evaluate(String value, BeanExpressionContext evalContext) throws BeansException {
|
||||||
try {
|
try {
|
||||||
Expression expr = this.expressionParser.parseExpression(exprString);
|
Expression expr = this.expressionCache.get(value);
|
||||||
StandardEvaluationContext ec = new StandardEvaluationContext(evalContext);
|
if (expr == null) {
|
||||||
ec.addPropertyAccessor(new BeanExpressionContextAccessor());
|
expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
|
||||||
ec.addPropertyAccessor(new BeanFactoryAccessor());
|
this.expressionCache.put(value, expr);
|
||||||
ec.addPropertyAccessor(new MapAccessor());
|
}
|
||||||
return expr.getValue(ec);
|
StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
|
||||||
|
if (sec == null) {
|
||||||
|
sec = new StandardEvaluationContext();
|
||||||
|
sec.setRootObject(evalContext);
|
||||||
|
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
|
||||||
|
sec.addPropertyAccessor(new BeanFactoryAccessor());
|
||||||
|
sec.addPropertyAccessor(new MapAccessor());
|
||||||
|
customizeEvaluationContext(sec);
|
||||||
|
this.evaluationCache.put(evalContext, sec);
|
||||||
|
}
|
||||||
|
return expr.getValue(sec);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new BeanExpressionException("Expression parsing failed", ex);
|
throw new BeanExpressionException("Expression parsing failed", ex);
|
||||||
|
|
|
||||||
|
|
@ -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,7 +16,10 @@
|
||||||
|
|
||||||
package org.springframework.context.expression;
|
package org.springframework.context.expression;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.TestBean;
|
import org.springframework.beans.TestBean;
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
|
|
@ -25,16 +28,23 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.beans.factory.config.Scope;
|
import org.springframework.beans.factory.config.Scope;
|
||||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||||
import org.springframework.context.support.GenericApplicationContext;
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.util.StopWatch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class ApplicationContextExpressionTests extends TestCase {
|
public class ApplicationContextExpressionTests {
|
||||||
|
|
||||||
public void testGenericApplicationContext() {
|
private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void genericApplicationContext() {
|
||||||
GenericApplicationContext ac = new GenericApplicationContext();
|
GenericApplicationContext ac = new GenericApplicationContext();
|
||||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);
|
AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);
|
||||||
|
|
||||||
|
|
@ -76,7 +86,7 @@ public class ApplicationContextExpressionTests extends TestCase {
|
||||||
GenericBeanDefinition bd2 = new GenericBeanDefinition();
|
GenericBeanDefinition bd2 = new GenericBeanDefinition();
|
||||||
bd2.setBeanClass(TestBean.class);
|
bd2.setBeanClass(TestBean.class);
|
||||||
bd2.setScope("myScope");
|
bd2.setScope("myScope");
|
||||||
bd2.getPropertyValues().addPropertyValue("name", "XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ");
|
bd2.getPropertyValues().addPropertyValue("name", "{ XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ }");
|
||||||
bd2.getPropertyValues().addPropertyValue("age", "#{mySpecialAttr}");
|
bd2.getPropertyValues().addPropertyValue("age", "#{mySpecialAttr}");
|
||||||
bd2.getPropertyValues().addPropertyValue("country", "#{systemProperties.country}");
|
bd2.getPropertyValues().addPropertyValue("country", "#{systemProperties.country}");
|
||||||
ac.registerBeanDefinition("tb2", bd2);
|
ac.registerBeanDefinition("tb2", bd2);
|
||||||
|
|
@ -107,7 +117,7 @@ public class ApplicationContextExpressionTests extends TestCase {
|
||||||
assertEquals(42, tb1.getAge());
|
assertEquals(42, tb1.getAge());
|
||||||
|
|
||||||
TestBean tb2 = ac.getBean("tb2", TestBean.class);
|
TestBean tb2 = ac.getBean("tb2", TestBean.class);
|
||||||
assertEquals("XXXmyNameYYY42ZZZ", tb2.getName());
|
assertEquals("{ XXXmyNameYYY42ZZZ }", tb2.getName());
|
||||||
assertEquals(42, tb2.getAge());
|
assertEquals(42, tb2.getAge());
|
||||||
assertEquals("UK", tb2.getCountry());
|
assertEquals("UK", tb2.getCountry());
|
||||||
|
|
||||||
|
|
@ -134,6 +144,37 @@ public class ApplicationContextExpressionTests extends TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void prototypeCreationIsFastEnough() {
|
||||||
|
if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
|
||||||
|
// Skip this test: Trace logging blows the time limit.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GenericApplicationContext ac = new GenericApplicationContext();
|
||||||
|
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
|
||||||
|
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
|
||||||
|
rbd.getPropertyValues().addPropertyValue("name", "juergen");
|
||||||
|
rbd.getPropertyValues().addPropertyValue("country", "#{systemProperties.country}");
|
||||||
|
ac.registerBeanDefinition("test", rbd);
|
||||||
|
ac.refresh();
|
||||||
|
StopWatch sw = new StopWatch();
|
||||||
|
sw.start("prototype");
|
||||||
|
System.getProperties().put("country", "UK");
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < 100000; i++) {
|
||||||
|
TestBean tb = (TestBean) ac.getBean("test");
|
||||||
|
assertEquals("juergen", tb.getName());
|
||||||
|
assertEquals("UK", tb.getCountry());
|
||||||
|
}
|
||||||
|
sw.stop();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
System.getProperties().remove("country");
|
||||||
|
}
|
||||||
|
System.out.println(sw.getTotalTimeMillis());
|
||||||
|
assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 6000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class ValueTestBean {
|
public static class ValueTestBean {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -73,6 +73,12 @@ public abstract class ClassUtils {
|
||||||
*/
|
*/
|
||||||
private static final Map<Class, Class> primitiveWrapperTypeMap = new HashMap<Class, Class>(8);
|
private static final Map<Class, Class> primitiveWrapperTypeMap = new HashMap<Class, Class>(8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map with primitive type as key and corresponding wrapper
|
||||||
|
* type as value, for example: int.class -> Integer.class.
|
||||||
|
*/
|
||||||
|
private static final Map<Class, Class> primitiveTypeToWrapperMap = new HashMap<Class, Class>(8);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map with primitive type name as key and corresponding primitive
|
* Map with primitive type name as key and corresponding primitive
|
||||||
* type as value, for example: "int" -> "int.class".
|
* type as value, for example: "int" -> "int.class".
|
||||||
|
|
@ -90,6 +96,10 @@ public abstract class ClassUtils {
|
||||||
primitiveWrapperTypeMap.put(Long.class, long.class);
|
primitiveWrapperTypeMap.put(Long.class, long.class);
|
||||||
primitiveWrapperTypeMap.put(Short.class, short.class);
|
primitiveWrapperTypeMap.put(Short.class, short.class);
|
||||||
|
|
||||||
|
for (Map.Entry<Class, Class> entry : primitiveWrapperTypeMap.entrySet()) {
|
||||||
|
primitiveTypeToWrapperMap.put(entry.getValue(), entry.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
Set<Class> primitiveTypes = new HashSet<Class>(16);
|
Set<Class> primitiveTypes = new HashSet<Class>(16);
|
||||||
primitiveTypes.addAll(primitiveWrapperTypeMap.values());
|
primitiveTypes.addAll(primitiveWrapperTypeMap.values());
|
||||||
primitiveTypes.addAll(Arrays.asList(
|
primitiveTypes.addAll(Arrays.asList(
|
||||||
|
|
@ -701,6 +711,17 @@ public abstract class ClassUtils {
|
||||||
return (clazz.isArray() && isPrimitiveWrapper(clazz.getComponentType()));
|
return (clazz.isArray() && isPrimitiveWrapper(clazz.getComponentType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the given class if it is a primitive class,
|
||||||
|
* returning the corresponding primitive wrapper type instead.
|
||||||
|
* @param clazz the class to check
|
||||||
|
* @return the original class, or a primitive wrapper for the original primitive type
|
||||||
|
*/
|
||||||
|
public static Class resolvePrimitiveIfNecessary(Class clazz) {
|
||||||
|
Assert.notNull(clazz, "Class must not be null");
|
||||||
|
return (clazz.isPrimitive() ? primitiveTypeToWrapperMap.get(clazz) : clazz);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the right-hand side type may be assigned to the left-hand side
|
* Check if the right-hand side type may be assigned to the left-hand side
|
||||||
* type, assuming setting by reflection. Considers primitive wrapper
|
* type, assuming setting by reflection. Considers primitive wrapper
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="module" module-name="core" />
|
||||||
<orderEntry type="module-library">
|
<orderEntry type="module-library">
|
||||||
<library>
|
<library>
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,18 +13,19 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An AccessException is thrown by an accessor if it has an unexpected problem.
|
* An AccessException is thrown by an accessor if it has an unexpected problem.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class AccessException extends Exception {
|
public class AccessException extends Exception {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an AccessException with a specific message and cause.
|
* Create an AccessException with a specific message and cause.
|
||||||
*
|
|
||||||
* @param message the message
|
* @param message the message
|
||||||
* @param cause the cause
|
* @param cause the cause
|
||||||
*/
|
*/
|
||||||
|
|
@ -34,7 +35,6 @@ public class AccessException extends Exception {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an AccessException with a specific message.
|
* Create an AccessException with a specific message.
|
||||||
*
|
|
||||||
* @param message the message
|
* @param message the message
|
||||||
*/
|
*/
|
||||||
public AccessException(String message) {
|
public AccessException(String message) {
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package org.springframework.expression;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A CacheablePropertyAccessor is an optimized PropertyAccessor where the two parts of accessing the property are
|
|
||||||
* separated: (1) resolving the property and (2) retrieving its value. In some cases there is a large cost to
|
|
||||||
* discovering which property an expression refers to and once discovered it will always resolve to the same property.
|
|
||||||
* In these situations a CacheablePropertyAccessor enables the resolution to be done once and a reusable object (an
|
|
||||||
* executor) returned that can be called over and over to retrieve the property value without going through resolution
|
|
||||||
* again.
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public abstract class CacheablePropertyAccessor implements PropertyAccessor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to resolve the named property and return an executor that can be called to get the value of that
|
|
||||||
* property. Return null if the property cannot be resolved.
|
|
||||||
*
|
|
||||||
* @param context the evaluation context
|
|
||||||
* @param target the target upon which the property is being accessed
|
|
||||||
* @param name the name of the property being accessed
|
|
||||||
* @return a reusable executor that can retrieve the property value
|
|
||||||
*/
|
|
||||||
public abstract PropertyReaderExecutor getReaderAccessor(EvaluationContext context, Object target, Object name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to resolve the named property and return an executor that can be called to set the value of that
|
|
||||||
* property. Return null if the property cannot be resolved.
|
|
||||||
*
|
|
||||||
* @param context the evaluation context
|
|
||||||
* @param target the target upon which the property is being accessed
|
|
||||||
* @param name the name of the property to be set
|
|
||||||
* @return a reusable executor that can set the property value
|
|
||||||
*/
|
|
||||||
public abstract PropertyWriterExecutor getWriterAccessor(EvaluationContext context, Object target, Object name);
|
|
||||||
|
|
||||||
// Implementation of PropertyAccessor follows, based on the resolver/executor model
|
|
||||||
|
|
||||||
public final boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException {
|
|
||||||
return getReaderAccessor(context, target, name) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException {
|
|
||||||
return getWriterAccessor(context, target, name) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Object read(EvaluationContext context, Object target, Object name) throws AccessException {
|
|
||||||
return getReaderAccessor(context, target, name).execute(context, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void write(EvaluationContext context, Object target, Object name, Object newValue)
|
|
||||||
throws AccessException {
|
|
||||||
getWriterAccessor(context, target, name).execute(context, target, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
// TODO Is the resolver/executor model too pervasive in this package?
|
// TODO Is the resolver/executor model too pervasive in this package?
|
||||||
|
|
@ -26,12 +27,12 @@ package org.springframework.expression;
|
||||||
* back to the resolvers to ask for a new one.
|
* back to the resolvers to ask for a new one.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface ConstructorExecutor {
|
public interface ConstructorExecutor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a constructor in the specified context using the specified arguments.
|
* Execute a constructor in the specified context using the specified arguments.
|
||||||
*
|
|
||||||
* @param context the evaluation context in which the command is being executed
|
* @param context the evaluation context in which the command is being executed
|
||||||
* @param arguments the arguments to the constructor call, should match (in terms of number and type) whatever the
|
* @param arguments the arguments to the constructor call, should match (in terms of number and type) whatever the
|
||||||
* command will need to run
|
* command will need to run
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,6 +21,7 @@ package org.springframework.expression;
|
||||||
* that constructor. The ConstructorExecutor will be cached but if it 'goes stale' the resolvers will be called again.
|
* that constructor. The ConstructorExecutor will be cached but if it 'goes stale' the resolvers will be called again.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface ConstructorResolver {
|
public interface ConstructorResolver {
|
||||||
|
|
||||||
|
|
@ -27,13 +29,12 @@ public interface ConstructorResolver {
|
||||||
* Within the supplied context determine a suitable constructor on the supplied type that can handle the specified
|
* Within the supplied context determine a suitable constructor on the supplied type that can handle the specified
|
||||||
* arguments. Return a ConstructorExecutor that can be used to invoke that constructor (or null if no constructor
|
* arguments. Return a ConstructorExecutor that can be used to invoke that constructor (or null if no constructor
|
||||||
* could be found).
|
* could be found).
|
||||||
*
|
|
||||||
* @param context the current evaluation context
|
* @param context the current evaluation context
|
||||||
* @param typename the type upon which to look for the constructor
|
* @param typeName the type upon which to look for the constructor
|
||||||
* @param argumentTypes the arguments that the constructor must be able to handle
|
* @param argumentTypes the arguments that the constructor must be able to handle
|
||||||
* @return a ConstructorExecutor that can invoke the constructor, or null if non found
|
* @return a ConstructorExecutor that can invoke the constructor, or null if non found
|
||||||
*/
|
*/
|
||||||
ConstructorExecutor resolve(EvaluationContext context, String typename, Class<?>[] argumentTypes)
|
ConstructorExecutor resolve(EvaluationContext context, String typeName, Class<?>[] argumentTypes)
|
||||||
throws AccessException;
|
throws AccessException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,61 +13,53 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
|
||||||
import org.springframework.expression.spel.standard.StandardTypeUtilities;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expressions are executed in an evaluation context. It is in this context that references are resolved when
|
* Expressions are executed in an evaluation context. It is in this context that references
|
||||||
* encountered during expression evaluation.
|
* are resolved when encountered during expression evaluation.
|
||||||
*
|
*
|
||||||
* There is a default implementation of the EvaluationContext, {@link StandardEvaluationContext} that can be extended,
|
* There is a default implementation of the EvaluationContext,
|
||||||
* rather than having to implement everything.
|
* {@link org.springframework.expression.spel.support.StandardEvaluationContext}
|
||||||
|
* that can be extended, rather than having to implement everything.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface EvaluationContext {
|
public interface EvaluationContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the root context object against which unqualified properties/methods/etc should be resolved
|
* @return the root context object against which unqualified properties/methods/etc should be resolved
|
||||||
*/
|
*/
|
||||||
Object getRootContextObject();
|
Object getRootObject();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a TypeUtilities implementation that can be used for looking up types, converting types, comparing types,
|
|
||||||
* and overloading basic operators for types. A standard implementation is provided in {@link StandardTypeUtilities}
|
|
||||||
*/
|
|
||||||
TypeUtils getTypeUtils();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Look up a named variable within this execution context.
|
|
||||||
*
|
|
||||||
* @param name variable to lookup
|
|
||||||
* @return the value of the variable
|
|
||||||
*/
|
|
||||||
Object lookupVariable(String name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a named variable within this execution context to a specified value.
|
* Set a named variable within this execution context to a specified value.
|
||||||
*
|
|
||||||
* @param name variable to set
|
* @param name variable to set
|
||||||
* @param value value to be placed in the variable
|
* @param value value to be placed in the variable
|
||||||
*/
|
*/
|
||||||
void setVariable(String name, Object value);
|
void setVariable(String name, Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a named variable within this execution context.
|
||||||
|
* @param name variable to lookup
|
||||||
|
* @return the value of the variable
|
||||||
|
*/
|
||||||
|
Object lookupVariable(String name);
|
||||||
|
|
||||||
// TODO lookupReference() - is it too expensive to return all objects within a context?
|
// TODO lookupReference() - is it too expensive to return all objects within a context?
|
||||||
/**
|
/**
|
||||||
* Look up an object reference in a particular context. If no contextName is specified (null), assume the default
|
* Look up an object reference in a particular context. If no contextName is specified (null), assume the default
|
||||||
* context. If no objectName is specified (null), return all objects in the specified context (List<Object>).
|
* context. If no objectName is specified (null), return all objects in the specified context (List).
|
||||||
*
|
* @param contextName the context in which to perform the lookup (or <code>null</code> for default context)
|
||||||
* @param contextName the context in which to perform the lookup (or null for default context)
|
* @param objectName the object to lookup in the context (or <code>null</code> to get all objects)
|
||||||
* @param objectName the object to lookup in the context (or null to get all objects)
|
* @return a specific object or List
|
||||||
* @return a specific object or List<Object>
|
|
||||||
*/
|
*/
|
||||||
Object lookupReference(Object contextName, Object objectName) throws EvaluationException;
|
Object lookupReference(Object contextName, String objectName) throws EvaluationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a list of resolvers that will be asked in turn to locate a constructor
|
* @return a list of resolvers that will be asked in turn to locate a constructor
|
||||||
|
|
@ -84,4 +76,25 @@ public interface EvaluationContext {
|
||||||
*/
|
*/
|
||||||
List<PropertyAccessor> getPropertyAccessors();
|
List<PropertyAccessor> getPropertyAccessors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a type locator that can be used to find types, either by short or fully qualified name.
|
||||||
|
*/
|
||||||
|
TypeLocator getTypeLocator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a type comparator for comparing pairs of objects for equality.
|
||||||
|
*/
|
||||||
|
TypeComparator getTypeComparator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a type converter that can convert (or coerce) a value from one type to another.
|
||||||
|
*/
|
||||||
|
TypeConverter getTypeConverter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return an operator overloader that may support mathematical operations between more than the standard set of
|
||||||
|
* types
|
||||||
|
*/
|
||||||
|
OperatorOverloader getOperatorOverloader();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,34 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for exceptions occurring during expression parsing and evaluation.
|
* Base class for exceptions occurring during expression parsing and evaluation.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class EvaluationException extends Exception {
|
public class EvaluationException extends Exception {
|
||||||
|
|
||||||
/**
|
|
||||||
* The expression string.
|
|
||||||
*/
|
|
||||||
private String expressionString;
|
private String expressionString;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
* Creates a new expression exception.
|
||||||
* setExpressionString().
|
|
||||||
*
|
|
||||||
* @param cause the underlying cause of this exception
|
* @param cause the underlying cause of this exception
|
||||||
*/
|
*/
|
||||||
public EvaluationException(Throwable cause) {
|
public EvaluationException(Throwable cause) {
|
||||||
|
|
@ -39,7 +37,6 @@ public class EvaluationException extends Exception {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new expression parsing exception.
|
* Creates a new expression parsing exception.
|
||||||
*
|
|
||||||
* @param expressionString the expression string that could not be parsed
|
* @param expressionString the expression string that could not be parsed
|
||||||
* @param cause the underlying cause of this exception
|
* @param cause the underlying cause of this exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -49,7 +46,6 @@ public class EvaluationException extends Exception {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new expression exception.
|
* Creates a new expression exception.
|
||||||
*
|
|
||||||
* @param expressionString the expression string
|
* @param expressionString the expression string
|
||||||
* @param message a descriptive message
|
* @param message a descriptive message
|
||||||
* @param cause the underlying cause of this exception
|
* @param cause the underlying cause of this exception
|
||||||
|
|
@ -61,7 +57,6 @@ public class EvaluationException extends Exception {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new expression exception.
|
* Creates a new expression exception.
|
||||||
*
|
|
||||||
* @param expressionString the expression string
|
* @param expressionString the expression string
|
||||||
* @param message a descriptive message
|
* @param message a descriptive message
|
||||||
*/
|
*/
|
||||||
|
|
@ -73,27 +68,15 @@ public class EvaluationException extends Exception {
|
||||||
/**
|
/**
|
||||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
* Creates a new expression exception. The expressionString field should be set by a later call to
|
||||||
* setExpressionString().
|
* setExpressionString().
|
||||||
*
|
|
||||||
* @param message a descriptive message
|
* @param message a descriptive message
|
||||||
*/
|
*/
|
||||||
public EvaluationException(String message) {
|
public EvaluationException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the expression string, called on exceptions where the expressionString is not known at the time of exception
|
public final String getExpressionString() {
|
||||||
* creation.
|
return this.expressionString;
|
||||||
*
|
|
||||||
* @param expressionString the expression string
|
|
||||||
*/
|
|
||||||
protected final void setExpressionString(String expressionString) {
|
|
||||||
this.expressionString = expressionString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the expression string
|
|
||||||
*/
|
|
||||||
public final String getExpressionString() {
|
|
||||||
return expressionString;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -22,6 +23,7 @@ package org.springframework.expression;
|
||||||
*
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface Expression {
|
public interface Expression {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,56 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses expression strings into compiled expressions that can be evaluated. Supports parsing templates as well as
|
* Parses expression strings into compiled expressions that can be evaluated.
|
||||||
* standard expression strings.
|
* Supports parsing templates as well as standard expression strings.
|
||||||
*
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface ExpressionParser {
|
public interface ExpressionParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the expression string and return an Expression object you can use for repeated evaluation. Some examples:
|
* Parse the expression string and return an Expression object you can use for repeated evaluation.
|
||||||
*
|
* <p>Some examples:
|
||||||
|
* <pre>
|
||||||
|
* 3 + 4
|
||||||
|
* name.firstName
|
||||||
|
* </pre>
|
||||||
|
* @param expressionString the raw expression string to parse
|
||||||
|
* @return an evaluator for the parsed expression
|
||||||
|
* @throws ParseException an exception occurred during parsing
|
||||||
|
*/
|
||||||
|
Expression parseExpression(String expressionString) throws ParseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the expression string and return an Expression object you can use for repeated evaluation.
|
||||||
|
* <p>Some examples:
|
||||||
* <pre>
|
* <pre>
|
||||||
* 3 + 4
|
* 3 + 4
|
||||||
* name.firstName
|
* name.firstName
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
|
||||||
* @param expressionString the raw expression string to parse
|
* @param expressionString the raw expression string to parse
|
||||||
* @param context a context for influencing this expression parsing routine (optional)
|
* @param context a context for influencing this expression parsing routine (optional)
|
||||||
* @return an evaluator for the parsed expression
|
* @return an evaluator for the parsed expression
|
||||||
* @throws ParseException an exception occurred during parsing
|
* @throws ParseException an exception occurred during parsing
|
||||||
*/
|
*/
|
||||||
public Expression parseExpression(String expressionString, ParserContext context) throws ParseException;
|
Expression parseExpression(String expressionString, ParserContext context) throws ParseException;
|
||||||
|
|
||||||
/**
|
}
|
||||||
* Parse the expression string and return an Expression object you can use for repeated evaluation. Some examples:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* 3 + 4
|
|
||||||
* name.firstName
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param expressionString the raw expression string to parse
|
|
||||||
* @return an evaluator for the parsed expression
|
|
||||||
* @throws ParseException an exception occurred during parsing
|
|
||||||
*/
|
|
||||||
public Expression parseExpression(String expressionString) throws ParseException;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,24 +21,24 @@ package org.springframework.expression;
|
||||||
* without going back to the resolvers. For example, the particular method to run on an object may be discovered by the
|
* without going back to the resolvers. For example, the particular method to run on an object may be discovered by the
|
||||||
* reflection method resolver - it will then build a MethodExecutor that executes that method and the MethodExecutor can
|
* reflection method resolver - it will then build a MethodExecutor that executes that method and the MethodExecutor can
|
||||||
* be reused without needing to go back to the resolver to discover the method again.
|
* be reused without needing to go back to the resolver to discover the method again.
|
||||||
* <p>
|
*
|
||||||
* They can become stale, and in that case should throw an AccessException - this will cause the infrastructure to go
|
* <p>They can become stale, and in that case should throw an AccessException - this will cause the infrastructure to go
|
||||||
* back to the resolvers to ask for a new one.
|
* back to the resolvers to ask for a new one.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface MethodExecutor {
|
public interface MethodExecutor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a command using the specified arguments, and using the specified expression state.
|
* Execute a command using the specified arguments, and using the specified expression state.
|
||||||
*
|
|
||||||
* @param context the evaluation context in which the command is being executed
|
* @param context the evaluation context in which the command is being executed
|
||||||
* @param target the target object of the call - null for static methods
|
* @param target the target object of the call - null for static methods
|
||||||
* @param methodArguments the arguments to the executor, should match (in terms of number and type) whatever the
|
* @param arguments the arguments to the executor, should match (in terms of number and type) whatever the
|
||||||
* command will need to run
|
* command will need to run
|
||||||
* @return the value returned from execution
|
* @return the value returned from execution
|
||||||
* @throws AccessException if there is a problem executing the command or the MethodExecutor is no longer valid
|
* @throws AccessException if there is a problem executing the command or the MethodExecutor is no longer valid
|
||||||
*/
|
*/
|
||||||
Object execute(EvaluationContext context, Object target, Object... methodArguments) throws AccessException;
|
Object execute(EvaluationContext context, Object target, Object... arguments) throws AccessException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,6 +21,7 @@ package org.springframework.expression;
|
||||||
* command executor will be cached but if it 'goes stale' the resolvers will be called again.
|
* command executor will be cached but if it 'goes stale' the resolvers will be called again.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface MethodResolver {
|
public interface MethodResolver {
|
||||||
|
|
||||||
|
|
@ -27,7 +29,6 @@ public interface MethodResolver {
|
||||||
* Within the supplied context determine a suitable method on the supplied object that can handle the specified
|
* Within the supplied context determine a suitable method on the supplied object that can handle the specified
|
||||||
* arguments. Return a MethodExecutor that can be used to invoke that method (or null if no method
|
* arguments. Return a MethodExecutor that can be used to invoke that method (or null if no method
|
||||||
* could be found).
|
* could be found).
|
||||||
*
|
|
||||||
* @param context the current evaluation context
|
* @param context the current evaluation context
|
||||||
* @param targetObject the object upon which the method is being called
|
* @param targetObject the object upon which the method is being called
|
||||||
* @param argumentTypes the arguments that the constructor must be able to handle
|
* @param argumentTypes the arguments that the constructor must be able to handle
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,14 +13,17 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.expression;
|
|
||||||
|
|
||||||
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported operations that an {@link OperatorOverloader} can implement for any pair of operands.
|
* Supported operations that an {@link OperatorOverloader} can implement for any pair of operands.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public enum Operation {
|
public enum Operation {
|
||||||
ADD, SUBTRACT, DIVIDE, MULTIPLY, MODULUS;
|
|
||||||
|
ADD, SUBTRACT, DIVIDE, MULTIPLY, MODULUS
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -5,6 +21,7 @@ package org.springframework.expression;
|
||||||
* implementation of OperatorOverloader, a user of the expression language can support these operations on other types.
|
* implementation of OperatorOverloader, a user of the expression language can support these operations on other types.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface OperatorOverloader {
|
public interface OperatorOverloader {
|
||||||
|
|
||||||
|
|
@ -12,26 +29,27 @@ public interface OperatorOverloader {
|
||||||
// TODO Operator overloading needs some testing!
|
// TODO Operator overloading needs some testing!
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the operator overloader supports the specified operation between the two operands and so should be
|
* Return true if the operator overloader supports the specified operation
|
||||||
* invoked to handle it.
|
* between the two operands and so should be invoked to handle it.
|
||||||
*
|
|
||||||
* @param operation the operation to be performed
|
* @param operation the operation to be performed
|
||||||
* @param leftOperand the left operand
|
* @param leftOperand the left operand
|
||||||
* @param rightOperand the right operand
|
* @param rightOperand the right operand
|
||||||
* @return true if the OperatorOverloader supports the specified operation between the two operands
|
* @return true if the OperatorOverloader supports the specified operation between the two operands
|
||||||
* @throws EvaluationException if there is a problem performing the operation
|
* @throws EvaluationException if there is a problem performing the operation
|
||||||
*/
|
*/
|
||||||
boolean overridesOperation(Operation operation, Object leftOperand, Object rightOperand) throws EvaluationException;
|
boolean overridesOperation(Operation operation, Object leftOperand, Object rightOperand)
|
||||||
|
throws EvaluationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the specified operation on two operands, returning a result. See {@link Operation} for supported
|
* Execute the specified operation on two operands, returning a result.
|
||||||
* operations.
|
* See {@link Operation} for supported operations.
|
||||||
*
|
|
||||||
* @param operation the operation to be performed
|
* @param operation the operation to be performed
|
||||||
* @param leftOperand the left operand
|
* @param leftOperand the left operand
|
||||||
* @param rightOperand the right operand
|
* @param rightOperand the right operand
|
||||||
* @return the result of performing the operation on the two operands
|
* @return the result of performing the operation on the two operands
|
||||||
* @throws EvaluationException if there is a problem performing the operation
|
* @throws EvaluationException if there is a problem performing the operation
|
||||||
*/
|
*/
|
||||||
Object operate(Operation operation, Object leftOperand, Object rightOperand) throws EvaluationException;
|
Object operate(Operation operation, Object leftOperand, Object rightOperand)
|
||||||
|
throws EvaluationException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,34 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for exceptions occurring during expression parsing and evaluation.
|
* Base class for exceptions occurring during expression parsing and evaluation.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class ParseException extends Exception {
|
public class ParseException extends Exception {
|
||||||
|
|
||||||
/**
|
|
||||||
* The expression string.
|
|
||||||
*/
|
|
||||||
private String expressionString;
|
private String expressionString;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new expression exception. The expressionString field should be set by a later call to
|
* Creates a new expression exception.
|
||||||
* setExpressionString().
|
|
||||||
*
|
|
||||||
* @param cause the underlying cause of this exception
|
* @param cause the underlying cause of this exception
|
||||||
*/
|
*/
|
||||||
public ParseException(Throwable cause) {
|
public ParseException(Throwable cause) {
|
||||||
|
|
@ -39,7 +37,6 @@ public class ParseException extends Exception {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new expression parsing exception.
|
* Creates a new expression parsing exception.
|
||||||
*
|
|
||||||
* @param expressionString the expression string that could not be parsed
|
* @param expressionString the expression string that could not be parsed
|
||||||
* @param cause the underlying cause of this exception
|
* @param cause the underlying cause of this exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -49,7 +46,6 @@ public class ParseException extends Exception {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new expression exception.
|
* Creates a new expression exception.
|
||||||
*
|
|
||||||
* @param expressionString the expression string
|
* @param expressionString the expression string
|
||||||
* @param message a descriptive message
|
* @param message a descriptive message
|
||||||
* @param cause the underlying cause of this exception
|
* @param cause the underlying cause of this exception
|
||||||
|
|
@ -61,7 +57,6 @@ public class ParseException extends Exception {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new expression exception.
|
* Creates a new expression exception.
|
||||||
*
|
|
||||||
* @param expressionString the expression string
|
* @param expressionString the expression string
|
||||||
* @param message a descriptive message
|
* @param message a descriptive message
|
||||||
*/
|
*/
|
||||||
|
|
@ -70,20 +65,9 @@ public class ParseException extends Exception {
|
||||||
this.expressionString = expressionString;
|
this.expressionString = expressionString;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the expression string, called on exceptions where the expressionString is not known at the time of exception
|
public final String getExpressionString() {
|
||||||
* creation.
|
return this.expressionString;
|
||||||
*
|
|
||||||
* @param expressionString the expression string
|
|
||||||
*/
|
|
||||||
protected final void setExpressionString(String expressionString) {
|
|
||||||
this.expressionString = expressionString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
}
|
||||||
* @return the expression string
|
|
||||||
*/
|
|
||||||
public final String getExpressionString() {
|
|
||||||
return expressionString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-2008 the original author or authors.
|
* Copyright 2004-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.
|
||||||
|
|
@ -13,13 +13,15 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input provided to an expression parser that can influence an expression parsing/compilation routine.
|
* Input provided to an expression parser that can influence an expression parsing/compilation routine.
|
||||||
*
|
*
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface ParserContext {
|
public interface ParserContext {
|
||||||
|
|
||||||
|
|
@ -35,21 +37,22 @@ public interface ParserContext {
|
||||||
*
|
*
|
||||||
* @return true if the expression is a template, false otherwise
|
* @return true if the expression is a template, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean isTemplate();
|
boolean isTemplate();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For template expressions, returns the prefix that identifies the start of an expression block within a string.
|
* For template expressions, returns the prefix that identifies the start of an expression block within a string.
|
||||||
* For example "${"
|
* For example: "${"
|
||||||
*
|
*
|
||||||
* @return the prefix that identifies the start of an expression
|
* @return the prefix that identifies the start of an expression
|
||||||
*/
|
*/
|
||||||
public String getExpressionPrefix();
|
String getExpressionPrefix();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For template expressions, return the prefix that identifies the end of an expression block within a string. For
|
* For template expressions, return the prefix that identifies the end of an expression block within a string.
|
||||||
* example "}$"
|
* For example: "}"
|
||||||
*
|
*
|
||||||
* @return the suffix that identifies the end of an expression
|
* @return the suffix that identifies the end of an expression
|
||||||
*/
|
*/
|
||||||
public String getExpressionSuffix();
|
String getExpressionSuffix();
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,66 +24,62 @@ package org.springframework.expression;
|
||||||
* to determine if it can read or write them. Property resolvers are considered to be ordered and each will be called in
|
* to determine if it can read or write them. Property resolvers are considered to be ordered and each will be called in
|
||||||
* turn. The only rule that affects the call order is that any naming the target class directly in
|
* turn. The only rule that affects the call order is that any naming the target class directly in
|
||||||
* getSpecifiedTargetClasses() will be called first, before the general resolvers.
|
* getSpecifiedTargetClasses() will be called first, before the general resolvers.
|
||||||
* <p>
|
*
|
||||||
* If the cost of locating the property is expensive, in relation to actually retrieving its value, consider extending
|
* <p>If the cost of locating the property is expensive, in relation to actually retrieving its value, consider extending
|
||||||
* CacheablePropertyAccessor rather than directly implementing PropertyAccessor. A CacheablePropertyAccessor enables the
|
* CacheablePropertyAccessor rather than directly implementing PropertyAccessor. A CacheablePropertyAccessor enables the
|
||||||
* discovery (resolution) of the property to be done once and then an object (an executor) returned and cached by the
|
* discovery (resolution) of the property to be done once and then an object (an executor) returned and cached by the
|
||||||
* infrastructure that can be used repeatedly to retrieve the property value.
|
* infrastructure that can be used repeatedly to retrieve the property value.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface PropertyAccessor {
|
public interface PropertyAccessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of classes for which this resolver should be called. Returning null indicates this is a general
|
* Return an array of classes for which this resolver should be called. Returning null indicates this is a general
|
||||||
* resolver that can be called in an attempt to resolve a property on any type.
|
* resolver that can be called in an attempt to resolve a property on any type.
|
||||||
*
|
|
||||||
* @return an array of classes that this resolver is suitable for (or null if a general resolver)
|
* @return an array of classes that this resolver is suitable for (or null if a general resolver)
|
||||||
*/
|
*/
|
||||||
public Class[] getSpecificTargetClasses();
|
Class[] getSpecificTargetClasses();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to determine if a resolver instance is able to access a specified property on a specified target object.
|
* Called to determine if a resolver instance is able to access a specified property on a specified target object.
|
||||||
*
|
|
||||||
* @param context the evaluation context in which the access is being attempted
|
* @param context the evaluation context in which the access is being attempted
|
||||||
* @param target the target object upon which the property is being accessed
|
* @param target the target object upon which the property is being accessed
|
||||||
* @param name the name of the property being accessed
|
* @param name the name of the property being accessed
|
||||||
* @return true if this resolver is able to read the property
|
* @return true if this resolver is able to read the property
|
||||||
* @throws AccessException if there is any problem determining whether the property can be read
|
* @throws AccessException if there is any problem determining whether the property can be read
|
||||||
*/
|
*/
|
||||||
public boolean canRead(EvaluationContext context, Object target, Object name) throws AccessException;
|
boolean canRead(EvaluationContext context, Object target, String name) throws AccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to read a property from a specified target object
|
* Called to read a property from a specified target object
|
||||||
*
|
|
||||||
* @param context the evaluation context in which the access is being attempted
|
* @param context the evaluation context in which the access is being attempted
|
||||||
* @param target the target object upon which the property is being accessed
|
* @param target the target object upon which the property is being accessed
|
||||||
* @param name the name of the property being accessed
|
* @param name the name of the property being accessed
|
||||||
* @return Object the value of the property
|
* @return Object the value of the property
|
||||||
* @throws AccessException if there is any problem accessing the property value
|
* @throws AccessException if there is any problem accessing the property value
|
||||||
*/
|
*/
|
||||||
public Object read(EvaluationContext context, Object target, Object name) throws AccessException;
|
Object read(EvaluationContext context, Object target, String name) throws AccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to determine if a resolver instance is able to write to a specified property on a specified target object.
|
* Called to determine if a resolver instance is able to write to a specified property on a specified target object.
|
||||||
*
|
|
||||||
* @param context the evaluation context in which the access is being attempted
|
* @param context the evaluation context in which the access is being attempted
|
||||||
* @param target the target object upon which the property is being accessed
|
* @param target the target object upon which the property is being accessed
|
||||||
* @param name the name of the property being accessed
|
* @param name the name of the property being accessed
|
||||||
* @return true if this resolver is able to write to the property
|
* @return true if this resolver is able to write to the property
|
||||||
* @throws AccessException if there is any problem determining whether the property can be written to
|
* @throws AccessException if there is any problem determining whether the property can be written to
|
||||||
*/
|
*/
|
||||||
public boolean canWrite(EvaluationContext context, Object target, Object name) throws AccessException;
|
boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to write to a property on a specified target object. Should only succeed if canWrite() also returns true.
|
* Called to write to a property on a specified target object. Should only succeed if canWrite() also returns true.
|
||||||
*
|
|
||||||
* @param context the evaluation context in which the access is being attempted
|
* @param context the evaluation context in which the access is being attempted
|
||||||
* @param target the target object upon which the property is being accessed
|
* @param target the target object upon which the property is being accessed
|
||||||
* @param name the name of the property being accessed
|
* @param name the name of the property being accessed
|
||||||
* @param newValue the new value for the property
|
* @param newValue the new value for the property
|
||||||
* @throws AccessException if there is any problem writing to the property value
|
* @throws AccessException if there is any problem writing to the property value
|
||||||
*/
|
*/
|
||||||
public void write(EvaluationContext context, Object target, Object name, Object newValue) throws AccessException;
|
void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a property accessor is built upon the CacheablePropertyAccessor class then once the property
|
|
||||||
* has been resolved the accessor will return an instance of this PropertyReaderExecutor interface
|
|
||||||
* that can be cached and repeatedly called to access the value of the property.
|
|
||||||
* <p>
|
|
||||||
* They can become stale, and in that case should throw an AccessException - this will cause the
|
|
||||||
* infrastructure to go back to the resolvers to ask for a new one.
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public interface PropertyReaderExecutor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value of a property for the specified target.
|
|
||||||
*
|
|
||||||
* @param context the evaluation context in which the command is being executed
|
|
||||||
* @param targetObject the target object on which property access is being attempted
|
|
||||||
* @return the property value
|
|
||||||
* @throws AccessException if there is a problem accessing the property or this executor has become stale
|
|
||||||
*/
|
|
||||||
Object execute(EvaluationContext context, Object targetObject) throws AccessException;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a property accessor is built upon the CacheablePropertyAccessor class then once the property
|
|
||||||
* has been resolved the accessor will return an instance of this PropertyWriterExecutor interface
|
|
||||||
* that can be cached and repeatedly called to set the value of the property.
|
|
||||||
*
|
|
||||||
* <p>They can become stale, and in that case should throw an AccessException - this will cause the
|
|
||||||
* infrastructure to go back to the resolvers to ask for a new one.
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public interface PropertyWriterExecutor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value of a property to the supplied new value.
|
|
||||||
* @param context the evaluation context in which the command is being executed
|
|
||||||
* @param targetObject the target object on which property write is being attempted
|
|
||||||
* @param newValue the new value for the property
|
|
||||||
* @throws AccessException if there is a problem setting the property or this executor has become stale
|
|
||||||
*/
|
|
||||||
void execute(EvaluationContext context, Object targetObject, Object newValue) throws AccessException;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,12 +21,12 @@ package org.springframework.expression;
|
||||||
* return value is the same as for {@link Comparable}.
|
* return value is the same as for {@link Comparable}.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface TypeComparator {
|
public interface TypeComparator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare two objects.
|
* Compare two objects.
|
||||||
*
|
|
||||||
* @param firstObject the first object
|
* @param firstObject the first object
|
||||||
* @param secondObject the second object
|
* @param secondObject the second object
|
||||||
* @return 0 if they are equal, <0 if the first is smaller than the second, or >0 if the first is larger than the
|
* @return 0 if they are equal, <0 if the first is smaller than the second, or >0 if the first is larger than the
|
||||||
|
|
@ -36,11 +37,10 @@ public interface TypeComparator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the comparator can compare these two objects
|
* Return true if the comparator can compare these two objects
|
||||||
*
|
|
||||||
* @param firstObject the first object
|
* @param firstObject the first object
|
||||||
* @param secondObject the second object
|
* @param secondObject the second object
|
||||||
* @return true if the comparator can compare these objects
|
* @return true if the comparator can compare these objects
|
||||||
*/
|
*/
|
||||||
public boolean canCompare(Object firstObject, Object secondObject);
|
boolean canCompare(Object firstObject, Object secondObject);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,18 +13,15 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
import org.springframework.expression.spel.standard.StandardIndividualTypeConverter;
|
|
||||||
import org.springframework.expression.spel.standard.StandardTypeConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type converter can convert values between different types. There is a default implementation called
|
* A type converter can convert values between different types encountered
|
||||||
* {@link StandardTypeConverter} that supports some basic conversions. That default implementation can be extended
|
* during expression evaluation.
|
||||||
* through subclassing or via registration of new {@link StandardIndividualTypeConverter} instances with the
|
*
|
||||||
* StandardTypeConverter.
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface TypeConverter {
|
public interface TypeConverter {
|
||||||
// TODO replace this stuff with Keiths spring-binding conversion code
|
// TODO replace this stuff with Keiths spring-binding conversion code
|
||||||
|
|
@ -32,21 +29,19 @@ public interface TypeConverter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert (may coerce) a value from one type to another, for example from a boolean to a string.
|
* Convert (may coerce) a value from one type to another, for example from a boolean to a string.
|
||||||
*
|
|
||||||
* @param value the value to be converted
|
* @param value the value to be converted
|
||||||
* @param targetType the type that the value should be converted to if possible
|
* @param targetType the type that the value should be converted to if possible
|
||||||
* @return the converted value
|
* @return the converted value
|
||||||
* @throws EvaluationException if conversion is not possible
|
* @throws EvaluationException if conversion is not possible
|
||||||
*/
|
*/
|
||||||
Object convertValue(Object value, Class<?> targetType) throws EvaluationException;
|
<T> T convertValue(Object value, Class<T> targetType) throws EvaluationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the type converter can convert the specified type to the desired target type.
|
* Return true if the type converter can convert the specified type to the desired target type.
|
||||||
*
|
|
||||||
* @param sourceType the type to be converted from
|
* @param sourceType the type to be converted from
|
||||||
* @param targetType the type to be converted to
|
* @param targetType the type to be converted to
|
||||||
* @return true if that conversion can be performed
|
* @return true if that conversion can be performed
|
||||||
*/
|
*/
|
||||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType);
|
boolean canConvert(Class<?> sourceType, Class<?> targetType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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,13 @@
|
||||||
|
|
||||||
package org.springframework.expression;
|
package org.springframework.expression;
|
||||||
|
|
||||||
import org.springframework.expression.spel.standard.StandardTypeLocator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementors of this interface are expected to be able to locate types. They may use custom classloaders or the
|
* Implementors of this interface are expected to be able to locate types. They may use custom classloaders
|
||||||
* and deal with common package prefixes (java.lang, etc) however they wish. See
|
* or the and deal with common package prefixes (java.lang, etc) however they wish. See
|
||||||
* {@link StandardTypeLocator} for an example implementation.
|
* {@link org.springframework.expression.spel.support.StandardTypeLocator} for an example implementation.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface TypeLocator {
|
public interface TypeLocator {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TypeUtilities brings together the various kinds of type related function that may occur
|
|
||||||
* whilst working with expressions. An implementor is providing support for four type related
|
|
||||||
* facilities:
|
|
||||||
* <ul>
|
|
||||||
* <li>a mechanism for finding types
|
|
||||||
* <li>a mechanism for comparing types
|
|
||||||
* <li>a mechanism for type conversion/coercion
|
|
||||||
* <li>a mechanism for overloading mathematical operations (add/subtract/etc)
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public interface TypeUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a type locator that can be used to find types, either by short or fully qualified name.
|
|
||||||
*/
|
|
||||||
TypeLocator getTypeLocator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a type comparator for comparing pairs of objects for equality.
|
|
||||||
*/
|
|
||||||
TypeComparator getTypeComparator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a type converter that can convert (or coerce) a value from one type to another.
|
|
||||||
*/
|
|
||||||
TypeConverter getTypeConverter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return an operator overloader that may support mathematical operations between more than the standard set of
|
|
||||||
* types
|
|
||||||
*/
|
|
||||||
OperatorOverloader getOperatorOverloader();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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.springframework.expression.common;
|
package org.springframework.expression.common;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a template expression broken into pieces. Each piece will be an Expression but pure text parts to the
|
* Represents a template expression broken into pieces. Each piece will be an Expression but pure text parts to the
|
||||||
* template will be represented as LiteralExpression objects. An example of a template expression might be: <code><pre>
|
* template will be represented as LiteralExpression objects. An example of a template expression might be:
|
||||||
* "Hello ${getName()}"
|
*
|
||||||
* </pre></code> which will be represented as a CompositeStringExpression of two parts. The first part being a
|
* <pre class="code">
|
||||||
* LiteralExpression representing 'Hello ' and the second part being a real expression that will call getName() when
|
* "Hello ${getName()}"</pre>
|
||||||
* invoked.
|
*
|
||||||
|
* which will be represented as a CompositeStringExpression of two parts. The first part being a
|
||||||
|
* LiteralExpression representing 'Hello ' and the second part being a real expression that will
|
||||||
|
* call <code>getName()</code> when invoked.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class CompositeStringExpression implements Expression {
|
public class CompositeStringExpression implements Expression {
|
||||||
|
|
||||||
private final String expressionString;
|
private final String expressionString;
|
||||||
|
|
||||||
/**
|
/** The array of expressions that make up the composite expression */
|
||||||
* The array of expressions that make up the composite expression
|
|
||||||
*/
|
|
||||||
private final Expression[] expressions;
|
private final Expression[] expressions;
|
||||||
|
|
||||||
|
|
||||||
public CompositeStringExpression(String expressionString, Expression[] expressions) {
|
public CompositeStringExpression(String expressionString, Expression[] expressions) {
|
||||||
this.expressionString = expressionString;
|
this.expressionString = expressionString;
|
||||||
this.expressions = expressions;
|
this.expressions = expressions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getExpressionString() {
|
|
||||||
return expressionString;
|
public final String getExpressionString() {
|
||||||
|
return this.expressionString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue() throws EvaluationException {
|
public String getValue() throws EvaluationException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (int i = 0; i < expressions.length; i++) {
|
for (Expression expression : this.expressions) {
|
||||||
// TODO is stringify ok for the non literal components? or should the converters be used? see another
|
sb.append(ObjectUtils.getDisplayString(expression.getValue()));
|
||||||
// case below
|
|
||||||
sb.append(expressions[i].getValue());
|
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue(EvaluationContext context) throws EvaluationException {
|
public String getValue(EvaluationContext context) throws EvaluationException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (int i = 0; i < expressions.length; i++) {
|
for (Expression expression : this.expressions) {
|
||||||
sb.append(expressions[i].getValue(context));
|
sb.append(ObjectUtils.getDisplayString(expression.getValue(context)));
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getValueType(EvaluationContext context) throws EvaluationException {
|
public Class getValueType(EvaluationContext context) {
|
||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getValueType() throws EvaluationException {
|
public Class getValueType() {
|
||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
||||||
throw new EvaluationException(expressionString, "Cannot call setValue() on a composite expression");
|
throw new EvaluationException(this.expressionString, "Cannot call setValue on a composite expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getValue(EvaluationContext context, Class<T> expectedResultType) throws EvaluationException {
|
public <T> T getValue(EvaluationContext context, Class<T> expectedResultType) throws EvaluationException {
|
||||||
Object value = getValue(context);
|
Object value = getValue(context);
|
||||||
return (T)ExpressionUtils.convert(context, value, expectedResultType);
|
return ExpressionUtils.convert(context, value, expectedResultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
|
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
|
||||||
Object value = getValue();
|
Object value = getValue();
|
||||||
return (T)ExpressionUtils.convert(null, value, expectedResultType);
|
return ExpressionUtils.convert(null, value, expectedResultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWritable(EvaluationContext context) throws EvaluationException {
|
public boolean isWritable(EvaluationContext context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package org.springframework.expression.common;
|
|
||||||
|
|
||||||
import org.springframework.expression.ParserContext;
|
|
||||||
|
|
||||||
public class DefaultNonTemplateParserContext implements ParserContext {
|
|
||||||
|
|
||||||
public static final DefaultNonTemplateParserContext INSTANCE = new DefaultNonTemplateParserContext();
|
|
||||||
|
|
||||||
private DefaultNonTemplateParserContext() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExpressionPrefix() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExpressionSuffix() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTemplate() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package org.springframework.expression.common;
|
|
||||||
|
|
||||||
import org.springframework.expression.ParserContext;
|
|
||||||
|
|
||||||
public class DefaultTemplateParserContext implements ParserContext {
|
|
||||||
|
|
||||||
public static final DefaultTemplateParserContext INSTANCE = new DefaultTemplateParserContext();
|
|
||||||
|
|
||||||
private DefaultTemplateParserContext() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExpressionPrefix() {
|
|
||||||
return "${";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExpressionSuffix() {
|
|
||||||
return "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTemplate() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,43 +13,43 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.common;
|
package org.springframework.expression.common;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.TypeConverter;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.expression.TypeUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common utility functions that may be used by any Expression Language provider.
|
* Common utility functions that may be used by any Expression Language provider.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class ExpressionUtils {
|
public abstract class ExpressionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if there is a type converter available in the specified context and attempts to use it to convert the
|
* Determines if there is a type converter available in the specified context and attempts to use it to convert the
|
||||||
* supplied value to the specified type. Throws an exception if conversion is not possible.
|
* supplied value to the specified type. Throws an exception if conversion is not possible.
|
||||||
*
|
|
||||||
* @param context the evaluation context that may define a type converter
|
* @param context the evaluation context that may define a type converter
|
||||||
* @param value the value to convert (may be null)
|
* @param value the value to convert (may be null)
|
||||||
* @param toType the type to attempt conversion to
|
* @param targetType the type to attempt conversion to
|
||||||
* @return the converted value
|
* @return the converted value
|
||||||
* @throws EvaluationException if there is a problem during conversion or conversion of the value to the specified
|
* @throws EvaluationException if there is a problem during conversion or conversion of the value to the specified
|
||||||
* type is not supported
|
* type is not supported
|
||||||
*/
|
*/
|
||||||
public static Object convert(EvaluationContext context, Object value, Class<?> toType) throws EvaluationException {
|
@SuppressWarnings("unchecked")
|
||||||
if (value == null || toType == null || toType.isAssignableFrom(value.getClass())) {
|
public static <T> T convert(EvaluationContext context, Object value, Class<T> targetType)
|
||||||
return value;
|
throws EvaluationException {
|
||||||
|
|
||||||
|
if (targetType == null || ClassUtils.isAssignableValue(targetType, value)) {
|
||||||
|
return (T) value;
|
||||||
}
|
}
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
TypeUtils typeUtils = context.getTypeUtils();
|
return context.getTypeConverter().convertValue(value, targetType);
|
||||||
if (typeUtils != null) {
|
|
||||||
TypeConverter typeConverter = typeUtils.getTypeConverter();
|
|
||||||
return typeConverter.convertValue(value, toType);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
throw new EvaluationException("Cannot convert value '" + value + "' to type '" + toType.getName() + "'");
|
throw new EvaluationException("Cannot convert value '" + value + "' to type '" + targetType.getName() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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.springframework.expression.common;
|
package org.springframework.expression.common;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
|
@ -8,35 +24,34 @@ import org.springframework.expression.Expression;
|
||||||
* A very simple hardcoded implementation of the Expression interface that represents a string literal. It is used with
|
* A very simple hardcoded implementation of the Expression interface that represents a string literal. It is used with
|
||||||
* CompositeStringExpression when representing a template expression which is made up of pieces - some being real
|
* CompositeStringExpression when representing a template expression which is made up of pieces - some being real
|
||||||
* expressions to be handled by an EL implementation like Spel, and some being just textual elements.
|
* expressions to be handled by an EL implementation like Spel, and some being just textual elements.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class LiteralExpression implements Expression {
|
public class LiteralExpression implements Expression {
|
||||||
|
|
||||||
/**
|
/** Fixed literal value of this expression */
|
||||||
* Fixed literal value of this expression
|
|
||||||
*/
|
|
||||||
private final String literalValue;
|
private final String literalValue;
|
||||||
|
|
||||||
|
|
||||||
public LiteralExpression(String literalValue) {
|
public LiteralExpression(String literalValue) {
|
||||||
this.literalValue = literalValue;
|
this.literalValue = literalValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getExpressionString() {
|
|
||||||
return literalValue;
|
public final String getExpressionString() {
|
||||||
// return new StringBuilder().append("'").append(literalValue).append("'").toString();
|
return this.literalValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue() throws EvaluationException {
|
public String getValue() {
|
||||||
return literalValue;
|
return this.literalValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue(EvaluationContext context) throws EvaluationException {
|
public String getValue(EvaluationContext context) {
|
||||||
return literalValue;
|
return this.literalValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getValueType(EvaluationContext context) throws EvaluationException {
|
public Class getValueType(EvaluationContext context) {
|
||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,19 +61,19 @@ public class LiteralExpression implements Expression {
|
||||||
|
|
||||||
public <T> T getValue(EvaluationContext context, Class<T> expectedResultType) throws EvaluationException {
|
public <T> T getValue(EvaluationContext context, Class<T> expectedResultType) throws EvaluationException {
|
||||||
Object value = getValue(context);
|
Object value = getValue(context);
|
||||||
return (T)ExpressionUtils.convert(context, value, expectedResultType);
|
return ExpressionUtils.convert(context, value, expectedResultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
|
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
|
||||||
Object value = getValue();
|
Object value = getValue();
|
||||||
return (T)ExpressionUtils.convert(null, value, expectedResultType);
|
return ExpressionUtils.convert(null, value, expectedResultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWritable(EvaluationContext context) throws EvaluationException {
|
public boolean isWritable(EvaluationContext context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getValueType() throws EvaluationException {
|
public Class getValueType() {
|
||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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.springframework.expression.common;
|
||||||
|
|
||||||
|
import org.springframework.expression.ParserContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configurable {@link ParserContext} implementation for template parsing.
|
||||||
|
* Expects the expression prefix and suffix as constructor arguments.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public class TemplateParserContext implements ParserContext {
|
||||||
|
|
||||||
|
private final String expressionPrefix;
|
||||||
|
|
||||||
|
private final String expressionSuffix;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new TemplateParserContext for the given prefix and suffix.
|
||||||
|
* @param expressionPrefix the expression prefix to use
|
||||||
|
* @param expressionSuffix the expression suffix to use
|
||||||
|
*/
|
||||||
|
public TemplateParserContext(String expressionPrefix, String expressionSuffix) {
|
||||||
|
this.expressionPrefix = expressionPrefix;
|
||||||
|
this.expressionSuffix = expressionSuffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final boolean isTemplate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getExpressionPrefix() {
|
||||||
|
return this.expressionPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getExpressionSuffix() {
|
||||||
|
return this.expressionSuffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -26,8 +26,6 @@ import org.springframework.expression.Operation;
|
||||||
import org.springframework.expression.OperatorOverloader;
|
import org.springframework.expression.OperatorOverloader;
|
||||||
import org.springframework.expression.PropertyAccessor;
|
import org.springframework.expression.PropertyAccessor;
|
||||||
import org.springframework.expression.TypeComparator;
|
import org.springframework.expression.TypeComparator;
|
||||||
import org.springframework.expression.TypeConverter;
|
|
||||||
import org.springframework.expression.TypeUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ExpressionState is for maintaining per-expression-evaluation state, any changes to it are not seen by other
|
* An ExpressionState is for maintaining per-expression-evaluation state, any changes to it are not seen by other
|
||||||
|
|
@ -38,203 +36,158 @@ import org.springframework.expression.TypeUtils;
|
||||||
* It also acts as a place for to define common utility routines that the various Ast nodes might need.
|
* It also acts as a place for to define common utility routines that the various Ast nodes might need.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class ExpressionState {
|
public class ExpressionState {
|
||||||
|
|
||||||
private EvaluationContext relatedContext;
|
private final EvaluationContext relatedContext;
|
||||||
|
|
||||||
private final Stack<VariableScope> variableScopes = new Stack<VariableScope>();
|
private final Stack<VariableScope> variableScopes = new Stack<VariableScope>();
|
||||||
|
|
||||||
private final Stack<Object> contextObjects = new Stack<Object>();
|
private final Stack<Object> contextObjects = new Stack<Object>();
|
||||||
|
|
||||||
public ExpressionState(EvaluationContext context) {
|
|
||||||
relatedContext = context;
|
|
||||||
createVariableScope();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExpressionState() {
|
public ExpressionState() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpressionState(EvaluationContext context) {
|
||||||
|
this.relatedContext = context;
|
||||||
createVariableScope();
|
createVariableScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void createVariableScope() {
|
private void createVariableScope() {
|
||||||
variableScopes.add(new VariableScope()); // create an empty top level VariableScope
|
this.variableScopes.add(new VariableScope()); // create an empty top level VariableScope
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The active context object is what unqualified references to properties/etc are resolved against.
|
* The active context object is what unqualified references to properties/etc are resolved against.
|
||||||
*/
|
*/
|
||||||
public Object getActiveContextObject() {
|
public Object getActiveContextObject() {
|
||||||
if (contextObjects.isEmpty()) {
|
if (this.contextObjects.isEmpty()) {
|
||||||
return relatedContext.getRootContextObject();
|
return this.relatedContext.getRootObject();
|
||||||
}
|
}
|
||||||
return contextObjects.peek();
|
return this.contextObjects.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushActiveContextObject(Object obj) {
|
public void pushActiveContextObject(Object obj) {
|
||||||
contextObjects.push(obj);
|
this.contextObjects.push(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void popActiveContextObject() {
|
public void popActiveContextObject() {
|
||||||
contextObjects.pop();
|
this.contextObjects.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getRootContextObject() {
|
public Object getRootContextObject() {
|
||||||
return relatedContext.getRootContextObject();
|
return this.relatedContext.getRootObject();
|
||||||
}
|
|
||||||
|
|
||||||
public Object lookupReference(Object contextName, Object objectName) throws EvaluationException {
|
|
||||||
return relatedContext.lookupReference(contextName, objectName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeUtils getTypeUtilities() {
|
|
||||||
return relatedContext.getTypeUtils();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeComparator getTypeComparator() {
|
|
||||||
return relatedContext.getTypeUtils().getTypeComparator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> findType(String type) throws EvaluationException {
|
|
||||||
return getTypeUtilities().getTypeLocator().findType(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO all these methods that grab the type converter will fail badly if there isn't one...
|
|
||||||
public boolean toBoolean(Object value) throws EvaluationException {
|
|
||||||
return ((Boolean) getTypeConverter().convertValue(value, Boolean.TYPE)).booleanValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public char toCharacter(Object value) throws EvaluationException {
|
|
||||||
return ((Character) getTypeConverter().convertValue(value, Character.TYPE)).charValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public short toShort(Object value) throws EvaluationException {
|
|
||||||
return ((Short) getTypeConverter().convertValue(value, Short.TYPE)).shortValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int toInteger(Object value) throws EvaluationException {
|
|
||||||
return ((Integer) getTypeConverter().convertValue(value, Integer.TYPE)).intValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public double toDouble(Object value) throws EvaluationException {
|
|
||||||
return ((Double) getTypeConverter().convertValue(value, Double.TYPE)).doubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public float toFloat(Object value) throws EvaluationException {
|
|
||||||
return ((Float) getTypeConverter().convertValue(value, Float.TYPE)).floatValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long toLong(Object value) throws EvaluationException {
|
|
||||||
return ((Long) getTypeConverter().convertValue(value, Long.TYPE)).longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte toByte(Object value) throws EvaluationException {
|
|
||||||
return ((Byte) getTypeConverter().convertValue(value, Byte.TYPE)).byteValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeConverter getTypeConverter() {
|
|
||||||
// TODO cache TypeConverter when it is set/changed?
|
|
||||||
return getTypeUtilities().getTypeConverter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVariable(String name, Object value) {
|
public void setVariable(String name, Object value) {
|
||||||
relatedContext.setVariable(name, value);
|
this.relatedContext.setVariable(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object lookupVariable(String name) {
|
public Object lookupVariable(String name) {
|
||||||
return relatedContext.lookupVariable(name);
|
return this.relatedContext.lookupVariable(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object lookupReference(Object contextName, String objectName) throws EvaluationException {
|
||||||
|
return this.relatedContext.lookupReference(contextName, objectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeComparator getTypeComparator() {
|
||||||
|
return this.relatedContext.getTypeComparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> findType(String type) throws EvaluationException {
|
||||||
|
return this.relatedContext.getTypeLocator().findType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T convertValue(Object value, Class<T> targetType) throws EvaluationException {
|
||||||
|
return this.relatedContext.getTypeConverter().convertValue(value, targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A new scope is entered when a function is invoked
|
* A new scope is entered when a function is invoked
|
||||||
*/
|
*/
|
||||||
public void enterScope(Map<String, Object> argMap) {
|
public void enterScope(Map<String, Object> argMap) {
|
||||||
variableScopes.push(new VariableScope(argMap));
|
this.variableScopes.push(new VariableScope(argMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enterScope(String name, Object value) {
|
public void enterScope(String name, Object value) {
|
||||||
variableScopes.push(new VariableScope(name, value));
|
this.variableScopes.push(new VariableScope(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exitScope() {
|
public void exitScope() {
|
||||||
variableScopes.pop();
|
this.variableScopes.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocalVariable(String name, Object value) {
|
public void setLocalVariable(String name, Object value) {
|
||||||
variableScopes.peek().setVariable(name, value);
|
this.variableScopes.peek().setVariable(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object lookupLocalVariable(String name) {
|
public Object lookupLocalVariable(String name) {
|
||||||
int scopeNumber = variableScopes.size() - 1;
|
int scopeNumber = this.variableScopes.size() - 1;
|
||||||
for (int i = scopeNumber; i >= 0; i--) {
|
for (int i = scopeNumber; i >= 0; i--) {
|
||||||
if (variableScopes.get(i).definesVariable(name)) {
|
if (this.variableScopes.get(i).definesVariable(name)) {
|
||||||
return variableScopes.get(i).lookupVariable(name);
|
return this.variableScopes.get(i).lookupVariable(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object operate(Operation op, Object left, Object right) throws SpelException {
|
public Object operate(Operation op, Object left, Object right) throws EvaluationException {
|
||||||
OperatorOverloader overloader = relatedContext.getTypeUtils().getOperatorOverloader();
|
OperatorOverloader overloader = this.relatedContext.getOperatorOverloader();
|
||||||
try {
|
if (overloader.overridesOperation(op, left, right)) {
|
||||||
if (overloader != null && overloader.overridesOperation(op, left, right)) {
|
return overloader.operate(op, left, right);
|
||||||
return overloader.operate(op, left, right);
|
}
|
||||||
} else {
|
else {
|
||||||
throw new SpelException(SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES, op, left, right);
|
throw new SpelException(SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES, op, left, right);
|
||||||
}
|
|
||||||
} catch (EvaluationException e) {
|
|
||||||
if (e instanceof SpelException) {
|
|
||||||
throw (SpelException) e;
|
|
||||||
} else {
|
|
||||||
throw new SpelException(e, SpelMessages.UNEXPECTED_PROBLEM_INVOKING_OPERATOR, op, left, right, e
|
|
||||||
.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PropertyAccessor> getPropertyAccessors() {
|
public List<PropertyAccessor> getPropertyAccessors() {
|
||||||
return relatedContext.getPropertyAccessors();
|
return this.relatedContext.getPropertyAccessors();
|
||||||
}
|
}
|
||||||
|
|
||||||
public EvaluationContext getEvaluationContext() {
|
public EvaluationContext getEvaluationContext() {
|
||||||
return relatedContext;
|
return this.relatedContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A new scope is entered when a function is called and it is used to hold the parameters to the function call. If the names
|
* A new scope is entered when a function is called and it is used to hold the parameters to the function call. If the names
|
||||||
* of the parameters clash with those in a higher level scope, those in the higher level scope will not be accessible whilst
|
* of the parameters clash with those in a higher level scope, those in the higher level scope will not be accessible whilst
|
||||||
* the function is executing. When the function returns the scope is exited.
|
* the function is executing. When the function returns the scope is exited.
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static class VariableScope {
|
private static class VariableScope {
|
||||||
|
|
||||||
private final Map<String, Object> vars = new HashMap<String, Object>();
|
private final Map<String, Object> vars = new HashMap<String, Object>();
|
||||||
|
|
||||||
public VariableScope() { }
|
public VariableScope() { }
|
||||||
|
|
||||||
public VariableScope(Map<String, Object> arguments) {
|
public VariableScope(Map<String, Object> arguments) {
|
||||||
if (arguments!=null) {
|
if (arguments != null) {
|
||||||
vars.putAll(arguments);
|
this.vars.putAll(arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableScope(String name,Object value) {
|
public VariableScope(String name, Object value) {
|
||||||
vars.put(name,value);
|
this.vars.put(name,value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object lookupVariable(String name) {
|
public Object lookupVariable(String name) {
|
||||||
return vars.get(name);
|
return this.vars.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVariable(String name, Object value) {
|
public void setVariable(String name, Object value) {
|
||||||
vars.put(name,value);
|
this.vars.put(name,value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean definesVariable(String name) {
|
public boolean definesVariable(String name) {
|
||||||
return vars.containsKey(name);
|
return this.vars.containsKey(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import org.springframework.expression.EvaluationException;
|
||||||
* that can occur.
|
* that can occur.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class SpelException extends EvaluationException {
|
public class SpelException extends EvaluationException {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,18 +26,17 @@ import org.springframework.expression.common.ExpressionUtils;
|
||||||
* asked to resolve references to types, beans, properties, methods.
|
* asked to resolve references to types, beans, properties, methods.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class SpelExpression implements Expression {
|
public class SpelExpression implements Expression {
|
||||||
|
|
||||||
private final String expression;
|
private final String expression;
|
||||||
|
|
||||||
public final SpelNode ast;
|
public final SpelNode ast;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an expression, only used by the parser.
|
* Construct an expression, only used by the parser.
|
||||||
*
|
|
||||||
* @param expression
|
|
||||||
* @param ast
|
|
||||||
*/
|
*/
|
||||||
public SpelExpression(String expression, SpelNode ast) {
|
public SpelExpression(String expression, SpelNode ast) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
|
|
@ -48,26 +47,27 @@ public class SpelExpression implements Expression {
|
||||||
* @return the expression string that was parsed to create this expression instance
|
* @return the expression string that was parsed to create this expression instance
|
||||||
*/
|
*/
|
||||||
public String getExpressionString() {
|
public String getExpressionString() {
|
||||||
return expression;
|
return this.expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public Object getValue() throws EvaluationException {
|
public Object getValue() throws EvaluationException {
|
||||||
return ast.getValue(null);
|
return this.ast.getValue(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public Object getValue(EvaluationContext context) throws EvaluationException {
|
public Object getValue(EvaluationContext context) throws EvaluationException {
|
||||||
return ast.getValue(new ExpressionState(context));
|
return this.ast.getValue(new ExpressionState(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T getValue(EvaluationContext context, Class<T> expectedResultType) throws EvaluationException {
|
public <T> T getValue(EvaluationContext context, Class<T> expectedResultType) throws EvaluationException {
|
||||||
Object result = ast.getValue(new ExpressionState(context));
|
Object result = ast.getValue(new ExpressionState(context));
|
||||||
|
|
||||||
|
|
@ -75,31 +75,31 @@ public class SpelExpression implements Expression {
|
||||||
Class<?> resultType = result.getClass();
|
Class<?> resultType = result.getClass();
|
||||||
if (!expectedResultType.isAssignableFrom(resultType)) {
|
if (!expectedResultType.isAssignableFrom(resultType)) {
|
||||||
// Attempt conversion to the requested type, may throw an exception
|
// Attempt conversion to the requested type, may throw an exception
|
||||||
result = context.getTypeUtils().getTypeConverter().convertValue(result, expectedResultType);
|
result = context.getTypeConverter().convertValue(result, expectedResultType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (T)result;
|
return (T) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
||||||
ast.setValue(new ExpressionState(context), value);
|
this.ast.setValue(new ExpressionState(context), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public boolean isWritable(EvaluationContext context) throws EvaluationException {
|
public boolean isWritable(EvaluationContext context) throws EvaluationException {
|
||||||
return ast.isWritable(new ExpressionState(context));
|
return this.ast.isWritable(new ExpressionState(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return return the Abstract Syntax Tree for the expression
|
* @return return the Abstract Syntax Tree for the expression
|
||||||
*/
|
*/
|
||||||
public SpelNode getAST() {
|
public SpelNode getAST() {
|
||||||
return ast;
|
return this.ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -110,7 +110,7 @@ public class SpelExpression implements Expression {
|
||||||
* @return the string representation of the AST
|
* @return the string representation of the AST
|
||||||
*/
|
*/
|
||||||
public String toStringAST() {
|
public String toStringAST() {
|
||||||
return ast.toStringAST();
|
return this.ast.toStringAST();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -120,11 +120,7 @@ public class SpelExpression implements Expression {
|
||||||
// TODO is this a legal implementation? The null return value could be very unhelpful. See other getValueType()
|
// TODO is this a legal implementation? The null return value could be very unhelpful. See other getValueType()
|
||||||
// also.
|
// also.
|
||||||
Object value = getValue(context);
|
Object value = getValue(context);
|
||||||
if (value == null) {
|
return (value != null ? value.getClass() : null);
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return value.getClass();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -132,20 +128,17 @@ public class SpelExpression implements Expression {
|
||||||
*/
|
*/
|
||||||
public Class getValueType() throws EvaluationException {
|
public Class getValueType() throws EvaluationException {
|
||||||
Object value = getValue();
|
Object value = getValue();
|
||||||
if (value == null) {
|
return (value != null ? value.getClass() : null);
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return value.getClass();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
|
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
|
||||||
Object result = getValue();
|
Object result = getValue();
|
||||||
// TODO propagate generic-ness into convert
|
// TODO propagate generic-ness into convert
|
||||||
return (T)ExpressionUtils.convert(null, result, expectedResultType);
|
return (T) ExpressionUtils.convert(null, result, expectedResultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression.spel;
|
|
||||||
|
|
||||||
import org.springframework.expression.Expression;
|
|
||||||
import org.springframework.expression.ParseException;
|
|
||||||
import org.springframework.expression.ParserContext;
|
|
||||||
import org.springframework.expression.common.DefaultNonTemplateParserContext;
|
|
||||||
import org.springframework.expression.common.TemplateAwareExpressionParser;
|
|
||||||
import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this parser class can process Spring Expression Language format expressions. The result of parsing an
|
|
||||||
* expression is a SpelExpression instance that can be repeatedly evaluated (possibly against different evaluation
|
|
||||||
* contexts) or serialized for later evaluation.
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public class SpelExpressionParser extends TemplateAwareExpressionParser {
|
|
||||||
|
|
||||||
private final SpelInternalParser expressionParser;
|
|
||||||
|
|
||||||
public SpelExpressionParser() {
|
|
||||||
// Use an Antlr based expression parser
|
|
||||||
expressionParser = new SpelAntlrExpressionParser();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse an expression string.
|
|
||||||
*
|
|
||||||
* @param expressionString the expression to parse
|
|
||||||
* @param context the parser context in which to perform the parse
|
|
||||||
* @return a parsed expression object
|
|
||||||
* @throws ParseException if the expression is invalid
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Expression doParseExpression(String expressionString, ParserContext context) throws ParseException {
|
|
||||||
return expressionParser.doParseExpression(expressionString,context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple override with covariance to return a nicer type
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public SpelExpression parseExpression(String expressionString) throws ParseException {
|
|
||||||
return (SpelExpression) super.parseExpression(expressionString, DefaultNonTemplateParserContext.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface SpelInternalParser {
|
|
||||||
Expression doParseExpression(String expressionString, ParserContext context) throws ParseException;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel;
|
package org.springframework.expression.spel;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
@ -33,7 +34,7 @@ import java.text.MessageFormat;
|
||||||
* message has had all relevant inserts applied to it.
|
* message has had all relevant inserts applied to it.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public enum SpelMessages {
|
public enum SpelMessages {
|
||||||
// TODO put keys and messages into bundles for easy NLS
|
// TODO put keys and messages into bundles for easy NLS
|
||||||
|
|
@ -107,7 +108,7 @@ public enum SpelMessages {
|
||||||
Kind.ERROR, 1060, "Expected the type of the new array to be specified as a String but found ''{0}''"), PROBLEM_DURING_TYPE_CONVERSION(
|
Kind.ERROR, 1060, "Expected the type of the new array to be specified as a String but found ''{0}''"), PROBLEM_DURING_TYPE_CONVERSION(
|
||||||
Kind.ERROR, 1061, "Problem occurred during type conversion: {0}"), MULTIPLE_POSSIBLE_METHODS(Kind.ERROR,
|
Kind.ERROR, 1061, "Problem occurred during type conversion: {0}"), MULTIPLE_POSSIBLE_METHODS(Kind.ERROR,
|
||||||
1062, "Method call of ''{0}'' is ambiguous, supported type conversions allow multiple variants to match"), EXCEPTION_DURING_PROPERTY_WRITE(
|
1062, "Method call of ''{0}'' is ambiguous, supported type conversions allow multiple variants to match"), EXCEPTION_DURING_PROPERTY_WRITE(
|
||||||
Kind.ERROR, 1063, "A problem occurred whilst attempting to set the property ''{0}'': ''{1}''"), NOT_AN_INTEGER(
|
Kind.ERROR, 1063, "A problem occurred whilst attempting to set the property ''{0}'': {1}"), NOT_AN_INTEGER(
|
||||||
Kind.ERROR, 1064, "The value ''{0}'' cannot be parsed as an int"), NOT_A_LONG(Kind.ERROR, 1065,
|
Kind.ERROR, 1064, "The value ''{0}'' cannot be parsed as an int"), NOT_A_LONG(Kind.ERROR, 1065,
|
||||||
"The value ''{0}'' cannot be parsed as a long"), PARSE_PROBLEM(Kind.ERROR, 1066,
|
"The value ''{0}'' cannot be parsed as a long"), PARSE_PROBLEM(Kind.ERROR, 1066,
|
||||||
"Error occurred during expression parse: {0}"), INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR(Kind.ERROR,
|
"Error occurred during expression parse: {0}"), INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR(Kind.ERROR,
|
||||||
|
|
@ -121,9 +122,6 @@ public enum SpelMessages {
|
||||||
private int code;
|
private int code;
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public static enum Kind {
|
|
||||||
INFO, WARNING, ERROR
|
|
||||||
};
|
|
||||||
|
|
||||||
private SpelMessages(Kind kind, int code, String message) {
|
private SpelMessages(Kind kind, int code, String message) {
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
|
|
@ -131,6 +129,7 @@ public enum SpelMessages {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a complete message including the prefix, the position (if known) and with the inserts applied to the
|
* Produce a complete message including the prefix, the position (if known) and with the inserts applied to the
|
||||||
* message.
|
* message.
|
||||||
|
|
@ -160,4 +159,10 @@ public enum SpelMessages {
|
||||||
formattedMessage.append(MessageFormat.format(message, inserts));
|
formattedMessage.append(MessageFormat.format(message, inserts));
|
||||||
return formattedMessage.toString();
|
return formattedMessage.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static enum Kind {
|
||||||
|
INFO, WARNING, ERROR
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,20 +13,21 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel;
|
package org.springframework.expression.spel;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a node in the Ast for a parsed expression.
|
* Represents a node in the Ast for a parsed expression.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface SpelNode {
|
public interface SpelNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate the expression node in the context of the supplied expression state and return the value.
|
* Evaluate the expression node in the context of the supplied expression state and return the value.
|
||||||
*
|
|
||||||
* @param expressionState the current expression state (includes the context)
|
* @param expressionState the current expression state (includes the context)
|
||||||
* @return the value of this node evaluated against the specified state
|
* @return the value of this node evaluated against the specified state
|
||||||
*/
|
*/
|
||||||
|
|
@ -44,7 +45,6 @@ public interface SpelNode {
|
||||||
/**
|
/**
|
||||||
* Evaluate the expression to a node and then set the new value on that node. For example, if the expression
|
* Evaluate the expression to a node and then set the new value on that node. For example, if the expression
|
||||||
* evaluates to a property reference then the property will be set to the new value.
|
* evaluates to a property reference then the property will be set to the new value.
|
||||||
*
|
|
||||||
* @param expressionState the current expression state (includes the context)
|
* @param expressionState the current expression state (includes the context)
|
||||||
* @param newValue the new value
|
* @param newValue the new value
|
||||||
* @throws EvaluationException if any problem occurs evaluating the expression or setting the new value
|
* @throws EvaluationException if any problem occurs evaluating the expression or setting the new value
|
||||||
|
|
@ -60,26 +60,23 @@ public interface SpelNode {
|
||||||
* @return the number of children under this node
|
* @return the number of children under this node
|
||||||
*/
|
*/
|
||||||
int getChildCount();
|
int getChildCount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method that returns a SpelNode rather than an Antlr Tree node.
|
* Helper method that returns a SpelNode rather than an Antlr Tree node.
|
||||||
*
|
|
||||||
* @return the child node cast to a SpelNode
|
* @return the child node cast to a SpelNode
|
||||||
*/
|
*/
|
||||||
SpelNode getChild(int index);
|
SpelNode getChild(int index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the class of the object passed in, unless it is already a class object.
|
* Determine the class of the object passed in, unless it is already a class object.
|
||||||
*
|
|
||||||
* @param o the object that the caller wants the class of
|
* @param o the object that the caller wants the class of
|
||||||
* @return the class of the object if it is not already a class object, or null if the object is null
|
* @return the class of the object if it is not already a class object, or null if the object is null
|
||||||
*/
|
*/
|
||||||
Class<?> getObjectClass(Object o);
|
Class<?> getObjectClass(Object obj);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the start position of this Ast node in the expression string
|
* @return the start position of this Ast node in the expression string
|
||||||
*/
|
*/
|
||||||
public int getStartPosition();
|
int getStartPosition();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,9 @@ package org.springframework.expression.spel;
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*/
|
*/
|
||||||
public class WrappedELException extends RuntimeException {
|
public class WrappedSpelException extends RuntimeException {
|
||||||
|
|
||||||
public WrappedELException(SpelException e) {
|
public WrappedSpelException(SpelException e) {
|
||||||
super(e);
|
super(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,63 +13,70 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.antlr;
|
package org.springframework.expression.spel.antlr;
|
||||||
|
|
||||||
import org.antlr.runtime.ANTLRStringStream;
|
import org.antlr.runtime.ANTLRStringStream;
|
||||||
import org.antlr.runtime.CommonTokenStream;
|
import org.antlr.runtime.CommonTokenStream;
|
||||||
import org.antlr.runtime.RecognitionException;
|
import org.antlr.runtime.RecognitionException;
|
||||||
|
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.ParseException;
|
import org.springframework.expression.ParseException;
|
||||||
import org.springframework.expression.ParserContext;
|
import org.springframework.expression.ParserContext;
|
||||||
|
import org.springframework.expression.common.TemplateAwareExpressionParser;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelExpression;
|
import org.springframework.expression.spel.SpelExpression;
|
||||||
import org.springframework.expression.spel.SpelNode;
|
import org.springframework.expression.spel.SpelNode;
|
||||||
import org.springframework.expression.spel.WrappedELException;
|
import org.springframework.expression.spel.WrappedSpelException;
|
||||||
import org.springframework.expression.spel.SpelExpressionParser.SpelInternalParser;
|
|
||||||
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
||||||
import org.springframework.expression.spel.generated.SpringExpressionsParser.expr_return;
|
import org.springframework.expression.spel.generated.SpringExpressionsParser.expr_return;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap an Antlr lexer and parser.
|
* Default {@link org.springframework.expression.ExpressionParser} implementation,
|
||||||
*
|
* wrapping an Antlr lexer and parser that implements standard Spring EL syntax.
|
||||||
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class SpelAntlrExpressionParser implements SpelInternalParser {
|
public class SpelAntlrExpressionParser extends TemplateAwareExpressionParser {
|
||||||
|
|
||||||
private final SpringExpressionsLexer lexer;
|
private final SpringExpressionsLexer lexer;
|
||||||
|
|
||||||
private final SpringExpressionsParserExtender parser;
|
private final SpringExpressionsParserExtender parser;
|
||||||
|
|
||||||
|
|
||||||
public SpelAntlrExpressionParser() {
|
public SpelAntlrExpressionParser() {
|
||||||
lexer = new SpringExpressionsLexerExtender();
|
this.lexer = new SpringExpressionsLexerExtender();
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
CommonTokenStream tokens = new CommonTokenStream(this.lexer);
|
||||||
parser = new SpringExpressionsParserExtender(tokens);
|
this.parser = new SpringExpressionsParserExtender(tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an expression string.
|
* Parse an expression string.
|
||||||
*
|
|
||||||
* @param expressionString the expression to parse
|
* @param expressionString the expression to parse
|
||||||
* @param context the parser context in which to perform the parse
|
* @param context the parser context in which to perform the parse
|
||||||
* @return a parsed expression object
|
* @return a parsed expression object
|
||||||
* @throws ParseException if the expression is invalid
|
* @throws ParseException if the expression is invalid
|
||||||
*/
|
*/
|
||||||
public Expression doParseExpression(String expressionString, ParserContext context) throws ParseException {
|
protected Expression doParseExpression(String expressionString, ParserContext context) throws ParseException {
|
||||||
try {
|
try {
|
||||||
lexer.setCharStream(new ANTLRStringStream(expressionString));
|
this.lexer.setCharStream(new ANTLRStringStream(expressionString));
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
CommonTokenStream tokens = new CommonTokenStream(this.lexer);
|
||||||
parser.setTokenStream(tokens);
|
this.parser.setTokenStream(tokens);
|
||||||
expr_return exprReturn = parser.expr();
|
expr_return exprReturn = this.parser.expr();
|
||||||
SpelExpression newExpression = new SpelExpression(expressionString, (SpelNode) exprReturn.getTree());
|
return new SpelExpression(expressionString, (SpelNode) exprReturn.getTree());
|
||||||
return newExpression;
|
}
|
||||||
} catch (RecognitionException re) {
|
catch (RecognitionException re) {
|
||||||
ParseException exception = new ParseException(expressionString, "Recognition error at position: "
|
throw new ParseException(expressionString,
|
||||||
+ re.charPositionInLine + ": " + re.getMessage(), re);
|
"Recognition error at position: " + re.charPositionInLine + ": " + re.getMessage(), re);
|
||||||
throw exception;
|
}
|
||||||
} catch (WrappedELException e) {
|
catch (WrappedSpelException ex) {
|
||||||
SpelException wrappedException = e.getCause();
|
SpelException wrappedException = ex.getCause();
|
||||||
throw new ParseException(expressionString, "Parsing problem: " + wrappedException.getMessage(),
|
throw new ParseException(expressionString,
|
||||||
wrappedException);
|
"Parsing problem: " + wrappedException.getMessage(), wrappedException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,19 +13,20 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.antlr;
|
package org.springframework.expression.spel.antlr;
|
||||||
|
|
||||||
import org.antlr.runtime.RecognitionException;
|
import org.antlr.runtime.RecognitionException;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.WrappedELException;
|
import org.springframework.expression.spel.WrappedSpelException;
|
||||||
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
||||||
|
|
||||||
public class SpringExpressionsLexerExtender extends SpringExpressionsLexer {
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
public SpringExpressionsLexerExtender() {
|
* @since 3.0
|
||||||
super();
|
*/
|
||||||
}
|
class SpringExpressionsLexerExtender extends SpringExpressionsLexer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* recover() attempts to provide better error messages once something has gone wrong. It then throws a
|
* recover() attempts to provide better error messages once something has gone wrong. It then throws a
|
||||||
|
|
@ -64,7 +65,7 @@ public class SpringExpressionsLexerExtender extends SpringExpressionsLexer {
|
||||||
// getCharErrorDisplay(mte.expecting), getCharErrorDisplay(mte.c));
|
// getCharErrorDisplay(mte.expecting), getCharErrorDisplay(mte.c));
|
||||||
// }
|
// }
|
||||||
SpelException realException = new SpelException(re, SpelMessages.RECOGNITION_ERROR, re.toString());
|
SpelException realException = new SpelException(re, SpelMessages.RECOGNITION_ERROR, re.toString());
|
||||||
throw new WrappedELException(realException);
|
throw new WrappedSpelException(realException);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.antlr;
|
package org.springframework.expression.spel.antlr;
|
||||||
|
|
||||||
import org.antlr.runtime.BitSet;
|
import org.antlr.runtime.BitSet;
|
||||||
|
|
@ -22,11 +23,15 @@ import org.antlr.runtime.Token;
|
||||||
import org.antlr.runtime.TokenStream;
|
import org.antlr.runtime.TokenStream;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.WrappedELException;
|
import org.springframework.expression.spel.WrappedSpelException;
|
||||||
import org.springframework.expression.spel.ast.SpelTreeAdaptor;
|
import org.springframework.expression.spel.ast.SpelTreeAdaptor;
|
||||||
import org.springframework.expression.spel.generated.SpringExpressionsParser;
|
import org.springframework.expression.spel.generated.SpringExpressionsParser;
|
||||||
|
|
||||||
public class SpringExpressionsParserExtender extends SpringExpressionsParser {
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
class SpringExpressionsParserExtender extends SpringExpressionsParser {
|
||||||
|
|
||||||
public SpringExpressionsParserExtender(TokenStream input) {
|
public SpringExpressionsParserExtender(TokenStream input) {
|
||||||
super(input);
|
super(input);
|
||||||
|
|
@ -53,7 +58,7 @@ public class SpringExpressionsParserExtender extends SpringExpressionsParser {
|
||||||
// message = "no more input data to process whilst constructing " + paraphrase.peek();
|
// message = "no more input data to process whilst constructing " + paraphrase.peek();
|
||||||
// }
|
// }
|
||||||
SpelException parsingProblem = new SpelException(e.charPositionInLine, e, SpelMessages.PARSE_PROBLEM, message);
|
SpelException parsingProblem = new SpelException(e.charPositionInLine, e, SpelMessages.PARSE_PROBLEM, message);
|
||||||
throw new WrappedELException(parsingProblem);
|
throw new WrappedSpelException(parsingProblem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -22,11 +23,11 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents assignment. An alternative to calling setValue() for an expression is to use an assign.
|
* Represents assignment. An alternative to calling setValue() for an expression is to use an assign.
|
||||||
* <p>
|
*
|
||||||
* Example: 'someNumberProperty=42'
|
* <p>Example: 'someNumberProperty=42'
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class Assign extends SpelNodeImpl {
|
public class Assign extends SpelNodeImpl {
|
||||||
|
|
||||||
|
|
@ -51,4 +52,5 @@ public class Assign extends SpelNodeImpl {
|
||||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,15 +13,16 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the literal values TRUE and FALSE.
|
* Represents the literal values TRUE and FALSE.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class BooleanLiteral extends Literal {
|
public class BooleanLiteral extends Literal {
|
||||||
|
|
||||||
|
|
@ -34,7 +35,7 @@ public class BooleanLiteral extends Literal {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean getLiteralValue() {
|
public Boolean getLiteralValue() {
|
||||||
return value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -24,7 +25,7 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
* Represents a DOT separated expression sequence, such as 'property1.property2.methodOne()'
|
* Represents a DOT separated expression sequence, such as 'property1.property2.methodOne()'
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class CompoundExpression extends SpelNodeImpl {
|
public class CompoundExpression extends SpelNodeImpl {
|
||||||
|
|
||||||
|
|
@ -35,7 +36,6 @@ public class CompoundExpression extends SpelNodeImpl {
|
||||||
/**
|
/**
|
||||||
* Evalutes a compound expression. This involves evaluating each piece in turn and the return value from each piece
|
* Evalutes a compound expression. This involves evaluating each piece in turn and the return value from each piece
|
||||||
* is the active context object for the subsequent piece.
|
* is the active context object for the subsequent piece.
|
||||||
*
|
|
||||||
* @param state the state in which the expression is being evaluated
|
* @param state the state in which the expression is being evaluated
|
||||||
* @return the final value from the last piece of the compound expression
|
* @return the final value from the last piece of the compound expression
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,12 +13,14 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.ConstructorExecutor;
|
import org.springframework.expression.ConstructorExecutor;
|
||||||
import org.springframework.expression.ConstructorResolver;
|
import org.springframework.expression.ConstructorResolver;
|
||||||
|
|
@ -27,8 +29,6 @@ import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.internal.TypeCode;
|
|
||||||
import org.springframework.expression.spel.internal.Utils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the invocation of a constructor. Either a constructor on a regular type or construction of an array. When
|
* Represents the invocation of a constructor. Either a constructor on a regular type or construction of an array. When
|
||||||
|
|
@ -40,41 +40,38 @@ import org.springframework.expression.spel.internal.Utils;
|
||||||
* new int[3] new int[3]{1,2,3}
|
* new int[3] new int[3]{1,2,3}
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class ConstructorReference extends SpelNodeImpl {
|
public class ConstructorReference extends SpelNodeImpl {
|
||||||
|
|
||||||
/**
|
|
||||||
* The resolver/executor model {@link ConstructorResolver} supports the caching of executor objects that can run
|
|
||||||
* some discovered constructor repeatedly without searching for it each time. This flag controls whether caching
|
|
||||||
* occurs and is primarily exposed for testing.
|
|
||||||
*/
|
|
||||||
public static boolean useCaching = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The cached executor that may be reused on subsequent evaluations.
|
|
||||||
*/
|
|
||||||
private ConstructorExecutor cachedExecutor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true then this is an array constructor, for example, 'new String[]', rather than a simple constructor 'new
|
* If true then this is an array constructor, for example, 'new String[]', rather than a simple constructor 'new
|
||||||
* String()'
|
* String()'
|
||||||
*/
|
*/
|
||||||
private final boolean isArrayConstructor;
|
private final boolean isArrayConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cached executor that may be reused on subsequent evaluations.
|
||||||
|
*/
|
||||||
|
private ConstructorExecutor cachedExecutor;
|
||||||
|
|
||||||
|
|
||||||
public ConstructorReference(Token payload, boolean isArrayConstructor) {
|
public ConstructorReference(Token payload, boolean isArrayConstructor) {
|
||||||
super(payload);
|
super(payload);
|
||||||
this.isArrayConstructor = isArrayConstructor;
|
this.isArrayConstructor = isArrayConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements getValue() - delegating to the code for building an array or a simple type.
|
* Implements getValue() - delegating to the code for building an array or a simple type.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
||||||
if (isArrayConstructor) {
|
if (this.isArrayConstructor) {
|
||||||
return createArray(state);
|
return createArray(state);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return createNewInstance(state);
|
return createNewInstance(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +84,7 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
sb.append(getChild(index++).toStringAST());
|
sb.append(getChild(index++).toStringAST());
|
||||||
|
|
||||||
if (!isArrayConstructor) {
|
if (!this.isArrayConstructor) {
|
||||||
sb.append("(");
|
sb.append("(");
|
||||||
for (int i = index; i < getChildCount(); i++) {
|
for (int i = index; i < getChildCount(); i++) {
|
||||||
if (i > index)
|
if (i > index)
|
||||||
|
|
@ -95,7 +92,8 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
sb.append(getChild(i).toStringAST());
|
sb.append(getChild(i).toStringAST());
|
||||||
}
|
}
|
||||||
sb.append(")");
|
sb.append(")");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Next child is EXPRESSIONLIST token with children that are the
|
// Next child is EXPRESSIONLIST token with children that are the
|
||||||
// expressions giving array size
|
// expressions giving array size
|
||||||
sb.append("[");
|
sb.append("[");
|
||||||
|
|
@ -117,10 +115,10 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an array and return it. The children of this node indicate the type of array, the array ranks and any
|
* Create an array and return it. The children of this node indicate the type of array, the array ranks and any
|
||||||
* optional initializer that might have been supplied.
|
* optional initializer that might have been supplied.
|
||||||
*
|
|
||||||
* @param state the expression state within which this expression is being evaluated
|
* @param state the expression state within which this expression is being evaluated
|
||||||
* @return the new array
|
* @return the new array
|
||||||
* @throws EvaluationException if there is a problem creating the array
|
* @throws EvaluationException if there is a problem creating the array
|
||||||
|
|
@ -129,8 +127,8 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
Object intendedArrayType = getChild(0).getValueInternal(state);
|
Object intendedArrayType = getChild(0).getValueInternal(state);
|
||||||
if (!(intendedArrayType instanceof String)) {
|
if (!(intendedArrayType instanceof String)) {
|
||||||
throw new SpelException(getChild(0).getCharPositionInLine(),
|
throw new SpelException(getChild(0).getCharPositionInLine(),
|
||||||
SpelMessages.TYPE_NAME_EXPECTED_FOR_ARRAY_CONSTRUCTION, Utils
|
SpelMessages.TYPE_NAME_EXPECTED_FOR_ARRAY_CONSTRUCTION,
|
||||||
.formatClassnameForMessage(intendedArrayType.getClass()));
|
FormatHelper.formatClassNameForMessage(intendedArrayType.getClass()));
|
||||||
}
|
}
|
||||||
String type = (String) intendedArrayType;
|
String type = (String) intendedArrayType;
|
||||||
Class<?> componentType = null;
|
Class<?> componentType = null;
|
||||||
|
|
@ -151,12 +149,13 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
// no array ranks so use the size of the initializer to determine array size
|
// no array ranks so use the size of the initializer to determine array size
|
||||||
int arraySize = getChild(2).getChildCount();
|
int arraySize = getChild(2).getChildCount();
|
||||||
newArray = Array.newInstance(componentType, arraySize);
|
newArray = Array.newInstance(componentType, arraySize);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Array ranks are specified but is it a single or multiple dimension array?
|
// Array ranks are specified but is it a single or multiple dimension array?
|
||||||
int dimensions = getChild(1).getChildCount();
|
int dimensions = getChild(1).getChildCount();
|
||||||
if (dimensions == 1) {
|
if (dimensions == 1) {
|
||||||
Object o = getChild(1).getValueInternal(state);
|
Object o = getChild(1).getValueInternal(state);
|
||||||
int arraySize = state.toInteger(o);
|
int arraySize = state.convertValue(o, Integer.class);
|
||||||
if (getChildCount() == 3) {
|
if (getChildCount() == 3) {
|
||||||
// Check initializer length matches array size length
|
// Check initializer length matches array size length
|
||||||
int initializerLength = getChild(2).getChildCount();
|
int initializerLength = getChild(2).getChildCount();
|
||||||
|
|
@ -166,11 +165,12 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newArray = Array.newInstance(componentType, arraySize);
|
newArray = Array.newInstance(componentType, arraySize);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Multi-dimensional - hold onto your hat !
|
// Multi-dimensional - hold onto your hat !
|
||||||
int[] dims = new int[dimensions];
|
int[] dims = new int[dimensions];
|
||||||
for (int d = 0; d < dimensions; d++) {
|
for (int d = 0; d < dimensions; d++) {
|
||||||
dims[d] = state.toInteger(getChild(1).getChild(d).getValueInternal(state));
|
dims[d] = state.convertValue(getChild(1).getChild(d).getValueInternal(state), Integer.class);
|
||||||
}
|
}
|
||||||
newArray = Array.newInstance(componentType, dims);
|
newArray = Array.newInstance(componentType, dims);
|
||||||
// TODO check any specified initializer for the multidim array matches
|
// TODO check any specified initializer for the multidim array matches
|
||||||
|
|
@ -195,42 +195,42 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
} else if (arrayTypeCode == TypeCode.INT) {
|
} else if (arrayTypeCode == TypeCode.INT) {
|
||||||
int[] newIntArray = (int[]) newArray;
|
int[] newIntArray = (int[]) newArray;
|
||||||
for (int i = 0; i < newIntArray.length; i++) {
|
for (int i = 0; i < newIntArray.length; i++) {
|
||||||
newIntArray[i] = state.toInteger(initializer.getChild(i).getValueInternal(state));
|
newIntArray[i] = state.convertValue(initializer.getChild(i).getValueInternal(state), Integer.class);
|
||||||
}
|
}
|
||||||
} else if (arrayTypeCode == TypeCode.BOOLEAN) {
|
} else if (arrayTypeCode == TypeCode.BOOLEAN) {
|
||||||
boolean[] newBooleanArray = (boolean[]) newArray;
|
boolean[] newBooleanArray = (boolean[]) newArray;
|
||||||
for (int i = 0; i < newBooleanArray.length; i++) {
|
for (int i = 0; i < newBooleanArray.length; i++) {
|
||||||
newBooleanArray[i] = state.toBoolean(initializer.getChild(i).getValueInternal(state));
|
newBooleanArray[i] = state.convertValue(initializer.getChild(i).getValueInternal(state), Boolean.class);
|
||||||
}
|
}
|
||||||
} else if (arrayTypeCode == TypeCode.CHAR) {
|
} else if (arrayTypeCode == TypeCode.CHAR) {
|
||||||
char[] newCharArray = (char[]) newArray;
|
char[] newCharArray = (char[]) newArray;
|
||||||
for (int i = 0; i < newCharArray.length; i++) {
|
for (int i = 0; i < newCharArray.length; i++) {
|
||||||
newCharArray[i] = state.toCharacter(initializer.getChild(i).getValueInternal(state));
|
newCharArray[i] = state.convertValue(initializer.getChild(i).getValueInternal(state), Character.class);
|
||||||
}
|
}
|
||||||
} else if (arrayTypeCode == TypeCode.SHORT) {
|
} else if (arrayTypeCode == TypeCode.SHORT) {
|
||||||
short[] newShortArray = (short[]) newArray;
|
short[] newShortArray = (short[]) newArray;
|
||||||
for (int i = 0; i < newShortArray.length; i++) {
|
for (int i = 0; i < newShortArray.length; i++) {
|
||||||
newShortArray[i] = state.toShort(initializer.getChild(i).getValueInternal(state));
|
newShortArray[i] = state.convertValue(initializer.getChild(i).getValueInternal(state), Short.class);
|
||||||
}
|
}
|
||||||
} else if (arrayTypeCode == TypeCode.LONG) {
|
} else if (arrayTypeCode == TypeCode.LONG) {
|
||||||
long[] newLongArray = (long[]) newArray;
|
long[] newLongArray = (long[]) newArray;
|
||||||
for (int i = 0; i < newLongArray.length; i++) {
|
for (int i = 0; i < newLongArray.length; i++) {
|
||||||
newLongArray[i] = state.toLong(initializer.getChild(i).getValueInternal(state));
|
newLongArray[i] = state.convertValue(initializer.getChild(i).getValueInternal(state), Long.class);
|
||||||
}
|
}
|
||||||
} else if (arrayTypeCode == TypeCode.FLOAT) {
|
} else if (arrayTypeCode == TypeCode.FLOAT) {
|
||||||
float[] newFloatArray = (float[]) newArray;
|
float[] newFloatArray = (float[]) newArray;
|
||||||
for (int i = 0; i < newFloatArray.length; i++) {
|
for (int i = 0; i < newFloatArray.length; i++) {
|
||||||
newFloatArray[i] = state.toFloat(initializer.getChild(i).getValueInternal(state));
|
newFloatArray[i] = state.convertValue(initializer.getChild(i).getValueInternal(state), Float.class);
|
||||||
}
|
}
|
||||||
} else if (arrayTypeCode == TypeCode.DOUBLE) {
|
} else if (arrayTypeCode == TypeCode.DOUBLE) {
|
||||||
double[] newDoubleArray = (double[]) newArray;
|
double[] newDoubleArray = (double[]) newArray;
|
||||||
for (int i = 0; i < newDoubleArray.length; i++) {
|
for (int i = 0; i < newDoubleArray.length; i++) {
|
||||||
newDoubleArray[i] = state.toDouble(initializer.getChild(i).getValueInternal(state));
|
newDoubleArray[i] = state.convertValue(initializer.getChild(i).getValueInternal(state), Double.class);
|
||||||
}
|
}
|
||||||
} else if (arrayTypeCode == TypeCode.BYTE) {
|
} else if (arrayTypeCode == TypeCode.BYTE) {
|
||||||
byte[] newByteArray = (byte[]) newArray;
|
byte[] newByteArray = (byte[]) newArray;
|
||||||
for (int i = 0; i < newByteArray.length; i++) {
|
for (int i = 0; i < newByteArray.length; i++) {
|
||||||
newByteArray[i] = state.toByte(initializer.getChild(i).getValueInternal(state));
|
newByteArray[i] = state.convertValue(initializer.getChild(i).getValueInternal(state), Byte.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +240,6 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new ordinary object and return it.
|
* Create a new ordinary object and return it.
|
||||||
*
|
|
||||||
* @param state the expression state within which this expression is being evaluated
|
* @param state the expression state within which this expression is being evaluated
|
||||||
* @return the new object
|
* @return the new object
|
||||||
* @throws EvaluationException if there is a problem creating the object
|
* @throws EvaluationException if there is a problem creating the object
|
||||||
|
|
@ -254,41 +253,41 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
argumentTypes[i] = childValue.getClass();
|
argumentTypes[i] = childValue.getClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedExecutor != null) {
|
ConstructorExecutor executorToUse = this.cachedExecutor;
|
||||||
|
if (executorToUse != null) {
|
||||||
try {
|
try {
|
||||||
return cachedExecutor.execute(state.getEvaluationContext(), arguments);
|
return executorToUse.execute(state.getEvaluationContext(), arguments);
|
||||||
} catch (AccessException ae) {
|
}
|
||||||
|
catch (AccessException ae) {
|
||||||
// this is OK - it may have gone stale due to a class change,
|
// this is OK - it may have gone stale due to a class change,
|
||||||
// let's try to get a new one and call it before giving up
|
// let's try to get a new one and call it before giving up
|
||||||
|
this.cachedExecutor = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// either there was no accessor or it no longer exists
|
// either there was no accessor or it no longer exists
|
||||||
String typename = (String) getChild(0).getValueInternal(state);
|
String typename = (String) getChild(0).getValueInternal(state);
|
||||||
cachedExecutor = findExecutorForConstructor(typename, argumentTypes, state);
|
executorToUse = findExecutorForConstructor(typename, argumentTypes, state);
|
||||||
try {
|
try {
|
||||||
return cachedExecutor.execute(state.getEvaluationContext(), arguments);
|
return executorToUse.execute(state.getEvaluationContext(), arguments);
|
||||||
} catch (AccessException ae) {
|
}
|
||||||
|
catch (AccessException ae) {
|
||||||
throw new SpelException(ae, SpelMessages.EXCEPTION_DURING_CONSTRUCTOR_INVOCATION, typename, ae.getMessage());
|
throw new SpelException(ae, SpelMessages.EXCEPTION_DURING_CONSTRUCTOR_INVOCATION, typename, ae.getMessage());
|
||||||
} finally {
|
|
||||||
if (!useCaching) {
|
|
||||||
cachedExecutor = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Go through the list of registered constructor resolvers and see if any can find a constructor that takes the
|
* Go through the list of registered constructor resolvers and see if any can find a constructor that takes the
|
||||||
* specified set of arguments.
|
* specified set of arguments.
|
||||||
*
|
|
||||||
* @param typename the type trying to be constructed
|
* @param typename the type trying to be constructed
|
||||||
* @param argumentTypes the types of the arguments supplied that the constructor must take
|
* @param argumentTypes the types of the arguments supplied that the constructor must take
|
||||||
* @param state the current state of the expression
|
* @param state the current state of the expression
|
||||||
* @return a reusable ConstructorExecutor that can be invoked to run the constructor or null
|
* @return a reusable ConstructorExecutor that can be invoked to run the constructor or null
|
||||||
* @throws SpelException if there is a problem locating the constructor
|
* @throws SpelException if there is a problem locating the constructor
|
||||||
*/
|
*/
|
||||||
public ConstructorExecutor findExecutorForConstructor(String typename, Class<?>[] argumentTypes,
|
protected ConstructorExecutor findExecutorForConstructor(
|
||||||
ExpressionState state) throws SpelException {
|
String typename, Class<?>[] argumentTypes, ExpressionState state) throws SpelException {
|
||||||
|
|
||||||
EvaluationContext eContext = state.getEvaluationContext();
|
EvaluationContext eContext = state.getEvaluationContext();
|
||||||
List<ConstructorResolver> cResolvers = eContext.getConstructorResolvers();
|
List<ConstructorResolver> cResolvers = eContext.getConstructorResolvers();
|
||||||
if (cResolvers != null) {
|
if (cResolvers != null) {
|
||||||
|
|
@ -299,18 +298,14 @@ public class ConstructorReference extends SpelNodeImpl {
|
||||||
if (cEx != null) {
|
if (cEx != null) {
|
||||||
return cEx;
|
return cEx;
|
||||||
}
|
}
|
||||||
} catch (AccessException e) {
|
}
|
||||||
Throwable cause = e.getCause();
|
catch (AccessException ex) {
|
||||||
if (cause instanceof SpelException) {
|
throw new SpelException(ex, SpelMessages.PROBLEM_LOCATING_CONSTRUCTOR, typename,
|
||||||
throw (SpelException) cause;
|
FormatHelper.formatMethodForMessage("", argumentTypes));
|
||||||
} else {
|
|
||||||
throw new SpelException(cause, SpelMessages.PROBLEM_LOCATING_CONSTRUCTOR, typename, Utils
|
|
||||||
.formatMethodForMessage("", argumentTypes));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new SpelException(SpelMessages.CONSTRUCTOR_NOT_FOUND, typename, Utils.formatMethodForMessage("",
|
throw new SpelException(SpelMessages.CONSTRUCTOR_NOT_FOUND, typename, FormatHelper.formatMethodForMessage("",
|
||||||
argumentTypes));
|
argumentTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -21,9 +22,9 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is used for preserving positional information from the input expression.
|
* This is used for preserving positional information from the input expression.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class Dot extends SpelNodeImpl {
|
public class Dot extends SpelNodeImpl {
|
||||||
// TODO Keep Dot for the positional information or remove it?
|
// TODO Keep Dot for the positional information or remove it?
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,12 +13,17 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class EmptySpelNode extends SpelNodeImpl {
|
public class EmptySpelNode extends SpelNodeImpl {
|
||||||
|
|
||||||
public EmptySpelNode(Token payload) {
|
public EmptySpelNode(Token payload) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,18 +13,18 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.expression.spel.internal;
|
|
||||||
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods (formatters, etc) used during parsing and evaluation.
|
* Utility methods (formatters, etc) used during parsing and evaluation.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*/
|
*/
|
||||||
public class Utils {
|
class FormatHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a nice string for a given method name with specified arguments.
|
* Produce a nice string for a given method name with specified arguments.
|
||||||
*
|
|
||||||
* @param name the name of the method
|
* @param name the name of the method
|
||||||
* @param argumentTypes the types of the arguments to the method
|
* @param argumentTypes the types of the arguments to the method
|
||||||
* @return nicely formatted string, eg. foo(String,int)
|
* @return nicely formatted string, eg. foo(String,int)
|
||||||
|
|
@ -35,8 +35,9 @@ public class Utils {
|
||||||
sb.append("(");
|
sb.append("(");
|
||||||
if (argumentTypes != null) {
|
if (argumentTypes != null) {
|
||||||
for (int i = 0; i < argumentTypes.length; i++) {
|
for (int i = 0; i < argumentTypes.length; i++) {
|
||||||
if (i > 0)
|
if (i > 0) {
|
||||||
sb.append(",");
|
sb.append(",");
|
||||||
|
}
|
||||||
sb.append(argumentTypes[i].getName());
|
sb.append(argumentTypes[i].getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -47,12 +48,11 @@ public class Utils {
|
||||||
/**
|
/**
|
||||||
* Produce a nice string for a given class object. For example a string array will have the formatted name
|
* Produce a nice string for a given class object. For example a string array will have the formatted name
|
||||||
* "java.lang.String[]".
|
* "java.lang.String[]".
|
||||||
*
|
|
||||||
* @param clazz The class whose name is to be formatted
|
* @param clazz The class whose name is to be formatted
|
||||||
* @return a formatted string suitable for message inclusion
|
* @return a formatted string suitable for message inclusion
|
||||||
*/
|
*/
|
||||||
public static String formatClassnameForMessage(Class<?> clazz) {
|
public static String formatClassNameForMessage(Class<?> clazz) {
|
||||||
if (clazz==null) {
|
if (clazz == null) {
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
StringBuilder fmtd = new StringBuilder();
|
StringBuilder fmtd = new StringBuilder();
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
@ -20,13 +21,13 @@ import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.TypeConverter;
|
import org.springframework.expression.TypeConverter;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.reflection.ReflectionUtils;
|
import org.springframework.expression.spel.support.ReflectionHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function reference is of the form "#someFunction(a,b,c)". Functions may be defined in the context prior to the
|
* A function reference is of the form "#someFunction(a,b,c)". Functions may be defined in the context prior to the
|
||||||
|
|
@ -38,16 +39,19 @@ import org.springframework.expression.spel.reflection.ReflectionUtils;
|
||||||
* Functions are very simplistic, the arguments are not part of the definition (right now), so the names must be unique.
|
* Functions are very simplistic, the arguments are not part of the definition (right now), so the names must be unique.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class FunctionReference extends SpelNodeImpl {
|
public class FunctionReference extends SpelNodeImpl {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
|
||||||
public FunctionReference(Token payload) {
|
public FunctionReference(Token payload) {
|
||||||
super(payload);
|
super(payload);
|
||||||
name = payload.getText();
|
this.name = payload.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
||||||
Object o = state.lookupVariable(name);
|
Object o = state.lookupVariable(name);
|
||||||
|
|
@ -87,15 +91,11 @@ public class FunctionReference extends SpelNodeImpl {
|
||||||
|
|
||||||
// Convert arguments if necessary and remap them for varargs if required
|
// Convert arguments if necessary and remap them for varargs if required
|
||||||
if (functionArgs != null) {
|
if (functionArgs != null) {
|
||||||
EvaluationContext ctx = state.getEvaluationContext();
|
TypeConverter converter = state.getEvaluationContext().getTypeConverter();
|
||||||
TypeConverter converter = null;
|
ReflectionHelper.convertArguments(m.getParameterTypes(), m.isVarArgs(), converter, functionArgs);
|
||||||
if (ctx.getTypeUtils() != null) {
|
|
||||||
converter = ctx.getTypeUtils().getTypeConverter();
|
|
||||||
}
|
|
||||||
ReflectionUtils.convertArguments(m.getParameterTypes(), m.isVarArgs(), converter, functionArgs);
|
|
||||||
}
|
}
|
||||||
if (m.isVarArgs()) {
|
if (m.isVarArgs()) {
|
||||||
functionArgs = ReflectionUtils.setupArgumentsForVarargsInvocation(m.getParameterTypes(), functionArgs);
|
functionArgs = ReflectionHelper.setupArgumentsForVarargsInvocation(m.getParameterTypes(), functionArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,29 +13,35 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.springframework.expression.spel.SpelException;
|
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
|
||||||
|
|
||||||
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
import org.springframework.expression.spel.SpelException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class Identifier extends SpelNodeImpl {
|
public class Identifier extends SpelNodeImpl {
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
|
|
||||||
public Identifier(Token payload) {
|
public Identifier(Token payload) {
|
||||||
super(payload);
|
super(payload);
|
||||||
id = payload.getText();
|
this.id = payload.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringAST() {
|
public String toStringAST() {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getValueInternal(ExpressionState state) throws SpelException {
|
public String getValueInternal(ExpressionState state) {
|
||||||
return id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -31,6 +32,7 @@ import org.springframework.expression.spel.SpelMessages;
|
||||||
* strings/collections (lists/sets)/arrays
|
* strings/collections (lists/sets)/arrays
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class Indexer extends SpelNodeImpl {
|
public class Indexer extends SpelNodeImpl {
|
||||||
|
|
||||||
|
|
@ -48,7 +50,7 @@ public class Indexer extends SpelNodeImpl {
|
||||||
return ((Map<?, ?>) ctx).get(index);
|
return ((Map<?, ?>) ctx).get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = state.toInteger(index);
|
int idx = state.convertValue(index, Integer.class);
|
||||||
|
|
||||||
if (ctx.getClass().isArray()) {
|
if (ctx.getClass().isArray()) {
|
||||||
return accessArrayElement(ctx, idx);
|
return accessArrayElement(ctx, idx);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,14 +13,16 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expression language AST node that represents an integer literal.
|
* Expression language AST node that represents an integer literal.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class IntLiteral extends Literal {
|
public class IntLiteral extends Literal {
|
||||||
|
|
||||||
|
|
@ -33,7 +35,7 @@ public class IntLiteral extends Literal {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer getLiteralValue() {
|
public Integer getLiteralValue() {
|
||||||
return value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.expression.spel.internal;
|
|
||||||
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special object that is used to wrap a map entry/value when iterating over a map. Providing a direct way for the
|
* Special object that is used to wrap a map entry/value when iterating over a map. Providing a direct way for the
|
||||||
|
|
@ -21,7 +22,8 @@ package org.springframework.expression.spel.internal;
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*/
|
*/
|
||||||
public class KeyValuePair {
|
class KeyValuePair {
|
||||||
|
|
||||||
public Object key;
|
public Object key;
|
||||||
public Object value;
|
public Object value;
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,13 +13,14 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.WrappedELException;
|
import org.springframework.expression.spel.WrappedSpelException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common superclass for nodes representing literals (boolean, string, number, etc).
|
* Common superclass for nodes representing literals (boolean, string, number, etc).
|
||||||
|
|
@ -84,7 +85,7 @@ public abstract class Literal extends SpelNodeImpl {
|
||||||
long value = Long.parseLong(numberString, radix);
|
long value = Long.parseLong(numberString, radix);
|
||||||
return new LongLiteral(numberToken, value);
|
return new LongLiteral(numberToken, value);
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
throw new WrappedELException(new SpelException(numberToken.getCharPositionInLine(), nfe,
|
throw new WrappedSpelException(new SpelException(numberToken.getCharPositionInLine(), nfe,
|
||||||
SpelMessages.NOT_A_LONG, numberToken.getText()));
|
SpelMessages.NOT_A_LONG, numberToken.getText()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -92,7 +93,7 @@ public abstract class Literal extends SpelNodeImpl {
|
||||||
int value = Integer.parseInt(numberString, radix);
|
int value = Integer.parseInt(numberString, radix);
|
||||||
return new IntLiteral(numberToken, value);
|
return new IntLiteral(numberToken, value);
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
throw new WrappedELException(new SpelException(numberToken.getCharPositionInLine(), nfe,
|
throw new WrappedSpelException(new SpelException(numberToken.getCharPositionInLine(), nfe,
|
||||||
SpelMessages.NOT_AN_INTEGER, numberToken.getText()));
|
SpelMessages.NOT_AN_INTEGER, numberToken.getText()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,14 +13,16 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expression language AST node that represents a long integer literal.
|
* Expression language AST node that represents a long integer literal.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class LongLiteral extends Literal {
|
public class LongLiteral extends Literal {
|
||||||
|
|
||||||
|
|
@ -33,7 +35,7 @@ public class LongLiteral extends Literal {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getLiteralValue() {
|
public Long getLiteralValue() {
|
||||||
return value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,11 +13,13 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
|
|
@ -26,18 +28,25 @@ import org.springframework.expression.MethodResolver;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.internal.Utils;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class MethodReference extends SpelNodeImpl {
|
public class MethodReference extends SpelNodeImpl {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private MethodExecutor fastInvocationAccessor;
|
|
||||||
|
private volatile MethodExecutor cachedExecutor;
|
||||||
|
|
||||||
|
|
||||||
public MethodReference(Token payload) {
|
public MethodReference(Token payload) {
|
||||||
super(payload);
|
super(payload);
|
||||||
name = payload.getText();
|
name = payload.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
||||||
Object currentContext = state.getActiveContextObject();
|
Object currentContext = state.getActiveContextObject();
|
||||||
|
|
@ -50,30 +59,36 @@ public class MethodReference extends SpelNodeImpl {
|
||||||
formatMethodForMessage(name, getTypes(arguments)));
|
formatMethodForMessage(name, getTypes(arguments)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fastInvocationAccessor != null) {
|
MethodExecutor executorToUse = this.cachedExecutor;
|
||||||
|
if (executorToUse != null) {
|
||||||
try {
|
try {
|
||||||
return fastInvocationAccessor.execute(state.getEvaluationContext(), state.getActiveContextObject(),
|
return executorToUse.execute(
|
||||||
arguments);
|
state.getEvaluationContext(), state.getActiveContextObject(), arguments);
|
||||||
} catch (AccessException ae) {
|
}
|
||||||
// this is OK - it may have gone stale due to a class change, let's get a new one and retry before
|
catch (AccessException ae) {
|
||||||
// giving up
|
// this is OK - it may have gone stale due to a class change,
|
||||||
|
// let's try to get a new one and call it before giving up
|
||||||
|
this.cachedExecutor = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// either there was no accessor or it no longer existed
|
// either there was no accessor or it no longer existed
|
||||||
fastInvocationAccessor = findAccessorForMethod(name, getTypes(arguments), state);
|
executorToUse = findAccessorForMethod(this.name, getTypes(arguments), state);
|
||||||
|
this.cachedExecutor = executorToUse;
|
||||||
try {
|
try {
|
||||||
return fastInvocationAccessor.execute(state.getEvaluationContext(), state.getActiveContextObject(),
|
return executorToUse.execute(
|
||||||
arguments);
|
state.getEvaluationContext(), state.getActiveContextObject(), arguments);
|
||||||
} catch (AccessException ae) {
|
}
|
||||||
ae.printStackTrace();
|
catch (AccessException ae) {
|
||||||
throw new SpelException(getCharPositionInLine(), ae, SpelMessages.EXCEPTION_DURING_METHOD_INVOCATION, name,
|
throw new SpelException(getCharPositionInLine(), ae, SpelMessages.EXCEPTION_DURING_METHOD_INVOCATION,
|
||||||
state.getActiveContextObject().getClass().getName(), ae.getMessage());
|
this.name, state.getActiveContextObject().getClass().getName(), ae.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?>[] getTypes(Object... arguments) {
|
private Class<?>[] getTypes(Object... arguments) {
|
||||||
if (arguments == null)
|
if (arguments == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
Class<?>[] argumentTypes = new Class[arguments.length];
|
Class<?>[] argumentTypes = new Class[arguments.length];
|
||||||
for (int i = 0; i < arguments.length; i++) {
|
for (int i = 0; i < arguments.length; i++) {
|
||||||
argumentTypes[i] = arguments[i].getClass();
|
argumentTypes[i] = arguments[i].getClass();
|
||||||
|
|
@ -120,37 +135,33 @@ public class MethodReference extends SpelNodeImpl {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final MethodExecutor findAccessorForMethod(String name, Class<?>[] argumentTypes, ExpressionState state)
|
|
||||||
|
protected MethodExecutor findAccessorForMethod(String name, Class<?>[] argumentTypes, ExpressionState state)
|
||||||
throws SpelException {
|
throws SpelException {
|
||||||
|
|
||||||
Object contextObject = state.getActiveContextObject();
|
Object contextObject = state.getActiveContextObject();
|
||||||
EvaluationContext eContext = state.getEvaluationContext();
|
EvaluationContext eContext = state.getEvaluationContext();
|
||||||
if (contextObject == null) {
|
if (contextObject == null) {
|
||||||
throw new SpelException(SpelMessages.ATTEMPTED_METHOD_CALL_ON_NULL_CONTEXT_OBJECT, Utils
|
throw new SpelException(SpelMessages.ATTEMPTED_METHOD_CALL_ON_NULL_CONTEXT_OBJECT,
|
||||||
.formatMethodForMessage(name, argumentTypes));
|
FormatHelper.formatMethodForMessage(name, argumentTypes));
|
||||||
}
|
}
|
||||||
List<MethodResolver> mResolvers = eContext.getMethodResolvers();
|
List<MethodResolver> mResolvers = eContext.getMethodResolvers();
|
||||||
if (mResolvers != null) {
|
if (mResolvers != null) {
|
||||||
for (MethodResolver methodResolver : mResolvers) {
|
for (MethodResolver methodResolver : mResolvers) {
|
||||||
try {
|
try {
|
||||||
MethodExecutor cEx = methodResolver.resolve(state.getEvaluationContext(), contextObject, name,
|
MethodExecutor cEx = methodResolver.resolve(
|
||||||
argumentTypes);
|
state.getEvaluationContext(), contextObject, name, argumentTypes);
|
||||||
if (cEx != null)
|
if (cEx != null) {
|
||||||
return cEx;
|
return cEx;
|
||||||
} catch (AccessException e) {
|
|
||||||
Throwable cause = e.getCause();
|
|
||||||
if (cause instanceof SpelException) {
|
|
||||||
throw (SpelException) cause;
|
|
||||||
} else {
|
|
||||||
throw new SpelException(cause, SpelMessages.PROBLEM_LOCATING_METHOD, name, contextObject
|
|
||||||
.getClass());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (AccessException ex) {
|
||||||
|
throw new SpelException(ex, SpelMessages.PROBLEM_LOCATING_METHOD, name, contextObject.getClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new SpelException(SpelMessages.METHOD_NOT_FOUND, Utils.formatMethodForMessage(name, argumentTypes), Utils
|
throw new SpelException(SpelMessages.METHOD_NOT_FOUND, FormatHelper.formatMethodForMessage(name, argumentTypes),
|
||||||
.formatClassnameForMessage(contextObject instanceof Class ? ((Class<?>) contextObject) : contextObject
|
FormatHelper.formatClassNameForMessage(contextObject instanceof Class ? ((Class<?>) contextObject) : contextObject.getClass()));
|
||||||
.getClass()));
|
|
||||||
// (contextObject instanceof Class ? ((Class<?>) contextObject).getName() : contextObject.getClass()
|
|
||||||
// .getName()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,10 +13,15 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class NullLiteral extends Literal {
|
public class NullLiteral extends Literal {
|
||||||
|
|
||||||
public NullLiteral(Token payload) {
|
public NullLiteral(Token payload) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -22,8 +23,9 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
/**
|
/**
|
||||||
* Common supertype for operators that operate on either one or two operands. In the case of multiply or divide there
|
* Common supertype for operators that operate on either one or two operands. In the case of multiply or divide there
|
||||||
* would be two operands, but for unary plus or minus, there is only one.
|
* would be two operands, but for unary plus or minus, there is only one.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public abstract class Operator extends SpelNodeImpl {
|
public abstract class Operator extends SpelNodeImpl {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -22,8 +23,9 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the boolean AND operation.
|
* Represents the boolean AND operation.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorAnd extends Operator {
|
public class OperatorAnd extends Operator {
|
||||||
|
|
||||||
|
|
@ -42,8 +44,9 @@ public class OperatorAnd extends Operator {
|
||||||
boolean rightValue;
|
boolean rightValue;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
leftValue = state.toBoolean(getLeftOperand().getValueInternal(state));
|
leftValue = state.convertValue(getLeftOperand().getValueInternal(state), Boolean.class);
|
||||||
} catch (SpelException ee) {
|
}
|
||||||
|
catch (SpelException ee) {
|
||||||
ee.setPosition(getLeftOperand().getCharPositionInLine());
|
ee.setPosition(getLeftOperand().getCharPositionInLine());
|
||||||
throw ee;
|
throw ee;
|
||||||
}
|
}
|
||||||
|
|
@ -53,8 +56,9 @@ public class OperatorAnd extends Operator {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
rightValue = state.toBoolean(getRightOperand().getValueInternal(state));
|
rightValue = state.convertValue(getRightOperand().getValueInternal(state), Boolean.class);
|
||||||
} catch (SpelException ee) {
|
}
|
||||||
|
catch (SpelException ee) {
|
||||||
ee.setPosition(getRightOperand().getCharPositionInLine());
|
ee.setPosition(getRightOperand().getCharPositionInLine());
|
||||||
throw ee;
|
throw ee;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -30,6 +31,7 @@ import org.springframework.expression.spel.SpelMessages;
|
||||||
* in the list. The definition of between being inclusive follows the SQL BETWEEN definition.
|
* in the list. The definition of between being inclusive follows the SQL BETWEEN definition.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorBetween extends Operator {
|
public class OperatorBetween extends Operator {
|
||||||
|
|
||||||
|
|
@ -45,7 +47,6 @@ public class OperatorBetween extends Operator {
|
||||||
/**
|
/**
|
||||||
* Returns a boolean based on whether a value is in the range expressed. The first operand is any value whilst the
|
* Returns a boolean based on whether a value is in the range expressed. The first operand is any value whilst the
|
||||||
* second is a list of two values - those two values being the bounds allowed for the first operand (inclusive).
|
* second is a list of two values - those two values being the bounds allowed for the first operand (inclusive).
|
||||||
*
|
|
||||||
* @param state the expression state
|
* @param state the expression state
|
||||||
* @return true if the left operand is in the range specified, false otherwise
|
* @return true if the left operand is in the range specified, false otherwise
|
||||||
* @throws EvaluationException if there is a problem evaluating the expression
|
* @throws EvaluationException if there is a problem evaluating the expression
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -21,9 +22,10 @@ import org.springframework.expression.Operation;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements division operator
|
* Implements division operator.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorDivide extends Operator {
|
public class OperatorDivide extends Operator {
|
||||||
|
|
||||||
|
|
@ -44,17 +46,16 @@ public class OperatorDivide extends Operator {
|
||||||
Number op1 = (Number) operandOne;
|
Number op1 = (Number) operandOne;
|
||||||
Number op2 = (Number) operandTwo;
|
Number op2 = (Number) operandTwo;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
Double result = op1.doubleValue() / op2.doubleValue();
|
return op1.doubleValue() / op2.doubleValue();
|
||||||
return result;
|
}
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
Float result = op1.floatValue() / op2.floatValue();
|
return op1.floatValue() / op2.floatValue();
|
||||||
return result;
|
}
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
Long result = op1.longValue() / op2.longValue();
|
return op1.longValue() / op2.longValue();
|
||||||
return result;
|
}
|
||||||
} else { // TODO what about non-int result of the division?
|
else { // TODO what about non-int result of the division?
|
||||||
Integer result = op1.intValue() / op2.intValue();
|
return op1.intValue() / op2.intValue();
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state.operate(Operation.DIVIDE, operandOne, operandTwo);
|
return state.operate(Operation.DIVIDE, operandOne, operandTwo);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -21,8 +22,9 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements equality operator.
|
* Implements equality operator.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorEquality extends Operator {
|
public class OperatorEquality extends Operator {
|
||||||
|
|
||||||
|
|
@ -44,11 +46,14 @@ public class OperatorEquality extends Operator {
|
||||||
Number op2 = (Number) right;
|
Number op2 = (Number) right;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
return op1.doubleValue() == op2.doubleValue();
|
return op1.doubleValue() == op2.doubleValue();
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
}
|
||||||
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
return op1.floatValue() == op2.floatValue();
|
return op1.floatValue() == op2.floatValue();
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
}
|
||||||
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
return op1.longValue() == op2.longValue();
|
return op1.longValue() == op2.longValue();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return op1.intValue() == op2.intValue();
|
return op1.intValue() == op2.intValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -20,9 +21,10 @@ import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements greater than operator.
|
* Implements greater-than operator.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorGreaterThan extends Operator {
|
public class OperatorGreaterThan extends Operator {
|
||||||
|
|
||||||
|
|
@ -44,11 +46,14 @@ public class OperatorGreaterThan extends Operator {
|
||||||
Number op2 = (Number) right;
|
Number op2 = (Number) right;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
return op1.doubleValue() > op2.doubleValue();
|
return op1.doubleValue() > op2.doubleValue();
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
}
|
||||||
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
return op1.floatValue() > op2.floatValue();
|
return op1.floatValue() > op2.floatValue();
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
}
|
||||||
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
return op1.longValue() > op2.longValue();
|
return op1.longValue() > op2.longValue();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return op1.intValue() > op2.intValue();
|
return op1.intValue() > op2.intValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -20,9 +21,10 @@ import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements greater than or equal operator.
|
* Implements greater-than-or-equal operator.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorGreaterThanOrEqual extends Operator {
|
public class OperatorGreaterThanOrEqual extends Operator {
|
||||||
|
|
||||||
|
|
@ -44,11 +46,14 @@ public class OperatorGreaterThanOrEqual extends Operator {
|
||||||
Number op2 = (Number) right;
|
Number op2 = (Number) right;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
return op1.doubleValue() >= op2.doubleValue();
|
return op1.doubleValue() >= op2.doubleValue();
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
}
|
||||||
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
return op1.floatValue() >= op2.floatValue();
|
return op1.floatValue() >= op2.floatValue();
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
}
|
||||||
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
return op1.longValue() >= op2.longValue();
|
return op1.longValue() >= op2.longValue();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return op1.intValue() >= op2.intValue();
|
return op1.intValue() >= op2.intValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -20,9 +21,10 @@ import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the not-equal operator
|
* Implements the not-equal operator.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorInequality extends Operator {
|
public class OperatorInequality extends Operator {
|
||||||
|
|
||||||
|
|
@ -44,11 +46,14 @@ public class OperatorInequality extends Operator {
|
||||||
Number op2 = (Number) right;
|
Number op2 = (Number) right;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
return op1.doubleValue() != op2.doubleValue();
|
return op1.doubleValue() != op2.doubleValue();
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
}
|
||||||
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
return op1.floatValue() != op2.floatValue();
|
return op1.floatValue() != op2.floatValue();
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
}
|
||||||
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
return op1.longValue() != op2.longValue();
|
return op1.longValue() != op2.longValue();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return op1.intValue() != op2.intValue();
|
return op1.intValue() != op2.intValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,19 +13,22 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The operator 'instanceof' checks if an object is of the class specified in the right hand operand, in the same way
|
* The operator 'instanceof' checks if an object is of the class specified in the right hand operand,
|
||||||
* that instanceof does in Java.
|
* in the same way that <code>instanceof</code> does in Java.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorInstanceof extends Operator {
|
public class OperatorInstanceof extends Operator {
|
||||||
|
|
||||||
|
|
@ -39,9 +42,8 @@ public class OperatorInstanceof extends Operator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare the left operand to see it is an instance of the type specified as the right operand. The right operand
|
* Compare the left operand to see it is an instance of the type specified as the right operand.
|
||||||
* must be a class.
|
* The right operand must be a class.
|
||||||
*
|
|
||||||
* @param state the expression state
|
* @param state the expression state
|
||||||
* @return true if the left operand is an instanceof of the right operand, otherwise false
|
* @return true if the left operand is an instanceof of the right operand, otherwise false
|
||||||
* @throws EvaluationException if there is a problem evaluating the expression
|
* @throws EvaluationException if there is a problem evaluating the expression
|
||||||
|
|
@ -51,11 +53,12 @@ public class OperatorInstanceof extends Operator {
|
||||||
Object left = getLeftOperand().getValueInternal(state);
|
Object left = getLeftOperand().getValueInternal(state);
|
||||||
Object right = getRightOperand().getValueInternal(state);
|
Object right = getRightOperand().getValueInternal(state);
|
||||||
if (left == null) {
|
if (left == null) {
|
||||||
return false; // null is not an instanceof anything
|
return false; // null is not an instanceof anything
|
||||||
}
|
}
|
||||||
if (right == null || !(right instanceof Class<?>)) {
|
if (right == null || !(right instanceof Class<?>)) {
|
||||||
throw new SpelException(getRightOperand().getCharPositionInLine(),
|
throw new SpelException(getRightOperand().getCharPositionInLine(),
|
||||||
SpelMessages.INSTANCEOF_OPERATOR_NEEDS_CLASS_OPERAND, (right == null ? "null" : right.getClass().getName()));
|
SpelMessages.INSTANCEOF_OPERATOR_NEEDS_CLASS_OPERAND,
|
||||||
|
(right == null ? "null" : right.getClass().getName()));
|
||||||
}
|
}
|
||||||
Class<?> rightClass = (Class<?>) right;
|
Class<?> rightClass = (Class<?>) right;
|
||||||
return rightClass.isAssignableFrom(left.getClass());
|
return rightClass.isAssignableFrom(left.getClass());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -20,9 +21,10 @@ import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the less than operator
|
* Implements the less-than operator.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorLessThan extends Operator {
|
public class OperatorLessThan extends Operator {
|
||||||
|
|
||||||
|
|
@ -44,11 +46,14 @@ public class OperatorLessThan extends Operator {
|
||||||
Number op2 = (Number) right;
|
Number op2 = (Number) right;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
return op1.doubleValue() < op2.doubleValue();
|
return op1.doubleValue() < op2.doubleValue();
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
}
|
||||||
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
return op1.floatValue() < op2.floatValue();
|
return op1.floatValue() < op2.floatValue();
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
}
|
||||||
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
return op1.longValue() < op2.longValue();
|
return op1.longValue() < op2.longValue();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return op1.intValue() < op2.intValue();
|
return op1.intValue() < op2.intValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -20,9 +21,10 @@ import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the less than or equal operator
|
* Implements the less-than-or-equal operator.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorLessThanOrEqual extends Operator {
|
public class OperatorLessThanOrEqual extends Operator {
|
||||||
|
|
||||||
|
|
@ -39,11 +41,14 @@ public class OperatorLessThanOrEqual extends Operator {
|
||||||
Number op2 = (Number) right;
|
Number op2 = (Number) right;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
return op1.doubleValue() <= op2.doubleValue();
|
return op1.doubleValue() <= op2.doubleValue();
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
}
|
||||||
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
return op1.floatValue() <= op2.floatValue();
|
return op1.floatValue() <= op2.floatValue();
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
}
|
||||||
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
return op1.longValue() <= op2.longValue();
|
return op1.longValue() <= op2.longValue();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return op1.intValue() <= op2.intValue();
|
return op1.intValue() <= op2.intValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
@ -28,8 +29,9 @@ import org.springframework.expression.spel.SpelMessages;
|
||||||
/**
|
/**
|
||||||
* Implements the matches operator. Matches takes two operands. The first is a string and the second is a java regex. It
|
* Implements the matches operator. Matches takes two operands. The first is a string and the second is a java regex. It
|
||||||
* will return true when getValue() is called if the first operand matches the regex.
|
* will return true when getValue() is called if the first operand matches the regex.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorMatches extends Operator {
|
public class OperatorMatches extends Operator {
|
||||||
|
|
||||||
|
|
@ -44,7 +46,6 @@ public class OperatorMatches extends Operator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the first operand matches the regex specified as the second operand.
|
* Check the first operand matches the regex specified as the second operand.
|
||||||
*
|
|
||||||
* @param state the expression state
|
* @param state the expression state
|
||||||
* @return true if the first operand matches the regex specified as the second operand, otherwise false
|
* @return true if the first operand matches the regex specified as the second operand, otherwise false
|
||||||
* @throws EvaluationException if there is a problem evaluating the expression (e.g. the regex is invalid)
|
* @throws EvaluationException if there is a problem evaluating the expression (e.g. the regex is invalid)
|
||||||
|
|
@ -67,7 +68,8 @@ public class OperatorMatches extends Operator {
|
||||||
Pattern pattern = Pattern.compile((String) right);
|
Pattern pattern = Pattern.compile((String) right);
|
||||||
Matcher matcher = pattern.matcher((String) left);
|
Matcher matcher = pattern.matcher((String) left);
|
||||||
return matcher.matches();
|
return matcher.matches();
|
||||||
} catch (PatternSyntaxException pse) {
|
}
|
||||||
|
catch (PatternSyntaxException pse) {
|
||||||
throw new SpelException(rightOp.getCharPositionInLine(), pse, SpelMessages.INVALID_PATTERN, right);
|
throw new SpelException(rightOp.getCharPositionInLine(), pse, SpelMessages.INVALID_PATTERN, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -24,8 +25,9 @@ import org.springframework.expression.spel.SpelMessages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the minus operator. If there is only one operand it is a unary minus.
|
* Implements the minus operator. If there is only one operand it is a unary minus.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorMinus extends Operator {
|
public class OperatorMinus extends Operator {
|
||||||
|
|
||||||
|
|
@ -55,41 +57,41 @@ public class OperatorMinus extends Operator {
|
||||||
if (left instanceof Number) {
|
if (left instanceof Number) {
|
||||||
Number n = (Number) left;
|
Number n = (Number) left;
|
||||||
if (left instanceof Double) {
|
if (left instanceof Double) {
|
||||||
Double result = 0 - n.doubleValue();
|
return 0 - n.doubleValue();
|
||||||
return result;
|
}
|
||||||
} else if (left instanceof Float) {
|
else if (left instanceof Float) {
|
||||||
Float result = 0 - n.floatValue();
|
return 0 - n.floatValue();
|
||||||
return result;
|
}
|
||||||
} else if (left instanceof Long) {
|
else if (left instanceof Long) {
|
||||||
Long result = 0 - n.longValue();
|
return 0 - n.longValue();
|
||||||
return result;
|
}
|
||||||
} else {
|
else {
|
||||||
Integer result = 0 - n.intValue();
|
return 0 - n.intValue();
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new SpelException(SpelMessages.CANNOT_NEGATE_TYPE, left.getClass().getName());
|
throw new SpelException(SpelMessages.CANNOT_NEGATE_TYPE, left.getClass().getName());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Object left = leftOp.getValueInternal(state);
|
Object left = leftOp.getValueInternal(state);
|
||||||
Object right = rightOp.getValueInternal(state);
|
Object right = rightOp.getValueInternal(state);
|
||||||
if (left instanceof Number && right instanceof Number) {
|
if (left instanceof Number && right instanceof Number) {
|
||||||
Number op1 = (Number) left;
|
Number op1 = (Number) left;
|
||||||
Number op2 = (Number) right;
|
Number op2 = (Number) right;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
Double result = op1.doubleValue() - op2.doubleValue();
|
return op1.doubleValue() - op2.doubleValue();
|
||||||
return result;
|
}
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
Float result = op1.floatValue() - op2.floatValue();
|
return op1.floatValue() - op2.floatValue();
|
||||||
return result;
|
}
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
Long result = op1.longValue() - op2.longValue();
|
return op1.longValue() - op2.longValue();
|
||||||
return result;
|
}
|
||||||
} else {
|
else {
|
||||||
Integer result = op1.intValue() - op2.intValue();
|
return op1.intValue() - op2.intValue();
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state.operate(Operation.SUBTRACT, left, right);
|
return state.operate(Operation.SUBTRACT, left, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -22,8 +23,9 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the modulus operator.
|
* Implements the modulus operator.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorModulus extends Operator {
|
public class OperatorModulus extends Operator {
|
||||||
|
|
||||||
|
|
@ -44,17 +46,16 @@ public class OperatorModulus extends Operator {
|
||||||
Number op1 = (Number) operandOne;
|
Number op1 = (Number) operandOne;
|
||||||
Number op2 = (Number) operandTwo;
|
Number op2 = (Number) operandTwo;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
Double result = op1.doubleValue() % op2.doubleValue();
|
return op1.doubleValue() % op2.doubleValue();
|
||||||
return result;
|
}
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
Float result = op1.floatValue() % op2.floatValue();
|
return op1.floatValue() % op2.floatValue();
|
||||||
return result;
|
}
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
Long result = op1.longValue() % op2.longValue();
|
return op1.longValue() % op2.longValue();
|
||||||
return result;
|
}
|
||||||
} else {
|
else {
|
||||||
Integer result = op1.intValue() % op2.intValue();
|
return op1.intValue() % op2.intValue();
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return state.operate(Operation.MODULUS, operandOne, operandTwo);
|
return state.operate(Operation.MODULUS, operandOne, operandTwo);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -23,14 +24,15 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
/**
|
/**
|
||||||
* Implements the multiply operator. Conversions and promotions:
|
* Implements the multiply operator. Conversions and promotions:
|
||||||
* http://java.sun.com/docs/books/jls/third_edition/html/conversions.html Section 5.6.2:
|
* http://java.sun.com/docs/books/jls/third_edition/html/conversions.html Section 5.6.2:
|
||||||
*
|
*
|
||||||
* If any of the operands is of a reference type, unboxing conversion (¤5.1.8) is performed. Then:<br>
|
* <p>If any of the operands is of a reference type, unboxing conversion (¤5.1.8) is performed. Then:<br>
|
||||||
* If either operand is of type double, the other is converted to double.<br>
|
* If either operand is of type double, the other is converted to double.<br>
|
||||||
* Otherwise, if either operand is of type float, the other is converted to float.<br>
|
* Otherwise, if either operand is of type float, the other is converted to float.<br>
|
||||||
* Otherwise, if either operand is of type long, the other is converted to long.<br>
|
* Otherwise, if either operand is of type long, the other is converted to long.<br>
|
||||||
* Otherwise, both operands are converted to type int.
|
* Otherwise, both operands are converted to type int.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorMultiply extends Operator {
|
public class OperatorMultiply extends Operator {
|
||||||
|
|
||||||
|
|
@ -55,20 +57,20 @@ public class OperatorMultiply extends Operator {
|
||||||
Number op1 = (Number) operandOne;
|
Number op1 = (Number) operandOne;
|
||||||
Number op2 = (Number) operandTwo;
|
Number op2 = (Number) operandTwo;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
Double result = op1.doubleValue() * op2.doubleValue();
|
return op1.doubleValue() * op2.doubleValue();
|
||||||
return result;
|
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
|
||||||
Float result = op1.floatValue() * op2.floatValue();
|
|
||||||
return result;
|
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
|
||||||
Long result = op1.longValue() * op2.longValue();
|
|
||||||
return result;
|
|
||||||
} else { // promote to int
|
|
||||||
Integer result = op1.intValue() * op2.intValue();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
} else if (operandOne instanceof String && operandTwo instanceof Integer) {
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
int repeats = ((Integer) operandTwo).intValue();
|
return op1.floatValue() * op2.floatValue();
|
||||||
|
}
|
||||||
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
|
return op1.longValue() * op2.longValue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return op1.intValue() * op2.intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (operandOne instanceof String && operandTwo instanceof Integer) {
|
||||||
|
int repeats = (Integer) operandTwo;
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
for (int i = 0; i < repeats; i++) {
|
for (int i = 0; i < repeats; i++) {
|
||||||
result.append(operandOne);
|
result.append(operandOne);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -20,6 +21,12 @@ import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a NOT operation.
|
||||||
|
*
|
||||||
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class OperatorNot extends SpelNodeImpl { // Not is a unary operator so do not extend BinaryOperator
|
public class OperatorNot extends SpelNodeImpl { // Not is a unary operator so do not extend BinaryOperator
|
||||||
|
|
||||||
public OperatorNot(Token payload) {
|
public OperatorNot(Token payload) {
|
||||||
|
|
@ -29,9 +36,10 @@ public class OperatorNot extends SpelNodeImpl { // Not is a unary operator so do
|
||||||
@Override
|
@Override
|
||||||
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
||||||
try {
|
try {
|
||||||
boolean value = state.toBoolean(getChild(0).getValueInternal(state));
|
boolean value = state.convertValue(getChild(0).getValueInternal(state), Boolean.class);
|
||||||
return !value;
|
return !value;
|
||||||
} catch (SpelException see) {
|
}
|
||||||
|
catch (SpelException see) {
|
||||||
see.setPosition(getChild(0).getCharPositionInLine());
|
see.setPosition(getChild(0).getCharPositionInLine());
|
||||||
throw see;
|
throw see;
|
||||||
}
|
}
|
||||||
|
|
@ -48,4 +56,5 @@ public class OperatorNot extends SpelNodeImpl { // Not is a unary operator so do
|
||||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -22,8 +23,9 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the boolean OR operation.
|
* Represents the boolean OR operation.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class OperatorOr extends Operator {
|
public class OperatorOr extends Operator {
|
||||||
|
|
||||||
|
|
@ -41,18 +43,21 @@ public class OperatorOr extends Operator {
|
||||||
boolean leftValue;
|
boolean leftValue;
|
||||||
boolean rightValue;
|
boolean rightValue;
|
||||||
try {
|
try {
|
||||||
leftValue = state.toBoolean(getLeftOperand().getValueInternal(state));
|
leftValue = state.convertValue(getLeftOperand().getValueInternal(state), Boolean.class);
|
||||||
} catch (SpelException see) {
|
}
|
||||||
|
catch (SpelException see) {
|
||||||
see.setPosition(getLeftOperand().getCharPositionInLine());
|
see.setPosition(getLeftOperand().getCharPositionInLine());
|
||||||
throw see;
|
throw see;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leftValue == true)
|
if (leftValue == true) {
|
||||||
return true; // no need to evaluate right operand
|
return true; // no need to evaluate right operand
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
rightValue = state.toBoolean(getRightOperand().getValueInternal(state));
|
rightValue = state.convertValue(getRightOperand().getValueInternal(state), Boolean.class);
|
||||||
} catch (SpelException see) {
|
}
|
||||||
|
catch (SpelException see) {
|
||||||
see.setPosition(getRightOperand().getCharPositionInLine());
|
see.setPosition(getRightOperand().getCharPositionInLine());
|
||||||
throw see;
|
throw see;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,13 +13,19 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.Operation;
|
import org.springframework.expression.Operation;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class OperatorPlus extends Operator {
|
public class OperatorPlus extends Operator {
|
||||||
|
|
||||||
public OperatorPlus(Token payload) {
|
public OperatorPlus(Token payload) {
|
||||||
|
|
@ -33,41 +39,40 @@ public class OperatorPlus extends Operator {
|
||||||
if (rightOp == null) { // If only one operand, then this is unary plus
|
if (rightOp == null) { // If only one operand, then this is unary plus
|
||||||
Object operandOne = leftOp.getValueInternal(state);
|
Object operandOne = leftOp.getValueInternal(state);
|
||||||
if (operandOne instanceof Number) {
|
if (operandOne instanceof Number) {
|
||||||
return new Integer(((Number) operandOne).intValue());
|
return ((Number) operandOne).intValue();
|
||||||
}
|
}
|
||||||
return state.operate(Operation.ADD, operandOne, null);
|
return state.operate(Operation.ADD, operandOne, null);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Object operandOne = leftOp.getValueInternal(state);
|
Object operandOne = leftOp.getValueInternal(state);
|
||||||
Object operandTwo = rightOp.getValueInternal(state);
|
Object operandTwo = rightOp.getValueInternal(state);
|
||||||
if (operandOne instanceof Number && operandTwo instanceof Number) {
|
if (operandOne instanceof Number && operandTwo instanceof Number) {
|
||||||
Number op1 = (Number) operandOne;
|
Number op1 = (Number) operandOne;
|
||||||
Number op2 = (Number) operandTwo;
|
Number op2 = (Number) operandTwo;
|
||||||
if (op1 instanceof Double || op2 instanceof Double) {
|
if (op1 instanceof Double || op2 instanceof Double) {
|
||||||
Double result = op1.doubleValue() + op2.doubleValue();
|
return op1.doubleValue() + op2.doubleValue();
|
||||||
return result;
|
|
||||||
} else if (op1 instanceof Float || op2 instanceof Float) {
|
|
||||||
Float result = op1.floatValue() + op2.floatValue();
|
|
||||||
return result;
|
|
||||||
} else if (op1 instanceof Long || op2 instanceof Long) {
|
|
||||||
Long result = op1.longValue() + op2.longValue();
|
|
||||||
return result;
|
|
||||||
} else { // TODO what about overflow?
|
|
||||||
Integer result = op1.intValue() + op2.intValue();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
} else if (operandOne instanceof String && operandTwo instanceof String) {
|
else if (op1 instanceof Float || op2 instanceof Float) {
|
||||||
|
return op1.floatValue() + op2.floatValue();
|
||||||
|
}
|
||||||
|
else if (op1 instanceof Long || op2 instanceof Long) {
|
||||||
|
return op1.longValue() + op2.longValue();
|
||||||
|
}
|
||||||
|
else { // TODO what about overflow?
|
||||||
|
return op1.intValue() + op2.intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (operandOne instanceof String && operandTwo instanceof String) {
|
||||||
return new StringBuilder((String) operandOne).append((String) operandTwo).toString();
|
return new StringBuilder((String) operandOne).append((String) operandTwo).toString();
|
||||||
} else if (operandOne instanceof String && operandTwo instanceof Integer) {
|
}
|
||||||
|
else if (operandOne instanceof String && operandTwo instanceof Integer) {
|
||||||
String l = (String) operandOne;
|
String l = (String) operandOne;
|
||||||
Integer i = (Integer) operandTwo;
|
Integer i = (Integer) operandTwo;
|
||||||
|
|
||||||
// implements character + int (ie. a + 1 = b)
|
// implements character + int (ie. a + 1 = b)
|
||||||
if (l.length() == 1) {
|
if (l.length() == 1) {
|
||||||
Character c = new Character((char) (new Character(l.charAt(0)) + i));
|
return Character.toString((char) (l.charAt(0) + i));
|
||||||
return c.toString();
|
|
||||||
}
|
}
|
||||||
|
return new StringBuilder(l).append(i).toString();
|
||||||
return new StringBuilder((String) operandOne).append(((Integer) operandTwo).toString()).toString();
|
|
||||||
}
|
}
|
||||||
return state.operate(Operation.ADD, operandOne, operandTwo);
|
return state.operate(Operation.ADD, operandOne, operandTwo);
|
||||||
}
|
}
|
||||||
|
|
@ -80,9 +85,10 @@ public class OperatorPlus extends Operator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringAST() {
|
public String toStringAST() {
|
||||||
if (getRightOperand() == null) { // unary plus
|
if (getRightOperand() == null) { // unary plus
|
||||||
return new StringBuilder().append("+").append(getLeftOperand()).toString();
|
return new StringBuilder().append("+").append(getLeftOperand()).toString();
|
||||||
}
|
}
|
||||||
return super.toStringAST();
|
return super.toStringAST();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -25,7 +26,7 @@ import org.springframework.expression.spel.ExpressionState;
|
||||||
* information for messages/etc.
|
* information for messages/etc.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class Placeholder extends SpelNodeImpl {
|
public class Placeholder extends SpelNodeImpl {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -21,11 +22,11 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
|
||||||
import org.springframework.expression.spel.internal.KeyValuePair;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents projection, where a given operation is performed on all elements in some input sequence, returning
|
* Represents projection, where a given operation is performed on all elements in some input sequence, returning
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,84 +13,87 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
import org.springframework.expression.AccessException;
|
||||||
import org.springframework.expression.CacheablePropertyAccessor;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.PropertyAccessor;
|
import org.springframework.expression.PropertyAccessor;
|
||||||
import org.springframework.expression.PropertyReaderExecutor;
|
|
||||||
import org.springframework.expression.PropertyWriterExecutor;
|
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.internal.Utils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a simple property or field reference.
|
* Represents a simple property or field reference.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class PropertyOrFieldReference extends SpelNodeImpl {
|
public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||||
|
|
||||||
public static boolean useCaching = true;
|
private final String name;
|
||||||
|
|
||||||
|
private volatile PropertyAccessor cachedReadAccessor;
|
||||||
|
|
||||||
|
private volatile PropertyAccessor cachedWriteAccessor;
|
||||||
|
|
||||||
private final Object name;
|
|
||||||
private PropertyReaderExecutor cachedReaderExecutor;
|
|
||||||
private PropertyWriterExecutor cachedWriterExecutor;
|
|
||||||
|
|
||||||
public PropertyOrFieldReference(Token payload) {
|
public PropertyOrFieldReference(Token payload) {
|
||||||
super(payload);
|
super(payload);
|
||||||
name = payload.getText();
|
this.name = payload.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueInternal(ExpressionState state) throws SpelException {
|
public Object getValueInternal(ExpressionState state) throws SpelException {
|
||||||
return readProperty(state, name);
|
return readProperty(state, this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(ExpressionState state, Object newValue) throws SpelException {
|
public void setValue(ExpressionState state, Object newValue) throws SpelException {
|
||||||
writeProperty(state, name, newValue);
|
writeProperty(state, this.name, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWritable(ExpressionState state) throws SpelException {
|
public boolean isWritable(ExpressionState state) throws SpelException {
|
||||||
return isWritableProperty(name, state);
|
return isWritableProperty(this.name, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringAST() {
|
public String toStringAST() {
|
||||||
return name.toString();
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to read the named property from the current context object.
|
* Attempt to read the named property from the current context object.
|
||||||
*
|
|
||||||
* @param state the evaluation state
|
* @param state the evaluation state
|
||||||
* @param name the name of the property
|
* @param name the name of the property
|
||||||
* @return the value of the property
|
* @return the value of the property
|
||||||
* @throws SpelException if any problem accessing the property or it cannot be found
|
* @throws SpelException if any problem accessing the property or it cannot be found
|
||||||
*/
|
*/
|
||||||
private Object readProperty(ExpressionState state, Object name) throws SpelException {
|
private Object readProperty(ExpressionState state, String name) throws SpelException {
|
||||||
Object contextObject = state.getActiveContextObject();
|
Object contextObject = state.getActiveContextObject();
|
||||||
EvaluationContext eContext = state.getEvaluationContext();
|
EvaluationContext eContext = state.getEvaluationContext();
|
||||||
|
|
||||||
if (cachedReaderExecutor != null) {
|
PropertyAccessor accessorToUse = this.cachedReadAccessor;
|
||||||
|
if (accessorToUse != null) {
|
||||||
try {
|
try {
|
||||||
return cachedReaderExecutor.execute(state.getEvaluationContext(), contextObject);
|
return accessorToUse.read(state.getEvaluationContext(), contextObject, name);
|
||||||
} catch (AccessException ae) {
|
}
|
||||||
|
catch (AccessException ae) {
|
||||||
// this is OK - it may have gone stale due to a class change,
|
// this is OK - it may have gone stale due to a class change,
|
||||||
// let's try to get a new one and call it before giving up
|
// let's try to get a new one and call it before giving up
|
||||||
|
this.cachedReadAccessor = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> contextObjectClass = getObjectClass(contextObject);
|
Class<?> contextObjectClass = getObjectClass(contextObject);
|
||||||
|
|
||||||
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObjectClass, state);
|
List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObjectClass, state);
|
||||||
|
|
||||||
// Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
|
// Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
|
||||||
|
|
@ -99,47 +102,34 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||||
if (accessorsToTry != null) {
|
if (accessorsToTry != null) {
|
||||||
try {
|
try {
|
||||||
for (PropertyAccessor accessor : accessorsToTry) {
|
for (PropertyAccessor accessor : accessorsToTry) {
|
||||||
if (accessor instanceof CacheablePropertyAccessor) {
|
if (accessor.canRead(eContext, contextObject, name)) {
|
||||||
cachedReaderExecutor = ((CacheablePropertyAccessor) accessor).getReaderAccessor(eContext,
|
this.cachedReadAccessor = accessor;
|
||||||
contextObject, name);
|
return accessor.read(eContext, contextObject, name);
|
||||||
if (cachedReaderExecutor != null) {
|
|
||||||
try {
|
|
||||||
return cachedReaderExecutor.execute(state.getEvaluationContext(), contextObject);
|
|
||||||
} catch (AccessException ae) {
|
|
||||||
cachedReaderExecutor = null;
|
|
||||||
throw ae;
|
|
||||||
} finally {
|
|
||||||
if (!useCaching) {
|
|
||||||
cachedReaderExecutor = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (accessor.canRead(eContext, contextObject, name)) {
|
|
||||||
Object value = accessor.read(eContext, contextObject, name);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (AccessException ae) {
|
}
|
||||||
|
catch (AccessException ae) {
|
||||||
throw new SpelException(ae, SpelMessages.EXCEPTION_DURING_PROPERTY_READ, name, ae.getMessage());
|
throw new SpelException(ae, SpelMessages.EXCEPTION_DURING_PROPERTY_READ, name, ae.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, name, Utils
|
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, name,
|
||||||
.formatClassnameForMessage(contextObjectClass));
|
FormatHelper.formatClassNameForMessage(contextObjectClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeProperty(ExpressionState state, Object name, Object newValue) throws SpelException {
|
private void writeProperty(ExpressionState state, String name, Object newValue) throws SpelException {
|
||||||
Object contextObject = state.getActiveContextObject();
|
Object contextObject = state.getActiveContextObject();
|
||||||
EvaluationContext eContext = state.getEvaluationContext();
|
EvaluationContext eContext = state.getEvaluationContext();
|
||||||
|
|
||||||
if (cachedWriterExecutor != null) {
|
PropertyAccessor accessorToUse = this.cachedWriteAccessor;
|
||||||
|
if (accessorToUse != null) {
|
||||||
try {
|
try {
|
||||||
cachedWriterExecutor.execute(state.getEvaluationContext(), contextObject, newValue);
|
accessorToUse.write(state.getEvaluationContext(), contextObject, name, newValue);
|
||||||
return;
|
return;
|
||||||
} catch (AccessException ae) {
|
}
|
||||||
|
catch (AccessException ae) {
|
||||||
// this is OK - it may have gone stale due to a class change,
|
// this is OK - it may have gone stale due to a class change,
|
||||||
// let's try to get a new one and call it before giving up
|
// let's try to get a new one and call it before giving up
|
||||||
|
this.cachedWriteAccessor = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,27 +139,10 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||||
if (accessorsToTry != null) {
|
if (accessorsToTry != null) {
|
||||||
try {
|
try {
|
||||||
for (PropertyAccessor accessor : accessorsToTry) {
|
for (PropertyAccessor accessor : accessorsToTry) {
|
||||||
if (accessor instanceof CacheablePropertyAccessor) {
|
if (accessor.canWrite(eContext, contextObject, name)) {
|
||||||
cachedWriterExecutor = ((CacheablePropertyAccessor) accessor).getWriterAccessor(eContext,
|
this.cachedWriteAccessor = accessor;
|
||||||
contextObject, name);
|
accessor.write(eContext, contextObject, name, newValue);
|
||||||
if (cachedWriterExecutor != null) {
|
return;
|
||||||
try {
|
|
||||||
cachedWriterExecutor.execute(state.getEvaluationContext(), contextObject, newValue);
|
|
||||||
return;
|
|
||||||
} catch (AccessException ae) {
|
|
||||||
cachedWriterExecutor = null;
|
|
||||||
throw ae;
|
|
||||||
} finally {
|
|
||||||
if (!useCaching) {
|
|
||||||
cachedWriterExecutor = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (accessor.canWrite(eContext, contextObject, name)) {
|
|
||||||
accessor.write(eContext, contextObject, name, newValue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (AccessException ae) {
|
} catch (AccessException ae) {
|
||||||
|
|
@ -177,11 +150,11 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||||
name, ae.getMessage());
|
name, ae.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_SETTER_NOT_FOUND, name, Utils
|
throw new SpelException(SpelMessages.PROPERTY_OR_FIELD_SETTER_NOT_FOUND, name, FormatHelper
|
||||||
.formatClassnameForMessage(contextObjectClass));
|
.formatClassNameForMessage(contextObjectClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWritableProperty(Object name, ExpressionState state) throws SpelException {
|
public boolean isWritableProperty(String name, ExpressionState state) throws SpelException {
|
||||||
Object contextObject = state.getActiveContextObject();
|
Object contextObject = state.getActiveContextObject();
|
||||||
EvaluationContext eContext = state.getEvaluationContext();
|
EvaluationContext eContext = state.getEvaluationContext();
|
||||||
if (contextObject == null) {
|
if (contextObject == null) {
|
||||||
|
|
@ -210,7 +183,6 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||||
* the start of the list. In addition, there are specific resolvers that exactly name the class in question and
|
* the start of the list. In addition, there are specific resolvers that exactly name the class in question and
|
||||||
* resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the
|
* resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the
|
||||||
* specific resolvers set and will be tried after exactly matching accessors but before generic accessors.
|
* specific resolvers set and will be tried after exactly matching accessors but before generic accessors.
|
||||||
*
|
|
||||||
* @param targetType the type upon which property access is being attempted
|
* @param targetType the type upon which property access is being attempted
|
||||||
* @return a list of resolvers that should be tried in order to access the property
|
* @return a list of resolvers that should be tried in order to access the property
|
||||||
*/
|
*/
|
||||||
|
|
@ -221,15 +193,16 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||||
Class<?>[] targets = resolver.getSpecificTargetClasses();
|
Class<?>[] targets = resolver.getSpecificTargetClasses();
|
||||||
if (targets == null) { // generic resolver that says it can be used for any type
|
if (targets == null) { // generic resolver that says it can be used for any type
|
||||||
generalAccessors.add(resolver);
|
generalAccessors.add(resolver);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (targetType != null) {
|
if (targetType != null) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
for (int i = 0; i < targets.length; i++) {
|
for (Class<?> clazz : targets) {
|
||||||
Class<?> clazz = targets[i];
|
|
||||||
if (clazz == targetType) { // put exact matches on the front to be tried first?
|
if (clazz == targetType) { // put exact matches on the front to be tried first?
|
||||||
specificAccessors.add(pos++, resolver);
|
specificAccessors.add(pos++, resolver);
|
||||||
} else if (clazz.isAssignableFrom(targetType)) { // put supertype matches at the end of the
|
}
|
||||||
// specificAccessor list
|
else if (clazz.isAssignableFrom(targetType)) { // put supertype matches at the end of the
|
||||||
|
// specificAccessor list
|
||||||
generalAccessors.add(resolver);
|
generalAccessors.add(resolver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,19 +13,21 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a dot separated sequence of strings that indicate a package qualified type reference.
|
* Represents a dot separated sequence of strings that indicate a package qualified type reference.
|
||||||
* <p>
|
*
|
||||||
* Example: "java.lang.String" as in the expression "new java.lang.String('hello')"
|
* <p>Example: "java.lang.String" as in the expression "new java.lang.String('hello')"
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class QualifiedIdentifier extends SpelNodeImpl {
|
public class QualifiedIdentifier extends SpelNodeImpl {
|
||||||
|
|
||||||
|
|
@ -39,27 +41,30 @@ public class QualifiedIdentifier extends SpelNodeImpl {
|
||||||
@Override
|
@Override
|
||||||
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
||||||
// Cache the concatenation of child identifiers
|
// Cache the concatenation of child identifiers
|
||||||
if (value == null) {
|
if (this.value == null) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (int i = 0; i < getChildCount(); i++) {
|
for (int i = 0; i < getChildCount(); i++) {
|
||||||
if (i > 0)
|
if (i > 0) {
|
||||||
sb.append(".");
|
sb.append(".");
|
||||||
|
}
|
||||||
sb.append(getChild(i).getValueInternal(state));
|
sb.append(getChild(i).getValueInternal(state));
|
||||||
}
|
}
|
||||||
value = sb.toString();
|
this.value = sb.toString();
|
||||||
}
|
}
|
||||||
return value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringAST() {
|
public String toStringAST() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (value != null) {
|
if (this.value != null) {
|
||||||
sb.append(value);
|
sb.append(this.value);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
for (int i = 0; i < getChildCount(); i++) {
|
for (int i = 0; i < getChildCount(); i++) {
|
||||||
if (i > 0)
|
if (i > 0) {
|
||||||
sb.append(".");
|
sb.append(".");
|
||||||
|
}
|
||||||
sb.append(getChild(i).toStringAST());
|
sb.append(getChild(i).toStringAST());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,10 +13,15 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class RealLiteral extends Literal {
|
public class RealLiteral extends Literal {
|
||||||
|
|
||||||
private final Double value;
|
private final Double value;
|
||||||
|
|
@ -28,7 +33,7 @@ public class RealLiteral extends Literal {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Double getLiteralValue() {
|
public Double getLiteralValue() {
|
||||||
return value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -21,11 +22,11 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
|
||||||
import org.springframework.expression.spel.internal.KeyValuePair;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents selection over a map or collection. For example: {1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this) == 'y'} returns
|
* Represents selection over a map or collection. For example: {1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this) == 'y'} returns
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,32 +13,33 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.antlr.runtime.tree.CommonTree;
|
import org.antlr.runtime.tree.CommonTree;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.common.ExpressionUtils;
|
import org.springframework.expression.common.ExpressionUtils;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelNode;
|
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
|
import org.springframework.expression.spel.SpelNode;
|
||||||
import org.springframework.expression.spel.generated.SpringExpressionsParser;
|
import org.springframework.expression.spel.generated.SpringExpressionsParser;
|
||||||
import org.springframework.expression.spel.standard.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The common supertype of all AST nodes in a parsed Spring Expression Language format expression.
|
* The common supertype of all AST nodes in a parsed Spring Expression Language format expression.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public abstract class SpelNodeImpl extends CommonTree implements Serializable, SpelNode {
|
public abstract class SpelNodeImpl extends CommonTree implements SpelNode, Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Antlr parser uses this constructor to build SpelNodes.
|
* The Antlr parser uses this constructor to build SpelNodes.
|
||||||
*
|
|
||||||
* @param payload the token for the node that has been parsed
|
* @param payload the token for the node that has been parsed
|
||||||
*/
|
*/
|
||||||
protected SpelNodeImpl(Token payload) {
|
protected SpelNodeImpl(Token payload) {
|
||||||
|
|
@ -46,38 +47,23 @@ public abstract class SpelNodeImpl extends CommonTree implements Serializable, S
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Object getValue(ExpressionState expressionState) throws EvaluationException {
|
public final Object getValue(ExpressionState expressionState) throws EvaluationException {
|
||||||
if (expressionState==null) {
|
if (expressionState != null) {
|
||||||
return getValue(new ExpressionState(new StandardEvaluationContext()));
|
|
||||||
} else {
|
|
||||||
return getValueInternal(expressionState);
|
return getValueInternal(expressionState);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return getValue(new ExpressionState(new StandardEvaluationContext()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.expression.spel.ast.ISpelNode#getValue(org.springframework.expression.spel.ExpressionState)
|
|
||||||
*/
|
|
||||||
public abstract Object getValueInternal(ExpressionState expressionState) throws EvaluationException;
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.expression.spel.ast.ISpelNode#isWritable(org.springframework.expression.spel.ExpressionState)
|
|
||||||
*/
|
|
||||||
public boolean isWritable(ExpressionState expressionState) throws EvaluationException {
|
public boolean isWritable(ExpressionState expressionState) throws EvaluationException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.expression.spel.ast.ISpelNode#setValue(org.springframework.expression.spel.ExpressionState, java.lang.Object)
|
|
||||||
*/
|
|
||||||
public void setValue(ExpressionState expressionState, Object newValue) throws EvaluationException {
|
public void setValue(ExpressionState expressionState, Object newValue) throws EvaluationException {
|
||||||
throw new SpelException(getCharPositionInLine(), SpelMessages.SETVALUE_NOT_SUPPORTED, getClass(),
|
throw new SpelException(
|
||||||
getTokenName());
|
getCharPositionInLine(), SpelMessages.SETVALUE_NOT_SUPPORTED, getClass(), getTokenName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return return the token this node represents
|
|
||||||
*/
|
|
||||||
protected String getTokenName() {
|
protected String getTokenName() {
|
||||||
if (getToken() == null) {
|
if (getToken() == null) {
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
|
|
@ -85,42 +71,39 @@ public abstract class SpelNodeImpl extends CommonTree implements Serializable, S
|
||||||
return SpringExpressionsParser.tokenNames[getToken().getType()];
|
return SpringExpressionsParser.tokenNames[getToken().getType()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.expression.spel.ast.ISpelNode#toStringAST()
|
|
||||||
*/
|
|
||||||
public abstract String toStringAST();
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.expression.spel.ast.ISpelNode#getChild(int)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public SpelNodeImpl getChild(int index) {
|
public SpelNodeImpl getChild(int index) {
|
||||||
return (SpelNodeImpl) super.getChild(index);
|
return (SpelNodeImpl) super.getChild(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
public Class<?> getObjectClass(Object obj) {
|
||||||
* @see org.springframework.expression.spel.ast.ISpelNode#getObjectClass(java.lang.Object)
|
if (obj == null) {
|
||||||
*/
|
|
||||||
public Class<?> getObjectClass(Object o) {
|
|
||||||
if (o == null)
|
|
||||||
return null;
|
return null;
|
||||||
return (o instanceof Class) ? ((Class<?>) o) : o.getClass();
|
}
|
||||||
|
return (obj instanceof Class ? ((Class<?>) obj) : obj.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final Object getValue(ExpressionState state, Class<?> desiredReturnType) throws EvaluationException {
|
@SuppressWarnings("unchecked")
|
||||||
|
protected final <T> T getValue(ExpressionState state, Class<T> desiredReturnType) throws EvaluationException {
|
||||||
Object result = getValueInternal(state);
|
Object result = getValueInternal(state);
|
||||||
if (result != null && desiredReturnType != null) {
|
if (result != null && desiredReturnType != null) {
|
||||||
Class<?> resultType = result.getClass();
|
Class<?> resultType = result.getClass();
|
||||||
if (desiredReturnType.isAssignableFrom(resultType)) {
|
if (desiredReturnType.isAssignableFrom(resultType)) {
|
||||||
return result;
|
return (T) result;
|
||||||
}
|
}
|
||||||
// Attempt conversion to the requested type, may throw an exception
|
// Attempt conversion to the requested type, may throw an exception
|
||||||
return ExpressionUtils.convert(state.getEvaluationContext(), result, desiredReturnType);
|
return ExpressionUtils.convert(state.getEvaluationContext(), result, desiredReturnType);
|
||||||
}
|
}
|
||||||
return result;
|
return (T) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getStartPosition() {
|
public int getStartPosition() {
|
||||||
return getCharPositionInLine();
|
return getCharPositionInLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract Object getValueInternal(ExpressionState expressionState) throws EvaluationException;
|
||||||
|
|
||||||
|
public abstract String toStringAST();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,13 +13,20 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.antlr.runtime.tree.CommonTreeAdaptor;
|
import org.antlr.runtime.tree.CommonTreeAdaptor;
|
||||||
|
|
||||||
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
import org.springframework.expression.spel.generated.SpringExpressionsLexer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class SpelTreeAdaptor extends CommonTreeAdaptor {
|
public class SpelTreeAdaptor extends CommonTreeAdaptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object create(Token payload) {
|
public Object create(Token payload) {
|
||||||
if (payload != null) {
|
if (payload != null) {
|
||||||
|
|
@ -131,4 +138,5 @@ public class SpelTreeAdaptor extends CommonTreeAdaptor {
|
||||||
}
|
}
|
||||||
return new EmptySpelNode(payload);
|
return new EmptySpelNode(payload);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,30 +13,36 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
public class StringLiteral extends Literal {
|
public class StringLiteral extends Literal {
|
||||||
|
|
||||||
private String value;
|
private final String value;
|
||||||
|
|
||||||
public StringLiteral(Token payload) {
|
public StringLiteral(Token payload) {
|
||||||
super(payload);
|
super(payload);
|
||||||
value = payload.getText();
|
String val = payload.getText();
|
||||||
// TODO should these have been skipped being created by the parser rules? or not?
|
// TODO should these have been skipped being created by the parser rules? or not?
|
||||||
value = value.substring(1, value.length() - 1);
|
val = val.substring(1, val.length() - 1);
|
||||||
value = value.replaceAll("''", "'");
|
this.value = val.replaceAll("''", "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLiteralValue() {
|
public String getLiteralValue() {
|
||||||
return value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new StringBuilder("'").append(getLiteralValue()).append("'").toString();
|
return "'" + getLiteralValue() + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
@ -22,8 +23,10 @@ import org.springframework.expression.spel.SpelException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a ternary expression, for example: "someCheck()?true:false".
|
* Represents a ternary expression, for example: "someCheck()?true:false".
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class Ternary extends SpelNodeImpl {
|
public class Ternary extends SpelNodeImpl {
|
||||||
|
|
||||||
|
|
@ -33,21 +36,22 @@ public class Ternary extends SpelNodeImpl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate the condition and if true evaluate the first alternative, otherwise evaluate the second alternative.
|
* Evaluate the condition and if true evaluate the first alternative, otherwise evaluate the second alternative.
|
||||||
*
|
|
||||||
* @param state the expression state
|
* @param state the expression state
|
||||||
* @throws EvaluationException if the condition does not evaluate correctly to a boolean or there is a problem
|
* @throws EvaluationException if the condition does not evaluate correctly to a boolean or there is a problem
|
||||||
* executing the chosen alternative
|
* executing the chosen alternative
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
public Object getValueInternal(ExpressionState state) throws EvaluationException {
|
||||||
Boolean b = (Boolean) getChild(0).getValue(state, Boolean.class);
|
Boolean b = getChild(0).getValue(state, Boolean.class);
|
||||||
try {
|
try {
|
||||||
if (b) {
|
if (b != null && b.booleanValue()) {
|
||||||
return getChild(1).getValueInternal(state);
|
return getChild(1).getValueInternal(state);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return getChild(2).getValueInternal(state);
|
return getChild(2).getValueInternal(state);
|
||||||
}
|
}
|
||||||
} catch (SpelException ex) {
|
}
|
||||||
|
catch (SpelException ex) {
|
||||||
ex.setPosition(getChild(0).getCharPositionInLine());
|
ex.setPosition(getChild(0).getCharPositionInLine());
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
|
@ -63,4 +67,5 @@ public class Ternary extends SpelNodeImpl {
|
||||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,9 +13,10 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.expression.spel.internal;
|
|
||||||
|
|
||||||
public enum TypeCode {
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
|
enum TypeCode {
|
||||||
|
|
||||||
OBJECT(0, Object.class), BOOLEAN(1, Boolean.TYPE), BYTE(1, Byte.TYPE), CHAR(1, Character.TYPE), SHORT(2, Short.TYPE), INT(
|
OBJECT(0, Object.class), BOOLEAN(1, Boolean.TYPE), BYTE(1, Byte.TYPE), CHAR(1, Character.TYPE), SHORT(2, Short.TYPE), INT(
|
||||||
3, Integer.TYPE), LONG(4, Long.TYPE), FLOAT(5, Float.TYPE), DOUBLE(6, Double.TYPE);
|
3, Integer.TYPE), LONG(4, Long.TYPE), FLOAT(5, Float.TYPE), DOUBLE(6, Double.TYPE);
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,19 +13,19 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.internal.TypeCode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a reference to a type, for example "T(String)" or "T(com.somewhere.Foo)"
|
* Represents a reference to a type, for example "T(String)" or "T(com.somewhere.Foo)"
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class TypeReference extends SpelNodeImpl {
|
public class TypeReference extends SpelNodeImpl {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2004-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.
|
||||||
|
|
@ -13,58 +13,64 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelException;
|
import org.springframework.expression.spel.SpelException;
|
||||||
import org.springframework.expression.spel.SpelMessages;
|
import org.springframework.expression.spel.SpelMessages;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a variable reference, eg. #someVar. Note this is different to a *local* variable like $someVar
|
* Represents a variable reference, eg. #someVar. Note this is different to a *local* variable like $someVar
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
*
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class VariableReference extends SpelNodeImpl {
|
public class VariableReference extends SpelNodeImpl {
|
||||||
|
|
||||||
// Well known variables:
|
// Well known variables:
|
||||||
private final static String THIS = "this"; // currently active context object
|
private final static String THIS = "this"; // currently active context object
|
||||||
private final static String ROOT = "root"; // root context object
|
private final static String ROOT = "root"; // root context object
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
|
||||||
public VariableReference(Token payload) {
|
public VariableReference(Token payload) {
|
||||||
super(payload);
|
super(payload);
|
||||||
name = payload.getText();
|
this.name = payload.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueInternal(ExpressionState state) throws SpelException {
|
public Object getValueInternal(ExpressionState state) throws SpelException {
|
||||||
if (name.equals(THIS))
|
if (this.name.equals(THIS)) {
|
||||||
return state.getActiveContextObject();
|
return state.getActiveContextObject();
|
||||||
if (name.equals(ROOT))
|
}
|
||||||
|
if (this.name.equals(ROOT)) {
|
||||||
return state.getRootContextObject();
|
return state.getRootContextObject();
|
||||||
Object result = state.lookupVariable(name);
|
}
|
||||||
|
Object result = state.lookupVariable(this.name);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
throw new SpelException(getCharPositionInLine(), SpelMessages.VARIABLE_NOT_FOUND, name);
|
throw new SpelException(getCharPositionInLine(), SpelMessages.VARIABLE_NOT_FOUND, this.name);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(ExpressionState state, Object value) throws SpelException {
|
public void setValue(ExpressionState state, Object value) throws SpelException {
|
||||||
// Object oldValue = state.lookupVariable(name);
|
state.setVariable(this.name, value);
|
||||||
state.setVariable(name, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toStringAST() {
|
public String toStringAST() {
|
||||||
return new StringBuilder("#").append(name).toString();
|
return "#" + this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||||
return !(name.equals(THIS) || name.equals(ROOT));
|
return !(this.name.equals(THIS) || this.name.equals(ROOT));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression.spel.internal;
|
|
||||||
|
|
||||||
import org.springframework.expression.spel.SpelException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps an ELException and can pass up through Antlr since it is unchecked, where it can then be unwrapped.
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public class WrappedExpressionException extends RuntimeException {
|
|
||||||
|
|
||||||
WrappedExpressionException(SpelException e) {
|
|
||||||
super(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpelException getCause() {
|
|
||||||
return (SpelException) super.getCause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression.spel.reflection;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
|
||||||
import org.springframework.expression.ConstructorExecutor;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.EvaluationException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple CommandExecutor implementation that runs a constructor using reflective invocation.
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public class ReflectionConstructorExecutor implements ConstructorExecutor {
|
|
||||||
|
|
||||||
private final Constructor<?> c;
|
|
||||||
|
|
||||||
// When the constructor was found, we will have determined if arguments need to be converted for it
|
|
||||||
// to be invoked. Conversion won't be cheap so let's only do it if necessary.
|
|
||||||
private final Integer[] argsRequiringConversion;
|
|
||||||
|
|
||||||
public ReflectionConstructorExecutor(Constructor<?> constructor, Integer[] argsRequiringConversion) {
|
|
||||||
c = constructor;
|
|
||||||
this.argsRequiringConversion = argsRequiringConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoke a constructor via reflection.
|
|
||||||
*/
|
|
||||||
public Object execute(EvaluationContext context, Object... arguments) throws AccessException {
|
|
||||||
if (argsRequiringConversion != null && arguments != null) {
|
|
||||||
try {
|
|
||||||
ReflectionUtils.convertArguments(c.getParameterTypes(), c.isVarArgs(), context.getTypeUtils()
|
|
||||||
.getTypeConverter(), argsRequiringConversion, arguments);
|
|
||||||
} catch (EvaluationException ex) {
|
|
||||||
throw new AccessException("Problem invoking constructor on '" + c + "': " + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c.isVarArgs()) {
|
|
||||||
arguments = ReflectionUtils.setupArgumentsForVarargsInvocation(c.getParameterTypes(), arguments);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (!c.isAccessible()) {
|
|
||||||
c.setAccessible(true);
|
|
||||||
}
|
|
||||||
return c.newInstance(arguments);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new AccessException("Problem invoking constructor on '" + c + "' : " + e.getMessage(), e);
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
throw new AccessException("Problem invoking constructor on '" + c + "' : " + e.getMessage(), e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new AccessException("Problem invoking constructor on '" + c + "' : " + e.getMessage(), e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new AccessException("Problem invoking constructor on '" + c + "' : " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression.spel.reflection;
|
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
|
||||||
import org.springframework.expression.ConstructorExecutor;
|
|
||||||
import org.springframework.expression.ConstructorResolver;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.EvaluationException;
|
|
||||||
import org.springframework.expression.spel.reflection.ReflectionUtils.DiscoveredConstructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A constructor resolver that uses reflection to locate the constructor that should be invoked
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public class ReflectionConstructorResolver implements ConstructorResolver {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indicates if this resolve will allow matches to be found that require some of the input arguments to be
|
|
||||||
* transformed by the conversion service.
|
|
||||||
*/
|
|
||||||
private boolean allowMatchesRequiringArgumentConversion = true;
|
|
||||||
|
|
||||||
public ReflectionConstructorResolver() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReflectionConstructorResolver(boolean allowMatchesRequiringArgumentConversion) {
|
|
||||||
this.allowMatchesRequiringArgumentConversion = allowMatchesRequiringArgumentConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAllowMatchRequiringArgumentConversion(boolean allow) {
|
|
||||||
this.allowMatchesRequiringArgumentConversion = allow;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locate a matching constructor or return null if non can be found.
|
|
||||||
*/
|
|
||||||
public ConstructorExecutor resolve(EvaluationContext context, String typename, Class<?>[] argumentTypes)
|
|
||||||
throws AccessException {
|
|
||||||
try {
|
|
||||||
Class<?> c = context.getTypeUtils().getTypeLocator().findType(typename);
|
|
||||||
DiscoveredConstructor dCtor = ReflectionUtils.findConstructor(context.getTypeUtils().getTypeConverter(), c,
|
|
||||||
argumentTypes, allowMatchesRequiringArgumentConversion);
|
|
||||||
if (dCtor == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ReflectionConstructorExecutor(dCtor.theConstructor, dCtor.argumentsRequiringConversion);
|
|
||||||
} catch (EvaluationException e) {
|
|
||||||
throw new AccessException(null,e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression.spel.reflection;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.EvaluationException;
|
|
||||||
import org.springframework.expression.MethodExecutor;
|
|
||||||
|
|
||||||
public class ReflectionMethodExecutor implements MethodExecutor {
|
|
||||||
|
|
||||||
private final Method m;
|
|
||||||
|
|
||||||
// When the method was found, we will have determined if arguments need to be converted for it
|
|
||||||
// to be invoked. Conversion won't be cheap so let's only do it if necessary.
|
|
||||||
private final Integer[] argsRequiringConversion;
|
|
||||||
|
|
||||||
public ReflectionMethodExecutor(Method theMethod, Integer[] argumentsRequiringConversion) {
|
|
||||||
m = theMethod;
|
|
||||||
argsRequiringConversion = argumentsRequiringConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object execute(EvaluationContext context, Object target, Object... arguments) throws AccessException {
|
|
||||||
if (argsRequiringConversion != null && arguments != null) {
|
|
||||||
try {
|
|
||||||
ReflectionUtils.convertArguments(m.getParameterTypes(), m.isVarArgs(), context.getTypeUtils()
|
|
||||||
.getTypeConverter(), argsRequiringConversion, arguments);
|
|
||||||
} catch (EvaluationException ex) {
|
|
||||||
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass()
|
|
||||||
+ "': " + ex.getMessage(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m.isVarArgs()) {
|
|
||||||
arguments = ReflectionUtils.setupArgumentsForVarargsInvocation(m.getParameterTypes(), arguments);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (!m.isAccessible()) {
|
|
||||||
m.setAccessible(true);
|
|
||||||
}
|
|
||||||
return m.invoke(target, arguments);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass() + "': "
|
|
||||||
+ e.getMessage(), e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass() + "': "
|
|
||||||
+ e.getMessage(), e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.getCause().printStackTrace();
|
|
||||||
throw new AccessException("Problem invoking method '" + m.getName() + "' on '" + target.getClass() + "': "
|
|
||||||
+ e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2008 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.springframework.expression.spel.reflection;
|
|
||||||
|
|
||||||
import org.springframework.expression.AccessException;
|
|
||||||
import org.springframework.expression.EvaluationContext;
|
|
||||||
import org.springframework.expression.EvaluationException;
|
|
||||||
import org.springframework.expression.MethodExecutor;
|
|
||||||
import org.springframework.expression.MethodResolver;
|
|
||||||
import org.springframework.expression.spel.reflection.ReflectionUtils.DiscoveredMethod;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A method resolver that uses reflection to locate the method that should be invoked
|
|
||||||
*
|
|
||||||
* @author Andy Clement
|
|
||||||
*/
|
|
||||||
public class ReflectionMethodResolver implements MethodResolver {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indicates if this resolve will allow matches to be found that require some of the input arguments to be
|
|
||||||
* transformed by the conversion service.
|
|
||||||
*/
|
|
||||||
private boolean allowMatchesRequiringArgumentConversion = true;
|
|
||||||
|
|
||||||
public ReflectionMethodResolver() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReflectionMethodResolver(boolean allowMatchesRequiringArgumentConversion) {
|
|
||||||
this.allowMatchesRequiringArgumentConversion = allowMatchesRequiringArgumentConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAllowMatchRequiringArgumentConversion(boolean allow) {
|
|
||||||
this.allowMatchesRequiringArgumentConversion = allow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, Class<?>[] argumentTypes) throws AccessException {
|
|
||||||
try {
|
|
||||||
Class<?> relevantClass = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
|
|
||||||
DiscoveredMethod dMethod = ReflectionUtils.findMethod(context.getTypeUtils().getTypeConverter(), name,
|
|
||||||
argumentTypes, relevantClass, allowMatchesRequiringArgumentConversion);
|
|
||||||
if (dMethod == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ReflectionMethodExecutor(dMethod.theMethod, dMethod.argumentsRequiringConversion);
|
|
||||||
} catch (EvaluationException e) {
|
|
||||||
throw new AccessException(null,e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue