Example #1
0
  private Expression createParameterUnmarshalExpressionForAnnotation(
      Class<?> clazz, Method method, Class<?> parameterType, Annotation annotation) {
    if (annotation instanceof AttachmentObjects) {
      return ExpressionBuilder.attachmentObjectsExpression();
    } else if (annotation instanceof Attachments) {
      return ExpressionBuilder.attachmentsExpression();
    } else if (annotation instanceof Property) {
      Property propertyAnnotation = (Property) annotation;
      return ExpressionBuilder.exchangePropertyExpression(propertyAnnotation.value());
    } else if (annotation instanceof ExchangeProperty) {
      ExchangeProperty propertyAnnotation = (ExchangeProperty) annotation;
      return ExpressionBuilder.exchangePropertyExpression(propertyAnnotation.value());
    } else if (annotation instanceof Properties) {
      return ExpressionBuilder.propertiesExpression();
    } else if (annotation instanceof Header) {
      Header headerAnnotation = (Header) annotation;
      return ExpressionBuilder.headerExpression(headerAnnotation.value());
    } else if (annotation instanceof Headers) {
      return ExpressionBuilder.headersExpression();
    } else if (annotation instanceof OutHeaders) {
      return ExpressionBuilder.outHeadersExpression();
    } else if (annotation instanceof ExchangeException) {
      return ExpressionBuilder.exchangeExceptionExpression(
          CastUtils.cast(parameterType, Exception.class));
    } else {
      LanguageAnnotation languageAnnotation =
          annotation.annotationType().getAnnotation(LanguageAnnotation.class);
      if (languageAnnotation != null) {
        Class<?> type = languageAnnotation.factory();
        Object object = camelContext.getInjector().newInstance(type);
        if (object instanceof AnnotationExpressionFactory) {
          AnnotationExpressionFactory expressionFactory = (AnnotationExpressionFactory) object;
          return expressionFactory.createExpression(
              camelContext, annotation, languageAnnotation, parameterType);
        } else {
          LOG.warn(
              "Ignoring bad annotation: "
                  + languageAnnotation
                  + "on method: "
                  + method
                  + " which declares a factory: "
                  + type.getName()
                  + " which does not implement "
                  + AnnotationExpressionFactory.class.getName());
        }
      }
    }

    return null;
  }
Example #2
0
 public static Expression header(String headerName) {
   return ExpressionBuilder.headerExpression(headerName);
 }
 public SetHeaderDefinition(String headerName, String value) {
   super(ExpressionBuilder.constantExpression(value));
   setHeaderName(headerName);
 }
Example #4
0
  private MethodInfo chooseBestPossibleMethodInfo(
      Exchange exchange,
      Collection<MethodInfo> operationList,
      Object body,
      List<MethodInfo> possibles,
      List<MethodInfo> possiblesWithException,
      List<MethodInfo> possibleWithCustomAnnotation)
      throws AmbiguousMethodCallException {

    Exception exception =
        ExpressionBuilder.exchangeExceptionExpression().evaluate(exchange, Exception.class);
    if (exception != null && possiblesWithException.size() == 1) {
      LOG.trace(
          "Exchange has exception set so we prefer method that also has exception as parameter");
      // prefer the method that accepts exception in case we have an exception also
      return possiblesWithException.get(0);
    } else if (possibles.size() == 1) {
      return possibles.get(0);
    } else if (possibles.isEmpty()) {
      LOG.trace("No possible methods so now trying to convert body to parameter types");

      // let's try converting
      Object newBody = null;
      MethodInfo matched = null;
      int matchCounter = 0;
      for (MethodInfo methodInfo : operationList) {
        if (methodInfo.getBodyParameterType() != null) {
          if (methodInfo.getBodyParameterType().isInstance(body)) {
            return methodInfo;
          }

          // we should only try to convert, as we are looking for best match
          Object value =
              exchange
                  .getContext()
                  .getTypeConverter()
                  .tryConvertTo(methodInfo.getBodyParameterType(), exchange, body);
          if (value != null) {
            if (LOG.isTraceEnabled()) {
              LOG.trace(
                  "Converted body from: {} to: {}",
                  body.getClass().getCanonicalName(),
                  methodInfo.getBodyParameterType().getCanonicalName());
            }
            matchCounter++;
            newBody = value;
            matched = methodInfo;
          }
        }
      }
      if (matchCounter > 1) {
        throw new AmbiguousMethodCallException(exchange, Arrays.asList(matched, matched));
      }
      if (matched != null) {
        LOG.trace("Setting converted body: {}", body);
        Message in = exchange.getIn();
        in.setBody(newBody);
        return matched;
      }
    } else {
      // if we only have a single method with custom annotations, let's use that one
      if (possibleWithCustomAnnotation.size() == 1) {
        MethodInfo answer = possibleWithCustomAnnotation.get(0);
        LOG.trace("There are only one method with annotations so we choose it: {}", answer);
        return answer;
      }
      // try to choose among multiple methods with annotations
      MethodInfo chosen = chooseMethodWithCustomAnnotations(exchange, possibles);
      if (chosen != null) {
        return chosen;
      }
      // just make sure the methods aren't all actually the same
      chosen = getSingleCovariantMethod(possibles);
      if (chosen != null) {
        return chosen;
      }
      throw new AmbiguousMethodCallException(exchange, possibles);
    }

    // cannot find a good method to use
    return null;
  }
Example #5
0
  protected MethodInfo createMethodInfo(Class<?> clazz, Method method) {
    Class<?>[] parameterTypes = method.getParameterTypes();
    List<Annotation>[] parametersAnnotations = collectParameterAnnotations(clazz, method);

    List<ParameterInfo> parameters = new ArrayList<ParameterInfo>();
    List<ParameterInfo> bodyParameters = new ArrayList<ParameterInfo>();

    boolean hasCustomAnnotation = false;
    boolean hasHandlerAnnotation =
        ObjectHelper.hasAnnotation(method.getAnnotations(), Handler.class);

    int size = parameterTypes.length;
    if (LOG.isTraceEnabled()) {
      LOG.trace(
          "Creating MethodInfo for class: {} method: {} having {} parameters",
          new Object[] {clazz, method, size});
    }

    for (int i = 0; i < size; i++) {
      Class<?> parameterType = parameterTypes[i];
      Annotation[] parameterAnnotations =
          parametersAnnotations[i].toArray(new Annotation[parametersAnnotations[i].size()]);
      Expression expression =
          createParameterUnmarshalExpression(clazz, method, parameterType, parameterAnnotations);
      hasCustomAnnotation |= expression != null;

      ParameterInfo parameterInfo =
          new ParameterInfo(i, parameterType, parameterAnnotations, expression);
      LOG.trace("Parameter #{}: {}", i, parameterInfo);
      parameters.add(parameterInfo);
      if (expression == null) {
        boolean bodyAnnotation = ObjectHelper.hasAnnotation(parameterAnnotations, Body.class);
        LOG.trace("Parameter #{} has @Body annotation", i);
        hasCustomAnnotation |= bodyAnnotation;
        if (bodyParameters.isEmpty()) {
          // okay we have not yet set the body parameter and we have found
          // the candidate now to use as body parameter
          if (Exchange.class.isAssignableFrom(parameterType)) {
            // use exchange
            expression = ExpressionBuilder.exchangeExpression();
          } else {
            // assume it's the body and it must be mandatory convertible to the parameter type
            // but we allow null bodies in case the message really contains a null body
            expression = ExpressionBuilder.mandatoryBodyExpression(parameterType, true);
          }
          LOG.trace("Parameter #{} is the body parameter using expression {}", i, expression);
          parameterInfo.setExpression(expression);
          bodyParameters.add(parameterInfo);
        } else {
          // will ignore the expression for parameter evaluation
        }
      }
      LOG.trace("Parameter #{} has parameter info: ", i, parameterInfo);
    }

    // now let's add the method to the repository
    return new MethodInfo(
        camelContext,
        clazz,
        method,
        parameters,
        bodyParameters,
        hasCustomAnnotation,
        hasHandlerAnnotation);
  }
Example #6
0
  private MethodInvocation createInvocation(Object pojo, Exchange exchange, Method explicitMethod)
      throws AmbiguousMethodCallException, MethodNotFoundException {
    MethodInfo methodInfo = null;

    // find the explicit method to invoke
    if (explicitMethod != null) {
      for (List<MethodInfo> infos : operations.values()) {
        for (MethodInfo info : infos) {
          if (explicitMethod.equals(info.getMethod())) {
            return info.createMethodInvocation(pojo, exchange);
          }
        }
      }
      throw new MethodNotFoundException(exchange, pojo, explicitMethod.getName());
    }

    String methodName = exchange.getIn().getHeader(Exchange.BEAN_METHOD_NAME, String.class);
    if (methodName != null) {

      // do not use qualifier for name
      String name = methodName;
      if (methodName.contains("(")) {
        name = ObjectHelper.before(methodName, "(");
        // the must be a ending parenthesis
        if (!methodName.endsWith(")")) {
          throw new IllegalArgumentException(
              "Method should end with parenthesis, was " + methodName);
        }
      }
      boolean emptyParameters = methodName.endsWith("()");

      // special for getClass, as we want the user to be able to invoke this method
      // for example to log the class type or the likes
      if ("class".equals(name) || "getClass".equals(name)) {
        try {
          Method method = pojo.getClass().getMethod("getClass");
          methodInfo =
              new MethodInfo(
                  exchange.getContext(),
                  pojo.getClass(),
                  method,
                  Collections.<ParameterInfo>emptyList(),
                  Collections.<ParameterInfo>emptyList(),
                  false,
                  false);
        } catch (NoSuchMethodException e) {
          throw new MethodNotFoundException(exchange, pojo, "getClass");
        }
        // special for length on an array type
      } else if ("length".equals(name) && pojo.getClass().isArray()) {
        try {
          // need to use arrayLength method from ObjectHelper as Camel's bean OGNL support is method
          // invocation based
          // and not for accessing fields. And hence we need to create a MethodInfo instance with a
          // method to call
          // and therefore use arrayLength from ObjectHelper to return the array length field.
          Method method = ObjectHelper.class.getMethod("arrayLength", Object[].class);
          ParameterInfo pi =
              new ParameterInfo(
                  0,
                  Object[].class,
                  null,
                  ExpressionBuilder.mandatoryBodyExpression(Object[].class, true));
          List<ParameterInfo> lpi = new ArrayList<ParameterInfo>(1);
          lpi.add(pi);
          methodInfo =
              new MethodInfo(
                  exchange.getContext(), pojo.getClass(), method, lpi, lpi, false, false);
          // Need to update the message body to be pojo for the invocation
          exchange.getIn().setBody(pojo);
        } catch (NoSuchMethodException e) {
          throw new MethodNotFoundException(exchange, pojo, "getClass");
        }
      } else {
        List<MethodInfo> methods = getOperations(name);
        if (methods != null && methods.size() == 1) {
          // only one method then choose it
          methodInfo = methods.get(0);

          // validate that if we want an explicit no-arg method, then that's what we get
          if (emptyParameters && methodInfo.hasParameters()) {
            throw new MethodNotFoundException(exchange, pojo, methodName, "(with no parameters)");
          }
        } else if (methods != null) {
          // there are more methods with that name so we cannot decide which to use

          // but first let's try to choose a method and see if that complies with the name
          // must use the method name which may have qualifiers
          methodInfo = chooseMethod(pojo, exchange, methodName);

          // validate that if we want an explicit no-arg method, then that's what we get
          if (emptyParameters) {
            if (methodInfo == null || methodInfo.hasParameters()) {
              // we could not find a no-arg method with that name
              throw new MethodNotFoundException(exchange, pojo, methodName, "(with no parameters)");
            }
          }

          if (methodInfo == null
              || (name != null && !name.equals(methodInfo.getMethod().getName()))) {
            throw new AmbiguousMethodCallException(exchange, methods);
          }
        } else {
          // a specific method was given to invoke but not found
          throw new MethodNotFoundException(exchange, pojo, methodName);
        }
      }
    }

    if (methodInfo == null) {
      // no name or type
      methodInfo = chooseMethod(pojo, exchange, null);
    }
    if (methodInfo == null) {
      methodInfo = defaultMethod;
    }
    if (methodInfo != null) {
      LOG.trace("Chosen method to invoke: {} on bean: {}", methodInfo, pojo);
      return methodInfo.createMethodInvocation(pojo, exchange);
    }

    LOG.debug("Cannot find suitable method to invoke on bean: {}", pojo);
    return null;
  }