/**
   * The service method gets the JSP/XTP page and executes it. The request and response objects are
   * converted to Caucho objects so other servlet runners will produce the same results as the
   * Caucho servlet runner.
   */
  public void service(ServletRequest req, ServletResponse res)
      throws ServletException, IOException {
    CauchoRequest request;
    CauchoResponse response;
    ResponseAdapter resAdapt = null;

    if (req instanceof CauchoRequest) request = (CauchoRequest) req;
    else request = RequestAdapter.create((HttpServletRequest) req, _webApp);

    if (res instanceof CauchoResponse) response = (CauchoResponse) res;
    else {
      resAdapt = ResponseAdapter.create((HttpServletResponse) res);
      response = resAdapt;
    }

    Page page = null;

    try {
      page = getPage(request, response);

      if (page == null) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      page.service(request, response);
    } catch (JspParseException e) {
      if (e.getErrorPage() != null) forwardErrorPage(request, response, e, e.getErrorPage());
      else throw new ServletException(e);
    } catch (ClientDisconnectException e) {
      throw e;
    } catch (Throwable e) {
      if (page != null
          && page.getErrorPage() != null
          && forwardErrorPage(request, response, e, page.getErrorPage())) {
      } else if (e instanceof IOException) {
        log.log(Level.FINE, e.toString(), e);
        throw (IOException) e;
      } else if (e instanceof ServletException) {
        log.log(Level.FINE, e.toString(), e);
        throw (ServletException) e;
      } else {
        log.log(Level.FINE, e.toString(), e);
        throw new ServletException(e);
      }
    }

    if (resAdapt != null) {
      resAdapt.close();
      ResponseAdapter.free(resAdapt);
    }
  }
  /**
   * Given a request and response, returns the compiled Page. For example, JspManager will return
   * the JspPage and XtpManager will return the XtpPage.
   *
   * @param req servlet request for generating the page.
   * @param res servlet response to any needed error messages.
   */
  private Page getSubPage(HttpServletRequest req, HttpServletResponse res) throws Exception {
    CauchoRequest cauchoRequest = null;

    initGetPage();

    /*
    if (! _webApp.isActive())
      throw new UnavailableException("JSP compilation unavailable during restart", 10);
    */

    if (req instanceof CauchoRequest) cauchoRequest = (CauchoRequest) req;

    String servletPath;

    if (cauchoRequest != null) servletPath = cauchoRequest.getPageServletPath();
    else servletPath = RequestAdapter.getPageServletPath(req);

    if (servletPath == null) servletPath = "/";

    String uri;

    if (cauchoRequest != null) uri = cauchoRequest.getPageURI();
    else uri = RequestAdapter.getPageURI(req);

    Path appDir = _webApp.getRootDirectory();

    String realPath;
    Path subcontext;

    ServletConfig config = null;

    String jspPath = (String) req.getAttribute("caucho.jsp.jsp-file");
    if (jspPath != null) {
      req.removeAttribute("caucho.jsp.jsp-file");

      subcontext = getPagePath(jspPath);

      return _manager.getPage(uri, jspPath, subcontext, config);
    }

    String pathInfo;

    if (cauchoRequest != null) pathInfo = cauchoRequest.getPagePathInfo();
    else pathInfo = RequestAdapter.getPagePathInfo(req);

    subcontext = getPagePath(servletPath);

    if (subcontext != null) return _manager.getPage(servletPath, subcontext);

    if (pathInfo == null) {
      realPath = _webApp.getRealPath(servletPath);
      subcontext = appDir.lookupNative(realPath);

      return _manager.getPage(servletPath, subcontext);
    }

    subcontext = getPagePath(servletPath + pathInfo);
    if (subcontext != null) return _manager.getPage(servletPath + pathInfo, subcontext);

    // If servlet path exists, can't use pathInfo to lookup servlet,
    // because /jsp/WEB-INF would be a security hole
    if (servletPath != null && !servletPath.equals("")) {
      // server/0035
      throw new FileNotFoundException(L.l("{0} was not found on this server.", uri));
      // return null;
    }

    subcontext = getPagePath(pathInfo);
    if (subcontext != null) return _manager.getPage(pathInfo, subcontext);

    subcontext = getPagePath(uri);
    if (subcontext == null)
      throw new FileNotFoundException(L.l("{0} was not found on this server.", uri));

    return _manager.getPage(uri, subcontext);
  }