Esempio n. 1
0
  private MethodInfo chooseMethodWithMatchingParameters(
      Exchange exchange, String parameters, Collection<MethodInfo> operationList)
      throws AmbiguousMethodCallException {
    // we have hardcoded parameters so need to match that with the given operations
    Iterator<?> it = ObjectHelper.createIterator(parameters);
    int count = 0;
    while (it.hasNext()) {
      it.next();
      count++;
    }

    List<MethodInfo> operations = new ArrayList<MethodInfo>();
    for (MethodInfo info : operationList) {
      if (info.getParameters().size() == count) {
        operations.add(info);
      }
    }

    if (operations.isEmpty()) {
      return null;
    } else if (operations.size() == 1) {
      return operations.get(0);
    }

    // okay we still got multiple operations, so need to match the best one
    List<MethodInfo> candidates = new ArrayList<MethodInfo>();
    for (MethodInfo info : operations) {
      it = ObjectHelper.createIterator(parameters);
      int index = 0;
      boolean matches = true;
      while (it.hasNext()) {
        String parameter = (String) it.next();
        Class<?> parameterType = BeanHelper.getValidParameterType(parameter);
        Class<?> expectedType = info.getParameters().get(index).getType();

        if (parameterType != null && expectedType != null) {
          if (!parameterType.isAssignableFrom(expectedType)) {
            matches = false;
            break;
          }
        }

        index++;
      }

      if (matches) {
        candidates.add(info);
      }
    }

    if (candidates.size() > 1) {
      MethodInfo answer = getSingleCovariantMethod(candidates);
      if (answer == null) {
        throw new AmbiguousMethodCallException(exchange, candidates);
      }
      return answer;
    }
    return candidates.size() == 1 ? candidates.get(0) : null;
  }
  @Override
  public void populateCamelHeaders(
      HttpResponse response,
      Map<String, Object> headers,
      Exchange exchange,
      NettyHttpConfiguration configuration)
      throws Exception {
    LOG.trace("populateCamelHeaders: {}", response);

    headers.put(Exchange.HTTP_RESPONSE_CODE, response.getStatus().getCode());
    headers.put(Exchange.HTTP_RESPONSE_TEXT, response.getStatus().getReasonPhrase());

    for (String name : response.headers().names()) {
      // mapping the content-type
      if (name.toLowerCase().equals("content-type")) {
        name = Exchange.CONTENT_TYPE;
      }
      // add the headers one by one, and use the header filter strategy
      List<String> values = response.headers().getAll(name);
      Iterator<?> it = ObjectHelper.createIterator(values);
      while (it.hasNext()) {
        Object extracted = it.next();
        LOG.trace("HTTP-header: {}", extracted);
        if (headerFilterStrategy != null
            && !headerFilterStrategy.applyFilterToExternalHeaders(name, extracted, exchange)) {
          NettyHttpHelper.appendHeader(headers, name, extracted);
        }
      }
    }
  }
  /**
   * Copied from CamelBlueprintHelper since there it is also a private method.
   *
   * <p>Gets the bundle descriptors as {@link URL} resources.
   *
   * @param descriptors the bundle descriptors, can be separated by comma
   * @return the bundle descriptors.
   * @throws FileNotFoundException is thrown if a bundle descriptor cannot be found
   */
  private static Collection<URL> getBlueprintDescriptors(String descriptors)
      throws FileNotFoundException, MalformedURLException {
    List<URL> answer = new ArrayList<URL>();
    String descriptor = descriptors;
    if (descriptor != null) {
      // there may be more resources separated by comma
      Iterator<Object> it = ObjectHelper.createIterator(descriptor);
      while (it.hasNext()) {
        String s = (String) it.next();
        LOG.trace("Resource descriptor: {}", s);

        // remove leading / to be able to load resource from the classpath
        s = FileUtil.stripLeadingSeparator(s);

        // if there is wildcards for *.xml then we need to find the urls from the package
        if (s.endsWith("*.xml")) {
          String packageName = s.substring(0, s.length() - 5);
          // remove trailing / to be able to load resource from the classpath
          Enumeration<URL> urls = ObjectHelper.loadResourcesAsURL(packageName);
          while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            File dir = new File(url.getFile());
            if (dir.isDirectory()) {
              File[] files = dir.listFiles();
              if (files != null) {
                for (File file : files) {
                  if (file.isFile() && file.exists() && file.getName().endsWith(".xml")) {
                    String name = packageName + file.getName();
                    LOG.debug("Resolving resource: {}", name);
                    URL xmlUrl = ObjectHelper.loadResourceAsURL(name);
                    if (xmlUrl != null) {
                      answer.add(xmlUrl);
                    }
                  }
                }
              }
            }
          }
        } else {
          LOG.debug("Resolving resource: {}", s);
          URL url = ResourceHelper.resolveMandatoryResourceAsUrl(RESOLVER, s);
          if (url == null) {
            throw new FileNotFoundException("Resource " + s + " not found");
          }
          answer.add(url);
        }
      }
    } else {
      throw new IllegalArgumentException(
          "No bundle descriptor configured. Override getBlueprintDescriptor() or getBlueprintDescriptors() method");
    }

    if (answer.isEmpty()) {
      throw new IllegalArgumentException(
          "Cannot find any resources in classpath from descriptor " + descriptors);
    }
    return answer;
  }
Esempio n. 4
0
    @SuppressWarnings("unchecked")
    public <T> T evaluate(Exchange exchange, Class<T> type) {
      Object body = exchange.getIn().getBody();
      boolean multiParameterArray = false;
      if (exchange.getIn().getHeader(Exchange.BEAN_MULTI_PARAMETER_ARRAY) != null) {
        multiParameterArray =
            exchange.getIn().getHeader(Exchange.BEAN_MULTI_PARAMETER_ARRAY, Boolean.class);
        if (multiParameterArray) {
          // Just change the message body to an Object array
          if (!(body instanceof Object[])) {
            body = exchange.getIn().getBody(Object[].class);
          }
        }
      }

      // if there was an explicit method name to invoke, then we should support using
      // any provided parameter values in the method name
      String methodName = exchange.getIn().getHeader(Exchange.BEAN_METHOD_NAME, "", String.class);
      // the parameter values is between the parenthesis
      String methodParameters = ObjectHelper.betweenOuterPair(methodName, '(', ')');
      // use an iterator to walk the parameter values
      Iterator<?> it = null;
      if (methodParameters != null) {
        // split the parameters safely separated by comma, but beware that we can have
        // quoted parameters which contains comma as well, so do a safe quote split
        String[] parameters = StringQuoteHelper.splitSafeQuote(methodParameters, ',', true);
        it = ObjectHelper.createIterator(parameters, ",", true);
      }

      // remove headers as they should not be propagated
      // we need to do this before the expressions gets evaluated as it may contain
      // a @Bean expression which would by mistake read these headers. So the headers
      // must be removed at this point of time
      exchange.getIn().removeHeader(Exchange.BEAN_MULTI_PARAMETER_ARRAY);
      exchange.getIn().removeHeader(Exchange.BEAN_METHOD_NAME);

      Object[] answer = evaluateParameterExpressions(exchange, body, multiParameterArray, it);
      return (T) answer;
    }
  @Override
  public void populateCamelHeaders(
      HttpRequest request,
      Map<String, Object> headers,
      Exchange exchange,
      NettyHttpConfiguration configuration)
      throws Exception {
    LOG.trace("populateCamelHeaders: {}", request);

    // NOTE: these headers is applied using the same logic as camel-http/camel-jetty to be
    // consistent

    headers.put(Exchange.HTTP_METHOD, request.getMethod().getName());
    // strip query parameters from the uri
    String s = request.getUri();
    if (s.contains("?")) {
      s = ObjectHelper.before(s, "?");
    }

    // we want the full path for the url, as the client may provide the url in the HTTP headers as
    // absolute or relative, eg
    //   /foo
    //   http://servername/foo
    String http = configuration.isSsl() ? "https://" : "http://";
    if (!s.startsWith(http)) {
      if (configuration.getPort() != 80) {
        s = http + configuration.getHost() + ":" + configuration.getPort() + s;
      } else {
        s = http + configuration.getHost() + s;
      }
    }

    headers.put(Exchange.HTTP_URL, s);
    // uri is without the host and port
    URI uri = new URI(request.getUri());
    // uri is path and query parameters
    headers.put(Exchange.HTTP_URI, uri.getPath());
    headers.put(Exchange.HTTP_QUERY, uri.getQuery());
    headers.put(Exchange.HTTP_RAW_QUERY, uri.getRawQuery());

    // strip the starting endpoint path so the path is relative to the endpoint uri
    String path = uri.getPath();
    if (configuration.getPath() != null && path.startsWith(configuration.getPath())) {
      path = path.substring(configuration.getPath().length());
    }
    headers.put(Exchange.HTTP_PATH, path);

    if (LOG.isTraceEnabled()) {
      LOG.trace("HTTP-Method {}", request.getMethod().getName());
      LOG.trace("HTTP-Uri {}", request.getUri());
    }

    for (String name : request.headers().names()) {
      // mapping the content-type
      if (name.toLowerCase(Locale.US).equals("content-type")) {
        name = Exchange.CONTENT_TYPE;
      }

      if (name.toLowerCase(Locale.US).equals("authorization")) {
        String value = request.headers().get(name);
        // store a special header that this request was authenticated using HTTP Basic
        if (value != null && value.trim().startsWith("Basic")) {
          if (headerFilterStrategy != null
              && !headerFilterStrategy.applyFilterToExternalHeaders(
                  NettyHttpConstants.HTTP_AUTHENTICATION, "Basic", exchange)) {
            NettyHttpHelper.appendHeader(headers, NettyHttpConstants.HTTP_AUTHENTICATION, "Basic");
          }
        }
      }

      // add the headers one by one, and use the header filter strategy
      List<String> values = request.headers().getAll(name);
      Iterator<?> it = ObjectHelper.createIterator(values);
      while (it.hasNext()) {
        Object extracted = it.next();
        Object decoded = shouldUrlDecodeHeader(configuration, name, extracted, "UTF-8");
        LOG.trace("HTTP-header: {}", extracted);
        if (headerFilterStrategy != null
            && !headerFilterStrategy.applyFilterToExternalHeaders(name, decoded, exchange)) {
          NettyHttpHelper.appendHeader(headers, name, decoded);
        }
      }
    }

    // add uri parameters as headers to the Camel message
    if (request.getUri().contains("?")) {
      String query = ObjectHelper.after(request.getUri(), "?");
      Map<String, Object> uriParameters = URISupport.parseQuery(query, false, true);

      for (Map.Entry<String, Object> entry : uriParameters.entrySet()) {
        String name = entry.getKey();
        Object values = entry.getValue();
        Iterator<?> it = ObjectHelper.createIterator(values);
        while (it.hasNext()) {
          Object extracted = it.next();
          Object decoded = shouldUrlDecodeHeader(configuration, name, extracted, "UTF-8");
          LOG.trace("URI-Parameter: {}", extracted);
          if (headerFilterStrategy != null
              && !headerFilterStrategy.applyFilterToExternalHeaders(name, decoded, exchange)) {
            NettyHttpHelper.appendHeader(headers, name, decoded);
          }
        }
      }
    }

    // if body is application/x-www-form-urlencoded then extract the body as query string and append
    // as headers
    // if it is a bridgeEndpoint we need to skip this part of work
    if (request.getMethod().getName().equals("POST")
        && request.headers().get(Exchange.CONTENT_TYPE) != null
        && request
            .headers()
            .get(Exchange.CONTENT_TYPE)
            .startsWith(NettyHttpConstants.CONTENT_TYPE_WWW_FORM_URLENCODED)
        && !configuration.isBridgeEndpoint()) {

      String charset = "UTF-8";

      // Push POST form params into the headers to retain compatibility with DefaultHttpBinding
      String body = request.getContent().toString(Charset.forName(charset));
      if (ObjectHelper.isNotEmpty(body)) {
        for (String param : body.split("&")) {
          String[] pair = param.split("=", 2);
          if (pair.length == 2) {
            String name = shouldUrlDecodeHeader(configuration, "", pair[0], charset);
            String value = shouldUrlDecodeHeader(configuration, name, pair[1], charset);
            if (headerFilterStrategy != null
                && !headerFilterStrategy.applyFilterToExternalHeaders(name, value, exchange)) {
              NettyHttpHelper.appendHeader(headers, name, value);
            }
          } else {
            throw new IllegalArgumentException(
                "Invalid parameter, expected to be a pair but was " + param);
          }
        }
      }
    }
  }
  @Override
  public HttpRequest toNettyRequest(
      Message message, String uri, NettyHttpConfiguration configuration) throws Exception {
    LOG.trace("toNettyRequest: {}", message);

    // the message body may already be a Netty HTTP response
    if (message.getBody() instanceof HttpRequest) {
      return (HttpRequest) message.getBody();
    }

    // just assume GET for now, we will later change that to the actual method to use
    HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri);

    TypeConverter tc = message.getExchange().getContext().getTypeConverter();

    // if we bridge endpoint then we need to skip matching headers with the HTTP_QUERY to avoid
    // sending
    // duplicated headers to the receiver, so use this skipRequestHeaders as the list of headers to
    // skip
    Map<String, Object> skipRequestHeaders = null;
    if (configuration.isBridgeEndpoint()) {
      String queryString = message.getHeader(Exchange.HTTP_QUERY, String.class);
      if (queryString != null) {
        skipRequestHeaders = URISupport.parseQuery(queryString, false, true);
      }
      // Need to remove the Host key as it should be not used
      message.getHeaders().remove("host");
    }

    // append headers
    // must use entrySet to ensure case of keys is preserved
    for (Map.Entry<String, Object> entry : message.getHeaders().entrySet()) {
      String key = entry.getKey();
      Object value = entry.getValue();

      // we should not add headers for the parameters in the uri if we bridge the endpoint
      // as then we would duplicate headers on both the endpoint uri, and in HTTP headers as well
      if (skipRequestHeaders != null && skipRequestHeaders.containsKey(key)) {
        continue;
      }

      // use an iterator as there can be multiple values. (must not use a delimiter)
      final Iterator<?> it = ObjectHelper.createIterator(value, null, true);
      while (it.hasNext()) {
        String headerValue = tc.convertTo(String.class, it.next());

        if (headerValue != null
            && headerFilterStrategy != null
            && !headerFilterStrategy.applyFilterToCamelHeaders(
                key, headerValue, message.getExchange())) {
          LOG.trace("HTTP-Header: {}={}", key, headerValue);
          request.headers().add(key, headerValue);
        }
      }
    }

    Object body = message.getBody();
    if (body != null) {
      // support bodies as native Netty
      ChannelBuffer buffer;
      if (body instanceof ChannelBuffer) {
        buffer = (ChannelBuffer) body;
      } else {
        // try to convert to buffer first
        buffer = message.getBody(ChannelBuffer.class);
        if (buffer == null) {
          // fallback to byte array as last resort
          byte[] data = message.getMandatoryBody(byte[].class);
          buffer = ChannelBuffers.copiedBuffer(data);
        }
      }
      if (buffer != null) {
        request.setContent(buffer);
        int len = buffer.readableBytes();
        // set content-length
        request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, len);
        LOG.trace("Content-Length: {}", len);
      } else {
        // we do not support this kind of body
        throw new NoTypeConversionAvailableException(body, ChannelBuffer.class);
      }
    }

    // update HTTP method accordingly as we know if we have a body or not
    HttpMethod method = NettyHttpHelper.createMethod(message, body != null);
    request.setMethod(method);

    // set the content type in the response.
    String contentType = MessageHelper.getContentType(message);
    if (contentType != null) {
      // set content-type
      request.headers().set(HttpHeaders.Names.CONTENT_TYPE, contentType);
      LOG.trace("Content-Type: {}", contentType);
    }

    // must include HOST header as required by HTTP 1.1
    // use URI as its faster than URL (no DNS lookup)
    URI u = new URI(uri);
    String host = u.getHost();
    request.headers().set(HttpHeaders.Names.HOST, host);
    LOG.trace("Host: {}", host);

    // configure connection to accordingly to keep alive configuration
    // favor using the header from the message
    String connection = message.getHeader(HttpHeaders.Names.CONNECTION, String.class);
    if (connection == null) {
      // fallback and use the keep alive from the configuration
      if (configuration.isKeepAlive()) {
        connection = HttpHeaders.Values.KEEP_ALIVE;
      } else {
        connection = HttpHeaders.Values.CLOSE;
      }
    }
    request.headers().set(HttpHeaders.Names.CONNECTION, connection);
    LOG.trace("Connection: {}", connection);
    return request;
  }
  @Override
  public HttpResponse toNettyResponse(Message message, NettyHttpConfiguration configuration)
      throws Exception {
    LOG.trace("toNettyResponse: {}", message);

    // the message body may already be a Netty HTTP response
    if (message.getBody() instanceof HttpResponse) {
      return (HttpResponse) message.getBody();
    }

    // the response code is 200 for OK and 500 for failed
    boolean failed = message.getExchange().isFailed();
    int defaultCode = failed ? 500 : 200;

    int code = message.getHeader(Exchange.HTTP_RESPONSE_CODE, defaultCode, int.class);
    HttpResponse response =
        new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(code));
    LOG.trace("HTTP Status Code: {}", code);

    TypeConverter tc = message.getExchange().getContext().getTypeConverter();

    // append headers
    // must use entrySet to ensure case of keys is preserved
    for (Map.Entry<String, Object> entry : message.getHeaders().entrySet()) {
      String key = entry.getKey();
      Object value = entry.getValue();
      // use an iterator as there can be multiple values. (must not use a delimiter)
      final Iterator<?> it = ObjectHelper.createIterator(value, null);
      while (it.hasNext()) {
        String headerValue = tc.convertTo(String.class, it.next());
        if (headerValue != null
            && headerFilterStrategy != null
            && !headerFilterStrategy.applyFilterToCamelHeaders(
                key, headerValue, message.getExchange())) {
          LOG.trace("HTTP-Header: {}={}", key, headerValue);
          response.headers().add(key, headerValue);
        }
      }
    }

    Object body = message.getBody();
    Exception cause = message.getExchange().getException();
    // support bodies as native Netty
    ChannelBuffer buffer;

    // if there was an exception then use that as body
    if (cause != null) {
      if (configuration.isTransferException()) {
        // we failed due an exception, and transfer it as java serialized object
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(cause);
        oos.flush();
        IOHelper.close(oos, bos);

        // the body should be the serialized java object of the exception
        body = ChannelBuffers.copiedBuffer(bos.toByteArray());
        // force content type to be serialized java object
        message.setHeader(
            Exchange.CONTENT_TYPE, NettyHttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT);
      } else {
        // we failed due an exception so print it as plain text
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        cause.printStackTrace(pw);

        // the body should then be the stacktrace
        body = ChannelBuffers.copiedBuffer(sw.toString().getBytes());
        // force content type to be text/plain as that is what the stacktrace is
        message.setHeader(Exchange.CONTENT_TYPE, "text/plain");
      }

      // and mark the exception as failure handled, as we handled it by returning it as the response
      ExchangeHelper.setFailureHandled(message.getExchange());
    }

    if (body instanceof ChannelBuffer) {
      buffer = (ChannelBuffer) body;
    } else {
      // try to convert to buffer first
      buffer = message.getBody(ChannelBuffer.class);
      if (buffer == null) {
        // fallback to byte array as last resort
        byte[] data = message.getBody(byte[].class);
        if (data != null) {
          buffer = ChannelBuffers.copiedBuffer(data);
        } else {
          // and if byte array fails then try String
          String str;
          if (body != null) {
            str = message.getMandatoryBody(String.class);
          } else {
            str = "";
          }
          buffer = ChannelBuffers.copiedBuffer(str.getBytes());
        }
      }
    }
    if (buffer != null) {
      response.setContent(buffer);
      // We just need to reset the readerIndex this time
      if (buffer.readerIndex() == buffer.writerIndex()) {
        buffer.setIndex(0, buffer.writerIndex());
      }
      // TODO How to enable the chunk transport
      int len = buffer.readableBytes();
      // set content-length
      response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, len);
      LOG.trace("Content-Length: {}", len);
    }

    // set the content type in the response.
    String contentType = MessageHelper.getContentType(message);
    if (contentType != null) {
      // set content-type
      response.headers().set(HttpHeaders.Names.CONTENT_TYPE, contentType);
      LOG.trace("Content-Type: {}", contentType);
    }

    // configure connection to accordingly to keep alive configuration
    // favor using the header from the message
    String connection = message.getHeader(HttpHeaders.Names.CONNECTION, String.class);
    // Read the connection header from the exchange property
    if (connection == null) {
      connection = message.getExchange().getProperty(HttpHeaders.Names.CONNECTION, String.class);
    }
    if (connection == null) {
      // fallback and use the keep alive from the configuration
      if (configuration.isKeepAlive()) {
        connection = HttpHeaders.Values.KEEP_ALIVE;
      } else {
        connection = HttpHeaders.Values.CLOSE;
      }
    }
    response.headers().set(HttpHeaders.Names.CONNECTION, connection);
    // Just make sure we close the channel when the connection value is close
    if (connection.equalsIgnoreCase(HttpHeaders.Values.CLOSE)) {
      message.setHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, true);
    }
    LOG.trace("Connection: {}", connection);

    return response;
  }
Esempio n. 8
0
  private MethodInfo chooseMethodWithMatchingParameters(
      Exchange exchange, String parameters, Collection<MethodInfo> operationList)
      throws AmbiguousMethodCallException {
    // we have hardcoded parameters so need to match that with the given operations
    Iterator<?> it = ObjectHelper.createIterator(parameters);
    int count = 0;
    while (it.hasNext()) {
      it.next();
      count++;
    }

    List<MethodInfo> operations = new ArrayList<MethodInfo>();
    for (MethodInfo info : operationList) {
      if (info.getParameters().size() == count) {
        operations.add(info);
      }
    }

    if (operations.isEmpty()) {
      return null;
    } else if (operations.size() == 1) {
      return operations.get(0);
    }

    // okay we still got multiple operations, so need to match the best one
    List<MethodInfo> candidates = new ArrayList<MethodInfo>();
    MethodInfo fallbackCandidate = null;
    for (MethodInfo info : operations) {
      it = ObjectHelper.createIterator(parameters, ",", false);
      int index = 0;
      boolean matches = true;
      while (it.hasNext()) {
        String parameter = (String) it.next();
        if (parameter != null) {
          // must trim
          parameter = parameter.trim();
        }

        Class<?> parameterType = BeanHelper.getValidParameterType(parameter);
        Class<?> expectedType = info.getParameters().get(index).getType();

        if (parameterType != null && expectedType != null) {

          // if its a simple language then we need to evaluate the expression
          // so we have the result and can find out what type the parameter actually is
          if (StringHelper.hasStartToken(parameter, "simple")) {
            LOG.trace(
                "Evaluating simple expression for parameter #{}: {} to determine the class type of the parameter",
                index,
                parameter);
            Object out =
                getCamelContext()
                    .resolveLanguage("simple")
                    .createExpression(parameter)
                    .evaluate(exchange, Object.class);
            if (out != null) {
              parameterType = out.getClass();
            }
          }

          // skip java.lang.Object type, when we have multiple possible methods we want to avoid it
          // if possible
          if (Object.class.equals(expectedType)) {
            fallbackCandidate = info;
            matches = false;
            break;
          }

          boolean matchingTypes = isParameterMatchingType(parameterType, expectedType);
          if (!matchingTypes) {
            matches = false;
            break;
          }
        }

        index++;
      }

      if (matches) {
        candidates.add(info);
      }
    }

    if (candidates.size() > 1) {
      MethodInfo answer = getSingleCovariantMethod(candidates);
      if (answer != null) {
        return answer;
      }
    }
    return candidates.size() == 1 ? candidates.get(0) : fallbackCandidate;
  }
Esempio n. 9
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;
  }
Esempio n. 10
0
  public void process(Exchange exchange) throws Exception {
    // if we bridge endpoint then we need to skip matching headers with the HTTP_QUERY to avoid
    // sending
    // duplicated headers to the receiver, so use this skipRequestHeaders as the list of headers to
    // skip
    Map<String, Object> skipRequestHeaders = null;

    if (getEndpoint().isBridgeEndpoint()) {
      exchange.setProperty(Exchange.SKIP_GZIP_ENCODING, Boolean.TRUE);
      String queryString = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class);
      if (queryString != null) {
        skipRequestHeaders = URISupport.parseQuery(queryString);
      }
      // Need to remove the Host key as it should be not used
      exchange.getIn().getHeaders().remove("host");
    }
    HttpMethod method = createMethod(exchange);
    Message in = exchange.getIn();
    String httpProtocolVersion = in.getHeader(Exchange.HTTP_PROTOCOL_VERSION, String.class);
    if (httpProtocolVersion != null) {
      // set the HTTP protocol version
      HttpMethodParams params = method.getParams();
      params.setVersion(HttpVersion.parse(httpProtocolVersion));
    }

    HeaderFilterStrategy strategy = getEndpoint().getHeaderFilterStrategy();

    // propagate headers as HTTP headers
    for (Map.Entry<String, Object> entry : in.getHeaders().entrySet()) {
      String key = entry.getKey();
      Object headerValue = in.getHeader(key);

      if (headerValue != null) {
        // use an iterator as there can be multiple values. (must not use a delimiter, and allow
        // empty values)
        final Iterator<?> it = ObjectHelper.createIterator(headerValue, null, true);

        // the value to add as request header
        final List<String> values = new ArrayList<String>();

        // if its a multi value then check each value if we can add it and for multi values they
        // should be combined into a single value
        while (it.hasNext()) {
          String value =
              exchange.getContext().getTypeConverter().convertTo(String.class, it.next());

          // we should not add headers for the parameters in the uri if we bridge the endpoint
          // as then we would duplicate headers on both the endpoint uri, and in HTTP headers as
          // well
          if (skipRequestHeaders != null && skipRequestHeaders.containsKey(key)) {
            continue;
          }
          if (value != null
              && strategy != null
              && !strategy.applyFilterToCamelHeaders(key, value, exchange)) {
            values.add(value);
          }
        }

        // add the value(s) as a http request header
        if (values.size() > 0) {
          // use the default toString of a ArrayList to create in the form [xxx, yyy]
          // if multi valued, for a single value, then just output the value as is
          String s = values.size() > 1 ? values.toString() : values.get(0);
          method.addRequestHeader(key, s);
        }
      }
    }

    // lets store the result in the output message.
    try {
      if (LOG.isDebugEnabled()) {
        LOG.debug("Executing http {} method: {}", method.getName(), method.getURI().toString());
      }
      int responseCode = executeMethod(method);
      LOG.debug("Http responseCode: {}", responseCode);

      if (!throwException) {
        // if we do not use failed exception then populate response for all response codes
        populateResponse(exchange, method, in, strategy, responseCode);
      } else {
        if (responseCode >= 100 && responseCode < 300) {
          // only populate response for OK response
          populateResponse(exchange, method, in, strategy, responseCode);
        } else {
          // operation failed so populate exception to throw
          throw populateHttpOperationFailedException(exchange, method, responseCode);
        }
      }
    } finally {
      method.releaseConnection();
    }
  }