Пример #1
0
  public void dispatch(ServletContext context, String path) {
    boolean dispatch = false;
    AsyncContextEvent event;
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("dispatch {} -> {}", toStringLocked(), path);

      boolean started = false;
      event = _event;
      switch (_async) {
        case STARTED:
          started = true;
          break;
        case EXPIRING:
        case ERRORING:
        case ERRORED:
          break;
        default:
          throw new IllegalStateException(this.getStatusStringLocked());
      }
      _async = Async.DISPATCH;

      if (context != null) _event.setDispatchContext(context);
      if (path != null) _event.setDispatchPath(path);

      if (started) {
        switch (_state) {
          case DISPATCHED:
          case ASYNC_IO:
          case ASYNC_WOKEN:
            break;
          case ASYNC_WAIT:
            _state = State.ASYNC_WOKEN;
            dispatch = true;
            break;
          default:
            LOG.warn("async dispatched when complete {}", this);
            break;
        }
      }
    }

    cancelTimeout(event);
    if (dispatch) scheduleDispatch();
  }
Пример #2
0
  protected void onError(Throwable failure) {
    final List<AsyncListener> listeners;
    final AsyncContextEvent event;
    final Request baseRequest = _channel.getRequest();

    int code = HttpStatus.INTERNAL_SERVER_ERROR_500;
    String reason = null;
    if (failure instanceof BadMessageException) {
      BadMessageException bme = (BadMessageException) failure;
      code = bme.getCode();
      reason = bme.getReason();
    } else if (failure instanceof UnavailableException) {
      if (((UnavailableException) failure).isPermanent()) code = HttpStatus.NOT_FOUND_404;
      else code = HttpStatus.SERVICE_UNAVAILABLE_503;
    }

    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onError {} {}", toStringLocked(), failure);

      // Set error on request.
      if (_event != null) {
        if (_event.getThrowable() != null)
          throw new IllegalStateException("Error already set", _event.getThrowable());
        _event.addThrowable(failure);
        _event.getSuppliedRequest().setAttribute(ERROR_STATUS_CODE, code);
        _event.getSuppliedRequest().setAttribute(ERROR_EXCEPTION, failure);
        _event
            .getSuppliedRequest()
            .setAttribute(
                RequestDispatcher.ERROR_EXCEPTION_TYPE,
                failure == null ? null : failure.getClass());

        _event.getSuppliedRequest().setAttribute(ERROR_MESSAGE, reason != null ? reason : null);
      } else {
        Throwable error = (Throwable) baseRequest.getAttribute(ERROR_EXCEPTION);
        if (error != null) throw new IllegalStateException("Error already set", error);
        baseRequest.setAttribute(ERROR_STATUS_CODE, code);
        baseRequest.setAttribute(ERROR_EXCEPTION, failure);
        baseRequest.setAttribute(
            RequestDispatcher.ERROR_EXCEPTION_TYPE, failure == null ? null : failure.getClass());
        baseRequest.setAttribute(ERROR_MESSAGE, reason != null ? reason : null);
      }

      // Are we blocking?
      if (_async == null) {
        // Only called from within HttpChannel Handling, so much be dispatched, let's stay
        // dispatched!
        if (_state == State.DISPATCHED) {
          _state = State.THROWN;
          return;
        }
        throw new IllegalStateException(this.getStatusStringLocked());
      }

      // We are Async
      _async = Async.ERRORING;
      listeners = _asyncListeners;
      event = _event;
    }

    if (listeners != null) {
      Runnable task =
          new Runnable() {
            @Override
            public void run() {
              for (AsyncListener listener : listeners) {
                try {
                  listener.onError(event);
                } catch (Throwable x) {
                  LOG.warn(x + " while invoking onError listener " + listener);
                  LOG.debug(x);
                }
              }
            }

            @Override
            public String toString() {
              return "onError";
            }
          };
      runInContext(event, task);
    }

    boolean dispatch = false;
    try (Locker.Lock lock = _locker.lock()) {
      switch (_async) {
        case ERRORING:
          {
            // Still in this state ? The listeners did not invoke API methods
            // and the container must provide a default error dispatch.
            _async = Async.ERRORED;
            break;
          }
        case DISPATCH:
        case COMPLETE:
          {
            // The listeners called dispatch() or complete().
            break;
          }
        default:
          {
            throw new IllegalStateException(toString());
          }
      }

      if (_state == State.ASYNC_WAIT) {
        _state = State.ASYNC_WOKEN;
        dispatch = true;
      }
    }

    if (dispatch) {
      if (LOG.isDebugEnabled()) LOG.debug("Dispatch after error {}", this);
      scheduleDispatch();
    }
  }
Пример #3
0
  protected void onTimeout() {
    final List<AsyncListener> listeners;
    AsyncContextEvent event;
    try (Locker.Lock lock = _locker.lock()) {
      if (DEBUG) LOG.debug("onTimeout {}", toStringLocked());

      if (_async != Async.STARTED) return;
      _async = Async.EXPIRING;
      event = _event;
      listeners = _asyncListeners;
    }

    final AtomicReference<Throwable> error = new AtomicReference<Throwable>();
    if (listeners != null) {
      Runnable task =
          new Runnable() {
            @Override
            public void run() {
              for (AsyncListener listener : listeners) {
                try {
                  listener.onTimeout(event);
                } catch (Throwable x) {
                  LOG.warn(x + " while invoking onTimeout listener " + listener);
                  LOG.debug(x);
                  if (error.get() == null) error.set(x);
                  else error.get().addSuppressed(x);
                }
              }
            }

            @Override
            public String toString() {
              return "onTimeout";
            }
          };

      runInContext(event, task);
    }

    Throwable th = error.get();
    boolean dispatch = false;
    try (Locker.Lock lock = _locker.lock()) {
      switch (_async) {
        case EXPIRING:
          _async = th == null ? Async.EXPIRED : Async.ERRORING;
          break;

        case COMPLETE:
        case DISPATCH:
          if (th != null) {
            LOG.ignore(th);
            th = null;
          }
          break;

        default:
          throw new IllegalStateException();
      }

      if (_state == State.ASYNC_WAIT) {
        _state = State.ASYNC_WOKEN;
        dispatch = true;
      }
    }

    if (th != null) {
      if (LOG.isDebugEnabled()) LOG.debug("Error after async timeout {}", this, th);
      onError(th);
    }

    if (dispatch) {
      if (LOG.isDebugEnabled()) LOG.debug("Dispatch after async timeout {}", this);
      scheduleDispatch();
    }
  }