@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);
  }