Complete Contents
Preface
Chapter 1 Understanding LDAP
Chapter 2 Using the Netscape Directory SDK for Java
Chapter 3 Quick Start
Chapter 4 Writing an LDAP Client
Chapter 5 Using the LDAP Java Classes
Chapter 6 Searching the Directory
Chapter 7 Using Filter Configuration Files
Chapter 8 Adding, Updating, and Deleting Entries
Chapter 9 Comparing Values in Entries
Chapter 10 Working with LDAP URLs
Chapter 11 Getting Server Information
Chapter 12 Connecting Over SSL
Chapter 13 Working with LDAP Controls
Chapter 14 Using SASL Authentication
Chapter 15 Using Netscape's JNDI Service Provider
Chapter 16 Working with Extended Operations
Chapter 17 Using the Asynchronous Interface
Glossary
Directory SDK for Java 4.0 Programmer's Guide: Searching the Directory
Previous Next Contents Index


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:


Overview: Searching with the LDAP Java Classes
In the Netscape Directory SDK for Java, searches are represented by objects of the following classes:

The rest of this chapter explains how to use these classes and methods to search a directory.


Sending a Search Request
To search the directory, use the search method of the LDAPConnection object. The search results are returned in the form of an LDAPSearchResults object.

public LDAPSearchResults search(String base, int scope, 
   String filter, String attrs[], boolean attrsOnly,
   LDAPSearchConstraints cons) throws LDAPException
You need to specify the following information as arguments to the search method:

Figure 6.1 illustrates how search criteria works.

Figure 6.1    Search criteria

of an LDAP search operation

You can also specify the criteria in the form of an LDAP URL. An LDAP URL allows you to specify the hostname and port number of the LDAP server that you want to search. (If you want to search a different LDAP server than the one you are connected to, you can invoke the search method and specify an LDAP URL in the form of an LDAPUrl object.)

For details on using LDAP URLs for searches, see Chapter 10, "Working with LDAP URLs".

Specifying the Base DN and Scope
When sending a search request, you need to specify the base DN and scope of the search to identify the entries that you want searched.

The base DN (the base argument) is the DN of the entry that serves as the starting point of the search.

To specify the scope of the search, you pass one of the following values as the scope parameter:

Figure 6.2    Example of a search with the scope LDAPv2.SCOPE_SUB

Figure 6.3    Example of a search with the scope LDAPv2.SCOPE_ONE

Figure 6.4    Example of a search with the scope LDAPv2.SCOPE_BASE

Specifying a Search Filter
When you search the directory, you use a search filter to define the search. Here is the basic syntax for a search filter:

(attribute operator value)
Here is a simple example of a search filter:

(cn=Barbara Jensen)
In this example, cn is the attribute, = is the operator, and Barbara Jensen is the value. The filter finds entries with the common name Barbara Jensen

For a listing of valid attributes that you can use in your search filter, see the documentation for the LDAP server. (For information on the attributes in the schema for the Netscape Directory Server, see the Administrator's Guide.)

Table 6.1 lists the valid operators you can use.

Table 6.1 Basic operators for search filters
Operator
Description
Example
=
Returns entries whose attribute is equal to the value.
(cn=Barbara Jensen) 
finds the entry "cn=Barbara Jensen"
>=
Returns entries whose attribute is greater than or equal to the value.
(sn >= jensen) 
finds all entries from "sn=jensen" to "sn=z..."
<=
Returns entries whose attribute is less than or equal to the value.
(sn <= jensen) 
finds all entries from "sn=a..." to "sn=jensen"
=*
Returns entries that have a value set for that attribute.
(sn =*) 
finds all entries that have the sn attribute.
~=
Returns entries whose attribute value approximately matches the specified value. Typically, this is an algorithm that matches words that sound alike.
(sn ~= jensen) 
finds the entry "sn = jansen"

Note that when comparing values containing letters, the letter a is less than the value z. For example, the following filter finds all entries with last names beginning with a through jensen:

(sn<=jensen)
Using Boolean operators and parentheses, you can combine different sets of conditions. Here is the syntax for combining search filters:

( boolean_operator (filter1)(filter2)(filter3) ) 
Table 6.2 lists the valid boolean operators you can use.

Table 6.2 Boolean operators for search filters
Boolean Operator
Description
& 
Returns entries matching all specified filter criteria.
| 
Returns entries matching one or more of the filter criteria.
!
Returns entries for which the filter is not true.You can only apply this operator to a single filter. For example, you can use:
(!(filter))

but not:
(!(filter1)(filter2))

For example, you can use this filter to search for all entries with the last name Jensen or the last name Johnson:

(|(sn=Jensen)(sn=Johnson))
You can also include wildcards to search for entries that start with, contain, or end with a given value. For example, you can use this filter to search for all entries whose names begin with the letter F:

(givenName=F*)
Specifying the Attributes to Retrieve
Using the attrs argument, you can either retrieve all attributes in entries returned by the search, or you can specify the attributes that you want returned in the search results. For example, you can specify that you want to return the following attributes:

Note that if you plan to sort the results on your client (see "Sorting the Search Results"), you need to return the attributes that you plan to use for sorting. For example, if you plan to sort by email address, make sure that the mail attribute is returned in the search results.

Some attributes are used by servers for administering the directory. For example, the creatorsName attribute specifies the DN of the user who added the entry.These attributes are called operational attributes.

Servers do not normally return operational attributes in search results unless you specify the attributes by name. For example, if you pass null for the attrs argument to retrieve all of the attributes in entries found by the search, the operational attribute creatorsName will not be returned to your client. You need to explicitly specify the creatorsName attribute in the attrs argument.

To return all attributes in an entry and selected operational attributes, pass a string array containing LDAPv3.ALL_USER_ATTRS and the names of the operational attributes as the attrs argument.

The following table lists some of the operational attributes and the information they contain.

Table 6.3 Information available in operational attributes
Attribute Name
Description of Values
createTimestamp
The time the entry was added to the directory.
modifyTimestamp
The time the entry was last modified.
creatorsName
Distinguished name (DN) of the user who added the entry to the directory.
modifiersName
Distinguished name (DN) of the user who last modified the entry.
subschemaSubentry
Distinguished name (DN) of the subschema entry, which controls the schema for this entry. (See "Getting Schema Information" for details.)

Setting Search Preferences
For a given search, you can apply a set of preferences that determine how the search is performed. For example, you can specify the maximum number of results to be returned or the maximum amount of time to wait for a search.

The LDAPSearchConstraints class represents a set of search constraints. The methods of this class allow you to get and set the constraints.

The rest of this section explains how to set these constraints. The following topics are discussed:

Setting Preferences for All Searches
The LDAPConnection object (which represents a connection to the LDAP server) is associated with a default set of search constraints. These constraints apply to all searches performed over the connection.

For example, if you want to specify the maximum number of results returned, you can either set this constraint for the connection:

LDAPConnection ld = new LDAPConnection();
ld.connect( "ldap.airius.com", LDAPv2.DEFAULT_PORT );
ld.setOption( LDAPv2.SIZELIMIT, new Integer( 100 ) );
Overriding Preferences on Individual Searches
To override the default set of search constraints for a given search request, construct your own LDAPSearchConstraints object and pass it to the search methodof the LDAPConnection object.

You can modify a copy of the existing search constraints and pass the modified set of constraints to the search method. Invoke the getSearchConstraints method of the LDAPConnection object to get the default set of constraints for that connection, then invoke the clone method of the LDAPSearchConstraints object to make a copy of the set.

Configuring the Search to Wait for All Results
By default, the search method of the LDAPConnection object does not block until all results are received. Instead, the search method returns as soon as one of the results has been received.

If you want to change this so that the search method blocks until all results are returned, you can do one of the following:

Note that in either case, you still need to invoke the next method of the returned LDAPSearchResults object to retrieve each individual result.

Setting Size and Time Limits
By default, when you search the directory from a client built with the Netscape Directory SDK for Java, the maximum number of entries to return is set to 1000, and there is no maximum time limit for waiting on an operation to complete.

To change these default values, you can do one of the following:

Setting the size limit or time limit may cause an LDAPException to be thrown if the size limit or time limit is exceeded:

Note that the smallest unit supported by the Netscape Directory Server is seconds, not milliseconds. Since the Netscape Directory SDK for Java allows you to specify the time limit in milliseconds, the value that you specify will be rounded to the nearest second by the Directory Server.

Example of Sending a Search Request
The following section of code searches for all entries with the last name (or surname) "Jensen" in the Airius.com organization. The search retrieves the names and values of the cn, mail, and telephoneNumber attributes.

...
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 );
}
...

Getting the Search Results
When you invoke the search method of an LDAPConnection object to search the directory, the method returns the search results in the form of an LDAPSearchResults object.

The search results consist of an enumeration of entries, which are represented by LDAPEntry objects. The search results can also include smart referrals (also known as a search reference) and exceptions.

Each entry contains a set of attributes, which are represented by LDAPAttributeSet objects. Individual attributes are represented by LDAPAttribute objects. Each attribute has a set of values that you can get.

Figure 6.5 illustrates the relationship between entries, attributes, values, and search results.

Figure 6.5    Search results in terms of entries, attributes, and values

The rest of this section explains the steps for getting data from the search results:

Getting Entries from the Results
The LDAPSearchResults object represents the results of the search. These results can include entries found by the search, search references, and result codes. (If your LDAP client receives an ADMIN_LIMIT_EXCEEDED, TIME_LIMIT_EXCEEDED, or SIZE_LIMIT_EXCEEDED result code from the server, the Netscape Directory SDK for Java adds an exception for this result code to the search results.)

To get entries from the LDAPSearchResults object, you can either invoke the next method or the nextElement method

As you iterate through the search results, you can invoke the hasMoreElements method to determine if you have reached the end of the search results.

For example:

...
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 ) {
   ...}
Getting Distinguished Names from the Results
To get the distinguished name of an LDAPEntry object, invoke the getDN method. This method returns a string. For example:

...
LDAPEntry nextEntry = res.next();
String nextDN = nextEntry.getDN();
...
Note that although the netscape.ldap package includes an LDAPDN class, you typically do not construct objects of this class to represent DNs. The LDAPDN class is mainly a utility class that provides methods for manipulating string DNs. (See "Getting the Components of a Distinguished Name" for details.)

Getting Attributes from an Entry
To get the set of attributes in an LDAPEntry object, invoke the getAttributeSet method. This method returns an LDAPAttributeSet object.

For example:

...
LDAPEntry nextEntry = res.next();
LDAPAttributeSet entryAttrs = nextEntry.getAttributeSet();
...
To get individual attributes from an LDAPAttributeSet object, invoke the getAttributes method. This method returns an enumeration of attributes. You can then iterate through the elements in this enumeration to retrieve individual LDAPAttribute objects.

For example:

...
/* 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 determine the number of attributes in the LDAPAttributeSet object, invoke the size method.

You can also retrieve a specific attribute from the entry or from the attribute set:

Both methods return an LDAPAttribute object.

For example:

...
LDAPEntry nextEntry = res.next();
LDAPAttribute anAttr = nextEntry.getAttribute( "cn" );
...
Getting the Name and Values of an Attribute
To get the name of an LDAPAttribute object, invoke the getName method. For example:

...
LDAPAttribute nextAttr =
   (LDAPAttribute)enumAttrs.nextElement();
String attrName = nextAttr.getName();
...
To get the values in an LDAPAttribute object, you can use the following methods:

Both methods return an enumeration that you can iterate through to retrieve individual results. If an error occurs (for example, if you invoke getStringValues and the values are binary data), the methods return null.

You can also count the number of values in an attribute by invoking the size method of the LDAPAttribute object.

For example:

...
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 );
   }
}
...

Sorting the Search Results
With the Netscape Directory SDK for Java, you can sort the search results in two ways:

You can sort the results on the client by invoking the sort methodof the LDAPSearchResults object.

When invoking this method, you need to pass a comparator object, which is an object of a class that implements the LDAPEntryComparator interface. The Netscape Directory SDK for Java includes an LDAPCompareAttrNames class hat implements this interface. This class specifies how entries are compared with each other and sorted.

To construct an LDAPCompareAttrNames object, you need to specify the attributes that you want to use for sorting and, optionally, the sort order.

For example, the following section of code sorts first by surname ("sn") and then by common name ("cn") in ascending 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) );
...
Note. Since the sorting is done by the client, the attributes used for sorting must be returned in the search results. If you are returning only a subset of attributes in the search results, make sure to include the attributes that you specify in the LDAPCompareAttrNames constructor.

If all search results have not yet been returned, the sort method will block until all results have been received.


Abandoning a Search
At any point during a search operation, you can send a request to the server to abandon (or cancel) the search. To abandon the search, use the abandon method of the LDAPConnection object. Pass in the LDAPSearchResults object that was returned to you when you first invoked the search method.


Example: Searching the Directory
The following section of code prints out the values of all attributes in the entries returned by a search.

...
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);
   }
}

Reading an Entry
To get a single entry from the directory, use the read methodof the LDAPConnection object. You can specify the DN of the entry and (optionally) the attributes that you want to retrieve (if you don't want to get all attributes of the entry back). Or you can specify an LDAP URL that identifies the entry that you want to retrieve.

You can use the same classes and methods described in "Getting Attributes from an Entry" and "Getting the Name and Values of an Attribute" to retrieve data from the entry.

The following section of code gets an entry and prints the values of its attributes.

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);
   }
}

Listing Subentries
To list the subentries beneath a particular entry, set the starting point of the search to the entry, and set the scope of the search to LDAPv2.SCOPE_ONE.

Figure 6.6    Using the LDAPv2.SCOPE_ONE scope to list subentries

The following section of code performs a one-level search.

...
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() );
}
...

 

© Copyright 1999 Netscape Communications Corporation. All rights reserved.