From aa7de3d53030da36ab15d7167faa3aae66083cfd Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 14 Jun 2018 11:42:48 +0200 Subject: [PATCH] =?UTF-8?q?DATACASS-568=20-=20Guard=20BasicCassandraPersis?= =?UTF-8?q?tentProperty.findAnnotatedType(=E2=80=A6)=20against=20non-param?= =?UTF-8?q?eterized=20types.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now check whether the inspected property type is a AnnotatedParameterizedType one before attempting to extract type parameters. Map-like and Collection-like properties can be generic typed, untyped or subtype of either one and we restrict annotation scanning to generic typed ones. Previously, we applied a downcast without checking for the actual type which lead to a ClassCastException. --- .../BasicCassandraPersistentProperty.java | 19 +++--- ...cCassandraPersistentPropertyUnitTests.java | 63 +++++++++++++++++++ 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentProperty.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentProperty.java index ee290eba1..60880114e 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentProperty.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentProperty.java @@ -446,16 +446,19 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP return true; } - AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) type; - AnnotatedType[] arguments = parameterizedType.getAnnotatedActualTypeArguments(); + if (type instanceof AnnotatedParameterizedType) { - if (typeInformation.isCollectionLike() && arguments.length == 1) { - return AnnotatedElementUtils.hasAnnotation(arguments[0], annotationType); - } + AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) type; + AnnotatedType[] arguments = parameterizedType.getAnnotatedActualTypeArguments(); - if (typeInformation.isMap() && arguments.length == 2) { - return AnnotatedElementUtils.hasAnnotation(arguments[0], annotationType) - || AnnotatedElementUtils.hasAnnotation(arguments[1], annotationType); + if (typeInformation.isCollectionLike() && arguments.length == 1) { + return AnnotatedElementUtils.hasAnnotation(arguments[0], annotationType); + } + + if (typeInformation.isMap() && arguments.length == 2) { + return AnnotatedElementUtils.hasAnnotation(arguments[0], annotationType) + || AnnotatedElementUtils.hasAnnotation(arguments[1], annotationType); + } } return false; diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentPropertyUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentPropertyUnitTests.java index 17cdf42cc..bb59226c3 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentPropertyUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/mapping/BasicCassandraPersistentPropertyUnitTests.java @@ -19,8 +19,11 @@ import static org.assertj.core.api.Assertions.*; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.AnnotatedType; import java.lang.reflect.Field; import java.util.Date; +import java.util.List; +import java.util.Map; import java.util.UUID; import org.junit.Test; @@ -106,6 +109,32 @@ public class BasicCassandraPersistentPropertyUnitTests { assertThat(timeUUIDProperty.getDataType().getName()).isEqualTo(Name.TIMEUUID); } + @Test // DATACASS-568 + public void shouldFindAnnotationInMapTypes() { + + assertThat(findAnnotatedType(TypeWithMaps.class, "parameterized")).isNull(); + assertThat(findAnnotatedType(TypeWithMaps.class, "parameterizedWithAnnotation")).isNotNull(); + assertThat(findAnnotatedType(TypeWithMaps.class, "parameterizedWithParameterAnnotation")).isNotNull(); + assertThat(findAnnotatedType(TypeWithMaps.class, "unparameterized")).isNull(); + assertThat(findAnnotatedType(TypeWithMaps.class, "unparameterizedWithAnnotation")).isNotNull(); + assertThat(findAnnotatedType(TypeWithMaps.class, "subtype")).isNull(); + } + + @Test // DATACASS-568 + public void shouldFindAnnotationInCollectionTypes() { + + assertThat(findAnnotatedType(TypeWithCollections.class, "parameterized")).isNull(); + assertThat(findAnnotatedType(TypeWithCollections.class, "parameterizedWithAnnotation")).isNotNull(); + assertThat(findAnnotatedType(TypeWithCollections.class, "parameterizedWithParameterAnnotation")).isNotNull(); + assertThat(findAnnotatedType(TypeWithCollections.class, "unparameterized")).isNull(); + assertThat(findAnnotatedType(TypeWithCollections.class, "unparameterizedWithAnnotation")).isNotNull(); + assertThat(findAnnotatedType(TypeWithCollections.class, "subtype")).isNull(); + } + + private AnnotatedType findAnnotatedType(Class type, String parameterized) { + return getPropertyFor(TypeWithMaps.class, parameterized).findAnnotatedType(Indexed.class); + } + private CassandraPersistentProperty getPropertyFor(Class type, String fieldName) { Field field = ReflectionUtils.findField(type, fieldName); @@ -181,4 +210,38 @@ public class BasicCassandraPersistentPropertyUnitTests { @CassandraType(type = Name.TIMEUUID) UUID timeUUID; } + + static class TypeWithMaps { + + Map parameterized; + + @Indexed Map parameterizedWithAnnotation; + + Map parameterizedWithParameterAnnotation; + + Map unparameterized; + + @Indexed Map unparameterizedWithAnnotation; + + MapType subtype; + } + + static class TypeWithCollections { + + List parameterized; + + @Indexed List parameterizedWithAnnotation; + + List<@Indexed String> parameterizedWithParameterAnnotation; + + List unparameterized; + + @Indexed List unparameterizedWithAnnotation; + + ListType subtype; + } + + interface MapType extends Map {} + + interface ListType extends List {} }