@Override
    public Collection<User> findUsers(Set<String> fields, String query, int startIndex,
            int numResults) throws UnsupportedOperationException
    {
        if (fields.isEmpty() || query == null || query.isEmpty()) {
            return Collections.emptyList();
        }
        
        query = LdapManager.sanitizeSearchFilter(query, true);
        
        // Make the query be a wildcard search by default. So, if the user searches for
        // "John", make the search be "John*" instead.
        if (!query.endsWith("*")) {
            query = query + "*";
        }

        if (!searchFields.keySet().containsAll(fields)) {
            throw new IllegalArgumentException("Search fields " + fields + " are not valid.");
        }
        StringBuilder filter = new StringBuilder();
        //Add the global search filter so only those users the directory administrator wants to include
        //are returned from the directory
        filter.append("(&(");
        filter.append(MessageFormat.format(manager.getSearchFilter(),"*"));
        filter.append(')');
        if (fields.size() > 1) {
            filter.append("(|");
        }
        for (String field:fields) {
            String attribute = searchFields.get(field);
            filter.append('(').append(attribute).append('=')
                .append( query ).append(")");
        }
        if (fields.size() > 1) {
            filter.append(')');
        }
        filter.append(')');
        List<String> userlist = manager.retrieveList(
                manager.getUsernameField(),
                filter.toString(),
                startIndex,
                numResults,
                manager.getUsernameSuffix(),
                true
        );
        if (manager.isFindUsersFromGroupsEnabled()) {
            userlist = userlist.stream()
                .filter(user ->
                    !GroupManager.getInstance().getGroups(
                        XMPPServer.getInstance().createJID(user, null))
                    .isEmpty())
                .collect(Collectors.toList());
        }
        return new UserCollection(userlist.toArray(new String[userlist.size()]));
    }
LDAP implementation of the UserProvider interface. All data in the directory is
treated as read-only so any set operations will result in an exception.

@author Matt Tucker
xmppserver/src/main/java/org/jivesoftware/openfire/ldap/LdapUserProvider.java