Browse Source

DATAMONGO-2545 - Fix regression in String query SpEL parameter binding.

We reenabled parameter binding within SpEL using query parameter placeholders ?0, ?1,... instead of their array index [0],[1],...

Original pull request: #864.
pull/868/head
Christoph Strobl 6 years ago committed by Mark Paluch
parent
commit
3af7269dbb
No known key found for this signature in database
GPG Key ID: 51A00FA751B91849
  1. 58
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java
  2. 51
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java

58
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java

@ -368,26 +368,33 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { @@ -368,26 +368,33 @@ public class ParameterBindingJsonReader extends AbstractBsonReader {
if (token.getType().equals(JsonTokenType.UNQUOTED_STRING)) {
if (matcher.find()) {
int index = computeParameterIndex(matcher.group());
bindableValue.setValue(getBindableValueForIndex(index));
bindableValue.setType(bsonTypeForValue(getBindableValueForIndex(index)));
return bindableValue;
}
Matcher regexMatcher = EXPRESSION_BINDING_PATTERN.matcher(tokenValue);
if (regexMatcher.find()) {
String binding = regexMatcher.group();
String expression = binding.substring(3, binding.length() - 1);
Matcher inSpelMatcher = PARAMETER_BINDING_PATTERN.matcher(expression);
while (inSpelMatcher.find()) {
int index = computeParameterIndex(inSpelMatcher.group());
expression = expression.replace(inSpelMatcher.group(), getBindableValueForIndex(index).toString());
}
Object value = evaluateExpression(expression);
bindableValue.setValue(value);
bindableValue.setType(bsonTypeForValue(value));
return bindableValue;
}
if (matcher.find()) {
int index = computeParameterIndex(matcher.group());
bindableValue.setValue(getBindableValueForIndex(index));
bindableValue.setType(bsonTypeForValue(getBindableValueForIndex(index)));
return bindableValue;
}
bindableValue.setValue(tokenValue);
bindableValue.setType(BsonType.STRING);
return bindableValue;
@ -396,26 +403,35 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { @@ -396,26 +403,35 @@ public class ParameterBindingJsonReader extends AbstractBsonReader {
String computedValue = tokenValue;
boolean matched = false;
while (matcher.find()) {
matched = true;
String group = matcher.group();
int index = computeParameterIndex(group);
computedValue = computedValue.replace(group, nullSafeToString(getBindableValueForIndex(index)));
}
if (!matched) {
Matcher regexMatcher = EXPRESSION_BINDING_PATTERN.matcher(computedValue);
Matcher regexMatcher = EXPRESSION_BINDING_PATTERN.matcher(tokenValue);
while (regexMatcher.find()) {
while (regexMatcher.find()) {
String binding = regexMatcher.group();
String expression = binding.substring(3, binding.length() - 1);
String binding = regexMatcher.group();
String expression = binding.substring(3, binding.length() - 1);
Matcher inSpelMatcher = PARAMETER_BINDING_PATTERN.matcher(expression);
while (inSpelMatcher.find()) {
computedValue = computedValue.replace(binding, nullSafeToString(evaluateExpression(expression)));
int index = computeParameterIndex(inSpelMatcher.group());
expression = expression.replace(inSpelMatcher.group(), getBindableValueForIndex(index).toString());
}
computedValue = computedValue.replace(binding, nullSafeToString(evaluateExpression(expression)));
bindableValue.setValue(computedValue);
bindableValue.setType(BsonType.STRING);
return bindableValue;
}
while (matcher.find()) {
String group = matcher.group();
int index = computeParameterIndex(group);
computedValue = computedValue.replace(group, nullSafeToString(getBindableValueForIndex(index)));
}
bindableValue.setValue(computedValue);

51
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReaderUnitTests.java

@ -26,6 +26,7 @@ import java.util.List; @@ -26,6 +26,7 @@ import java.util.List;
import org.bson.Document;
import org.bson.codecs.DecoderContext;
import org.junit.jupiter.api.Test;
import org.springframework.data.spel.EvaluationContextProvider;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@ -264,10 +265,60 @@ class ParameterBindingJsonReaderUnitTests { @@ -264,10 +265,60 @@ class ParameterBindingJsonReaderUnitTests {
assertThat(target).isEqualTo(Document.parse("{\"$and\": [{\"v1\": {\"$in\": [1]}}]}"));
}
@Test // DATAMONGO-2545
void shouldABindArgumentsViaIndexInSpelExpressions() {
Object[] args = new Object[] { "yess", "nooo" };
StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT
.getEvaluationContext(args);
ParameterBindingJsonReader reader = new ParameterBindingJsonReader(
"{ 'isBatman' : ?#{ T(" + this.getClass().getName() + ").isBatman() ? [0] : [1] }}",
new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext));
Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build());
assertThat(target).isEqualTo(new Document("isBatman", "nooo"));
}
@Test // DATAMONGO-2545
void shouldAllowMethodArgumentPlaceholdersInSpelExpressions/*becuase this worked before*/() {
Object[] args = new Object[] { "yess", "nooo" };
StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT
.getEvaluationContext(args);
ParameterBindingJsonReader reader = new ParameterBindingJsonReader(
"{ 'isBatman' : ?#{ T(" + this.getClass().getName() + ").isBatman() ? '?0' : '?1' }}",
new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext));
Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build());
assertThat(target).isEqualTo(new Document("isBatman", "nooo"));
}
@Test // DATAMONGO-2545
void shouldAllowMethodArgumentPlaceholdersInQuotedSpelExpressions/*becuase this worked before*/() {
Object[] args = new Object[] { "yess", "nooo" };
StandardEvaluationContext evaluationContext = (StandardEvaluationContext) EvaluationContextProvider.DEFAULT
.getEvaluationContext(args);
ParameterBindingJsonReader reader = new ParameterBindingJsonReader(
"{ 'isBatman' : \"?#{ T(" + this.getClass().getName() + ").isBatman() ? '?0' : '?1' }\" }",
new ParameterBindingContext((index) -> args[index], new SpelExpressionParser(), evaluationContext));
Document target = new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build());
assertThat(target).isEqualTo(new Document("isBatman", "nooo"));
}
private static Document parse(String json, Object... args) {
ParameterBindingJsonReader reader = new ParameterBindingJsonReader(json, args);
return new ParameterBindingDocumentCodec().decode(reader, DecoderContext.builder().build());
}
// DATAMONGO-2545
public static boolean isBatman() {
return false;
}
}

Loading…
Cancel
Save