Coverage Report - org.acegisecurity.ldap.search.FilterBasedLdapUserSearch
 
Classes in this File Line Coverage Branch Coverage Complexity
FilterBasedLdapUserSearch
73% 
80% 
1.875
 
 1  
 /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 2  
  *
 3  
  * Licensed under the Apache License, Version 2.0 (the "License");
 4  
  * you may not use this file except in compliance with the License.
 5  
  * You may obtain a copy of the License at
 6  
  *
 7  
  *     http://www.apache.org/licenses/LICENSE-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing, software
 10  
  * distributed under the License is distributed on an "AS IS" BASIS,
 11  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
  * See the License for the specific language governing permissions and
 13  
  * limitations under the License.
 14  
  */
 15  
 
 16  
 package org.acegisecurity.ldap.search;
 17  
 
 18  
 import org.acegisecurity.ldap.InitialDirContextFactory;
 19  
 import org.acegisecurity.ldap.LdapTemplate;
 20  
 import org.acegisecurity.ldap.LdapUserSearch;
 21  
 
 22  
 import org.acegisecurity.userdetails.UsernameNotFoundException;
 23  
 import org.acegisecurity.userdetails.ldap.LdapUserDetails;
 24  
 import org.acegisecurity.userdetails.ldap.LdapUserDetailsImpl;
 25  
 import org.acegisecurity.userdetails.ldap.LdapUserDetailsMapper;
 26  
 
 27  
 import org.apache.commons.logging.Log;
 28  
 import org.apache.commons.logging.LogFactory;
 29  
 
 30  
 import org.springframework.dao.IncorrectResultSizeDataAccessException;
 31  
 
 32  
 import org.springframework.util.Assert;
 33  
 
 34  
 import javax.naming.directory.DirContext;
 35  
 import javax.naming.directory.SearchControls;
 36  
 
 37  
 
 38  
 /**
 39  
  * LdapUserSearch implementation which uses an Ldap filter to locate the user.
 40  
  *
 41  
  * @author Robert Sanders
 42  
  * @author Luke Taylor
 43  
  * @version $Id: FilterBasedLdapUserSearch.java 2626 2008-02-14 18:58:08Z luke_t $
 44  
  *
 45  
  * @see SearchControls
 46  
  */
 47  
 public class FilterBasedLdapUserSearch implements LdapUserSearch {
 48  
     //~ Static fields/initializers =====================================================================================
 49  
 
 50  2
     private static final Log logger = LogFactory.getLog(FilterBasedLdapUserSearch.class);
 51  
 
 52  
     //~ Instance fields ================================================================================================
 53  
 
 54  
     private InitialDirContextFactory initialDirContextFactory;
 55  5
     private LdapUserDetailsMapper userDetailsMapper = new LdapUserDetailsMapper();
 56  
 
 57  
     /**
 58  
      * The LDAP SearchControls object used for the search. Shared between searches so shouldn't be modified
 59  
      * once the bean has been configured.
 60  
      */
 61  5
     private SearchControls searchControls = new SearchControls();
 62  
 
 63  
     /** Context name to search in, relative to the root DN of the configured InitialDirContextFactory. */
 64  5
     private String searchBase = "";
 65  
 
 66  
     /**
 67  
      * The filter expression used in the user search. This is an LDAP search filter (as defined in 'RFC 2254')
 68  
      * with optional arguments. See the documentation for the <tt>search</tt> methods in {@link
 69  
      * javax.naming.directory.DirContext DirContext} for more information.<p>In this case, the username is the
 70  
      * only parameter.</p>
 71  
      *  Possible examples are:
 72  
      *  <ul>
 73  
      *      <li>(uid={0}) - this would search for a username match on the uid attribute.</li>
 74  
      *  </ul>
 75  
      *  TODO: more examples.
 76  
      */
 77  
     private String searchFilter;
 78  
 
 79  
     //~ Constructors ===================================================================================================
 80  
 
 81  
     public FilterBasedLdapUserSearch(String searchBase, String searchFilter,
 82  5
             InitialDirContextFactory initialDirContextFactory) {
 83  5
         Assert.notNull(initialDirContextFactory, "initialDirContextFactory must not be null");
 84  5
         Assert.notNull(searchFilter, "searchFilter must not be null.");
 85  5
         Assert.notNull(searchBase, "searchBase must not be null (an empty string is acceptable).");
 86  
 
 87  5
         this.searchFilter = searchFilter;
 88  5
         this.initialDirContextFactory = initialDirContextFactory;
 89  5
         this.searchBase = searchBase;
 90  
 
 91  5
         if (searchBase.length() == 0) {
 92  1
             logger.info("SearchBase not set. Searches will be performed from the root: "
 93  
                 + initialDirContextFactory.getRootDn());
 94  
         }
 95  5
     }
 96  
 
 97  
     //~ Methods ========================================================================================================
 98  
 
 99  
     /**
 100  
      * Return the LdapUserDetails containing the user's information
 101  
      *
 102  
      * @param username the username to search for.
 103  
      *
 104  
      * @return An LdapUserDetails object containing the details of the located user's directory entry
 105  
      *
 106  
      * @throws UsernameNotFoundException if no matching entry is found.
 107  
      */
 108  
     public LdapUserDetails searchForUser(String username) {
 109  5
         if (logger.isDebugEnabled()) {
 110  0
             logger.debug("Searching for user '" + username + "', with user search "
 111  
                 + this.toString());
 112  
         }
 113  
 
 114  5
         LdapTemplate template = new LdapTemplate(initialDirContextFactory);
 115  
 
 116  5
         template.setSearchControls(searchControls);
 117  
 
 118  
         try {
 119  5
             LdapUserDetailsImpl.Essence user = (LdapUserDetailsImpl.Essence) template.searchForSingleEntry(searchBase,
 120  
                     searchFilter, new String[] {username}, userDetailsMapper);
 121  3
             user.setUsername(username);
 122  
 
 123  3
             return user.createUserDetails();
 124  2
         } catch (IncorrectResultSizeDataAccessException notFound) {
 125  2
             if (notFound.getActualSize() == 0) {
 126  1
                 throw new UsernameNotFoundException("User " + username + " not found in directory.");
 127  
             }
 128  
             // Search should never return multiple results if properly configured, so just rethrow
 129  1
             throw notFound;
 130  
         }
 131  
     }
 132  
 
 133  
     /**
 134  
      * Sets the corresponding property on the {@link SearchControls} instance used in the search.
 135  
      *
 136  
      * @param deref the derefLinkFlag value as defined in SearchControls..
 137  
      */
 138  
     public void setDerefLinkFlag(boolean deref) {
 139  1
         searchControls.setDerefLinkFlag(deref);
 140  1
     }
 141  
 
 142  
     /**
 143  
      * If true then searches the entire subtree as identified by context, if false (the default) then only
 144  
      * searches the level identified by the context.
 145  
      *
 146  
      * @param searchSubtree true the underlying search controls should be set to SearchControls.SUBTREE_SCOPE
 147  
      * rather than SearchControls.ONELEVEL_SCOPE.
 148  
      */
 149  
     public void setSearchSubtree(boolean searchSubtree) {
 150  2
         searchControls.setSearchScope(searchSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
 151  2
     }
 152  
 
 153  
     /**
 154  
      * The time to wait before the search fails; the default is zero, meaning forever.
 155  
      *
 156  
      * @param searchTimeLimit the time limit for the search (in milliseconds).
 157  
      */
 158  
     public void setSearchTimeLimit(int searchTimeLimit) {
 159  1
         searchControls.setTimeLimit(searchTimeLimit);
 160  1
     }
 161  
 
 162  
     protected LdapUserDetailsMapper getUserDetailsMapper() {
 163  0
         return userDetailsMapper;
 164  
     }
 165  
 
 166  
     public void setUserDetailsMapper(LdapUserDetailsMapper userDetailsMapper) {
 167  0
         this.userDetailsMapper = userDetailsMapper;
 168  0
     }
 169  
 
 170  
     public String toString() {
 171  0
         StringBuffer sb = new StringBuffer();
 172  
 
 173  0
         sb.append("[ searchFilter: '").append(searchFilter).append("', ");
 174  0
         sb.append("searchBase: '").append(searchBase).append("'");
 175  0
         sb.append(", scope: ")
 176  
           .append(searchControls.getSearchScope() == SearchControls.SUBTREE_SCOPE ? "subtree" : "single-level, ");
 177  0
         sb.append("searchTimeLimit: ").append(searchControls.getTimeLimit());
 178  0
         sb.append("derefLinkFlag: ").append(searchControls.getDerefLinkFlag()).append(" ]");
 179  
 
 180  0
         return sb.toString();
 181  
     }
 182  
 }