diff --git a/src/main/java/org/springframework/data/mapping/PropertyPath.java b/src/main/java/org/springframework/data/mapping/PropertyPath.java index da10c72273..cc2d51891f 100644 --- a/src/main/java/org/springframework/data/mapping/PropertyPath.java +++ b/src/main/java/org/springframework/data/mapping/PropertyPath.java @@ -47,7 +47,7 @@ public class PropertyPath implements Streamable { private static final String PARSE_DEPTH_EXCEEDED = "Trying to parse a path with depth greater than 1000; This has been disabled for security reasons to prevent parsing overflows"; - private static final String DELIMITERS = "_\\."; + private static final String DELIMITERS = "_."; // dot not need to be escaped in the character group private static final Pattern SPLITTER = Pattern.compile("(?:[%s]?([%s]*?[^%s]+))".replaceAll("%s", DELIMITERS)); private static final Pattern SPLITTER_FOR_QUOTED = Pattern.compile("(?:[%s]?([%s]*?[^%s]+))".replaceAll("%s", "\\.")); private static final Pattern NESTED_PROPERTY_PATTERN = Pattern.compile("\\p{Lu}[\\p{Ll}\\p{Nd}]*$"); @@ -471,6 +471,10 @@ private static PropertyPath create(String source, TypeInformation type, Strin throw e; } + if (source.isEmpty() || Character.isWhitespace(source.charAt(0))) { + throw e; + } + exception = e; } @@ -497,42 +501,5 @@ public String toString() { return String.format("%s.%s", owningType.getType().getSimpleName(), toDotPath()); } - private static final class Property { - - private final TypeInformation type; - private final String path; - - private Property(TypeInformation type, String path) { - this.type = type; - this.path = path; - } - - @Override - public boolean equals(@Nullable Object obj) { - - if (obj == this) { - return true; - } - - if (!(obj instanceof Property that)) { - return false; - } - - return Objects.equals(this.type, that.type) && - Objects.equals(this.path, that.path); - } - - @Override - public int hashCode() { - return Objects.hash(type, path); - } - - @Override - public String toString() { - - return "Key[" + - "type=" + type + ", " + - "path=" + path + ']'; - } - } + private record Property(TypeInformation type, String path) { } } diff --git a/src/test/java/org/springframework/data/mapping/PropertyPathUnitTests.java b/src/test/java/org/springframework/data/mapping/PropertyPathUnitTests.java index d5e8efa1d3..d8dcd4a58a 100755 --- a/src/test/java/org/springframework/data/mapping/PropertyPathUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/PropertyPathUnitTests.java @@ -25,6 +25,8 @@ import java.util.regex.Pattern; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.data.util.TypeInformation; /** @@ -93,6 +95,12 @@ void prefersExplicitPaths() { assertThat(reference.next()).isEqualTo(new PropertyPath("name", FooBar.class)); } + @ParameterizedTest + @ValueSource(strings = {"user_ name", "user_ Name", "user. Name", "user. name"}) + void testPathStartedWithWhitespaceAreNotValid(String source) { + assertThatThrownBy(() -> PropertyPath.from(source, Sample.class)).isInstanceOf(PropertyReferenceException.class); + } + @Test void handlesGenericsCorrectly() {