Merge branch '3.2.x' into master
Conflicts: gradle.properties spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java spring-core/src/main/java/org/springframework/core/convert/support/StringToEnumConverterFactory.java spring-core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/AbstractLobHandler.java spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpRequestWrapper.java spring-web/src/main/java/org/springframework/http/client/SimpleBufferingClientHttpRequest.java spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java
This commit is contained in:
@@ -43,4 +43,4 @@ public interface MethodFilter {
|
||||
*/
|
||||
List<Method> filter(List<Method> methods);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -108,7 +108,9 @@ public enum SpelMessage {
|
||||
OPERAND_NOT_INCREMENTABLE(Kind.ERROR,1066,"the expression component ''{0}'' does not support increment"), //
|
||||
OPERAND_NOT_DECREMENTABLE(Kind.ERROR,1067,"the expression component ''{0}'' does not support decrement"), //
|
||||
NOT_ASSIGNABLE(Kind.ERROR,1068,"the expression component ''{0}'' is not assignable"), //
|
||||
;
|
||||
MISSING_CHARACTER(Kind.ERROR,1069,"missing expected character ''{0}''"),
|
||||
LEFT_OPERAND_PROBLEM(Kind.ERROR,1070, "Problem parsing left operand"),
|
||||
MISSING_SELECTION_EXPRESSION(Kind.ERROR, 1071, "A required selection expression has not been specified");
|
||||
|
||||
private Kind kind;
|
||||
private int code;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ package org.springframework.expression.spel;
|
||||
* Configuration object for the SpEL expression parser.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
* @since 3.0
|
||||
* @see org.springframework.expression.spel.standard.SpelExpressionParser#SpelExpressionParser(SpelParserConfiguration)
|
||||
*/
|
||||
@@ -29,19 +30,52 @@ public class SpelParserConfiguration {
|
||||
|
||||
private final boolean autoGrowCollections;
|
||||
|
||||
private int maximumAutoGrowSize;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link SpelParserConfiguration} instance.
|
||||
* @param autoGrowNullReferences if null references should automatically grow
|
||||
* @param autoGrowCollections if collections should automatically grow
|
||||
* @see #SpelParserConfiguration(boolean, boolean, int)
|
||||
*/
|
||||
public SpelParserConfiguration(boolean autoGrowNullReferences, boolean autoGrowCollections) {
|
||||
this(autoGrowNullReferences, autoGrowCollections, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link SpelParserConfiguration} instance.
|
||||
* @param autoGrowNullReferences if null references should automatically grow
|
||||
* @param autoGrowCollections if collections should automatically grow
|
||||
* @param maximumAutoGrowSize the maximum size that the collection can auto grow
|
||||
*/
|
||||
public SpelParserConfiguration(boolean autoGrowNullReferences,
|
||||
boolean autoGrowCollections, int maximumAutoGrowSize) {
|
||||
this.autoGrowNullReferences = autoGrowNullReferences;
|
||||
this.autoGrowCollections = autoGrowCollections;
|
||||
this.maximumAutoGrowSize = maximumAutoGrowSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return {@code true} if {@code null} references should be automatically grown
|
||||
*/
|
||||
public boolean isAutoGrowNullReferences() {
|
||||
return this.autoGrowNullReferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if collections should be automatically grown
|
||||
*/
|
||||
public boolean isAutoGrowCollections() {
|
||||
return this.autoGrowCollections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum size that a collection can auto grow
|
||||
*/
|
||||
public int getMaximumAutoGrowSize() {
|
||||
return this.maximumAutoGrowSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public class CompoundExpression extends SpelNodeImpl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
|
||||
if (getChildCount()==1) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,6 +38,7 @@ import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||
* (lists/sets)/arrays
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Phillip Webb
|
||||
* @since 3.0
|
||||
*/
|
||||
// TODO support multidimensional arrays
|
||||
@@ -257,25 +258,20 @@ public class Indexer extends SpelNodeImpl {
|
||||
|
||||
private final boolean growCollection;
|
||||
|
||||
private int maximumSize;
|
||||
|
||||
CollectionIndexingValueRef(Collection collection, int index, TypeDescriptor collectionEntryTypeDescriptor,
|
||||
TypeConverter typeConverter, boolean growCollection) {
|
||||
TypeConverter typeConverter, boolean growCollection, int maximumSize) {
|
||||
this.collection = collection;
|
||||
this.index = index;
|
||||
this.collectionEntryTypeDescriptor = collectionEntryTypeDescriptor;
|
||||
this.typeConverter = typeConverter;
|
||||
this.growCollection = growCollection;
|
||||
this.maximumSize = maximumSize;
|
||||
}
|
||||
|
||||
public TypedValue getValue() {
|
||||
if (this.index >= this.collection.size()) {
|
||||
if (this.growCollection) {
|
||||
growCollection(this.collectionEntryTypeDescriptor, this.index, this.collection);
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.COLLECTION_INDEX_OUT_OF_BOUNDS,
|
||||
this.collection.size(), this.index);
|
||||
}
|
||||
}
|
||||
growCollectionIfNecessary();
|
||||
if (this.collection instanceof List) {
|
||||
Object o = ((List) this.collection).get(this.index);
|
||||
return new TypedValue(o, this.collectionEntryTypeDescriptor.elementTypeDescriptor(o));
|
||||
@@ -291,15 +287,7 @@ public class Indexer extends SpelNodeImpl {
|
||||
}
|
||||
|
||||
public void setValue(Object newValue) {
|
||||
if (this.index >= this.collection.size()) {
|
||||
if (this.growCollection) {
|
||||
growCollection(this.collectionEntryTypeDescriptor, this.index, this.collection);
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.COLLECTION_INDEX_OUT_OF_BOUNDS,
|
||||
this.collection.size(), this.index);
|
||||
}
|
||||
}
|
||||
growCollectionIfNecessary();
|
||||
if (this.collection instanceof List) {
|
||||
List list = (List) this.collection;
|
||||
if (this.collectionEntryTypeDescriptor.getElementTypeDescriptor() != null) {
|
||||
@@ -314,6 +302,36 @@ public class Indexer extends SpelNodeImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private void growCollectionIfNecessary() {
|
||||
if (this.index >= this.collection.size()) {
|
||||
|
||||
if (!this.growCollection) {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.COLLECTION_INDEX_OUT_OF_BOUNDS,
|
||||
this.collection.size(), this.index);
|
||||
}
|
||||
|
||||
if(this.index >= this.maximumSize) {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.UNABLE_TO_GROW_COLLECTION);
|
||||
}
|
||||
|
||||
if (this.collectionEntryTypeDescriptor.getElementTypeDescriptor() == null) {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.UNABLE_TO_GROW_COLLECTION_UNKNOWN_ELEMENT_TYPE);
|
||||
}
|
||||
|
||||
TypeDescriptor elementType = this.collectionEntryTypeDescriptor.getElementTypeDescriptor();
|
||||
try {
|
||||
int newElements = this.index - this.collection.size();
|
||||
while (newElements >= 0) {
|
||||
(this.collection).add(elementType.getType().newInstance());
|
||||
newElements--;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.UNABLE_TO_GROW_COLLECTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWritable() {
|
||||
return true;
|
||||
}
|
||||
@@ -403,7 +421,8 @@ public class Indexer extends SpelNodeImpl {
|
||||
}
|
||||
else if (targetObject instanceof Collection) {
|
||||
return new CollectionIndexingValueRef((Collection<?>) targetObject, idx, targetObjectTypeDescriptor,
|
||||
state.getTypeConverter(), state.getConfiguration().isAutoGrowCollections());
|
||||
state.getTypeConverter(), state.getConfiguration().isAutoGrowCollections(),
|
||||
state.getConfiguration().getMaximumAutoGrowSize());
|
||||
}
|
||||
else if (targetObject instanceof String) {
|
||||
return new StringIndexingLValue((String) targetObject, idx, targetObjectTypeDescriptor);
|
||||
@@ -421,32 +440,6 @@ public class Indexer extends SpelNodeImpl {
|
||||
targetObjectTypeDescriptor.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to grow the specified collection so that the specified index is valid.
|
||||
* @param targetType the type of the elements in the collection
|
||||
* @param index the index into the collection that needs to be valid
|
||||
* @param collection the collection to grow with elements
|
||||
*/
|
||||
private void growCollection(TypeDescriptor targetType, int index, Collection<Object> collection) {
|
||||
if (targetType.getElementTypeDescriptor() == null) {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.UNABLE_TO_GROW_COLLECTION_UNKNOWN_ELEMENT_TYPE);
|
||||
}
|
||||
TypeDescriptor elementType = targetType.getElementTypeDescriptor();
|
||||
Object newCollectionElement;
|
||||
try {
|
||||
int newElements = index - collection.size();
|
||||
while (newElements > 0) {
|
||||
collection.add(elementType.getType().newInstance());
|
||||
newElements--;
|
||||
}
|
||||
newCollectionElement = elementType.getType().newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.UNABLE_TO_GROW_COLLECTION);
|
||||
}
|
||||
collection.add(newCollectionElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,23 +17,32 @@
|
||||
package org.springframework.expression.spel.ast;
|
||||
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.*;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.InternalParseException;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
import org.springframework.expression.spel.SpelParseException;
|
||||
|
||||
/**
|
||||
* Common superclass for nodes representing literals (boolean, string, number, etc).
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public abstract class Literal extends SpelNodeImpl {
|
||||
|
||||
protected String literalValue;
|
||||
private final String originalValue;
|
||||
|
||||
public Literal(String payload, int pos) {
|
||||
|
||||
public Literal(String originalValue, int pos) {
|
||||
super(pos);
|
||||
this.literalValue = payload;
|
||||
this.originalValue = originalValue;
|
||||
}
|
||||
|
||||
public abstract TypedValue getLiteralValue();
|
||||
|
||||
public final String getOriginalValue() {
|
||||
return this.originalValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TypedValue getValueInternal(ExpressionState state) throws SpelEvaluationException {
|
||||
@@ -50,10 +59,13 @@ public abstract class Literal extends SpelNodeImpl {
|
||||
return toString();
|
||||
}
|
||||
|
||||
|
||||
public abstract TypedValue getLiteralValue();
|
||||
|
||||
|
||||
/**
|
||||
* Process the string form of a number, using the specified base if supplied and return an appropriate literal to
|
||||
* hold it. Any suffix to indicate a long will be taken into account (either 'l' or 'L' is supported).
|
||||
*
|
||||
* @param numberToken the token holding the number as its payload (eg. 1234 or 0xCAFE)
|
||||
* @param radix the base of number
|
||||
* @return a subtype of Literal that can represent it
|
||||
@@ -62,7 +74,8 @@ public abstract class Literal extends SpelNodeImpl {
|
||||
try {
|
||||
int value = Integer.parseInt(numberToken, radix);
|
||||
return new IntLiteral(numberToken, pos, value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
throw new InternalParseException(new SpelParseException(pos>>16, nfe, SpelMessage.NOT_AN_INTEGER, numberToken));
|
||||
}
|
||||
}
|
||||
@@ -71,25 +84,26 @@ public abstract class Literal extends SpelNodeImpl {
|
||||
try {
|
||||
long value = Long.parseLong(numberToken, radix);
|
||||
return new LongLiteral(numberToken, pos, value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
throw new InternalParseException(new SpelParseException(pos>>16, nfe, SpelMessage.NOT_A_LONG, numberToken));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Literal getRealLiteral(String numberToken, int pos, boolean isFloat) {
|
||||
try {
|
||||
if (isFloat) {
|
||||
float value = Float.parseFloat(numberToken);
|
||||
return new FloatLiteral(numberToken, pos, value);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
double value = Double.parseDouble(numberToken);
|
||||
return new RealLiteral(numberToken, pos, value);
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
throw new InternalParseException(new SpelParseException(pos>>16, nfe, SpelMessage.NOT_A_REAL, numberToken));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ public class Projection extends SpelNodeImpl {
|
||||
if (operand instanceof Map) {
|
||||
Map<?, ?> mapData = (Map<?, ?>) operand;
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
for (Map.Entry<?,?> entry : mapData.entrySet()) {
|
||||
for (Map.Entry<?, ?> entry : mapData.entrySet()) {
|
||||
try {
|
||||
state.pushActiveContextObject(new TypedValue(entry));
|
||||
result.add(this.children[0].getValueInternal(state).getValue());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,7 @@ import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -54,7 +55,9 @@ public class Selection extends SpelNodeImpl {
|
||||
private final boolean nullSafe;
|
||||
|
||||
public Selection(boolean nullSafe, int variant,int pos,SpelNodeImpl expression) {
|
||||
super(pos,expression);
|
||||
super(pos, expression != null ? new SpelNodeImpl[] { expression }
|
||||
: new SpelNodeImpl[] {});
|
||||
Assert.notNull(expression, "Expression must not be null");
|
||||
this.nullSafe = nullSafe;
|
||||
this.variant = variant;
|
||||
}
|
||||
@@ -73,9 +76,9 @@ public class Selection extends SpelNodeImpl {
|
||||
if (operand instanceof Map) {
|
||||
Map<?, ?> mapdata = (Map<?, ?>) operand;
|
||||
// TODO don't lose generic info for the new map
|
||||
Map<Object,Object> result = new HashMap<Object,Object>();
|
||||
Map<Object, Object> result = new HashMap<Object, Object>();
|
||||
Object lastKey = null;
|
||||
for (Map.Entry<?,?> entry : mapdata.entrySet()) {
|
||||
for (Map.Entry<?, ?> entry : mapdata.entrySet()) {
|
||||
try {
|
||||
TypedValue kvpair = new TypedValue(entry);
|
||||
state.pushActiveContextObject(kvpair);
|
||||
@@ -101,7 +104,7 @@ public class Selection extends SpelNodeImpl {
|
||||
return new ValueRef.TypedValueHolderValueRef(new TypedValue(null),this);
|
||||
}
|
||||
if (variant == LAST) {
|
||||
Map<Object,Object> resultMap = new HashMap<Object,Object>();
|
||||
Map<Object, Object> resultMap = new HashMap<Object, Object>();
|
||||
Object lastValue = result.get(lastKey);
|
||||
resultMap.put(lastKey,lastValue);
|
||||
return new ValueRef.TypedValueHolderValueRef(new TypedValue(resultMap),this);
|
||||
|
||||
@@ -149,5 +149,4 @@ public abstract class SpelNodeImpl implements SpelNode {
|
||||
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
|
||||
throw new SpelEvaluationException(pos,SpelMessage.NOT_ASSIGNABLE,toStringAST());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,6 +37,7 @@ import org.springframework.util.StringUtils;
|
||||
* Hand written SpEL parser. Instances are reusable but are not thread safe.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Phillip Webb
|
||||
* @since 3.0
|
||||
*/
|
||||
class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
@@ -104,8 +105,8 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
Token t = peekToken();
|
||||
if (t.kind==TokenKind.ASSIGN) { // a=b
|
||||
if (expr==null) {
|
||||
expr = new NullLiteral(toPos(t.startpos-1,t.endpos-1));
|
||||
}
|
||||
expr = new NullLiteral(toPos(t.startpos-1,t.endpos-1));
|
||||
}
|
||||
nextToken();
|
||||
SpelNodeImpl assignedValue = eatLogicalOrExpression();
|
||||
return new Assign(toPos(t),expr,assignedValue);
|
||||
@@ -139,7 +140,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
while (peekIdentifierToken("or") || peekToken(TokenKind.SYMBOLIC_OR)) {
|
||||
Token t = nextToken(); //consume OR
|
||||
SpelNodeImpl rhExpr = eatLogicalAndExpression();
|
||||
checkRightOperand(t,rhExpr);
|
||||
checkOperands(t,expr,rhExpr);
|
||||
expr = new OpOr(toPos(t),expr,rhExpr);
|
||||
}
|
||||
return expr;
|
||||
@@ -151,7 +152,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
while (peekIdentifierToken("and") || peekToken(TokenKind.SYMBOLIC_AND)) {
|
||||
Token t = nextToken();// consume 'AND'
|
||||
SpelNodeImpl rhExpr = eatRelationalExpression();
|
||||
checkRightOperand(t,rhExpr);
|
||||
checkOperands(t,expr,rhExpr);
|
||||
expr = new OpAnd(toPos(t),expr,rhExpr);
|
||||
}
|
||||
return expr;
|
||||
@@ -164,7 +165,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
if (relationalOperatorToken != null) {
|
||||
Token t = nextToken(); //consume relational operator token
|
||||
SpelNodeImpl rhExpr = eatSumExpression();
|
||||
checkRightOperand(t,rhExpr);
|
||||
checkOperands(t,expr,rhExpr);
|
||||
TokenKind tk = relationalOperatorToken.kind;
|
||||
if (relationalOperatorToken.isNumericRelationalOperator()) {
|
||||
int pos = toPos(t);
|
||||
@@ -217,7 +218,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
while (peekToken(TokenKind.STAR,TokenKind.DIV,TokenKind.MOD)) {
|
||||
Token t = nextToken(); // consume STAR/DIV/MOD
|
||||
SpelNodeImpl rhExpr = eatPowerIncDecExpression();
|
||||
checkRightOperand(t,rhExpr);
|
||||
checkOperands(t,expr,rhExpr);
|
||||
if (t.kind==TokenKind.STAR) {
|
||||
expr = new OpMultiply(toPos(t),expr,rhExpr);
|
||||
} else if (t.kind==TokenKind.DIV) {
|
||||
@@ -556,6 +557,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
}
|
||||
nextToken();
|
||||
SpelNodeImpl expr = eatExpression();
|
||||
if(expr == null) {
|
||||
raiseInternalException(toPos(t), SpelMessage.MISSING_SELECTION_EXPRESSION);
|
||||
}
|
||||
eatToken(TokenKind.RSQUARE);
|
||||
if (t.kind==TokenKind.SELECT_FIRST) {
|
||||
constructedNodes.push(new Selection(nullSafeNavigation,Selection.FIRST,toPos(t),expr));
|
||||
@@ -836,6 +840,17 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOperands(Token token, SpelNodeImpl left, SpelNodeImpl right) {
|
||||
checkLeftOperand(token, left);
|
||||
checkRightOperand(token, right);
|
||||
}
|
||||
|
||||
private void checkLeftOperand(Token token, SpelNodeImpl operandExpression) {
|
||||
if (operandExpression==null) {
|
||||
raiseInternalException(token.startpos,SpelMessage.LEFT_OPERAND_PROBLEM);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRightOperand(Token token, SpelNodeImpl operandExpression) {
|
||||
if (operandExpression==null) {
|
||||
raiseInternalException(token.startpos,SpelMessage.RIGHT_OPERAND_PROBLEM);
|
||||
|
||||
@@ -84,4 +84,4 @@ class Token {
|
||||
public Token asBetweenToken() {
|
||||
return new Token(TokenKind.BETWEEN,startpos,endpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,4 +56,4 @@ enum TokenKind {
|
||||
public int getLength() {
|
||||
return tokenChars.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,7 @@ import org.springframework.util.Assert;
|
||||
* Lex some input data into a stream of tokens that can then be parsed.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Phillip Webb
|
||||
* @since 3.0
|
||||
*/
|
||||
class Tokenizer {
|
||||
@@ -137,14 +138,20 @@ class Tokenizer {
|
||||
}
|
||||
break;
|
||||
case '&':
|
||||
if (isTwoCharToken(TokenKind.SYMBOLIC_AND)) {
|
||||
pushPairToken(TokenKind.SYMBOLIC_AND);
|
||||
if (!isTwoCharToken(TokenKind.SYMBOLIC_AND)) {
|
||||
throw new InternalParseException(new SpelParseException(
|
||||
expressionString, pos,
|
||||
SpelMessage.MISSING_CHARACTER, "&"));
|
||||
}
|
||||
pushPairToken(TokenKind.SYMBOLIC_AND);
|
||||
break;
|
||||
case '|':
|
||||
if (isTwoCharToken(TokenKind.SYMBOLIC_OR)) {
|
||||
pushPairToken(TokenKind.SYMBOLIC_OR);
|
||||
if (!isTwoCharToken(TokenKind.SYMBOLIC_OR)) {
|
||||
throw new InternalParseException(new SpelParseException(
|
||||
expressionString, pos,
|
||||
SpelMessage.MISSING_CHARACTER, "|"));
|
||||
}
|
||||
pushPairToken(TokenKind.SYMBOLIC_OR);
|
||||
break;
|
||||
case '?':
|
||||
if (isTwoCharToken(TokenKind.SELECT)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,13 +19,16 @@ package org.springframework.expression.spel.support;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
@@ -37,7 +40,6 @@ import org.springframework.expression.MethodResolver;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Reflection-based {@link MethodResolver} used by default in
|
||||
@@ -92,25 +94,16 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
try {
|
||||
TypeConverter typeConverter = context.getTypeConverter();
|
||||
Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
|
||||
Method[] methods = getMethods(type, targetObject);
|
||||
List<Method> methods = new ArrayList<Method>(Arrays.asList(getMethods(type, targetObject)));
|
||||
|
||||
// If a filter is registered for this type, call it
|
||||
MethodFilter filter = (this.filters != null ? this.filters.get(type) : null);
|
||||
if (filter != null) {
|
||||
List<Method> methodsForFiltering = new ArrayList<Method>();
|
||||
for (Method method: methods) {
|
||||
methodsForFiltering.add(method);
|
||||
}
|
||||
List<Method> methodsFiltered = filter.filter(methodsForFiltering);
|
||||
if (CollectionUtils.isEmpty(methodsFiltered)) {
|
||||
methods = NO_METHODS;
|
||||
}
|
||||
else {
|
||||
methods = methodsFiltered.toArray(new Method[methodsFiltered.size()]);
|
||||
}
|
||||
methods = filter.filter(methods);
|
||||
}
|
||||
|
||||
Arrays.sort(methods, new Comparator<Method>() {
|
||||
// Sort methods into a sensible order
|
||||
Collections.sort(methods, new Comparator<Method>() {
|
||||
public int compare(Method m1, Method m2) {
|
||||
int m1pl = m1.getParameterTypes().length;
|
||||
int m2pl = m2.getParameterTypes().length;
|
||||
@@ -118,6 +111,14 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
}
|
||||
});
|
||||
|
||||
// Resolve any bridge methods
|
||||
for (int i = 0; i < methods.size(); i++) {
|
||||
methods.set(i, BridgeMethodResolver.findBridgedMethod(methods.get(i)));
|
||||
}
|
||||
|
||||
// Remove duplicate methods (possible due to resolved bridge methods)
|
||||
methods = new ArrayList<Method>(new LinkedHashSet<Method>(methods));
|
||||
|
||||
Method closeMatch = null;
|
||||
int closeMatchDistance = Integer.MAX_VALUE;
|
||||
int[] argsToConvert = null;
|
||||
@@ -125,9 +126,6 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
boolean multipleOptions = false;
|
||||
|
||||
for (Method method : methods) {
|
||||
if (method.isBridge()) {
|
||||
continue;
|
||||
}
|
||||
if (method.getName().equals(name)) {
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
List<TypeDescriptor> paramDescriptors = new ArrayList<TypeDescriptor>(paramTypes.length);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,8 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -42,6 +44,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
@@ -284,7 +287,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
|
||||
private Method findGetterForProperty(String propertyName, Class<?> clazz, Object target) {
|
||||
Method method = findGetterForProperty(propertyName, clazz, target instanceof Class);
|
||||
if(method == null && target instanceof Class) {
|
||||
if (method == null && target instanceof Class) {
|
||||
method = findGetterForProperty(propertyName, target.getClass(), false);
|
||||
}
|
||||
return method;
|
||||
@@ -292,7 +295,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
|
||||
private Method findSetterForProperty(String propertyName, Class<?> clazz, Object target) {
|
||||
Method method = findSetterForProperty(propertyName, clazz, target instanceof Class);
|
||||
if(method == null && target instanceof Class) {
|
||||
if (method == null && target instanceof Class) {
|
||||
method = findSetterForProperty(propertyName, target.getClass(), false);
|
||||
}
|
||||
return method;
|
||||
@@ -300,7 +303,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
|
||||
private Field findField(String name, Class<?> clazz, Object target) {
|
||||
Field field = findField(name, clazz, target instanceof Class);
|
||||
if(field == null && target instanceof Class) {
|
||||
if (field == null && target instanceof Class) {
|
||||
field = findField(name, target.getClass(), false);
|
||||
}
|
||||
return field;
|
||||
@@ -310,13 +313,13 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
* Find a getter method for the specified property.
|
||||
*/
|
||||
protected Method findGetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
|
||||
Method[] ms = clazz.getMethods();
|
||||
Method[] ms = getSortedClassMethods(clazz);
|
||||
String propertyMethodSuffix = getPropertyMethodSuffix(propertyName);
|
||||
|
||||
// Try "get*" method...
|
||||
String getterName = "get" + propertyMethodSuffix;
|
||||
for (Method method : ms) {
|
||||
if (!method.isBridge() && method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
|
||||
if (method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
|
||||
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
||||
return method;
|
||||
}
|
||||
@@ -324,7 +327,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
// Try "is*" method...
|
||||
getterName = "is" + propertyMethodSuffix;
|
||||
for (Method method : ms) {
|
||||
if (!method.isBridge() && method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
|
||||
if (method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
|
||||
(boolean.class.equals(method.getReturnType()) || Boolean.class.equals(method.getReturnType())) &&
|
||||
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
||||
return method;
|
||||
@@ -337,10 +340,10 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
* Find a setter method for the specified property.
|
||||
*/
|
||||
protected Method findSetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
|
||||
Method[] methods = clazz.getMethods();
|
||||
Method[] methods = getSortedClassMethods(clazz);
|
||||
String setterName = "set" + getPropertyMethodSuffix(propertyName);
|
||||
for (Method method : methods) {
|
||||
if (!method.isBridge() && method.getName().equals(setterName) && method.getParameterTypes().length == 1 &&
|
||||
if (method.getName().equals(setterName) && method.getParameterTypes().length == 1 &&
|
||||
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
||||
return method;
|
||||
}
|
||||
@@ -348,6 +351,19 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns class methods ordered with non bridge methods appearing higher.
|
||||
*/
|
||||
private Method[] getSortedClassMethods(Class<?> clazz) {
|
||||
Method[] methods = clazz.getMethods();
|
||||
Arrays.sort(methods, new Comparator<Method>() {
|
||||
public int compare(Method o1, Method o2) {
|
||||
return (o1.isBridge() == o2.isBridge()) ? 0 : (o1.isBridge() ? 1 : -1);
|
||||
}
|
||||
});
|
||||
return methods;
|
||||
}
|
||||
|
||||
protected String getPropertyMethodSuffix(String propertyName) {
|
||||
if (propertyName.length() > 1 && Character.isUpperCase(propertyName.charAt(1))) {
|
||||
return propertyName;
|
||||
@@ -367,6 +383,20 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
// We'll search superclasses and implemented interfaces explicitly,
|
||||
// although it shouldn't be necessary - however, see SPR-10125.
|
||||
if (clazz.getSuperclass() != null) {
|
||||
Field field = findField(name, clazz.getSuperclass(), mustBeStatic);
|
||||
if (field != null) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
for (Class<?> implementedInterface : clazz.getInterfaces()) {
|
||||
Field field = findField(name, implementedInterface, mustBeStatic);
|
||||
if (field != null) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,14 @@
|
||||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
@@ -24,7 +31,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.BeanResolver;
|
||||
@@ -48,6 +54,7 @@ import org.springframework.expression.spel.testresources.TestPerson;
|
||||
* @author Andy Clement
|
||||
* @author Mark Fisher
|
||||
* @author Sam Brannen
|
||||
* @author Phillip Webb
|
||||
* @since 3.0
|
||||
*/
|
||||
public class EvaluationTests extends ExpressionTestCase {
|
||||
@@ -708,6 +715,23 @@ public class EvaluationTests extends ExpressionTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void limitCollectionGrowing() throws Exception {
|
||||
TestClass instance = new TestClass();
|
||||
StandardEvaluationContext ctx = new StandardEvaluationContext(instance);
|
||||
SpelExpressionParser parser = new SpelExpressionParser( new SpelParserConfiguration(true, true, 3));
|
||||
Expression expression = parser.parseExpression("foo[2]");
|
||||
expression.setValue(ctx, "2");
|
||||
assertThat(instance.getFoo().size(), equalTo(3));
|
||||
expression = parser.parseExpression("foo[3]");
|
||||
try {
|
||||
expression.setValue(ctx, "3");
|
||||
} catch(SpelEvaluationException see) {
|
||||
assertEquals(SpelMessage.UNABLE_TO_GROW_COLLECTION, see.getMessageCode());
|
||||
assertThat(instance.getFoo().size(), equalTo(3));
|
||||
}
|
||||
}
|
||||
|
||||
// For now I am making #this not assignable
|
||||
@Test
|
||||
public void increment01root() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -83,9 +84,10 @@ public class MapAccessTests extends ExpressionTestCase {
|
||||
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
Expression exp = parser.parseExpression("testBean.properties['key2']");
|
||||
String key= (String)exp.getValue(bean);
|
||||
String key = (String) exp.getValue(bean);
|
||||
assertNotNull(key);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestBean
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.expression.spel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@@ -213,9 +214,11 @@ public class SpelDocumentationTests extends ExpressionTestCase {
|
||||
societyContext.setRootObject(new IEEE());
|
||||
// Officer's Dictionary
|
||||
Inventor pupin = parser.parseExpression("officers['president']").getValue(societyContext, Inventor.class);
|
||||
assertNotNull(pupin);
|
||||
|
||||
// evaluates to "Idvor"
|
||||
String city = parser.parseExpression("officers['president'].PlaceOfBirth.city").getValue(societyContext, String.class);
|
||||
assertNotNull(city);
|
||||
|
||||
// setting values
|
||||
Inventor i = parser.parseExpression("officers['advisors'][0]").getValue(societyContext,Inventor.class);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,18 @@
|
||||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -26,8 +35,9 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.BeanResolver;
|
||||
@@ -48,17 +58,19 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeLocator;
|
||||
import org.springframework.expression.spel.testresources.le.div.mod.reserved.Reserver;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Reproduction tests cornering various SpEL JIRA issues.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
* @author Clark Duplichien
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SpelReproTests extends ExpressionTestCase {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void testNPE_SPR5661() {
|
||||
evaluate("joinThreeStrings('a',null,'c')", "anullc", String.class);
|
||||
@@ -1656,11 +1668,21 @@ public class SpelReproTests extends ExpressionTestCase {
|
||||
assertEquals(Integer.class, value.getTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR_10162_onlyBridgeMethodTest() throws Exception {
|
||||
ReflectivePropertyAccessor accessor = new ReflectivePropertyAccessor();
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
Object target = new OnlyBridgeMethod();
|
||||
TypedValue value = accessor.read(context, target , "property");
|
||||
assertEquals(Integer.class, value.getTypeDescriptor().getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR_10091_simpleTestValueType() {
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new BooleanHolder());
|
||||
Class<?> valueType = parser.parseExpression("simpleProperty").getValueType(evaluationContext);
|
||||
assertNotNull(valueType);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1668,6 +1690,7 @@ public class SpelReproTests extends ExpressionTestCase {
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new BooleanHolder());
|
||||
Object value = parser.parseExpression("simpleProperty").getValue(evaluationContext);
|
||||
assertNotNull(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1675,6 +1698,7 @@ public class SpelReproTests extends ExpressionTestCase {
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new BooleanHolder());
|
||||
Class<?> valueType = parser.parseExpression("primitiveProperty").getValueType(evaluationContext);
|
||||
assertNotNull(valueType);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1682,8 +1706,52 @@ public class SpelReproTests extends ExpressionTestCase {
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new BooleanHolder());
|
||||
Object value = parser.parseExpression("primitiveProperty").getValue(evaluationContext);
|
||||
assertNotNull(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR_10146_malformedExpressions() throws Exception {
|
||||
doTestSpr10146("/foo", "EL1070E:(pos 0): Problem parsing left operand");
|
||||
doTestSpr10146("*foo", "EL1070E:(pos 0): Problem parsing left operand");
|
||||
doTestSpr10146("%foo", "EL1070E:(pos 0): Problem parsing left operand");
|
||||
doTestSpr10146("<foo", "EL1070E:(pos 0): Problem parsing left operand");
|
||||
doTestSpr10146(">foo", "EL1070E:(pos 0): Problem parsing left operand");
|
||||
doTestSpr10146("&&foo", "EL1070E:(pos 0): Problem parsing left operand");
|
||||
doTestSpr10146("||foo", "EL1070E:(pos 0): Problem parsing left operand");
|
||||
doTestSpr10146("&foo", "EL1069E:(pos 0): missing expected character '&'");
|
||||
doTestSpr10146("|foo", "EL1069E:(pos 0): missing expected character '|'");
|
||||
}
|
||||
|
||||
private void doTestSpr10146(String expression, String expectedMessage) {
|
||||
thrown.expect(SpelParseException.class);
|
||||
thrown.expectMessage(expectedMessage);
|
||||
new SpelExpressionParser().parseExpression(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR_10125() throws Exception {
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
String fromInterface = parser.parseExpression("T("+StaticFinalImpl1.class.getName()+").VALUE").getValue(context, String.class);
|
||||
assertThat(fromInterface, is("interfaceValue"));
|
||||
String fromClass = parser.parseExpression("T("+StaticFinalImpl2.class.getName()+").VALUE").getValue(context, String.class);
|
||||
assertThat(fromClass, is("interfaceValue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR_10210() throws Exception {
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
context.setVariable("bridgeExample", new org.springframework.expression.spel.spr10210.D());
|
||||
Expression parseExpression = parser.parseExpression("#bridgeExample.bridgeMethod()");
|
||||
parseExpression.getValue(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR_10328() throws Exception {
|
||||
thrown.expect(SpelParseException.class);
|
||||
thrown.expectMessage("EL1071E:(pos 2): A required selection expression has not been specified");
|
||||
Expression exp = parser.parseExpression("$[]");
|
||||
exp.getValue(Arrays.asList("foo", "bar", "baz"));
|
||||
}
|
||||
|
||||
public static class BooleanHolder {
|
||||
|
||||
@@ -1722,4 +1790,28 @@ public class SpelReproTests extends ExpressionTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
static class PackagePrivateClassWithGetter {
|
||||
|
||||
public Integer getProperty() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OnlyBridgeMethod extends PackagePrivateClassWithGetter {
|
||||
|
||||
}
|
||||
|
||||
public static interface StaticFinal {
|
||||
public static final String VALUE = "interfaceValue";
|
||||
}
|
||||
|
||||
public abstract static class AbstractStaticFinal implements StaticFinal {
|
||||
}
|
||||
|
||||
public static class StaticFinalImpl1 extends AbstractStaticFinal implements StaticFinal {
|
||||
}
|
||||
|
||||
public static class StaticFinalImpl2 extends AbstractStaticFinal {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.spr10210;
|
||||
|
||||
import org.springframework.expression.spel.spr10210.comp.B;
|
||||
import org.springframework.expression.spel.spr10210.infra.C;
|
||||
|
||||
abstract class A extends B<C> {
|
||||
|
||||
public void bridgeMethod() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.spr10210;
|
||||
|
||||
public class D extends A {
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.spr10210.comp;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.expression.spel.spr10210.infra.C;
|
||||
|
||||
public class B<T extends C> implements Serializable {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.spr10210.infra;
|
||||
|
||||
public interface C {
|
||||
}
|
||||
Reference in New Issue
Block a user