public void render(HttpServletRequest request, HttpServletResponse response, Portlet portlet)
      throws PortletContainerException {

    ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

    try {
      _doRender(request, response, portlet);

      if (themeDisplay.isIsolated() || themeDisplay.isStateExclusive()) {
        AUIUtil.outputScriptData(request, response.getWriter());
      }
    } catch (Exception e) {
      throw new PortletContainerException(e);
    }
  }
  protected void includeLayoutContent(
      HttpServletRequest request,
      HttpServletResponse response,
      ThemeDisplay themeDisplay,
      Layout layout)
      throws Exception {

    ServletContext servletContext = (ServletContext) request.getAttribute(WebKeys.CTX);

    String path = StrutsUtil.TEXT_HTML_DIR;

    if (BrowserSnifferUtil.isWap(request)) {
      path = StrutsUtil.TEXT_WAP_DIR;
    }

    // Manually check the p_p_id. See LEP-1724.

    if (themeDisplay.isStateExclusive()
        || Validator.isNotNull(ParamUtil.getString(request, "p_p_id"))) {

      if (layout.isTypePanel()) {
        path += "/portal/layout/view/panel.jsp";
      } else if (layout.isTypeControlPanel()) {
        path += "/portal/layout/view/control_panel.jsp";
      } else {
        path += "/portal/layout/view/portlet.jsp";
      }
    } else {
      path += PortalUtil.getLayoutViewPage(layout);
    }

    RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher(path);

    UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();

    PipingServletResponse pipingServletResponse =
        new PipingServletResponse(response, unsyncStringWriter);

    String contentType = pipingServletResponse.getContentType();

    requestDispatcher.include(request, pipingServletResponse);

    if (contentType != null) {
      pipingServletResponse.setContentType(contentType);
    }

    request.setAttribute(WebKeys.LAYOUT_CONTENT, unsyncStringWriter.getStringBundler());
  }
  protected ActionForward processLayout(
      ActionMapping mapping, HttpServletRequest request, HttpServletResponse response, long plid)
      throws Exception {

    HttpSession session = request.getSession();

    ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

    try {
      Layout layout = themeDisplay.getLayout();

      boolean resetLayout =
          ParamUtil.getBoolean(request, "p_l_reset", PropsValues.LAYOUT_DEFAULT_P_L_RESET);

      String portletId = ParamUtil.getString(request, "p_p_id");

      Layout previousLayout = (Layout) session.getAttribute(WebKeys.PREVIOUS_LAYOUT);

      if ((previousLayout == null) || (layout.getPlid() != previousLayout.getPlid())) {

        session.setAttribute(WebKeys.PREVIOUS_LAYOUT, layout);

        if (themeDisplay.isSignedIn()
            && PropsValues.AUDIT_MESSAGE_COM_LIFERAY_PORTAL_MODEL_LAYOUT_VIEW
            && MessageBusUtil.hasMessageListener(DestinationNames.AUDIT)) {

          User user = themeDisplay.getUser();

          AuditMessage auditMessage =
              new AuditMessage(
                  ActionKeys.VIEW,
                  user.getCompanyId(),
                  user.getUserId(),
                  user.getFullName(),
                  Layout.class.getName(),
                  String.valueOf(layout.getPlid()));

          AuditRouterUtil.route(auditMessage);
        }
      }

      if (!PropsValues.TCK_URL
          && resetLayout
          && (Validator.isNull(portletId)
              || ((previousLayout != null) && (layout.getPlid() != previousLayout.getPlid())))) {

        // Always clear render parameters on a layout url, but do not
        // clear on portlet urls invoked on the same layout

        RenderParametersPool.clear(request, plid);
      }

      if (themeDisplay.isLifecycleAction()) {
        Portlet portlet = processPortletRequest(request, response, PortletRequest.ACTION_PHASE);

        if (portlet != null) {
          ActionResponseImpl actionResponseImpl =
              (ActionResponseImpl) request.getAttribute(JavaConstants.JAVAX_PORTLET_RESPONSE);

          String redirectLocation = actionResponseImpl.getRedirectLocation();

          if (Validator.isNotNull(redirectLocation)) {
            response.sendRedirect(redirectLocation);

            return null;
          }

          if (portlet.isActionURLRedirect()) {
            redirectActionURL(request, response, actionResponseImpl, portlet);

            return null;
          }
        }
      } else if (themeDisplay.isLifecycleRender()) {
        processPortletRequest(request, response, PortletRequest.RENDER_PHASE);
      }

      if (themeDisplay.isLifecycleResource()) {
        processPortletRequest(request, response, PortletRequest.RESOURCE_PHASE);

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

        if (layout != null) {

          // Include layout content before the page loads because
          // portlets on the page can set the page title and page
          // subtitle

          includeLayoutContent(request, response, themeDisplay, layout);

          if (themeDisplay.isStateExclusive()) {
            renderExclusive(request, response, themeDisplay);

            return null;
          }
        }

        return mapping.findForward("portal.layout");
      }
    } catch (Exception e) {
      PortalUtil.sendError(e, request, response);

      return null;
    } finally {
      if (!ServerDetector.isResin()) {
        PortletRequest portletRequest =
            (PortletRequest) request.getAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);

        if (portletRequest != null) {
          PortletRequestImpl portletRequestImpl = (PortletRequestImpl) portletRequest;

          portletRequestImpl.cleanUp();
        }
      }
    }
  }