@Override
    public Collection<String> search(String query, int startIndex, int numResults) {
        if (query == null || query.isEmpty()) {
            return Collections.emptyList();
        }
        StringBuilder filter = new StringBuilder();
        // Make the query be a wildcard search by default. So, if the user searches for
        // "Test", make the sanitized search be "Test*" instead.
        filter.append('(').append(manager.getGroupNameField()).append('=')
                .append(LdapManager.sanitizeSearchFilter(query, false)).append("*)");
        // Perform the LDAP query
        return manager.retrieveList(
                manager.getGroupNameField(),
                filter.toString(),
                startIndex,
                numResults,
                null
        );
    }
Reads the group with the given DN

@param groupDN         the absolute DN of the group
@param membersToIgnore A mutable set of DNs and/or UIDs (for Posix mode) to ignore. This set will be
                       filled with visited DNs. If flatten of hierarchies of groups is active
                       ({@link LdapManager#isFlattenNestedGroups()}, this will prevent endless loops
                       for cyclic hierarchies.
@return A group (never null)
@throws NamingException When a group can't be read from LDAP.
xmppserver/src/main/java/org/jivesoftware/openfire/ldap/LdapGroupProvider.java