@Override public TypedValue execute(EvaluationContext context, Object... arguments) throws AccessException { try { ReflectionHelper.convertArguments( context.getTypeConverter(), arguments, this.ctor, this.varargsPosition); if (this.ctor.isVarArgs()) { arguments = ReflectionHelper.setupArgumentsForVarargsInvocation( this.ctor.getParameterTypes(), arguments); } ReflectionUtils.makeAccessible(this.ctor); return new TypedValue(this.ctor.newInstance(arguments)); } catch (Exception ex) { throw new AccessException("Problem invoking constructor: " + this.ctor, ex); } }
if (method.isVarArgs() && argumentTypes.size() >= (paramTypes.length - 1)) { matchInfo = ReflectionHelper.compareArgumentsVarargs(paramDescriptors, argumentTypes, typeConverter); matchInfo = ReflectionHelper.compareArguments(paramDescriptors, argumentTypes, typeConverter); int matchDistance = ReflectionHelper.getTypeDifferenceWeight(paramDescriptors, argumentTypes); if (closeMatch == null || matchDistance < closeMatchDistance) {
boolean argumentConversionOccurred = ReflectionHelper.convertAllArguments(converter, functionArgs, method); if (method.isVarArgs()) { functionArgs = ReflectionHelper.setupArgumentsForVarargsInvocation( method.getParameterTypes(), functionArgs);
matchInfo = ReflectionHelper.compareArgumentsVarargs(paramDescriptors, argumentTypes, typeConverter); matchInfo = ReflectionHelper.compareArguments(paramDescriptors, argumentTypes, typeConverter);
/** * Convert a supplied set of arguments into the requested types. If the parameterTypes are related to * a varargs method then the final entry in the parameterTypes array is going to be an array itself whose * component type should be used as the conversion target for extraneous arguments. (For example, if the * parameterTypes are {Integer, String[]} and the input arguments are {Integer, boolean, float} then both * the boolean and float must be converted to strings). This method does *not* repackage the arguments * into a form suitable for the varargs invocation - a subsequent call to setupArgumentsForVarargsInvocation handles that. * @param converter the converter to use for type conversions * @param arguments the arguments to convert to the requested parameter types * @param method the target Method * @return true if some kind of conversion occurred on the argument * @throws SpelEvaluationException if there is a problem with conversion */ public static boolean convertAllArguments(TypeConverter converter, Object[] arguments, Method method) throws SpelEvaluationException { Integer varargsPosition = (method.isVarArgs() ? method.getParameterCount() - 1 : null); return convertArguments(converter, arguments, method, varargsPosition); }
@Test public void testSetupArguments() { Object[] newArray = ReflectionHelper.setupArgumentsForVarargsInvocation( new Class<?>[] {String[].class}, "a", "b", "c"); assertEquals(1, newArray.length); Object firstParam = newArray[0]; assertEquals(String.class,firstParam.getClass().getComponentType()); Object[] firstParamArray = (Object[]) firstParam; assertEquals(3,firstParamArray.length); assertEquals("a",firstParamArray[0]); assertEquals("b",firstParamArray[1]); assertEquals("c",firstParamArray[2]); }
@Test public void testConvertArguments2() throws Exception { StandardTypeConverter tc = new StandardTypeConverter(); Method oneArg = TestInterface.class.getMethod("oneArg", String.class); Method twoArg = TestInterface.class.getMethod("twoArg", String.class, String[].class); // Simple conversion: int to string Object[] args = new Object[] {3}; ReflectionHelper.convertAllArguments(tc, args, oneArg); checkArguments(args, "3"); // varargs conversion args = new Object[] {3, false, 3.0f}; ReflectionHelper.convertAllArguments(tc, args, twoArg); checkArguments(args, "3", "false", "3.0"); // varargs conversion but no varargs args = new Object[] {3}; ReflectionHelper.convertAllArguments(tc, args, twoArg); checkArguments(args, "3"); // null value args = new Object[] {3, null, 3.0f}; ReflectionHelper.convertAllArguments(tc, args, twoArg); checkArguments(args, "3", null, "3.0"); }
!isFirstEntryInArray(argument, arguments[varargsPosition])) { conversionOccurred = true; // case 3
/** * Used to validate the match returned from a compareArguments call. */ private void checkMatch(Class<?>[] inputTypes, Class<?>[] expectedTypes, StandardTypeConverter typeConverter, ArgumentsMatchKind expectedMatchKind) { ReflectionHelper.ArgumentsMatchInfo matchInfo = ReflectionHelper.compareArguments(getTypeDescriptors(expectedTypes), getTypeDescriptors(inputTypes), typeConverter); if (expectedMatchKind == null) { assertNull("Did not expect them to match in any way", matchInfo); } else { assertNotNull("Should not be a null match", matchInfo); } if (expectedMatchKind == ArgumentsMatchKind.EXACT) { assertTrue(matchInfo.isExactMatch()); } else if (expectedMatchKind == ArgumentsMatchKind.CLOSE) { assertTrue(matchInfo.isCloseMatch()); } else if (expectedMatchKind == ArgumentsMatchKind.REQUIRES_CONVERSION) { assertTrue("expected to be a match requiring conversion, but was " + matchInfo, matchInfo.isMatchRequiringConversion()); } }
/** * Used to validate the match returned from a compareArguments call. */ private void checkMatch2(Class<?>[] inputTypes, Class<?>[] expectedTypes, StandardTypeConverter typeConverter, ArgumentsMatchKind expectedMatchKind) { ReflectionHelper.ArgumentsMatchInfo matchInfo = ReflectionHelper.compareArgumentsVarargs(getTypeDescriptors(expectedTypes), getTypeDescriptors(inputTypes), typeConverter); if (expectedMatchKind == null) { assertNull("Did not expect them to match in any way: " + matchInfo, matchInfo); } else { assertNotNull("Should not be a null match", matchInfo); } if (expectedMatchKind == ArgumentsMatchKind.EXACT) { assertTrue(matchInfo.isExactMatch()); } else if (expectedMatchKind == ArgumentsMatchKind.CLOSE) { assertTrue(matchInfo.isCloseMatch()); } else if (expectedMatchKind == ArgumentsMatchKind.REQUIRES_CONVERSION) { assertTrue("expected to be a match requiring conversion, but was " + matchInfo, matchInfo.isMatchRequiringConversion()); } }
matchInfo = ReflectionHelper.compareArgumentsVarargs(paramDescriptors, argumentTypes, typeConverter); matchInfo = ReflectionHelper.compareArguments(paramDescriptors, argumentTypes, typeConverter);
/** * Convert a supplied set of arguments into the requested types. If the parameterTypes are related to * a varargs method then the final entry in the parameterTypes array is going to be an array itself whose * component type should be used as the conversion target for extraneous arguments. (For example, if the * parameterTypes are {Integer, String[]} and the input arguments are {Integer, boolean, float} then both * the boolean and float must be converted to strings). This method does *not* repackage the arguments * into a form suitable for the varargs invocation - a subsequent call to setupArgumentsForVarargsInvocation handles that. * @param converter the converter to use for type conversions * @param arguments the arguments to convert to the requested parameter types * @param method the target Method * @return true if some kind of conversion occurred on the argument * @throws SpelEvaluationException if there is a problem with conversion */ public static boolean convertAllArguments(TypeConverter converter, Object[] arguments, Method method) throws SpelEvaluationException { Integer varargsPosition = (method.isVarArgs() ? method.getParameterCount() - 1 : null); return convertArguments(converter, arguments, method, varargsPosition); }
@Override public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException { try { if (arguments != null) { this.argumentConversionOccurred = //Nussknacker: here we invoke different implementation SpelEspReflectionHelper.convertArguments(context.getTypeConverter(), arguments, this.method, this.varargsPosition); } if (this.method.isVarArgs()) { arguments = ReflectionHelper.setupArgumentsForVarargsInvocation(this.method.getParameterTypes(), arguments); } ReflectionUtils.makeAccessible(this.method); Object value = this.method.invoke(target, arguments); return new TypedValue(value, new TypeDescriptor(new MethodParameter(this.method, -1)).narrow(value)); } catch (Exception ex) { throw new AccessException("Problem invoking method: " + this.method, ex); } }
!isFirstEntryInArray(argument, arguments[varargsPosition])) { conversionOccurred = true; // case 3
@Override public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException { try { this.argumentConversionOccurred = ReflectionHelper.convertArguments( context.getTypeConverter(), arguments, this.originalMethod, this.varargsPosition); if (this.originalMethod.isVarArgs()) { arguments = ReflectionHelper.setupArgumentsForVarargsInvocation( this.originalMethod.getParameterTypes(), arguments); } ReflectionUtils.makeAccessible(this.methodToInvoke); Object value = this.methodToInvoke.invoke(target, arguments); return new TypedValue(value, new TypeDescriptor(new MethodParameter(this.originalMethod, -1)).narrow(value)); } catch (Exception ex) { throw new AccessException("Problem invoking method: " + this.methodToInvoke, ex); } }
if (method.isVarArgs() && argumentTypes.size() >= (paramTypes.length - 1)) { matchInfo = ReflectionHelper.compareArgumentsVarargs(paramDescriptors, argumentTypes, typeConverter); matchInfo = ReflectionHelper.compareArguments(paramDescriptors, argumentTypes, typeConverter); int matchDistance = ReflectionHelper.getTypeDifferenceWeight(paramDescriptors, argumentTypes); if (closeMatch == null || matchDistance < closeMatchDistance) {
@Override public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException { try { Method m = HasRoleExecutor.class.getMethod("hasRole", String[].class); Object[] args = arguments; if (args != null) { ReflectionHelper.convertAllArguments(tc, args, m); } if (m.isVarArgs()) { args = ReflectionHelper.setupArgumentsForVarargsInvocation(m.getParameterTypes(), args); } return new TypedValue(m.invoke(null, args), new TypeDescriptor(new MethodParameter(m,-1))); } catch (Exception ex) { throw new AccessException("Problem invoking hasRole", ex); } }
matchInfo = ReflectionHelper.compareArgumentsVarargs(paramDescriptors, argumentTypes, typeConverter); matchInfo = ReflectionHelper.compareArguments(paramDescriptors, argumentTypes, typeConverter);
@Test public void testConvertArguments() throws Exception { StandardTypeConverter tc = new StandardTypeConverter(); Method oneArg = TestInterface.class.getMethod("oneArg", String.class); Method twoArg = TestInterface.class.getMethod("twoArg", String.class, String[].class); // basic conversion int>String Object[] args = new Object[] {3}; ReflectionHelper.convertArguments(tc, args, oneArg, null); checkArguments(args, "3"); // varargs but nothing to convert args = new Object[] {3}; ReflectionHelper.convertArguments(tc, args, twoArg, 1); checkArguments(args, "3"); // varargs with nothing needing conversion args = new Object[] {3, "abc", "abc"}; ReflectionHelper.convertArguments(tc, args, twoArg, 1); checkArguments(args, "3", "abc", "abc"); // varargs with conversion required args = new Object[] {3, false ,3.0d}; ReflectionHelper.convertArguments(tc, args, twoArg, 1); checkArguments(args, "3", "false", "3.0"); }
!isFirstEntryInArray(argument, arguments[varargsPosition])) { conversionOccurred = true; // case 3