Esempio n. 1
0
  public void testXPathNodeListTest() throws Exception {
    String xml =
        "<foo><person id=\"1\">Claus<country>SE</country></person>"
            + "<person id=\"2\">Jonathan<country>CA</country></person></foo>";
    Document doc = context.getTypeConverter().convertTo(Document.class, xml);

    Object result = xpath("/foo/person").nodeSetResult().evaluate(createExchange(doc));
    assertNotNull(result);

    String s = context.getTypeConverter().convertTo(String.class, result);
    assertEquals(ObjectHelper.between(xml, "<foo>", "</foo>"), s);
  }
Esempio n. 2
0
  /**
   * Choose one of the available methods to invoke if we can match the message body to the body
   * parameter
   *
   * @param pojo the bean to invoke a method on
   * @param exchange the message exchange
   * @param name an optional name of the method that must match, use <tt>null</tt> to indicate all
   *     methods
   * @return the method to invoke or null if no definitive method could be matched
   * @throws AmbiguousMethodCallException is thrown if cannot choose method due to ambiguity
   */
  protected MethodInfo chooseMethod(Object pojo, Exchange exchange, String name)
      throws AmbiguousMethodCallException {
    // @Handler should be select first
    // then any single method that has a custom @annotation
    // or any single method that has a match parameter type that matches the Exchange payload
    // and last then try to select the best among the rest

    // must use defensive copy, to avoid altering the shared lists
    // and we want to remove unwanted operations from these local lists
    final List<MethodInfo> localOperationsWithBody = new ArrayList<MethodInfo>(operationsWithBody);
    final List<MethodInfo> localOperationsWithNoBody =
        new ArrayList<MethodInfo>(operationsWithNoBody);
    final List<MethodInfo> localOperationsWithCustomAnnotation =
        new ArrayList<MethodInfo>(operationsWithCustomAnnotation);
    final List<MethodInfo> localOperationsWithHandlerAnnotation =
        new ArrayList<MethodInfo>(operationsWithHandlerAnnotation);

    // remove all abstract methods
    removeAllAbstractMethods(localOperationsWithBody);
    removeAllAbstractMethods(localOperationsWithNoBody);
    removeAllAbstractMethods(localOperationsWithCustomAnnotation);
    removeAllAbstractMethods(localOperationsWithHandlerAnnotation);

    if (name != null) {
      // filter all lists to only include methods with this name
      removeNonMatchingMethods(localOperationsWithHandlerAnnotation, name);
      removeNonMatchingMethods(localOperationsWithCustomAnnotation, name);
      removeNonMatchingMethods(localOperationsWithBody, name);
      removeNonMatchingMethods(localOperationsWithNoBody, name);
    } else {
      // remove all getter/setter as we do not want to consider these methods
      removeAllSetterOrGetterMethods(localOperationsWithHandlerAnnotation);
      removeAllSetterOrGetterMethods(localOperationsWithCustomAnnotation);
      removeAllSetterOrGetterMethods(localOperationsWithBody);
      removeAllSetterOrGetterMethods(localOperationsWithNoBody);
    }

    if (localOperationsWithHandlerAnnotation.size() > 1) {
      // if we have more than 1 @Handler then its ambiguous
      throw new AmbiguousMethodCallException(exchange, localOperationsWithHandlerAnnotation);
    }

    if (localOperationsWithHandlerAnnotation.size() == 1) {
      // methods with handler should be preferred
      return localOperationsWithHandlerAnnotation.get(0);
    } else if (localOperationsWithCustomAnnotation.size() == 1) {
      // if there is one method with an annotation then use that one
      return localOperationsWithCustomAnnotation.get(0);
    }

    // named method and with no parameters
    boolean noParameters = name != null && name.endsWith("()");
    if (noParameters && localOperationsWithNoBody.size() == 1) {
      // if there was a method name configured and it has no parameters, then use the method with no
      // body (eg no parameters)
      return localOperationsWithNoBody.get(0);
    } else if (!noParameters
        && localOperationsWithBody.size() == 1
        && localOperationsWithCustomAnnotation.isEmpty()) {
      // if there is one method with body then use that one
      return localOperationsWithBody.get(0);
    }

    Collection<MethodInfo> possibleOperations = new ArrayList<MethodInfo>();
    possibleOperations.addAll(localOperationsWithBody);
    possibleOperations.addAll(localOperationsWithCustomAnnotation);

    if (!possibleOperations.isEmpty()) {

      MethodInfo answer = null;

      if (name != null) {
        // do we have hardcoded parameters values provided from the method name then use that for
        // matching
        String parameters = ObjectHelper.between(name, "(", ")");
        if (parameters != null) {
          // special as we have hardcoded parameters, so we need to choose method that matches those
          // parameters the best
          LOG.trace("Choosing best matching method matching parameters: {}", parameters);
          answer = chooseMethodWithMatchingParameters(exchange, parameters, possibleOperations);
        }
      }
      if (answer == null) {
        // multiple possible operations so find the best suited if possible
        answer =
            chooseMethodWithMatchingBody(
                exchange, possibleOperations, localOperationsWithCustomAnnotation);
      }
      if (answer == null && possibleOperations.size() > 1) {
        answer = getSingleCovariantMethod(possibleOperations);
      }

      if (answer == null) {
        throw new AmbiguousMethodCallException(exchange, possibleOperations);
      } else {
        return answer;
      }
    }

    // not possible to determine
    return null;
  }
Esempio n. 3
0
  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;
  }