/**
   * Initialize this manager by calling {@link IndexProvider#initialize()} on each of the
   * currently-registered providers.
   *
   * @return the information about the portions of the repository that need to be scanned to
   *     (re)build indexes; null if no scanning is required
   */
  protected synchronized ScanningTasks initialize() {
    if (initialized.get()) {
      // nothing to do ...
      return null;
    }

    // Initialize each of the providers, removing any that are not properly initialized ...
    for (Iterator<Map.Entry<String, IndexProvider>> providerIter = providers.entrySet().iterator();
        providerIter.hasNext(); ) {
      IndexProvider provider = providerIter.next().getValue();
      try {
        doInitialize(provider);
      } catch (Throwable t) {
        if (t.getCause() != null) {
          t = t.getCause();
        }
        repository.error(
            t,
            JcrI18n.unableToInitializeIndexProvider,
            provider.getName(),
            repository.name(),
            t.getMessage());
        providerIter.remove();
      }
    }
    // Re-read the index definitions in case there were disabled index definitions that used the
    // now-available provider ...
    RepositoryIndexes indexes = readIndexDefinitions();

    // Notify the providers of all the index definitions (which we'll treat as "new" since we're
    // just starting up) ...
    ScanningTasks feedback = new ScanningTasks();
    for (Iterator<Map.Entry<String, IndexProvider>> providerIter = providers.entrySet().iterator();
        providerIter.hasNext(); ) {
      IndexProvider provider = providerIter.next().getValue();
      if (provider == null) continue;
      final String providerName = provider.getName();

      IndexChanges changes = new IndexChanges();
      for (IndexDefinition indexDefn : indexes.getIndexDefinitions().values()) {
        if (!providerName.equals(indexDefn.getProviderName())) continue;
        changes.change(indexDefn);
      }
      // Even if there are no definitions, we still want to notify each of the providers ...
      try {
        provider.notify(
            changes,
            repository.changeBus(),
            repository.nodeTypeManager(),
            repository.repositoryCache().getWorkspaceNames(),
            feedback.forProvider(providerName));
      } catch (RuntimeException e) {
        logger.error(
            e,
            JcrI18n.errorNotifyingProviderOfIndexChanges,
            providerName,
            repository.name(),
            e.getMessage());
      }
    }

    // Refresh the index writer ...
    refreshIndexWriter();
    initialized.set(true);
    return feedback;
  }