/**
   * Initializes all of the root users currently defined in the Directory Server configuration, as
   * well as the set of privileges that root users will inherit by default.
   *
   * @throws ConfigException If a configuration problem causes the identity mapper initialization
   *     process to fail.
   * @throws InitializationException If a problem occurs while initializing the identity mappers
   *     that is not related to the server configuration.
   */
  public void initializeRootDNs() throws ConfigException, InitializationException {
    // Get the root configuration object.
    ServerManagementContext managementContext = ServerManagementContext.getInstance();
    RootCfg rootConfiguration = managementContext.getRootConfiguration();

    // Get the root DN configuration object, use it to set the default root
    // privileges, and register a change listener for it.
    RootDNCfg rootDNCfg = rootConfiguration.getRootDN();
    rootPrivilegeChangeListener.setDefaultRootPrivileges(rootDNCfg);
    rootDNCfg.addChangeListener(rootPrivilegeChangeListener);

    // Register as an add and delete listener for new root DN users.
    rootDNCfg.addRootDNUserAddListener(this);
    rootDNCfg.addRootDNUserDeleteListener(this);

    // Get the set of root users defined below "cn=Root DNs,cn=config".  For
    // each one, register as a change listener, and get the set of alternate
    // bind DNs.
    for (String name : rootDNCfg.listRootDNUsers()) {
      RootDNUserCfg rootUserCfg = rootDNCfg.getRootDNUser(name);
      rootUserCfg.addChangeListener(this);
      DirectoryServer.registerRootDN(rootUserCfg.dn());

      HashSet<DN> altBindDNs = new HashSet<DN>();
      for (DN alternateBindDN : rootUserCfg.getAlternateBindDN()) {
        try {
          altBindDNs.add(alternateBindDN);
          DirectoryServer.registerAlternateRootDN(rootUserCfg.dn(), alternateBindDN);
        } catch (DirectoryException de) {
          throw new InitializationException(de.getMessageObject());
        }
      }

      alternateBindDNs.put(rootUserCfg.dn(), altBindDNs);
    }
  }
  /** Reads configuration information from the configuration files. */
  public void readConfiguration() {
    List<OpenDsException> ex = new ArrayList<OpenDsException>();
    Set<ConnectionHandlerDescriptor> ls = new HashSet<ConnectionHandlerDescriptor>();
    Set<BackendDescriptor> bs = new HashSet<BackendDescriptor>();
    Set<DN> as = new HashSet<DN>();
    try {
      DirectoryServer.getInstance().initializeConfiguration();

      if (mustReadSchema()) {
        try {
          readSchema();
          if (getSchema() != null) {
            // Update the schema: so that when we call the server code the
            // latest schema read on the server we are managing is used.
            DirectoryServer.setSchema(getSchema());
          }
        } catch (OpenDsException oe) {
          ex.add(oe);
        }
      }

      // Get the Directory Server configuration handler and use it.
      RootCfg root = ServerManagementContext.getInstance().getRootConfiguration();
      try {
        AdministrationConnectorCfg adminConnector = root.getAdministrationConnector();
        this.adminConnector = getConnectionHandler(adminConnector);
      } catch (ConfigException ce) {
        ex.add(ce);
      }
      for (String connHandler : root.listConnectionHandlers()) {
        try {
          ConnectionHandlerCfg connectionHandler = root.getConnectionHandler(connHandler);
          ls.add(getConnectionHandler(connectionHandler, connHandler));
        } catch (OpenDsException oe) {
          ex.add(oe);
        }
      }
      isSchemaEnabled = root.getGlobalConfiguration().isCheckSchema();

      for (String backendName : root.listBackends()) {
        try {
          BackendCfg backend = root.getBackend(backendName);
          Set<BaseDNDescriptor> baseDNs = new HashSet<BaseDNDescriptor>();
          for (DN dn : backend.getBaseDN()) {
            BaseDNDescriptor baseDN =
                new BaseDNDescriptor(BaseDNDescriptor.Type.NOT_REPLICATED, dn, null, -1, -1, -1);
            baseDNs.add(baseDN);
          }
          Set<IndexDescriptor> indexes = new HashSet<IndexDescriptor>();
          Set<VLVIndexDescriptor> vlvIndexes = new HashSet<VLVIndexDescriptor>();
          BackendDescriptor.Type type;
          if (backend instanceof LocalDBBackendCfg) {
            type = BackendDescriptor.Type.LOCAL_DB;
            LocalDBBackendCfg db = (LocalDBBackendCfg) backend;
            try {
              for (String indexName : db.listLocalDBIndexes()) {
                LocalDBIndexCfg index = db.getLocalDBIndex(indexName);
                indexes.add(
                    new IndexDescriptor(
                        index.getAttribute().getNameOrOID(),
                        index.getAttribute(),
                        null,
                        index.getIndexType(),
                        index.getIndexEntryLimit()));
              }
            } catch (OpenDsException oe) {
              ex.add(oe);
            }
            indexes.add(new IndexDescriptor("dn2id", null, null, new TreeSet<IndexType>(), -1));
            indexes.add(
                new IndexDescriptor("id2children", null, null, new TreeSet<IndexType>(), -1));
            indexes.add(
                new IndexDescriptor("id2subtree", null, null, new TreeSet<IndexType>(), -1));

            try {
              for (String vlvIndexName : db.listLocalDBVLVIndexes()) {
                LocalDBVLVIndexCfg index = db.getLocalDBVLVIndex(vlvIndexName);
                String s = index.getSortOrder();
                List<VLVSortOrder> sortOrder = getVLVSortOrder(s);
                vlvIndexes.add(
                    new VLVIndexDescriptor(
                        index.getName(),
                        null,
                        index.getBaseDN(),
                        index.getScope(),
                        index.getFilter(),
                        sortOrder,
                        index.getMaxBlockSize()));
              }
            } catch (OpenDsException oe) {
              ex.add(oe);
            }
          } else if (backend instanceof LDIFBackendCfg) {
            type = BackendDescriptor.Type.LDIF;
          } else if (backend instanceof MemoryBackendCfg) {
            type = BackendDescriptor.Type.MEMORY;
          } else if (backend instanceof BackupBackendCfg) {
            type = BackendDescriptor.Type.BACKUP;
          } else if (backend instanceof MonitorBackendCfg) {
            type = BackendDescriptor.Type.MONITOR;
          } else if (backend instanceof TaskBackendCfg) {
            type = BackendDescriptor.Type.TASK;
          } else {
            type = BackendDescriptor.Type.OTHER;
          }
          BackendDescriptor desc =
              new BackendDescriptor(
                  backend.getBackendId(),
                  baseDNs,
                  indexes,
                  vlvIndexes,
                  -1,
                  backend.isEnabled(),
                  type);
          for (AbstractIndexDescriptor index : indexes) {
            index.setBackend(desc);
          }
          for (AbstractIndexDescriptor index : vlvIndexes) {
            index.setBackend(desc);
          }

          bs.add(desc);
        } catch (OpenDsException oe) {
          ex.add(oe);
        }
      }

      boolean isReplicationSecure = false;
      try {
        CryptoManagerCfg cryptoManager = root.getCryptoManager();
        isReplicationSecure = cryptoManager.isSSLEncryption();
      } catch (OpenDsException oe) {
        ex.add(oe);
      }

      replicationPort = -1;
      ReplicationSynchronizationProviderCfg sync = null;
      try {
        sync =
            (ReplicationSynchronizationProviderCfg)
                root.getSynchronizationProvider("Multimaster Synchronization");
      } catch (OpenDsException oe) {
        // Ignore this one
      }
      if (sync != null) {
        try {
          if (sync.isEnabled() && sync.hasReplicationServer()) {
            ReplicationServerCfg replicationServer = sync.getReplicationServer();
            if (replicationServer != null) {
              replicationPort = replicationServer.getReplicationPort();
              ConnectionHandlerDescriptor.Protocol protocol =
                  isReplicationSecure
                      ? ConnectionHandlerDescriptor.Protocol.REPLICATION_SECURE
                      : ConnectionHandlerDescriptor.Protocol.REPLICATION;
              Set<CustomSearchResult> emptySet = Collections.emptySet();
              ConnectionHandlerDescriptor connHandler =
                  new ConnectionHandlerDescriptor(
                      new HashSet<InetAddress>(),
                      replicationPort,
                      protocol,
                      ConnectionHandlerDescriptor.State.ENABLED,
                      "Multimaster Synchronization",
                      emptySet);
              ls.add(connHandler);
            }
          }
          String[] domains = sync.listReplicationDomains();
          if (domains != null) {
            for (String domain2 : domains) {
              ReplicationDomainCfg domain = sync.getReplicationDomain(domain2);
              DN dn = domain.getBaseDN();
              for (BackendDescriptor backend : bs) {
                for (BaseDNDescriptor baseDN : backend.getBaseDns()) {
                  if (baseDN.getDn().equals(dn)) {
                    baseDN.setType(
                        sync.isEnabled()
                            ? BaseDNDescriptor.Type.REPLICATED
                            : BaseDNDescriptor.Type.DISABLED);
                    baseDN.setReplicaID(domain.getServerId());
                  }
                }
              }
            }
          }
        } catch (OpenDsException oe) {
          ex.add(oe);
        }
      }

      try {
        RootDNCfg rootDN = root.getRootDN();
        String[] rootUsers = rootDN.listRootDNUsers();
        as.clear();
        if (rootUsers != null) {
          for (String rootUser2 : rootUsers) {
            RootDNUserCfg rootUser = rootDN.getRootDNUser(rootUser2);
            as.addAll(rootUser.getAlternateBindDN());
          }
        }
      } catch (OpenDsException oe) {
        ex.add(oe);
      }
    } catch (OpenDsException oe) {
      ex.add(oe);
    } catch (final Throwable t) {
      LOG.log(Level.WARNING, "Error reading configuration: " + t, t);
      OfflineUpdateException oue =
          new OfflineUpdateException(ERR_READING_CONFIG_LDAP.get(t.getMessage().toString()), t);
      ex.add(oue);
    }

    if (ex.size() > 0) {
      if (environmentSettingException != null) {
        ex.add(0, environmentSettingException);
      }
    }

    for (OpenDsException oe : ex) {
      LOG.log(Level.WARNING, "Error reading configuration: " + oe, oe);
    }
    exceptions = Collections.unmodifiableList(ex);
    administrativeUsers = Collections.unmodifiableSet(as);
    listeners = Collections.unmodifiableSet(ls);
    backends = Collections.unmodifiableSet(bs);
  }