ldap/src/main/java/org/springframework/security/ldap/SpringSecurityLdapTemplate.java
public Set<Map<String, List<String>>> searchForMultipleAttributeValues(
			final String base, final String filter, final Object[] params,
			final String[] attributeNames) {
		// Escape the params acording to RFC2254
		Object[] encodedParams = new String[params.length];

		for (int i = 0; i < params.length; i++) {
			encodedParams[i] = LdapEncoder.filterEncode(params[i].toString());
		}

		String formattedFilter = MessageFormat.format(filter, encodedParams);
		logger.debug("Using filter: " + formattedFilter);

		final HashSet<Map<String, List<String>>> set = new HashSet<Map<String, List<String>>>();

		ContextMapper roleMapper = new ContextMapper() {
			public Object mapFromContext(Object ctx) {
				DirContextAdapter adapter = (DirContextAdapter) ctx;
				Map<String, List<String>> record = new HashMap<String, List<String>>();
				if (attributeNames == null || attributeNames.length == 0) {
					try {
						for (NamingEnumeration ae = adapter.getAttributes().getAll(); ae
								.hasMore();) {
							Attribute attr = (Attribute) ae.next();
							extractStringAttributeValues(adapter, record, attr.getID());
						}
					}
					catch (NamingException x) {
						org.springframework.ldap.support.LdapUtils
								.convertLdapException(x);
					}
				}
				else {
					for (String attributeName : attributeNames) {
						extractStringAttributeValues(adapter, record, attributeName);
					}
				}
				record.put(DN_KEY, Arrays.asList(getAdapterDN(adapter)));
				set.add(record);
				return null;
			}
		};

		SearchControls ctls = new SearchControls();
		ctls.setSearchScope(searchControls.getSearchScope());
		ctls.setReturningAttributes(attributeNames != null && attributeNames.length > 0 ? attributeNames
				: null);

		search(base, formattedFilter, ctls, roleMapper);

		return set;
	}
public Set<Map<String, List<String>>> searchForMultipleAttributeValues(
			final String base, final String filter, final Object[] params,
			final String[] attributeNames) {
		// Escape the params acording to RFC2254
		Object[] encodedParams = new String[params.length];

		for (int i = 0; i < params.length; i++) {
			encodedParams[i] = LdapEncoder.filterEncode(params[i].toString());
		}

		String formattedFilter = MessageFormat.format(filter, encodedParams);
		logger.debug("Using filter: " + formattedFilter);

		final HashSet<Map<String, List<String>>> set = new HashSet<Map<String, List<String>>>();

		ContextMapper roleMapper = new ContextMapper() {
			public Object mapFromContext(Object ctx) {
				DirContextAdapter adapter = (DirContextAdapter) ctx;
				Map<String, List<String>> record = new HashMap<String, List<String>>();
				if (attributeNames == null || attributeNames.length == 0) {
					try {
						for (NamingEnumeration ae = adapter.getAttributes().getAll(); ae
								.hasMore();) {
							Attribute attr = (Attribute) ae.next();
							extractStringAttributeValues(adapter, record, attr.getID());
						}
					}
					catch (NamingException x) {
						org.springframework.ldap.support.LdapUtils
								.convertLdapException(x);
					}
				}
				else {
					for (String attributeName : attributeNames) {
						extractStringAttributeValues(adapter, record, attributeName);
					}
				}
				record.put(DN_KEY, Arrays.asList(getAdapterDN(adapter)));
				set.add(record);
				return null;
			}
		};

		SearchControls ctls = new SearchControls();
		ctls.setSearchScope(searchControls.getSearchScope());
		ctls.setReturningAttributes(attributeNames != null && attributeNames.length > 0 ? attributeNames
				: null);

		search(base, formattedFilter, ctls, roleMapper);

		return set;
	}
Performs a search using the supplied filter and returns the values of each named
attribute found in all entries matched by the search. Note that one directory entry
may have several values for the attribute. Intended for role searches and similar
scenarios.

@param base the DN to search in
@param filter search filter to use
@param params the parameters to substitute in the search filter
@param attributeNames the attributes' values that are to be retrieved.

@return the set of String values for each attribute found in all the matching
entries. The attribute name is the key for each set of values. In addition each map
contains the DN as a String with the key predefined key {@link #DN_KEY}.