mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noël Rouvignac
07.41.2016 a128022ac288ec241c2ff37e9c9aad87c4c42d1c
Partial OPENDJ-2625 Convert all code that uses JNDI to use the SDK instead

Converted a lot of code from dsreplication to use the SDK
3 files modified
1095 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/admin/ads/ADSContext.java 948 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/admin/ads/ADSContextHelper.java 124 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java 23 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/admin/ads/ADSContext.java
@@ -16,10 +16,16 @@
 */
package org.opends.admin.ads;
import static org.forgerock.opendj.ldap.ModificationType.*;
import static org.forgerock.opendj.ldap.SearchScope.*;
import static org.forgerock.opendj.ldap.requests.Requests.*;
import static org.forgerock.util.Utils.*;
import static org.opends.messages.QuickSetupMessages.*;
import static org.opends.server.schema.SchemaConstants.*;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -29,33 +35,35 @@
import java.util.SortedSet;
import java.util.TreeSet;
import javax.naming.CompositeName;
import javax.naming.InvalidNameException;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NoPermissionException;
import javax.naming.NotContextException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.AuthorizationException;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.EntryNotFoundException;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.LinkedAttribute;
import org.forgerock.opendj.ldap.Modification;
import org.forgerock.opendj.ldap.ModificationType;
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.requests.AddRequest;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.opends.admin.ads.ADSContextException.ErrorType;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.quicksetup.Constants;
import org.opends.server.schema.SchemaConstants;
import org.opends.server.types.HostPort;
/** Class used to update and read the contents of the Administration Data. */
@@ -288,16 +296,6 @@
  }
  /**
   * Returns the DirContext used to retrieve information by this ADSContext.
   *
   * @return the DirContext used to retrieve information by this ADSContext.
   */
  public InitialLdapContext getDirContext()
  {
    return connectionWrapper.getLdapContext();
  }
  /**
   * Returns the connection used to retrieve information by this ADSContext.
   *
   * @return the connection
@@ -327,17 +325,28 @@
   */
  public void registerServer(Map<ServerProperty, Object> serverProperties) throws ADSContextException
  {
    LdapName dn = makeDNFromServerProperties(serverProperties);
    BasicAttributes attrs = makeAttrsFromServerProperties(serverProperties, true);
    String dn = makeDNFromServerProperties(serverProperties);
    AddRequest request = newAddRequest(dn);
    for (ServerProperty prop : serverProperties.keySet())
    {
      Attribute attribute = makeAttrFromServerProperty(prop, serverProperties.get(prop));
      if (attribute != null)
      {
        request.addAttribute(attribute);
      }
    }
    // TODO: use another structural objectclass
    request.addAttribute("objectclass", "top", "ds-cfg-branch", "extensibleobject");
    try
    {
      // This check is required because by default the server container entry
      // does not exist.
      if (!isExistingEntry(nameFromDN(getServerContainerDN())))
      if (!isExistingEntry(getServerContainerDN()))
      {
        createContainerEntry(getServerContainerDN());
      }
      connectionWrapper.getLdapContext().createSubcontext(dn, attrs).close();
      throwIfNotSuccess(connectionWrapper.getConnection().add(request));
      if (serverProperties.containsKey(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE))
      {
        registerInstanceKeyCertificate(serverProperties, dn);
@@ -375,12 +384,12 @@
    {
      throw ace;
    }
    catch (NameAlreadyBoundException x)
    catch (LdapException x)
    {
      if (x.getResult().getResultCode().equals(ResultCode.ENTRY_ALREADY_EXISTS))
    {
      throw new ADSContextException(ErrorType.ALREADY_REGISTERED);
    }
    catch (Exception x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
  }
@@ -398,7 +407,7 @@
  private void updateServer(Map<ServerProperty, Object> serverProperties, String newServerId)
      throws ADSContextException
  {
    LdapName dn = makeDNFromServerProperties(serverProperties);
    String dn = makeDNFromServerProperties(serverProperties);
    try
    {
@@ -406,13 +415,23 @@
      {
        Map<ServerProperty, Object> newServerProps = new HashMap<>(serverProperties);
        newServerProps.put(ServerProperty.ID, newServerId);
        LdapName newDn = makeDNFromServerProperties(newServerProps);
        connectionWrapper.getLdapContext().rename(dn, newDn);
        String newDn = makeDNFromServerProperties(newServerProps);
        throwIfNotSuccess(connectionWrapper.getConnection().modifyDN(dn, newDn));
        dn = newDn;
        serverProperties.put(ServerProperty.ID, newServerId);
      }
      BasicAttributes attrs = makeAttrsFromServerProperties(serverProperties, false);
      connectionWrapper.getLdapContext().modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, attrs);
      ModifyRequest request = newModifyRequest(dn);
      for (ServerProperty prop : serverProperties.keySet())
      {
        Attribute attr = makeAttrFromServerProperty(prop, serverProperties.get(prop));
        if (attr != null)
        {
          request.addModification(new Modification(REPLACE, attr));
        }
      }
      throwIfNotSuccess(connectionWrapper.getConnection().modify(request));
      if (serverProperties.containsKey(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE))
      {
        registerInstanceKeyCertificate(serverProperties, dn);
@@ -422,7 +441,7 @@
    {
      throw ace;
    }
    catch (NameNotFoundException x)
    catch (EntryNotFoundException x)
    {
      throw new ADSContextException(ErrorType.NOT_YET_REGISTERED);
    }
@@ -444,7 +463,8 @@
   */
  public void unregisterServer(Map<ServerProperty, Object> serverProperties) throws ADSContextException
  {
    LdapName dn = makeDNFromServerProperties(serverProperties);
    String dn = makeDNFromServerProperties(serverProperties);
    Connection conn = connectionWrapper.getConnection();
    try
    {
      // Unregister the server from the server groups.
@@ -462,96 +482,63 @@
        }
      }
      connectionWrapper.getLdapContext().destroySubcontext(dn);
      throwIfNotSuccess(conn.delete(dn));
    }
    catch (NameNotFoundException x)
    catch (EntryNotFoundException x)
    {
      throw new ADSContextException(ErrorType.NOT_YET_REGISTERED);
    }
    catch (NamingException x)
    catch (LdapException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    // Unregister the server in server groups
    NamingEnumeration<SearchResult> ne = null;
    try
    {
      SearchControls sc = new SearchControls();
      String serverID = getServerID(serverProperties);
      if (serverID != null)
      {
      // Unregister the server in server groups
        String memberAttrName = ServerGroupProperty.MEMBERS.getAttributeName();
        String filter = "(" + memberAttrName + "=cn=" + serverID + ")";
        sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
        ne = connectionWrapper.getLdapContext().search(getServerGroupContainerDN(), filter, sc);
        while (ne.hasMore())
      SearchRequest request = newSearchRequest(getServerGroupContainerDN(), SINGLE_LEVEL, filter);
      try (ConnectionEntryReader entryReader = conn.search(request);)
        {
          SearchResult sr = ne.next();
          String groupDn = sr.getNameInNamespace();
          BasicAttribute newAttr = new BasicAttribute(memberAttrName);
          NamingEnumeration<? extends Attribute> attrs = sr.getAttributes().getAll();
          try
        while (entryReader.hasNext())
          {
            while (attrs.hasMore())
          SearchResultEntry sr = entryReader.readEntry();
          DN groupDn = sr.getName();
          Attribute newAttr = new LinkedAttribute(memberAttrName);
          for (Attribute attr : sr.getAllAttributes())
            {
              Attribute attr = attrs.next();
              String attrID = attr.getID();
              if (attrID.equalsIgnoreCase(memberAttrName))
            AttributeType attrType = attr.getAttributeDescription().getAttributeType();
            if (attrType.hasName(memberAttrName))
              {
                NamingEnumeration<?> ae = attr.getAll();
                try
              for (ByteString value : attr)
                {
                  while (ae.hasMore())
                  {
                    String value = (String) ae.next();
                    if (!value.equalsIgnoreCase("cn=" + serverID))
                if (!value.toString().equalsIgnoreCase("cn=" + serverID))
                    {
                      newAttr.add(value);
                    }
                  }
                }
                finally
                {
                  handleCloseNamingEnumeration(ae);
          }
          ModificationType modType = newAttr.size() > 0 ? REPLACE : DELETE;
          ModifyRequest modRequest = newModifyRequest(groupDn)
              .addModification(new Modification(modType, newAttr));
          throwIfNotSuccess(conn.modify(modRequest));
                }
              }
            }
          }
          finally
          {
            handleCloseNamingEnumeration(attrs);
          }
          BasicAttributes newAttrs = new BasicAttributes();
          newAttrs.put(newAttr);
          if (newAttr.size() > 0)
          {
            connectionWrapper.getLdapContext().modifyAttributes(groupDn, DirContext.REPLACE_ATTRIBUTE, newAttrs);
          }
          else
          {
            connectionWrapper.getLdapContext().modifyAttributes(groupDn, DirContext.REMOVE_ATTRIBUTE, newAttrs);
          }
        }
      }
    }
    catch (NameNotFoundException x)
      catch (EntryNotFoundException x)
    {
      throw new ADSContextException(ErrorType.BROKEN_INSTALL);
    }
    catch (NoPermissionException x)
      catch (AuthorizationException x)
    {
      throw new ADSContextException(ErrorType.ACCESS_PERMISSION);
    }
    catch (NamingException x)
      catch (IOException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    finally
    {
      handleCloseNamingEnumeration(ne);
    }
  }
@@ -582,7 +569,7 @@
   */
  private boolean isAdministratorAlreadyRegistered(String uid) throws ADSContextException
  {
    return isExistingEntry(makeDNFromAdministratorProperties(uid));
    return isExistingEntry(getAdministratorDN(uid));
  }
  /**
@@ -627,67 +614,48 @@
   */
  private Set<String> getServerGroupMemberList(String serverGroupId) throws ADSContextException
  {
    LdapName dn = nameFromDN("cn=" + Rdn.escapeValue(serverGroupId) + "," + getServerGroupContainerDN());
    String dn = "cn=" + Rdn.escapeValue(serverGroupId) + "," + getServerGroupContainerDN();
    Set<String> result = new HashSet<>();
    NamingEnumeration<SearchResult> srs = null;
    NamingEnumeration<? extends Attribute> ne = null;
    try
    SearchRequest request = newSearchRequest(dn, BASE_OBJECT, "(objectclass=*)");
    try (ConnectionEntryReader entryReader = getConnection().getConnection().search(request))
    {
      SearchControls sc = new SearchControls();
      sc.setSearchScope(SearchControls.OBJECT_SCOPE);
      srs = getDirContext().search(dn, "(objectclass=*)", sc);
      if (!srs.hasMore())
      Set<String> result = new HashSet<>();
      if (!entryReader.hasNext())
      {
        return result;
      }
      Attributes attrs = srs.next().getAttributes();
      ne = attrs.getAll();
      while (ne.hasMore())
      for (Attribute attr : entryReader.readEntry().getAllAttributes())
      {
        Attribute attr = ne.next();
        String attrID = attr.getID();
        if (!attrID.toLowerCase().equals(ServerGroupProperty.MEMBERS.getAttributeName().toLowerCase()))
        AttributeType attrType = attr.getAttributeDescription().getAttributeType();
        if (attrType.hasName(ServerGroupProperty.MEMBERS.getAttributeName()))
        {
          continue;
        }
        // We have the members list
        NamingEnumeration<?> ae = attr.getAll();
        try
        {
          while (ae.hasMore())
          {
            result.add((String) ae.next());
          }
        }
        finally
        {
          handleCloseNamingEnumeration(ae);
        }
          toStrings(result, attr);
        break;
      }
    }
    catch (NameNotFoundException x)
    {
      result = new HashSet<>();
      return result;
    }
    catch (NoPermissionException x)
    catch (EntryNotFoundException x)
    {
      return new HashSet<>();
    }
    catch (AuthorizationException x)
    {
      throw new ADSContextException(ErrorType.ACCESS_PERMISSION);
    }
    catch (NamingException x)
    catch (IOException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    finally
    {
      handleCloseNamingEnumeration(srs);
      handleCloseNamingEnumeration(ne);
    }
    return result;
  private void toStrings(Set<String> result, Attribute attr)
  {
    for (ByteString value : attr)
    {
      result.add(value.toString());
    }
  }
  /**
@@ -700,36 +668,28 @@
  public Set<Map<ServerProperty, Object>> readServerRegistry() throws ADSContextException
  {
    Set<Map<ServerProperty, Object>> result = new HashSet<>();
    NamingEnumeration<SearchResult> ne = null;
    try
    {
      SearchControls sc = new SearchControls();
      sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
      ne = connectionWrapper.getLdapContext().search(getServerContainerDN(), "(objectclass=*)", sc);
      while (ne.hasMore())
    SearchRequest request = newSearchRequest(getServerContainerDN(), SINGLE_LEVEL, "(objectclass=*)");
    try (ConnectionEntryReader entryReader = connectionWrapper.getConnection().search(request))
      {
        SearchResult sr = ne.next();
        Map<ServerProperty, Object> properties = makePropertiesFromServerAttrs(sr.getAttributes());
      while (entryReader.hasNext())
      {
        SearchResultEntry sr = entryReader.readEntry();
        Map<ServerProperty, Object> properties = makePropertiesFromServerAttrs(sr);
        Object keyId = properties.get(ServerProperty.INSTANCE_KEY_ID);
        if (keyId != null)
        {
          NamingEnumeration<SearchResult> ne2 = null;
          try
          SearchRequest request2 = newSearchRequest(
              getInstanceKeysContainerDN(), SINGLE_LEVEL, "(ds-cfg-key-id=" + keyId + ")",
              "ds-cfg-public-key-certificate;binary");
          try (ConnectionEntryReader entryReader2 = connectionWrapper.getConnection().search(request2))
          {
            SearchControls sc1 = new SearchControls();
            sc1.setSearchScope(SearchControls.ONELEVEL_SCOPE);
            final String attrIDs[] = { "ds-cfg-public-key-certificate;binary" };
            sc1.setReturningAttributes(attrIDs);
            ne2 = connectionWrapper.getLdapContext().search(
                getInstanceKeysContainerDN(), "(ds-cfg-key-id=" + keyId + ")", sc);
            boolean found = false;
            while (ne2.hasMore())
            while (entryReader2.hasNext())
            {
              SearchResult certEntry = ne2.next();
              Attribute certAttr = certEntry.getAttributes().get(attrIDs[0]);
              properties.put(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE, certAttr.get());
              SearchResultEntry certEntry = entryReader2.readEntry();
              Attribute certAttr = certEntry.getAttribute("ds-cfg-public-key-certificate;binary");
              properties.put(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE, certAttr.firstValue().toByteArray());
              found = true;
            }
            if (!found)
@@ -737,36 +697,27 @@
              logger.warn(LocalizableMessage.raw("Could not find public key for " + properties));
            }
          }
          catch (NameNotFoundException x)
          catch (EntryNotFoundException x)
          {
            logger.warn(LocalizableMessage.raw("Could not find public key for " + properties));
          }
          finally
          {
            handleCloseNamingEnumeration(ne2);
          }
        }
        result.add(properties);
      }
      return result;
    }
    catch (NameNotFoundException x)
    catch (EntryNotFoundException x)
    {
      throw new ADSContextException(ErrorType.BROKEN_INSTALL);
    }
    catch (NoPermissionException x)
    catch (AuthorizationException x)
    {
      throw new ADSContextException(ErrorType.ACCESS_PERMISSION);
    }
    catch (NamingException x)
    catch (IOException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    finally
    {
      handleCloseNamingEnumeration(ne);
    }
    return result;
  }
  /**
@@ -779,24 +730,24 @@
   */
  private void createServerGroup(Map<ServerGroupProperty, Object> serverGroupProperties) throws ADSContextException
  {
    LdapName dn = makeDNFromServerGroupProperties(serverGroupProperties);
    BasicAttributes attrs = makeAttrsFromServerGroupProperties(serverGroupProperties);
    // Add the objectclass attribute value
    Attribute oc = new BasicAttribute("objectclass");
    oc.add("top");
    oc.add("groupOfUniqueNames");
    attrs.put(oc);
    String dn = makeDNFromServerGroupProperties(serverGroupProperties);
    AddRequest request = newAddRequest(dn)
        .addAttribute("objectclass", "top", "groupOfUniqueNames");
    for (ServerGroupProperty prop : serverGroupProperties.keySet())
    {
      request.addAttribute(makeAttrFromServerGroupProperty(prop, serverGroupProperties.get(prop)));
    }
    try
    {
      DirContext ctx = connectionWrapper.getLdapContext().createSubcontext(dn, attrs);
      ctx.close();
      throwIfNotSuccess(connectionWrapper.getConnection().add(request));
    }
    catch (NameAlreadyBoundException x)
    catch (LdapException x)
    {
      if (x.getResult().getResultCode().equals(ResultCode.ENTRY_ALREADY_EXISTS))
    {
      throw new ADSContextException(ErrorType.ALREADY_REGISTERED);
    }
    catch (NamingException x)
    {
      throw new ADSContextException(ErrorType.BROKEN_INSTALL, x);
    }
  }
@@ -814,7 +765,7 @@
  private void updateServerGroup(String groupID, Map<ServerGroupProperty, Object> serverGroupProperties)
      throws ADSContextException
  {
    LdapName dn = nameFromDN("cn=" + Rdn.escapeValue(groupID) + "," + getServerGroupContainerDN());
    String dn = "cn=" + Rdn.escapeValue(groupID) + "," + getServerGroupContainerDN();
    try
    {
      // Entry renaming ?
@@ -824,8 +775,8 @@
        if (!newGroupId.equals(groupID))
        {
          // Rename to entry
          LdapName newDN = nameFromDN("cn=" + Rdn.escapeValue(newGroupId) + "," + getServerGroupContainerDN());
          connectionWrapper.getLdapContext().rename(dn, newDN);
          String newDN = ("cn=" + Rdn.escapeValue(newGroupId) + "," + getServerGroupContainerDN());
          throwIfNotSuccess(connectionWrapper.getConnection().modifyDN(dn, newDN));
          dn = newDN;
        }
@@ -837,20 +788,25 @@
        return;
      }
      BasicAttributes attrs = makeAttrsFromServerGroupProperties(serverGroupProperties);
      // attribute modification
      connectionWrapper.getLdapContext().modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, attrs);
      // Transform 'properties' into 'attributes'
      ModifyRequest request = newModifyRequest(dn);
      for (ServerGroupProperty prop : serverGroupProperties.keySet())
      {
        request.addModification(new Modification(
            REPLACE, makeAttrFromServerGroupProperty(prop, serverGroupProperties.get(prop))));
    }
    catch (NameNotFoundException x)
      throwIfNotSuccess(connectionWrapper.getConnection().modify(request));
    }
    catch (EntryNotFoundException x)
    {
      throw new ADSContextException(ErrorType.NOT_YET_REGISTERED);
    }
    catch (NameAlreadyBoundException x)
    catch (LdapException x)
    {
      if (x.getResult().getResultCode().equals(ResultCode.ENTRY_ALREADY_EXISTS))
    {
      throw new ADSContextException(ErrorType.ALREADY_REGISTERED);
    }
    catch (NamingException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
  }
@@ -864,36 +820,29 @@
   */
  private Set<Map<ServerGroupProperty, Object>> readServerGroupRegistry() throws ADSContextException
  {
    SearchRequest request = newSearchRequest(getServerGroupContainerDN(), SINGLE_LEVEL, "(objectclass=*)");
    try (ConnectionEntryReader entryReader = connectionWrapper.getConnection().search(request))
    {
    Set<Map<ServerGroupProperty, Object>> result = new HashSet<>();
    NamingEnumeration<SearchResult> ne = null;
    try
      while (entryReader.hasNext())
    {
      SearchControls sc = new SearchControls();
      sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
      ne = connectionWrapper.getLdapContext().search(getServerGroupContainerDN(), "(objectclass=*)", sc);
      while (ne.hasMore())
      {
        SearchResult sr = ne.next();
        result.add(makePropertiesFromServerGroupAttrs(sr.getAttributes()));
        SearchResultEntry sr = entryReader.readEntry();
        result.add(makePropertiesFromServerGroupAttrs(sr));
      }
      return result;
    }
    catch (NameNotFoundException x)
    catch (EntryNotFoundException x)
    {
      throw new ADSContextException(ErrorType.BROKEN_INSTALL);
    }
    catch (NoPermissionException x)
    catch (AuthorizationException x)
    {
      throw new ADSContextException(ErrorType.ACCESS_PERMISSION);
    }
    catch (NamingException x)
    catch (IOException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    finally
    {
      handleCloseNamingEnumeration(ne);
    }
    return result;
  }
  /**
@@ -906,36 +855,29 @@
  public Set<Map<AdministratorProperty, Object>> readAdministratorRegistry() throws ADSContextException
  {
    Set<Map<AdministratorProperty, Object>> result = new HashSet<>();
    NamingEnumeration<SearchResult> ne = null;
    try
    SearchRequest request = newSearchRequest(
        getAdministratorContainerDN(), SINGLE_LEVEL, "(objectclass=*)",
        "cn", "userpassword", "ds-privilege-name", "description");
    try (ConnectionEntryReader entryReader = connectionWrapper.getConnection().search(request))
    {
      SearchControls sc = new SearchControls();
      sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
      String[] attList = { "cn", "userpassword", "ds-privilege-name", "description" };
      sc.setReturningAttributes(attList);
      ne = connectionWrapper.getLdapContext().search(getAdministratorContainerDN(), "(objectclass=*)", sc);
      while (ne.hasMore())
      while (entryReader.hasNext())
      {
        SearchResult sr = ne.next();
        result.add(makePropertiesFromAdministratorAttrs(getRdn(sr.getName()), sr.getAttributes()));
        SearchResultEntry sr = entryReader.readEntry();
        result.add(makePropertiesFromAdministratorAttrs(sr.getName().rdn(), sr.getAllAttributes()));
      }
    }
    catch (NameNotFoundException x)
    catch (EntryNotFoundException x)
    {
      throw new ADSContextException(ErrorType.BROKEN_INSTALL);
    }
    catch (NoPermissionException x)
    catch (AuthorizationException x)
    {
      throw new ADSContextException(ErrorType.ACCESS_PERMISSION);
    }
    catch (NamingException x)
    catch (IOException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    finally
    {
      handleCloseNamingEnumeration(ne);
    }
    return result;
  }
@@ -962,25 +904,25 @@
  private void createAdminDataContainers() throws ADSContextException
  {
    // Create the DIT below the administration suffix
    if (!isExistingEntry(nameFromDN(getAdministrationSuffixDN())))
    if (!isExistingEntry(getAdministrationSuffixDN()))
    {
      createTopContainerEntry();
    }
    if (!isExistingEntry(nameFromDN(getAdministratorContainerDN())))
    if (!isExistingEntry(getAdministratorContainerDN()))
    {
      createAdministratorContainerEntry();
    }
    if (!isExistingEntry(nameFromDN(getServerContainerDN())))
    if (!isExistingEntry(getServerContainerDN()))
    {
      createContainerEntry(getServerContainerDN());
    }
    if (!isExistingEntry(nameFromDN(getServerGroupContainerDN())))
    if (!isExistingEntry(getServerGroupContainerDN()))
    {
      createContainerEntry(getServerGroupContainerDN());
    }
    // Add the default "all-servers" group
    if (!isExistingEntry(nameFromDN(getAllServerGroupDN())))
    if (!isExistingEntry((getAllServerGroupDN())))
    {
      Map<ServerGroupProperty, Object> allServersGroupsMap = new HashMap<>();
      allServersGroupsMap.put(ServerGroupProperty.UID, ALL_SERVERGROUP_NAME);
@@ -988,13 +930,13 @@
    }
    // Create the CryptoManager instance key DIT below the administration suffix
    if (!isExistingEntry(nameFromDN(getInstanceKeysContainerDN())))
    if (!isExistingEntry(getInstanceKeysContainerDN()))
    {
      createContainerEntry(getInstanceKeysContainerDN());
    }
    // Create the CryptoManager secret key DIT below the administration suffix
    if (!isExistingEntry(nameFromDN(getSecretKeysContainerDN())))
    if (!isExistingEntry(getSecretKeysContainerDN()))
    {
      createContainerEntry(getSecretKeysContainerDN());
    }
@@ -1025,8 +967,7 @@
        {
          if (dn != null)
          {
            LdapName ldapName = nameFromDN(dn);
            if (isExistingEntry(ldapName))
            if (isExistingEntry(dn))
            {
              tmpContext.destroySubcontext(dn);
            }
@@ -1069,7 +1010,7 @@
    boolean hasAdminData = true;
    for (int i = 0; i < dns.length && hasAdminData; i++)
    {
      hasAdminData = isExistingEntry(nameFromDN(dns[i]));
      hasAdminData = isExistingEntry(dns[i]);
    }
    return hasAdminData;
  }
@@ -1096,24 +1037,23 @@
   */
  public void createAdministrator(Map<AdministratorProperty, Object> adminProperties) throws ADSContextException
  {
    LdapName dnCentralAdmin = makeDNFromAdministratorProperties(adminProperties);
    BasicAttributes attrs = makeAttrsFromAdministratorProperties(adminProperties, true, null);
    AddRequest request = newAddRequest(getAdministratorDN(getAdministratorUID(adminProperties)));
    addAttrsFromAdministratorProperties(request, adminProperties, true);
    try
    {
      DirContext ctx = connectionWrapper.getLdapContext().createSubcontext(dnCentralAdmin, attrs);
      ctx.close();
      throwIfNotSuccess(connectionWrapper.getConnection().add(request));
    }
    catch (NameAlreadyBoundException x)
    {
      throw new ADSContextException(ErrorType.ALREADY_REGISTERED);
    }
    catch (NoPermissionException x)
    catch (AuthorizationException x)
    {
      throw new ADSContextException(ErrorType.ACCESS_PERMISSION);
    }
    catch (NamingException x)
    catch (LdapException x)
    {
      if (x.getResult().getResultCode().equals(ResultCode.ENTRY_ALREADY_EXISTS))
      {
        throw new ADSContextException(ErrorType.ALREADY_REGISTERED);
      }
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
  }
@@ -1128,21 +1068,20 @@
   */
  public void deleteAdministrator(Map<AdministratorProperty, Object> adminProperties) throws ADSContextException
  {
    LdapName dnCentralAdmin = makeDNFromAdministratorProperties(adminProperties);
    String dnCentralAdmin = getAdministratorDN(getAdministratorUID(adminProperties));
    try
    {
      connectionWrapper.getLdapContext().destroySubcontext(dnCentralAdmin);
      throwIfNotSuccess(connectionWrapper.getConnection().delete(dnCentralAdmin));
    }
    catch (NameNotFoundException | NotContextException x)
    catch (EntryNotFoundException x)
    {
      throw new ADSContextException(ErrorType.NOT_YET_REGISTERED);
    }
    catch (NoPermissionException x)
    catch (AuthorizationException x)
    {
      throw new ADSContextException(ErrorType.ACCESS_PERMISSION);
    }
    catch (NamingException x)
    catch (LdapException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
@@ -1171,9 +1110,9 @@
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private static LdapName makeDNFromHostnameAndPath(String hostname, String ipath) throws ADSContextException
  private static String makeDNFromHostnameAndPath(String hostname, String ipath) throws ADSContextException
  {
    return nameFromDN("cn=" + Rdn.escapeValue(hostname + "@" + ipath) + "," + getServerContainerDN());
    return "cn=" + Rdn.escapeValue(hostname + "@" + ipath) + "," + getServerContainerDN();
  }
  /**
@@ -1187,9 +1126,9 @@
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private static LdapName makeDNFromServerUniqueId(String serverUniqueId) throws ADSContextException
  private static String makeDNFromServerUniqueId(String serverUniqueId) throws ADSContextException
  {
    return nameFromDN("cn=" + Rdn.escapeValue(serverUniqueId) + "," + getServerContainerDN());
    return "cn=" + Rdn.escapeValue(serverUniqueId) + "," + getServerContainerDN();
  }
  /**
@@ -1203,7 +1142,7 @@
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private static LdapName makeDNFromServerGroupProperties(Map<ServerGroupProperty, Object> serverGroupProperties)
  private static String makeDNFromServerGroupProperties(Map<ServerGroupProperty, Object> serverGroupProperties)
      throws ADSContextException
  {
    String serverGroupId = (String) serverGroupProperties.get(ServerGroupProperty.UID);
@@ -1211,7 +1150,7 @@
    {
      throw new ADSContextException(ErrorType.MISSING_NAME);
    }
    return nameFromDN("cn=" + Rdn.escapeValue(serverGroupId) + "," + getServerGroupContainerDN());
    return "cn=" + Rdn.escapeValue(serverGroupId) + "," + getServerGroupContainerDN();
  }
  /**
@@ -1225,7 +1164,7 @@
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private static LdapName makeDNFromServerProperties(Map<ServerProperty, Object> serverProperties)
  private static String makeDNFromServerProperties(Map<ServerProperty, Object> serverProperties)
      throws ADSContextException
  {
    String serverID = getServerID(serverProperties);
@@ -1248,108 +1187,51 @@
  }
  /**
   * This method returns the DN of the entry that corresponds to the given
   * administrator properties.
   *
   * @param adminProperties
   *          the administrator properties.
   * @return the DN of the entry that corresponds to the given administrator
   *         properties.
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private static LdapName makeDNFromAdministratorProperties(Map<AdministratorProperty, Object> adminProperties)
      throws ADSContextException
  {
    return makeDNFromAdministratorProperties(getAdministratorUID(adminProperties));
  }
  /**
   * This method returns the DN of the entry that corresponds to the given
   * administrator properties.
   *
   * @param adminUid
   *          the administrator uid.
   * @return the DN of the entry that corresponds to the given administrator
   *         properties.
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private static LdapName makeDNFromAdministratorProperties(String adminUid) throws ADSContextException
  {
    return nameFromDN(getAdministratorDN(adminUid));
  }
  /**
   * Returns the attributes for some administrator properties.
   * Enrich the provided add request with the attributes for some administrator properties.
   *
   * @param adminProperties
   *          the administrator properties.
   * @param passwordRequired
   *          Indicates if the properties should include the password.
   * @param currentPrivileges
   *          The current privilege list or null.
   * @return the attributes for the given administrator properties.
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private static BasicAttributes makeAttrsFromAdministratorProperties(
      Map<AdministratorProperty, Object> adminProperties, boolean passwordRequired,
      NamingEnumeration<?> currentPrivileges) throws ADSContextException
  private static void addAttrsFromAdministratorProperties(AddRequest request,
      Map<AdministratorProperty, Object> adminProperties, boolean passwordRequired) throws ADSContextException
  {
    BasicAttributes attrs = new BasicAttributes();
    Attribute oc = new BasicAttribute("objectclass");
    if (passwordRequired)
    {
      attrs.put("userPassword", getAdministratorPassword(adminProperties));
      request.addAttribute("userPassword", getAdministratorPassword(adminProperties));
    }
    oc.add("top");
    oc.add("person");
    attrs.put(oc);
    attrs.put("sn", GLOBAL_ADMIN_UID);
    request.addAttribute("objectclass", "top", "person");
    request.addAttribute("sn", GLOBAL_ADMIN_UID);
    if (adminProperties.containsKey(AdministratorProperty.DESCRIPTION))
    {
      attrs.put("description", adminProperties.get(AdministratorProperty.DESCRIPTION));
      request.addAttribute("description", adminProperties.get(AdministratorProperty.DESCRIPTION));
    }
    Attribute privilegeAtt;
    if (adminProperties.containsKey(AdministratorProperty.PRIVILEGE))
    {
      // We assume that privilege strings provided in
      // AdministratorProperty.PRIVILEGE
      // are valid privileges represented as a LinkedList of string.
      privilegeAtt = new BasicAttribute("ds-privilege-name");
      if (currentPrivileges != null)
      {
        while (currentPrivileges.hasMoreElements())
        {
          privilegeAtt.add(currentPrivileges.nextElement().toString());
        }
      }
      LinkedList<?> privileges = (LinkedList<?>) adminProperties.get(AdministratorProperty.PRIVILEGE);
      for (Object o : privileges)
      {
        String p = o.toString();
        if (p.startsWith("-"))
        {
          privilegeAtt.remove(p.substring(1));
          request.removeAttribute("ds-privilege-name", p.substring(1));
        }
        else
        {
          privilegeAtt.add(p);
          request.addAttribute("ds-privilege-name", p);
        }
      }
    }
    else
    {
      privilegeAtt = addRootPrivileges();
      request.addAttribute(addRootPrivileges());
    }
    attrs.put(privilegeAtt);
    // Add the RootDNs Password policy so the password do not expire.
    attrs.put("ds-pwp-password-policy-dn", "cn=Root Password Policy,cn=Password Policies,cn=config");
    return attrs;
    request.addAttribute("ds-pwp-password-policy-dn", "cn=Root Password Policy,cn=Password Policies,cn=config");
  }
  /**
@@ -1359,7 +1241,7 @@
   */
  private static Attribute addRootPrivileges()
  {
    Attribute privilege = new BasicAttribute("ds-privilege-name");
    Attribute privilege = new LinkedAttribute("ds-privilege-name");
    privilege.add("bypass-acl");
    privilege.add("modify-acl");
    privilege.add("config-read");
@@ -1382,42 +1264,6 @@
  }
  /**
   * Returns the attributes for some server properties.
   *
   * @param serverProperties
   *          the server properties.
   * @param addObjectClass
   *          Indicates if the object class has to be added.
   * @return the attributes for the given server properties.
   */
  private static BasicAttributes makeAttrsFromServerProperties(Map<ServerProperty, Object> serverProperties,
      boolean addObjectClass)
  {
    BasicAttributes result = new BasicAttributes();
    // Transform 'properties' into 'attributes'
    for (ServerProperty prop : serverProperties.keySet())
    {
      Attribute attr = makeAttrFromServerProperty(prop, serverProperties.get(prop));
      if (attr != null)
      {
        result.put(attr);
      }
    }
    if (addObjectClass)
    {
      // Add the objectclass attribute value
      // TODO: use another structural objectclass
      Attribute oc = new BasicAttribute("objectclass");
      oc.add("top");
      oc.add("ds-cfg-branch");
      oc.add("extensibleobject");
      result.put(oc);
    }
    return result;
  }
  /**
   * Returns the attribute for a given server property.
   *
   * @param property
@@ -1428,48 +1274,16 @@
   */
  private static Attribute makeAttrFromServerProperty(ServerProperty property, Object value)
  {
    Attribute result;
    switch (property)
    {
    case INSTANCE_PUBLIC_KEY_CERTIFICATE:
      result = null; // used in separate instance key entry
      break;
      // used in separate instance key entry
      return null;
    case GROUPS:
      result = new BasicAttribute(ServerProperty.GROUPS.getAttributeName());
      for (Object o : ((Set<?>) value))
      {
        result.add(o);
      }
      break;
      return new LinkedAttribute(ServerProperty.GROUPS.getAttributeName(), ((Collection<?>) value));
    default:
      result = new BasicAttribute(property.getAttributeName(), value);
      return new LinkedAttribute(property.getAttributeName(), value);
    }
    return result;
  }
  /**
   * Returns the attributes for some server group properties.
   *
   * @param serverGroupProperties
   *          the server group properties.
   * @return the attributes for the given server group properties.
   */
  private static BasicAttributes makeAttrsFromServerGroupProperties(
      Map<ServerGroupProperty, Object> serverGroupProperties)
  {
    BasicAttributes result = new BasicAttributes();
    // Transform 'properties' into 'attributes'
    for (ServerGroupProperty prop : serverGroupProperties.keySet())
    {
      Attribute attr = makeAttrFromServerGroupProperty(prop, serverGroupProperties.get(prop));
      if (attr != null)
      {
        result.put(attr);
      }
    }
    return result;
  }
  /**
@@ -1486,35 +1300,28 @@
    switch (property)
    {
    case MEMBERS:
      Attribute result = new BasicAttribute(ServerGroupProperty.MEMBERS.getAttributeName());
      for (Object o : ((Set<?>) value))
      {
        result.add(o);
      }
      return result;
      return new LinkedAttribute(ServerGroupProperty.MEMBERS.getAttributeName(), (Collection<?>) value);
    default:
      return new BasicAttribute(property.getAttributeName(), value);
      return new LinkedAttribute(property.getAttributeName(), value);
    }
  }
  /**
   * Returns the properties of a server group for some LDAP attributes.
   *
   * @param attrs
   *          the LDAP attributes.
   * @param entry
   *          the LDAP entry.
   * @return the properties of a server group for some LDAP attributes.
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private Map<ServerGroupProperty, Object> makePropertiesFromServerGroupAttrs(Attributes attrs)
  private Map<ServerGroupProperty, Object> makePropertiesFromServerGroupAttrs(SearchResultEntry entry)
      throws ADSContextException
  {
    Map<ServerGroupProperty, Object> result = new HashMap<>();
    try
    {
      for (ServerGroupProperty prop : ServerGroupProperty.values())
      {
        Attribute attr = attrs.get(prop.getAttributeName());
      Attribute attr = entry.getAttribute(prop.getAttributeName());
        if (attr == null)
        {
          continue;
@@ -1524,67 +1331,42 @@
        if (attr.size() >= 1 && MULTIVALUED_SERVER_GROUP_PROPERTIES.contains(prop))
        {
          Set<String> set = new HashSet<>();
          NamingEnumeration<?> ae = attr.getAll();
          try
          {
            while (ae.hasMore())
            {
              set.add((String) ae.next());
            }
          }
          finally
          {
            ae.close();
          }
        toStrings(set, attr);
          value = set;
        }
        else
        {
          value = attr.get(0);
        value = attr.firstValueAsString();
        }
        result.put(prop, value);
      }
    }
    catch (NamingException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    return result;
  }
  /**
   * Returns the properties of a server for some LDAP attributes.
   *
   * @param attrs
   *          the LDAP attributes.
   * @param entry
   *          the entry.
   * @return the properties of a server for some LDAP attributes.
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private Map<ServerProperty, Object> makePropertiesFromServerAttrs(Attributes attrs) throws ADSContextException
  private Map<ServerProperty, Object> makePropertiesFromServerAttrs(SearchResultEntry entry) throws ADSContextException
  {
    Map<ServerProperty, Object> result = new HashMap<>();
    try
    for (Attribute attr : entry.getAllAttributes())
    {
      NamingEnumeration<? extends Attribute> ne = attrs.getAll();
      while (ne.hasMore())
      {
        Attribute attr = ne.next();
        String attrID = attr.getID();
      AttributeType attrType = attr.getAttributeDescription().getAttributeType();
        Object value;
        if (attrID.endsWith(";binary"))
        {
          attrID = attrID.substring(0, attrID.lastIndexOf(";binary"));
        }
        ServerProperty prop = null;
        ServerProperty[] props = ServerProperty.values();
        for (int i = 0; i < props.length && prop == null; i++)
        {
          String v = props[i].getAttributeName();
          if (attrID.equalsIgnoreCase(v))
        if (attrType.hasName(v))
          {
            prop = props[i];
          }
@@ -1598,33 +1380,17 @@
          if (attr.size() >= 1 && MULTIVALUED_SERVER_PROPERTIES.contains(prop))
          {
            Set<String> set = new HashSet<>();
            NamingEnumeration<?> ae = attr.getAll();
            try
            {
              while (ae.hasMore())
              {
                set.add((String) ae.next());
              }
            }
            finally
            {
              ae.close();
            }
          toStrings(set, attr);
            value = set;
          }
          else
          {
            value = attr.get(0);
          value = attr.firstValueAsString();
          }
          result.put(prop, value);
        }
      }
    }
    catch (NamingException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    return result;
  }
@@ -1641,58 +1407,33 @@
   * @throws ADSContextException
   *           if something goes wrong.
   */
  private Map<AdministratorProperty, Object> makePropertiesFromAdministratorAttrs(String rdn, Attributes attrs)
      throws ADSContextException
  private Map<AdministratorProperty, Object> makePropertiesFromAdministratorAttrs(RDN rdn, Iterable<Attribute> attrs)
  {
    Map<AdministratorProperty, Object> result = new HashMap<>();
    String dn = nameFromDN(rdn) + "," + getAdministratorContainerDN();
    result.put(AdministratorProperty.ADMINISTRATOR_DN, dn);
    NamingEnumeration<? extends Attribute> ne = null;
    try
    result.put(AdministratorProperty.ADMINISTRATOR_DN, rdn + "," + getAdministratorContainerDN());
    for (Attribute attr : attrs)
    {
      ne = attrs.getAll();
      while (ne.hasMore())
      {
        Attribute attr = ne.next();
        String attrID = attr.getID();
        Object value;
      AttributeType attrName = attr.getAttributeDescription().getAttributeType();
        if ("cn".equalsIgnoreCase(attrID))
      if (attrName.hasName("cn"))
        {
          value = attr.get(0);
          result.put(AdministratorProperty.UID, value);
        result.put(AdministratorProperty.UID, attr.firstValueAsString());
        }
        else if ("userpassword".equalsIgnoreCase(attrID))
      else if (attrName.hasName("userpassword"))
        {
          value = new String((byte[]) attr.get());
          result.put(AdministratorProperty.PASSWORD, value);
        result.put(AdministratorProperty.PASSWORD, new String(attr.firstValue().toByteArray()));
        }
        else if ("description".equalsIgnoreCase(attrID))
      else if (attrName.hasName("description"))
        {
          value = attr.get(0);
          result.put(AdministratorProperty.DESCRIPTION, value);
        result.put(AdministratorProperty.DESCRIPTION, attr.firstValueAsString());
        }
        else if ("ds-privilege-name".equalsIgnoreCase(attrID))
      else if (attrName.hasName("ds-privilege-name"))
        {
          LinkedHashSet<String> privileges = new LinkedHashSet<>();
          NamingEnumeration<?> attValueList = attr.getAll();
          while (attValueList.hasMoreElements())
          {
            privileges.add(attValueList.next().toString());
          }
        toStrings(privileges, attr);
          result.put(AdministratorProperty.PRIVILEGE, privileges);
        }
      }
    }
    catch (NamingException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    finally
    {
      handleCloseNamingEnumeration(ne);
    }
    return result;
  }
@@ -1840,51 +1581,6 @@
  }
  // LDAP utilities
  /**
   * Returns the LdapName object for the given dn.
   *
   * @param dn
   *          the DN.
   * @return the LdapName object for the given dn.
   * @throws ADSContextException
   *           if a valid LdapName could not be retrieved for the given dn.
   */
  private static LdapName nameFromDN(String dn) throws ADSContextException
  {
    try
    {
      return new LdapName(dn);
    }
    catch (InvalidNameException x)
    {
      logger.error(LocalizableMessage.raw("Error parsing dn " + dn, x));
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
  }
  /**
   * Returns the String rdn for the given search result name.
   *
   * @param rdnName
   *          the search result name.
   * @return the String rdn for the given search result name.
   * @throws ADSContextException
   *           if a valid String rdn could not be retrieved for the given result
   *           name.
   */
  private static String getRdn(String rdnName) throws ADSContextException
  {
    // Transform the JNDI name into a RDN string
    try
    {
      return new CompositeName(rdnName).get(0);
    }
    catch (InvalidNameException x)
    {
      logger.error(LocalizableMessage.raw("Error parsing rdn " + rdnName, x));
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
  }
  /**
   * Tells whether an entry with the provided DN exists.
@@ -1896,37 +1592,27 @@
   * @throws ADSContextException
   *           if an error occurred while checking if the entry exists or not.
   */
  private boolean isExistingEntry(LdapName dn) throws ADSContextException
  private boolean isExistingEntry(String dn) throws ADSContextException
  {
    try
    SearchRequest request = newSearchRequest(dn, BASE_OBJECT, "(objectclass=*)", NO_ATTRIBUTES);
    try (ConnectionEntryReader entryReader = getConnection().getConnection().search(request))
    {
      SearchControls sc = new SearchControls();
      sc.setSearchScope(SearchControls.OBJECT_SCOPE);
      sc.setReturningAttributes(new String[] { SchemaConstants.NO_ATTRIBUTES });
      NamingEnumeration<SearchResult> sr = getDirContext().search(dn, "(objectclass=*)", sc);
      try
      while (entryReader.hasNext())
      {
        while (sr.hasMore())
        {
          sr.next();
        entryReader.readEntry();
          return true;
        }
      }
      finally
      {
        sr.close();
      }
      return false;
    }
    catch (NameNotFoundException x)
    catch (EntryNotFoundException x)
    {
      return false;
    }
    catch (NoPermissionException x)
    catch (AuthorizationException x)
    {
      throw new ADSContextException(ErrorType.ACCESS_PERMISSION);
    }
    catch (javax.naming.NamingException x)
    catch (IOException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
@@ -1942,12 +1628,7 @@
   */
  private void createContainerEntry(String dn) throws ADSContextException
  {
    Attribute oc = new BasicAttribute("objectclass");
    oc.add("top");
    oc.add("ds-cfg-branch");
    BasicAttributes attrs = new BasicAttributes();
    attrs.put(oc);
    createEntry(dn, attrs);
    createEntry(newAddRequest(dn).addAttribute("objectclass", "top", "ds-cfg-branch"));
  }
  /**
@@ -1958,13 +1639,11 @@
   */
  private void createAdministratorContainerEntry() throws ADSContextException
  {
    Attribute oc = new BasicAttribute("objectclass");
    oc.add("groupofurls");
    BasicAttributes attrs = new BasicAttributes();
    attrs.put(oc);
    attrs.put("memberURL", "ldap:///" + getAdministratorContainerDN() + "??one?(objectclass=*)");
    attrs.put("description", "Group of identities which have full access.");
    createEntry(getAdministratorContainerDN(), attrs);
    AddRequest request = newAddRequest(getAdministratorContainerDN())
        .addAttribute("objectclass", "groupofurls")
        .addAttribute("memberURL", "ldap:///" + getAdministratorContainerDN() + "??one?(objectclass=*)")
        .addAttribute("description", "Group of identities which have full access.");
    createEntry(request);
  }
  /**
@@ -1975,34 +1654,37 @@
   */
  private void createTopContainerEntry() throws ADSContextException
  {
    Attribute oc = new BasicAttribute("objectclass");
    oc.add("top");
    oc.add("ds-cfg-branch");
    BasicAttributes attrs = new BasicAttributes();
    attrs.put(oc);
    createEntry(getAdministrationSuffixDN(), attrs);
    AddRequest request = newAddRequest(getAdministrationSuffixDN())
        .addAttribute("objectclass", "top", "ds-cfg-branch");
    createEntry(request);
  }
  /**
   * Creates an entry with the provided dn and attributes.
   * Creates an entry with the provided add request.
   *
   * @param dn
   *          the dn of the entry.
   * @param attrs
   *          the attributes of the entry.
   * @param addRequest
   *          the add request.
   * @throws ADSContextException
   *           if the entry could not be created.
   */
  private void createEntry(String dn, Attributes attrs) throws ADSContextException
  private void createEntry(AddRequest request) throws ADSContextException
  {
    try
    {
      DirContext ctx = getDirContext().createSubcontext(nameFromDN(dn), attrs);
      ctx.close();
      throwIfNotSuccess(getConnection().getConnection().add(request));
    }
    catch (NamingException x)
    catch (LdapException e)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, e);
    }
  }
  private void throwIfNotSuccess(Result result) throws LdapException
  {
    ResultCode rc = result.getResultCode();
    if (rc.isExceptional())
    {
      throw LdapException.newLdapException(result);
    }
  }
@@ -2107,7 +1789,7 @@
   * @throws ADSContextException
   *           In case there is a problem registering the instance public key certificate ID
   */
  private void registerInstanceKeyCertificate(Map<ServerProperty, Object> serverProperties, LdapName serverEntryDn)
  private void registerInstanceKeyCertificate(Map<ServerProperty, Object> serverProperties, String serverEntryDn)
      throws ADSContextException
  {
    ADSContextHelper helper = new ADSContextHelper();
@@ -2129,55 +1811,38 @@
   */
  public Map<String, byte[]> getTrustedCertificates() throws ADSContextException
  {
    final Map<String, byte[]> certificateMap = new HashMap<>();
    final String baseDNStr = getInstanceKeysContainerDN();
    try
    {
    final String baseDN = getInstanceKeysContainerDN();
      ADSContextHelper helper = new ADSContextHelper();
      final LdapName baseDN = new LdapName(baseDNStr);
      final String FILTER_OC_INSTANCE_KEY = "(objectclass=" + helper.getOcCryptoInstanceKey() + ")";
      final String FILTER_NOT_COMPROMISED = "(!(" + helper.getAttrCryptoKeyCompromisedTime() + "=*))";
      final String searchFilter = "(&" + FILTER_OC_INSTANCE_KEY + FILTER_NOT_COMPROMISED + ")";
      final SearchControls searchControls = new SearchControls();
      searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
      final String attrIDs[] =
          { ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName(),
            ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName() + ";binary" };
      searchControls.setReturningAttributes(attrIDs);
      NamingEnumeration<SearchResult> keyEntries =
          connectionWrapper.getLdapContext().search(baseDN, searchFilter, searchControls);
      try
    String instanceKeyId = ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName();
    String instanceKeyCertificate =
        ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName() + ";binary";
    SearchRequest request =
        newSearchRequest(baseDN, SINGLE_LEVEL, searchFilter, instanceKeyId, instanceKeyCertificate);
    final Map<String, byte[]> certificateMap = new HashMap<>();
    try (ConnectionEntryReader entryReader = connectionWrapper.getConnection().search(request))
      {
        while (keyEntries.hasMore())
      while (entryReader.hasNext())
        {
          final SearchResult entry = keyEntries.next();
          final Attributes attrs = entry.getAttributes();
          final Attribute keyIDAttr = attrs.get(attrIDs[0]);
          final Attribute keyCertAttr = attrs.get(attrIDs[1]);
        final SearchResultEntry entry = entryReader.readEntry();
        final Attribute keyIDAttr = entry.getAttribute(instanceKeyId);
        final Attribute keyCertAttr = entry.getAttribute(instanceKeyCertificate);
          if (null == keyIDAttr || null == keyCertAttr)
          {
            continue;// schema viol.
          }
          certificateMap.put((String) keyIDAttr.get(), (byte[]) keyCertAttr.get());
        certificateMap.put(keyIDAttr.firstValueAsString(), keyCertAttr.firstValue().toByteArray());
        }
      return certificateMap;
      }
      finally
      {
        try
        {
          keyEntries.close();
        }
        catch (Exception ex)
        {
          logger.warn(LocalizableMessage.raw("Unexpected error closing enumeration on ADS key pairs", ex));
        }
      }
    }
    catch (NamingException x)
    catch (IOException x)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x);
    }
    return certificateMap;
  }
  /**
@@ -2308,19 +1973,4 @@
      }
    }
  }
  private void handleCloseNamingEnumeration(NamingEnumeration<?> ne) throws ADSContextException
  {
    if (ne != null)
    {
      try
      {
        ne.close();
      }
      catch (NamingException ex)
      {
        throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, ex);
      }
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/admin/ads/ADSContextHelper.java
@@ -16,22 +16,29 @@
 */
package org.opends.admin.ads;
import static org.forgerock.opendj.ldap.Filter.*;
import static org.forgerock.opendj.ldap.ModificationType.*;
import static org.forgerock.opendj.ldap.SearchScope.*;
import static org.forgerock.opendj.ldap.requests.Requests.*;
import java.io.IOException;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import org.forgerock.opendj.config.ManagedObjectNotFoundException;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.requests.AddRequest;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.Result;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.forgerock.opendj.server.config.client.LDIFBackendCfgClient;
import org.forgerock.opendj.server.config.client.RootCfgClient;
import org.forgerock.opendj.server.config.meta.BackendCfgDefn;
@@ -127,12 +134,9 @@
  @throws ADSContextException In case some JNDI operation fails or there is a
  problem getting the instance public key certificate ID.
   */
  void registerInstanceKeyCertificate(
      ConnectionWrapper conn, Map<ServerProperty, Object> serverProperties,
      LdapName serverEntryDn)
  throws ADSContextException {
    assert serverProperties.containsKey(
        ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE);
  void registerInstanceKeyCertificate(ConnectionWrapper conn, Map<ServerProperty, Object> serverProperties,
      String serverEntryDn) throws ADSContextException
  {
    if (! serverProperties.containsKey(
        ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)) {
      return;
@@ -141,35 +145,32 @@
    // the key ID might be supplied in serverProperties (although, I am unaware of any such case).
    String keyID = (String)serverProperties.get(ServerProperty.INSTANCE_KEY_ID);
    /* these attributes are used both to search for an existing certificate
   entry and, if one does not exist, add a new certificate entry */
    final BasicAttributes keyAttrs = new BasicAttributes();
    final Attribute oc = new BasicAttribute("objectclass");
    oc.add("top"); oc.add("ds-cfg-instance-key");
    keyAttrs.put(oc);
    // These attributes are used both to search for an existing certificate entry and,
    // if one does not exist, add a new certificate entry
    Filter filter = equality("objectclass", "ds-cfg-instance-key");
    if (null != keyID) {
      keyAttrs.put(new BasicAttribute(
          ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
      filter = and(
          filter,
          equality(ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
    }
    keyAttrs.put(new BasicAttribute(
        ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName()
        + ";binary",
        serverProperties.get(
            ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)));
    filter = and(
        filter,
        equality(
            ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName() + ";binary",
            serverProperties.get(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)));
    /* search for public-key certificate entry in ADS DIT */
    final String attrIDs[] = { "ds-cfg-key-id" };
    NamingEnumeration<SearchResult> results = null;
    try
    DN dn = DN.valueOf(ADSContext.getInstanceKeysContainerDN());
    SearchRequest searchRequest = newSearchRequest(dn, WHOLE_SUBTREE, filter, "ds-cfg-key-id");
    try (ConnectionEntryReader entryReader = conn.getConnection().search(searchRequest))
    {
      results = conn.getLdapContext().search(ADSContext.getInstanceKeysContainerDN(), keyAttrs, attrIDs);
      boolean found = false;
      while (results.hasMore()) {
        final Attribute keyIdAttr =
          results.next().getAttributes().get(attrIDs[0]);
      while (entryReader.hasNext())
      {
        final Attribute keyIdAttr = entryReader.readEntry().getAttribute("ds-cfg-key-id");
        if (null != keyIdAttr) {
          /* attribute ds-cfg-key-id is the entry is a MUST in the schema */
          keyID = (String)keyIdAttr.get();
          keyID = keyIdAttr.firstValueAsString();
        }
        found = true;
      }
@@ -185,32 +186,45 @@
          keyID = CryptoManagerImpl.getInstanceKeyID(
              (byte[])serverProperties.get(
                  ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE));
          keyAttrs.put(new BasicAttribute(
              ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
        }
        /* add public-key certificate entry */
        final LdapName keyDn = new LdapName(
            ServerProperty.INSTANCE_KEY_ID.getAttributeName() + "=" + Rdn.escapeValue(keyID)
                + "," + ADSContext.getInstanceKeysContainerDN());
        conn.getLdapContext().createSubcontext(keyDn, keyAttrs).close();
        String keyDn = ServerProperty.INSTANCE_KEY_ID.getAttributeName() + "=" + Rdn.escapeValue(keyID)
            + "," + ADSContext.getInstanceKeysContainerDN();
        AddRequest addRequest = newAddRequest(keyDn)
            .addAttribute("objectclass", "top", "ds-cfg-instance-key");
        if (null != keyID) {
          addRequest.addAttribute(ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID);
        }
        addRequest
            .addAttribute(
                ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName() + ";binary",
                serverProperties.get(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE))
            .addAttribute(ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID);
        throwIfNotSuccess(conn.getConnection().add(addRequest));
      }
      if (serverEntryDn != null)
      {
        /* associate server entry with certificate entry via key ID attribute */
        conn.getLdapContext().modifyAttributes(serverEntryDn,
          DirContext.REPLACE_ATTRIBUTE,
          new BasicAttributes(ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
        ModifyRequest request = newModifyRequest(serverEntryDn)
            .addModification(REPLACE, ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID);
        throwIfNotSuccess(conn.getConnection().modify(request));
      }
    }
    catch (NamingException | CryptoManagerException ne)
    catch (IOException | CryptoManagerException ne)
    {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, ne);
    }
    finally
  }
  private void throwIfNotSuccess(Result result) throws LdapException
    {
      handleCloseNamingEnumeration(results);
    ResultCode rc = result.getResultCode();
    if (rc.isExceptional())
    {
      throw LdapException.newLdapException(result);
    }
  }
@@ -235,20 +249,4 @@
  {
    return ConfigConstants.ATTR_CRYPTO_KEY_COMPROMISED_TIME;
  }
  private void handleCloseNamingEnumeration(NamingEnumeration<?> ne)
  throws ADSContextException
  {
    if (ne != null)
    {
      try
      {
        ne.close();
      }
      catch (NamingException ex)
      {
        throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, ex);
      }
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java
@@ -3821,17 +3821,13 @@
   */
  private ReplicationCliReturnCode enableReplication(EnableReplicationUserData uData)
  {
    ConnectionWrapper conn1 = null;
    ConnectionWrapper conn2 = null;
    try
    {
      println();
      print(formatter.getFormattedWithPoints(INFO_REPLICATION_CONNECTING.get()));
      List<LocalizableMessage> errorMessages = new LinkedList<>();
      conn1 = createAdministrativeConnection(uData.getServer1(), errorMessages);
      conn2 = createAdministrativeConnection(uData.getServer2(), errorMessages);
    try (ConnectionWrapper conn1 = createAdministrativeConnection(uData.getServer1(), errorMessages);
        ConnectionWrapper conn2 = createAdministrativeConnection(uData.getServer2(), errorMessages))
    {
      if (!errorMessages.isEmpty())
      {
        errPrintLn(errorMessages);
@@ -3887,10 +3883,6 @@
        return rce.getErrorCode();
      }
    }
    finally
    {
      close(conn1, conn2);
    }
  }
  private void checkReplicationServerAlreadyConfigured(ConnectionWrapper conn, EnableReplicationServerData server)
@@ -4132,9 +4124,8 @@
   */
  private ReplicationCliReturnCode initializeReplication(SourceDestinationServerUserData uData)
  {
    ConnectionWrapper connSource = createAdministrativeConnection(uData, uData.getSource());
    ConnectionWrapper connDestination = createAdministrativeConnection(uData, uData.getDestination());
    try
    try (ConnectionWrapper connSource = createAdministrativeConnection(uData, uData.getSource());
        ConnectionWrapper connDestination = createAdministrativeConnection(uData, uData.getDestination()))
    {
      if (connSource == null || connDestination == null)
      {
@@ -4175,10 +4166,6 @@
      }
      return returnValue;
    }
    finally
    {
      close(connDestination, connSource);
    }
  }
  private ConnectionWrapper createAdministrativeConnection(SourceDestinationServerUserData uData, HostPort server)