diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/CodeFlow.java b/spring-expression/src/main/java/org/springframework/expression/spel/CodeFlow.java index 245989aacc..ad8c65daa0 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/CodeFlow.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/CodeFlow.java @@ -945,7 +945,8 @@ public class CodeFlow implements Opcodes { // is [[I then we want [I and not [I; if (CodeFlow.isReferenceTypeArray(arraytype)) { mv.visitTypeInsn(ANEWARRAY, arraytype+";"); - } else { + } + else { mv.visitTypeInsn(ANEWARRAY, arraytype); } } @@ -956,19 +957,22 @@ public class CodeFlow implements Opcodes { } /** - * For use in mathematical operators, handles converting from a (possibly boxed) number on the stack to a primitive numeric type. - * For example, from a Integer to a double, just need to call 'Number.doubleValue()' but from an int to a double, need to use - * the bytecode 'i2d'. + * For use in mathematical operators, handles converting from a (possibly boxed) + * number on the stack to a primitive numeric type. + *
For example, from a Integer to a double, just need to call 'Number.doubleValue()' + * but from an int to a double, need to use the bytecode 'i2d'. * @param mv the method visitor when instructions should be appended * @param stackDescriptor a descriptor of the operand on the stack * @param targetDescriptor a primitive type descriptor */ - public static void insertNumericUnboxOrPrimitiveTypeCoercion(MethodVisitor mv, - String stackDescriptor, char targetDecriptor) { + public static void insertNumericUnboxOrPrimitiveTypeCoercion( + MethodVisitor mv, String stackDescriptor, char targetDescriptor) { + if (!CodeFlow.isPrimitive(stackDescriptor)) { - CodeFlow.insertUnboxNumberInsns(mv, targetDecriptor, stackDescriptor); - } else { - CodeFlow.insertAnyNecessaryTypeConversionBytecodes(mv, targetDecriptor, stackDescriptor); + CodeFlow.insertUnboxNumberInsns(mv, targetDescriptor, stackDescriptor); + } + else { + CodeFlow.insertAnyNecessaryTypeConversionBytecodes(mv, targetDescriptor, stackDescriptor); } } diff --git a/spring-test/src/main/java/org/springframework/test/util/ReflectionTestUtils.java b/spring-test/src/main/java/org/springframework/test/util/ReflectionTestUtils.java index 7eb67409d6..4f781e555b 100644 --- a/spring-test/src/main/java/org/springframework/test/util/ReflectionTestUtils.java +++ b/spring-test/src/main/java/org/springframework/test/util/ReflectionTestUtils.java @@ -72,10 +72,8 @@ public class ReflectionTestUtils { /** * Set the {@linkplain Field field} with the given {@code name} on the * provided {@code targetObject} to the supplied {@code value}. - * *
This method delegates to {@link #setField(Object, String, Object, Class)}, * supplying {@code null} for the {@code type} argument. - * * @param targetObject the target object on which to set the field; never {@code null} * @param name the name of the field to set; never {@code null} * @param value the value to set @@ -87,10 +85,8 @@ public class ReflectionTestUtils { /** * Set the {@linkplain Field field} with the given {@code name}/{@code type} * on the provided {@code targetObject} to the supplied {@code value}. - * *
This method delegates to {@link #setField(Object, Class, String, Object, Class)}, * supplying {@code null} for the {@code targetClass} argument. - * * @param targetObject the target object on which to set the field; never {@code null} * @param name the name of the field to set; may be {@code null} if * {@code type} is specified @@ -105,10 +101,8 @@ public class ReflectionTestUtils { /** * Set the static {@linkplain Field field} with the given {@code name} on * the provided {@code targetClass} to the supplied {@code value}. - * *
This method delegates to {@link #setField(Object, Class, String, Object, Class)}, * supplying {@code null} for the {@code targetObject} and {@code type} arguments. - * * @param targetClass the target class on which to set the static field; * never {@code null} * @param name the name of the field to set; never {@code null} @@ -123,10 +117,8 @@ public class ReflectionTestUtils { * Set the static {@linkplain Field field} with the given * {@code name}/{@code type} on the provided {@code targetClass} to * the supplied {@code value}. - * *
This method delegates to {@link #setField(Object, Class, String, Object, Class)}, * supplying {@code null} for the {@code targetObject} argument. - * * @param targetClass the target class on which to set the static field; * never {@code null} * @param name the name of the field to set; may be {@code null} if @@ -144,12 +136,10 @@ public class ReflectionTestUtils { * Set the {@linkplain Field field} with the given {@code name}/{@code type} * on the provided {@code targetObject}/{@code targetClass} to the supplied * {@code value}. - * *
This method traverses the class hierarchy in search of the desired * field. In addition, an attempt will be made to make non-{@code public} * fields accessible, thus allowing one to set {@code protected}, * {@code private}, and package-private fields. - * * @param targetObject the target object on which to set the field; may be * {@code null} if the field is static * @param targetClass the target class on which to set the field; may @@ -171,19 +161,18 @@ public class ReflectionTestUtils { if (targetClass == null) { targetClass = targetObject.getClass(); } - Field field = ReflectionUtils.findField(targetClass, name, type); - // Inline Assert.notNull() to avoid invoking toString() on a non-null target. + Field field = ReflectionUtils.findField(targetClass, name, type); if (field == null) { throw new IllegalArgumentException(String.format( - "Could not find field [%s] of type [%s] on target object [%s] or target class [%s]", name, type, - targetObject, targetClass)); + "Could not find field '%s' of type [%s] on target object [%s] or target class [%s]", name, type, + targetObject, targetClass)); } if (logger.isDebugEnabled()) { logger.debug(String.format( - "Setting field [%s] of type [%s] on target object [%s] or target class [%s] to value [%s]", name, type, - targetObject, targetClass, value)); + "Setting field '%s' of type [%s] on target object [%s] or target class [%s] to value [%s]", name, type, + targetObject, targetClass, value)); } ReflectionUtils.makeAccessible(field); ReflectionUtils.setField(field, targetObject, value); @@ -192,10 +181,8 @@ public class ReflectionTestUtils { /** * Get the value of the {@linkplain Field field} with the given {@code name} * from the provided {@code targetObject}. - * *
This method delegates to {@link #getField(Object, Class, String)}, * supplying {@code null} for the {@code targetClass} argument. - * * @param targetObject the target object from which to get the field; * never {@code null} * @param name the name of the field to get; never {@code null} @@ -209,16 +196,14 @@ public class ReflectionTestUtils { /** * Get the value of the static {@linkplain Field field} with the given * {@code name} from the provided {@code targetClass}. - * *
This method delegates to {@link #getField(Object, Class, String)}, * supplying {@code null} for the {@code targetObject} argument. - * * @param targetClass the target class from which to get the static field; * never {@code null} * @param name the name of the field to get; never {@code null} * @return the field's current value - * @see #getField(Object, String) * @since 4.2 + * @see #getField(Object, String) */ public static Object getField(Class> targetClass, String name) { return getField(null, targetClass, name); @@ -227,24 +212,22 @@ public class ReflectionTestUtils { /** * Get the value of the {@linkplain Field field} with the given {@code name} * from the provided {@code targetObject}/{@code targetClass}. - * *
This method traverses the class hierarchy in search of the desired * field. In addition, an attempt will be made to make non-{@code public} * fields accessible, thus allowing one to get {@code protected}, * {@code private}, and package-private fields. - * * @param targetObject the target object from which to get the field; may be * {@code null} if the field is static * @param targetClass the target class from which to get the field; may * be {@code null} if the field is an instance field * @param name the name of the field to get; never {@code null} * @return the field's current value + * @since 4.2 * @see #getField(Object, String) * @see #getField(Class, String) * @see ReflectionUtils#findField(Class, String, Class) * @see ReflectionUtils#makeAccessible(Field) - * @see ReflectionUtils#getField(Field, Object, Object) - * @since 4.2 + * @see ReflectionUtils#getField(Field, Object) */ public static Object getField(Object targetObject, Class> targetClass, String name) { Assert.isTrue(targetObject != null || targetClass != null, @@ -253,18 +236,17 @@ public class ReflectionTestUtils { if (targetClass == null) { targetClass = targetObject.getClass(); } - Field field = ReflectionUtils.findField(targetClass, name); - // Inline Assert.notNull() to avoid invoking toString() on a non-null target. + Field field = ReflectionUtils.findField(targetClass, name); if (field == null) { throw new IllegalArgumentException( - String.format("Could not find field [%s] on target object [%s] or target class [%s]", name, - targetObject, targetClass)); + String.format("Could not find field '%s' on target object [%s] or target class [%s]", name, + targetObject, targetClass)); } if (logger.isDebugEnabled()) { - logger.debug(String.format("Getting field [%s] from target object [%s] or target class [%s]", name, - targetObject, targetClass)); + logger.debug(String.format("Getting field '%s' from target object [%s] or target class [%s]", name, + targetObject, targetClass)); } ReflectionUtils.makeAccessible(field); return ReflectionUtils.getField(field, targetObject); @@ -273,17 +255,14 @@ public class ReflectionTestUtils { /** * Invoke the setter method with the given {@code name} on the supplied * target object with the supplied {@code value}. - * *
This method traverses the class hierarchy in search of the desired * method. In addition, an attempt will be made to make non-{@code public} * methods accessible, thus allowing one to invoke {@code protected}, * {@code private}, and package-private setter methods. - * *
In addition, this method supports JavaBean-style property * names. For example, if you wish to set the {@code name} property on the * target object, you may pass either "name" or * "setName" as the method name. - * * @param target the target object on which to invoke the specified setter * method * @param name the name of the setter method to invoke or the corresponding @@ -300,17 +279,14 @@ public class ReflectionTestUtils { /** * Invoke the setter method with the given {@code name} on the supplied * target object with the supplied {@code value}. - * *
This method traverses the class hierarchy in search of the desired * method. In addition, an attempt will be made to make non-{@code public} * methods accessible, thus allowing one to invoke {@code protected}, * {@code private}, and package-private setter methods. - * *
In addition, this method supports JavaBean-style property * names. For example, if you wish to set the {@code name} property on the * target object, you may pass either "name" or * "setName" as the method name. - * * @param target the target object on which to invoke the specified setter * method * @param name the name of the setter method to invoke or the corresponding @@ -324,41 +300,41 @@ public class ReflectionTestUtils { public static void invokeSetterMethod(Object target, String name, Object value, Class> type) { Assert.notNull(target, "Target object must not be null"); Assert.hasText(name, "Method name must not be empty"); - Class>[] paramTypes = (type != null ? new Class>[] { type } : null); + Class>[] paramTypes = (type != null ? new Class>[] {type} : null); String setterMethodName = name; if (!name.startsWith(SETTER_PREFIX)) { setterMethodName = SETTER_PREFIX + StringUtils.capitalize(name); } + Method method = ReflectionUtils.findMethod(target.getClass(), setterMethodName, paramTypes); if (method == null && !setterMethodName.equals(name)) { setterMethodName = name; method = ReflectionUtils.findMethod(target.getClass(), setterMethodName, paramTypes); } - Assert.notNull(method, "Could not find setter method [" + setterMethodName + "] on target [" + target - + "] with parameter type [" + type + "]"); + if (method == null) { + throw new IllegalArgumentException("Could not find setter method '" + setterMethodName + + "' on target [" + target + "] with parameter type [" + type + "]"); + } if (logger.isDebugEnabled()) { - logger.debug("Invoking setter method [" + setterMethodName + "] on target [" + target + "]"); + logger.debug("Invoking setter method '" + setterMethodName + "' on target [" + target + "]"); } ReflectionUtils.makeAccessible(method); - ReflectionUtils.invokeMethod(method, target, new Object[] { value }); + ReflectionUtils.invokeMethod(method, target, value); } /** * Invoke the getter method with the given {@code name} on the supplied * target object with the supplied {@code value}. - * *
This method traverses the class hierarchy in search of the desired * method. In addition, an attempt will be made to make non-{@code public} * methods accessible, thus allowing one to invoke {@code protected}, * {@code private}, and package-private getter methods. - * *
In addition, this method supports JavaBean-style property * names. For example, if you wish to get the {@code name} property on the * target object, you may pass either "name" or * "getName" as the method name. - * * @param target the target object on which to invoke the specified getter * method * @param name the name of the getter method to invoke or the corresponding @@ -381,10 +357,13 @@ public class ReflectionTestUtils { getterMethodName = name; method = ReflectionUtils.findMethod(target.getClass(), getterMethodName); } - Assert.notNull(method, "Could not find getter method [" + getterMethodName + "] on target [" + target + "]"); + if (method == null) { + throw new IllegalArgumentException("Could not find getter method '" + getterMethodName + + "' on target [" + target + "]"); + } if (logger.isDebugEnabled()) { - logger.debug("Invoking getter method [" + getterMethodName + "] on target [" + target + "]"); + logger.debug("Invoking getter method '" + getterMethodName + "' on target [" + target + "]"); } ReflectionUtils.makeAccessible(method); return ReflectionUtils.invokeMethod(method, target); @@ -393,12 +372,10 @@ public class ReflectionTestUtils { /** * Invoke the method with the given {@code name} on the supplied target * object with the supplied arguments. - * *
This method traverses the class hierarchy in search of the desired * method. In addition, an attempt will be made to make non-{@code public} * methods accessible, thus allowing one to invoke {@code protected}, * {@code private}, and package-private methods. - * * @param target the target object on which to invoke the specified method * @param name the name of the method to invoke * @param args the arguments to provide to the method @@ -421,17 +398,16 @@ public class ReflectionTestUtils { methodInvoker.prepare(); if (logger.isDebugEnabled()) { - logger.debug("Invoking method [" + name + "] on target [" + target + "] with arguments [" - + ObjectUtils.nullSafeToString(args) + "]"); + logger.debug("Invoking method '" + name + "' on target [" + target + "] with arguments [" + + ObjectUtils.nullSafeToString(args) + "]"); } return (T) methodInvoker.invoke(); } - catch (Exception e) { - ReflectionUtils.handleReflectionException(e); + catch (Exception ex) { + ReflectionUtils.handleReflectionException(ex); + throw new IllegalStateException("Should never get here"); } - - throw new IllegalStateException("Should never get here"); } } diff --git a/spring-test/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java b/spring-test/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java index 43d7b3014a..fa692ed9b1 100644 --- a/spring-test/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java @@ -42,6 +42,7 @@ public class ReflectionTestUtilsTests { private static final Float PI = new Float((float) 22 / 7); private final Person person = new Person(); + private final Component component = new Component(); @Rule @@ -53,6 +54,7 @@ public class ReflectionTestUtilsTests { StaticFields.reset(); } + @Test public void setFieldWithNullTargetObject() throws Exception { exception.expect(IllegalArgumentException.class); @@ -91,7 +93,7 @@ public class ReflectionTestUtilsTests { @Test public void setFieldWithBogusName() throws Exception { exception.expect(IllegalArgumentException.class); - exception.expectMessage(startsWith("Could not find field [bogus]")); + exception.expectMessage(startsWith("Could not find field 'bogus'")); setField(person, "bogus", new Long(99), long.class); }