From f45e2be383c66bbd8ea63f3cc1744ff4d58f3f31 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 18 Oct 2017 14:27:05 +0200 Subject: [PATCH] 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. --- .../ClassGeneratingEntityInstantiator.java | 21 +++++++++++++++++++ ...GeneratingEntityInstantiatorUnitTests.java | 11 ++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java b/src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java index 144b3e005..a2092ba2e 100644 --- a/src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java +++ b/src/main/java/org/springframework/data/convert/ClassGeneratingEntityInstantiator.java @@ -23,6 +23,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.springframework.asm.ClassWriter; @@ -399,6 +400,7 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { Constructor ctor = constructor.getConstructor(); Class[] parameterTypes = ctor.getParameterTypes(); + List> parameters = constructor.getParameters(); for (int i = 0; i < parameterTypes.length; i++) { @@ -409,6 +411,11 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { mv.visitInsn(AALOAD); 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), ""); } else { mv.visitTypeInsn(CHECKCAST, Type.getInternalName(parameterTypes[i])); @@ -438,6 +445,20 @@ public class ClassGeneratingEntityInstantiator implements EntityInstantiator { 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. *

diff --git a/src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java b/src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java index 242b1a701..bb3f263cd 100755 --- a/src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java +++ b/src/test/java/org/springframework/data/convert/ClassGeneratingEntityInstantiatorUnitTests.java @@ -264,6 +264,17 @@ public class ClassGeneratingEntityInstantiatorUnitTests

this.instance.createInstance(entity, provider)) // + .hasCauseInstanceOf(IllegalArgumentException.class); + } + @Test // DATACMNS-578, DATACMNS-1126 @SuppressWarnings("unchecked") public void instantiateObjectCtor7ParamsString5IntsString() {