public void produceContent(final ContentEncoder encoder, final IOControl ioctrl)
     throws IOException {
   encoder.write(this.buf);
   if (!this.buf.hasRemaining()) {
     encoder.complete();
   }
 }
  public void outputReady(NHttpServerConnection conn, ContentEncoder encoder) {
    try {
      ProtocolState protocolState = SourceContext.getState(conn);

      // special case to handle WSDLs
      if (protocolState == ProtocolState.WSDL_RESPONSE_DONE) {
        // we need to shut down if the shutdown flag is set
        HttpContext context = conn.getContext();
        ContentOutputBuffer outBuf =
            (ContentOutputBuffer) context.getAttribute("synapse.response-source-buffer");
        int bytesWritten = outBuf.produceContent(encoder);
        if (metrics != null && bytesWritten > 0) {
          metrics.incrementBytesSent(bytesWritten);
        }

        conn.requestInput();
        if (outBuf instanceof SimpleOutputBuffer && !((SimpleOutputBuffer) outBuf).hasData()) {
          sourceConfiguration.getSourceConnections().releaseConnection(conn);
        }

        return;
      }

      if (protocolState != ProtocolState.RESPONSE_HEAD
          && protocolState != ProtocolState.RESPONSE_BODY) {
        log.warn(
            "Illegal incoming connection state: "
                + protocolState
                + " . Possibly two send backs "
                + "are happening for the same request");

        handleInvalidState(conn, "Trying to write response body");
        return;
      }

      SourceContext.updateState(conn, ProtocolState.RESPONSE_BODY);

      SourceResponse response = SourceContext.getResponse(conn);

      int bytesSent = response.write(conn, encoder);

      if (encoder.isCompleted()) {
        HttpContext context = conn.getContext();
        if (context.getAttribute(PassThroughConstants.REQ_ARRIVAL_TIME) != null
            && context.getAttribute(PassThroughConstants.REQ_DEPARTURE_TIME) != null
            && context.getAttribute(PassThroughConstants.RES_HEADER_ARRIVAL_TIME) != null) {

          if (latencyView != null) {
            latencyView.notifyTimes(
                (Long) context.getAttribute(PassThroughConstants.REQ_ARRIVAL_TIME),
                (Long) context.getAttribute(PassThroughConstants.REQ_DEPARTURE_TIME),
                (Long) context.getAttribute(PassThroughConstants.RES_HEADER_ARRIVAL_TIME),
                System.currentTimeMillis());
          } else if (s2sLatencyView != null) {
            s2sLatencyView.notifyTimes(
                (Long) context.getAttribute(PassThroughConstants.REQ_ARRIVAL_TIME),
                (Long) context.getAttribute(PassThroughConstants.REQ_DEPARTURE_TIME),
                (Long) context.getAttribute(PassThroughConstants.RES_HEADER_ARRIVAL_TIME),
                System.currentTimeMillis());
          }
        }

        context.removeAttribute(PassThroughConstants.REQ_ARRIVAL_TIME);
        context.removeAttribute(PassThroughConstants.REQ_DEPARTURE_TIME);
        context.removeAttribute(PassThroughConstants.RES_HEADER_ARRIVAL_TIME);
      }

      metrics.incrementBytesSent(bytesSent);
    } catch (IOException e) {
      logIOException(conn, e);

      informWriterError(conn);

      SourceContext.updateState(conn, ProtocolState.CLOSING);
      sourceConfiguration.getSourceConnections().shutDownConnection(conn);
    }
  }