@Override
  public BackgroundTaskResult execute(BackgroundTask backgroundTask) {
    ExportImportConfiguration exportImportConfiguration =
        getExportImportConfiguration(backgroundTask);

    clearBackgroundTaskStatus(backgroundTask);

    Thread currentThread = Thread.currentThread();

    ClassLoader contextClassLoader = currentThread.getContextClassLoader();

    File file = null;
    HttpPrincipal httpPrincipal = null;
    MissingReferences missingReferences = null;
    long stagingRequestId = 0L;

    try {
      currentThread.setContextClassLoader(ClassLoaderUtil.getPortalClassLoader());

      ExportImportThreadLocal.setLayoutStagingInProcess(true);

      ExportImportLifecycleManagerUtil.fireExportImportLifecycleEvent(
          EVENT_PUBLICATION_LAYOUT_REMOTE_STARTED,
          PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS,
          exportImportConfiguration);

      Map<String, Serializable> settingsMap = exportImportConfiguration.getSettingsMap();

      long sourceGroupId = MapUtil.getLong(settingsMap, "sourceGroupId");
      boolean privateLayout = MapUtil.getBoolean(settingsMap, "privateLayout");

      initThreadLocals(sourceGroupId, privateLayout);

      Map<Long, Boolean> layoutIdMap = (Map<Long, Boolean>) settingsMap.get("layoutIdMap");
      long targetGroupId = MapUtil.getLong(settingsMap, "targetGroupId");

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

      httpPrincipal = (HttpPrincipal) taskContextMap.get("httpPrincipal");

      file =
          exportLayoutsAsFile(exportImportConfiguration, layoutIdMap, targetGroupId, httpPrincipal);

      String checksum = FileUtil.getMD5Checksum(file);

      stagingRequestId =
          StagingServiceHttp.createStagingRequest(httpPrincipal, targetGroupId, checksum);

      transferFileToRemoteLive(file, stagingRequestId, httpPrincipal);

      markBackgroundTask(backgroundTask.getBackgroundTaskId(), "exported");

      missingReferences =
          StagingServiceHttp.publishStagingRequest(
              httpPrincipal, stagingRequestId, exportImportConfiguration);

      ExportImportThreadLocal.setLayoutStagingInProcess(false);

      ExportImportLifecycleManagerUtil.fireExportImportLifecycleEvent(
          EVENT_PUBLICATION_LAYOUT_REMOTE_SUCCEEDED,
          PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS,
          exportImportConfiguration);
    } catch (Throwable t) {
      ExportImportThreadLocal.setLayoutStagingInProcess(false);

      ExportImportLifecycleManagerUtil.fireExportImportLifecycleEvent(
          EVENT_PUBLICATION_LAYOUT_REMOTE_FAILED,
          PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS,
          exportImportConfiguration);

      if (_log.isDebugEnabled()) {
        _log.debug(t, t);
      } else if (_log.isWarnEnabled()) {
        _log.warn("Unable to publish layout: " + t.getMessage());
      }

      deleteTempLarOnFailure(file);

      throw new SystemException(t);
    } finally {
      currentThread.setContextClassLoader(contextClassLoader);

      if ((stagingRequestId > 0) && (httpPrincipal != null)) {
        try {
          StagingServiceHttp.cleanUpStagingRequest(httpPrincipal, stagingRequestId);
        } catch (PortalException pe) {
          _log.warn("Unable to clean up the remote live site");
        }
      }
    }

    deleteTempLarOnSuccess(file);

    return processMissingReferences(backgroundTask.getBackgroundTaskId(), missingReferences);
  }
  @Test
  public void testTypeLinkToLayout() throws Exception {
    initExport();

    Map<String, List<StagedModel>> dependentStagedModelsMap = new HashMap<>();

    Layout linkedLayout = LayoutTestUtil.addLayout(stagingGroup);

    List<LayoutFriendlyURL> linkedLayoutFriendlyURLs =
        LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(linkedLayout.getPlid());

    addDependentStagedModel(dependentStagedModelsMap, Layout.class, linkedLayout);

    addDependentLayoutFriendlyURLs(dependentStagedModelsMap, linkedLayout);

    Layout layout =
        LayoutTestUtil.addTypeLinkToLayoutLayout(
            stagingGroup.getGroupId(), linkedLayout.getLayoutId());

    List<LayoutFriendlyURL> layoutFriendlyURLs =
        LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(layout.getPlid());

    addDependentLayoutFriendlyURLs(dependentStagedModelsMap, layout);

    StagedModelDataHandlerUtil.exportStagedModel(portletDataContext, layout);

    validateExport(portletDataContext, layout, dependentStagedModelsMap);

    initImport();

    ExportImportLifecycleManagerUtil.fireExportImportLifecycleEvent(
        ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_STARTED,
        ExportImportLifecycleConstants.PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS,
        PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext));

    Layout exportedLayout = (Layout) readExportedStagedModel(layout);

    StagedModelDataHandlerUtil.importStagedModel(portletDataContext, exportedLayout);

    Layout exportedLinkedLayout = (Layout) readExportedStagedModel(linkedLayout);

    StagedModelDataHandlerUtil.importStagedModel(portletDataContext, exportedLinkedLayout);

    ExportImportLifecycleManagerUtil.fireExportImportLifecycleEvent(
        ExportImportLifecycleConstants.EVENT_LAYOUT_IMPORT_SUCCEEDED,
        ExportImportLifecycleConstants.PROCESS_FLAG_LAYOUT_STAGING_IN_PROCESS,
        PortletDataContextFactoryUtil.clonePortletDataContext(portletDataContext));

    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
        linkedLayout.getUuid(), liveGroup.getGroupId(), false);

    LayoutFriendlyURL linkedLayoutFriendlyURL = linkedLayoutFriendlyURLs.get(0);

    LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLByUuidAndGroupId(
        linkedLayoutFriendlyURL.getUuid(), liveGroup.getGroupId());

    LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
        layout.getUuid(), liveGroup.getGroupId(), false);

    LayoutFriendlyURL layoutFriendlyURL = layoutFriendlyURLs.get(0);

    LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLByUuidAndGroupId(
        layoutFriendlyURL.getUuid(), liveGroup.getGroupId());
  }