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

Ludovic Poitou
13.09.2011 66e0ea567ae7d17fe9c348016b18c90a33fca561
Fix to OPENDJ-197: In the StaticGroup cache, keep members as strings (ByteString) rather than DN objects. These are much more compact. DNs are built from the ByteString only when needed.
7 files modified
220 ■■■■■ changed files
opends/src/messages/messages/extension.properties 18 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/extension_es.properties 18 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/extension_fr.properties 17 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/Group.java 5 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/FilteredStaticGroupMemberList.java 32 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/SimpleStaticGroupMemberList.java 34 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/StaticGroup.java 96 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/extension.properties
@@ -21,6 +21,7 @@
# CDDL HEADER END
#
#      Copyright 2006-2010 Sun Microsystems, Inc.
#      Portions Copyright 2011 ForgeRock AS
@@ -901,10 +902,6 @@
NOTICE_ERRORLOG_ACCTNOTHANDLER_NOTIFICATION_375=Account-Status-Notification \
 type='%s' userdn='%s' id=%d msg='%s'
MILD_ERR_SASLCRAMMD5_CANNOT_GET_REVERSIBLE_PASSWORDS_377=An error occurred \
 while attempting to retrieve the clear-text password(s) for user %s in order \
 to perform SASL CRAM-MD5 authentication:  %s
@@ -948,9 +945,6 @@
 perform an internal modification to update the group:  %s
MILD_ERR_EXTOP_PASSMOD_INSUFFICIENT_PRIVILEGES_392=You do not have sufficient \
 privileges to perform password reset operations
MILD_ERR_SASLDIGESTMD5_EMPTY_AUTHZID_393=The provided authorization ID was \
 empty, which is not allowed for DIGEST-MD5 authentication
MILD_ERR_SASLDIGESTMD5_AUTHZID_INVALID_DN_394=The provided authorization ID \
@@ -963,14 +957,6 @@
 find any entry corresponding to authorization ID %s
MILD_ERR_SASLDIGESTMD5_CANNOT_MAP_AUTHZID_399=An error occurred while \
 attempting to map authorization ID %s to a user entry:  %s
MILD_ERR_SASLPLAIN_AUTHZID_INVALID_DN_400=The provided authorization ID %s \
 contained an invalid DN:  %s
MILD_ERR_SASLPLAIN_AUTHZID_INSUFFICIENT_PRIVILEGES_401=The authenticating \
@@ -1439,3 +1425,5 @@
MILD_ERR_CHARSET_VALIDATOR_TOO_FEW_OPTIONAL_CHAR_SETS_581=The provided \
 password did not contain characters from at least %d of the following \
 character sets: %s
MILD_ERR_STATICMEMBERS_CANNOT_DECODE_DN_582=An error occurred while \
 attempting to decode member's DN %s of static group %s:  %s
opends/src/messages/messages/extension_es.properties
@@ -21,6 +21,7 @@
# CDDL HEADER END
#
#      Copyright 2006-2010 Sun Microsystems, Inc.
#      Portions Copyright 2011 ForgeRock AS
@@ -321,10 +322,6 @@
MILD_ERR_ERRORLOG_ACCTNOTHANDLER_CANNOT_GET_NOTIFICATION_TYPES_374=Se produjo un error al intentar determinar los tipos de notificaci\u00f3n de estado de cuenta a partir de la entrada de configuraci\u00f3n %s:  %s
NOTICE_ERRORLOG_ACCTNOTHANDLER_NOTIFICATION_375=Tipo Account-Status-Notification='%s' userdn='%s' id=%d msg='%s'
MILD_ERR_SASLCRAMMD5_CANNOT_GET_REVERSIBLE_PASSWORDS_377=Se produjo un error al intentar recuperar la(s) contrase\u00f1a(s) no cifrada(s) para el usuario %s de cara a realizar la autenticaci\u00f3n SASL CRAM-MD5:  %s
MILD_ERR_SASLPLAIN_CANNOT_CHECK_PASSWORD_VALIDITY_378=Se produjo un error al intentar verificar la contrase\u00f1a para el usuario %s durante la autenticaci\u00f3n SASL PLAIN:  %s
MILD_ERR_STARTTLS_ERROR_SENDING_CLEAR_RESPONSE_379=Se produjo un error inesperado al intentar enviar la respuesta no cifrada al cliente despu\u00e9s de iniciar la negociaci\u00f3n TLS:  %s
@@ -341,23 +338,12 @@
MILD_ERR_STATICGROUP_ADD_MEMBER_UPDATE_FAILED_390=No se puede agregar al usuario %s como miembro nuevo del grupo est\u00e1tico %s porque se produjo un error al intentar realizar una modificaci\u00f3n interna para actualizar el grupo:  %s
MILD_ERR_STATICGROUP_REMOVE_MEMBER_UPDATE_FAILED_391=No se puede agregar al usuario %s como miembro del grupo est\u00e1tico %s porque se produjo un error al intentar realizar una modificaci\u00f3n interna para actualizar el grupo:  %s
MILD_ERR_EXTOP_PASSMOD_INSUFFICIENT_PRIVILEGES_392=No dispone de los privilegios suficientes para realizar operaciones de restablecimiento de contrase\u00f1a
MILD_ERR_SASLDIGESTMD5_EMPTY_AUTHZID_393=El ID de autorizaci\u00f3n proporcionado estaba vac\u00edo, lo cual no est\u00e1 permitido para la autenticaci\u00f3n DIGEST-MD5
MILD_ERR_SASLDIGESTMD5_AUTHZID_INVALID_DN_394=El ID de autorizaci\u00f3n proporcionado %s conten\u00eda un ND no v\u00e1lido:  %s
MILD_ERR_SASLDIGESTMD5_AUTHZID_NO_SUCH_ENTRY_396=La entrada %s especificada como identidad de autorizaci\u00f3n no existe
MILD_ERR_SASLDIGESTMD5_AUTHZID_CANNOT_GET_ENTRY_397=No se puede recuperar la entrada %s, que se especific\u00f3 como identidad de la autorizaci\u00f3n:  %s
MILD_ERR_SASLDIGESTMD5_AUTHZID_NO_MAPPED_ENTRY_398=El servidor no pudo encontrar ninguna entrada que se correspondiera con el ID de autorizaci\u00f3n %s
MILD_ERR_SASLDIGESTMD5_CANNOT_MAP_AUTHZID_399=Se produjo un error al intentar asignar el ID de autorizaci\u00f3n %s a una entrada de usuario:  %s
MILD_ERR_SASLPLAIN_AUTHZID_INVALID_DN_400=El ID de autorizaci\u00f3n proporcionado %s conten\u00eda un ND no v\u00e1lido:  %s
MILD_ERR_SASLPLAIN_AUTHZID_INSUFFICIENT_PRIVILEGES_401=El usuario que intenta la autenticaci\u00f3n %s no dispone de los privilegios suficientes para especificar un ID de autorizaci\u00f3n alternativo
MILD_ERR_SASLPLAIN_AUTHZID_NO_SUCH_ENTRY_402=La entrada correspondiente al ND de autorizaci\u00f3n %s no existe en Directory Server
@@ -528,3 +514,5 @@
INFO_GSSAPI_STOPPED_575=El controlador del mecanismo GSSAPI (SASL) se ha detenido
MILD_ERR_COLLECTIVEATTRIBUTESUBENTRIES_VATTR_NOT_SEARCHABLE_576=El atributo %s no permite su b\u00fasqueda y no se deber\u00eda incluir en filtros de b\u00fasqueda no indizados
MILD_ERR_PASSWORDPOLICYSUBENTRY_VATTR_NOT_SEARCHABLE_577=El atributo %s no permite su b\u00fasqueda y no se deber\u00eda incluir en filtros de b\u00fasqueda no indizados
MILD_ERR_STATICMEMBERS_CANNOT_DECODE_DN_582=Se produjo un error al intentar analizar el ND del miembro %s del grupo est\u00e1tico %s:  %s
opends/src/messages/messages/extension_fr.properties
@@ -21,6 +21,7 @@
# CDDL HEADER END
#
#      Copyright 2006-2010 Sun Microsystems, Inc.
#      Portions Copyright 2011 ForgeRock AS
@@ -321,10 +322,6 @@
MILD_ERR_ERRORLOG_ACCTNOTHANDLER_CANNOT_GET_NOTIFICATION_TYPES_374=Une erreur s'est produite lors de la d\u00e9termination des types de notification statut de compte \u00e0 partir de l'entr\u00e9e de configuration %s\u00a0: %s
NOTICE_ERRORLOG_ACCTNOTHANDLER_NOTIFICATION_375=Account-Status-Notification type='%s' userdn='%s' id=%d msg='%s'
MILD_ERR_SASLCRAMMD5_CANNOT_GET_REVERSIBLE_PASSWORDS_377=Une erreur s'est produite lors de la r\u00e9cup\u00e9ration d'au moins un mot de passe en texte clair pour l'utilisateur %s \u00e0 des fins d'authentification SASL CRAM-MD5\u00a0: %s
MILD_ERR_SASLPLAIN_CANNOT_CHECK_PASSWORD_VALIDITY_378=Une erreur s'est produite lors de la v\u00e9rification du mot de passe pour l'utilisateur %s lors de l'authentification SASL PLAIN\u00a0: %s
MILD_ERR_STARTTLS_ERROR_SENDING_CLEAR_RESPONSE_379=Une erreur inattendue s'est produite lors de l'envoi d'une r\u00e9ponse en texte clair au client apr\u00e8s le d\u00e9marrage de la n\u00e9gociation TLS\u00a0: %s
@@ -341,23 +338,12 @@
MILD_ERR_STATICGROUP_ADD_MEMBER_UPDATE_FAILED_390=Impossible d'ajouter l'utilisateur %s comme nouveau membre du groupe statique %s car une erreur s'est produite lors de la modification interne destin\u00e9e \u00e0 mettre \u00e0 jour le groupe\u00a0: %s
MILD_ERR_STATICGROUP_REMOVE_MEMBER_UPDATE_FAILED_391=Impossible de supprimer l'utilisateur %s comme membre du groupe statique %s car une erreur s'est produite lors de la modification interne destin\u00e9e \u00e0 mettre \u00e0 jour le groupe\u00a0: %s
MILD_ERR_EXTOP_PASSMOD_INSUFFICIENT_PRIVILEGES_392=Vous ne disposez pas des privil\u00e8ges suffisants pour ex\u00e9cuter des op\u00e9rations de r\u00e9initialisation de mot de passe
MILD_ERR_SASLDIGESTMD5_EMPTY_AUTHZID_393=L'ID d'autorisation fournie est vide, ce qui n'est pas autoris\u00e9 dans le cadre de l'authentification DIGEST-MD5
MILD_ERR_SASLDIGESTMD5_AUTHZID_INVALID_DN_394=L'ID d'autorisation fournie %s contient un DN non valide\u00a0: %s
MILD_ERR_SASLDIGESTMD5_AUTHZID_NO_SUCH_ENTRY_396=L'entr\u00e9e %s sp\u00e9cifi\u00e9e comme identit\u00e9 d'autorisation n'existe pas
MILD_ERR_SASLDIGESTMD5_AUTHZID_CANNOT_GET_ENTRY_397=Impossible de r\u00e9cup\u00e9rer l'entr\u00e9e %s sp\u00e9cifi\u00e9e comme identit\u00e9 d'autorisation\u00a0: %s
MILD_ERR_SASLDIGESTMD5_AUTHZID_NO_MAPPED_ENTRY_398=Impossible pour le serveur de trouver une entr\u00e9e correspondant \u00e0 l'ID d'autorisation %s
MILD_ERR_SASLDIGESTMD5_CANNOT_MAP_AUTHZID_399=Une erreur s'est produite lors du mappage de l'ID d'autorisation %s \u00e0 une entr\u00e9e utilisateur\u00a0: %s
MILD_ERR_SASLPLAIN_AUTHZID_INVALID_DN_400=L'ID d'autorisation fournie %s contient un DN non valide\u00a0: %s
MILD_ERR_SASLPLAIN_AUTHZID_INSUFFICIENT_PRIVILEGES_401=L'utilisateur en cours d'authentification %s ne poss\u00e8de pas les privil\u00e8ges suffisants pour sp\u00e9cifier une ID d'autorisation de remplacement
MILD_ERR_SASLPLAIN_AUTHZID_NO_SUCH_ENTRY_402=L'entr\u00e9e correspondant au DN d'autorisation %s n'existe pas dans Directory Server
@@ -529,3 +515,4 @@
MILD_ERR_COLLECTIVEATTRIBUTESUBENTRIES_VATTR_NOT_SEARCHABLE_576=L'attribut %s ne peut pas faire l'objet d'une recherche et ne doit pas \u00eatre inclus dans des filtres de recherche non index\u00e9s
MILD_ERR_PASSWORDPOLICYSUBENTRY_VATTR_NOT_SEARCHABLE_577=L'attribut %s ne peut pas faire l'objet d'une recherche et ne doit pas \u00eatre inclus dans des filtres de recherche non index\u00e9s
MILD_ERR_PWSCHEME_INVALID_BASE64_DECODED_STORED_PASSWORD_578=La valeur du mot de passe %s a \u00e9t\u00e9 d\u00e9cod\u00e9 en base64, mais est trop courte pour \u00eatre valide
MILD_ERR_STATICMEMBERS_CANNOT_DECODE_DN_582=Une erreur s'est produite lors du d\u00e9codage du DN %s, membre du groupe statique %s\u00a0: %s
opends/src/server/org/opends/server/api/Group.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 */
package org.opends.server.api;
import org.opends.messages.Message;
@@ -299,7 +300,9 @@
  public boolean isMember(DN userDN)
         throws DirectoryException
  {
    return isMember(userDN, new HashSet<DN>());
    if (userDN != null)
      return isMember(userDN, new HashSet<DN>());
    return false;
  }
opends/src/server/org/opends/server/extensions/FilteredStaticGroupMemberList.java
@@ -23,8 +23,10 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 */
package org.opends.server.extensions;
import org.opends.server.types.ByteString;
import org.opends.messages.Message;
@@ -76,11 +78,11 @@
  private Entry nextMatchingEntry;
  // The iterator used to traverse the set of member DNs.
  private Iterator<DN> memberDNIterator;
  private Iterator<ByteString> memberDNIterator;
  // The set of DNs for the users that are members of the associated static
  // group.
  private LinkedList<DN> memberDNs;
  private LinkedList<ByteString> memberDNs;
  // The membership exception that should be thrown the next time a member is
  // requested.
@@ -111,13 +113,14 @@
   *                    match.  If this is {@code null}, then all members will
   *                    be considered eligible.
   */
  public FilteredStaticGroupMemberList(DN groupDN, Set<DN> memberDNs, DN baseDN,
                                       SearchScope scope, SearchFilter filter)
  public FilteredStaticGroupMemberList(DN groupDN, Set<ByteString> memberDNs,
                                       DN baseDN, SearchScope scope,
                                       SearchFilter filter)
  {
    ensureNotNull(groupDN, memberDNs);
    this.groupDN   = groupDN;
    this.memberDNs = new LinkedList<DN>(memberDNs);
    this.memberDNs = new LinkedList<ByteString>(memberDNs);
    memberDNIterator = memberDNs.iterator();
    this.baseDN = baseDN;
@@ -152,8 +155,25 @@
  {
    while (memberDNIterator.hasNext())
    {
      DN nextDN = memberDNIterator.next();
      DN nextDN = null;
      try
      {
        nextDN = DN.decode(memberDNIterator.next());
      }
      catch (DirectoryException de)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, de);
        }
        Message message = ERR_STATICMEMBERS_CANNOT_DECODE_DN.
            get(String.valueOf(nextDN), String.valueOf(groupDN),
                String.valueOf(de.getMessageObject()));
        nextMembershipException =
             new MembershipException(message, true, de);
        return;
      }
      // Check to see if we can eliminate the entry as a possible match purely
      // based on base DN and scope.
opends/src/server/org/opends/server/extensions/SimpleStaticGroupMemberList.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 */
package org.opends.server.extensions;
import org.opends.messages.Message;
@@ -33,6 +34,7 @@
import java.util.LinkedList;
import java.util.Set;
import org.opends.server.types.ByteString;
import org.opends.server.types.DirectoryConfig;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
@@ -68,11 +70,11 @@
  private DN groupDN;
  // The iterator used to traverse the set of member DNs.
  private Iterator<DN> memberDNIterator;
  private Iterator<ByteString> memberDNIterator;
  // The set of DNs for the users that are members of the associated static
  // group.
  private LinkedList<DN> memberDNs;
  private LinkedList<ByteString> memberDNs;
@@ -85,12 +87,12 @@
   * @param  memberDNs  The set of DNs for the users that are members of the
   *                    associated static group.
   */
  public SimpleStaticGroupMemberList(DN groupDN, Set<DN> memberDNs)
  public SimpleStaticGroupMemberList(DN groupDN, Set<ByteString> memberDNs)
  {
    ensureNotNull(groupDN, memberDNs);
    this.groupDN   = groupDN;
    this.memberDNs = new LinkedList<DN>(memberDNs);
    this.memberDNs = new LinkedList<ByteString>(memberDNs);
    memberDNIterator = memberDNs.iterator();
  }
@@ -114,12 +116,28 @@
  public DN nextMemberDN()
         throws MembershipException
  {
    DN dn = null;
    if (memberDNIterator.hasNext())
    {
      return memberDNIterator.next();
      try{
        dn = DN.decode(memberDNIterator.next());
      }
      catch (DirectoryException de)
      {
        // Should not happen
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, de);
        }
        Message message = ERR_STATICMEMBERS_CANNOT_DECODE_DN.
            get(String.valueOf(dn), String.valueOf(groupDN),
                String.valueOf(de.getMessageObject()));
        throw new MembershipException(message, true, de);
      }
    }
    return null;
    return dn;
  }
@@ -133,11 +151,11 @@
  {
    if (memberDNIterator.hasNext())
    {
      DN memberDN = memberDNIterator.next();
      ByteString memberDN = memberDNIterator.next();
      try
      {
        Entry memberEntry = DirectoryConfig.getEntry(memberDN);
        Entry memberEntry = DirectoryConfig.getEntry(DN.decode(memberDN));
        if (memberEntry == null)
        {
          Message message = ERR_STATICMEMBERS_NO_SUCH_ENTRY.get(
opends/src/server/org/opends/server/extensions/StaticGroup.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 */
package org.opends.server.extensions;
@@ -49,6 +50,7 @@
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.Attributes;
import org.opends.server.types.ByteString;
import org.opends.server.types.Control;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DirectoryConfig;
@@ -74,11 +76,12 @@
/**
 * This class provides a static group implementation, in which the DNs
 * of all members are explicitly listed.  There are two variants of
 * static groups:  one based on the {@code groupOfNames} object class,
 * which stores the member list in the {@code member} attribute, and
 * one based on the {@code groupOfUniqueNames} object class, which
 * stores the member list in the {@code uniqueMember} attribute.
 * of all members are explicitly listed.  There are three variants of
 * static groups:  two based on the {@code groupOfNames} and
 * {@code groupOfEntries} object classes, which store the member list in
 * the {@code member} attribute, and one based on the
 * {@code groupOfUniqueNames} object class, which stores the member list
 * in the {@code uniqueMember} attribute.
 */
public class StaticGroup
       extends Group<StaticGroupImplementationCfg>
@@ -95,7 +98,7 @@
  private DN groupEntryDN;
  // The set of the DNs of the members for this group.
  private LinkedHashSet<DN> memberDNs;
  private LinkedHashSet<ByteString> memberDNs;
  //The list of nested group DNs for this group.
  private LinkedList<DN> nestedGroups = new LinkedList<DN>();
@@ -132,7 +135,7 @@
   *                              group.
   */
  public StaticGroup(DN groupEntryDN, AttributeType memberAttributeType,
                     LinkedHashSet<DN> memberDNs)
                     LinkedHashSet<ByteString> memberDNs)
  {
    super();
@@ -170,9 +173,9 @@
    ensureNotNull(groupEntry);
    // Determine whether it is a groupOfNames or groupOfUniqueNames entry.  If
    // neither, then that's a problem.
    AttributeType memberAttributeType;
    // Determine whether it is a groupOfNames, groupOfEntries or
    // groupOfUniqueNames entry.  If not, then that's a problem.
    AttributeType someMemberAttributeType;
    ObjectClass groupOfEntriesClass =
         DirectoryConfig.getObjectClass(OC_GROUP_OF_ENTRIES_LC, true);
    ObjectClass groupOfNamesClass =
@@ -196,7 +199,8 @@
        throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message);
      }
      memberAttributeType = DirectoryConfig.getAttributeType(ATTR_MEMBER, true);
      someMemberAttributeType = DirectoryConfig
              .getAttributeType(ATTR_MEMBER, true);
    }
    else if (groupEntry.hasObjectClass(groupOfNamesClass))
    {
@@ -208,11 +212,12 @@
        throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message);
      }
      memberAttributeType = DirectoryConfig.getAttributeType(ATTR_MEMBER, true);
      someMemberAttributeType = DirectoryConfig
              .getAttributeType(ATTR_MEMBER, true);
    }
    else if (groupEntry.hasObjectClass(groupOfUniqueNamesClass))
    {
      memberAttributeType =
      someMemberAttributeType =
           DirectoryConfig.getAttributeType(ATTR_UNIQUE_MEMBER_LC, true);
    }
    else
@@ -223,10 +228,19 @@
      throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message);
    }
    LinkedHashSet<DN> memberDNs = new LinkedHashSet<DN>();
    List<Attribute> memberAttrList =
         groupEntry.getAttribute(memberAttributeType);
         groupEntry.getAttribute(someMemberAttributeType);
    int membersCount = 0;
    if (memberAttrList != null)
    {
      for (Attribute a : memberAttrList)
      {
        membersCount += a.size();
      }
    }
    LinkedHashSet<ByteString> someMemberDNs =
            new LinkedHashSet<ByteString>(membersCount);
    if (memberAttrList != null)
    {
      for (Attribute a : memberAttrList)
@@ -235,8 +249,7 @@
        {
          try
          {
            DN memberDN = DN.decode(v.getValue());
            memberDNs.add(memberDN);
            someMemberDNs.add(v.getNormalizedValue());
          }
          catch (DirectoryException de)
          {
@@ -246,7 +259,8 @@
            }
            Message message = ERR_STATICGROUP_CANNOT_DECODE_MEMBER_VALUE_AS_DN.
                get(v.getValue().toString(), memberAttributeType.getNameOrOID(),
                get(v.getValue().toString(),
                    someMemberAttributeType.getNameOrOID(),
                    String.valueOf(groupEntry.getDN()), de.getMessageObject());
            ErrorLogger.logError(message);
          }
@@ -255,7 +269,8 @@
    }
    return new StaticGroup(groupEntry.getDN(), memberAttributeType, memberDNs);
    return new StaticGroup(groupEntry.getDN(),
            someMemberAttributeType, someMemberDNs);
  }
@@ -433,8 +448,9 @@
      newNestedGroups.add(nestedGroupDN);
      nestedGroups = newNestedGroups;
      //Add it to the member DN list.
      LinkedHashSet<DN> newMemberDNs = new LinkedHashSet<DN>(memberDNs);
      newMemberDNs.add(nestedGroupDN);
      LinkedHashSet<ByteString> newMemberDNs =
              new LinkedHashSet<ByteString>(memberDNs);
      newMemberDNs.add(ByteString.valueOf(nestedGroupDN.toNormalizedString()));
      memberDNs = newMemberDNs;
    }
  }
@@ -493,8 +509,10 @@
      newNestedGroups.remove(nestedGroupDN);
      nestedGroups = newNestedGroups;
      //Remove it from the member DN list.
      LinkedHashSet<DN> newMemberDNs = new LinkedHashSet<DN>(memberDNs);
      newMemberDNs.remove(nestedGroupDN);
      LinkedHashSet<ByteString> newMemberDNs =
              new LinkedHashSet<ByteString>(memberDNs);
      newMemberDNs.remove(
              ByteString.valueOf(nestedGroupDN.toNormalizedString()));
      memberDNs = newMemberDNs;
    }
  }
@@ -509,7 +527,8 @@
          throws DirectoryException
  {
    reloadIfNeeded();
    if(memberDNs.contains(userDN))
    ByteString userDNString = ByteString.valueOf(userDN.toNormalizedString());
    if(memberDNs.contains(userDNString))
    {
      return true;
    }
@@ -570,18 +589,21 @@
                  ERR_STATICGROUP_GROUP_INSTANCE_INVALID.get(
                    String.valueOf(groupEntryDN)));
        } else if(thisGroup != this) {
          LinkedHashSet<DN> newMemberDNs = new LinkedHashSet<DN>();
          LinkedHashSet<ByteString> newMemberDNs =
                  new LinkedHashSet<ByteString>();
          MemberList memberList=thisGroup.getMembers();
          while (memberList.hasMoreMembers()) {
            try {
              newMemberDNs.add(memberList.nextMemberDN());
              newMemberDNs.add(ByteString.valueOf(
                      memberList.nextMemberDN().toNormalizedString()));
            } catch (MembershipException ex) {}
          }
          memberDNs=newMemberDNs;
        }
        LinkedList<DN> newNestedGroups = new LinkedList<DN>();
        for(DN dn : memberDNs)
        for(ByteString dnString : memberDNs)
        {
          DN dn = DN.decode(dnString);
          Group gr=DirectoryServer.getGroupManager().getGroupInstance(dn);
          if(gr != null)
          {
@@ -654,7 +676,9 @@
    synchronized (this)
    {
      DN userDN = userEntry.getDN();
      if (memberDNs.contains(userDN))
      ByteString userDNString = ByteString.valueOf(userDN.toNormalizedString());
      if (memberDNs.contains(userDNString))
      {
        Message message = ERR_STATICGROUP_ADD_MEMBER_ALREADY_EXISTS.get(
            String.valueOf(userDN), String.valueOf(groupEntryDN));
@@ -687,10 +711,10 @@
      }
      LinkedHashSet<DN> newMemberDNs =
           new LinkedHashSet<DN>(memberDNs.size()+1);
      LinkedHashSet<ByteString> newMemberDNs =
           new LinkedHashSet<ByteString>(memberDNs.size()+1);
      newMemberDNs.addAll(memberDNs);
      newMemberDNs.add(userDN);
      newMemberDNs.add(userDNString);
      memberDNs = newMemberDNs;
    }
  }
@@ -706,9 +730,10 @@
  {
    ensureNotNull(userDN);
    ByteString userDNString = ByteString.valueOf(userDN.toNormalizedString());
    synchronized (this)
    {
      if (! memberDNs.contains(userDN))
      if (! memberDNs.contains(userDNString))
      {
        Message message = ERR_STATICGROUP_REMOVE_MEMBER_NO_SUCH_MEMBER.get(
            String.valueOf(userDN), String.valueOf(groupEntryDN));
@@ -741,8 +766,9 @@
      }
      LinkedHashSet<DN> newMemberDNs = new LinkedHashSet<DN>(memberDNs);
      newMemberDNs.remove(userDN);
      LinkedHashSet<ByteString> newMemberDNs =
              new LinkedHashSet<ByteString>(memberDNs);
      newMemberDNs.remove(userDNString);
      memberDNs = newMemberDNs;
      //If it is in the nested group list remove it.
      if(nestedGroups.contains(userDN)) {