/* ------------------------------------------------------------ */
  public void commitResponse(boolean last) throws IOException {
    if (!_generator.isCommitted()) {
      _generator.setResponse(_response.getStatus(), _response.getReason());
      try {
        // If the client was expecting 100 continues, but we sent something
        // else, then we need to close the connection
        if (_expect100Continue && _response.getStatus() != 100) _generator.setPersistent(false);
        _generator.completeHeader(_responseFields, last);
      } catch (IOException io) {
        throw io;
      } catch (RuntimeException e) {
        LOG.warn("header full: " + e);

        _response.reset();
        _generator.reset(true);
        _generator.setResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, null);
        _generator.completeHeader(_responseFields, Generator.LAST);
        _generator.complete();
        throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR_500);
      }
    }
    if (last) _generator.complete();
  }
  /* ------------------------------------------------------------ */
  protected void handleRequest() throws IOException {
    boolean error = false;

    String threadName = null;
    try {
      if (LOG.isDebugEnabled()) {
        threadName = Thread.currentThread().getName();
        Thread.currentThread().setName(threadName + " - " + _uri);
      }

      // Loop here to handle async request redispatches.
      // The loop is controlled by the call to async.unhandle in the
      // finally block below.  If call is from a non-blocking connector,
      // then the unhandle will return false only if an async dispatch has
      // already happened when unhandle is called.   For a blocking connector,
      // the wait for the asynchronous dispatch or timeout actually happens
      // within the call to unhandle().

      final Server server = _server;
      boolean handling = _request._async.handling() && server != null && server.isRunning();
      while (handling) {
        _request.setHandled(false);

        String info = null;
        try {
          _uri.getPort();
          info = URIUtil.canonicalPath(_uri.getDecodedPath());
          if (info == null && !_request.getMethod().equals(HttpMethods.CONNECT))
            throw new HttpException(400);
          _request.setPathInfo(info);

          if (_out != null) _out.reopen();

          if (_request._async.isInitial()) {
            _request.setDispatcherType(DispatcherType.REQUEST);
            _connector.customize(_endp, _request);
            server.handle(this);
          } else {
            _request.setDispatcherType(DispatcherType.ASYNC);
            server.handleAsync(this);
          }
        } catch (ContinuationThrowable e) {
          LOG.ignore(e);
        } catch (EofException e) {
          LOG.debug(e);
          error = true;
          _request.setHandled(true);
        } catch (RuntimeIOException e) {
          LOG.debug(e);
          error = true;
          _request.setHandled(true);
        } catch (HttpException e) {
          LOG.debug(e);
          error = true;
          _request.setHandled(true);
          _response.sendError(e.getStatus(), e.getReason());
        } catch (Throwable e) {
          if (e instanceof ThreadDeath) throw (ThreadDeath) e;

          LOG.warn(String.valueOf(_uri), e);
          error = true;
          _request.setHandled(true);
          _generator.sendError(info == null ? 400 : 500, null, null, true);
        } finally {
          handling = !_request._async.unhandle() && server.isRunning() && _server != null;
        }
      }
    } finally {
      if (threadName != null) Thread.currentThread().setName(threadName);

      if (_request._async.isUncompleted()) {
        _request._async.doComplete();

        if (_expect100Continue) {
          LOG.debug("100 continues not sent");
          // We didn't send 100 continues, but the latest interpretation
          // of the spec (see httpbis) is that the client will either
          // send the body anyway, or close.  So we no longer need to
          // do anything special here other than make the connection not persistent
          _expect100Continue = false;
          if (!_response.isCommitted()) _generator.setPersistent(false);
        }

        if (_endp.isOpen()) {
          if (error) {
            _endp.shutdownOutput();
            _generator.setPersistent(false);
            if (!_generator.isComplete()) _response.complete();
          } else {
            if (!_response.isCommitted() && !_request.isHandled())
              _response.sendError(HttpServletResponse.SC_NOT_FOUND);
            _response.complete();
            if (_generator.isPersistent()) _connector.persist(_endp);
          }
        } else {
          _response.complete();
        }

        _request.setHandled(true);
      }
    }
  }