/** * Evaluate using parameter values where the values can be provided in the method name syntax. * * <p>This methods returns accordingly: * * <ul> * <li><tt>null</tt> - if not a parameter value * <li><tt>Void.TYPE</tt> - if an explicit null, forcing Camel to pass in <tt>null</tt> for * that given parameter * <li>a non <tt>null</tt> value - if the parameter was a parameter value, and to be used * </ul> * * @since 2.9 */ private Object evaluateParameterValue( Exchange exchange, int index, Object parameterValue, Class<?> parameterType) { Object answer = null; // convert the parameter value to a String String exp = exchange .getContext() .getTypeConverter() .convertTo(String.class, exchange, parameterValue); if (exp != null) { // check if its a valid parameter value boolean valid = BeanHelper.isValidParameterValue(exp); if (!valid) { // it may be a parameter type instead, and if so, then we should return null, // as this method is only for evaluating parameter values Boolean isClass = BeanHelper.isAssignableToExpectedType( exchange.getContext().getClassResolver(), exp, parameterType); // the method will return a non null value if exp is a class if (isClass != null) { return null; } } // use simple language to evaluate the expression, as it may use the simple language to // refer to message body, headers etc. Expression expression = null; try { expression = exchange.getContext().resolveLanguage("simple").createExpression(exp); parameterValue = expression.evaluate(exchange, Object.class); // use "null" to indicate the expression returned a null value which is a valid response // we need to honor if (parameterValue == null) { parameterValue = "null"; } } catch (Exception e) { throw new ExpressionEvaluationException( expression, "Cannot create/evaluate simple expression: " + exp + " to be bound to parameter at index: " + index + " on method: " + getMethod(), exchange, e); } // special for explicit null parameter values (as end users can explicit indicate they want // null as parameter) // see method javadoc for details if ("null".equals(parameterValue)) { return Void.TYPE; } // the parameter value may match the expected type, then we use it as-is if (parameterType.isAssignableFrom(parameterValue.getClass())) { valid = true; } else { // the parameter value was not already valid, but since the simple language have evaluated // the expression // which may change the parameterValue, so we have to check it again to see if its now // valid exp = exchange.getContext().getTypeConverter().tryConvertTo(String.class, parameterValue); // String values from the simple language is always valid if (!valid) { // re validate if the parameter was not valid the first time (String values should be // accepted) valid = parameterValue instanceof String || BeanHelper.isValidParameterValue(exp); } } if (valid) { // we need to unquote String parameters, as the enclosing quotes is there to denote a // parameter value if (parameterValue instanceof String) { parameterValue = StringHelper.removeLeadingAndEndingQuotes((String) parameterValue); } if (parameterValue != null) { try { // its a valid parameter value, so convert it to the expected type of the parameter answer = exchange .getContext() .getTypeConverter() .mandatoryConvertTo(parameterType, exchange, parameterValue); if (LOG.isTraceEnabled()) { LOG.trace( "Parameter #{} evaluated as: {} type: ", new Object[] {index, answer, ObjectHelper.type(answer)}); } } catch (Exception e) { if (LOG.isDebugEnabled()) { LOG.debug( "Cannot convert from type: {} to type: {} for parameter #{}", new Object[] {ObjectHelper.type(parameterValue), parameterType, index}); } throw new ParameterBindingException(e, method, index, parameterType, parameterValue); } } } } return answer; }
private boolean matchMethod(Method method, String methodName) { if (methodName == null) { return true; } if (methodName.contains("(") && !methodName.endsWith(")")) { throw new IllegalArgumentException( "Name must have both starting and ending parenthesis, was: " + methodName); } // do not use qualifier for name matching String name = methodName; if (name.contains("(")) { name = ObjectHelper.before(name, "("); } // must match name if (name != null && !name.equals(method.getName())) { return false; } // is it a method with no parameters boolean noParameters = methodName.endsWith("()"); if (noParameters) { return method.getParameterTypes().length == 0; } // match qualifier types which is used to select among overloaded methods String types = ObjectHelper.between(methodName, "(", ")"); if (ObjectHelper.isNotEmpty(types)) { // we must qualify based on types to match method String[] parameters = StringQuoteHelper.splitSafeQuote(types, ','); Iterator<?> it = ObjectHelper.createIterator(parameters); for (int i = 0; i < method.getParameterTypes().length; i++) { if (it.hasNext()) { Class<?> parameterType = method.getParameterTypes()[i]; String qualifyType = (String) it.next(); if (ObjectHelper.isEmpty(qualifyType)) { continue; } // trim the type qualifyType = qualifyType.trim(); if ("*".equals(qualifyType)) { // * is a wildcard so we accept and match that parameter type continue; } if (BeanHelper.isValidParameterValue(qualifyType)) { // its a parameter value, so continue to next parameter // as we should only check for FQN/type parameters continue; } // if qualify type indeed is a class, then it must be assignable with the parameter type Boolean assignable = BeanHelper.isAssignableToExpectedType( getCamelContext().getClassResolver(), qualifyType, parameterType); // the method will return null if the qualifyType is not a class if (assignable != null && !assignable) { return false; } } else { // there method has more parameters than was specified in the method name qualifiers return false; } } // if the method has no more types then we can only regard it as matched // if there are no more qualifiers if (it.hasNext()) { return false; } } // the method matched return true; }