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

Ludovic Poitou
07.25.2014 bc11734a34d63204bfcc6e9087e0664a9772fae3
Port to the DJ3 dev branch the fix for OPENDJ-1586 - Nested Groups fail to return indirect members with db's larger than 10 entries.
2 files modified
98 ■■■■ changed files
opendj3-server-dev/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProvider.java 82 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java 16 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProvider.java
@@ -26,7 +26,9 @@
 */
package org.opends.server.extensions;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
@@ -248,32 +250,32 @@
  public void processSearch(VirtualAttributeRule rule,
                            SearchOperation searchOperation)
  {
    SearchFilter filter = searchOperation.getFilter();
    Group<?> group = extractGroup(rule.getAttributeType(), filter);
    Group<?> group = extractGroup(rule.getAttributeType(), searchOperation.getFilter());
    if (group == null)
    {
      return;
    }
    DN          baseDN = searchOperation.getBaseDN();
    SearchScope scope  = searchOperation.getScope();
    try
    {
      MemberList  memberList = group.getMembers();
      while (memberList.hasMoreMembers())
      // Check for nested groups to see if we need to keep track of returned entries
      List<DN> nestedGroupsDNs = group.getNestedGroupDNs();
      HashSet<String> returnedDNs = null;
      if (!nestedGroupsDNs.isEmpty())
      {
        try
        returnedDNs = new HashSet<String>();
      }
      if (!returnGroupMembers(searchOperation, group.getMembers(), returnedDNs))
      {
        return;
      }
      // Now check members of nested groups
      for (DN dn : nestedGroupsDNs)
      {
        group = DirectoryServer.getGroupManager().getGroupInstance(dn);
        if (!returnGroupMembers(searchOperation, group.getMembers(), returnedDNs))
        {
          Entry e = memberList.nextMemberEntry();
          if (e.matchesBaseAndScope(baseDN, scope) &&
              filter.matchesEntry(e))
          {
            searchOperation.returnEntry(e, null);
          }
        }
        catch (Exception e)
        {
          logger.traceException(e);
          return;
        }
      }
    }
@@ -283,6 +285,52 @@
    }
  }
  /**
   *
   * @param searchOperation the search operation being processed.
   * @param memberList the list of members of the group being processed.
   * @param returnedDNs a set to store the DNs of entries already returned,
   *                    null if there's no need to track for entries.
   * @return  <CODE>true</CODE> if the caller should continue processing the
   *          search request and sending additional entries and references, or
   *          <CODE>false</CODE> if not for some reason (e.g., the size limit
   *          has been reached or the search has been abandoned).
   * @throws DirectoryException If a problem occurs while attempting to send
   *          the entry to the client and the search should be terminated.
   */
  private boolean returnGroupMembers(SearchOperation searchOperation,
                                  MemberList memberList, Set<String> returnedDNs)
          throws DirectoryException
  {
    DN baseDN = searchOperation.getBaseDN();
    SearchScope scope  = searchOperation.getScope();
    SearchFilter filter = searchOperation.getFilter();
    while (memberList.hasMoreMembers())
    {
      try
      {
        Entry e = memberList.nextMemberEntry();
        if (e.matchesBaseAndScope(baseDN, scope) &&
            filter.matchesEntry(e))
        {
          if (returnedDNs == null
              || returnedDNs.add(e.getName().toNormalizedString()))
          {
            if (!searchOperation.returnEntry(e, null))
            {
              return false;
            }
          }
        }
      }
      catch (Exception e)
      {
        logger.traceException(e);
      }
    }
    return true;
  }
  /**
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java
@@ -942,28 +942,30 @@
    builder.append("\nobjectClass: domain");
    builder.append("\ndc: example");
    builder.append("\n\ndn: ou=People"+SUFFIX);
    builder.append("\n\ndn: ou=People").append(SUFFIX);
    builder.append("\nobjectClass: organizationalunit");
    builder.append("\nou: People");
    //Go beyond ALL ID threshold.
    for(int i=0;i<4001;i++)
    {
      builder.append("\n\ndn: cn=user." + i + ",ou=People"+SUFFIX);
      builder.append("\n\ndn: cn=user.").append(i)
             .append(",ou=People").append(SUFFIX);
      builder.append("\nobjectclass: person");
      builder.append("\ncn: user." + i);
      builder.append("\nsn: " + i);
      builder.append("\ncn: user.").append(i);
      builder.append("\nsn: ").append(i);
    }
    //Add the group information.
    builder.append("\n\ndn: ou=Groups"+SUFFIX);
    builder.append("\n\ndn: ou=Groups").append(SUFFIX);
    builder.append("\nobjectclass: organizationalunit");
    builder.append("\nou: Groups");
    //Dynamic group.
    builder.append("\n\ndn: cn=MyDGrp,ou=Groups"+SUFFIX);
    builder.append("\n\ndn: cn=MyDGrp,ou=Groups").append(SUFFIX);
    builder.append("\nobjectClass: groupOfURLs");
    builder.append("\ncn: MyDGrp");
    builder.append("\nmemberURL: ldap:///ou=people"+SUFFIX+"??sub?(objectclass=person)");
    builder.append("\nmemberURL: ldap:///ou=people").append(SUFFIX)
           .append("??sub?(objectclass=person)");
    TestCaseUtils.addEntries(builder.toString());
    //Verify the entry.
    Entry e =