docs: protected void parsePayload(IAsyncResultHandler<Object> payloadResultHandler) {
          // Strip out any content-length header from the request.  It will very likely
          // no longer be accurate.
          request.getHeaders().remove("Content-Length"); //$NON-NLS-1$
  
          // Configure the api's max payload buffer size, if it's not already set.
          if (api.getMaxPayloadBufferSize() <= 0) {
              api.setMaxPayloadBufferSize(maxPayloadBufferSize);
          }
  
          // Now "handle" the inbound request stream, which will cause bytes to be streamed
          // to the writeStream we provide (which will store the bytes in a buffer for parsing)
          final ByteBuffer buffer = new ByteBuffer(2048);
          inboundStreamHandler.handle(new ISignalWriteStream() {
              private boolean done = false;
  
              @Override
              public void abort(Throwable t) {
                  done = true;
                  payloadResultHandler.handle(AsyncResultImpl.create(new RuntimeException("Inbound request stream aborted.", t))); //$NON-NLS-1$
              }
  
              @Override
              public boolean isFinished() {
                  return done;
              }
  
              @Override
              public void write(IApimanBuffer chunk) {
                  if (done) {
                      return;
                  }
                  if (buffer.length() > api.getMaxPayloadBufferSize()) {
                      payloadResultHandler.handle(AsyncResultImpl.create(new Exception("Max request payload size exceeded."))); //$NON-NLS-1$
                      done = true;
                      return;
                  }
                  buffer.append(chunk);
              }
  
              @Override
              public void end() {
                  if (done) {
                      return;
                  }
                  // When end() is called, the stream of bytes is done and we can parse them into
                  // an appropriate payload object.
                  done = true;
                  if (buffer.length() == 0) {
                      payloadResultHandler.handle(AsyncResultImpl.create(null));
                  } else {
                      payloadIO = null;
                      if ("soap".equalsIgnoreCase(api.getEndpointType())) { //$NON-NLS-1$
                          payloadIO = new SoapPayloadIO();
                      } else if ("rest".equalsIgnoreCase(api.getEndpointType())) { //$NON-NLS-1$
                          if ("xml".equalsIgnoreCase(api.getEndpointContentType())) { //$NON-NLS-1$
                              payloadIO = new XmlPayloadIO();
                          } else if ("json".equalsIgnoreCase(api.getEndpointContentType())) { //$NON-NLS-1$
                              payloadIO = new JsonPayloadIO();
                          }
                      }
                      if (payloadIO == null) {
                          payloadIO = new BytesPayloadIO();
                      }
                      try {
                          Object payload = payloadIO.unmarshall(buffer.getBytes());
                          payloadResultHandler.handle(AsyncResultImpl.create(payload));
                      } catch (Exception e) {
                          payloadResultHandler.handle(AsyncResultImpl.create(new Exception("Failed to parse inbound request payload.", e))); //$NON-NLS-1$
                      }
                  }
              }
  
              /**
               * Because of the way the parsePayload code was written, it's possible
               * with async for apiConnection to be +null+ when this is called.
               *
               * This is because parsePayload invokes inboundStreamHandler before
               * policiesLoadedHandler has had a chance to return (and assigned apiConnection).
               *
               * To work around this we check whether apiConnection is null for #drainHandler
               * and #isFull.
               */
              @Override
              public void drainHandler(IAsyncHandler<Void> drainHandler) {
                  if (apiConnection != null)
                      apiConnection.drainHandler(drainHandler);
              }
  
              @Override
              public boolean isFull() {
                  if (apiConnection != null) {
                      return apiConnection.isFull();
                  } else {
                      return false;
                  }
              }
          });
      }