private void sendUsingOutputStream(MessageContext msgContext) throws AxisFault {

    OMOutputFormat format = NhttpUtil.getOMOutputFormat(msgContext);
    MessageFormatter messageFormatter =
        MessageFormatterDecoratorFactory.createMessageFormatterDecorator(msgContext);
    OutputStream out = (OutputStream) msgContext.getProperty(MessageContext.TRANSPORT_OUT);

    if (msgContext.isServerSide()) {
      OutTransportInfo transportInfo =
          (OutTransportInfo) msgContext.getProperty(Constants.OUT_TRANSPORT_INFO);

      if (transportInfo != null) {
        transportInfo.setContentType(
            messageFormatter.getContentType(msgContext, format, msgContext.getSoapAction()));
      } else {
        throw new AxisFault(Constants.OUT_TRANSPORT_INFO + " has not been set");
      }
    }

    try {
      messageFormatter.writeTo(msgContext, format, out, false);
      out.close();
    } catch (IOException e) {
      handleException("IO Error sending response message", e);
    }
  }
 /**
  * Write the stream to a temporary storage and calculate the content length
  *
  * @param entity HTTPEntity
  * @param messageFormatter message formatter
  * @param msgContext current message context
  * @param format message format
  * @throws IOException if an exception occurred while writing data
  */
 private void setStreamAsTempData(
     BasicHttpEntity entity,
     MessageFormatter messageFormatter,
     MessageContext msgContext,
     OMOutputFormat format)
     throws IOException {
   TemporaryData serialized = new TemporaryData(256, 4096, "http-nio_", ".dat");
   OutputStream out = serialized.getOutputStream();
   try {
     messageFormatter.writeTo(msgContext, format, out, true);
   } finally {
     out.close();
   }
   msgContext.setProperty(NhttpConstants.SERIALIZED_BYTES, serialized);
   entity.setContentLength(serialized.getLength());
 }
  /**
   * Send the passed in response message, asynchronously
   *
   * @param msgContext the message context to be sent
   * @throws AxisFault on error
   */
  private void sendAsyncResponse(MessageContext msgContext) throws AxisFault {

    int contentLength = extractContentLength(msgContext);

    // remove unwanted HTTP headers (if any from the current message)
    removeUnwantedHeaders(msgContext);
    Map transportHeaders = (Map) msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);

    ServerWorker worker = (ServerWorker) msgContext.getProperty(Constants.OUT_TRANSPORT_INFO);
    HttpResponse response = worker.getResponse();

    OMOutputFormat format = NhttpUtil.getOMOutputFormat(msgContext);
    MessageFormatter messageFormatter =
        MessageFormatterDecoratorFactory.createMessageFormatterDecorator(msgContext);
    Boolean noEntityBody = (Boolean) msgContext.getProperty(NhttpConstants.NO_ENTITY_BODY);
    if (noEntityBody == null || Boolean.FALSE == noEntityBody) {
      response.setHeader(
          HTTP.CONTENT_TYPE,
          messageFormatter.getContentType(msgContext, format, msgContext.getSoapAction()));
    } else if (Boolean.TRUE == noEntityBody) {
      ((BasicHttpEntity) response.getEntity()).setChunked(false);
      ((BasicHttpEntity) response.getEntity()).setContentLength(0);

      // Since HTTP HEAD request doesn't contain message body content length of the is set to be 0.
      // To handle
      // content length 0 while serving head method, content length of the backend response is set
      // as the content
      // as synapse cannot calculate content length without providing message body.
      if (transportHeaders.get(NhttpConstants.HTTP_REQUEST_METHOD) != null
          && NhttpConstants.HTTP_HEAD.equals(
              transportHeaders.get(NhttpConstants.HTTP_REQUEST_METHOD))
          && transportHeaders.get(NhttpConstants.ORIGINAL_CONTENT_LEN) != null) {

        ((BasicHttpEntity) response.getEntity())
            .setContentLength(
                Long.parseLong(
                    String.valueOf(transportHeaders.get(NhttpConstants.ORIGINAL_CONTENT_LEN))));
        transportHeaders.remove(NhttpConstants.ORIGINAL_CONTENT_LEN);
        transportHeaders.remove(NhttpConstants.HTTP_REQUEST_METHOD);
      }
    }
    response.setStatusCode(determineHttpStatusCode(msgContext, response));

    // Override the Standard Reason Phrase
    if (msgContext.getProperty(NhttpConstants.HTTP_REASON_PHRASE) != null
        && !msgContext.getProperty(NhttpConstants.HTTP_REASON_PHRASE).equals("")) {
      response.setReasonPhrase(
          msgContext.getProperty(NhttpConstants.HTTP_REASON_PHRASE).toString());
    }

    // set any transport headers
    if (transportHeaders != null && !transportHeaders.values().isEmpty()) {
      Iterator iter = transportHeaders.keySet().iterator();
      while (iter.hasNext()) {
        Object header = iter.next();
        Object value = transportHeaders.get(header);
        if (value != null && header instanceof String && value instanceof String) {
          response.addHeader((String) header, (String) value);

          String excessProp = NhttpConstants.EXCESS_TRANSPORT_HEADERS;

          Map map = (Map) msgContext.getProperty(excessProp);
          if (map != null && map.get(header) != null) {
            log.debug(
                "Number of excess values for "
                    + header
                    + " header is : "
                    + ((Collection) (map.get(header))).size());

            for (Iterator iterator = map.keySet().iterator(); iterator.hasNext(); ) {
              String key = (String) iterator.next();

              for (String excessVal : (Collection<String>) map.get(key)) {
                if (header.equals(key)) {
                  response.addHeader((String) header, (String) excessVal);
                }
              }
            }
          }
        }
      }
    }

    boolean forceContentLength =
        msgContext.isPropertyTrue(NhttpConstants.FORCE_HTTP_CONTENT_LENGTH);
    boolean forceContentLengthCopy =
        msgContext.isPropertyTrue(NhttpConstants.COPY_CONTENT_LENGTH_FROM_INCOMING);

    BasicHttpEntity entity = (BasicHttpEntity) response.getEntity();

    MetricsCollector lstMetrics = worker.getServiceHandler().getMetrics();
    try {
      if (forceContentLength) {
        entity.setChunked(false);
        if (forceContentLengthCopy && contentLength > 0) {
          entity.setContentLength(contentLength);
        } else {
          setStreamAsTempData(entity, messageFormatter, msgContext, format);
        }
      }

      worker.getServiceHandler().commitResponse(worker.getConn(), response);
      lstMetrics.reportResponseCode(response.getStatusLine().getStatusCode());
      OutputStream out = worker.getOutputStream();

      /*
       * if this is a dummy message to handle http 202 case with non-blocking IO
       * write an empty byte array as body
       */
      if (msgContext.isPropertyTrue(NhttpConstants.SC_ACCEPTED) || Boolean.TRUE == noEntityBody) {
        out.write(new byte[0]);
      } else {
        if (forceContentLength) {
          if (forceContentLengthCopy && contentLength > 0) {
            messageFormatter.writeTo(msgContext, format, out, false);
          } else {
            writeMessageFromTempData(out, msgContext);
          }
        } else {
          messageFormatter.writeTo(msgContext, format, out, false);
        }
      }
      out.close();
      if (lstMetrics != null) {
        lstMetrics.incrementMessagesSent();
      }

    } catch (ProtocolException e) {
      log.error(e + " (Synapse may be trying to send an exact response more than once )");
    } catch (HttpException e) {
      if (lstMetrics != null) {
        lstMetrics.incrementFaultsSending();
      }
      handleException(
          "Unexpected HTTP protocol error sending response to : " + worker.getRemoteAddress(), e);
    } catch (ConnectionClosedException e) {
      if (lstMetrics != null) {
        lstMetrics.incrementFaultsSending();
      }
      log.warn("Connection closed by client : " + worker.getRemoteAddress());
    } catch (IllegalStateException e) {
      if (lstMetrics != null) {
        lstMetrics.incrementFaultsSending();
      }
      log.warn("Connection closed by client : " + worker.getRemoteAddress());
    } catch (IOException e) {
      if (lstMetrics != null) {
        lstMetrics.incrementFaultsSending();
      }
      handleException("IO Error sending response message to : " + worker.getRemoteAddress(), e);
    } catch (Exception e) {
      if (lstMetrics != null) {
        lstMetrics.incrementFaultsSending();
      }
      handleException(
          "General Error sending response message to : " + worker.getRemoteAddress(), e);
    }

    InputStream is = worker.getIs();
    if (is != null) {
      try {
        is.close();
      } catch (IOException ignore) {
      }
    }
  }