public void importServicePortletPreferences(
      PortletDataContext portletDataContext, Element serviceElement) throws PortalException {

    long ownerId = GetterUtil.getLong(serviceElement.attributeValue("owner-id"));
    int ownerType = GetterUtil.getInteger(serviceElement.attributeValue("owner-type"));
    String serviceName = serviceElement.attributeValue("service-name");

    if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
      ownerId = portletDataContext.getGroupId();
    } else if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
      ownerId = portletDataContext.getCompanyId();
    }

    PortletPreferences portletPreferences =
        getPortletPreferences(
            portletDataContext.getCompanyId(),
            ownerId,
            ownerType,
            LayoutConstants.DEFAULT_PLID,
            serviceName);

    for (Attribute attribute : serviceElement.attributes()) {
      serviceElement.remove(attribute);
    }

    String xml = serviceElement.asXML();

    portletPreferences.setPreferences(xml);

    _portletPreferencesLocalService.updatePortletPreferences(portletPreferences);
  }
  @Override
  public void deleteStagedModels(PortletDataContext portletDataContext) throws PortalException {

    Map<String, String[]> parameterMap = portletDataContext.getParameterMap();

    long classNameId = MapUtil.getLong(parameterMap, "parentStagedModelClassNameId");

    _friendlyURLLocalService.deleteGroupFriendlyURLs(portletDataContext.getGroupId(), classNameId);
  }
  protected String deletePortletData(
      PortletDataContext portletDataContext, javax.portlet.PortletPreferences portletPreferences)
      throws Exception {

    Group group = _groupLocalService.getGroup(portletDataContext.getGroupId());

    if (!group.isStagedPortlet(portletDataContext.getPortletId())) {
      if (_log.isDebugEnabled()) {
        _log.debug(
            "Do not delete portlet data for "
                + portletDataContext.getPortletId()
                + " because the portlet is not staged");
      }

      return null;
    }

    PortletDataHandler portletDataHandler =
        _portletDataHandlerProvider.provide(
            portletDataContext.getCompanyId(), portletDataContext.getPortletId());

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

        sb.append("Do not delete portlet data for ");
        sb.append(portletDataContext.getPortletId());
        sb.append(" because the portlet does not have a ");
        sb.append("PortletDataHandler");

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

      return null;
    }

    if (_log.isDebugEnabled()) {
      _log.debug("Deleting data for " + portletDataContext.getPortletId());
    }

    try {
      portletPreferences =
          portletDataHandler.deleteData(
              portletDataContext, portletDataContext.getPortletId(), portletPreferences);
    } finally {
      portletDataContext.setGroupId(portletDataContext.getScopeGroupId());
    }

    if (portletPreferences == null) {
      return null;
    }

    return PortletPreferencesFactoryUtil.toXML(portletPreferences);
  }
  @Override
  protected void doImportStagedModel(PortletDataContext portletDataContext, UserGroup userGroup)
      throws Exception {

    long userId = portletDataContext.getUserId(userGroup.getUserUuid());

    ServiceContext serviceContext = portletDataContext.createServiceContext(userGroup);

    UserGroup existingUserGroup =
        fetchStagedModelByUuidAndGroupId(userGroup.getUuid(), portletDataContext.getGroupId());

    if (existingUserGroup == null) {
      existingUserGroup =
          _userGroupLocalService.fetchUserGroup(
              portletDataContext.getCompanyId(), userGroup.getName());
    }

    UserGroup importedUserGroup = null;

    if (existingUserGroup == null) {
      serviceContext.setUuid(userGroup.getUuid());

      importedUserGroup =
          _userGroupLocalService.addUserGroup(
              userId,
              portletDataContext.getCompanyId(),
              userGroup.getName(),
              userGroup.getDescription(),
              serviceContext);
    } else {
      importedUserGroup =
          _userGroupLocalService.updateUserGroup(
              portletDataContext.getCompanyId(),
              existingUserGroup.getUserGroupId(),
              userGroup.getName(),
              userGroup.getDescription(),
              serviceContext);
    }

    portletDataContext.importClassedModel(userGroup, importedUserGroup);
  }
  protected void doImportPortletInfo(PortletDataContext portletDataContext, long userId)
      throws Exception {

    Map<String, String[]> parameterMap = portletDataContext.getParameterMap();

    boolean importPermissions =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();

    if (serviceContext == null) {
      serviceContext = new ServiceContext();

      serviceContext.setCompanyId(portletDataContext.getCompanyId());
      serviceContext.setSignedIn(false);
      serviceContext.setUserId(userId);

      ServiceContextThreadLocal.pushServiceContext(serviceContext);
    }

    // LAR validation

    validateFile(
        portletDataContext.getCompanyId(),
        portletDataContext.getGroupId(),
        portletDataContext.getPortletId(),
        portletDataContext.getZipReader());

    // Source and target group id

    Map<Long, Long> groupIds =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(Group.class);

    groupIds.put(portletDataContext.getSourceGroupId(), portletDataContext.getGroupId());

    // Manifest

    ManifestSummary manifestSummary = ExportImportHelperUtil.getManifestSummary(portletDataContext);

    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
      PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
          "portlet", portletDataContext.getPortletId(), manifestSummary);
    }

    portletDataContext.setManifestSummary(manifestSummary);

    // Read expando tables, locks and permissions to make them
    // available to the data handlers through the portlet data context

    Element rootElement = portletDataContext.getImportDataRootElement();

    Element portletElement = null;

    try {
      portletElement = rootElement.element("portlet");

      Document portletDocument =
          SAXReaderUtil.read(
              portletDataContext.getZipEntryAsString(portletElement.attributeValue("path")));

      portletElement = portletDocument.getRootElement();
    } catch (DocumentException de) {
      throw new SystemException(de);
    }

    LayoutCache layoutCache = new LayoutCache();

    if (importPermissions) {
      _permissionImporter.checkRoles(
          layoutCache,
          portletDataContext.getCompanyId(),
          portletDataContext.getGroupId(),
          userId,
          portletElement);

      _permissionImporter.readPortletDataPermissions(portletDataContext);
    }

    readExpandoTables(portletDataContext);
    readLocks(portletDataContext);

    Element portletDataElement = portletElement.element("portlet-data");

    Map<String, Boolean> importPortletControlsMap =
        ExportImportHelperUtil.getImportPortletControlsMap(
            portletDataContext.getCompanyId(),
            portletDataContext.getPortletId(),
            parameterMap,
            portletDataElement,
            manifestSummary);

    Layout layout = _layoutLocalService.getLayout(portletDataContext.getPlid());

    try {

      // Portlet preferences

      importPortletPreferences(
          portletDataContext,
          layout.getCompanyId(),
          portletDataContext.getGroupId(),
          layout,
          portletElement,
          true,
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP),
          importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));

      // Portlet data

      if (importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA)) {

        if (_log.isDebugEnabled()) {
          _log.debug("Importing portlet data");
        }

        importPortletData(portletDataContext, portletDataElement);
      }
    } finally {
      resetPortletScope(portletDataContext, portletDataContext.getGroupId());
    }

    // Portlet permissions

    if (importPermissions) {
      if (_log.isDebugEnabled()) {
        _log.debug("Importing portlet permissions");
      }

      _permissionImporter.importPortletPermissions(
          layoutCache,
          portletDataContext.getCompanyId(),
          portletDataContext.getGroupId(),
          userId,
          layout,
          portletElement,
          portletDataContext.getPortletId());

      if (userId > 0) {
        Indexer<User> indexer = IndexerRegistryUtil.nullSafeGetIndexer(User.class);

        User user = _userLocalService.fetchUser(userId);

        indexer.reindex(user);
      }
    }

    // Asset links

    if (_log.isDebugEnabled()) {
      _log.debug("Importing asset links");
    }

    importAssetLinks(portletDataContext);

    // Deletion system events

    _deletionSystemEventImporter.importDeletionSystemEvents(portletDataContext);

    if (_log.isInfoEnabled()) {
      _log.info("Importing portlet takes " + stopWatch.getTime() + " ms");
    }

    // Service portlet preferences

    boolean importPortletSetup = importPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP);

    if (importPortletSetup) {
      try {
        List<Element> serviceElements = rootElement.elements("service");

        for (Element serviceElement : serviceElements) {
          Document serviceDocument =
              SAXReaderUtil.read(
                  portletDataContext.getZipEntryAsString(serviceElement.attributeValue("path")));

          importServicePortletPreferences(portletDataContext, serviceDocument.getRootElement());
        }
      } catch (DocumentException de) {
        throw new SystemException(de);
      }
    }

    ZipReader zipReader = portletDataContext.getZipReader();

    zipReader.close();
  }
  protected void exportPortlet(
      PortletDataContext portletDataContext,
      Layout layout,
      Element parentElement,
      boolean exportPermissions,
      boolean exportPortletArchivedSetups,
      boolean exportPortletData,
      boolean exportPortletSetup,
      boolean exportPortletUserPreferences)
      throws Exception {

    long plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
    long layoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;

    if (layout != null) {
      plid = layout.getPlid();
      layoutId = layout.getLayoutId();
    }

    Portlet portlet =
        _portletLocalService.getPortletById(
            portletDataContext.getCompanyId(), portletDataContext.getPortletId());

    if ((portlet == null) || portlet.isUndeployedPortlet()) {
      if (_log.isDebugEnabled()) {
        _log.debug(
            "Do not export portlet "
                + portletDataContext.getPortletId()
                + " because the portlet is not deployed");
      }

      return;
    }

    if (!portlet.isInstanceable()
        && !portlet.isPreferencesUniquePerLayout()
        && portletDataContext.hasNotUniquePerLayout(portletDataContext.getPortletId())) {

      return;
    }

    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
      PortletDataContext clonedPortletDataContext =
          PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext);

      ManifestSummary manifestSummary = clonedPortletDataContext.getManifestSummary();

      manifestSummary.resetCounters();

      PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

      portletDataHandler.prepareManifestSummary(clonedPortletDataContext);

      PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
          "portlet", portletDataContext.getPortletId(), manifestSummary);
    }

    Document document = SAXReaderUtil.createDocument();

    Element portletElement = document.addElement("portlet");

    portletElement.addAttribute("portlet-id", portletDataContext.getPortletId());
    portletElement.addAttribute("root-portlet-id", portletDataContext.getRootPortletId());
    portletElement.addAttribute("old-plid", String.valueOf(plid));
    portletElement.addAttribute(
        "scope-group-id", String.valueOf(portletDataContext.getScopeGroupId()));
    portletElement.addAttribute("scope-layout-type", portletDataContext.getScopeType());
    portletElement.addAttribute("scope-layout-uuid", portletDataContext.getScopeLayoutUuid());
    portletElement.addAttribute("private-layout", String.valueOf(layout.isPrivateLayout()));

    // Data

    if (exportPortletData) {
      javax.portlet.PortletPreferences jxPortletPreferences = null;

      if (ExportImportThreadLocal.isInitialLayoutStagingInProcess()) {
        Group liveGroup = layout.getGroup();

        Group stagingGroup = liveGroup.getStagingGroup();

        layout.setGroupId(stagingGroup.getGroupId());

        jxPortletPreferences =
            PortletPreferencesFactoryUtil.getStrictPortletSetup(
                layout, portletDataContext.getPortletId());

        layout.setGroupId(liveGroup.getGroupId());
      } else {
        jxPortletPreferences =
            PortletPreferencesFactoryUtil.getStrictPortletSetup(
                layout, portletDataContext.getPortletId());
      }

      if (!portlet.isPreferencesUniquePerLayout()) {
        StringBundler sb = new StringBundler(5);

        sb.append(portletDataContext.getPortletId());
        sb.append(StringPool.AT);
        sb.append(portletDataContext.getScopeType());
        sb.append(StringPool.AT);
        sb.append(portletDataContext.getScopeLayoutUuid());

        String dataKey = sb.toString();

        if (!portletDataContext.hasNotUniquePerLayout(dataKey)) {
          portletDataContext.putNotUniquePerLayout(dataKey);

          exportPortletData(
              portletDataContext, portlet, layout, jxPortletPreferences, portletElement);
        }
      } else {
        exportPortletData(
            portletDataContext, portlet, layout, jxPortletPreferences, portletElement);
      }
    }

    // Portlet preferences

    if (exportPortletSetup) {

      // Company

      exportPortletPreferences(
          portletDataContext,
          portletDataContext.getCompanyId(),
          PortletKeys.PREFS_OWNER_TYPE_COMPANY,
          false,
          layout,
          plid,
          portlet.getRootPortletId(),
          portletElement);

      // Group

      exportPortletPreferences(
          portletDataContext,
          portletDataContext.getScopeGroupId(),
          PortletKeys.PREFS_OWNER_TYPE_GROUP,
          false,
          layout,
          PortletKeys.PREFS_PLID_SHARED,
          portlet.getRootPortletId(),
          portletElement);

      // Layout

      exportPortletPreferences(
          portletDataContext,
          PortletKeys.PREFS_OWNER_ID_DEFAULT,
          PortletKeys.PREFS_OWNER_TYPE_LAYOUT,
          false,
          layout,
          plid,
          portletDataContext.getPortletId(),
          portletElement);
    }

    // Portlet user preferences

    if (exportPortletUserPreferences) {
      List<PortletPreferences> portletPreferencesList =
          _portletPreferencesLocalService.getPortletPreferences(
              PortletKeys.PREFS_OWNER_TYPE_USER, plid, portletDataContext.getPortletId());

      for (PortletPreferences portletPreferences : portletPreferencesList) {

        boolean defaultUser = false;

        if (portletPreferences.getOwnerId() == PortletKeys.PREFS_OWNER_ID_DEFAULT) {

          defaultUser = true;
        }

        exportPortletPreferences(
            portletDataContext,
            portletPreferences.getOwnerId(),
            PortletKeys.PREFS_OWNER_TYPE_USER,
            defaultUser,
            layout,
            plid,
            portletDataContext.getPortletId(),
            portletElement);
      }

      try {
        PortletPreferences groupPortletPreferences =
            _portletPreferencesLocalService.getPortletPreferences(
                portletDataContext.getScopeGroupId(),
                PortletKeys.PREFS_OWNER_TYPE_GROUP,
                PortletKeys.PREFS_PLID_SHARED,
                portlet.getRootPortletId());

        exportPortletPreference(
            portletDataContext,
            portletDataContext.getScopeGroupId(),
            PortletKeys.PREFS_OWNER_TYPE_GROUP,
            false,
            groupPortletPreferences,
            portlet.getRootPortletId(),
            PortletKeys.PREFS_PLID_SHARED,
            portletElement);
      } catch (NoSuchPortletPreferencesException nsppe) {
      }
    }

    // Archived setups

    if (exportPortletArchivedSetups) {
      List<PortletItem> portletItems =
          _portletItemLocalService.getPortletItems(
              portletDataContext.getGroupId(),
              portletDataContext.getRootPortletId(),
              PortletPreferences.class.getName());

      for (PortletItem portletItem : portletItems) {
        exportPortletPreferences(
            portletDataContext,
            portletItem.getPortletItemId(),
            PortletKeys.PREFS_OWNER_TYPE_ARCHIVED,
            false,
            null,
            plid,
            portletItem.getPortletId(),
            portletElement);
      }
    }

    // Permissions

    if (exportPermissions) {
      _permissionExporter.exportPortletPermissions(
          portletDataContext, portletDataContext.getPortletId(), layout, portletElement);
    }

    // Zip

    StringBundler pathSB = new StringBundler(4);

    pathSB.append(ExportImportPathUtil.getPortletPath(portletDataContext));
    pathSB.append(StringPool.SLASH);
    pathSB.append(plid);
    pathSB.append("/portlet.xml");

    String path = pathSB.toString();

    Element element = parentElement.addElement("portlet");

    element.addAttribute("portlet-id", portletDataContext.getPortletId());
    element.addAttribute("layout-id", String.valueOf(layoutId));
    element.addAttribute("path", path);
    element.addAttribute("portlet-data", String.valueOf(exportPortletData));

    PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

    element.addAttribute("schema-version", portletDataHandler.getSchemaVersion());

    StringBundler configurationOptionsSB = new StringBundler(6);

    if (exportPortletSetup) {
      configurationOptionsSB.append("setup");
      configurationOptionsSB.append(StringPool.COMMA);
    }

    if (exportPortletArchivedSetups) {
      configurationOptionsSB.append("archived-setups");
      configurationOptionsSB.append(StringPool.COMMA);
    }

    if (exportPortletUserPreferences) {
      configurationOptionsSB.append("user-preferences");
      configurationOptionsSB.append(StringPool.COMMA);
    }

    if (configurationOptionsSB.index() > 0) {
      configurationOptionsSB.setIndex(configurationOptionsSB.index() - 1);
    }

    element.addAttribute("portlet-configuration", configurationOptionsSB.toString());

    try {
      portletDataContext.addZipEntry(path, document.formattedString());
    } catch (IOException ioe) {
      if (_log.isWarnEnabled()) {
        _log.warn(ioe.getMessage());
      }
    }
  }
  protected File doExport(PortletDataContext portletDataContext) throws Exception {

    boolean exportPermissions =
        MapUtil.getBoolean(
            portletDataContext.getParameterMap(), PortletDataHandlerKeys.PERMISSIONS);

    if (_log.isDebugEnabled()) {
      _log.debug("Export permissions " + exportPermissions);
    }

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    Layout layout = _layoutLocalService.getLayout(portletDataContext.getPlid());

    if (!layout.isTypeControlPanel() && !layout.isTypePanel() && !layout.isTypePortlet()) {

      throw new LayoutImportException("Layout type " + layout.getType() + " is not valid");
    }

    ServiceContext serviceContext = ServiceContextThreadLocal.getServiceContext();

    if (serviceContext == null) {
      serviceContext = new ServiceContext();

      serviceContext.setCompanyId(layout.getCompanyId());
      serviceContext.setSignedIn(false);

      long defaultUserId = _userLocalService.getDefaultUserId(layout.getCompanyId());

      serviceContext.setUserId(defaultUserId);

      ServiceContextThreadLocal.pushServiceContext(serviceContext);
    }

    long layoutSetBranchId =
        MapUtil.getLong(portletDataContext.getParameterMap(), "layoutSetBranchId");

    serviceContext.setAttribute("layoutSetBranchId", layoutSetBranchId);

    long scopeGroupId = portletDataContext.getGroupId();

    javax.portlet.PortletPreferences jxPortletPreferences =
        PortletPreferencesFactoryUtil.getLayoutPortletSetup(
            layout, portletDataContext.getPortletId());

    String scopeType = GetterUtil.getString(jxPortletPreferences.getValue("lfrScopeType", null));
    String scopeLayoutUuid =
        GetterUtil.getString(jxPortletPreferences.getValue("lfrScopeLayoutUuid", null));

    if (Validator.isNotNull(scopeType)) {
      Group scopeGroup = null;

      if (scopeType.equals("company")) {
        scopeGroup = _groupLocalService.getCompanyGroup(layout.getCompanyId());
      } else if (Validator.isNotNull(scopeLayoutUuid)) {
        scopeGroup = layout.getScopeGroup();
      }

      if (scopeGroup != null) {
        scopeGroupId = scopeGroup.getGroupId();
      }
    }

    portletDataContext.setScopeType(scopeType);
    portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);

    Document document = SAXReaderUtil.createDocument();

    Element rootElement = document.addElement("root");

    portletDataContext.setExportDataRootElement(rootElement);

    Element headerElement = rootElement.addElement("header");

    headerElement.addAttribute(
        "available-locales",
        StringUtil.merge(
            LanguageUtil.getAvailableLocales(
                PortalUtil.getSiteGroupId(portletDataContext.getScopeGroupId()))));
    headerElement.addAttribute("build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
    headerElement.addAttribute("export-date", Time.getRFC822());

    if (portletDataContext.hasDateRange()) {
      headerElement.addAttribute("start-date", String.valueOf(portletDataContext.getStartDate()));
      headerElement.addAttribute("end-date", String.valueOf(portletDataContext.getEndDate()));
    }

    headerElement.addAttribute("type", "portlet");
    headerElement.addAttribute("company-id", String.valueOf(portletDataContext.getCompanyId()));
    headerElement.addAttribute(
        "company-group-id", String.valueOf(portletDataContext.getCompanyGroupId()));
    headerElement.addAttribute("group-id", String.valueOf(scopeGroupId));
    headerElement.addAttribute(
        "user-personal-site-group-id",
        String.valueOf(portletDataContext.getUserPersonalSiteGroupId()));
    headerElement.addAttribute("private-layout", String.valueOf(layout.isPrivateLayout()));
    headerElement.addAttribute("root-portlet-id", portletDataContext.getRootPortletId());

    Element missingReferencesElement = rootElement.addElement("missing-references");

    portletDataContext.setMissingReferencesElement(missingReferencesElement);

    Map<String, Boolean> exportPortletControlsMap =
        ExportImportHelperUtil.getExportPortletControlsMap(
            layout.getCompanyId(),
            portletDataContext.getPortletId(),
            portletDataContext.getParameterMap());

    exportPortlet(
        portletDataContext,
        layout,
        rootElement,
        exportPermissions,
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA),
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP),
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
    exportService(
        portletDataContext,
        rootElement,
        exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP));

    exportAssetLinks(portletDataContext);
    exportExpandoTables(portletDataContext);
    exportLocks(portletDataContext);

    _deletionSystemEventExporter.exportDeletionSystemEvents(portletDataContext);

    if (exportPermissions) {
      _permissionExporter.exportPortletDataPermissions(portletDataContext);
    }

    ExportImportHelperUtil.writeManifestSummary(document, portletDataContext.getManifestSummary());

    if (_log.isInfoEnabled()) {
      _log.info("Exporting portlet took " + stopWatch.getTime() + " ms");
    }

    try {
      portletDataContext.addZipEntry("/manifest.xml", document.formattedString());
    } catch (IOException ioe) {
      throw new SystemException(ioe);
    }

    ZipWriter zipWriter = portletDataContext.getZipWriter();

    return zipWriter.getFile();
  }
  public void exportPortletData(
      PortletDataContext portletDataContext,
      Portlet portlet,
      Layout layout,
      javax.portlet.PortletPreferences jxPortletPreferences,
      Element parentElement)
      throws Exception {

    if (portlet == null) {
      return;
    }

    PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

    if ((portletDataHandler == null) || portletDataHandler.isDataPortletInstanceLevel()) {

      return;
    }

    Group group = layout.getGroup();

    if (group.isStagingGroup()) {
      group = group.getLiveGroup();
    }

    String portletId = portlet.getPortletId();

    if (ExportImportThreadLocal.isStagingInProcess() && !group.isStagedPortlet(portletId)) {

      if (_log.isDebugEnabled()) {
        _log.debug(
            "Not exporting data for " + portletId + " because it is configured not to be staged");
      }

      return;
    }

    if (_log.isDebugEnabled()) {
      _log.debug("Exporting data for " + portletId);
    }

    StringBundler sb = new StringBundler(4);

    sb.append(ExportImportPathUtil.getPortletPath(portletDataContext, portletId));
    sb.append(StringPool.SLASH);

    if (portlet.isPreferencesUniquePerLayout()) {
      sb.append(layout.getPlid());
    } else {
      sb.append(portletDataContext.getScopeGroupId());
    }

    sb.append("/portlet-data.xml");

    String path = sb.toString();

    if (portletDataContext.hasPrimaryKey(String.class, path)) {
      return;
    }

    Date originalStartDate = portletDataContext.getStartDate();

    Date portletLastPublishDate =
        ExportImportDateUtil.getLastPublishDate(portletDataContext, jxPortletPreferences);

    portletDataContext.setStartDate(portletLastPublishDate);

    long groupId = portletDataContext.getGroupId();

    portletDataContext.setGroupId(portletDataContext.getScopeGroupId());

    portletDataContext.clearScopedPrimaryKeys();

    String data = null;

    try {
      data = portletDataHandler.exportData(portletDataContext, portletId, jxPortletPreferences);
    } catch (PortletDataException pde) {
      throw pde;
    } catch (Exception e) {
      throw new SystemException(e);
    } finally {
      portletDataContext.setGroupId(groupId);
      portletDataContext.setStartDate(originalStartDate);
    }

    if (Validator.isNull(data)) {
      if (_log.isDebugEnabled()) {
        _log.debug("Not exporting data for " + portletId + " because null data was returned");
      }

      return;
    }

    Element portletDataElement = parentElement.addElement("portlet-data");

    portletDataElement.addAttribute("path", path);

    portletDataContext.addZipEntry(path, data);

    boolean updateLastPublishDate =
        MapUtil.getBoolean(
            portletDataContext.getParameterMap(), PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE);

    if (ExportImportThreadLocal.isStagingInProcess() && updateLastPublishDate) {

      DateRange adjustedDateRange =
          new DateRange(portletLastPublishDate, portletDataContext.getEndDate());

      ExportImportProcessCallbackRegistryUtil.registerCallback(
          new UpdatePortletLastPublishDateCallable(
              adjustedDateRange,
              portletDataContext.getEndDate(),
              portletDataContext.getGroupId(),
              layout.getPlid(),
              portletId));
    }
  }
  protected void getLayoutPortlets(
      PortletDataContext portletDataContext,
      long[] layoutIds,
      Map<String, Object[]> portletIds,
      Layout layout)
      throws Exception {

    if (!ArrayUtil.contains(layoutIds, layout.getLayoutId())) {
      return;
    }

    if (!prepareLayoutStagingHandler(portletDataContext, layout)
        || !layout.isSupportsEmbeddedPortlets()) {

      // Only portlet type layouts support page scoping

      return;
    }

    LayoutTypePortlet layoutTypePortlet = (LayoutTypePortlet) layout.getLayoutType();

    // The getAllPortlets method returns all effective nonsystem portlets
    // for any layout type, including embedded portlets, or in the case of
    // panel type layout, selected portlets

    for (Portlet portlet : layoutTypePortlet.getAllPortlets(false)) {
      String portletId = portlet.getPortletId();

      Settings portletInstanceSettings =
          SettingsFactoryUtil.getSettings(new PortletInstanceSettingsLocator(layout, portletId));

      String scopeType = portletInstanceSettings.getValue("lfrScopeType", null);
      String scopeLayoutUuid = portletInstanceSettings.getValue("lfrScopeLayoutUuid", null);

      long scopeGroupId = portletDataContext.getScopeGroupId();

      if (Validator.isNotNull(scopeType)) {
        Group scopeGroup = null;

        if (scopeType.equals("company")) {
          scopeGroup = _groupLocalService.getCompanyGroup(layout.getCompanyId());
        } else if (scopeType.equals("layout")) {
          Layout scopeLayout = null;

          scopeLayout =
              _layoutLocalService.fetchLayoutByUuidAndGroupId(
                  scopeLayoutUuid,
                  portletDataContext.getGroupId(),
                  portletDataContext.isPrivateLayout());

          if (scopeLayout == null) {
            continue;
          }

          scopeGroup = scopeLayout.getScopeGroup();
        } else {
          throw new IllegalArgumentException("Scope type " + scopeType + " is invalid");
        }

        if (scopeGroup != null) {
          scopeGroupId = scopeGroup.getGroupId();
        }
      }

      String key = PortletPermissionUtil.getPrimaryKey(layout.getPlid(), portletId);

      portletIds.put(
          key,
          new Object[] {portletId, layout.getPlid(), scopeGroupId, scopeType, scopeLayoutUuid});
    }
  }
  protected File doExport(PortletDataContext portletDataContext, long[] layoutIds)
      throws Exception {

    Map<String, String[]> parameterMap = portletDataContext.getParameterMap();

    boolean ignoreLastPublishDate =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.IGNORE_LAST_PUBLISH_DATE);
    boolean layoutSetPrototypeSettings =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_SETTINGS);
    boolean layoutSetSettings =
        MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);
    boolean logo = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.LOGO);
    boolean permissions = MapUtil.getBoolean(parameterMap, PortletDataHandlerKeys.PERMISSIONS);

    if (_log.isDebugEnabled()) {
      _log.debug("Export permissions " + permissions);
    }

    LayoutSet layoutSet =
        _layoutSetLocalService.getLayoutSet(
            portletDataContext.getGroupId(), portletDataContext.isPrivateLayout());

    long companyId = layoutSet.getCompanyId();
    long defaultUserId = _userLocalService.getDefaultUserId(companyId);

    ServiceContext serviceContext = ServiceContextThreadLocal.popServiceContext();

    if (serviceContext == null) {
      serviceContext = new ServiceContext();
    }

    serviceContext.setCompanyId(companyId);
    serviceContext.setSignedIn(false);
    serviceContext.setUserId(defaultUserId);

    serviceContext.setAttribute("exporting", Boolean.TRUE);

    long layoutSetBranchId = MapUtil.getLong(parameterMap, "layoutSetBranchId");

    serviceContext.setAttribute("layoutSetBranchId", layoutSetBranchId);

    ServiceContextThreadLocal.pushServiceContext(serviceContext);

    if (ignoreLastPublishDate) {
      portletDataContext.setEndDate(null);
      portletDataContext.setStartDate(null);
    }

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    Document document = SAXReaderUtil.createDocument();

    Element rootElement = document.addElement("root");

    portletDataContext.setExportDataRootElement(rootElement);

    Element headerElement = rootElement.addElement("header");

    headerElement.addAttribute(
        "available-locales",
        StringUtil.merge(LanguageUtil.getAvailableLocales(portletDataContext.getScopeGroupId())));
    headerElement.addAttribute("build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
    headerElement.addAttribute("export-date", Time.getRFC822());

    if (portletDataContext.hasDateRange()) {
      headerElement.addAttribute("start-date", String.valueOf(portletDataContext.getStartDate()));
      headerElement.addAttribute("end-date", String.valueOf(portletDataContext.getEndDate()));
    }

    headerElement.addAttribute("company-id", String.valueOf(portletDataContext.getCompanyId()));
    headerElement.addAttribute(
        "company-group-id", String.valueOf(portletDataContext.getCompanyGroupId()));
    headerElement.addAttribute("group-id", String.valueOf(portletDataContext.getGroupId()));
    headerElement.addAttribute(
        "user-personal-site-group-id",
        String.valueOf(portletDataContext.getUserPersonalSiteGroupId()));
    headerElement.addAttribute(
        "private-layout", String.valueOf(portletDataContext.isPrivateLayout()));

    Group group = layoutSet.getGroup();

    String type = "layout-set";

    if (group.isLayoutPrototype()) {
      type = "layout-prototype";

      LayoutPrototype layoutPrototype =
          _layoutPrototypeLocalService.getLayoutPrototype(group.getClassPK());

      headerElement.addAttribute("type-uuid", layoutPrototype.getUuid());

      layoutIds =
          ExportImportHelperUtil.getAllLayoutIds(
              portletDataContext.getGroupId(), portletDataContext.isPrivateLayout());
    } else if (group.isLayoutSetPrototype()) {
      type = "layout-set-prototype";

      LayoutSetPrototype layoutSetPrototype =
          _layoutSetPrototypeLocalService.getLayoutSetPrototype(group.getClassPK());

      headerElement.addAttribute("type-uuid", layoutSetPrototype.getUuid());
    }

    headerElement.addAttribute("type", type);

    LayoutSetBranch layoutSetBranch =
        _layoutSetBranchLocalService.fetchLayoutSetBranch(layoutSetBranchId);

    if (logo) {
      Image image = null;

      if (layoutSetBranch != null) {
        image = _imageLocalService.getImage(layoutSetBranch.getLogoId());
      } else {
        image = _imageLocalService.getImage(layoutSet.getLogoId());
      }

      if ((image != null) && (image.getTextObj() != null)) {
        String logoPath = ExportImportPathUtil.getRootPath(portletDataContext);

        logoPath += "/logo";

        headerElement.addAttribute("logo-path", logoPath);

        portletDataContext.addZipEntry(logoPath, image.getTextObj());
      }
    }

    String layoutSetPrototypeUuid = layoutSet.getLayoutSetPrototypeUuid();

    if (layoutSetPrototypeSettings && Validator.isNotNull(layoutSetPrototypeUuid)) {

      LayoutSetPrototype layoutSetPrototype =
          _layoutSetPrototypeLocalService.getLayoutSetPrototypeByUuidAndCompanyId(
              layoutSetPrototypeUuid, companyId);

      headerElement.addAttribute("layout-set-prototype-uuid", layoutSetPrototypeUuid);
      headerElement.addAttribute(
          "layout-set-prototype-name", layoutSetPrototype.getName(LocaleUtil.getDefault()));
    }

    Element missingReferencesElement = rootElement.addElement("missing-references");

    portletDataContext.setMissingReferencesElement(missingReferencesElement);

    if (layoutSetBranch != null) {
      _themeExporter.exportTheme(portletDataContext, layoutSetBranch);
    } else {
      _themeExporter.exportTheme(portletDataContext, layoutSet);
    }

    if (layoutSetSettings) {
      Element settingsElement = headerElement.addElement("settings");

      if (layoutSetBranch != null) {
        settingsElement.addCDATA(layoutSetBranch.getSettings());
      } else {
        settingsElement.addCDATA(layoutSet.getSettings());
      }
    }

    Map<String, Object[]> portletIds = new LinkedHashMap<>();

    List<Layout> layouts =
        _layoutLocalService.getLayouts(
            portletDataContext.getGroupId(), portletDataContext.isPrivateLayout());

    if (group.isStagingGroup()) {
      group = group.getLiveGroup();
    }

    // Collect data portlets

    for (Portlet portlet : ExportImportHelperUtil.getDataSiteLevelPortlets(companyId)) {

      String portletId = portlet.getRootPortletId();

      if (ExportImportThreadLocal.isStagingInProcess() && !group.isStagedPortlet(portletId)) {

        continue;
      }

      // Calculate the amount of exported data

      if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
        PortletDataHandler portletDataHandler = portlet.getPortletDataHandlerInstance();

        portletDataHandler.prepareManifestSummary(portletDataContext);
      }

      // Add portlet ID to exportable portlets list

      portletIds.put(
          PortletPermissionUtil.getPrimaryKey(0, portletId),
          new Object[] {
            portletId,
            LayoutConstants.DEFAULT_PLID,
            portletDataContext.getGroupId(),
            StringPool.BLANK,
            StringPool.BLANK
          });

      if (!portlet.isScopeable()) {
        continue;
      }

      // Scoped data

      for (Layout layout : layouts) {
        if (!ArrayUtil.contains(layoutIds, layout.getLayoutId())
            || !layout.isTypePortlet()
            || !layout.hasScopeGroup()) {

          continue;
        }

        Group scopeGroup = layout.getScopeGroup();

        portletIds.put(
            PortletPermissionUtil.getPrimaryKey(layout.getPlid(), portlet.getPortletId()),
            new Object[] {
              portlet.getPortletId(),
              layout.getPlid(),
              scopeGroup.getGroupId(),
              StringPool.BLANK,
              layout.getUuid()
            });
      }
    }

    // Collect layout portlets

    for (Layout layout : layouts) {
      getLayoutPortlets(portletDataContext, layoutIds, portletIds, layout);
    }

    if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
      ManifestSummary manifestSummary = portletDataContext.getManifestSummary();

      PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
          "layout", ArrayUtil.toStringArray(portletIds.keySet()), manifestSummary);

      manifestSummary.resetCounters();
    }

    // Export actual data

    portletDataContext.addDeletionSystemEventStagedModelTypes(new StagedModelType(Layout.class));

    // Force to always have a layout group element

    portletDataContext.getExportDataGroupElement(Layout.class);

    for (Layout layout : layouts) {
      exportLayout(portletDataContext, layoutIds, layout);
    }

    Element portletsElement = rootElement.addElement("portlets");

    Element servicesElement = rootElement.addElement("services");

    long previousScopeGroupId = portletDataContext.getScopeGroupId();

    for (Map.Entry<String, Object[]> portletIdsEntry : portletIds.entrySet()) {

      Object[] portletObjects = portletIdsEntry.getValue();

      String portletId = null;
      long plid = LayoutConstants.DEFAULT_PLID;
      long scopeGroupId = 0;
      String scopeType = StringPool.BLANK;
      String scopeLayoutUuid = null;

      if (portletObjects.length == 4) {
        portletId = (String) portletIdsEntry.getValue()[0];
        plid = (Long) portletIdsEntry.getValue()[1];
        scopeGroupId = (Long) portletIdsEntry.getValue()[2];
        scopeLayoutUuid = (String) portletIdsEntry.getValue()[3];
      } else {
        portletId = (String) portletIdsEntry.getValue()[0];
        plid = (Long) portletIdsEntry.getValue()[1];
        scopeGroupId = (Long) portletIdsEntry.getValue()[2];
        scopeType = (String) portletIdsEntry.getValue()[3];
        scopeLayoutUuid = (String) portletIdsEntry.getValue()[4];
      }

      Layout layout = _layoutLocalService.fetchLayout(plid);

      if (layout == null) {
        layout = new LayoutImpl();

        layout.setCompanyId(companyId);
        layout.setGroupId(portletDataContext.getGroupId());
      }

      portletDataContext.setPlid(plid);
      portletDataContext.setOldPlid(plid);
      portletDataContext.setPortletId(portletId);
      portletDataContext.setScopeGroupId(scopeGroupId);
      portletDataContext.setScopeType(scopeType);
      portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);

      Map<String, Boolean> exportPortletControlsMap =
          ExportImportHelperUtil.getExportPortletControlsMap(
              companyId, portletId, parameterMap, type);

      try {
        _exportImportLifecycleManager.fireExportImportLifecycleEvent(
            EVENT_PORTLET_EXPORT_STARTED,
            getProcessFlag(),
            PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext));

        _portletExportController.exportPortlet(
            portletDataContext,
            layout,
            portletsElement,
            permissions,
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_DATA),
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP),
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
        _portletExportController.exportService(
            portletDataContext,
            servicesElement,
            exportPortletControlsMap.get(PortletDataHandlerKeys.PORTLET_SETUP));

        _exportImportLifecycleManager.fireExportImportLifecycleEvent(
            EVENT_PORTLET_EXPORT_SUCCEEDED,
            getProcessFlag(),
            PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext));
      } catch (Throwable t) {
        _exportImportLifecycleManager.fireExportImportLifecycleEvent(
            EVENT_PORTLET_EXPORT_FAILED,
            getProcessFlag(),
            PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext),
            t);

        throw t;
      }
    }

    portletDataContext.setScopeGroupId(previousScopeGroupId);

    _portletExportController.exportAssetLinks(portletDataContext);
    _portletExportController.exportExpandoTables(portletDataContext);
    _portletExportController.exportLocks(portletDataContext);

    _deletionSystemEventExporter.exportDeletionSystemEvents(portletDataContext);

    if (permissions) {
      _permissionExporter.exportPortletDataPermissions(portletDataContext);
    }

    ExportImportHelperUtil.writeManifestSummary(document, portletDataContext.getManifestSummary());

    if (_log.isInfoEnabled()) {
      _log.info("Exporting layouts takes " + stopWatch.getTime() + " ms");
    }

    boolean updateLastPublishDate =
        MapUtil.getBoolean(
            portletDataContext.getParameterMap(), PortletDataHandlerKeys.UPDATE_LAST_PUBLISH_DATE);

    if (ExportImportThreadLocal.isStagingInProcess() && updateLastPublishDate) {

      ExportImportProcessCallbackRegistryUtil.registerCallback(
          new UpdateLayoutSetLastPublishDateCallable(
              portletDataContext.getDateRange(),
              portletDataContext.getGroupId(),
              portletDataContext.isPrivateLayout()));
    }

    portletDataContext.addZipEntry("/manifest.xml", document.formattedString());

    ZipWriter zipWriter = portletDataContext.getZipWriter();

    return zipWriter.getFile();
  }