@Override
    public Collection<String> getGroupNames(JID user) {
        // Get DN of specified user
        XMPPServer server = XMPPServer.getInstance();
        String username;
        if (!manager.isPosixMode()) {
            // Check if the user exists (only if user is a local user)
            if (!server.isLocal(user)) {
                return Collections.emptyList();
            }
            username = JID.unescapeNode(user.getNode());
            try {
                final String relativePart =
                    Arrays.stream(manager.findUserRDN(username))
                    .map(Rdn::toString)
                    .collect(Collectors.joining(","));

                username = relativePart + "," + manager.getUsersBaseDN(username);
            }
            catch (Exception e) {
                Log.debug("Unable to find groups for a user that was not recognized in LDAP: {}", username);
                return Collections.emptyList();
            }
        }
        else {
            username = server.isLocal(user) ? JID.unescapeNode(user.getNode()) : user.toBareJID();
        }
        // Do nothing if the user is empty or null
        if (username == null || username.isEmpty()) {
            return Collections.emptyList();
        }

        Set<String> groupNames = new LinkedHashSet<>(search(manager.getGroupMemberField(), username));

        if (manager.isFlattenNestedGroups()) {
            // search groups that contain the given groups

            Set<String> checkedGroups = new HashSet<>();
            Deque<String> todo = new ArrayDeque<>(groupNames);
            String group;
            while (null != (group = todo.pollFirst())) {
                if (checkedGroups.contains(group)) {
                    continue;
                }
                checkedGroups.add(group);
                try {
                    // get the DN of the group
                    LdapName groupDN = manager.findGroupAbsoluteDN(group);
                    if(manager.isPosixMode()){
                        // in posix mode we need to search for the "uid" of the group.
                        List<String> uids = manager.retrieveAttributeOf(manager.getUsernameField(), groupDN);
                        if(uids.isEmpty()) {
                            // group not there or has not the "uid" attribute
                            continue;
                        }
                        group = uids.get(0);
                    } else {
                        group = groupDN.toString();
                    }
                    // search for groups that have the given group (DN normal, UID posix) as member
                    Collection<String> containingGroupNames = search(manager.getGroupMemberField(), group);
                    // add the found groups to the result and to the groups to be checked transitively
                    todo.addAll(containingGroupNames);
                    groupNames.addAll(containingGroupNames);
                }
                catch (Exception e) {
                    Log.warn("Error looking up group: {}", group);
                }
            }
        }
        return groupNames;
    }
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