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.
This commit is contained in:
committed by
Oliver Gierke
parent
d1fc97ea75
commit
f45e2be383
@@ -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>
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user