Ejemplo n.º 1
0
  public static ModelTree getTreeFromWebappContext(
      String resourceName, String treeName, HttpServletRequest request)
      throws IOException, SAXException, ParserConfigurationException {
    String webappName = UtilHttp.getApplicationName(request);
    String cacheKey = webappName + "::" + resourceName;

    Map<String, ModelTree> modelTreeMap = treeWebappCache.get(cacheKey);
    if (modelTreeMap == null) {
      synchronized (TreeFactory.class) {
        modelTreeMap = treeWebappCache.get(cacheKey);
        if (modelTreeMap == null) {
          ServletContext servletContext = (ServletContext) request.getAttribute("servletContext");
          Delegator delegator = (Delegator) request.getAttribute("delegator");
          LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");

          URL treeFileUrl = servletContext.getResource(resourceName);
          Document treeFileDoc = UtilXml.readXmlDocument(treeFileUrl, true);
          modelTreeMap = readTreeDocument(treeFileDoc, delegator, dispatcher, cacheKey);
          treeWebappCache.put(cacheKey, modelTreeMap);
        }
      }
    }

    ModelTree modelTree = (ModelTree) modelTreeMap.get(treeName);
    if (modelTree == null) {
      throw new IllegalArgumentException(
          "Could not find tree with name ["
              + treeName
              + "] in webapp resource ["
              + resourceName
              + "] in the webapp ["
              + webappName
              + "]");
    }
    return modelTree;
  }
  /**
   * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
   *     javax.servlet.http.HttpServletResponse)
   */
  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    long requestStartTime = System.currentTimeMillis();
    RequestHandler requestHandler = this.getRequestHandler();
    HttpSession session = request.getSession();

    // setup DEFAULT chararcter encoding and content type, this will be overridden in the
    // RequestHandler for view rendering
    String charset = getServletContext().getInitParameter("charset");
    if (UtilValidate.isEmpty(charset)) charset = request.getCharacterEncoding();
    if (UtilValidate.isEmpty(charset)) charset = "UTF-8";
    if (Debug.verboseOn())
      Debug.logVerbose(
          "The character encoding of the request is: ["
              + request.getCharacterEncoding()
              + "]. The character encoding we will use for the request and response is: ["
              + charset
              + "]",
          module);

    if (!"none".equals(charset)) {
      request.setCharacterEncoding(charset);
    }

    // setup content type
    String contentType = "text/html";
    if (charset.length() > 0 && !"none".equals(charset)) {
      response.setContentType(contentType + "; charset=" + charset);
      response.setCharacterEncoding(charset);
    } else {
      response.setContentType(contentType);
    }

    GenericValue userLogin = (GenericValue) session.getAttribute("userLogin");
    // Debug.log("Cert Chain: " + request.getAttribute("javax.servlet.request.X509Certificate"),
    // module);

    // set the Entity Engine user info if we have a userLogin
    if (userLogin != null) {
      GenericDelegator.pushUserIdentifier(userLogin.getString("userLoginId"));
    }

    // workaraound if we are in the root webapp
    String webappName = UtilHttp.getApplicationName(request);

    String rname = "";
    if (request.getPathInfo() != null) {
      rname = request.getPathInfo().substring(1);
    }
    if (rname.indexOf('/') > 0) {
      rname = rname.substring(0, rname.indexOf('/'));
    }

    UtilTimer timer = null;
    if (Debug.timingOn()) {
      timer = new UtilTimer();
      timer.setLog(true);
      timer.timerString(
          "["
              + rname
              + "(Domain:"
              + request.getServerName()
              + ")] Request Begun, encoding=["
              + charset
              + "]",
          module);
    }

    // Setup the CONTROL_PATH for JSP dispatching.
    String contextPath = request.getContextPath();
    if (contextPath == null || "/".equals(contextPath)) {
      contextPath = "";
    }
    request.setAttribute("_CONTROL_PATH_", contextPath + request.getServletPath());
    if (Debug.verboseOn())
      Debug.logVerbose("Control Path: " + request.getAttribute("_CONTROL_PATH_"), module);

    // for convenience, and necessity with event handlers, make security and delegator available in
    // the request:
    // try to get it from the session first so that we can have a delegator/dispatcher/security for
    // a certain user if desired
    Delegator delegator = null;
    String delegatorName = (String) session.getAttribute("delegatorName");
    if (UtilValidate.isNotEmpty(delegatorName)) {
      delegator = DelegatorFactory.getDelegator(delegatorName);
    }
    if (delegator == null) {
      delegator = (Delegator) getServletContext().getAttribute("delegator");
    }
    if (delegator == null) {
      Debug.logError("[ControlServlet] ERROR: delegator not found in ServletContext", module);
    } else {
      request.setAttribute("delegator", delegator);
      // always put this in the session too so that session events can use the delegator
      session.setAttribute("delegatorName", delegator.getDelegatorName());
    }

    LocalDispatcher dispatcher = (LocalDispatcher) session.getAttribute("dispatcher");
    if (dispatcher == null) {
      dispatcher = (LocalDispatcher) getServletContext().getAttribute("dispatcher");
    }
    if (dispatcher == null) {
      Debug.logError("[ControlServlet] ERROR: dispatcher not found in ServletContext", module);
    }
    request.setAttribute("dispatcher", dispatcher);

    Authorization authz = (Authorization) session.getAttribute("authz");
    if (authz == null) {
      authz = (Authorization) getServletContext().getAttribute("authz");
    }
    if (authz == null) {
      Debug.logError("[ControlServlet] ERROR: authorization not found in ServletContext", module);
    }
    request.setAttribute("authz", authz); // maybe we should also add the value to 'security'

    Security security = (Security) session.getAttribute("security");
    if (security == null) {
      security = (Security) getServletContext().getAttribute("security");
    }
    if (security == null) {
      Debug.logError("[ControlServlet] ERROR: security not found in ServletContext", module);
    }
    request.setAttribute("security", security);

    request.setAttribute("_REQUEST_HANDLER_", requestHandler);

    ServletContextHashModel ftlServletContext =
        new ServletContextHashModel(this, BeansWrapper.getDefaultInstance());
    request.setAttribute("ftlServletContext", ftlServletContext);

    // setup some things that should always be there
    UtilHttp.setInitialRequestInfo(request);
    VisitHandler.getVisitor(request, response);

    // set the Entity Engine user info if we have a userLogin
    String visitId = VisitHandler.getVisitId(session);
    if (UtilValidate.isNotEmpty(visitId)) {
      GenericDelegator.pushSessionIdentifier(visitId);
    }

    // display details on the servlet objects
    if (Debug.verboseOn()) {
      logRequestInfo(request);
    }

    // some containers call filters on EVERY request, even forwarded ones, so let it know that it
    // came from the control servlet
    request.setAttribute(ContextFilter.FORWARDED_FROM_SERVLET, Boolean.TRUE);

    String errorPage = null;
    try {
      // the ServerHitBin call for the event is done inside the doRequest method
      requestHandler.doRequest(request, response, null, userLogin, delegator);
    } catch (RequestHandlerException e) {
      Throwable throwable = e.getNested() != null ? e.getNested() : e;
      Debug.logError(throwable, "Error in request handler: ", module);
      StringUtil.HtmlEncoder encoder = new StringUtil.HtmlEncoder();
      request.setAttribute("_ERROR_MESSAGE_", encoder.encode(throwable.toString()));
      errorPage = requestHandler.getDefaultErrorPage(request);
    } catch (Exception e) {
      Debug.logError(e, "Error in request handler: ", module);
      StringUtil.HtmlEncoder encoder = new StringUtil.HtmlEncoder();
      request.setAttribute("_ERROR_MESSAGE_", encoder.encode(e.toString()));
      errorPage = requestHandler.getDefaultErrorPage(request);
    }

    // Forward to the JSP
    // if (Debug.infoOn()) Debug.logInfo("[" + rname + "] Event done, rendering page: " + nextPage,
    // module);
    // if (Debug.timingOn()) timer.timerString("[" + rname + "] Event done, rendering page: " +
    // nextPage, module);

    if (errorPage != null) {
      Debug.logError("An error occurred, going to the errorPage: " + errorPage, module);

      RequestDispatcher rd = request.getRequestDispatcher(errorPage);

      // use this request parameter to avoid infinite looping on errors in the error page...
      if (request.getAttribute("_ERROR_OCCURRED_") == null && rd != null) {
        request.setAttribute("_ERROR_OCCURRED_", Boolean.TRUE);
        Debug.logError("Including errorPage: " + errorPage, module);

        // NOTE DEJ20070727 after having trouble with all of these, try to get the page out and as a
        // last resort just send something back
        try {
          rd.include(request, response);
        } catch (Throwable t) {
          Debug.logWarning(
              "Error while trying to send error page using rd.include (will try response.getOutputStream or response.getWriter): "
                  + t.toString(),
              module);

          String errorMessage =
              "ERROR rendering error page ["
                  + errorPage
                  + "], but here is the error text: "
                  + request.getAttribute("_ERROR_MESSAGE_");
          try {
            if (UtilJ2eeCompat.useOutputStreamNotWriter(getServletContext())) {
              response.getOutputStream().print(errorMessage);
            } else {
              response.getWriter().print(errorMessage);
            }
          } catch (Throwable t2) {
            try {
              int errorToSend = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
              Debug.logWarning(
                  "Error while trying to write error message using response.getOutputStream or response.getWriter: "
                      + t.toString()
                      + "; sending error code ["
                      + errorToSend
                      + "], and message ["
                      + errorMessage
                      + "]",
                  module);
              response.sendError(errorToSend, errorMessage);
            } catch (Throwable t3) {
              // wow, still bad... just throw an IllegalStateException with the message and let the
              // servlet container handle it
              throw new IllegalStateException(errorMessage);
            }
          }
        }

      } else {
        if (rd == null) {
          Debug.logError("Could not get RequestDispatcher for errorPage: " + errorPage, module);
        }

        String errorMessage =
            "<html><body>ERROR in error page, (infinite loop or error page not found with name ["
                + errorPage
                + "]), but here is the text just in case it helps you: "
                + request.getAttribute("_ERROR_MESSAGE_")
                + "</body></html>";
        if (UtilJ2eeCompat.useOutputStreamNotWriter(getServletContext())) {
          response.getOutputStream().print(errorMessage);
        } else {
          response.getWriter().print(errorMessage);
        }
      }
    }

    // sanity check: make sure we don't have any transactions in place
    try {
      // roll back current TX first
      if (TransactionUtil.isTransactionInPlace()) {
        Debug.logWarning(
            "*** NOTICE: ControlServlet finished w/ a transaction in place! Rolling back.", module);
        TransactionUtil.rollback();
      }

      // now resume/rollback any suspended txs
      if (TransactionUtil.suspendedTransactionsHeld()) {
        int suspended = TransactionUtil.cleanSuspendedTransactions();
        Debug.logWarning("Resumed/Rolled Back [" + suspended + "] transactions.", module);
      }
    } catch (GenericTransactionException e) {
      Debug.logWarning(e, module);
    }

    // run these two again before the ServerHitBin.countRequest call because on a logout this will
    // end up creating a new visit
    if (response.isCommitted() && request.getSession(false) == null) {
      // response committed and no session, and we can't get a new session, what to do!
      // without a session we can't log the hit, etc; so just do nothing; this should NOT happen
      // much!
      Debug.logError(
          "Error in ControlServlet output where response isCommitted and there is no session (probably because of a logout); not saving ServerHit/Bin information because there is no session and as the response isCommitted we can't get a new one. The output was successful, but we just can't save ServerHit/Bin info.",
          module);
    } else {
      try {
        UtilHttp.setInitialRequestInfo(request);
        VisitHandler.getVisitor(request, response);
        if (requestHandler.trackStats(request)) {
          ServerHitBin.countRequest(
              webappName + "." + rname,
              request,
              requestStartTime,
              System.currentTimeMillis() - requestStartTime,
              userLogin);
        }
      } catch (Throwable t) {
        Debug.logError(
            t,
            "Error in ControlServlet saving ServerHit/Bin information; the output was successful, but can't save this tracking information. The error was: "
                + t.toString(),
            module);
      }
    }
    if (Debug.timingOn())
      timer.timerString(
          "[" + rname + "(Domain:" + request.getServerName() + ")] Request Done", module);

    // sanity check 2: make sure there are no user or session infos in the delegator, ie clear the
    // thread
    GenericDelegator.clearUserIdentifierStack();
    GenericDelegator.clearSessionIdentifierStack();
  }