Browse Source

DATACMNS-1200 - Guard casts to primitive type in ClassGeneratingEntityInstantiator.

We now insert assertions for primitive types before passing these to the actual constructor to prevent NullPointerExceptions. We also output the index/parameter name if the parameter was null.

Original pull request: #255.
pull/271/head
Mark Paluch 9 years ago committed by Oliver Gierke
parent
commit
f45e2be383
  1. 21
      src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java
  2. 11
      src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java

21
src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java

@ -23,6 +23,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.asm.ClassWriter; import org.springframework.asm.ClassWriter;
@ -399,6 +400,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
Constructor<?> ctor = constructor.getConstructor(); Constructor<?> ctor = constructor.getConstructor();
Class<?>[] parameterTypes = ctor.getParameterTypes(); Class<?>[] parameterTypes = ctor.getParameterTypes();
List<? extends Parameter<Object, ?>> parameters = constructor.getParameters();
for (int i = 0; i < parameterTypes.length; i++) { for (int i = 0; i < parameterTypes.length; i++) {
@ -409,6 +411,11 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
mv.visitInsn(AALOAD); mv.visitInsn(AALOAD);
if (parameterTypes[i].isPrimitive()) { if (parameterTypes[i].isPrimitive()) {
mv.visitInsn(DUP);
String parameterName = parameters.size() > i ? parameters.get(i).getName() : null;
insertAssertNotNull(mv, parameterName == null ? String.format("at index %d", i) : parameterName);
insertUnboxInsns(mv, Type.getType(parameterTypes[i]).toString().charAt(0), ""); insertUnboxInsns(mv, Type.getType(parameterTypes[i]).toString().charAt(0), "");
} else { } else {
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(parameterTypes[i])); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(parameterTypes[i]));
@ -438,6 +445,20 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator {
mv.visitLdcInsn(idx); mv.visitLdcInsn(idx);
} }
/**
* Insert not {@literal null} assertion for a parameter.
*
* @param mv the method visitor into which instructions should be inserted
* @param parameterName name of the parameter to create the appropriate assertion message.
*/
private void insertAssertNotNull(MethodVisitor mv, String parameterName) {
// Assert.notNull(property)
mv.visitLdcInsn(String.format("Parameter %s must not be null!", parameterName));
mv.visitMethodInsn(INVOKESTATIC, "org/springframework/util/Assert", "notNull",
String.format("(%s%s)V", String.format("L%s;", JAVA_LANG_OBJECT), "Ljava/lang/String;"), false);
}
/** /**
* Insert any necessary cast and value call to convert from a boxed type to a primitive value. * Insert any necessary cast and value call to convert from a boxed type to a primitive value.
* <p> * <p>

11
src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java

@ -264,6 +264,17 @@ public class ClassGeneratingEntityInstantiatorUnitTests<P extends PersistentProp
}); });
} }
@Test // DATACMNS-1200
public void instantiateObjectCtor1ParamIntWithoutValue() {
doReturn(ObjectCtor1ParamInt.class).when(entity).getType();
doReturn(PreferredConstructorDiscoverer.discover(ObjectCtor1ParamInt.class))//
.when(entity).getPersistenceConstructor();
assertThatThrownBy(() -> this.instance.createInstance(entity, provider)) //
.hasCauseInstanceOf(IllegalArgumentException.class);
}
@Test // DATACMNS-578, DATACMNS-1126 @Test // DATACMNS-578, DATACMNS-1126
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void instantiateObjectCtor7ParamsString5IntsString() { public void instantiateObjectCtor7ParamsString5IntsString() {

Loading…
Cancel
Save