@Override
  public DelegationActionResponse doAction(
      ActionRequest actionRequest,
      ActionResponse actionResponse,
      DelegationRequest delegationRequest)
      throws IOException {
    final HttpServletRequest request = this.portalRequestUtils.getPortletHttpRequest(actionRequest);
    final HttpServletResponse response =
        this.portalRequestUtils.getOriginalPortalResponse(actionRequest);

    // Sanity check that the dispatch is being called by the same user it was created for
    final IPerson person = this.personManager.getPerson(request);
    if (this.userId != person.getID()) {
      throw new IllegalStateException(
          "This dispatcher was created for userId "
              + this.userId
              + " but is being executed for userId "
              + person.getID());
    }

    this.setupDelegateRequestInfo(request, delegationRequest);

    final IPortletWindowId portletWindowId = this.portletWindow.getPortletWindowId();
    try {
      // TODO canRender permission checks!
      this.portletRenderer.doAction(portletWindowId, request, response);
    } catch (RuntimeException e) {
      this.logger.error("Failed to execute action on delegate", e);
      throw e;
    }

    // Get the portal URL builders for this request and check if a redirect was sent
    final IPortalActionUrlBuilder portalActionUrlBuilder =
        this.portalUrlProvider.getPortalActionUrlBuilder(request);
    final String redirectLocation = portalActionUrlBuilder.getRedirectLocation();
    if (redirectLocation != null) {
      final String renderUrlParamName = portalActionUrlBuilder.getRenderUrlParamName();

      // clear out the redirect from the delegate, leave it up to the parent if the redirect should
      // happen
      portalActionUrlBuilder.setRedirectLocation(null, null);

      return new DelegationActionResponse(
          this.getDelegateState(), redirectLocation, renderUrlParamName);
    }

    // No redirect so get the portlet's url builder and copy the state-changing data into the
    // delegate response
    final IPortletUrlBuilder portletUrlBuilder =
        portalActionUrlBuilder.getPortletUrlBuilder(portletWindowId);

    final WindowState windowState = portletUrlBuilder.getWindowState();
    final PortletMode portletMode = portletUrlBuilder.getPortletMode();
    final Map<String, String[]> parameters = portletUrlBuilder.getParameters();

    return new DelegationActionResponse(
        this.getDelegateState(), portletMode, windowState, parameters);
  }