Ejemplo n.º 1
0
  /**
   * Invoke the next Valve in the sequence. When the invoke returns, check the response state, and
   * output an error report is necessary.
   *
   * @param request The servlet request to be processed
   * @param response The servlet response to be created
   * @exception IOException if an input/output error occurs
   * @exception ServletException if a servlet error occurs
   */
  @Override
  public void invoke(Request request, Response response) throws IOException, ServletException {

    // Perform the request
    getNext().invoke(request, response);

    if (response.isCommitted()) {
      return;
    }

    Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

    if (request.isAsyncStarted() && response.getStatus() < 400 && throwable == null) {
      return;
    }

    if (throwable != null) {

      // The response is an error
      response.setError();

      // Reset the response (if possible)
      try {
        response.reset();
      } catch (IllegalStateException e) {
        // Ignore
      }

      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }

    response.setSuspended(false);

    try {
      report(request, response, throwable);
    } catch (Throwable tt) {
      ExceptionUtils.handleThrowable(tt);
    }

    if (request.isAsyncStarted()) {
      request.getAsyncContext().complete();
    }
  }
  /**
   * Process Comet event.
   *
   * @param request Request to be processed
   * @param response Response to be produced
   * @param event the event
   * @exception IOException if an input/output error occurred
   * @exception ServletException if a servlet error occurred
   */
  @Override
  public final void event(Request request, Response response, CometEvent event)
      throws IOException, ServletException {

    // Select the Context to be used for this Request
    Context context = request.getContext();

    // Bind the context CL to the current thread
    if (context.getLoader() != null) {
      // Not started - it should check for availability first
      // This should eventually move to Engine, it's generic.
      Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
    }

    // Ask this Context to process this request
    context.getPipeline().getFirst().event(request, response, event);

    // Error page processing
    response.setSuspended(false);

    Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

    if (t != null) {
      throwable(request, response, t);
    } else {
      status(request, response);
    }

    // Access a session (if present) to update last accessed time, based on a
    // strict interpretation of the specification
    if (ACCESS_SESSION) {
      request.getSession(false);
    }

    // Restore the context classloader
    Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader());
  }
 @Override
 public void addElement(
     StringBuilder buf, Date date, Request request, Response response, long time) {
   buf.append(wrap(request.getAttribute(attribute)));
 }
  /**
   * Select the appropriate child Context to process this request, based on the specified request
   * URI. If no matching Context can be found, return an appropriate HTTP error.
   *
   * @param request Request to be processed
   * @param response Response to be produced
   * @exception IOException if an input/output error occurred
   * @exception ServletException if a servlet error occurred
   */
  @Override
  public final void invoke(Request request, Response response)
      throws IOException, ServletException {

    /*
     * xujb:
     * 和Engine一样,调用下层的context,让它来做一些处理
     * 自身也处理了一些的逻辑
     *
     * */

    // Select the Context to be used for this Request
    Context context = request.getContext();
    if (context == null) {
      response.sendError(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm.getString("standardHost.noContext"));
      return;
    }

    // Bind the context CL to the current thread
    if (context.getLoader() != null) {
      // Not started - it should check for availability first
      // This should eventually move to Engine, it's generic.
      if (Globals.IS_SECURITY_ENABLED) {
        PrivilegedAction<Void> pa = new PrivilegedSetTccl(context.getLoader().getClassLoader());
        AccessController.doPrivileged(pa);
      } else {
        Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
      }
    }
    if (request.isAsyncSupported()) {
      request.setAsyncSupported(context.getPipeline().isAsyncSupported());
    }

    boolean asyncAtStart = request.isAsync();
    boolean asyncDispatching = request.isAsyncDispatching();
    if (asyncAtStart || context.fireRequestInitEvent(request)) {

      // Ask this Context to process this request. Requests that are in
      // async mode and are not being dispatched to this resource must be
      // in error and have been routed here to check for application
      // defined error pages.
      try {
        if (!asyncAtStart || asyncDispatching) {
          context.getPipeline().getFirst().invoke(request, response);
        } else {
          // Make sure this request/response is here because an error
          // report is required.
          if (!response.isErrorReportRequired()) {
            throw new IllegalStateException(sm.getString("standardHost.asyncStateError"));
          }
        }
      } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        // If a new error occurred while trying to report a previous
        // error simply log the new error and allow the original error
        // to be reported.
        if (response.isErrorReportRequired()) {
          container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
        } else {
          request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
          throwable(request, response, t);
        }
      }

      // Now that the request/response pair is back under container
      // control lift the suspension so that the error handling can
      // complete and/or the container can flush any remaining data
      response.setSuspended(false);

      Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

      // Protect against NPEs if the context was destroyed during a
      // long running request.
      if (!context.getState().isAvailable()) {
        return;
      }

      // Look for (and render if found) an application level error page
      if (response.isErrorReportRequired()) {
        if (t != null) {
          throwable(request, response, t);
        } else {
          status(request, response);
        }
      }

      if (!request.isAsync() && (!asyncAtStart || !response.isErrorReportRequired())) {
        context.fireRequestDestroyEvent(request);
      }
    }

    // Access a session (if present) to update last accessed time, based on a
    // strict interpretation of the specification
    if (ACCESS_SESSION) {
      request.getSession(false);
    }

    // Restore the context classloader
    if (Globals.IS_SECURITY_ENABLED) {
      PrivilegedAction<Void> pa = new PrivilegedSetTccl(StandardHostValve.class.getClassLoader());
      AccessController.doPrivileged(pa);
    } else {
      Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader());
    }
  }