DATACASS-568 - Guard BasicCassandraPersistentProperty.findAnnotatedType(…) against non-parameterized types.

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.
This commit is contained in:
Mark Paluch
2018-06-14 11:42:48 +02:00
parent 7e64eddbfd
commit 9474b3de91
2 changed files with 74 additions and 8 deletions

View File

@@ -443,16 +443,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;

View File

@@ -19,8 +19,11 @@ import static org.assertj.core.api.Assertions.assertThat;
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;
@@ -107,6 +110,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<String, String> parameterized;
@Indexed Map<String, String> parameterizedWithAnnotation;
Map<String, @Indexed String> parameterizedWithParameterAnnotation;
Map unparameterized;
@Indexed Map unparameterizedWithAnnotation;
MapType subtype;
}
static class TypeWithCollections {
List<String> parameterized;
@Indexed List<String> parameterizedWithAnnotation;
List<@Indexed String> parameterizedWithParameterAnnotation;
List unparameterized;
@Indexed List unparameterizedWithAnnotation;
ListType subtype;
}
interface MapType extends Map<String, String> {}
interface ListType extends List<String> {}
}