Chapter 6 Searching the Directory This chapter explains how to use the LDAP Java classes to search the directory and retrieve entries. The chapter also describes how to get attributes and attribute values from an entry. This chapter covers the following topics:
This chapter explains how to use the LDAP Java classes to search the directory and retrieve entries. The chapter also describes how to get attributes and attribute values from an entry.
"Overview: Searching with the LDAP Java Classes"
"Sending a Search Request"
"Getting the Search Results"
"Sorting the Search Results"
"Abandoning a Search"
"Example: Searching the Directory"
"Reading an Entry"
"Listing Subentries"
You can send a search request by invoking the search method of the LDAPConnection object.
You can specify a set of search constraints (such as the maximum number of results to return or the maximum amount to time allowed for a search) by using an LDAPSearchConstraints object.
You can either specify different parts of the search criteria in separate arguments, or you can construct an LDAPUrl object to specify the search criteria.
The server returns the search results to the LDAP Java classes, which represents the results as an LDAPSearchResults object.
You can search for a single entry by invoking the read method of the LDAPConnection object.
public LDAPSearchResults search(String base, int scope, String filter, String attrs[], boolean attrsOnly, LDAPSearchConstraints cons) throws LDAPException
base specifies the starting point in the directory, or the base DN (an entry where to start searching)
To search entries under "o=Airius.com", the base DN is "o=Airius.com". See "Specifying the Base DN and Scope" for details.
scope specifies the scope of the search (which entries you want to search)
You can narrow the scope of the search to search only the base DN, entries at one level under the base DN, or entries at all levels under the base DN. See "Specifying the Base DN and Scope" for details.
filter specifies a search filter (what to search for)
A search filter can be as simple as "find entries where the last name is Jensen" or as complex as "find entries that belong to Dept. #17 and whose first names start with the letter F." See "Specifying a Search Filter" for details.
attrs and attrsOnly specify the type of information that you want return (which attributes you want to retrieve)
For example, you can return only email addresses and phone numbers, or you can set up a search to return all attributes in an entry. You can also specify that you only want to return the names of attributes, not the values. See "Specifying the Attributes to Retrieve" for details.
cons specifies the search constraints that you want applied to this search
For example, you can set up a set of search constraints that differs from the default set of constraints. See "Setting Search Preferences" for details.
Figure 6.1    Search criteria
of an LDAP search operation
LDAPv2.SCOPE_SUB searches the base entry and all entries at all levels below the base entry (as illustrated in Figure 6.2).
Figure 6.2    Example of a search with the scope LDAPv2.SCOPE_SUB
LDAPv2.SCOPE_ONE searches all entries at one level below the base entry (as illustrated in Figure 6.3). The base entry is not included in the search. Use this setting if you just want a list of the entries under a given entry. (See "Listing Subentries" for an example.)
Figure 6.3    Example of a search with the scope LDAPv2.SCOPE_ONE
LDAPv2.SCOPE_BASE searches only the base entry. Use this setting if you just want to read the attributes of the base entry (as illustrated in Figure 6.4). (See "Reading an Entry" for an example.)
Figure 6.4    Example of a search with the scope LDAPv2.SCOPE_BASE
(attribute operator value)
(cn=Barbara Jensen)
=
>=
(sn >= jensen)
<=
(sn <= jensen)
=*
(sn =*)
~=
(sn ~= jensen)
(sn<=jensen)
( boolean_operator (filter1)(filter2)(filter3) )
&
|
!
(|(sn=Jensen)(sn=Johnson))
(givenName=F*)
To return selected attributes, pass an array of the attribute names as the attrs argument. For example, to return only email addresses and phone numbers, pass the array {"mail", "telephoneNumber"} as the attrs argument.
To return all attributes in an entry, pass null as the attrs argument.
To return none of the attributes from an entry, pass LDAPv3.NO_ATTRS as the attrs argument.
Setting Preferences for All Searches
Overriding Preferences on Individual Searches
Configuring the Search to Wait for All Results
Setting Size and Time Limits
To get the default set of search constraints for the connection, you can use the getSearchConstraints method
To get or set any of the search constraints individually, you can use the getOption method and the setOption method.
LDAPConnection ld = new LDAPConnection(); ld.connect( "ldap.airius.com", LDAPv2.DEFAULT_PORT ); ld.setOption( LDAPv2.SIZELIMIT, new Integer( 100 ) );
Use the setOption methodof the LDAPConnection object to set the LDAPv2.BATCHSIZE preference to 0.
Pass a 0 to the setBatchSize method of the LDAPSearchConstraints object to change this for a particular set of search constraints.
Use the setOption methodof the LDAPConnection object to set the LDAPv2.SIZELIMIT and LDAPv2.TIMELIMIT preferences.
Use the setMaxResults method and the setTimeLimit method of the LDAPSearchConstraints object to change this for a particular set of search constraints.
If the size limit is exceeded, the server returns an LDAPException.SIZE_LIMIT_EXCEEDED result code.
If the time limit is exceeded, the server returns an LDAPException.TIME_LIMIT_EXCEEDED result code.)
... LDAPConnection ld = null; try { /* Create a new LDAPConnection object. */ ld = new LDAPConnection(); /* Connect and bind to the server. */ String HOSTNAME = "localhost"; ld.connect( HOSTNAME, DEFAULT_PORT, null, null ); /* Specify the search criteria. */ String baseDN = "o=Airius.com"; int searchScope = LDAPv2.SCOPE_SUB; String searchFilter = "(sn=Jensen)"; String getAttrs[] = {"cn", "mail", "telephoneNumber"}; /* Send the search request. */ LDAPSearchResults res = ld.search( baseDN, searchScope, searchFilter, getAttrs, false ); ... } catch( LDAPException e ) { System.out.println( "Error: " + e.toString ); } ...
Figure 6.5    Search results in terms of entries, attributes, and values
For information on getting individual entries from the results, see "Getting Entries from the Results".
For information on getting the DN of an entry, see "Getting Distinguished Names from the Results".
For information on getting the attributes of an entry, see "Getting Attributes from an Entry".
For information on getting the values of an attribute, see "Getting the Name and Values of an Attribute".
When you invoke the next method, if the next item in the search results is an entry, the method returns an LDAPEntry object.
If the next item is a search reference, one of the following can occur:
If referrals are not followed automatically, or if the referral hop limit has been exceeded, an LDAPReferralException is thrown.
If referrals are followed automatically and if the referral hop limit has not been exceeded, the LDAP Java classes follow the referral and retrieve the entry for you. (The method creates a new connection to the server specified in the referral and attempts to retrieve the entry from that server.)
For information about referrals and search references, see "Handling Referrals".
If the next item is an LDAP result code such as ADMIN_LIMIT_EXCEEDED, TIME_LIMIT_EXCEEDED, or SIZE_LIMIT_EXCEEDED, the LDAP Java classes throw an LDAPException.
When you invoke the nextElement method, the method returns an object that you must cast. The object is an LDAPEntry object, an LDAPReferralException, or an LDAPException.
... LDAPConnection ld = null; try { /* Create a new LDAPConnection object. */ ld = new LDAPConnection(); ... /* Send the search request. */ LDAPSearchResults res = ld.search( baseDN, searchScope, searchFilter, getAttrs, false ); /* Iterate through the results until finished. */ while ( res.hasMoreElements() ) { /* Get the next entry in the results. */ LDAPEntry findEntry = null; try { findEntry = res.next(); /* If it is a search reference, print the LDAP URLs in the reference. */ } catch ( LDAPReferralException e ) { System.out.println( "Search references: " ); LDAPUrl refUrls[] = e.getURLs(); for ( int i=0; i < refUrls.length; i++ ) { System.out.println( "\t" + refUrls[i].getUrl() ); } continue; } catch ( LDAPException e ) { System.out.println( "Error: " + e.toString() ); continue; } ... } ... } catch ( LDAPException e ) { ...}
... LDAPEntry nextEntry = res.next(); String nextDN = nextEntry.getDN(); ...
... LDAPEntry nextEntry = res.next(); LDAPAttributeSet entryAttrs = nextEntry.getAttributeSet(); ...
... /* Get the set of attributes for an entry. */ LDAPAttributeSet entryAttrs = nextEntry.getAttributeSet(); /* Get an enumeration of those attribute. */ Enumeration enumAttrs = entryAttrs.getAttributes(); /* Loop through the enumeration to get each attribute. */ while ( enumAttrs.hasMoreElements() ) { LDAPAttribute nextAttr = (LDAPAttribute)enumAttrs.nextElement(); ... } ...
To get a specific attribute from an LDAPEntry object, invoke the getAttribute method.
To get a specific attribute from an LDAPAttributeSet object by invoking the getAttribute method.
... LDAPEntry nextEntry = res.next(); LDAPAttribute anAttr = nextEntry.getAttribute( "cn" ); ...
... LDAPAttribute nextAttr = (LDAPAttribute)enumAttrs.nextElement(); String attrName = nextAttr.getName(); ...
To get the string values, invoke the getStringValues method.
To get the binary values as byte arrays, invoke the getByteValues method.
... LDAPAttribute nextAttr = (LDAPAttribute)enumAttrs.nextElement(); /* Get and print the attribute name. */ String attrName = nextAttr.getName(); System.out.println( "\t" + attrName + ":" ); /* Iterate through the attribute's values. */ Enumeration enumVals = nextAttr.getStringValues(); if (enumVals != null) { while ( enumVals.hasMoreElements() ) { String nextValue = ( String )enumVals.nextElement(); System.out.println( "\t\t" + nextValue ); } } ...
You can specify that the LDAP server should sort the results before returning the results to your client.
To do this, you need to send a server-side sorting control to the server. For details, see Chapter 13, "Working with LDAP Controls". Note that in the Netscape Directory Server, server-side sorting works best if you specify a filter that uses an indexed attribute.
After you receive the results from the server, you can sort them on your client.
To do this, you need to specify the names of the attributes that you want to use for sorting. You also need to specify whether or not the sorting is done in ascending or descending order.
... LDAPConnection ld = new LDAPConnection(); ld.connect( ... ); LDAPSearchResults res = ld.search( ... ); String[] sortAttrs = {"sn", "cn"}; boolean[] ascending = {true, true}; res.sort( new LDAPCompareAttrNames(sortAttrs, ascending) ); ...
If all search results have not yet been returned, the sort method will block until all results have been received.
... import netscape.ldap.*; import java.util.*; public class Search { public static void main( String[] args ) { LDAPConnection ld = null; int status = -1; try { ld = new LDAPConnection(); /* Connect to the server. */ String MY_HOST = "localhost"; int MY_PORT = 389; ld.connect( MY_HOST, MY_PORT ); /* Search for all entries with surname of Jensen. */ String MY_FILTER = "sn=Jensen"; String MY_SEARCHBASE = "o=Airius.com"; /* Send the search request. */ LDAPSearchResults res = ld.search( MY_SEARCHBASE, LDAPConnection.SCOPE_SUB, MY_FILTER, null, false ); /* Sort the results first by last name, then by first. */ String[] sortAttrs = {"sn", "cn"}; boolean[] ascending = {true, true}; res.sort( new LDAPCompareAttrNames(sortAttrs, ascending) ); /* Iterate through and print out the results. */ while ( res.hasMoreElements() ) { /* Get the next directory entry. */ LDAPEntry findEntry = null; try { findEntry = res.next(); /* If the next result is a search reference, print the LDAP URLs in that reference. */ } catch ( LDAPReferralException e ) { System.out.println( "Search references: " ); LDAPUrl refUrls[] = e.getURLs(); for ( int i=0; i < refUrls.length; i++ ) { System.out.println( "\t" + refUrls[i].getURL() ); } continue; } catch ( LDAPException e ) { System.out.println( "Error: " + e.toString() ); continue; } /* Print the DN of the entry. */ System.out.println( findEntry.getDN() ); /* Get the attributes of the entry */ LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); Enumeration enumAttrs = findAttrs.getAttributes(); System.out.println( "\tAttributes: " ); /* Loop on attributes */ while ( enumAttrs.hasMoreElements()) { LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement(); String attrName = anAttr.getName(); System.out.println( "\t\t" + attrName ); /* Loop on values for this attribute */ Enumeration enumVals = anAttr.getStringValues(); if (enumVals != null) { while ( enumVals.hasMoreElements() ) { String aVal = ( String )enumVals.nextElement(); System.out.println( "\t\t\t" + aVal ); } } } } status = 0; } catch( LDAPException e ) { System.out.println( "Error: " + e.toString() ); } /* Done, so disconnect */ if ( (ld != null) && ld.isConnected() ) { try { ld.disconnect(); } catch ( LDAPException e ) { System.out.println( "Error: " + e.toString() ); } } System.exit(status); } }
import netscape.ldap.*; import java.util.*; public class RdEntry { public static void main( String[] args ) { LDAPConnection ld = null; int status = -1; try { ld = new LDAPConnection(); /* Connect to the server. */ String MY_HOST = "localhost"; int MY_PORT = 389; ld.connect( MY_HOST, MY_PORT ); /* Get the specified entry and all of its attributes. */ String ENTRYDN = "uid=bjensen, ou=People, o=Airius.com"; LDAPEntry findEntry = ld.read( ENTRYDN ); /* Get and print the DN of the entry. */ System.out.println( findEntry.getDN() ); /* Get the set of attributes in the entry. */ LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); Enumeration enumAttrs = findAttrs.getAttributes(); System.out.println( "\tAttributes: " ); /* Get each individual attribute. */ while ( enumAttrs.hasMoreElements() ) { LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement(); /* Get and print the attribute name. */ String attrName = anAttr.getName(); System.out.println( "\t\t" + attrName ); /* Get and print each value of this attribute. */ Enumeration enumVals = anAttr.getStringValues(); if (enumVals != null) { while ( enumVals.hasMoreElements() ) { String aVal = ( String )enumVals.nextElement(); System.out.println( "\t\t\t" + aVal ); } } } } catch( LDAPException e ) { System.out.println( "Error: " + e.toString() ); } /* Done, so disconnect from the server. */ if ( (ld != null) && ld.isConnected() ) { try { ld.disconnect(); } catch ( LDAPException e ) { System.out.println( "Error: " + e.toString() ); } } System.exit(status); } }
Figure 6.6    Using the LDAPv2.SCOPE_ONE scope to list subentries
... import netscape.ldap.*; import java.util.*; ... LDAPConnection ld = null; try { ld = new LDAPConnection(); /* Connect to the server. */ String MY_HOST = "localhost"; int MY_PORT = LDAPv2.DEFAULT_PORT; ld.connect( MY_HOST, MY_PORT ); /* Search for all entries at this level. */ String MY_FILTER = "objectclass=*"; String MY_SEARCHBASE = "o=Airius.com"; LDAPSearchResults res = ld.search( MY_SEARCHBASE, LDAPConnection.SCOPE_ONE, MY_FILTER, null, false ); /* Loop on results until finished */ while ( res.hasMoreElements() ) { /* Get the next directory entry */ LDAPEntry findEntry = null; try { findEntry = res.next(); /* If the next result is a search reference, print the LDAP URLs in the reference. */ } catch ( LDAPReferralException e ) { System.out.println( "Search references: " ); LDAPUrl refUrls[] = e.getURLs(); for ( int i=0; i < refUrls.length; i++ ) { System.out.println( "\t" + refUrls[i].getUrl() ); } continue; } catch ( LDAPException e ) { System.out.println( "Error: " + e.toString() ); continue; } /* Print the DN of the entry. */ System.out.println( findEntry.getDN() ); /* Get the attributes of the entry */ LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); Enumeration enumAttrs = findAttrs.getAttributes(); System.out.println( "\tAttributes: " ); /* Loop on attributes */ while ( enumAttrs.hasMoreElements() ) { LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement(); String attrName = anAttr.getName(); System.out.println( "\t\t" + attrName ); /* Loop on values for this attribute */ Enumeration enumVals = anAttr.getStringValues(); if (enumVals != null) { while ( enumVals.hasMoreElements() ) { String aVal = ( String )enumVals.nextElement(); System.out.println( "\t\t\t" + aVal ); } } } } } catch( LDAPException e ) { System.out.println( "Error: " + e.toString() ); } /* Done, so disconnect */ if ( (ld != null) && ld.isConnected() ) { try { ld.disconnect(); } catch ( LDAPException e ) { System.out.println( "Error: " + e.toString() ); } ...