@Override
  protected void doProcessAction(ActionRequest actionRequest, ActionResponse actionResponse)
      throws Exception {

    hideDefaultSuccessMessage(actionRequest);

    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);

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

    try {
      long exportImportConfigurationId =
          ParamUtil.getLong(actionRequest, "exportImportConfigurationId");

      if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
        updatePublishConfiguration(actionRequest);
      } else if (cmd.equals(Constants.PUBLISH_TO_LIVE)) {
        StagingUtil.publishLayouts(themeDisplay.getUserId(), exportImportConfigurationId);
      } else if (cmd.equals(Constants.PUBLISH_TO_REMOTE)) {
        StagingUtil.copyRemoteLayouts(exportImportConfigurationId);
      } else if (cmd.equals(Constants.RELAUNCH)) {
        relaunchPublishLayoutConfiguration(themeDisplay.getUserId(), actionRequest);
      }

      String redirect = ParamUtil.getString(actionRequest, "redirect");

      sendRedirect(actionRequest, actionResponse, redirect);
    } catch (Exception e) {
      _log.error(e, e);

      SessionErrors.add(actionRequest, e.getClass());
    }
  }
  @Deprecated
  @Override
  public boolean isCommunityOwner(long groupId) {
    long liveGroupId = StagingUtil.getLiveGroupId(groupId);

    return _permissionChecker.isCommunityOwner(liveGroupId);
  }
  @Test
  public void testFailedPortletLocalPublishing() throws Exception {
    User user = TestPropsValues.getUser();

    try (CaptureAppender captureAppender =
        Log4JLoggerTestUtil.configureLog4JLogger(
            BackgroundTaskMessageListener.class.getName(), Level.ERROR)) {

      StagingUtil.publishPortlet(
          user.getUserId(),
          _group.getGroupId(),
          _liveGroup.getGroupId(),
          0,
          0,
          StringPool.BLANK,
          _parameterMap);

      List<LoggingEvent> loggingEvents = captureAppender.getLoggingEvents();

      LoggingEvent loggingEvent = loggingEvents.get(0);

      Assert.assertEquals("Unable to execute background task", loggingEvent.getMessage());

      ThrowableInformation throwableInformation = loggingEvent.getThrowableInformation();

      Throwable throwable = throwableInformation.getThrowable();

      Assert.assertSame(NoSuchLayoutException.class, throwable.getClass());
    }

    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_PUBLICATION_PORTLET_LOCAL_FAILED));
  }
  @Override
  public List<Long> getResourceBlockIds(
      long companyId, long groupId, long userId, String name, String actionId) {

    long liveGroupId = StagingUtil.getLiveGroupId(groupId);

    return _permissionChecker.getResourceBlockIds(companyId, liveGroupId, userId, name, actionId);
  }
  @Override
  public boolean hasUserPermission(
      long groupId, String name, String primKey, String actionId, boolean checkAdmin) {

    long liveGroupId = StagingUtil.getLiveGroupId(groupId);

    return _permissionChecker.hasUserPermission(liveGroupId, name, primKey, actionId, checkAdmin);
  }
  @Test
  public void testSuccessfulLayoutLocalPublishing() throws Exception {
    LayoutTestUtil.addLayout(_group, false);

    JournalTestUtil.addArticle(
        _group.getGroupId(), JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID);

    StagingUtil.publishLayouts(
        TestPropsValues.getUserId(),
        _group.getGroupId(),
        _liveGroup.getGroupId(),
        false,
        null,
        _parameterMap);

    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_LAYOUT_EXPORT_STARTED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_LAYOUT_EXPORT_SUCCEEDED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_STARTED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_SUCCEEDED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_PORTLET_EXPORT_STARTED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_PORTLET_EXPORT_SUCCEEDED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_PORTLET_IMPORT_STARTED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_PORTLET_IMPORT_SUCCEEDED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_PUBLICATION_LAYOUT_LOCAL_STARTED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_PUBLICATION_LAYOUT_LOCAL_SUCCEEDED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_STAGED_MODEL_EXPORT_STARTED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_STAGED_MODEL_EXPORT_SUCCEEDED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_STAGED_MODEL_IMPORT_STARTED));
    Assert.assertTrue(
        _firedExportImportLifecycleEventsMap.containsKey(
            ExportImportLifecycleConstants.EVENT_STAGED_MODEL_IMPORT_SUCCEEDED));
  }
  @Override
  public boolean hasPermission(long groupId, String name, long primKey, String actionId) {

    long liveGroupId = StagingUtil.getLiveGroupId(groupId);

    if (liveGroupId != groupId) {
      if (primKey == groupId) {
        primKey = liveGroupId;
      }
    }

    return _permissionChecker.hasPermission(liveGroupId, name, primKey, actionId);
  }
  protected void relaunchPublishLayoutConfiguration(long userId, ActionRequest actionRequest)
      throws PortalException {

    long backgroundTaskId =
        ParamUtil.getLong(actionRequest, BackgroundTaskConstants.BACKGROUND_TASK_ID);

    BackgroundTask backgroundTask = BackgroundTaskManagerUtil.getBackgroundTask(backgroundTaskId);

    Map<String, Serializable> taskContextMap = backgroundTask.getTaskContextMap();

    ExportImportConfiguration exportImportConfiguration =
        _exportImportConfigurationLocalService.getExportImportConfiguration(
            MapUtil.getLong(taskContextMap, "exportImportConfigurationId"));

    if (exportImportConfiguration.getType()
        == ExportImportConfigurationConstants.TYPE_PUBLISH_LAYOUT_LOCAL) {

      StagingUtil.publishLayouts(userId, exportImportConfiguration);
    } else if (exportImportConfiguration.getType()
        == ExportImportConfigurationConstants.TYPE_PUBLISH_LAYOUT_REMOTE) {

      StagingUtil.copyRemoteLayouts(exportImportConfiguration);
    }
  }
  @Override
  public boolean isStagedPortlet(String portletId) {
    UnicodeProperties typeSettingsProperties = getParentLiveGroupTypeSettingsProperties();

    portletId = PortletConstants.getRootPortletId(portletId);

    String typeSettingsProperty =
        typeSettingsProperties.getProperty(StagingUtil.getStagedPortletId(portletId));

    if (Validator.isNotNull(typeSettingsProperty)) {
      return GetterUtil.getBoolean(typeSettingsProperty);
    }

    try {
      Portlet portlet = PortletLocalServiceUtil.getPortletById(portletId);

      PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

      if (portletDataHandler == null) {
        return false;
      }

      for (Map.Entry<String, String> entry : typeSettingsProperties.entrySet()) {

        String key = entry.getKey();

        if (!key.contains(StagingConstants.STAGED_PORTLET)) {
          continue;
        }

        String stagedPortletId =
            StringUtil.replace(key, StagingConstants.STAGED_PORTLET, StringPool.BLANK);

        Portlet stagedPortlet = PortletLocalServiceUtil.getPortletById(stagedPortletId);

        if (portletDataHandler.equals(stagedPortlet.getPortletDataHandlerInstance())) {

          return GetterUtil.getBoolean(entry.getValue());
        }
      }
    } catch (Exception e) {
    }

    return true;
  }
  @Override
  public long[] getRoleIds(long userId, long groupId) {
    long liveGroupId = StagingUtil.getLiveGroupId(groupId);

    return _permissionChecker.getRoleIds(userId, liveGroupId);
  }
  @Override
  public boolean isGroupOwner(long groupId) {
    long liveGroupId = StagingUtil.getLiveGroupId(groupId);

    return _permissionChecker.isGroupOwner(liveGroupId);
  }
  @Override
  public boolean isContentReviewer(long companyId, long groupId) {
    long liveGroupId = StagingUtil.getLiveGroupId(groupId);

    return _permissionChecker.isContentReviewer(companyId, liveGroupId);
  }
  @Override
  protected void doImportStagedModel(PortletDataContext portletDataContext, Layout layout)
      throws Exception {

    long groupId = portletDataContext.getGroupId();
    long userId = portletDataContext.getUserId(layout.getUserUuid());

    Element layoutElement = portletDataContext.getImportDataStagedModelElement(layout);

    String layoutUuid = GetterUtil.getString(layoutElement.attributeValue("layout-uuid"));

    long layoutId = GetterUtil.getInteger(layoutElement.attributeValue("layout-id"));

    long oldLayoutId = layoutId;

    boolean privateLayout = portletDataContext.isPrivateLayout();

    String action = layoutElement.attributeValue(Constants.ACTION);

    if (action.equals(Constants.DELETE)) {
      Layout deletingLayout =
          _layoutLocalService.fetchLayoutByUuidAndGroupId(layoutUuid, groupId, privateLayout);

      _layoutLocalService.deleteLayout(
          deletingLayout, false, ServiceContextThreadLocal.getServiceContext());

      return;
    }

    Map<Long, Layout> layouts =
        (Map<Long, Layout>) portletDataContext.getNewPrimaryKeysMap(Layout.class + ".layout");

    Layout existingLayout = null;
    Layout importedLayout = null;

    String friendlyURL = layout.getFriendlyURL();

    String layoutsImportMode =
        MapUtil.getString(
            portletDataContext.getParameterMap(),
            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID);

    if (layoutsImportMode.equals(PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_ADD_AS_NEW)) {

      layoutId = _layoutLocalService.getNextLayoutId(groupId, privateLayout);
      friendlyURL = StringPool.SLASH + layoutId;
    } else if (layoutsImportMode.equals(
        PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_NAME)) {

      Locale locale = LocaleUtil.getSiteDefault();

      String localizedName = layout.getName(locale);

      List<Layout> previousLayouts = _layoutLocalService.getLayouts(groupId, privateLayout);

      for (Layout curLayout : previousLayouts) {
        if (localizedName.equals(curLayout.getName(locale))
            || friendlyURL.equals(curLayout.getFriendlyURL())) {

          existingLayout = curLayout;

          break;
        }
      }

      if (existingLayout == null) {
        layoutId = _layoutLocalService.getNextLayoutId(groupId, privateLayout);

        friendlyURL = getFriendlyURL(friendlyURL, layoutId);
      }
    } else if (layoutsImportMode.equals(
        PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {

      existingLayout =
          _layoutLocalService.fetchLayoutByUuidAndGroupId(layout.getUuid(), groupId, privateLayout);

      if (SitesUtil.isLayoutModifiedSinceLastMerge(existingLayout)) {
        layouts.put(oldLayoutId, existingLayout);

        return;
      }

      LayoutFriendlyURL layoutFriendlyURL =
          _layoutFriendlyURLLocalService.fetchFirstLayoutFriendlyURL(
              groupId, privateLayout, friendlyURL);

      if ((layoutFriendlyURL != null) && (existingLayout == null)) {
        Layout mergeFailFriendlyURLLayout =
            _layoutLocalService.getLayout(layoutFriendlyURL.getPlid());

        SitesUtil.addMergeFailFriendlyURLLayout(mergeFailFriendlyURLLayout);

        if (!_log.isWarnEnabled()) {
          return;
        }

        StringBundler sb = new StringBundler(6);

        sb.append("Layout with layout ID ");
        sb.append(layout.getLayoutId());
        sb.append(" cannot be propagated because the friendly URL ");
        sb.append("conflicts with the friendly URL of layout with ");
        sb.append("layout ID ");
        sb.append(mergeFailFriendlyURLLayout.getLayoutId());

        _log.warn(sb.toString());

        return;
      }
    } else {

      // The default behavior of import mode is
      // PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID

      existingLayout =
          _layoutLocalService.fetchLayoutByUuidAndGroupId(layout.getUuid(), groupId, privateLayout);

      if (existingLayout == null) {
        existingLayout =
            _layoutLocalService.fetchLayoutByFriendlyURL(groupId, privateLayout, friendlyURL);
      }

      if (existingLayout == null) {
        layoutId = _layoutLocalService.getNextLayoutId(groupId, privateLayout);

        friendlyURL = getFriendlyURL(friendlyURL, layoutId);
      }
    }

    if (_log.isDebugEnabled()) {
      StringBundler sb = new StringBundler(7);

      sb.append("Layout with {groupId=");
      sb.append(groupId);
      sb.append(",privateLayout=");
      sb.append(privateLayout);
      sb.append(",layoutId=");
      sb.append(layoutId);

      if (existingLayout == null) {
        sb.append("} does not exist");

        _log.debug(sb.toString());
      } else {
        sb.append("} exists");

        _log.debug(sb.toString());
      }
    }

    if (existingLayout == null) {
      long plid = _counterLocalService.increment();

      importedLayout = _layoutLocalService.createLayout(plid);

      if (layoutsImportMode.equals(
          PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {

        importedLayout.setSourcePrototypeLayoutUuid(layout.getUuid());

        layoutId = _layoutLocalService.getNextLayoutId(groupId, privateLayout);

        friendlyURL = getFriendlyURL(friendlyURL, layoutId);
      } else {
        importedLayout.setCreateDate(layout.getCreateDate());
        importedLayout.setModifiedDate(layout.getModifiedDate());
        importedLayout.setLayoutPrototypeUuid(layout.getLayoutPrototypeUuid());
        importedLayout.setLayoutPrototypeLinkEnabled(layout.isLayoutPrototypeLinkEnabled());
        importedLayout.setSourcePrototypeLayoutUuid(layout.getSourcePrototypeLayoutUuid());
      }

      importedLayout.setUuid(layout.getUuid());
      importedLayout.setGroupId(groupId);
      importedLayout.setUserId(userId);
      importedLayout.setPrivateLayout(privateLayout);
      importedLayout.setLayoutId(layoutId);

      initNewLayoutPermissions(
          portletDataContext.getCompanyId(),
          groupId,
          userId,
          layout,
          importedLayout,
          privateLayout);

      LayoutSet layoutSet = _layoutSetLocalService.getLayoutSet(groupId, privateLayout);

      importedLayout.setLayoutSet(layoutSet);
    } else {
      importedLayout = existingLayout;
    }

    portletDataContext.setPlid(importedLayout.getPlid());
    portletDataContext.setOldPlid(layout.getPlid());

    long parentLayoutId = layout.getParentLayoutId();

    String parentLayoutUuid =
        GetterUtil.getString(layoutElement.attributeValue("parent-layout-uuid"));

    Element parentLayoutElement =
        portletDataContext.getReferenceDataElement(
            layout, Layout.class, layout.getGroupId(), parentLayoutUuid);

    if ((parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID)
        && (parentLayoutElement != null)) {

      StagedModelDataHandlerUtil.importStagedModel(portletDataContext, parentLayoutElement);

      Layout importedParentLayout = layouts.get(parentLayoutId);

      parentLayoutId = importedParentLayout.getLayoutId();
    }

    if (_log.isDebugEnabled()) {
      StringBundler sb = new StringBundler(4);

      sb.append("Importing layout with layout id ");
      sb.append(layoutId);
      sb.append(" and parent layout id ");
      sb.append(parentLayoutId);

      _log.debug(sb.toString());
    }

    importedLayout.setCompanyId(portletDataContext.getCompanyId());

    if (layout.getLayoutPrototypeUuid() != null) {
      importedLayout.setModifiedDate(new Date());
    }

    importedLayout.setParentLayoutId(parentLayoutId);
    importedLayout.setName(layout.getName());
    importedLayout.setTitle(layout.getTitle());
    importedLayout.setDescription(layout.getDescription());
    importedLayout.setKeywords(layout.getKeywords());
    importedLayout.setRobots(layout.getRobots());
    importedLayout.setType(layout.getType());

    String portletsMergeMode =
        MapUtil.getString(
            portletDataContext.getParameterMap(),
            PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
            PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);

    if (layout.isTypePortlet()
        && Validator.isNotNull(layout.getTypeSettings())
        && !portletsMergeMode.equals(PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE)) {

      mergePortlets(importedLayout, layout.getTypeSettings(), portletsMergeMode);
    } else if (layout.isTypeLinkToLayout()) {
      importLinkedLayout(portletDataContext, layout, importedLayout, layoutElement, layouts);
    } else {
      updateTypeSettings(importedLayout, layout);
    }

    importedLayout.setHidden(layout.isHidden());
    importedLayout.setFriendlyURL(
        getUniqueFriendlyURL(portletDataContext, importedLayout, friendlyURL));

    if (layout.getIconImageId() > 0) {
      importLayoutIconImage(portletDataContext, importedLayout, layoutElement);
    } else if (importedLayout.getIconImageId() > 0) {
      _imageLocalService.deleteImage(importedLayout.getIconImageId());
    }

    if (existingLayout == null) {
      int priority =
          _layoutLocalServiceHelper.getNextPriority(
              groupId, privateLayout, parentLayoutId, null, -1);

      importedLayout.setPriority(priority);
    }

    importedLayout.setLayoutPrototypeUuid(layout.getLayoutPrototypeUuid());
    importedLayout.setLayoutPrototypeLinkEnabled(layout.isLayoutPrototypeLinkEnabled());

    ServiceContext serviceContext = portletDataContext.createServiceContext(layout);

    importedLayout.setExpandoBridgeAttributes(serviceContext);

    StagingUtil.updateLastImportSettings(layoutElement, importedLayout, portletDataContext);

    fixImportTypeSettings(importedLayout);

    importTheme(portletDataContext, layout, importedLayout);

    _layoutLocalService.updateLayout(importedLayout);

    _layoutSetLocalService.updatePageCount(groupId, privateLayout);

    Map<Long, Long> layoutPlids =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(Layout.class);

    layoutPlids.put(layout.getPlid(), importedLayout.getPlid());

    layouts.put(oldLayoutId, importedLayout);

    importAssets(portletDataContext, layout, importedLayout);

    importLayoutFriendlyURLs(portletDataContext, layout, importedLayout);

    portletDataContext.importClassedModel(layout, importedLayout);
  }
  @Override
  protected void doProcessAction(ActionRequest actionRequest, ActionResponse actionResponse)
      throws Exception {

    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);

    if (Validator.isNull(cmd)) {
      SessionMessages.add(
          actionRequest,
          PortalUtil.getPortletId(actionRequest) + SessionMessages.KEY_SUFFIX_FORCE_SEND_REDIRECT);

      hideDefaultSuccessMessage(actionRequest);

      return;
    }

    try {
      if (cmd.equals("copy_from_live")) {
        StagingUtil.copyFromLive(actionRequest);
      } else if (cmd.equals(Constants.PUBLISH_TO_LIVE)) {
        hideDefaultSuccessMessage(actionRequest);

        StagingUtil.publishToLive(actionRequest);
      } else if (cmd.equals(Constants.PUBLISH_TO_REMOTE)) {
        hideDefaultSuccessMessage(actionRequest);

        StagingUtil.publishToRemote(actionRequest);
      } else if (cmd.equals("schedule_copy_from_live")) {
        StagingUtil.scheduleCopyFromLive(actionRequest);
      } else if (cmd.equals("schedule_publish_to_live")) {
        StagingUtil.schedulePublishToLive(actionRequest);
      } else if (cmd.equals("schedule_publish_to_remote")) {
        StagingUtil.schedulePublishToRemote(actionRequest);
      } else if (cmd.equals("unschedule_copy_from_live")) {
        StagingUtil.unscheduleCopyFromLive(actionRequest);
      } else if (cmd.equals("unschedule_publish_to_live")) {
        StagingUtil.unschedulePublishToLive(actionRequest);
      } else if (cmd.equals("unschedule_publish_to_remote")) {
        StagingUtil.unschedulePublishToRemote(actionRequest);
      }

      sendRedirect(actionRequest, actionResponse);
    } catch (Exception e) {
      if (e instanceof PrincipalException) {
        SessionErrors.add(actionRequest, e.getClass());

        actionResponse.setRenderParameter("mvcPath", "/error.jsp");
      } else if (e instanceof AuthException
          || e instanceof DuplicateLockException
          || e instanceof LayoutPrototypeException
          || e instanceof RemoteAuthException
          || e instanceof RemoteExportException
          || e instanceof RemoteOptionsException
          || e instanceof SystemException) {

        if (e instanceof RemoteAuthException) {
          SessionErrors.add(actionRequest, AuthException.class, e);
        } else {
          SessionErrors.add(actionRequest, e.getClass(), e);
        }

        sendRedirect(actionRequest, actionResponse);
      } else {
        throw e;
      }
    }
  }