Skip to content

Commit 613cf08

Browse files
committed
DATACMNS-1264 - MapDataBinder now rejects improper property expressions.
We now make sure that type expressions cannot be used in SpEL expressions handled by MapDataBinder. They're gonna be rejected by considering the property not writable. SpEL expression evaluation errors are now forwarded as NotWritablePropertyException to make sure the failure gets handled as if the property referred to doesn't exist.
1 parent 3dff7ea commit 613cf08

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

src/main/java/org/springframework/data/web/MapDataBinder.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import org.springframework.expression.EvaluationContext;
4444
import org.springframework.expression.Expression;
4545
import org.springframework.expression.TypedValue;
46+
import org.springframework.expression.spel.SpelEvaluationException;
47+
import org.springframework.expression.spel.SpelMessage;
4648
import org.springframework.expression.spel.SpelParserConfiguration;
4749
import org.springframework.expression.spel.standard.SpelExpressionParser;
4850
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -177,6 +179,9 @@ public void setPropertyValue(String propertyName, @Nullable Object value) throws
177179
StandardEvaluationContext context = new StandardEvaluationContext();
178180
context.addPropertyAccessor(new PropertyTraversingMapAccessor(type, conversionService));
179181
context.setTypeConverter(new StandardTypeConverter(conversionService));
182+
context.setTypeLocator(typeName -> {
183+
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
184+
});
180185
context.setRootObject(map);
181186

182187
Expression expression = PARSER.parseExpression(propertyName);
@@ -208,7 +213,11 @@ public void setPropertyValue(String propertyName, @Nullable Object value) throws
208213
value = conversionService.convert(value, TypeDescriptor.forObject(value), typeDescriptor);
209214
}
210215

211-
expression.setValue(context, value);
216+
try {
217+
expression.setValue(context, value);
218+
} catch (SpelEvaluationException o_O) {
219+
throw new NotWritablePropertyException(type, propertyName, "Could not write property!", o_O);
220+
}
212221
}
213222

214223
private boolean conversionRequired(@Nullable Object source, Class<?> targetType) {

src/test/java/org/springframework/data/web/MapDataBinderUnitTests.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@
2828
import java.util.Map;
2929

3030
import org.junit.Test;
31+
import org.springframework.beans.ConfigurablePropertyAccessor;
3132
import org.springframework.beans.MutablePropertyValues;
33+
import org.springframework.beans.NotWritablePropertyException;
3234
import org.springframework.beans.PropertyValues;
35+
import org.springframework.expression.spel.SpelEvaluationException;
3336
import org.springframework.format.annotation.DateTimeFormat;
3437
import org.springframework.format.annotation.DateTimeFormat.ISO;
3538
import org.springframework.format.support.DefaultFormattingConversionService;
@@ -91,7 +94,29 @@ public void skipsPropertyNotExposedByTheTypeHierarchy() {
9194
MutablePropertyValues values = new MutablePropertyValues();
9295
values.add("somethingWeird", "Value");
9396

94-
assertThat(bind(values)).isEqualTo(Collections.<String, Object> emptyMap());
97+
assertThat(bind(values)).isEqualTo(Collections.emptyMap());
98+
}
99+
100+
@Test // DATACMNS-1264
101+
public void dropsMapExpressionsForCollectionReferences() {
102+
103+
ConfigurablePropertyAccessor accessor = new MapDataBinder(Bar.class, new DefaultFormattingConversionService())
104+
.getPropertyAccessor();
105+
106+
assertThatExceptionOfType(NotWritablePropertyException.class) //
107+
.isThrownBy(() -> accessor.setPropertyValue("fooBar['foo']", null)) //
108+
.withCauseInstanceOf(SpelEvaluationException.class);
109+
}
110+
111+
@Test // DATACMNS-1264
112+
public void rejectsExpressionContainingTypeExpression() {
113+
114+
ConfigurablePropertyAccessor accessor = new MapDataBinder(Bar.class, new DefaultFormattingConversionService())
115+
.getPropertyAccessor();
116+
117+
assertThatExceptionOfType(NotWritablePropertyException.class) //
118+
.isThrownBy(() -> accessor.setPropertyValue("fooBar[T(java.lang.String)]", null)) //
119+
.withCauseInstanceOf(SpelEvaluationException.class);
95120
}
96121

97122
private static Map<String, Object> bind(PropertyValues values) {

0 commit comments

Comments
 (0)