@Override
 public boolean parsedHeader(HttpField field) {
   if (updateState(State.RECEIVE, State.RECEIVE)) {
     HttpExchange exchange = connection.getExchange();
     // The exchange may be null if it failed concurrently
     if (exchange != null) {
       HttpConversation conversation = exchange.getConversation();
       HttpResponse response = exchange.getResponse();
       ResponseNotifier notifier = connection.getDestination().getResponseNotifier();
       boolean process =
           notifier.notifyHeader(conversation.getResponseListeners(), response, field);
       if (process) {
         response.getHeaders().add(field);
         HttpHeader fieldHeader = field.getHeader();
         if (fieldHeader != null) {
           switch (fieldHeader) {
             case SET_COOKIE:
             case SET_COOKIE2:
               {
                 storeCookie(exchange.getRequest().getURI(), field);
                 break;
               }
             default:
               {
                 break;
               }
           }
         }
       }
     }
   }
   return false;
 }
  @Override
  public boolean headerComplete() {
    if (updateState(State.RECEIVE, State.RECEIVE)) {
      HttpExchange exchange = connection.getExchange();
      // The exchange may be null if it failed concurrently
      if (exchange != null) {
        HttpConversation conversation = exchange.getConversation();
        HttpResponse response = exchange.getResponse();
        LOG.debug("Headers {}", response);
        ResponseNotifier notifier = connection.getDestination().getResponseNotifier();
        notifier.notifyHeaders(conversation.getResponseListeners(), response);

        Enumeration<String> contentEncodings =
            response.getHeaders().getValues(HttpHeader.CONTENT_ENCODING.asString(), ",");
        if (contentEncodings != null) {
          for (ContentDecoder.Factory factory :
              connection.getHttpClient().getContentDecoderFactories()) {
            while (contentEncodings.hasMoreElements()) {
              if (factory.getEncoding().equalsIgnoreCase(contentEncodings.nextElement())) {
                this.decoder = factory.newContentDecoder();
                break;
              }
            }
          }
        }
      }
    }
    return false;
  }
  @Override
  public boolean startResponse(HttpVersion version, int status, String reason) {
    if (updateState(State.IDLE, State.RECEIVE)) {
      HttpExchange exchange = connection.getExchange();
      // The exchange may be null if it failed concurrently
      if (exchange != null) {
        HttpConversation conversation = exchange.getConversation();
        HttpResponse response = exchange.getResponse();

        String method = exchange.getRequest().method();
        parser.setHeadResponse(HttpMethod.HEAD.is(method) || HttpMethod.CONNECT.is(method));
        response.version(version).status(status).reason(reason);

        // Probe the protocol handlers
        HttpClient client = connection.getHttpClient();
        ProtocolHandler protocolHandler =
            client.findProtocolHandler(exchange.getRequest(), response);
        Response.Listener handlerListener = null;
        if (protocolHandler != null) {
          handlerListener = protocolHandler.getResponseListener();
          LOG.debug("Found protocol handler {}", protocolHandler);
        }
        exchange.getConversation().updateResponseListeners(handlerListener);

        LOG.debug("Receiving {}", response);
        ResponseNotifier notifier = connection.getDestination().getResponseNotifier();
        notifier.notifyBegin(conversation.getResponseListeners(), response);
      }
    }
    return false;
  }
  @Override
  public boolean content(ByteBuffer buffer) {
    if (updateState(State.RECEIVE, State.RECEIVE)) {
      HttpExchange exchange = connection.getExchange();
      // The exchange may be null if it failed concurrently
      if (exchange != null) {
        HttpConversation conversation = exchange.getConversation();
        HttpResponse response = exchange.getResponse();
        LOG.debug("Content {}: {} bytes", response, buffer.remaining());

        ContentDecoder decoder = this.decoder;
        if (decoder != null) {
          buffer = decoder.decode(buffer);
          LOG.debug("{} {}: {} bytes", decoder, response, buffer.remaining());
        }

        ResponseNotifier notifier = connection.getDestination().getResponseNotifier();
        notifier.notifyContent(conversation.getResponseListeners(), response, buffer);
      }
    }
    return false;
  }
  protected boolean fail(Throwable failure) {
    HttpExchange exchange = connection.getExchange();
    // In case of a response error, the failure has already been notified
    // and it is possible that a further attempt to read in the receive
    // loop throws an exception that reenters here but without exchange;
    // or, the server could just have timed out the connection.
    if (exchange == null) return false;

    AtomicMarkableReference<Result> completion = exchange.responseComplete(failure);
    if (!completion.isMarked()) return false;

    parser.close();
    decoder = null;

    while (true) {
      State current = state.get();
      if (updateState(current, State.FAILURE)) break;
    }

    exchange.terminateResponse();

    HttpResponse response = exchange.getResponse();
    HttpConversation conversation = exchange.getConversation();
    ResponseNotifier notifier = connection.getDestination().getResponseNotifier();
    notifier.notifyFailure(conversation.getResponseListeners(), response, failure);
    LOG.debug("Failed {} {}", response, failure);

    Result result = completion.getReference();
    if (result != null) {
      connection.complete(exchange, false);

      notifier.notifyComplete(conversation.getResponseListeners(), result);
    }

    return true;
  }