protected ModelAndView handleContext(
      String contextName, Context context, HttpServletRequest request, HttpServletResponse response)
      throws Exception {

    boolean calcSize =
        ServletRequestUtils.getBooleanParameter(request, "size", false)
            && SecurityUtils.hasAttributeValueRole(getServletContext(), request);

    Application app =
        ApplicationUtils.getApplication(
            context,
            isExtendedInfo() ? getContainerWrapper().getResourceResolver() : null,
            calcSize,
            getContainerWrapper());

    if (isExtendedInfo() && getStatsCollection() != null) {
      String avgStatisticName = "app.avg_proc_time." + app.getName();
      app.setAvgTime(getStatsCollection().getLastValueForStat(avgStatisticName));
    }

    return new ModelAndView(getViewName())
        .addObject("app", app)
        .addObject(
            "no_resources", !getContainerWrapper().getResourceResolver().supportsPrivateResources())
        .addObject("collectionPeriod", getCollectionPeriod());
  }
  /**
   * Calculates Sum of requestCount, errorCount and processingTime for all servlets for the given
   * application. It also works out minimum value of minTime and maximum value for maxTime for all
   * servlets.
   *
   * @param context the context whose stats will be collected
   * @param app the application in which to store the collected stats
   */
  public static void collectApplicationServletStats(Context context, Application app) {
    int svltCount = 0;
    int reqCount = 0;
    int errCount = 0;
    long procTime = 0;
    long minTime = Long.MAX_VALUE;
    long maxTime = 0;

    for (Container container : context.findChildren()) {
      if (container instanceof StandardWrapper) {
        StandardWrapper sw = (StandardWrapper) container;
        svltCount++;
        reqCount += sw.getRequestCount();
        errCount += sw.getErrorCount();
        procTime += sw.getProcessingTime();
        if (sw.getRequestCount() > 0) {
          minTime = Math.min(minTime, sw.getMinTime());
        }
        maxTime = Math.max(maxTime, sw.getMaxTime());
      }
    }
    app.setServletCount(svltCount);
    app.setRequestCount(reqCount);
    app.setErrorCount(errCount);
    app.setProcessingTime(procTime);
    app.setMinTime(minTime == Long.MAX_VALUE ? 0 : minTime);
    app.setMaxTime(maxTime);
  }
  /**
   * Creates Application instance from Tomcat Context object. If ResourceResolver is passed the
   * method will also collect additional information about the application such as session count,
   * session attribute count, application attribute count, servlet count, servlet stats summary and
   * datasource usage summary. Collecting additional information can be CPU intensive and time
   * consuming so this should be avoided unless absolutely required. Some datasource implementations
   * (c3p0) are known to be prone to internal deadlocks, so this method can also hang is datasource
   * usage stats is to be collected.
   *
   * @param context the context from which to create the Application
   * @param resourceResolver the resolver to use for resources associated with the given context
   * @param calcSize flag which controls whether to calculate session size
   * @param containerWrapper the wrapper for the context's root containing server
   * @return Application object
   */
  public static Application getApplication(
      Context context,
      ResourceResolver resourceResolver,
      boolean calcSize,
      ContainerWrapperBean containerWrapper) {

    // ContainerWrapperBean containerWrapper
    logger.debug("Querying webapp: " + context.getName());

    Application app = new Application();
    app.setName(context.getName().length() > 0 ? context.getName() : "/");
    app.setDocBase(context.getDocBase());
    app.setDisplayName(context.getDisplayName());

    app.setAvailable(containerWrapper.getTomcatContainer().getAvailable(context));
    app.setDistributable(context.getDistributable());
    app.setSessionTimeout(context.getSessionTimeout());
    app.setServletVersion(
        context.getServletContext().getMajorVersion()
            + "."
            + context.getServletContext().getMinorVersion());

    if (resourceResolver != null) {
      logger.debug("counting servlet attributes");

      int ctxAttrCount = 0;
      for (Enumeration e = context.getServletContext().getAttributeNames();
          e.hasMoreElements();
          e.nextElement()) {
        ctxAttrCount++;
      }
      app.setContextAttributeCount(ctxAttrCount);

      if (app.isAvailable()) {
        logger.debug("collecting session information");

        app.setSessionCount(context.getManager().findSessions().length);

        boolean serializable = true;
        int sessionAttributeCount = 0;
        long size = 0;

        for (Session session : context.getManager().findSessions()) {
          ApplicationSession appSession = getApplicationSession(session, calcSize, false);
          if (appSession != null) {
            sessionAttributeCount += appSession.getObjectCount();
            serializable = serializable && appSession.isSerializable();
            size += appSession.getSize();
          }
        }
        app.setSerializable(serializable);
        app.setSessionAttributeCount(sessionAttributeCount);
        app.setSize(size);
      }

      logger.debug("aggregating servlet stats");

      collectApplicationServletStats(context, app);

      if (resourceResolver.supportsPrivateResources() && app.isAvailable()) {
        int[] scores =
            getApplicationDataSourceUsageScores(context, resourceResolver, containerWrapper);
        app.setDataSourceBusyScore(scores[0]);
        app.setDataSourceEstablishedScore(scores[1]);
      }
    }

    return app;
  }