diff --git a/core-tiger/src/main/java/org/springframework/ldap/core/simple/SimpleLdapOperations.java b/core-tiger/src/main/java/org/springframework/ldap/core/simple/SimpleLdapOperations.java index a24ad7f5..9f3e9c75 100644 --- a/core-tiger/src/main/java/org/springframework/ldap/core/simple/SimpleLdapOperations.java +++ b/core-tiger/src/main/java/org/springframework/ldap/core/simple/SimpleLdapOperations.java @@ -22,6 +22,7 @@ import javax.naming.directory.Attributes; import javax.naming.directory.SearchControls; import org.springframework.ldap.NamingException; +import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DirContextProcessor; import org.springframework.ldap.core.LdapOperations; @@ -131,6 +132,36 @@ public interface SimpleLdapOperations { */ T lookup(Name dn, ParameterizedContextMapper mapper); + /** + * Perform a search for a unique entry matching the specified search + * criteria and return the found object. If no entry is found or if there + * are more than one matching entry, an + * {@link IncorrectResultSizeDataAccessException} is thrown. + * @param base the DN to use as the base of the search. + * @param filter the search filter. + * @param mapper the mapper to use for the search. + * @return the single object returned by the mapper that matches the search + * criteria. + * @throws IncorrectResultSizeDataAccessException if the result is not one unique entry + * @since 1.3 + */ + T searchForObject(String base, String filter, ParameterizedContextMapper mapper); + + /** + * Perform a search for a unique entry matching the specified search + * criteria and return the found object. If no entry is found or if there + * are more than one matching entry, an + * {@link IncorrectResultSizeDataAccessException} is thrown. + * @param base the DN to use as the base of the search. + * @param filter the search filter. + * @param mapper the mapper to use for the search. + * @return the single object returned by the mapper that matches the search + * criteria. + * @throws IncorrectResultSizeDataAccessException if the result is not one unique entry + * @since 1.3 + */ + T searchForObject(Name base, String filter, ParameterizedContextMapper mapper); + /** * Look up the specified DN, and automatically cast it to a * {@link DirContextOperations} instance. @@ -232,4 +263,52 @@ public interface SimpleLdapOperations { * @throws NamingException if any error occurs. */ void modifyAttributes(DirContextOperations ctx); + + /** + * Utility method to perform a simple LDAP 'bind' authentication. Search for + * the LDAP entry to authenticate using the supplied base DN and filter; use + * the DN of the found entry together with the password as input to + * {@link ContextSource#getContext(String, String)}, thus authenticating the + * entry. + *

+ * Example:
+ * + *

+	 * AndFilter filter = new AndFilter();
+	 * filter.and("objectclass", "person").and("uid", userId);
+	 * boolean authenticated = ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), password);
+	 * 
+ * + * @param base the DN to use as the base of the search. + * @param filter the search filter - must result in a unique result. + * @param password the password to use for authentication. + * @return true if the authentication was successful, + * false otherwise. + * @since 1.3 + */ + boolean authenticate(String base, String filter, String password); + + /** + * Utility method to perform a simple LDAP 'bind' authentication. Search for + * the LDAP entry to authenticate using the supplied base DN and filter; use + * the DN of the found entry together with the password as input to + * {@link ContextSource#getContext(String, String)}, thus authenticating the + * entry. + *

+ * Example:
+ * + *

+	 * AndFilter filter = new AndFilter();
+	 * filter.and("objectclass", "person").and("uid", userId);
+	 * boolean authenticated = ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), password);
+	 * 
+ * + * @param base the DN to use as the base of the search. + * @param filter the search filter - must result in a unique result. + * @param password the password to use for authentication. + * @return true if the authentication was successful, + * false otherwise. + * @since 1.3 + */ + boolean authenticate(Name base, String filter, String password); } diff --git a/core-tiger/src/main/java/org/springframework/ldap/core/simple/SimpleLdapTemplate.java b/core-tiger/src/main/java/org/springframework/ldap/core/simple/SimpleLdapTemplate.java index 2546253e..7a62b5c0 100644 --- a/core-tiger/src/main/java/org/springframework/ldap/core/simple/SimpleLdapTemplate.java +++ b/core-tiger/src/main/java/org/springframework/ldap/core/simple/SimpleLdapTemplate.java @@ -239,4 +239,52 @@ public class SimpleLdapTemplate implements SimpleLdapOperations { public void bind(DirContextOperations ctx) { ldapOperations.bind(ctx); } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.simple.SimpleLdapOperations#searchForObject + * (java.lang.String, java.lang.String, + * org.springframework.ldap.core.simple.ParameterizedContextMapper) + */ + @SuppressWarnings("unchecked") + public T searchForObject(String base, String filter, ParameterizedContextMapper mapper) { + return (T) ldapOperations.searchForObject(base, filter, mapper); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.simple.SimpleLdapOperations#searchForObject + * (javax.naming.Name, java.lang.String, + * org.springframework.ldap.core.simple.ParameterizedContextMapper) + */ + @SuppressWarnings("unchecked") + public T searchForObject(Name base, String filter, ParameterizedContextMapper mapper) { + return (T) ldapOperations.searchForObject(base, filter, mapper); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.simple.SimpleLdapOperations#authenticate + * (java.lang.String, java.lang.String, java.lang.String) + */ + public boolean authenticate(String base, String filter, String password) { + return ldapOperations.authenticate(base, filter, password); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.simple.SimpleLdapOperations#authenticate + * (javax.naming.Name, java.lang.String, java.lang.String) + */ + public boolean authenticate(Name base, String filter, String password) { + return ldapOperations.authenticate(base, filter, password); + } } diff --git a/core/src/main/java/org/springframework/ldap/core/AuthenticatedLdapEntryContextCallback.java b/core/src/main/java/org/springframework/ldap/core/AuthenticatedLdapEntryContextCallback.java new file mode 100644 index 00000000..61275e6e --- /dev/null +++ b/core/src/main/java/org/springframework/ldap/core/AuthenticatedLdapEntryContextCallback.java @@ -0,0 +1,40 @@ +/* + * Copyright 2005-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.core; + +import javax.naming.directory.DirContext; + +/** + * Callback interface to be used in the authentication methods in + * {@link LdapOperations} for performing operations on individually + * authenticated contexts. + * + * @author Mattias Hellborg Arthursson + * @since 1.3 + */ +public interface AuthenticatedLdapEntryContextCallback { + /** + * Perform some LDAP operation on the supplied authenticated + * DirContext instance. The target context will be + * automatically closed. + * + * @param ctx the DirContext instance to perform an operation + * on. + * @param ldapEntryIdentification the identification of the LDAP entry used + * to authenticate the supplied DirContext. + */ + void executeWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification); +} diff --git a/core/src/main/java/org/springframework/ldap/core/LdapEntryIdentification.java b/core/src/main/java/org/springframework/ldap/core/LdapEntryIdentification.java new file mode 100644 index 00000000..7651340b --- /dev/null +++ b/core/src/main/java/org/springframework/ldap/core/LdapEntryIdentification.java @@ -0,0 +1,87 @@ +/* + * Copyright 2005-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.core; + +import javax.naming.directory.DirContext; + +import org.springframework.util.Assert; + +/** + * Wrapper class to handle the full identification of an LDAP entry. An LDAP + * entry is identified by its Distinguished Name, in Spring LDAP represented by + * the {@link DistinguishedName} class. A Distinguished Name can be absolute - + * i.e. complete including the very root (base) of the LDAP tree - or relative - + * i.e relative to the base LDAP path of the current LDAP connection (specified + * as base to the {@link ContextSource}). + *

+ * The different representations are needed on different occasions, e.g. the + * relative DN is typically what is needed to perform lookups and searches in + * the LDAP tree, whereas the absolute DN is needed when authenticating and when + * an LDAP entry is referred to in e.g. a group. This wrapper class contains + * both of these representations. + * + * @author Mattias Hellborg Arthursson + */ +public class LdapEntryIdentification { + private final DistinguishedName relativeDn; + + private final DistinguishedName absoluteDn; + + /** + * Construct an LdapEntryIdentification instance. + * @param absoluteDn the absolute DN of the identified entry, e.g. as + * returned by {@link DirContext#getNameInNamespace()}. + * @param relativeDn the DN of the identified entry relative to the base + * LDAP path, e.g. as returned by {@link DirContextOperations#getDn()}. + */ + public LdapEntryIdentification(DistinguishedName absoluteDn, DistinguishedName relativeDn) { + Assert.notNull(absoluteDn, "Absolute DN must not be null"); + Assert.notNull(relativeDn, "Relative DN must not be null"); + this.absoluteDn = absoluteDn.immutableDistinguishedName(); + this.relativeDn = relativeDn.immutableDistinguishedName(); + } + + /** + * Get the DN of the identified entry relative to the base LDAP path, e.g. + * as returned by {@link DirContextOperations#getDn()}. + * @return the relative DN. + */ + public DistinguishedName getRelativeDn() { + return relativeDn; + } + + /** + * Get the absolute DN of the identified entry, e.g. as returned by + * {@link DirContext#getNameInNamespace()}. + * @return the absolute DN. + */ + public DistinguishedName getAbsoluteDn() { + return absoluteDn; + } + + public boolean equals(Object obj) { + if (obj != null && obj.getClass().equals(this.getClass())) { + LdapEntryIdentification that = (LdapEntryIdentification) obj; + return this.absoluteDn.equals(that.absoluteDn) && this.relativeDn.equals(that.relativeDn); + } + + return false; + } + + public int hashCode() { + return absoluteDn.hashCode() ^ relativeDn.hashCode(); + } +} diff --git a/core/src/main/java/org/springframework/ldap/core/LdapOperations.java b/core/src/main/java/org/springframework/ldap/core/LdapOperations.java index 9a5e6062..43d993a5 100644 --- a/core/src/main/java/org/springframework/ldap/core/LdapOperations.java +++ b/core/src/main/java/org/springframework/ldap/core/LdapOperations.java @@ -25,6 +25,8 @@ import javax.naming.directory.Attributes; import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; +import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.ldap.AuthenticationException; import org.springframework.ldap.ContextNotEmptyException; import org.springframework.ldap.NamingException; import org.springframework.ldap.core.support.AbstractContextSource; @@ -39,1548 +41,1234 @@ import org.springframework.ldap.support.LdapUtils; * @author Ulrik Sandberg */ public interface LdapOperations { - /** - * Perform a search using a particular {@link SearchExecutor} and context - * processor. Use this method only if especially needed - for the most cases - * there is an overloaded convenience method which calls this one with - * suitable argments. This method handles all the plumbing; getting a - * readonly context; looping through the NamingEnumeration - * and closing the context and enumeration. The actual search is delegated - * to the SearchExecutor and each found NameClassPair is - * passed to the CallbackHandler. Any encountered - * NamingException will be translated using - * {@link LdapUtils#convertLdapException(javax.naming.NamingException)}. - * - * @param se - * The SearchExecutor to use for performing the - * actual search. - * @param handler - * The NameClassPairCallbackHandler to which each - * found entry will be passed. - * @param processor - * DirContextProcessor for custom pre- and - * post-processing. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted as no entries being found. - */ - void search(SearchExecutor se, NameClassPairCallbackHandler handler, - DirContextProcessor processor) throws NamingException; - - /** - * Perform a search using a particular {@link SearchExecutor}. Use this - * method only if especially needed - for the most cases there is an - * overloaded convenience method which calls this one with suitable - * argments. This method handles all the plumbing; getting a readonly - * context; looping through the NamingEnumeration and closing - * the context and enumeration. The actual search is delegated to the - * SearchExecutor and each found NameClassPair - * is passed to the CallbackHandler. Any encountered - * NamingException will be translated using the - * {@link LdapUtils#convertLdapException(javax.naming.NamingException)}. - * - * @param se - * The SearchExecutor to use for performing the - * actual search. - * @param handler - * The NameClassPairCallbackHandler to which each - * found entry will be passed. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted as no entries being found. - * @see #search(Name, String, AttributesMapper) - * @see #search(Name, String, ContextMapper) - */ - void search(SearchExecutor se, NameClassPairCallbackHandler handler) - throws NamingException; - - /** - * Perform an operation (or series of operations) on a read-only context. - * This method handles the plumbing - getting a DirContext, - * translating any Exceptions and closing the context afterwards. This - * method is not intended for searches; use - * {@link #search(SearchExecutor, NameClassPairCallbackHandler)} or any of - * the overloaded search methods for this. - * - * @param ce - * The ContextExecutor to which the actual - * operation on the DirContext will be delegated. - * @return the result from the ContextExecutor's operation. - * @throws NamingException - * if the operation resulted in a NamingException. - * - * @see #search(SearchExecutor, NameClassPairCallbackHandler) - * @see #search(Name, String, AttributesMapper) - * @see #search(Name, String, ContextMapper) - */ - Object executeReadOnly(ContextExecutor ce) throws NamingException; - - /** - * Perform an operation (or series of operations) on a read-write context. - * This method handles the plumbing - getting a DirContext, - * translating any exceptions and closing the context afterwards. This - * method is intended only for very particular cases, where there is no - * suitable method in this interface to use. - * - * @param ce - * The ContextExecutor to which the actual - * operation on the DirContext will be delegated. - * @return the result from the ContextExecutor's operation. - * @throws NamingException - * if the operation resulted in a NamingException. - * @see #bind(Name, Object, Attributes) - * @see #unbind(Name) - * @see #rebind(Name, Object, Attributes) - * @see #rename(Name, Name) - * @see #modifyAttributes(Name, ModificationItem[]) - */ - Object executeReadWrite(ContextExecutor ce) throws NamingException; - - /** - * Search for all objects matching the supplied filter. Each - * SearchResult is supplied to the specified - * NameClassPairCallbackHandler. The - * SearchScope specified in the supplied - * SearchControls will be used in the search. Note that if - * you are using a ContextMapper, the returningObjFlag needs - * to be set to true in the SearchControls. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. - * @param handler - * The NameClassPairCallbackHandler to supply the - * SearchResult to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void search(Name base, String filter, SearchControls controls, - NameClassPairCallbackHandler handler) throws NamingException; - - /** - * Search for all objects matching the supplied filter. See - * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler)} - * for details. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. - * @param handler - * The NameClassPairCallbackHandler to supply the - * SearchResult to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void search(String base, String filter, SearchControls controls, - NameClassPairCallbackHandler handler) throws NamingException; - - /** - * Search for all objects matching the supplied filter. Each - * SearchResult is supplied to the specified - * NameClassPairCallbackHandler. The - * SearchScope specified in the supplied - * SearchControls will be used in the search. Note that if - * you are using a ContextMapper, the returningObjFlag needs - * to be set to true in the SearchControls. The given - * DirContextProcessor will be called before and after the - * search. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. - * @param handler - * The NameClassPairCallbackHandler to supply the - * SearchResult to. - * @param processor - * The DirContextProcessor to use before and after - * the search. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void search(Name base, String filter, SearchControls controls, - NameClassPairCallbackHandler handler, DirContextProcessor processor) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Attributes in - * each SearchResult is supplied to the specified - * AttributesMapper. The SearchScope - * specified in the supplied SearchControls will be used in - * the search. The given DirContextProcessor will be called - * before and after the search. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @param processor - * The DirContextProcessor to use before and after - * the search. - * @return a List containing all entries received from the - * AttributesMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, SearchControls controls, - AttributesMapper mapper, DirContextProcessor processor) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Attributes in - * each SearchResult is supplied to the specified - * AttributesMapper. The SearchScope - * specified in the supplied SearchControls will be used in - * the search. The given DirContextProcessor will be called - * before and after the search. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @param processor - * The DirContextProcessor to use before and after - * the search. - * @return a List containing all entries received from the - * AttributesMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, SearchControls controls, - AttributesMapper mapper, DirContextProcessor processor) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Object returned - * in each SearchResult is supplied to the specified - * ContextMapper. The SearchScope specified - * in the supplied SearchControls will be used in the search. - * The given DirContextProcessor will be called before and - * after the search. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. If the - * returnObjFlag is not set in the SearchControls, - * this method will set it automatically, as this is required for - * the ContextMapper to work. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @param processor - * The DirContextProcessor to use before and after - * the search. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, SearchControls controls, - ContextMapper mapper, DirContextProcessor processor) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Object returned - * in each SearchResult is supplied to the specified - * ContextMapper. The SearchScope specified - * in the supplied SearchControls will be used in the search. - * The given DirContextProcessor will be called before and - * after the search. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. If the - * returnObjFlag is not set in the SearchControls, - * this method will set it automatically, as this is required for - * the ContextMapper to work. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @param processor - * The DirContextProcessor to use before and after - * the search. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, SearchControls controls, - ContextMapper mapper, DirContextProcessor processor) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. See - * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler, DirContextProcessor)} - * for details. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. - * @param handler - * The NameClassPairCallbackHandler to supply the - * SearchResults to. - * @param processor - * The DirContextProcessor to use before and after - * the search. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void search(String base, String filter, SearchControls controls, - NameClassPairCallbackHandler handler, DirContextProcessor processor) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. Each - * SearchResult is supplied to the specified - * NameClassPairCallbackHandler. Use the specified values - * for search scope and return objects flag. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param returningObjFlag - * Whether the bound object should be returned in search results. - * Must be set to true if a - * ContextMapper is used. - * @param handler - * The NameClassPairCallbackHandler to supply the - * SearchResults to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void search(Name base, String filter, int searchScope, - boolean returningObjFlag, NameClassPairCallbackHandler handler) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. Each - * SearchResult is supplied to the specified - * NameClassPairCallbackHandler. Use the specified values - * for search scope and return objects flag. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param returningObjFlag - * Whether the bound object should be returned in search results. - * Must be set to true if a - * ContextMapper is used. - * @param handler - * The NameClassPairCallbackHandler to supply the - * SearchResults to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void search(String base, String filter, int searchScope, - boolean returningObjFlag, NameClassPairCallbackHandler handler) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. Each - * SearchResult is supplied to the specified - * NameClassPairCallbackHandler. The default Search scope (SearchControls.SUBTREE_SCOPE) - * will be used and the returnObjects flag will be set to false. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param handler - * The NameClassPairCallbackHandler to supply the - * SearchResults to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void search(Name base, String filter, - NameClassPairCallbackHandler handler) throws NamingException; - - /** - * Search for all objects matching the supplied filter. Each - * SearchResult is supplied to the specified - * NameClassPairCallbackHandler. The default Search scope (SearchControls.SUBTREE_SCOPE) - * will be used and the returnObjects flag will be set to false. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param handler - * The NameClassPairCallbackHandler to supply the - * SearchResults to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void search(String base, String filter, - NameClassPairCallbackHandler handler) throws NamingException; - - /** - * Search for all objects matching the supplied filter. Only return any - * attributes mathing the specified attribute names. The Attributes in each - * SearchResult is supplied to the specified - * AttributesMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param attrs - * The attributes to return, null means returning - * all attributes. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @return a List containing all entries received from the - * AttributesMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, int searchScope, - String[] attrs, AttributesMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. Only return any - * attributes mathing the specified attribute names. The Attributes in each - * SearchResult is supplied to the specified - * AttributesMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param attrs - * The attributes to return, null means returning - * all attributes. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @return a List containing all entries received from the - * AttributesMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, int searchScope, - String[] attrs, AttributesMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Attributes in - * each SearchResult is supplied to the specified - * AttributesMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @return a List containing all entries received from the - * AttributesMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, int searchScope, - AttributesMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Attributes in - * each SearchResult is supplied to the specified - * AttributesMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @return a List containing all entries received from the - * AttributesMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, int searchScope, - AttributesMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Attributes in - * each SearchResult is supplied to the specified - * AttributesMapper. The default search scope will be used. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @return a List containing all entries received from the - * AttributesMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, AttributesMapper mapper) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Attributes in - * each SearchResult is supplied to the specified - * AttributesMapper. The default search scope will be used. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @return a List containing all entries received from the - * AttributesMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, AttributesMapper mapper) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. The - * Object returned in each SearchResult is - * supplied to the specified ContextMapper. Only return the - * supplied attributes. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param attrs - * The attributes to return, null means all - * attributes. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, int searchScope, - String[] attrs, ContextMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The - * Object returned in each SearchResult is - * supplied to the specified ContextMapper. Only return the - * supplied attributes. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param attrs - * The attributes to return, null means all - * attributes. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, int searchScope, - String[] attrs, ContextMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The - * Object returned in each SearchResult is - * supplied to the specified ContextMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, int searchScope, - ContextMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The - * Object returned in each SearchResult is - * supplied to the specified ContextMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param searchScope - * The search scope to set in SearchControls. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, int searchScope, - ContextMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The - * Object returned in each SearchResult is - * supplied to the specified ContextMapper. The default - * search scope (SearchControls.SUBTREE_SCOPE) will be - * used. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, ContextMapper mapper) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. The - * Object returned in each SearchResult is - * supplied to the specified ContextMapper. The default - * search scope (SearchControls.SUBTREE_SCOPE) will be - * used. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, ContextMapper mapper) - throws NamingException; - - /** - * Search for all objects matching the supplied filter. The - * Object returned in each SearchResult is - * supplied to the specified ContextMapper. The default - * search scope (SearchControls.SUBTREE_SCOPE) will be - * used. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, SearchControls controls, - ContextMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Object returned - * in each SearchResult is supplied to the specified - * ContextMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. If the - * returnObjFlag is not set in the SearchControls, - * this method will set it automatically, as this is required for - * the ContextMapper to work. - * @param mapper - * The ContextMapper to use for translating each - * entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, SearchControls controls, - ContextMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Attributes - * returned in each SearchResult is supplied to the specified - * AttributesMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(String base, String filter, SearchControls controls, - AttributesMapper mapper) throws NamingException; - - /** - * Search for all objects matching the supplied filter. The Attributes - * returned in each SearchResult is supplied to the specified - * AttributesMapper. - * - * @param base - * The base DN where the search should begin. - * @param filter - * The filter to use in the search. - * @param controls - * The SearchControls to use in the search. - * @param mapper - * The AttributesMapper to use for translating - * each entry. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List search(Name base, String filter, SearchControls controls, - AttributesMapper mapper) throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. Each resulting NameClassPair is - * supplied to the specified NameClassPairCallbackHandler. - * - * @param base - * The base DN where the list should be performed. - * @param handler - * The NameClassPairCallbackHandler to supply each - * {@link NameClassPair} to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void list(String base, NameClassPairCallbackHandler handler) - throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. Each resulting NameClassPair is - * supplied to the specified NameClassPairCallbackHandler. - * - * @param base - * The base DN where the list should be performed. - * @param handler - * The NameClassPairCallbackHandler to supply each - * {@link NameClassPair} to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void list(Name base, NameClassPairCallbackHandler handler) - throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. Pass all the found NameClassPair - * objects to the supplied NameClassPairMapper and return all - * the returned values as a List. - * - * @param base - * The base DN where the list should be performed. - * @param mapper - * The NameClassPairMapper to supply each - * {@link NameClassPair} to. - * @return a List containing the Objects returned from the - * Mapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List list(String base, NameClassPairMapper mapper) - throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. Pass all the found NameClassPair - * objects to the supplied NameClassPairMapper and return all - * the returned values as a List. - * - * @param base - * The base DN where the list should be performed. - * @param mapper - * The NameClassPairMapper to supply each - * {@link NameClassPair} to. - * @return a List containing the Objects returned from the - * Mapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List list(Name base, NameClassPairMapper mapper) - throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. - * - * @param base - * The base DN where the list should be performed. - * @return a List containing the names of all the contexts bound to - * base. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List list(String base) throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. - * - * @param base - * The base DN where the list should be performed. - * @return a List containing the names of all the contexts bound to - * base. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List list(Name base) throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. Each resulting Binding is supplied - * to the specified NameClassPairCallbackHandler. - * - * @param base - * The base DN where the list should be performed. - * @param handler - * The NameClassPairCallbackHandler to supply each - * {@link Binding} to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void listBindings(final String base, - NameClassPairCallbackHandler handler) throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. Each resulting Binding is supplied - * to the specified NameClassPairCallbackHandler. - * - * @param base - * The base DN where the list should be performed. - * @param handler - * The NameClassPairCallbackHandler to supply each - * {@link Binding} to. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - void listBindings(final Name base, - NameClassPairCallbackHandler handler) throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. Pass all the found Binding objects - * to the supplied NameClassPairMapper and return all the - * returned values as a List. - * - * @param base - * The base DN where the list should be performed. - * @param mapper - * The NameClassPairMapper to supply each - * {@link Binding} to. - * @return a List containing the Objects returned from the - * Mapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List listBindings(String base, NameClassPairMapper mapper) - throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. Pass all the found Binding objects - * to the supplied NameClassPairMapper and return all the - * returned values as a List. - * - * @param base - * The base DN where the list should be performed. - * @param mapper - * The NameClassPairMapper to supply each - * {@link Binding} to. - * @return a List containing the Objects returned from the - * Mapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List listBindings(Name base, NameClassPairMapper mapper) - throws NamingException; - - /** - * Perform a non-recursive listing of children of the given - * base. - * - * @param base - * The base DN where the list should be performed. - * @return a List containing the names of all the contexts - * bound to base. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List listBindings(final String base) throws NamingException; - - /** - * Perform a non-recursive listing of children of the given - * base. - * - * @param base - * The base DN where the list should be performed. - * @return a List containing the names of all the contexts - * bound to base. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List listBindings(final Name base) throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. The Object returned in each {@link Binding} is - * supplied to the specified ContextMapper. - * - * @param base - * The base DN where the list should be performed. - * @param mapper - * The ContextMapper to use for mapping the found - * object. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List listBindings(String base, ContextMapper mapper) - throws NamingException; - - /** - * Perform a non-recursive listing of the children of the given - * base. The Object returned in each {@link Binding} is - * supplied to the specified ContextMapper. - * - * @param base - * The base DN where the list should be performed. - * @param mapper - * The ContextMapper to use for mapping the found - * object. - * @return a List containing all entries received from the - * ContextMapper. - * @throws NamingException - * if any error occurs. Note that a - * NameNotFoundException will be ignored. Instead - * this is interpreted that no entries were found. - */ - List listBindings(Name base, ContextMapper mapper) - throws NamingException; - - /** - * Lookup the supplied DN and return the found object. This will typically - * be a {@link DirContextAdapter}, unless the DirObjectFactory - * has been modified in the ContextSource. - * - * @param dn - * The distinguished name of the object to find. - * @return the found object, typically a {@link DirContextAdapter} instance. - * @throws NamingException - * if any error occurs. - * @see #lookupContext(Name) - * @see AbstractContextSource#setDirObjectFactory(Class) - */ - Object lookup(Name dn) throws NamingException; - - /** - * Lookup the supplied DN and return the found object. This will typically - * be a {@link DirContextAdapter}, unless the DirObjectFactory - * has been modified in the ContextSource. - * - * @param dn - * The distinguished name of the object to find. - * @return the found object, typically a {@link DirContextAdapter} instance. - * @throws NamingException - * if any error occurs. - * @see #lookupContext(String) - * @see AbstractContextSource#setDirObjectFactory(Class) - */ - Object lookup(String dn) throws NamingException; - - /** - * Convenience method to get the attributes of a specified DN and - * automatically pass them to an AttributesMapper. - * - * @param dn - * The distinguished name to find. - * @param mapper - * The AttributesMapper to use for mapping the - * found object. - * @return the object returned from the mapper. - * @throws NamingException - * if any error occurs. - */ - Object lookup(Name dn, AttributesMapper mapper) - throws NamingException; - - /** - * Convenience method to get the attributes of a specified DN and - * automatically pass them to an AttributesMapper. - * - * @param dn - * The distinguished name to find. - * @param mapper - * The AttributesMapper to use for mapping the - * found object. - * @return the object returned from the mapper. - * @throws NamingException - * if any error occurs. - */ - Object lookup(String dn, AttributesMapper mapper) - throws NamingException; - - /** - * Convenience method to lookup a specified DN and automatically pass the - * found object to a ContextMapper. - * - * @param dn - * The distinguished name to find. - * @param mapper - * The ContextMapper to use for mapping the found - * object. - * @return the object returned from the mapper. - * @throws NamingException - * if any error occurs. - */ - Object lookup(Name dn, ContextMapper mapper) throws NamingException; - - /** - * Convenience method to lookup a specified DN and automatically pass the - * found object to a ContextMapper. - * - * @param dn - * The distinguished name to find. - * @param mapper - * The ContextMapper to use for mapping the found - * object. - * @return the object returned from the mapper. - * @throws NamingException - * if any error occurs. - */ - Object lookup(String dn, ContextMapper mapper) - throws NamingException; - - /** - * Convenience method to get the specified attributes of a specified DN and - * automatically pass them to an AttributesMapper. - * - * @param dn - * The distinguished name to find. - * @param attributes - * The names of the attributes to pass to the mapper. - * @param mapper - * The AttributesMapper to use for mapping the - * found object. - * @return the object returned from the mapper. - * @throws NamingException - * if any error occurs. - */ - Object lookup(Name dn, String[] attributes, AttributesMapper mapper) - throws NamingException; - - /** - * Convenience method to get the specified attributes of a specified DN and - * automatically pass them to an AttributesMapper. - * - * @param dn - * The distinguished name to find. - * @param attributes - * The names of the attributes to pass to the mapper. - * @param mapper - * The AttributesMapper to use for mapping the - * found object. - * @return the object returned from the mapper. - * @throws NamingException - * if any error occurs. - */ - Object lookup(String dn, String[] attributes, AttributesMapper mapper) - throws NamingException; - - /** - * Convenience method to get the specified attributes of a specified DN and - * automatically pass them to a ContextMapper. - * - * @param dn - * The distinguished name to find. - * @param attributes - * The names of the attributes to pass to the mapper. - * @param mapper - * The ContextMapper to use for mapping the found - * object. - * @return the object returned from the mapper. - * @throws NamingException - * if any error occurs. - */ - Object lookup(Name dn, String[] attributes, ContextMapper mapper) - throws NamingException; - - /** - * Convenience method to get the specified attributes of a specified DN and - * automatically pass them to a ContextMapper. - * - * @param dn - * The distinguished name to find. - * @param attributes - * The names of the attributes to pass to the mapper. - * @param mapper - * The ContextMapper to use for mapping the found - * object. - * @return the object returned from the mapper. - * @throws NamingException - * if any error occurs. - */ - Object lookup(String dn, String[] attributes, ContextMapper mapper) - throws NamingException; - - /** - * Modify an entry in the LDAP tree using the supplied - * ModificationItems. - * - * @param dn - * The distinguished name of the node to modify. - * @param mods - * The modifications to perform. - * @throws NamingException - * if any error occurs. - * @see #modifyAttributes(DirContextOperations) - */ - void modifyAttributes(Name dn, ModificationItem[] mods) - throws NamingException; - - /** - * Modify an entry in the LDAP tree using the supplied - * ModificationItems. - * - * @param dn - * The distinguished name of the node to modify. - * @param mods - * The modifications to perform. - * @throws NamingException - * if any error occurs. - * @see #modifyAttributes(DirContextOperations) - */ - void modifyAttributes(String dn, ModificationItem[] mods) - throws NamingException; - - /** - * Create an entry in the LDAP tree. The attributes used to create the entry - * are either retrieved from the obj parameter or the - * attributes parameter (or both). One of these parameters - * may be null but not both. - * - * @param dn - * The distinguished name to bind the object and attributes to. - * @param obj - * The object to bind, may be null. Typically a - * DirContext implementation. - * @param attributes - * The attributes to bind, may be null. - * @throws NamingException - * if any error occurs. - * @see DirContextAdapter - */ - void bind(Name dn, Object obj, Attributes attributes) - throws NamingException; - - /** - * Create an entry in the LDAP tree. The attributes used to create the entry - * are either retrieved from the obj parameter or the - * attributes parameter (or both). One of these parameters - * may be null but not both. - * - * @param dn - * The distinguished name to bind the object and attributes to. - * @param obj - * The object to bind, may be null. Typically a - * DirContext implementation. - * @param attributes - * The attributes to bind, may be null. - * @throws NamingException - * if any error occurs. - * @see DirContextAdapter - */ - void bind(String dn, Object obj, Attributes attributes) - throws NamingException; - - /** - * Remove an entry from the LDAP tree. The entry must not have any children - - * if you suspect that the entry might have descendants, use - * {@link #unbind(Name, boolean)} in stead. - * - * @param dn - * The distinguished name of the entry to remove. - * @throws NamingException - * if any error occurs. - */ - void unbind(Name dn) throws NamingException; - - /** - * Remove an entry from the LDAP tree. The entry must not have any children - - * if you suspect that the entry might have descendants, use - * {@link #unbind(Name, boolean)} in stead. - * - * @param dn - * The distinguished name to unbind. - * @throws NamingException - * if any error occurs. - */ - void unbind(String dn) throws NamingException; - - /** - * Remove an entry from the LDAP tree, optionally removing all descendants - * in the process. - * - * @param dn - * The distinguished name to unbind. - * @param recursive - * Whether to unbind all subcontexts as well. If this parameter - * is false and the entry has children, the - * operation will fail. - * @throws NamingException - * if any error occurs. - */ - void unbind(Name dn, boolean recursive) throws NamingException; - - /** - * Remove an entry from the LDAP tree, optionally removing all descendants - * in the process. - * - * @param dn - * The distinguished name to unbind. - * @param recursive - * Whether to unbind all subcontexts as well. If this parameter - * is false and the entry has children, the - * operation will fail. - * @throws NamingException - * if any error occurs. - */ - void unbind(String dn, boolean recursive) throws NamingException; - - /** - * Remove an entry and replace it with a new one. The attributes used to - * create the entry are either retrieved from the obj - * parameter or the attributes parameter (or both). One of - * these parameters may be null but not both. This method - * assumes that the specified context already exists - if not it will fail. - * - * @param dn - * The distinguished name to rebind. - * @param obj - * The object to bind to the DN, may be null. - * Typically a DirContext implementation. - * @param attributes - * The attributes to bind, may be null. - * @throws NamingException - * if any error occurs. - * @see DirContextAdapter - */ - void rebind(Name dn, Object obj, Attributes attributes) - throws NamingException; - - /** - * Remove an entry and replace it with a new one. The attributes used to - * create the entry are either retrieved from the obj - * parameter or the attributes parameter (or both). One of - * these parameters may be null but not both. This method - * assumes that the specified context already exists - if not it will fail. - * - * @param dn - * The distinguished name to rebind. - * @param obj - * The object to bind to the DN, may be null. - * Typically a DirContext implementation. - * @param attributes - * The attributes to bind, may be null. - * @throws NamingException - * if any error occurs. - * @see DirContextAdapter - */ - void rebind(String dn, Object obj, Attributes attributes) - throws NamingException; - - /** - * Move an entry in the LDAP tree to a new location. - * - * @param oldDn - * The distinguished name of the entry to move; may not be - * null or empty. - * @param newDn - * The distinguished name where the entry should be moved; may - * not be null or empty. - * @throws ContextNotEmptyException - * if newDn is already bound - * @throws NamingException - * if any other error occurs. - */ - void rename(final Name oldDn, final Name newDn) - throws NamingException; - - /** - * Move an entry in the LDAP tree to a new location. - * - * @param oldDn - * The distinguished name of the entry to move; may not be - * null or empty. - * @param newDn - * The distinguished name where the entry should be moved; may - * not be null or empty. - * @throws ContextNotEmptyException - * if newDn is already bound - * @throws NamingException - * if any other error occurs. - */ - void rename(final String oldDn, final String newDn) - throws NamingException; - - /** - * Convenience method to lookup the supplied DN and automatically cast it to - * {@link DirContextOperations}. - * - * @param dn - * The distinguished name of the object to find. - * @return The found object, cast to {@link DirContextOperations}. - * @throws ClassCastException - * if an alternative DirObjectFactory has been - * registered with the ContextSource, causing - * the actual class of the returned object to be something else - * than {@link DirContextOperations}. - * @throws NamingException - * if any other error occurs. - * @see #lookup(Name) - * @see #modifyAttributes(DirContextOperations) - * @since 1.2 - */ - DirContextOperations lookupContext(Name dn) throws NamingException, - ClassCastException; - - /** - * Convenience method to lookup the supplied DN and automatically cast it to - * {@link DirContextOperations}. - * - * @param dn - * The distinguished name of the object to find. - * @return The found object, cast to {@link DirContextOperations}. - * @throws ClassCastException - * if an alternative DirObjectFactory has been - * registered with the ContextSource, causing - * the actual class of the returned object to be something else - * than {@link DirContextOperations}. - * @throws NamingException - * if any other error occurs. - * @see #lookup(String) - * @see #modifyAttributes(DirContextOperations) - * @since 1.2 - */ - DirContextOperations lookupContext(String dn) - throws NamingException, ClassCastException; - - /** - * Modify the attributes of the entry referenced by the supplied - * {@link DirContextOperations} instance. The DN to update will be the DN of - * the DirContextOperationsinstance, and the - * ModificationItem array is retrieved from the - * DirContextOperations instance using a call to - * {@link AttributeModificationsAware#getModificationItems()}. NB: - * The supplied instance needs to have been properly initialized; this means - * that if it hasn't been received from a lookup operation, - * its DN needs to be initialized and it must have been put in update mode ({@link DirContextAdapter#setUpdateMode(boolean)}). - *

- * Typical use of this method would be as follows: - * - *

-     * public void update(Person person) {
-     *     DirContextOperations ctx = ldapOperations.lookupContext(person.getDn());
-     * 
-     *     ctx.setAttributeValue("description", person.getDescription());
-     *     ctx.setAttributeValue("telephoneNumber", person.getPhone());
-     *     // More modifications here
-     * 
-     *     ldapOperations.modifyAttributes(ctx);
-     * }
-     * 
- * - * @param ctx - * the DirContextOperations instance to use in the update. - * @throws IllegalStateException - * if the supplied instance is not in update mode or has not - * been properly initialized. - * @throws NamingException - * if any other error occurs. - * @since 1.2 - * @see #lookupContext(Name) - * @see DirContextAdapter - */ - void modifyAttributes(DirContextOperations ctx) - throws IllegalStateException, NamingException; - + /** + * Perform a search using a particular {@link SearchExecutor} and context + * processor. Use this method only if especially needed - for the most cases + * there is an overloaded convenience method which calls this one with + * suitable argments. This method handles all the plumbing; getting a + * readonly context; looping through the NamingEnumeration and + * closing the context and enumeration. The actual search is delegated to + * the SearchExecutor and each found NameClassPair is passed to + * the CallbackHandler. Any encountered + * NamingException will be translated using + * {@link LdapUtils#convertLdapException(javax.naming.NamingException)}. + * + * @param se The SearchExecutor to use for performing the + * actual search. + * @param handler The NameClassPairCallbackHandler to which + * each found entry will be passed. + * @param processor DirContextProcessor for custom pre- and + * post-processing. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted as no entries being found. + */ + void search(SearchExecutor se, NameClassPairCallbackHandler handler, DirContextProcessor processor) + throws NamingException; + + /** + * Perform a search using a particular {@link SearchExecutor}. Use this + * method only if especially needed - for the most cases there is an + * overloaded convenience method which calls this one with suitable + * argments. This method handles all the plumbing; getting a readonly + * context; looping through the NamingEnumeration and closing + * the context and enumeration. The actual search is delegated to the + * SearchExecutor and each found NameClassPair is + * passed to the CallbackHandler. Any encountered + * NamingException will be translated using the + * {@link LdapUtils#convertLdapException(javax.naming.NamingException)}. + * + * @param se The SearchExecutor to use for performing the + * actual search. + * @param handler The NameClassPairCallbackHandler to which + * each found entry will be passed. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted as no entries being found. + * @see #search(Name, String, AttributesMapper) + * @see #search(Name, String, ContextMapper) + */ + void search(SearchExecutor se, NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Perform an operation (or series of operations) on a read-only context. + * This method handles the plumbing - getting a DirContext, + * translating any Exceptions and closing the context afterwards. This + * method is not intended for searches; use + * {@link #search(SearchExecutor, NameClassPairCallbackHandler)} or any of + * the overloaded search methods for this. + * + * @param ce The ContextExecutor to which the actual operation + * on the DirContext will be delegated. + * @return the result from the ContextExecutor's operation. + * @throws NamingException if the operation resulted in a + * NamingException. + * + * @see #search(SearchExecutor, NameClassPairCallbackHandler) + * @see #search(Name, String, AttributesMapper) + * @see #search(Name, String, ContextMapper) + */ + Object executeReadOnly(ContextExecutor ce) throws NamingException; + + /** + * Perform an operation (or series of operations) on a read-write context. + * This method handles the plumbing - getting a DirContext, + * translating any exceptions and closing the context afterwards. This + * method is intended only for very particular cases, where there is no + * suitable method in this interface to use. + * + * @param ce The ContextExecutor to which the actual operation + * on the DirContext will be delegated. + * @return the result from the ContextExecutor's operation. + * @throws NamingException if the operation resulted in a + * NamingException. + * @see #bind(Name, Object, Attributes) + * @see #unbind(Name) + * @see #rebind(Name, Object, Attributes) + * @see #rename(Name, Name) + * @see #modifyAttributes(Name, ModificationItem[]) + */ + Object executeReadWrite(ContextExecutor ce) throws NamingException; + + /** + * Search for all objects matching the supplied filter. Each + * SearchResult is supplied to the specified + * NameClassPairCallbackHandler. The SearchScope + * specified in the supplied SearchControls will be used in the + * search. Note that if you are using a ContextMapper, the + * returningObjFlag needs to be set to true in the + * SearchControls. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. + * @param handler The NameClassPairCallbackHandler to supply + * the SearchResult to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void search(Name base, String filter, SearchControls controls, NameClassPairCallbackHandler handler) + throws NamingException; + + /** + * Search for all objects matching the supplied filter. See + * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler)} + * for details. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. + * @param handler The NameClassPairCallbackHandler to supply + * the SearchResult to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void search(String base, String filter, SearchControls controls, NameClassPairCallbackHandler handler) + throws NamingException; + + /** + * Search for all objects matching the supplied filter. Each + * SearchResult is supplied to the specified + * NameClassPairCallbackHandler. The SearchScope + * specified in the supplied SearchControls will be used in the + * search. Note that if you are using a ContextMapper, the + * returningObjFlag needs to be set to true in the + * SearchControls. The given DirContextProcessor + * will be called before and after the search. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. + * @param handler The NameClassPairCallbackHandler to supply + * the SearchResult to. + * @param processor The DirContextProcessor to use before and + * after the search. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void search(Name base, String filter, SearchControls controls, NameClassPairCallbackHandler handler, + DirContextProcessor processor) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified + * AttributesMapper. The SearchScope specified in + * the supplied SearchControls will be used in the search. The + * given DirContextProcessor will be called before and after + * the search. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. + * @param mapper The AttributesMapper to use for translating + * each entry. + * @param processor The DirContextProcessor to use before and + * after the search. + * @return a List containing all entries received from the + * AttributesMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, SearchControls controls, AttributesMapper mapper, + DirContextProcessor processor) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified + * AttributesMapper. The SearchScope specified in + * the supplied SearchControls will be used in the search. The + * given DirContextProcessor will be called before and after + * the search. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. + * @param mapper The AttributesMapper to use for translating + * each entry. + * @param processor The DirContextProcessor to use before and + * after the search. + * @return a List containing all entries received from the + * AttributesMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, SearchControls controls, AttributesMapper mapper, + DirContextProcessor processor) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified + * ContextMapper. The SearchScope specified in the + * supplied SearchControls will be used in the search. The + * given DirContextProcessor will be called before and after + * the search. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. If + * the returnObjFlag is not set in the SearchControls, this + * method will set it automatically, as this is required for the + * ContextMapper to work. + * @param mapper The ContextMapper to use for translating each + * entry. + * @param processor The DirContextProcessor to use before and + * after the search. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, SearchControls controls, ContextMapper mapper, DirContextProcessor processor) + throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified + * ContextMapper. The SearchScope specified in the + * supplied SearchControls will be used in the search. The + * given DirContextProcessor will be called before and after + * the search. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. If + * the returnObjFlag is not set in the SearchControls, this + * method will set it automatically, as this is required for the + * ContextMapper to work. + * @param mapper The ContextMapper to use for translating each + * entry. + * @param processor The DirContextProcessor to use before and + * after the search. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, SearchControls controls, ContextMapper mapper, DirContextProcessor processor) + throws NamingException; + + /** + * Search for all objects matching the supplied filter. See + * {@link #search(Name, String, SearchControls, NameClassPairCallbackHandler, DirContextProcessor)} + * for details. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. + * @param handler The NameClassPairCallbackHandler to supply + * the SearchResults to. + * @param processor The DirContextProcessor to use before and + * after the search. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void search(String base, String filter, SearchControls controls, NameClassPairCallbackHandler handler, + DirContextProcessor processor) throws NamingException; + + /** + * Search for all objects matching the supplied filter. Each + * SearchResult is supplied to the specified + * NameClassPairCallbackHandler. Use the specified values for + * search scope and return objects flag. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param returningObjFlag Whether the bound object should be returned in + * search results. Must be set to true if a + * ContextMapper is used. + * @param handler The NameClassPairCallbackHandler to supply + * the SearchResults to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void search(Name base, String filter, int searchScope, boolean returningObjFlag, + NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Search for all objects matching the supplied filter. Each + * SearchResult is supplied to the specified + * NameClassPairCallbackHandler. Use the specified values for + * search scope and return objects flag. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param returningObjFlag Whether the bound object should be returned in + * search results. Must be set to true if a + * ContextMapper is used. + * @param handler The NameClassPairCallbackHandler to supply + * the SearchResults to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void search(String base, String filter, int searchScope, boolean returningObjFlag, + NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Search for all objects matching the supplied filter. Each + * SearchResult is supplied to the specified + * NameClassPairCallbackHandler. The default Search scope ( + * SearchControls.SUBTREE_SCOPE) will be used and the + * returnObjects flag will be set to false. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param handler The NameClassPairCallbackHandler to supply + * the SearchResults to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void search(Name base, String filter, NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Search for all objects matching the supplied filter. Each + * SearchResult is supplied to the specified + * NameClassPairCallbackHandler. The default Search scope ( + * SearchControls.SUBTREE_SCOPE) will be used and the + * returnObjects flag will be set to false. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param handler The NameClassPairCallbackHandler to supply + * the SearchResults to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void search(String base, String filter, NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Search for all objects matching the supplied filter. Only return any + * attributes mathing the specified attribute names. The Attributes in each + * SearchResult is supplied to the specified + * AttributesMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param attrs The attributes to return, null means returning + * all attributes. + * @param mapper The AttributesMapper to use for translating + * each entry. + * @return a List containing all entries received from the + * AttributesMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, int searchScope, String[] attrs, AttributesMapper mapper) + throws NamingException; + + /** + * Search for all objects matching the supplied filter. Only return any + * attributes mathing the specified attribute names. The Attributes in each + * SearchResult is supplied to the specified + * AttributesMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param attrs The attributes to return, null means returning + * all attributes. + * @param mapper The AttributesMapper to use for translating + * each entry. + * @return a List containing all entries received from the + * AttributesMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, int searchScope, String[] attrs, AttributesMapper mapper) + throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified + * AttributesMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param mapper The AttributesMapper to use for translating + * each entry. + * @return a List containing all entries received from the + * AttributesMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, int searchScope, AttributesMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified + * AttributesMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param mapper The AttributesMapper to use for translating + * each entry. + * @return a List containing all entries received from the + * AttributesMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, int searchScope, AttributesMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified + * AttributesMapper. The default search scope will be used. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param mapper The AttributesMapper to use for translating + * each entry. + * @return a List containing all entries received from the + * AttributesMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, AttributesMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Attributes in + * each SearchResult is supplied to the specified + * AttributesMapper. The default search scope will be used. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param mapper The AttributesMapper to use for translating + * each entry. + * @return a List containing all entries received from the + * AttributesMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, AttributesMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The + * Object returned in each SearchResult is + * supplied to the specified ContextMapper. Only return the + * supplied attributes. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param attrs The attributes to return, null means all + * attributes. + * @param mapper The ContextMapper to use for translating each + * entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, int searchScope, String[] attrs, ContextMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The + * Object returned in each SearchResult is + * supplied to the specified ContextMapper. Only return the + * supplied attributes. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param attrs The attributes to return, null means all + * attributes. + * @param mapper The ContextMapper to use for translating each + * entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, int searchScope, String[] attrs, ContextMapper mapper) + throws NamingException; + + /** + * Search for all objects matching the supplied filter. The + * Object returned in each SearchResult is + * supplied to the specified ContextMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param mapper The ContextMapper to use for translating each + * entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, int searchScope, ContextMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The + * Object returned in each SearchResult is + * supplied to the specified ContextMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param searchScope The search scope to set in SearchControls + * . + * @param mapper The ContextMapper to use for translating each + * entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, int searchScope, ContextMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The + * Object returned in each SearchResult is + * supplied to the specified ContextMapper. The default search + * scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param mapper The ContextMapper to use for translating each + * entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, ContextMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The + * Object returned in each SearchResult is + * supplied to the specified ContextMapper. The default search + * scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param mapper The ContextMapper to use for translating each + * entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, ContextMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The + * Object returned in each SearchResult is + * supplied to the specified ContextMapper. The default search + * scope (SearchControls.SUBTREE_SCOPE) will be used. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param mapper The ContextMapper to use for translating each + * entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, SearchControls controls, ContextMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Object returned + * in each SearchResult is supplied to the specified + * ContextMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. If + * the returnObjFlag is not set in the SearchControls, this + * method will set it automatically, as this is required for the + * ContextMapper to work. + * @param mapper The ContextMapper to use for translating each + * entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, SearchControls controls, ContextMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Attributes + * returned in each SearchResult is supplied to the specified + * AttributesMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. + * @param mapper The AttributesMapper to use for translating + * each entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(String base, String filter, SearchControls controls, AttributesMapper mapper) throws NamingException; + + /** + * Search for all objects matching the supplied filter. The Attributes + * returned in each SearchResult is supplied to the specified + * AttributesMapper. + * + * @param base The base DN where the search should begin. + * @param filter The filter to use in the search. + * @param controls The SearchControls to use in the search. + * @param mapper The AttributesMapper to use for translating + * each entry. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List search(Name base, String filter, SearchControls controls, AttributesMapper mapper) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting NameClassPair is supplied + * to the specified NameClassPairCallbackHandler. + * + * @param base The base DN where the list should be performed. + * @param handler The NameClassPairCallbackHandler to supply + * each {@link NameClassPair} to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void list(String base, NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting NameClassPair is supplied + * to the specified NameClassPairCallbackHandler. + * + * @param base The base DN where the list should be performed. + * @param handler The NameClassPairCallbackHandler to supply + * each {@link NameClassPair} to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void list(Name base, NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found NameClassPair objects + * to the supplied NameClassPairMapper and return all the + * returned values as a List. + * + * @param base The base DN where the list should be performed. + * @param mapper The NameClassPairMapper to supply each + * {@link NameClassPair} to. + * @return a List containing the Objects returned from the + * Mapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List list(String base, NameClassPairMapper mapper) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found NameClassPair objects + * to the supplied NameClassPairMapper and return all the + * returned values as a List. + * + * @param base The base DN where the list should be performed. + * @param mapper The NameClassPairMapper to supply each + * {@link NameClassPair} to. + * @return a List containing the Objects returned from the + * Mapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List list(Name base, NameClassPairMapper mapper) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. + * + * @param base The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List list(String base) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. + * + * @param base The base DN where the list should be performed. + * @return a List containing the names of all the contexts bound to + * base. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List list(Name base) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting Binding is supplied to the + * specified NameClassPairCallbackHandler. + * + * @param base The base DN where the list should be performed. + * @param handler The NameClassPairCallbackHandler to supply + * each {@link Binding} to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void listBindings(final String base, NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Each resulting Binding is supplied to the + * specified NameClassPairCallbackHandler. + * + * @param base The base DN where the list should be performed. + * @param handler The NameClassPairCallbackHandler to supply + * each {@link Binding} to. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + void listBindings(final Name base, NameClassPairCallbackHandler handler) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found Binding objects to the + * supplied NameClassPairMapper and return all the returned + * values as a List. + * + * @param base The base DN where the list should be performed. + * @param mapper The NameClassPairMapper to supply each + * {@link Binding} to. + * @return a List containing the Objects returned from the + * Mapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List listBindings(String base, NameClassPairMapper mapper) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. Pass all the found Binding objects to the + * supplied NameClassPairMapper and return all the returned + * values as a List. + * + * @param base The base DN where the list should be performed. + * @param mapper The NameClassPairMapper to supply each + * {@link Binding} to. + * @return a List containing the Objects returned from the + * Mapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List listBindings(Name base, NameClassPairMapper mapper) throws NamingException; + + /** + * Perform a non-recursive listing of children of the given + * base. + * + * @param base The base DN where the list should be performed. + * @return a List containing the names of all the contexts + * bound to base. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List listBindings(final String base) throws NamingException; + + /** + * Perform a non-recursive listing of children of the given + * base. + * + * @param base The base DN where the list should be performed. + * @return a List containing the names of all the contexts + * bound to base. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List listBindings(final Name base) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. The Object returned in each {@link Binding} is + * supplied to the specified ContextMapper. + * + * @param base The base DN where the list should be performed. + * @param mapper The ContextMapper to use for mapping the found + * object. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List listBindings(String base, ContextMapper mapper) throws NamingException; + + /** + * Perform a non-recursive listing of the children of the given + * base. The Object returned in each {@link Binding} is + * supplied to the specified ContextMapper. + * + * @param base The base DN where the list should be performed. + * @param mapper The ContextMapper to use for mapping the found + * object. + * @return a List containing all entries received from the + * ContextMapper. + * @throws NamingException if any error occurs. Note that a + * NameNotFoundException will be ignored. Instead this is + * interpreted that no entries were found. + */ + List listBindings(Name base, ContextMapper mapper) throws NamingException; + + /** + * Lookup the supplied DN and return the found object. This will typically + * be a {@link DirContextAdapter}, unless the DirObjectFactory + * has been modified in the ContextSource. + * + * @param dn The distinguished name of the object to find. + * @return the found object, typically a {@link DirContextAdapter} instance. + * @throws NamingException if any error occurs. + * @see #lookupContext(Name) + * @see AbstractContextSource#setDirObjectFactory(Class) + */ + Object lookup(Name dn) throws NamingException; + + /** + * Lookup the supplied DN and return the found object. This will typically + * be a {@link DirContextAdapter}, unless the DirObjectFactory + * has been modified in the ContextSource. + * + * @param dn The distinguished name of the object to find. + * @return the found object, typically a {@link DirContextAdapter} instance. + * @throws NamingException if any error occurs. + * @see #lookupContext(String) + * @see AbstractContextSource#setDirObjectFactory(Class) + */ + Object lookup(String dn) throws NamingException; + + /** + * Convenience method to get the attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn The distinguished name to find. + * @param mapper The AttributesMapper to use for mapping the + * found object. + * @return the object returned from the mapper. + * @throws NamingException if any error occurs. + */ + Object lookup(Name dn, AttributesMapper mapper) throws NamingException; + + /** + * Convenience method to get the attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn The distinguished name to find. + * @param mapper The AttributesMapper to use for mapping the + * found object. + * @return the object returned from the mapper. + * @throws NamingException if any error occurs. + */ + Object lookup(String dn, AttributesMapper mapper) throws NamingException; + + /** + * Convenience method to lookup a specified DN and automatically pass the + * found object to a ContextMapper. + * + * @param dn The distinguished name to find. + * @param mapper The ContextMapper to use for mapping the found + * object. + * @return the object returned from the mapper. + * @throws NamingException if any error occurs. + */ + Object lookup(Name dn, ContextMapper mapper) throws NamingException; + + /** + * Convenience method to lookup a specified DN and automatically pass the + * found object to a ContextMapper. + * + * @param dn The distinguished name to find. + * @param mapper The ContextMapper to use for mapping the found + * object. + * @return the object returned from the mapper. + * @throws NamingException if any error occurs. + */ + Object lookup(String dn, ContextMapper mapper) throws NamingException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn The distinguished name to find. + * @param attributes The names of the attributes to pass to the mapper. + * @param mapper The AttributesMapper to use for mapping the + * found object. + * @return the object returned from the mapper. + * @throws NamingException if any error occurs. + */ + Object lookup(Name dn, String[] attributes, AttributesMapper mapper) throws NamingException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to an AttributesMapper. + * + * @param dn The distinguished name to find. + * @param attributes The names of the attributes to pass to the mapper. + * @param mapper The AttributesMapper to use for mapping the + * found object. + * @return the object returned from the mapper. + * @throws NamingException if any error occurs. + */ + Object lookup(String dn, String[] attributes, AttributesMapper mapper) throws NamingException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to a ContextMapper. + * + * @param dn The distinguished name to find. + * @param attributes The names of the attributes to pass to the mapper. + * @param mapper The ContextMapper to use for mapping the found + * object. + * @return the object returned from the mapper. + * @throws NamingException if any error occurs. + */ + Object lookup(Name dn, String[] attributes, ContextMapper mapper) throws NamingException; + + /** + * Convenience method to get the specified attributes of a specified DN and + * automatically pass them to a ContextMapper. + * + * @param dn The distinguished name to find. + * @param attributes The names of the attributes to pass to the mapper. + * @param mapper The ContextMapper to use for mapping the found + * object. + * @return the object returned from the mapper. + * @throws NamingException if any error occurs. + */ + Object lookup(String dn, String[] attributes, ContextMapper mapper) throws NamingException; + + /** + * Modify an entry in the LDAP tree using the supplied + * ModificationItems. + * + * @param dn The distinguished name of the node to modify. + * @param mods The modifications to perform. + * @throws NamingException if any error occurs. + * @see #modifyAttributes(DirContextOperations) + */ + void modifyAttributes(Name dn, ModificationItem[] mods) throws NamingException; + + /** + * Modify an entry in the LDAP tree using the supplied + * ModificationItems. + * + * @param dn The distinguished name of the node to modify. + * @param mods The modifications to perform. + * @throws NamingException if any error occurs. + * @see #modifyAttributes(DirContextOperations) + */ + void modifyAttributes(String dn, ModificationItem[] mods) throws NamingException; + + /** + * Create an entry in the LDAP tree. The attributes used to create the entry + * are either retrieved from the obj parameter or the + * attributes parameter (or both). One of these parameters may + * be null but not both. + * + * @param dn The distinguished name to bind the object and attributes to. + * @param obj The object to bind, may be null. Typically a + * DirContext implementation. + * @param attributes The attributes to bind, may be null. + * @throws NamingException if any error occurs. + * @see DirContextAdapter + */ + void bind(Name dn, Object obj, Attributes attributes) throws NamingException; + + /** + * Create an entry in the LDAP tree. The attributes used to create the entry + * are either retrieved from the obj parameter or the + * attributes parameter (or both). One of these parameters may + * be null but not both. + * + * @param dn The distinguished name to bind the object and attributes to. + * @param obj The object to bind, may be null. Typically a + * DirContext implementation. + * @param attributes The attributes to bind, may be null. + * @throws NamingException if any error occurs. + * @see DirContextAdapter + */ + void bind(String dn, Object obj, Attributes attributes) throws NamingException; + + /** + * Remove an entry from the LDAP tree. The entry must not have any children + * - if you suspect that the entry might have descendants, use + * {@link #unbind(Name, boolean)} in stead. + * + * @param dn The distinguished name of the entry to remove. + * @throws NamingException if any error occurs. + */ + void unbind(Name dn) throws NamingException; + + /** + * Remove an entry from the LDAP tree. The entry must not have any children + * - if you suspect that the entry might have descendants, use + * {@link #unbind(Name, boolean)} in stead. + * + * @param dn The distinguished name to unbind. + * @throws NamingException if any error occurs. + */ + void unbind(String dn) throws NamingException; + + /** + * Remove an entry from the LDAP tree, optionally removing all descendants + * in the process. + * + * @param dn The distinguished name to unbind. + * @param recursive Whether to unbind all subcontexts as well. If this + * parameter is false and the entry has children, the operation + * will fail. + * @throws NamingException if any error occurs. + */ + void unbind(Name dn, boolean recursive) throws NamingException; + + /** + * Remove an entry from the LDAP tree, optionally removing all descendants + * in the process. + * + * @param dn The distinguished name to unbind. + * @param recursive Whether to unbind all subcontexts as well. If this + * parameter is false and the entry has children, the operation + * will fail. + * @throws NamingException if any error occurs. + */ + void unbind(String dn, boolean recursive) throws NamingException; + + /** + * Remove an entry and replace it with a new one. The attributes used to + * create the entry are either retrieved from the obj parameter + * or the attributes parameter (or both). One of these + * parameters may be null but not both. This method assumes + * that the specified context already exists - if not it will fail. + * + * @param dn The distinguished name to rebind. + * @param obj The object to bind to the DN, may be null. + * Typically a DirContext implementation. + * @param attributes The attributes to bind, may be null. + * @throws NamingException if any error occurs. + * @see DirContextAdapter + */ + void rebind(Name dn, Object obj, Attributes attributes) throws NamingException; + + /** + * Remove an entry and replace it with a new one. The attributes used to + * create the entry are either retrieved from the obj parameter + * or the attributes parameter (or both). One of these + * parameters may be null but not both. This method assumes + * that the specified context already exists - if not it will fail. + * + * @param dn The distinguished name to rebind. + * @param obj The object to bind to the DN, may be null. + * Typically a DirContext implementation. + * @param attributes The attributes to bind, may be null. + * @throws NamingException if any error occurs. + * @see DirContextAdapter + */ + void rebind(String dn, Object obj, Attributes attributes) throws NamingException; + + /** + * Move an entry in the LDAP tree to a new location. + * + * @param oldDn The distinguished name of the entry to move; may not be + * null or empty. + * @param newDn The distinguished name where the entry should be moved; may + * not be null or empty. + * @throws ContextNotEmptyException if newDn is already bound + * @throws NamingException if any other error occurs. + */ + void rename(final Name oldDn, final Name newDn) throws NamingException; + + /** + * Move an entry in the LDAP tree to a new location. + * + * @param oldDn The distinguished name of the entry to move; may not be + * null or empty. + * @param newDn The distinguished name where the entry should be moved; may + * not be null or empty. + * @throws ContextNotEmptyException if newDn is already bound + * @throws NamingException if any other error occurs. + */ + void rename(final String oldDn, final String newDn) throws NamingException; + + /** + * Convenience method to lookup the supplied DN and automatically cast it to + * {@link DirContextOperations}. + * + * @param dn The distinguished name of the object to find. + * @return The found object, cast to {@link DirContextOperations}. + * @throws ClassCastException if an alternative + * DirObjectFactory has been registered with the + * ContextSource, causing the actual class of the returned + * object to be something else than {@link DirContextOperations}. + * @throws NamingException if any other error occurs. + * @see #lookup(Name) + * @see #modifyAttributes(DirContextOperations) + * @since 1.2 + */ + DirContextOperations lookupContext(Name dn) throws NamingException, ClassCastException; + + /** + * Convenience method to lookup the supplied DN and automatically cast it to + * {@link DirContextOperations}. + * + * @param dn The distinguished name of the object to find. + * @return The found object, cast to {@link DirContextOperations}. + * @throws ClassCastException if an alternative + * DirObjectFactory has been registered with the + * ContextSource, causing the actual class of the returned + * object to be something else than {@link DirContextOperations}. + * @throws NamingException if any other error occurs. + * @see #lookup(String) + * @see #modifyAttributes(DirContextOperations) + * @since 1.2 + */ + DirContextOperations lookupContext(String dn) throws NamingException, ClassCastException; + + /** + * Modify the attributes of the entry referenced by the supplied + * {@link DirContextOperations} instance. The DN to update will be the DN of + * the DirContextOperationsinstance, and the + * ModificationItem array is retrieved from the + * DirContextOperations instance using a call to + * {@link AttributeModificationsAware#getModificationItems()}. NB: + * The supplied instance needs to have been properly initialized; this means + * that if it hasn't been received from a lookup operation, its + * DN needs to be initialized and it must have been put in update mode ( + * {@link DirContextAdapter#setUpdateMode(boolean)}). + *

+ * Typical use of this method would be as follows: + * + *

+	 * public void update(Person person) {
+	 * 	DirContextOperations ctx = ldapOperations.lookupContext(person.getDn());
+	 * 
+	 * 	ctx.setAttributeValue("description", person.getDescription());
+	 * 	ctx.setAttributeValue("telephoneNumber", person.getPhone());
+	 * 	// More modifications here
+	 * 
+	 * 	ldapOperations.modifyAttributes(ctx);
+	 * }
+	 * 
+ * + * @param ctx the DirContextOperations instance to use in the update. + * @throws IllegalStateException if the supplied instance is not in update + * mode or has not been properly initialized. + * @throws NamingException if any other error occurs. + * @since 1.2 + * @see #lookupContext(Name) + * @see DirContextAdapter + */ + void modifyAttributes(DirContextOperations ctx) throws IllegalStateException, NamingException; + /** * Bind the data in the supplied context in the tree. All specified * Attributes in will be bound to the DN set on the instance. - *

Example:
+ *

+ * Example:
+ * *

 	 * DirContextOperations ctx = new DirContextAdapter(dn);
-	 * ctx.setAttributeValue("cn", "john doe");
-	 * ctx.setAttributeValue("description", "some description");
+	 * ctx.setAttributeValue("cn", "john doe");
+	 * ctx.setAttributeValue("description", "some description");
 	 * //More initialization here.
 	 * 
 	 * ldapTemplate.bind(ctx);
@@ -1591,4 +1279,124 @@ public interface LdapOperations {
 	 * @since 1.3
 	 */
 	void bind(DirContextOperations ctx);
+
+	/**
+	 * Utility method to perform a simple LDAP 'bind' authentication. Search for
+	 * the LDAP entry to authenticate using the supplied base DN and filter; use
+	 * the DN of the found entry together with the password as input to
+	 * {@link ContextSource#getContext(String, String)}, thus authenticating the
+	 * entry.
+	 * 

+ * Example:
+ * + *

+	 * AndFilter filter = new AndFilter();
+	 * filter.and("objectclass", "person").and("uid", userId);
+	 * boolean authenticated = ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), password);
+	 * 
+ * + * @param base the DN to use as the base of the search. + * @param filter the search filter - must result in a unique result. + * @param password the password to use for authentication. + * @return true if the authentication was successful, + * false otherwise. + * @since 1.3 + */ + boolean authenticate(Name base, String filter, String password); + + /** + * Utility method to perform a simple LDAP 'bind' authentication. Search for + * the LDAP entry to authenticate using the supplied base DN and filter; use + * the DN of the found entry together with the password as input to + * {@link ContextSource#getContext(String, String)}, thus authenticating the + * entry. + *

+ * Example:
+ * + *

+	 * AndFilter filter = new AndFilter();
+	 * filter.and("objectclass", "person").and("uid", userId);
+	 * boolean authenticated = ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), password);
+	 * 
+ * + * @param base the DN to use as the base of the search. + * @param filter the search filter - must result in a unique result. + * @param password the password to use for authentication. + * @return true if the authentication was successful, + * false otherwise. + * @since 1.3 + */ + boolean authenticate(String base, String filter, String password); + + /** + * Utility method to perform a simple LDAP 'bind' authentication. Search for + * the LDAP entry to authenticate using the supplied base DN and filter; use + * the DN of the found entry together with the password as input to + * {@link ContextSource#getContext(String, String)}, thus authenticating the + * entry. The resulting DirContext instance is then used as input to the + * supplied {@link AuthenticatedLdapEntryContextCallback} to perform any + * additional LDAP operations against the authenticated DirContext. + * + * @param base the DN to use as the base of the search. + * @param filter the search filter - must result in a unique result. + * @param password the password to use for authentication. + * @param callback the callback to that will be called to perform operations + * on the DirContext authenticated with the found user. + * @return true if the authentication was successful, + * false otherwise. + * @see #authenticate(Name, String, String) + * @since 1.3 + */ + boolean authenticate(Name base, String filter, String password, AuthenticatedLdapEntryContextCallback callback); + + /** + * Utility method to perform a simple LDAP 'bind' authentication. Search for + * the LDAP entry to authenticate using the supplied base DN and filter; use + * the DN of the found entry together with the password as input to + * {@link ContextSource#getContext(String, String)}, thus authenticating the + * entry. The resulting DirContext instance is then used as input to the + * supplied {@link AuthenticatedLdapEntryContextCallback} to perform any + * additional LDAP operations against the authenticated DirContext. + * + * @param base the DN to use as the base of the search. + * @param filter the search filter - must result in a unique result. + * @param password the password to use for authentication. + * @param callback the callback to that will be called to perform operations + * on the DirContext authenticated with the found user. + * @return true if the authentication was successful, + * false otherwise. + * @see #authenticate(String, String, String) + * @since 1.3 + */ + boolean authenticate(String base, String filter, String password, AuthenticatedLdapEntryContextCallback callback); + + /** + * Perform a search for a unique entry matching the specified search + * criteria and return the found object. If no entry is found or if there + * are more than one matching entry, an + * {@link IncorrectResultSizeDataAccessException} is thrown. + * @param base the DN to use as the base of the search. + * @param filter the search filter. + * @param mapper the mapper to use for the search. + * @return the single object returned by the mapper that matches the search + * criteria. + * @throws IncorrectResultSizeDataAccessException if the result is not one unique entry + * @since 1.3 + */ + Object searchForObject(Name base, String filter, ContextMapper mapper); + + /** + * Perform a search for a unique entry matching the specified search + * criteria and return the found object. If no entry is found or if there + * are more than one matching entry, an + * {@link IncorrectResultSizeDataAccessException} is thrown. + * @param base the DN to use as the base of the search. + * @param filter the search filter. + * @param mapper the mapper to use for the search. + * @return the single object returned by the mapper that matches the search + * criteria. + * @throws IncorrectResultSizeDataAccessException if the result is not one unique entry + * @since 1.3 + */ + Object searchForObject(String base, String filter, ContextMapper mapper); } diff --git a/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java b/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java index 6a206e77..35bf8ece 100644 --- a/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java +++ b/core/src/main/java/org/springframework/ldap/core/LdapTemplate.java @@ -32,7 +32,10 @@ import org.apache.commons.lang.Validate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.ldap.NamingException; +import org.springframework.ldap.support.LdapEntryIdentificationContextMapper; import org.springframework.ldap.support.LdapUtils; /** @@ -1347,4 +1350,112 @@ public class LdapTemplate implements LdapOperations, InitializingBean { throw new IllegalStateException("The DirContextOperations instance needs to be properly initialized."); } } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.LdapOperations#authenticate(javax.naming + * .Name, java.lang.String, java.lang.String) + */ + public boolean authenticate(Name base, String filter, String password) { + return authenticate(base, filter, password, new NullAuthenticatedLdapEntryContextCallback()); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.LdapOperations#authenticate(java.lang.String + * , java.lang.String, java.lang.String) + */ + public boolean authenticate(String base, String filter, String password) { + return authenticate(base, filter, password, new NullAuthenticatedLdapEntryContextCallback()); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.LdapOperations#authenticate(java.lang.String + * , java.lang.String, java.lang.String, + * org.springframework.ldap.core.AuthenticatedLdapEntryContextCallback) + */ + public boolean authenticate(String base, String filter, String password, + AuthenticatedLdapEntryContextCallback callback) { + return authenticate(new DistinguishedName(base), filter, password, callback); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.LdapOperations#authenticate(javax.naming + * .Name, java.lang.String, java.lang.String, + * org.springframework.ldap.core.AuthenticatedLdapEntryContextCallback) + */ + public boolean authenticate(Name base, String filter, String password, + final AuthenticatedLdapEntryContextCallback callback) { + + List result = search(base, filter, new LdapEntryIdentificationContextMapper()); + if (result.size() != 1) { + log.error("Unable to find unique entry matching in authentication; base: '" + base + "'; filter: '" + + filter + "'. Found " + result.size() + " mathching entries"); + return false; + } + + final LdapEntryIdentification entryIdentification = (LdapEntryIdentification) result.get(0); + + try { + DirContext ctx = contextSource.getContext(entryIdentification.getAbsoluteDn().toString(), password); + executeWithContext(new ContextExecutor() { + public Object executeWithContext(DirContext ctx) throws javax.naming.NamingException { + callback.executeWithContext(ctx, entryIdentification); + return null; + } + }, ctx); + return true; + } + catch (Exception e) { + log.error("Authentication failed for entry with DN '" + entryIdentification.getAbsoluteDn() + "'", e); + return false; + } + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.LdapOperations#searchForObject(javax.naming + * .Name, java.lang.String, org.springframework.ldap.core.ContextMapper) + */ + public Object searchForObject(Name base, String filter, ContextMapper mapper) { + List result = search(base, filter, mapper); + if (result.size() == 0) { + throw new EmptyResultDataAccessException(1); + } + else if (result.size() != 1) { + throw new IncorrectResultSizeDataAccessException(1, result.size()); + } + + return result.get(0); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.ldap.core.LdapOperations#searchForObject(java.lang + * .String, java.lang.String, org.springframework.ldap.core.ContextMapper) + */ + public Object searchForObject(String base, String filter, ContextMapper mapper) { + return searchForObject(new DistinguishedName(base), filter, mapper); + } + + private static final class NullAuthenticatedLdapEntryContextCallback implements + AuthenticatedLdapEntryContextCallback { + public void executeWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification) { + // Do nothing + } + } } diff --git a/core/src/main/java/org/springframework/ldap/support/LdapEntryIdentificationContextMapper.java b/core/src/main/java/org/springframework/ldap/support/LdapEntryIdentificationContextMapper.java new file mode 100644 index 00000000..0efe3169 --- /dev/null +++ b/core/src/main/java/org/springframework/ldap/support/LdapEntryIdentificationContextMapper.java @@ -0,0 +1,37 @@ +/* + * Copyright 2005-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ldap.support; + +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.DistinguishedName; +import org.springframework.ldap.core.LdapEntryIdentification; +import org.springframework.ldap.core.support.AbstractContextMapper; + +/** + * ContextMapper implementation that maps the found entries to the + * {@link LdapEntryIdentification} of each respective entry. + * + * @author Mattias Hellborg Arthursson + * @since 1.3 + */ +public class LdapEntryIdentificationContextMapper extends AbstractContextMapper { + + protected Object doMapFromContext(DirContextOperations ctx) { + return new LdapEntryIdentification(new DistinguishedName(ctx.getNameInNamespace()), new DistinguishedName(ctx + .getDn())); + } + +} diff --git a/core/src/test/java/org/springframework/ldap/core/LdapTemplateTest.java b/core/src/test/java/org/springframework/ldap/core/LdapTemplateTest.java index b75510e5..3d7570f7 100644 --- a/core/src/test/java/org/springframework/ldap/core/LdapTemplateTest.java +++ b/core/src/test/java/org/springframework/ldap/core/LdapTemplateTest.java @@ -32,332 +32,317 @@ import junit.framework.TestCase; import org.easymock.AbstractMatcher; import org.easymock.MockControl; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.ldap.LimitExceededException; import org.springframework.ldap.NameNotFoundException; import org.springframework.ldap.PartialResultException; +import org.springframework.ldap.UncategorizedLdapException; public class LdapTemplateTest extends TestCase { - private static final String DEFAULT_BASE_STRING = "o=example.com"; + private static final String DEFAULT_BASE_STRING = "o=example.com"; - private MockControl contextSourceControl; + private MockControl contextSourceControl; - private ContextSource contextSourceMock; + private ContextSource contextSourceMock; - private MockControl dirContextControl; + private MockControl dirContextControl; - private DirContext dirContextMock; + private DirContext dirContextMock; - private MockControl attributesMapperControl; + private MockControl attributesMapperControl; - private AttributesMapper attributesMapperMock; + private AttributesMapper attributesMapperMock; - private MockControl namingEnumerationControl; + private MockControl namingEnumerationControl; - private NamingEnumeration namingEnumerationMock; + private NamingEnumeration namingEnumerationMock; - private MockControl nameControl; + private MockControl nameControl; - private Name nameMock; + private Name nameMock; - private MockControl handlerControl; + private MockControl handlerControl; - private NameClassPairCallbackHandler handlerMock; + private NameClassPairCallbackHandler handlerMock; - private MockControl contextMapperControl; + private MockControl contextMapperControl; - private ContextMapper contextMapperMock; + private ContextMapper contextMapperMock; - private MockControl contextExecutorControl; + private MockControl contextExecutorControl; - private ContextExecutor contextExecutorMock; + private ContextExecutor contextExecutorMock; - private MockControl searchExecutorControl; + private MockControl searchExecutorControl; - private SearchExecutor searchExecutorMock; + private SearchExecutor searchExecutorMock; - private LdapTemplate tested; + private LdapTemplate tested; - private MockControl dirContextProcessorControl; + private MockControl dirContextProcessorControl; - private DirContextProcessor dirContextProcessorMock; + private DirContextProcessor dirContextProcessorMock; - private MockControl dirContextOperationsConrol; + private MockControl dirContextOperationsConrol; - private DirContextOperations dirContextOperationsMock; + private DirContextOperations dirContextOperationsMock; - protected void setUp() throws Exception { - super.setUp(); + protected void setUp() throws Exception { + super.setUp(); - // Setup ContextSource mock - contextSourceControl = MockControl.createControl(ContextSource.class); - contextSourceMock = (ContextSource) contextSourceControl.getMock(); + // Setup ContextSource mock + contextSourceControl = MockControl.createControl(ContextSource.class); + contextSourceMock = (ContextSource) contextSourceControl.getMock(); - // Setup LdapContext mock - dirContextControl = MockControl.createControl(LdapContext.class); - dirContextMock = (LdapContext) dirContextControl.getMock(); + // Setup LdapContext mock + dirContextControl = MockControl.createControl(LdapContext.class); + dirContextMock = (LdapContext) dirContextControl.getMock(); - // Setup NamingEnumeration mock - namingEnumerationControl = MockControl - .createControl(NamingEnumeration.class); - namingEnumerationMock = (NamingEnumeration) namingEnumerationControl - .getMock(); + // Setup NamingEnumeration mock + namingEnumerationControl = MockControl.createControl(NamingEnumeration.class); + namingEnumerationMock = (NamingEnumeration) namingEnumerationControl.getMock(); - // Setup Name mock - nameControl = MockControl.createControl(Name.class); - nameMock = (Name) nameControl.getMock(); + // Setup Name mock + nameControl = MockControl.createControl(Name.class); + nameMock = (Name) nameControl.getMock(); - // Setup Handler mock - handlerControl = MockControl - .createControl(NameClassPairCallbackHandler.class); - handlerMock = (NameClassPairCallbackHandler) handlerControl.getMock(); + // Setup Handler mock + handlerControl = MockControl.createControl(NameClassPairCallbackHandler.class); + handlerMock = (NameClassPairCallbackHandler) handlerControl.getMock(); - contextMapperControl = MockControl.createControl(ContextMapper.class); - contextMapperMock = (ContextMapper) contextMapperControl.getMock(); + contextMapperControl = MockControl.createControl(ContextMapper.class); + contextMapperMock = (ContextMapper) contextMapperControl.getMock(); - attributesMapperControl = MockControl - .createControl(AttributesMapper.class); - attributesMapperMock = (AttributesMapper) attributesMapperControl - .getMock(); + attributesMapperControl = MockControl.createControl(AttributesMapper.class); + attributesMapperMock = (AttributesMapper) attributesMapperControl.getMock(); - contextExecutorControl = MockControl - .createControl(ContextExecutor.class); - contextExecutorMock = (ContextExecutor) contextExecutorControl - .getMock(); + contextExecutorControl = MockControl.createControl(ContextExecutor.class); + contextExecutorMock = (ContextExecutor) contextExecutorControl.getMock(); - searchExecutorControl = MockControl.createControl(SearchExecutor.class); - searchExecutorMock = (SearchExecutor) searchExecutorControl.getMock(); + searchExecutorControl = MockControl.createControl(SearchExecutor.class); + searchExecutorMock = (SearchExecutor) searchExecutorControl.getMock(); - dirContextProcessorControl = MockControl - .createControl(DirContextProcessor.class); - dirContextProcessorMock = (DirContextProcessor) dirContextProcessorControl - .getMock(); + dirContextProcessorControl = MockControl.createControl(DirContextProcessor.class); + dirContextProcessorMock = (DirContextProcessor) dirContextProcessorControl.getMock(); - dirContextOperationsConrol = MockControl - .createControl(DirContextOperations.class); - dirContextOperationsMock = (DirContextOperations) dirContextOperationsConrol - .getMock(); + dirContextOperationsConrol = MockControl.createControl(DirContextOperations.class); + dirContextOperationsMock = (DirContextOperations) dirContextOperationsConrol.getMock(); - tested = new LdapTemplate(contextSourceMock); - } + tested = new LdapTemplate(contextSourceMock); + } - protected void tearDown() throws Exception { - super.tearDown(); + protected void tearDown() throws Exception { + super.tearDown(); - contextSourceControl = null; - contextSourceMock = null; + contextSourceControl = null; + contextSourceMock = null; - dirContextControl = null; - dirContextMock = null; + dirContextControl = null; + dirContextMock = null; - namingEnumerationControl = null; - namingEnumerationMock = null; + namingEnumerationControl = null; + namingEnumerationMock = null; - nameControl = null; - nameMock = null; + nameControl = null; + nameMock = null; - handlerControl = null; - handlerMock = null; + handlerControl = null; + handlerMock = null; - contextMapperControl = null; - contextMapperMock = null; + contextMapperControl = null; + contextMapperMock = null; - attributesMapperControl = null; - attributesMapperMock = null; + attributesMapperControl = null; + attributesMapperMock = null; - contextExecutorControl = null; - contextExecutorMock = null; + contextExecutorControl = null; + contextExecutorMock = null; - searchExecutorControl = null; - searchExecutorMock = null; + searchExecutorControl = null; + searchExecutorMock = null; - dirContextProcessorControl = null; - dirContextProcessorMock = null; + dirContextProcessorControl = null; + dirContextProcessorMock = null; - dirContextOperationsConrol = null; - dirContextOperationsMock = null; + dirContextOperationsConrol = null; + dirContextOperationsMock = null; - } + } - protected void replay() { - contextSourceControl.replay(); - dirContextControl.replay(); - namingEnumerationControl.replay(); - nameControl.replay(); - handlerControl.replay(); - contextMapperControl.replay(); - attributesMapperControl.replay(); - contextExecutorControl.replay(); - searchExecutorControl.replay(); - dirContextProcessorControl.replay(); - dirContextOperationsConrol.replay(); - } + protected void replay() { + contextSourceControl.replay(); + dirContextControl.replay(); + namingEnumerationControl.replay(); + nameControl.replay(); + handlerControl.replay(); + contextMapperControl.replay(); + attributesMapperControl.replay(); + contextExecutorControl.replay(); + searchExecutorControl.replay(); + dirContextProcessorControl.replay(); + dirContextOperationsConrol.replay(); + } - protected void verify() { - contextSourceControl.verify(); - dirContextControl.verify(); - namingEnumerationControl.verify(); - nameControl.verify(); - handlerControl.verify(); - contextMapperControl.verify(); - attributesMapperControl.verify(); - contextExecutorControl.verify(); - searchExecutorControl.verify(); - dirContextProcessorControl.verify(); - dirContextOperationsConrol.verify(); - } + protected void verify() { + contextSourceControl.verify(); + dirContextControl.verify(); + namingEnumerationControl.verify(); + nameControl.verify(); + handlerControl.verify(); + contextMapperControl.verify(); + attributesMapperControl.verify(); + contextExecutorControl.verify(); + searchExecutorControl.verify(); + dirContextProcessorControl.verify(); + dirContextOperationsConrol.verify(); + } - private void expectGetReadWriteContext() { - contextSourceControl.expectAndReturn(contextSourceMock - .getReadWriteContext(), dirContextMock); - } + private void expectGetReadWriteContext() { + contextSourceControl.expectAndReturn(contextSourceMock.getReadWriteContext(), dirContextMock); + } - private void expectGetReadOnlyContext() { - contextSourceControl.expectAndReturn(contextSourceMock - .getReadOnlyContext(), dirContextMock); - } + private void expectGetReadOnlyContext() { + contextSourceControl.expectAndReturn(contextSourceMock.getReadOnlyContext(), dirContextMock); + } - public void testSearch_CallbackHandler() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_CallbackHandler() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); - SearchResult searchResult = new SearchResult("", new Object(), - new BasicAttributes()); + SearchResult searchResult = new SearchResult("", new Object(), new BasicAttributes()); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - handlerMock.handleNameClassPair(searchResult); + handlerMock.handleNameClassPair(searchResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - tested.search(nameMock, "(ou=somevalue)", 1, true, handlerMock); + tested.search(nameMock, "(ou=somevalue)", 1, true, handlerMock); - verify(); - } + verify(); + } - public void testSearch_StringBase_CallbackHandler() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_StringBase_CallbackHandler() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); - SearchResult searchResult = new SearchResult("", new Object(), - new BasicAttributes()); + SearchResult searchResult = new SearchResult("", new Object(), new BasicAttributes()); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - handlerMock.handleNameClassPair(searchResult); + handlerMock.handleNameClassPair(searchResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, true, - handlerMock); + tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, true, handlerMock); - verify(); - } + verify(); + } - private void setupStringSearchAndNamingEnumeration(SearchControls controls, - SearchResult searchResult) throws Exception { - dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); - dirContextControl.expectAndReturn(dirContextMock.search( - DEFAULT_BASE_STRING, "(ou=somevalue)", controls), - namingEnumerationMock); + private void setupStringSearchAndNamingEnumeration(SearchControls controls, SearchResult searchResult) + throws Exception { + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + dirContextControl.expectAndReturn(dirContextMock.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls), + namingEnumerationMock); - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), true); - namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), - searchResult); - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), false); - namingEnumerationMock.close(); - } + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); + } - public void testSearch_CallbackHandler_Defaults() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_CallbackHandler_Defaults() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); - SearchResult searchResult = new SearchResult("", new Object(), - new BasicAttributes()); + SearchResult searchResult = new SearchResult("", new Object(), new BasicAttributes()); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - handlerMock.handleNameClassPair(searchResult); + handlerMock.handleNameClassPair(searchResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - tested.search(nameMock, "(ou=somevalue)", handlerMock); + tested.search(nameMock, "(ou=somevalue)", handlerMock); - verify(); - } + verify(); + } - public void testSearch_String_CallbackHandler_Defaults() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_CallbackHandler_Defaults() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); - SearchResult searchResult = new SearchResult("", new Object(), - new BasicAttributes()); + SearchResult searchResult = new SearchResult("", new Object(), new BasicAttributes()); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - handlerMock.handleNameClassPair(searchResult); + handlerMock.handleNameClassPair(searchResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", handlerMock); + tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", handlerMock); - verify(); - } + verify(); + } - private void setupSearchAndNamingEnumeration(SearchControls controls, - SearchResult searchResult) throws Exception { - dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); - dirContextControl.expectAndReturn(dirContextMock.search(nameMock, - "(ou=somevalue)", controls), namingEnumerationMock); + private void setupSearchAndNamingEnumeration(SearchControls controls, SearchResult searchResult) throws Exception { + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + dirContextControl.expectAndReturn(dirContextMock.search(nameMock, "(ou=somevalue)", controls), + namingEnumerationMock); - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), true); - namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), - searchResult); - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), false); - namingEnumerationMock.close(); - } + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); + } - public void testSearch_NameNotFoundException() throws Exception { - expectGetReadOnlyContext(); + private void setupSearchAndNamingEnumerationForNoHits(SearchControls controls) throws Exception { + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + dirContextControl.expectAndReturn(dirContextMock.search(nameMock, "(ou=somevalue)", controls), + namingEnumerationMock); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(false); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); + } - dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); - javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException("some text"); - dirContextControl.expectAndThrow(dirContextMock.search(nameMock, - "(ou=somevalue)", controls), ne); + public void testSearch_NameNotFoundException() throws Exception { + expectGetReadOnlyContext(); - dirContextMock.close(); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); - replay(); + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException("some text"); + dirContextControl.expectAndThrow(dirContextMock.search(nameMock, "(ou=somevalue)", controls), ne); - try { + dirContextMock.close(); + + replay(); + + try { tested.search(nameMock, "(ou=somevalue)", handlerMock); fail("NameNotFoundException expected"); } @@ -365,1433 +350,1540 @@ public class LdapTemplateTest extends TestCase { assertTrue(true); } - verify(); - } + verify(); + } - public void testSearch_NamingException() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_NamingException() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); - dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); - javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); - dirContextControl.expectAndThrow(dirContextMock.search(nameMock, - "(ou=somevalue)", controls), ne); + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); + dirContextControl.expectAndThrow(dirContextMock.search(nameMock, "(ou=somevalue)", controls), ne); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - try { - tested.search(nameMock, "(ou=somevalue)", handlerMock); - fail("LimitExceededException expected"); - } catch (LimitExceededException expected) { - // expected - } + try { + tested.search(nameMock, "(ou=somevalue)", handlerMock); + fail("LimitExceededException expected"); + } + catch (LimitExceededException expected) { + // expected + } - verify(); - } + verify(); + } - public void testSearch_CallbackHandler_DirContextProcessor() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_CallbackHandler_DirContextProcessor() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); - SearchResult searchResult = new SearchResult("", new Object(), - new BasicAttributes()); + SearchResult searchResult = new SearchResult("", new Object(), new BasicAttributes()); - dirContextProcessorMock.preProcess(dirContextMock); + dirContextProcessorMock.preProcess(dirContextMock); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - handlerMock.handleNameClassPair(searchResult); + handlerMock.handleNameClassPair(searchResult); - dirContextProcessorMock.postProcess(dirContextMock); + dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - tested.search(nameMock, "(ou=somevalue)", controls, handlerMock, - dirContextProcessorMock); + tested.search(nameMock, "(ou=somevalue)", controls, handlerMock, dirContextProcessorMock); - verify(); - } + verify(); + } - public void testSearch_String_CallbackHandler_DirContextProcessor() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_CallbackHandler_DirContextProcessor() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); - SearchResult searchResult = new SearchResult("", new Object(), - new BasicAttributes()); + SearchResult searchResult = new SearchResult("", new Object(), new BasicAttributes()); - dirContextProcessorMock.preProcess(dirContextMock); + dirContextProcessorMock.preProcess(dirContextMock); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - handlerMock.handleNameClassPair(searchResult); + handlerMock.handleNameClassPair(searchResult); - dirContextProcessorMock.postProcess(dirContextMock); + dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls, - handlerMock, dirContextProcessorMock); + tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls, handlerMock, dirContextProcessorMock); - verify(); - } + verify(); + } - public void testSearch_String_AttributesMapper_DirContextProcessor() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_AttributesMapper_DirContextProcessor() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - dirContextProcessorMock.preProcess(dirContextMock); - setupStringSearchAndNamingEnumeration(controls, searchResult); + dirContextProcessorMock.preProcess(dirContextMock); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", - controls, attributesMapperMock, dirContextProcessorMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls, attributesMapperMock, + dirContextProcessorMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_Name_AttributesMapper_DirContextProcessor() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_Name_AttributesMapper_DirContextProcessor() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - dirContextProcessorMock.preProcess(dirContextMock); - setupSearchAndNamingEnumeration(controls, searchResult); + dirContextProcessorMock.preProcess(dirContextMock); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", controls, - attributesMapperMock, dirContextProcessorMock); + List list = tested.search(nameMock, "(ou=somevalue)", controls, attributesMapperMock, dirContextProcessorMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_SearchControls_ContextMapper_DirContextProcessor() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_SearchControls_ContextMapper_DirContextProcessor() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - dirContextProcessorMock.preProcess(dirContextMock); - setupStringSearchAndNamingEnumeration(controls, searchResult); + dirContextProcessorMock.preProcess(dirContextMock); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", - controls, contextMapperMock, dirContextProcessorMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls, contextMapperMock, + dirContextProcessorMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_Name_SearchControls_ContextMapper_DirContextProcessor() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_Name_SearchControls_ContextMapper_DirContextProcessor() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - dirContextProcessorMock.preProcess(dirContextMock); - setupSearchAndNamingEnumeration(controls, searchResult); + dirContextProcessorMock.preProcess(dirContextMock); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", controls, - contextMapperMock, dirContextProcessorMock); + List list = tested.search(nameMock, "(ou=somevalue)", controls, contextMapperMock, dirContextProcessorMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_AttributesMapper_ReturningAttrs() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_AttributesMapper_ReturningAttrs() throws Exception { + expectGetReadOnlyContext(); - String[] attrs = new String[0]; - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(false); - controls.setReturningAttributes(attrs); + String[] attrs = new String[0]; + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + controls.setReturningAttributes(attrs); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", 1, attrs, - attributesMapperMock); + List list = tested.search(nameMock, "(ou=somevalue)", 1, attrs, attributesMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_AttributesMapper_ReturningAttrs() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_AttributesMapper_ReturningAttrs() throws Exception { + expectGetReadOnlyContext(); - String[] attrs = new String[0]; - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(false); - controls.setReturningAttributes(attrs); + String[] attrs = new String[0]; + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); + controls.setReturningAttributes(attrs); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, - attrs, attributesMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, attrs, attributesMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_AttributesMapper() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_AttributesMapper() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", 1, - attributesMapperMock); + List list = tested.search(nameMock, "(ou=somevalue)", 1, attributesMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_AttributesMapper() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_AttributesMapper() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, - attributesMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, attributesMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_AttributesMapper_Default() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_AttributesMapper_Default() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", - attributesMapperMock); + List list = tested.search(nameMock, "(ou=somevalue)", attributesMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_AttributesMapper_Default() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_AttributesMapper_Default() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(false); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", - attributesMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", attributesMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_ContextMapper() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_ContextMapper() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", 1, - contextMapperMock); + List list = tested.search(nameMock, "(ou=somevalue)", 1, contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_ContextMapper_ReturningAttrs() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_ContextMapper_ReturningAttrs() throws Exception { + expectGetReadOnlyContext(); - String[] attrs = new String[0]; + String[] attrs = new String[0]; - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(true); - controls.setReturningAttributes(attrs); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); + controls.setReturningAttributes(attrs); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", 1, attrs, - contextMapperMock); + List list = tested.search(nameMock, "(ou=somevalue)", 1, attrs, contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_ContextMapper_ReturningAttrs() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_ContextMapper_ReturningAttrs() throws Exception { + expectGetReadOnlyContext(); - String[] attrs = new String[0]; + String[] attrs = new String[0]; - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(true); - controls.setReturningAttributes(attrs); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); + controls.setReturningAttributes(attrs); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, - attrs, contextMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, attrs, contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_ContextMapper() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_ContextMapper() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, - contextMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", 1, contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_ContextMapper_Default() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_ContextMapper_Default() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested - .search(nameMock, "(ou=somevalue)", contextMapperMock); + List list = tested.search(nameMock, "(ou=somevalue)", contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_ContextMapper_Default() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_ContextMapper_Default() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", - contextMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_SearchControls_ContextMapper() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_SearchControls_ContextMapper() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", - controls, contextMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls, contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_SearchControls_ContextMapper_ReturningObjFlagNotSet() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_SearchControls_ContextMapper_ReturningObjFlagNotSet() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - SearchControls expectedControls = new SearchControls(); - expectedControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - expectedControls.setReturningObjFlag(true); + SearchControls expectedControls = new SearchControls(); + expectedControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + expectedControls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupStringSearchAndNamingEnumeration(expectedControls, searchResult); + setupStringSearchAndNamingEnumeration(expectedControls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", - controls, contextMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls, contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_Name_SearchControls_ContextMapper() throws Exception { - expectGetReadOnlyContext(); + public void testSearch_Name_SearchControls_ContextMapper() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setReturningObjFlag(true); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setReturningObjFlag(true); - Object expectedObject = new Object(); - SearchResult searchResult = new SearchResult("", expectedObject, - new BasicAttributes()); + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = expectedObject; - contextMapperControl.expectAndReturn(contextMapperMock - .mapFromContext(expectedObject), expectedResult); + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", controls, - contextMapperMock); + List list = tested.search(nameMock, "(ou=somevalue)", controls, contextMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_String_SearchControls_AttributesMapper() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_String_SearchControls_AttributesMapper() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - setupStringSearchAndNamingEnumeration(controls, searchResult); + setupStringSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", - controls, attributesMapperMock); + List list = tested.search(DEFAULT_BASE_STRING, "(ou=somevalue)", controls, attributesMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testSearch_Name_SearchControls_AttributesMapper() - throws Exception { - expectGetReadOnlyContext(); + public void testSearch_Name_SearchControls_AttributesMapper() throws Exception { + expectGetReadOnlyContext(); - SearchControls controls = new SearchControls(); - controls.setSearchScope(1); - controls.setReturningObjFlag(false); + SearchControls controls = new SearchControls(); + controls.setSearchScope(1); + controls.setReturningObjFlag(false); - BasicAttributes expectedAttributes = new BasicAttributes(); - SearchResult searchResult = new SearchResult("", null, - expectedAttributes); + BasicAttributes expectedAttributes = new BasicAttributes(); + SearchResult searchResult = new SearchResult("", null, expectedAttributes); - setupSearchAndNamingEnumeration(controls, searchResult); + setupSearchAndNamingEnumeration(controls, searchResult); - Object expectedResult = new Object(); - attributesMapperControl.expectAndReturn(attributesMapperMock - .mapFromAttributes(expectedAttributes), expectedResult); + Object expectedResult = new Object(); + attributesMapperControl.expectAndReturn(attributesMapperMock.mapFromAttributes(expectedAttributes), + expectedResult); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - List list = tested.search(nameMock, "(ou=somevalue)", controls, - attributesMapperMock); + List list = tested.search(nameMock, "(ou=somevalue)", controls, attributesMapperMock); - verify(); + verify(); - assertNotNull(list); - assertEquals(1, list.size()); - assertSame(expectedResult, list.get(0)); - } + assertNotNull(list); + assertEquals(1, list.size()); + assertSame(expectedResult, list.get(0)); + } - public void testModifyAttributes() throws Exception { - expectGetReadWriteContext(); + public void testModifyAttributes() throws Exception { + expectGetReadWriteContext(); - ModificationItem[] mods = new ModificationItem[0]; - dirContextMock.modifyAttributes(nameMock, mods); + ModificationItem[] mods = new ModificationItem[0]; + dirContextMock.modifyAttributes(nameMock, mods); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - tested.modifyAttributes(nameMock, mods); + tested.modifyAttributes(nameMock, mods); - verify(); - } + verify(); + } - public void testModifyAttributes_String() throws Exception { - expectGetReadWriteContext(); + public void testModifyAttributes_String() throws Exception { + expectGetReadWriteContext(); - ModificationItem[] mods = new ModificationItem[0]; - dirContextMock.modifyAttributes(DEFAULT_BASE_STRING, mods); + ModificationItem[] mods = new ModificationItem[0]; + dirContextMock.modifyAttributes(DEFAULT_BASE_STRING, mods); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - tested.modifyAttributes(DEFAULT_BASE_STRING, mods); + tested.modifyAttributes(DEFAULT_BASE_STRING, mods); - verify(); - } + verify(); + } - public void testModifyAttributes_NamingException() throws Exception { - expectGetReadWriteContext(); + public void testModifyAttributes_NamingException() throws Exception { + expectGetReadWriteContext(); - ModificationItem[] mods = new ModificationItem[0]; - dirContextMock.modifyAttributes(nameMock, mods); - javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); - dirContextControl.setThrowable(ne); + ModificationItem[] mods = new ModificationItem[0]; + dirContextMock.modifyAttributes(nameMock, mods); + javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); + dirContextControl.setThrowable(ne); - dirContextMock.close(); + dirContextMock.close(); - replay(); + replay(); - try { - tested.modifyAttributes(nameMock, mods); - fail("LimitExceededException expected"); - } catch (LimitExceededException expected) { - assertTrue(true); - } + try { + tested.modifyAttributes(nameMock, mods); + fail("LimitExceededException expected"); + } + catch (LimitExceededException expected) { + assertTrue(true); + } - verify(); - } + verify(); + } - public void testBind() throws Exception { - expectGetReadWriteContext(); + public void testBind() throws Exception { + expectGetReadWriteContext(); - Object expectedObject = new Object(); - BasicAttributes expectedAttributes = new BasicAttributes(); - dirContextMock.bind(nameMock, expectedObject, expectedAttributes); - dirContextMock.close(); + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.bind(nameMock, expectedObject, expectedAttributes); + dirContextMock.close(); - replay(); + replay(); - tested.bind(nameMock, expectedObject, expectedAttributes); + tested.bind(nameMock, expectedObject, expectedAttributes); - verify(); + verify(); - } + } - public void testBind_String() throws Exception { - expectGetReadWriteContext(); + public void testBind_String() throws Exception { + expectGetReadWriteContext(); - Object expectedObject = new Object(); - BasicAttributes expectedAttributes = new BasicAttributes(); - dirContextMock.bind(DEFAULT_BASE_STRING, expectedObject, - expectedAttributes); - dirContextMock.close(); + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.bind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes); + dirContextMock.close(); - replay(); + replay(); - tested.bind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes); + tested.bind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes); - verify(); + verify(); - } + } - public void testBind_NamingException() throws Exception { - expectGetReadWriteContext(); + public void testBind_NamingException() throws Exception { + expectGetReadWriteContext(); - Object expectedObject = new Object(); - BasicAttributes expectedAttributes = new BasicAttributes(); - dirContextMock.bind(nameMock, expectedObject, expectedAttributes); - javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException(); - dirContextControl.setThrowable(ne); - dirContextMock.close(); + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.bind(nameMock, expectedObject, expectedAttributes); + javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException(); + dirContextControl.setThrowable(ne); + dirContextMock.close(); - replay(); + replay(); - try { - tested.bind(nameMock, expectedObject, expectedAttributes); - fail("NameNotFoundException expected"); - } catch (NameNotFoundException expected) { - assertTrue(true); - } - - verify(); - - } - - public void testUnbind() throws Exception { - expectGetReadWriteContext(); - - dirContextMock.unbind(nameMock); - dirContextMock.close(); - replay(); - - tested.unbind(nameMock); - - verify(); - } - - public void testUnbind_String() throws Exception { - expectGetReadWriteContext(); - - dirContextMock.unbind(DEFAULT_BASE_STRING); - dirContextMock.close(); - replay(); - - tested.unbind(DEFAULT_BASE_STRING); - - verify(); - } - - public void testUnbindRecursive() throws Exception { - expectGetReadWriteContext(); - - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), true); - Binding binding = new Binding("cn=Some name", null); - namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), - binding); - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), false); - namingEnumerationMock.close(); - - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), false); - namingEnumerationMock.close(); - - DistinguishedName listDn = new DistinguishedName(DEFAULT_BASE_STRING); - dirContextMock.listBindings(listDn); - dirContextControl.setReturnValue(namingEnumerationMock); - DistinguishedName subListDn = new DistinguishedName( - "cn=Some name, o=example.com"); - dirContextMock.listBindings(subListDn); - dirContextControl.setReturnValue(namingEnumerationMock); - - dirContextMock.unbind(subListDn); - dirContextMock.unbind(listDn); - dirContextMock.close(); - - // Caused by creating a DistinguishedName from a Name - nameControl.expectAndReturn(nameMock.size(), 1, 2); - nameControl.expectAndReturn(nameMock.get(0), "o=example.com"); - - replay(); - - tested.unbind(nameMock, true); - - verify(); - } - - public void testUnbindRecursive_String() throws Exception { - expectGetReadWriteContext(); - - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), true); - Binding binding = new Binding("cn=Some name", null); - namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), - binding); - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), false); - namingEnumerationMock.close(); - - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), false); - namingEnumerationMock.close(); - - DistinguishedName listDn = new DistinguishedName(DEFAULT_BASE_STRING); - dirContextMock.listBindings(listDn); - dirContextControl.setReturnValue(namingEnumerationMock); - DistinguishedName subListDn = new DistinguishedName( - "cn=Some name, o=example.com"); - dirContextMock.listBindings(subListDn); - dirContextControl.setReturnValue(namingEnumerationMock); - - dirContextMock.unbind(subListDn); - dirContextMock.unbind(listDn); - dirContextMock.close(); - replay(); - - tested.unbind(DEFAULT_BASE_STRING, true); - - verify(); - } - - public void testRebind() throws Exception { - expectGetReadWriteContext(); - - Object expectedObject = new Object(); - BasicAttributes expectedAttributes = new BasicAttributes(); - dirContextMock.rebind(nameMock, expectedObject, expectedAttributes); - - dirContextMock.close(); - - replay(); - - tested.rebind(nameMock, expectedObject, expectedAttributes); - - verify(); - } - - public void testRebind_String() throws Exception { - expectGetReadWriteContext(); - - Object expectedObject = new Object(); - BasicAttributes expectedAttributes = new BasicAttributes(); - dirContextMock.rebind(DEFAULT_BASE_STRING, expectedObject, - expectedAttributes); - - dirContextMock.close(); - - replay(); - - tested.rebind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes); - - verify(); - } - - public void testUnbind_NamingException() throws Exception { - expectGetReadWriteContext(); - - dirContextMock.unbind(nameMock); - javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException(); - dirContextControl.setThrowable(ne); - dirContextMock.close(); - - replay(); - - try { - tested.unbind(nameMock); - fail("NameNotFoundException expected"); - } catch (NameNotFoundException expected) { - assertTrue(true); - } - - verify(); - } - - public void testExecuteReadOnly() throws Exception { - expectGetReadOnlyContext(); - - Object object = new Object(); - contextExecutorControl.expectAndReturn(contextExecutorMock - .executeWithContext(dirContextMock), object); - - dirContextMock.close(); - - replay(); - - Object result = tested.executeReadOnly(contextExecutorMock); - - verify(); - - assertSame(object, result); - } - - public void testExecuteReadOnly_NamingException() throws Exception { - expectGetReadOnlyContext(); - - javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException(); - contextExecutorControl.expectAndThrow(contextExecutorMock - .executeWithContext(dirContextMock), ne); - - dirContextMock.close(); - - replay(); - - try { - tested.executeReadOnly(contextExecutorMock); - fail("NameNotFoundException expected"); - } catch (NameNotFoundException expected) { - assertTrue(true); - } - - verify(); - } - - public void testExecuteReadWrite() throws Exception { - expectGetReadWriteContext(); - - Object object = new Object(); - contextExecutorControl.expectAndReturn(contextExecutorMock - .executeWithContext(dirContextMock), object); - - dirContextMock.close(); - - replay(); - - Object result = tested.executeReadWrite(contextExecutorMock); - - verify(); - - assertSame(object, result); - } - - public void testExecuteReadWrite_NamingException() throws Exception { - expectGetReadWriteContext(); - - javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException(); - contextExecutorControl.expectAndThrow(contextExecutorMock - .executeWithContext(dirContextMock), ne); - - dirContextMock.close(); - - replay(); - - try { - tested.executeReadWrite(contextExecutorMock); - fail("NameNotFoundException expected"); - } catch (NameNotFoundException expected) { - assertTrue(true); - } - - verify(); - } - - public void testDoSearch_DirContextProcessor() throws Exception { - expectGetReadOnlyContext(); - - SearchResult searchResult = new SearchResult(null, null, null); - - dirContextProcessorMock.preProcess(dirContextMock); - - searchExecutorControl.expectAndReturn(searchExecutorMock - .executeSearch(dirContextMock), namingEnumerationMock); - - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), true); - namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), - searchResult); - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), false); - namingEnumerationMock.close(); - - handlerMock.handleNameClassPair(searchResult); - - dirContextProcessorMock.postProcess(dirContextMock); - - dirContextMock.close(); - - replay(); - - tested.search(searchExecutorMock, handlerMock, dirContextProcessorMock); - - verify(); - } - - public void testDoSearch_DirContextProcessor_NamingException() - throws Exception { - expectGetReadOnlyContext(); - - dirContextProcessorMock.preProcess(dirContextMock); - - javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); - searchExecutorControl.expectAndThrow(searchExecutorMock - .executeSearch(dirContextMock), ne); - - dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); - - replay(); - - try { - tested.search(searchExecutorMock, handlerMock, - dirContextProcessorMock); - fail("LimitExceededException expected"); - } catch (LimitExceededException expected) { - assertTrue(true); - } - - verify(); - } - - public void testDoSearch() throws Exception { - expectGetReadOnlyContext(); - - SearchResult searchResult = new SearchResult(null, null, null); - - searchExecutorControl.expectAndReturn(searchExecutorMock - .executeSearch(dirContextMock), namingEnumerationMock); - - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), true); - namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), - searchResult); - namingEnumerationControl.expectAndReturn(namingEnumerationMock - .hasMore(), false); - namingEnumerationMock.close(); - - handlerMock.handleNameClassPair(searchResult); - - dirContextMock.close(); - - replay(); - - tested.search(searchExecutorMock, handlerMock); - - verify(); - } - - public void testDoSearch_NamingException() throws Exception { - expectGetReadOnlyContext(); - - javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); - searchExecutorControl.expectAndThrow(searchExecutorMock - .executeSearch(dirContextMock), ne); - - dirContextMock.close(); - - replay(); - - try { - tested.search(searchExecutorMock, handlerMock); - fail("LimitExceededException expected"); - } catch (LimitExceededException expected) { - assertTrue(true); - } - - verify(); - } - - public void testDoSearch_NamingException_NamingEnumeration() - throws Exception { - expectGetReadOnlyContext(); - - searchExecutorControl.expectAndReturn(searchExecutorMock - .executeSearch(dirContextMock), namingEnumerationMock); - - javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); - namingEnumerationControl.expectAndThrow( - namingEnumerationMock.hasMore(), ne); - namingEnumerationMock.close(); - - dirContextMock.close(); - - replay(); - - try { - tested.search(searchExecutorMock, handlerMock); - fail("LimitExceededException expected"); - } catch (LimitExceededException expected) { - assertTrue(true); - } - - verify(); - } - - public void testDoSearch_NameNotFoundException() throws Exception { - expectGetReadOnlyContext(); - - searchExecutorControl.expectAndThrow(searchExecutorMock - .executeSearch(dirContextMock), - new javax.naming.NameNotFoundException()); - dirContextMock.close(); - - replay(); - - try { - tested.search(searchExecutorMock, handlerMock); + try { + tested.bind(nameMock, expectedObject, expectedAttributes); fail("NameNotFoundException expected"); } catch (NameNotFoundException expected) { assertTrue(true); } - verify(); - } + verify(); - public void testSearch_PartialResult_IgnoreNotSet() throws Exception { - expectGetReadOnlyContext(); + } - dirContextProcessorMock.preProcess(dirContextMock); + public void testUnbind() throws Exception { + expectGetReadWriteContext(); - javax.naming.PartialResultException ex = new javax.naming.PartialResultException(); - searchExecutorControl.expectAndThrow(searchExecutorMock - .executeSearch(dirContextMock), ex); - dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); + dirContextMock.unbind(nameMock); + dirContextMock.close(); + replay(); - replay(); + tested.unbind(nameMock); - try { - tested.search(searchExecutorMock, handlerMock, - dirContextProcessorMock); - fail("PartialResultException expected"); - } catch (PartialResultException expected) { - assertTrue(true); - } + verify(); + } - verify(); - } + public void testUnbind_String() throws Exception { + expectGetReadWriteContext(); - public void testSearch_PartialResult_IgnoreSet() throws Exception { - tested.setIgnorePartialResultException(true); + dirContextMock.unbind(DEFAULT_BASE_STRING); + dirContextMock.close(); + replay(); - expectGetReadOnlyContext(); + tested.unbind(DEFAULT_BASE_STRING); - dirContextProcessorMock.preProcess(dirContextMock); + verify(); + } - searchExecutorControl.expectAndThrow(searchExecutorMock - .executeSearch(dirContextMock), - new javax.naming.PartialResultException()); + public void testUnbindRecursive() throws Exception { + expectGetReadWriteContext(); - dirContextProcessorMock.postProcess(dirContextMock); - dirContextMock.close(); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), true); + Binding binding = new Binding("cn=Some name", null); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), binding); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); - replay(); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); - tested.search(searchExecutorMock, handlerMock, dirContextProcessorMock); + DistinguishedName listDn = new DistinguishedName(DEFAULT_BASE_STRING); + dirContextMock.listBindings(listDn); + dirContextControl.setReturnValue(namingEnumerationMock); + DistinguishedName subListDn = new DistinguishedName("cn=Some name, o=example.com"); + dirContextMock.listBindings(subListDn); + dirContextControl.setReturnValue(namingEnumerationMock); - verify(); - } + dirContextMock.unbind(subListDn); + dirContextMock.unbind(listDn); + dirContextMock.close(); - public void testLookupContextWithName() { - final DirContextAdapter expectedResult = new DirContextAdapter(); + // Caused by creating a DistinguishedName from a Name + nameControl.expectAndReturn(nameMock.size(), 1, 2); + nameControl.expectAndReturn(nameMock.get(0), "o=example.com"); - LdapTemplate tested = new LdapTemplate() { - public Object lookup(Name dn) { - assertSame(DistinguishedName.EMPTY_PATH, dn); - return expectedResult; - } - }; + replay(); - DirContextOperations result = tested - .lookupContext(DistinguishedName.EMPTY_PATH); - assertSame(expectedResult, result); + tested.unbind(nameMock, true); - } + verify(); + } - public void testLookupContextWithString() { - final DirContextAdapter expectedResult = new DirContextAdapter(); - final String expectedName = "cn=John Doe"; + public void testUnbindRecursive_String() throws Exception { + expectGetReadWriteContext(); - LdapTemplate tested = new LdapTemplate() { - public Object lookup(String dn) { - assertSame(expectedName, dn); - return expectedResult; - } - }; + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), true); + Binding binding = new Binding("cn=Some name", null); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), binding); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); - DirContextOperations result = tested.lookupContext(expectedName); - assertSame(expectedResult, result); - } + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); - public void testModifyAttributesWithDirContextOperations() throws Exception { - final ModificationItem[] expectedModifications = new ModificationItem[0]; + DistinguishedName listDn = new DistinguishedName(DEFAULT_BASE_STRING); + dirContextMock.listBindings(listDn); + dirContextControl.setReturnValue(namingEnumerationMock); + DistinguishedName subListDn = new DistinguishedName("cn=Some name, o=example.com"); + dirContextMock.listBindings(subListDn); + dirContextControl.setReturnValue(namingEnumerationMock); - dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock - .getDn(), DistinguishedName.EMPTY_PATH); - dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock - .isUpdateMode(), true); - dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock - .getModificationItems(), expectedModifications); + dirContextMock.unbind(subListDn); + dirContextMock.unbind(listDn); + dirContextMock.close(); + replay(); - LdapTemplate tested = new LdapTemplate() { - public void modifyAttributes(Name dn, ModificationItem[] mods) { - assertSame(DistinguishedName.EMPTY_PATH, dn); - assertSame(expectedModifications, mods); - } - }; + tested.unbind(DEFAULT_BASE_STRING, true); - replay(); + verify(); + } - tested.modifyAttributes(dirContextOperationsMock); + public void testRebind() throws Exception { + expectGetReadWriteContext(); - verify(); - } + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.rebind(nameMock, expectedObject, expectedAttributes); - public void testModifyAttributesWithDirContextOperationsNotInitializedDn() - throws Exception { + dirContextMock.close(); - dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock - .getDn(), DistinguishedName.EMPTY_PATH); - dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock - .isUpdateMode(), false); + replay(); - LdapTemplate tested = new LdapTemplate() { - public void modifyAttributes(Name dn, ModificationItem[] mods) { - fail("The call to the base modifyAttributes should not have occured."); - } - }; + tested.rebind(nameMock, expectedObject, expectedAttributes); - replay(); + verify(); + } - try { - tested.modifyAttributes(dirContextOperationsMock); - fail("IllegalStateException expected"); - } catch (IllegalStateException expected) { - assertTrue(true); - } - verify(); - } + public void testRebind_String() throws Exception { + expectGetReadWriteContext(); - public void testModifyAttributesWithDirContextOperationsNotInitializedInUpdateMode() - throws Exception { + Object expectedObject = new Object(); + BasicAttributes expectedAttributes = new BasicAttributes(); + dirContextMock.rebind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes); - dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock - .getDn(), null); + dirContextMock.close(); - LdapTemplate tested = new LdapTemplate() { - public void modifyAttributes(Name dn, ModificationItem[] mods) { - fail("The call to the base modifyAttributes should not have occured."); - } - }; + replay(); - replay(); + tested.rebind(DEFAULT_BASE_STRING, expectedObject, expectedAttributes); - try { - tested.modifyAttributes(dirContextOperationsMock); - fail("IllegalStateException expected"); - } catch (IllegalStateException expected) { - assertTrue(true); - } - verify(); - } + verify(); + } - /** - * Needed to verify search control values. - * - * @author Mattias Hellborg Arthursson - */ - private static class SearchControlsMatcher extends AbstractMatcher { - protected boolean argumentMatches(Object arg0, Object arg1) { - if (arg0 instanceof SearchControls - && arg1 instanceof SearchControls) { - SearchControls s0 = (SearchControls) arg0; - SearchControls s1 = (SearchControls) arg1; + public void testUnbind_NamingException() throws Exception { + expectGetReadWriteContext(); - return s0.getSearchScope() == s1.getSearchScope() - && s0.getReturningObjFlag() == s1.getReturningObjFlag() - && s0.getDerefLinkFlag() == s1.getDerefLinkFlag() - && s0.getCountLimit() == s1.getCountLimit() - && s0.getTimeLimit() == s1.getTimeLimit() - && s0.getReturningAttributes() == s1 - .getReturningAttributes(); - } else { - return super.argumentMatches(arg0, arg1); - } - } - } + dirContextMock.unbind(nameMock); + javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException(); + dirContextControl.setThrowable(ne); + dirContextMock.close(); + + replay(); + + try { + tested.unbind(nameMock); + fail("NameNotFoundException expected"); + } + catch (NameNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testExecuteReadOnly() throws Exception { + expectGetReadOnlyContext(); + + Object object = new Object(); + contextExecutorControl.expectAndReturn(contextExecutorMock.executeWithContext(dirContextMock), object); + + dirContextMock.close(); + + replay(); + + Object result = tested.executeReadOnly(contextExecutorMock); + + verify(); + + assertSame(object, result); + } + + public void testExecuteReadOnly_NamingException() throws Exception { + expectGetReadOnlyContext(); + + javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException(); + contextExecutorControl.expectAndThrow(contextExecutorMock.executeWithContext(dirContextMock), ne); + + dirContextMock.close(); + + replay(); + + try { + tested.executeReadOnly(contextExecutorMock); + fail("NameNotFoundException expected"); + } + catch (NameNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testExecuteReadWrite() throws Exception { + expectGetReadWriteContext(); + + Object object = new Object(); + contextExecutorControl.expectAndReturn(contextExecutorMock.executeWithContext(dirContextMock), object); + + dirContextMock.close(); + + replay(); + + Object result = tested.executeReadWrite(contextExecutorMock); + + verify(); + + assertSame(object, result); + } + + public void testExecuteReadWrite_NamingException() throws Exception { + expectGetReadWriteContext(); + + javax.naming.NameNotFoundException ne = new javax.naming.NameNotFoundException(); + contextExecutorControl.expectAndThrow(contextExecutorMock.executeWithContext(dirContextMock), ne); + + dirContextMock.close(); + + replay(); + + try { + tested.executeReadWrite(contextExecutorMock); + fail("NameNotFoundException expected"); + } + catch (NameNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testDoSearch_DirContextProcessor() throws Exception { + expectGetReadOnlyContext(); + + SearchResult searchResult = new SearchResult(null, null, null); + + dirContextProcessorMock.preProcess(dirContextMock); + + searchExecutorControl.expectAndReturn(searchExecutorMock.executeSearch(dirContextMock), namingEnumerationMock); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); + + handlerMock.handleNameClassPair(searchResult); + + dirContextProcessorMock.postProcess(dirContextMock); + + dirContextMock.close(); + + replay(); + + tested.search(searchExecutorMock, handlerMock, dirContextProcessorMock); + + verify(); + } + + public void testDoSearch_DirContextProcessor_NamingException() throws Exception { + expectGetReadOnlyContext(); + + dirContextProcessorMock.preProcess(dirContextMock); + + javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); + searchExecutorControl.expectAndThrow(searchExecutorMock.executeSearch(dirContextMock), ne); + + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock, dirContextProcessorMock); + fail("LimitExceededException expected"); + } + catch (LimitExceededException expected) { + assertTrue(true); + } + + verify(); + } + + public void testDoSearch() throws Exception { + expectGetReadOnlyContext(); + + SearchResult searchResult = new SearchResult(null, null, null); + + searchExecutorControl.expectAndReturn(searchExecutorMock.executeSearch(dirContextMock), namingEnumerationMock); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); + + handlerMock.handleNameClassPair(searchResult); + + dirContextMock.close(); + + replay(); + + tested.search(searchExecutorMock, handlerMock); + + verify(); + } + + public void testDoSearch_NamingException() throws Exception { + expectGetReadOnlyContext(); + + javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); + searchExecutorControl.expectAndThrow(searchExecutorMock.executeSearch(dirContextMock), ne); + + dirContextMock.close(); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock); + fail("LimitExceededException expected"); + } + catch (LimitExceededException expected) { + assertTrue(true); + } + + verify(); + } + + public void testDoSearch_NamingException_NamingEnumeration() throws Exception { + expectGetReadOnlyContext(); + + searchExecutorControl.expectAndReturn(searchExecutorMock.executeSearch(dirContextMock), namingEnumerationMock); + + javax.naming.LimitExceededException ne = new javax.naming.LimitExceededException(); + namingEnumerationControl.expectAndThrow(namingEnumerationMock.hasMore(), ne); + namingEnumerationMock.close(); + + dirContextMock.close(); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock); + fail("LimitExceededException expected"); + } + catch (LimitExceededException expected) { + assertTrue(true); + } + + verify(); + } + + public void testDoSearch_NameNotFoundException() throws Exception { + expectGetReadOnlyContext(); + + searchExecutorControl.expectAndThrow(searchExecutorMock.executeSearch(dirContextMock), + new javax.naming.NameNotFoundException()); + dirContextMock.close(); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock); + fail("NameNotFoundException expected"); + } + catch (NameNotFoundException expected) { + assertTrue(true); + } + + verify(); + } + + public void testSearch_PartialResult_IgnoreNotSet() throws Exception { + expectGetReadOnlyContext(); + + dirContextProcessorMock.preProcess(dirContextMock); + + javax.naming.PartialResultException ex = new javax.naming.PartialResultException(); + searchExecutorControl.expectAndThrow(searchExecutorMock.executeSearch(dirContextMock), ex); + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); + + replay(); + + try { + tested.search(searchExecutorMock, handlerMock, dirContextProcessorMock); + fail("PartialResultException expected"); + } + catch (PartialResultException expected) { + assertTrue(true); + } + + verify(); + } + + public void testSearch_PartialResult_IgnoreSet() throws Exception { + tested.setIgnorePartialResultException(true); + + expectGetReadOnlyContext(); + + dirContextProcessorMock.preProcess(dirContextMock); + + searchExecutorControl.expectAndThrow(searchExecutorMock.executeSearch(dirContextMock), + new javax.naming.PartialResultException()); + + dirContextProcessorMock.postProcess(dirContextMock); + dirContextMock.close(); + + replay(); + + tested.search(searchExecutorMock, handlerMock, dirContextProcessorMock); + + verify(); + } + + public void testLookupContextWithName() { + final DirContextAdapter expectedResult = new DirContextAdapter(); + + LdapTemplate tested = new LdapTemplate() { + public Object lookup(Name dn) { + assertSame(DistinguishedName.EMPTY_PATH, dn); + return expectedResult; + } + }; + + DirContextOperations result = tested.lookupContext(DistinguishedName.EMPTY_PATH); + assertSame(expectedResult, result); + + } + + public void testLookupContextWithString() { + final DirContextAdapter expectedResult = new DirContextAdapter(); + final String expectedName = "cn=John Doe"; + + LdapTemplate tested = new LdapTemplate() { + public Object lookup(String dn) { + assertSame(expectedName, dn); + return expectedResult; + } + }; + + DirContextOperations result = tested.lookupContext(expectedName); + assertSame(expectedResult, result); + } + + public void testModifyAttributesWithDirContextOperations() throws Exception { + final ModificationItem[] expectedModifications = new ModificationItem[0]; + + dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock.getDn(), DistinguishedName.EMPTY_PATH); + dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock.isUpdateMode(), true); + dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock.getModificationItems(), + expectedModifications); + + LdapTemplate tested = new LdapTemplate() { + public void modifyAttributes(Name dn, ModificationItem[] mods) { + assertSame(DistinguishedName.EMPTY_PATH, dn); + assertSame(expectedModifications, mods); + } + }; + + replay(); + + tested.modifyAttributes(dirContextOperationsMock); + + verify(); + } + + public void testModifyAttributesWithDirContextOperationsNotInitializedDn() throws Exception { + + dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock.getDn(), DistinguishedName.EMPTY_PATH); + dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock.isUpdateMode(), false); + + LdapTemplate tested = new LdapTemplate() { + public void modifyAttributes(Name dn, ModificationItem[] mods) { + fail("The call to the base modifyAttributes should not have occured."); + } + }; + + replay(); + + try { + tested.modifyAttributes(dirContextOperationsMock); + fail("IllegalStateException expected"); + } + catch (IllegalStateException expected) { + assertTrue(true); + } + verify(); + } + + public void testModifyAttributesWithDirContextOperationsNotInitializedInUpdateMode() throws Exception { + + dirContextOperationsConrol.expectAndReturn(dirContextOperationsMock.getDn(), null); + + LdapTemplate tested = new LdapTemplate() { + public void modifyAttributes(Name dn, ModificationItem[] mods) { + fail("The call to the base modifyAttributes should not have occured."); + } + }; + + replay(); + + try { + tested.modifyAttributes(dirContextOperationsMock); + fail("IllegalStateException expected"); + } + catch (IllegalStateException expected) { + assertTrue(true); + } + verify(); + } + + public void testSearchForObject() throws Exception { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(2); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + Object result = tested.searchForObject(nameMock, "(ou=somevalue)", contextMapperMock); + + verify(); + + assertNotNull(result); + assertSame(expectedResult, result); + } + + public void testSearchForObjectWithMultipleResults() throws Exception { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(2); + controls.setReturningObjFlag(true); + + Object expectedObject = new Object(); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); + + dirContextControl.setDefaultMatcher(new SearchControlsMatcher()); + dirContextControl.expectAndReturn(dirContextMock.search(nameMock, "(ou=somevalue)", controls), + namingEnumerationMock); + + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), true); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.next(), searchResult); + namingEnumerationControl.expectAndReturn(namingEnumerationMock.hasMore(), false); + namingEnumerationMock.close(); + + Object expectedResult = expectedObject; + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); + contextMapperControl.expectAndReturn(contextMapperMock.mapFromContext(expectedObject), expectedResult); + + dirContextMock.close(); + + replay(); + + try { + tested.searchForObject(nameMock, "(ou=somevalue)", contextMapperMock); + fail("IncorrectResultSizeDataAccessException expected"); + } + catch (IncorrectResultSizeDataAccessException expected) { + assertTrue(true); + } + + verify(); + } + + public void testSearchForObjectWithNoResults() throws Exception { + expectGetReadOnlyContext(); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(2); + controls.setReturningObjFlag(true); + + setupSearchAndNamingEnumerationForNoHits(controls); + + dirContextMock.close(); + + replay(); + + try { + tested.searchForObject(nameMock, "(ou=somevalue)", contextMapperMock); + fail("EmptyResultDataAccessException expected"); + } + catch (EmptyResultDataAccessException expected) { + assertTrue(true); + } + verify(); + } + + public void testAuthenticate() throws Exception { + contextSourceControl.expectAndReturn(contextSourceMock.getReadOnlyContext(), dirContextMock); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(2); + controls.setReturningObjFlag(true); + + Object expectedObject = new DirContextAdapter(new BasicAttributes(), new DistinguishedName("cn=john doe"), + new DistinguishedName("dc=jayway, dc=se")); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + MockControl authenticatedContextControl = MockControl.createControl(DirContext.class); + DirContext authenticatedContextMock = (DirContext) authenticatedContextControl.getMock(); + + MockControl entryContextCallbackControl = MockControl + .createControl(AuthenticatedLdapEntryContextCallback.class); + AuthenticatedLdapEntryContextCallback entryContextCallbackMock = (AuthenticatedLdapEntryContextCallback) entryContextCallbackControl + .getMock(); + + contextSourceControl.expectAndReturn(contextSourceMock.getContext("cn=john doe,dc=jayway,dc=se", "password"), + authenticatedContextMock); + entryContextCallbackMock.executeWithContext(authenticatedContextMock, new LdapEntryIdentification( + new DistinguishedName("cn=john doe,dc=jayway,dc=se"), new DistinguishedName("cn=john doe"))); + + authenticatedContextMock.close(); + dirContextMock.close(); + + replay(); + authenticatedContextControl.replay(); + entryContextCallbackControl.replay(); + + boolean result = tested.authenticate(nameMock, "(ou=somevalue)", "password", entryContextCallbackMock); + + verify(); + authenticatedContextControl.verify(); + entryContextCallbackControl.verify(); + + assertTrue(result); + } + + public void testAuthenticateWithFailedAuthentication() throws Exception { + contextSourceControl.expectAndReturn(contextSourceMock.getReadOnlyContext(), dirContextMock); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(2); + controls.setReturningObjFlag(true); + + Object expectedObject = new DirContextAdapter(new BasicAttributes(), new DistinguishedName("cn=john doe"), + new DistinguishedName("dc=jayway, dc=se")); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + MockControl entryContextCallbackControl = MockControl + .createControl(AuthenticatedLdapEntryContextCallback.class); + AuthenticatedLdapEntryContextCallback entryContextCallbackMock = (AuthenticatedLdapEntryContextCallback) entryContextCallbackControl + .getMock(); + + contextSourceControl.expectAndThrow(contextSourceMock.getContext("cn=john doe,dc=jayway,dc=se", "password"), + new UncategorizedLdapException("Authentication failed")); + + dirContextMock.close(); + + replay(); + entryContextCallbackControl.replay(); + + boolean result = tested.authenticate(nameMock, "(ou=somevalue)", "password", entryContextCallbackMock); + + verify(); + entryContextCallbackControl.verify(); + + assertFalse(result); + } + + public void testAuthenticateWithErrorInCallback() throws Exception { + contextSourceControl.expectAndReturn(contextSourceMock.getReadOnlyContext(), dirContextMock); + + SearchControls controls = new SearchControls(); + controls.setSearchScope(2); + controls.setReturningObjFlag(true); + + Object expectedObject = new DirContextAdapter(new BasicAttributes(), new DistinguishedName("cn=john doe"), + new DistinguishedName("dc=jayway, dc=se")); + SearchResult searchResult = new SearchResult("", expectedObject, new BasicAttributes()); + + setupSearchAndNamingEnumeration(controls, searchResult); + + MockControl authenticatedContextControl = MockControl.createControl(DirContext.class); + DirContext authenticatedContextMock = (DirContext) authenticatedContextControl.getMock(); + + MockControl entryContextCallbackControl = MockControl + .createControl(AuthenticatedLdapEntryContextCallback.class); + AuthenticatedLdapEntryContextCallback entryContextCallbackMock = (AuthenticatedLdapEntryContextCallback) entryContextCallbackControl + .getMock(); + + contextSourceControl.expectAndReturn(contextSourceMock.getContext("cn=john doe,dc=jayway,dc=se", "password"), + authenticatedContextMock); + entryContextCallbackMock.executeWithContext(authenticatedContextMock, new LdapEntryIdentification( + new DistinguishedName("cn=john doe,dc=jayway,dc=se"), new DistinguishedName("cn=john doe"))); + entryContextCallbackControl.setThrowable(new UncategorizedLdapException("Authentication failed")); + + authenticatedContextMock.close(); + dirContextMock.close(); + + replay(); + authenticatedContextControl.replay(); + entryContextCallbackControl.replay(); + + boolean result = tested.authenticate(nameMock, "(ou=somevalue)", "password", entryContextCallbackMock); + + verify(); + authenticatedContextControl.verify(); + entryContextCallbackControl.verify(); + + assertFalse(result); + } + /** + * Needed to verify search control values. + * + * @author Mattias Hellborg Arthursson + */ + private static class SearchControlsMatcher extends AbstractMatcher { + protected boolean argumentMatches(Object arg0, Object arg1) { + if (arg0 instanceof SearchControls && arg1 instanceof SearchControls) { + SearchControls s0 = (SearchControls) arg0; + SearchControls s1 = (SearchControls) arg1; + + return s0.getSearchScope() == s1.getSearchScope() + && s0.getReturningObjFlag() == s1.getReturningObjFlag() + && s0.getDerefLinkFlag() == s1.getDerefLinkFlag() && s0.getCountLimit() == s1.getCountLimit() + && s0.getTimeLimit() == s1.getTimeLimit() + && s0.getReturningAttributes() == s1.getReturningAttributes(); + } + else { + return super.argumentMatches(arg0, arg1); + } + } + } } diff --git a/test-support/src/main/java/org/springframework/ldap/test/AttributeCheckContextMapper.java b/test-support/src/main/java/org/springframework/ldap/test/AttributeCheckContextMapper.java index d2cedaef..434d7103 100644 --- a/test-support/src/main/java/org/springframework/ldap/test/AttributeCheckContextMapper.java +++ b/test-support/src/main/java/org/springframework/ldap/test/AttributeCheckContextMapper.java @@ -49,7 +49,7 @@ public class AttributeCheckContextMapper implements ContextMapper { Assert.assertNull(adapter.getStringAttribute(absentAttributes[i])); } - return null; + return adapter; } public void setAbsentAttributes(String[] absentAttributes) { diff --git a/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateAuthenticationITest.java b/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateAuthenticationITest.java new file mode 100644 index 00000000..c9110628 --- /dev/null +++ b/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateAuthenticationITest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2005-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.assertTrue; + +import javax.naming.NamingException; +import javax.naming.directory.Attributes; + +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ldap.core.AttributesMapper; +import org.springframework.ldap.core.ContextMapper; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DistinguishedName; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.support.AbstractContextSource; +import org.springframework.ldap.filter.AndFilter; +import org.springframework.ldap.filter.EqualsFilter; +import org.springframework.ldap.filter.WhitespaceWildcardsFilter; +import org.springframework.test.context.ContextConfiguration; + +/** + * Tests the lookup methods of LdapTemplate. + * + * @author Mattias Hellborg Arthursson + * @author Ulrik Sandberg + */ +@ContextConfiguration(locations = { "/conf/ldapTemplateTestContext.xml" }) +public class LdapTemplateAuthenticationITest extends AbstractLdapTemplateIntegrationTest { + + @Autowired + private LdapTemplate tested; + + @Test + public void testAuthenticate() { + AndFilter filter = new AndFilter(); + filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("uid", "some.person3")); + assertTrue(tested.authenticate("", filter.toString(), "password")); + } + + @Test + public void testAuthenticateWithInvalidPassword() { + AndFilter filter = new AndFilter(); + filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("uid", "some.person3")); + assertFalse(tested.authenticate("", filter.toString(), "invalidpassword")); + } + + @Test + public void testAuthenticateWithFilterThatDoesNotMatchAnything() { + AndFilter filter = new AndFilter(); + filter.and(new EqualsFilter("objectclass", "person")).and( + new EqualsFilter("uid", "some.person.that.isnt.there")); + assertFalse(tested.authenticate("", filter.toString(), "password")); + } + + @Test + public void testAuthenticateWithFilterThatMatchesSeveralEntries() { + AndFilter filter = new AndFilter(); + filter.and(new EqualsFilter("objectclass", "person")).and(new WhitespaceWildcardsFilter("uid", "some.person")); + assertFalse(tested.authenticate("", filter.toString(), "password")); + } +} diff --git a/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateSearchResultITest.java b/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateSearchResultITest.java index 4684e6de..7b0f764e 100644 --- a/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateSearchResultITest.java +++ b/test/integration-tests/src/test/java/org/springframework/ldap/LdapTemplateSearchResultITest.java @@ -16,6 +16,7 @@ package org.springframework.ldap; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -28,8 +29,13 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DistinguishedName; import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.support.AbstractContextMapper; import org.springframework.ldap.test.AttributeCheckAttributesMapper; import org.springframework.ldap.test.AttributeCheckContextMapper; import org.springframework.test.context.ContextConfiguration; @@ -140,6 +146,35 @@ public class LdapTemplateSearchResultITest extends AbstractLdapTemplateIntegrati assertEquals(1, list.size()); } + @Test + public void testSearchForObject() { + contextMapper.setExpectedAttributes(ALL_ATTRIBUTES); + contextMapper.setExpectedValues(ALL_VALUES); + DirContextAdapter result = (DirContextAdapter) tested + .searchForObject(BASE_STRING, FILTER_STRING, contextMapper); + assertNotNull(result); + } + + @Test(expected = IncorrectResultSizeDataAccessException.class) + public void testSearchForObjectWithMultipleHits() { + tested.searchForObject(BASE_STRING, "(&(objectclass=person)(sn=*))", new AbstractContextMapper() { + @Override + protected Object doMapFromContext(DirContextOperations ctx) { + return ctx; + } + }); + } + + @Test(expected = EmptyResultDataAccessException.class) + public void testSearchForObjectNoHits() { + tested.searchForObject(BASE_STRING, "(&(objectclass=person)(sn=Person does not exist))", new AbstractContextMapper() { + @Override + protected Object doMapFromContext(DirContextOperations ctx) { + return ctx; + } + }); + } + @Test public void testSearch_SearchScope_ContextMapper() { contextMapper.setExpectedAttributes(ALL_ATTRIBUTES); diff --git a/test/integration-tests/src/test/java/org/springframework/ldap/core/simple/SimpleLdapTemplateITest.java b/test/integration-tests/src/test/java/org/springframework/ldap/core/simple/SimpleLdapTemplateITest.java index 60831853..36197ef4 100644 --- a/test/integration-tests/src/test/java/org/springframework/ldap/core/simple/SimpleLdapTemplateITest.java +++ b/test/integration-tests/src/test/java/org/springframework/ldap/core/simple/SimpleLdapTemplateITest.java @@ -33,6 +33,8 @@ import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DirContextProcessor; import org.springframework.ldap.core.DistinguishedName; +import org.springframework.ldap.filter.AndFilter; +import org.springframework.ldap.filter.EqualsFilter; import org.springframework.test.context.ContextConfiguration; @ContextConfiguration(locations = { "/conf/simpleLdapTemplateTestContext.xml" }) @@ -65,6 +67,12 @@ public class SimpleLdapTemplateITest extends AbstractLdapTemplateIntegrationTest assertEquals("Some Person3", cns.get(0)); } + @Test + public void testSearchForObject() { + String cn = ldapTemplate.searchForObject("", "(&(objectclass=person)(sn=Person3))", new CnContextMapper()); + assertEquals("Some Person3", cn); + } + @Test public void testSearchProcessor() { SearchControls searchControls = new SearchControls(); @@ -184,6 +192,13 @@ public class SimpleLdapTemplateITest extends AbstractLdapTemplateIntegrationTest verifyCleanup(); } + @Test + public void testAuthenticate() { + AndFilter filter = new AndFilter(); + filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("uid", "some.person3")); + assertTrue(ldapTemplate.authenticate("", filter.toString(), "password")); + } + private void verifyBoundCorrectData() { DirContextOperations result = ldapTemplate.lookupContext(DN_STRING); assertEquals("Some Person4", result.getStringAttribute("cn"));