@Nonnull
    private HashSet<String> getVisibleGroupNames(@Nonnull final String userGroup, @Nonnull final Set<String> visited) {
        HashSet<String> results = new HashSet<>();

        // Ensure that recursive calls won't cause duplicate (or cyclic) queries.
        if (!visited.add(userGroup)) {
            return results;
        }

        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = DbConnectionManager.getConnection();
            pstmt = con.prepareStatement(GROUPLIST_CONTAINERS);
            pstmt.setString(1, "%" + userGroup + "%");
            pstmt.setString(2, userGroup);
            rs = pstmt.executeQuery();
            while (rs.next()) {
                results.add(rs.getString(1));
            }

        } catch (SQLException sqle) {
            Log.error(sqle.getMessage(), sqle);
        } finally {
            DbConnectionManager.closeConnection(rs, pstmt, con);
        }

        if (SHARED_GROUP_RECURSIVE.getValue()) {
            for (final String result : results) {
                results.addAll(getVisibleGroupNames(result, visited));
            }
        }
        return results;
    }
Checks if any shared groups exists. No distinction is made between the type of shared group: any group that is
shared (with anything other than 'nobody') qualifies.

@return true if at least one shared group exists, otherwise false.
xmppserver/src/main/java/org/jivesoftware/openfire/group/AbstractGroupProvider.java