public AMQP.BasicProperties.Builder buildProperties(Exchange exchange) {
    AMQP.BasicProperties.Builder properties = new AMQP.BasicProperties.Builder();

    Message msg;
    if (exchange.hasOut()) {
      msg = exchange.getOut();
    } else {
      msg = exchange.getIn();
    }

    final Object contentType = msg.removeHeader(RabbitMQConstants.CONTENT_TYPE);
    if (contentType != null) {
      properties.contentType(contentType.toString());
    }

    final Object priority = msg.removeHeader(RabbitMQConstants.PRIORITY);
    if (priority != null) {
      properties.priority(Integer.parseInt(priority.toString()));
    }

    final Object messageId = msg.removeHeader(RabbitMQConstants.MESSAGE_ID);
    if (messageId != null) {
      properties.messageId(messageId.toString());
    }

    final Object clusterId = msg.removeHeader(RabbitMQConstants.CLUSTERID);
    if (clusterId != null) {
      properties.clusterId(clusterId.toString());
    }

    final Object replyTo = msg.removeHeader(RabbitMQConstants.REPLY_TO);
    if (replyTo != null) {
      properties.replyTo(replyTo.toString());
    }

    final Object correlationId = msg.removeHeader(RabbitMQConstants.CORRELATIONID);
    if (correlationId != null) {
      properties.correlationId(correlationId.toString());
    }

    final Object deliveryMode = msg.removeHeader(RabbitMQConstants.DELIVERY_MODE);
    if (deliveryMode != null) {
      properties.deliveryMode(Integer.parseInt(deliveryMode.toString()));
    }

    final Object userId = msg.removeHeader(RabbitMQConstants.USERID);
    if (userId != null) {
      properties.userId(userId.toString());
    }

    final Object type = msg.removeHeader(RabbitMQConstants.TYPE);
    if (type != null) {
      properties.type(type.toString());
    }

    final Object contentEncoding = msg.removeHeader(RabbitMQConstants.CONTENT_ENCODING);
    if (contentEncoding != null) {
      properties.contentEncoding(contentEncoding.toString());
    }

    final Object expiration = msg.removeHeader(RabbitMQConstants.EXPIRATION);
    if (expiration != null) {
      properties.expiration(expiration.toString());
    }

    final Object appId = msg.removeHeader(RabbitMQConstants.APP_ID);
    if (appId != null) {
      properties.appId(appId.toString());
    }

    final Object timestamp = msg.removeHeader(RabbitMQConstants.TIMESTAMP);
    if (timestamp != null) {
      properties.timestamp(convertTimestamp(timestamp));
    }

    final Map<String, Object> headers = msg.getHeaders();
    Map<String, Object> filteredHeaders = new HashMap<>();

    // TODO: Add support for a HeaderFilterStrategy. See:
    // org.apache.camel.component.jms.JmsBinding#shouldOutputHeader
    for (Map.Entry<String, Object> header : headers.entrySet()) {
      // filter header values.
      Object value = getValidRabbitMQHeaderValue(header.getValue());
      if (value != null) {
        filteredHeaders.put(header.getKey(), header.getValue());
      } else if (LOG.isDebugEnabled()) {
        if (header.getValue() == null) {
          LOG.debug("Ignoring header: {} with null value", header.getKey());
        } else {
          LOG.debug(
              "Ignoring header: {} of class: {} with value: {}",
              header.getKey(),
              ObjectHelper.classCanonicalName(header.getValue()),
              header.getValue());
        }
      }
    }

    properties.headers(filteredHeaders);

    return properties;
  }