All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datatransferproject.transfer.microsoft.MicrosoftTransferExtension Maven / Gradle / Ivy

package org.datatransferproject.transfer.microsoft;

import static org.datatransferproject.types.common.models.DataVertical.CALENDAR;
import static org.datatransferproject.types.common.models.DataVertical.CONTACTS;
import static org.datatransferproject.types.common.models.DataVertical.MEDIA;
import static org.datatransferproject.types.common.models.DataVertical.OFFLINE_DATA;
import static org.datatransferproject.types.common.models.DataVertical.PHOTOS;

import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import okhttp3.OkHttpClient;
import org.datatransferproject.api.launcher.ExtensionContext;
import org.datatransferproject.api.launcher.Monitor;
import org.datatransferproject.spi.cloud.storage.AppCredentialStore;
import org.datatransferproject.spi.cloud.storage.TemporaryPerJobDataStore;
import org.datatransferproject.types.common.models.DataVertical;
import org.datatransferproject.spi.transfer.extension.TransferExtension;
import org.datatransferproject.spi.transfer.provider.Exporter;
import org.datatransferproject.spi.transfer.provider.Importer;
import org.datatransferproject.transfer.microsoft.calendar.MicrosoftCalendarExporter;
import org.datatransferproject.transfer.microsoft.calendar.MicrosoftCalendarImporter;
import org.datatransferproject.transfer.microsoft.common.MicrosoftCredentialFactory;
import org.datatransferproject.transfer.microsoft.contacts.MicrosoftContactsExporter;
import org.datatransferproject.transfer.microsoft.contacts.MicrosoftContactsImporter;
import org.datatransferproject.transfer.microsoft.offline.MicrosoftOfflineDataExporter;
import org.datatransferproject.transfer.microsoft.media.MicrosoftMediaExporter;
import org.datatransferproject.transfer.microsoft.media.MicrosoftMediaImporter;
import org.datatransferproject.transfer.microsoft.photos.MicrosoftPhotosExporter;
import org.datatransferproject.transfer.microsoft.photos.MicrosoftPhotosImporter;
import org.datatransferproject.transfer.microsoft.transformer.TransformerService;
import org.datatransferproject.transfer.microsoft.transformer.TransformerServiceImpl;
import org.datatransferproject.types.transfer.auth.AppCredentials;

import java.io.IOException;

/** Bootstraps the Microsoft data transfer services. */
public class MicrosoftTransferExtension implements TransferExtension {
  public static final String SERVICE_ID = "microsoft";

  // TODO(#1065) don't keep adding here - just have the converters invoked automatically when Media
  // isn't supported on one or the other side of this equation; this is just a WIP prototype to show
  // the concept of converters at play.
  private static final ImmutableList SUPPORTED_IMPORT_SERVICES =
      ImmutableList.of(CALENDAR, CONTACTS, PHOTOS, MEDIA);
  private static final ImmutableList SUPPORTED_EXPORT_SERVICES =
      ImmutableList.of(CALENDAR, CONTACTS, PHOTOS, MEDIA, OFFLINE_DATA);
  private ImmutableMap importerMap;
  private ImmutableMap exporterMap;

  private static final String BASE_GRAPH_URL = "https://graph.microsoft.com";

  private final boolean offlineData;

  private boolean initialized = false;

  // Needed for ServiceLoader to load this class.
  public MicrosoftTransferExtension() {
    offlineData = Boolean.parseBoolean(System.getProperty("offlineData"));
  }

  @Override
  public String getServiceId() {
    return SERVICE_ID;
  }

  @Override
  public Exporter getExporter(DataVertical transferDataType) {
    Preconditions.checkState(initialized);

    if (!offlineData && transferDataType.equals(OFFLINE_DATA)) {
      // only enable if derived data explicitly set as a configuration value
      // TODO we may want to provide a config option that allows deployers to disable transfer of
      // certain data types
      return null;
    }

    Preconditions.checkArgument(SUPPORTED_EXPORT_SERVICES.contains(transferDataType));
    return exporterMap.get(transferDataType);
  }

  @Override
  public Importer getImporter(DataVertical transferDataType) {
    Preconditions.checkState(initialized);
    Preconditions.checkArgument(SUPPORTED_IMPORT_SERVICES.contains(transferDataType));
    return importerMap.get(transferDataType);
  }

  @Override
  public void initialize(ExtensionContext context) {
    // Note: initialize could be called twice in an account migration scenario where we import and
    // export to the same service provider. So just return rather than throwing if called multiple
    // times.
    if (initialized) return;

    TemporaryPerJobDataStore jobStore = context.getService(TemporaryPerJobDataStore.class);
    HttpTransport httpTransport = context.getService(HttpTransport.class);
    JsonFactory jsonFactory = context.getService(JsonFactory.class);
    TransformerService transformerService = new TransformerServiceImpl();
    OkHttpClient client = new OkHttpClient.Builder().build();
    ObjectMapper mapper = new ObjectMapper();

    AppCredentials appCredentials;
    try {
      appCredentials =
          context
              .getService(AppCredentialStore.class)
              .getAppCredentials("MICROSOFT_KEY", "MICROSOFT_SECRET");
    } catch (IOException e) {
      Monitor monitor = context.getMonitor();
      monitor.info(
          () ->
              "Unable to retrieve Microsoft AppCredentials. Did you set MICROSOFT_KEY and MICROSOFT_SECRET?");
      return;
    }

    // Create the MicrosoftCredentialFactory with the given {@link AppCredentials}.
    MicrosoftCredentialFactory credentialFactory =
        new MicrosoftCredentialFactory(httpTransport, jsonFactory, appCredentials);

    Monitor monitor = context.getMonitor();

    ImmutableMap.Builder importBuilder = ImmutableMap.builder();
    importBuilder.put(
        CONTACTS,
        new MicrosoftContactsImporter(BASE_GRAPH_URL, client, mapper, transformerService));
    importBuilder.put(
        CALENDAR,
        new MicrosoftCalendarImporter(BASE_GRAPH_URL, client, mapper, transformerService));
    importBuilder.put(
        PHOTOS, new MicrosoftPhotosImporter(BASE_GRAPH_URL, client, mapper, jobStore, monitor,
          credentialFactory));
    importBuilder.put(MEDIA, new MicrosoftMediaImporter(BASE_GRAPH_URL, client, mapper, jobStore, monitor,
          credentialFactory));
    importerMap = importBuilder.build();

    ImmutableMap.Builder exporterBuilder = ImmutableMap.builder();
    exporterBuilder.put(
        CONTACTS,
        new MicrosoftContactsExporter(BASE_GRAPH_URL, client, mapper, transformerService));
    exporterBuilder.put(
        CALENDAR,
        new MicrosoftCalendarExporter(BASE_GRAPH_URL, client, mapper, transformerService));
    exporterBuilder.put(PHOTOS, new MicrosoftPhotosExporter(credentialFactory, jsonFactory, monitor));
    exporterBuilder.put(MEDIA, new MicrosoftMediaExporter(credentialFactory, jsonFactory, monitor));
    exporterBuilder.put(
        OFFLINE_DATA, new MicrosoftOfflineDataExporter(BASE_GRAPH_URL, client, mapper));

    exporterMap = exporterBuilder.build();

    initialized = true;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy