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: Working with LDAP Controls
Previous Next Contents Index


Chapter 13 Working with LDAP Controls

This chapter explains how LDAP controls work and how to use the LDAP controls that are supported by the Netscape Directory Server.

The chapter includes the following sections:


How LDAP Controls Work
The LDAP v3 protocol (documented in RFC 2251, "Lightweight Directory Access Protocol (v3)") allows clients and servers to use controls as a mechanism for extending an LDAP operation. A control is a way to specify additional information as part of a request and a response.

For example, a client can send a control to a server as part of a search request to indicate that the server should sort the search results before sending the results back to the client.

Servers can also send controls back to clients. For example, the Netscape Directory Server sends a control back to a client during the authentication process if the client's password has expired or is going to expire.

A control specifies the following information:

The OID identifies the control. If you plan to use a control, you need to make sure that the server supports the control. (See "Determining the Controls Supported By the Server" for details.)

When your client includes a control in a request for an LDAP operation, the server may respond in one of the following ways:

Note that servers can also send controls back to clients.

There are two types of controls:

The next section describes how controls are implemented in the LDAP Java classes and which classes and methods you can use to create, send, and parse data from LDAP controls.


Using Controls in the LDAP Java Classes
In the LDAP Java classes, a control is represented by an object of the LDAPControl class.

To include a control in a request, you should do the following:

  1. Invoke the getSearchConstraints method of the LDAPConnection object to get a clone of LDAPSearchConstraints for this connection.
  2. Invoke the setServerControls method of the cloned constraints object, passing in the LDAPControl object that represents the control you want to include.
  3. Invoke the appropriate method to perform the LDAP operation, passing in the constraints object. For example, if you are performing a search, invoke the search method and pass the search constraints as an argument.
(You can also include controls by invoking the setServerControls method for the default set of search constraints or by invoking the setOption method to set the LDAPv3.SERVERCONTROLS option. Note, however, that these controls will be sent to the server with every request. In general, controls tend to be specific to a type of operation, so you should only include a control in a request for the operation that it applies to.)

You can then retrieve data from the returned controls through accessor methods in the LDAPControl object.

The rest of this chapter explains how to use the LDAP Java classes to send and retrieve specific types of controls.


Determining the Controls Supported By the Server
According to the LDAP v3 protocol, servers should list any controls that they support in the supportedControl attribute in the root DSE.

The following table lists some of the OIDs for server controls.

Table 13.1 LDAP v3 Server Controls
OID of Control and Defined Constant
Description of Control
2.16.840.1.113730.3.4.2
netscape.ldap.LDAPControl.
MANAGEDSAIT

"Manage DSA IT" control (see "Using the Manage DSA IT Control" for details)
2.16.840.1.113730.3.4.3
netscape.ldap.controls.
LDAPPersistSearchControl.
PERSISTENTSEARCH

"Persistent search" control (see "Using the Persistent Search Control" for details)
2.16.840.1.113730.3.4.4
netscape.ldap.LDAPControl.
PWEXPIRED

"Password expired" control (see "Using Password Policy Controls" for details)
2.16.840.1.113730.3.4.5
netscape.ldap.LDAPControl.
PWEXPIRING

"Password expiration warning" control (see "Using Password Policy Controls" for details)
2.16.840.1.113730.3.4.9
netscape.ldap.controls.
LDAPVirtualListControl.
VIRTUALLIST

"Virtual list view" control (see "Using the Virtual List View Control" for details)
2.16.840.1.113730.3.4.12
netscape.ldap.controls.
LDAPProxiedAuthControl.
PROXIEDAUTHREQUEST

"Proxied authorization" control (see "Using the Proxied Authorization Control" for details)
1.2.840.113556.1.4.473
netscape.ldap.controls.
LDAPSortControl.SORTREQUEST

"Server-side sorting" control (see "Using the Server-Side Sorting Control" for details)

The following example is a simple command-line program that searches for the root DSE and prints the values of the supportedControl attribute.

...
import netscape.ldap.*;
import netscape.ldap.controls.*;
import java.util.*;
...
public class ListCtrl {
   public static void main( String[] args ) {

      /* Hashtable mapping OIDs of known controls to descriptions of
         each control. */
      Hashtable knownControls = new Hashtable();
      knownControls.put( LDAPSortControl.SORTREQUEST,
         "Sort control" );
      knownControls.put( LDAPControl.MANAGEDSAIT,
         "ManageDsaIT control" );
      knownControls.put( LDAPPersistSearchControl.PERSISTENTSEARCH,
         "Persistent Search control" );
      knownControls.put( LDAPControl.PWEXPIRED,
         "Password Expiration Notification control" );
      knownControls.put( LDAPControl.PWEXPIRING,
         "Password Expiration Warning control" );
      knownControls.put( LDAPVirtualListControl.VIRTUALLIST,
         "Virtual List View control" );
      knownControls.put( LDAPProxiedAuthControl.PROXIEDAUTHREQUEST,
         "Proxied Authorization control" );

      LDAPConnection ld = new LDAPConnection();
      String hostname = "localhost";
      int portnumber = LDAPv2.DEFAULT_PORT;
      try {

         /* Connect and authenticate to server */
         ld.connect( 3, hostname, portnumber );

         /* The list of supported controls can be retrieved by
            getting the root DSE. To get the root DSE, you need
            to do a search where:
            - The scope is SCOPE_BASE
            - The base is ""
            - The search filter is "(objectclass=*)"
            The values of the supportedControl attribute of the
            resulting entry are the OIDs of the supported controls. */
         int MY_SCOPE = LDAPv2.SCOPE_BASE;
         String MY_FILTER = "(objectclass=*)";
         String MY_SEARCHBASE = "";
         String getAttrs[] = { "supportedControl" };
         LDAPSearchResults res = ld.search( MY_SEARCHBASE,
            MY_SCOPE, MY_FILTER, getAttrs, false );

         /* There should only be one entry found. */

         /* Get the attributes of this entry. */
         LDAPEntry DSE = (LDAPEntry)res.nextElement();
         LDAPAttributeSet findAttrs = DSE.getAttributeSet();
         Enumeration enumAttrs = findAttrs.getAttributes();

         /* Print each attribute returned
            (this should only be the supportedControl attribute) */
         while ( enumAttrs.hasMoreElements() ) {
            LDAPAttribute anAttr =
               (LDAPAttribute)enumAttrs.nextElement();
            String attrName = anAttr.getName();
            System.out.println( attrName );

            /* Get the values of this attribute. */
            Enumeration enumVals = anAttr.getStringValues();
            if ( enumVals == null ) {
               System.out.println( "\tNo values." );
               continue;
            }
            while ( enumVals.hasMoreElements() ) {
               String aVal = ( String )enumVals.nextElement();

               /* Each value should be the OID of a control. Look up the
                  description corresponding to the OID. */
               String aDesc = ( String )knownControls.get( aVal );
               if ( aDesc != null ) {
                  System.out.println( "\t" + aDesc+ " (" + aVal + ")" );
               } else {
                  System.out.println( "\t" + aVal );
               }
            }
         }
      }
      catch( LDAPException e ) {
            System.out.println( "Error: " + e.toString() );
      }
      try {
         ld.disconnect();
      }
      catch( LDAPException e ) {
          System.exit(1);
      }
      System.exit(0);
   }
}
...

Using the Server-Side Sorting Control
The control with the OID 1.2.840.113556.1.4.473 (or the constant netscape.ldap.LDAPControl.SORTREQUEST) is a server-side sorting control. When you send a search request with this control to the server, the server should sort the results before sending them back to you.

The server-side sorting control is described in the Internet-Draft "LDAP Control Extension for Server Side Sorting of Search Results." This document is available at: http://www.ietf.org/internet-drafts/draft-ietf-ldapext-sorting-02.txt

Note. Internet-Drafts expire every six months. If the URL above does not work, try incrementing the number by one. For example, draft-06.txt would become draft-07.txt.

This section covers the following topics:

Specifying the Sort Order
To specify the sort order of the results, construct one or more LDAPSortKey objects. Each object represents a sort key generated from a string in the following format:

[-]<attrname>[:<matchingruleoid>]
<attrname> is the name of the attribute that you want to sort by. <matchingruleoid> is the optional OID of a matching rule that you want to use for sorting. The minus sign indicates that the results should be sorted in reverse order for that attribute.

For example, the following string specifies that results should be sorted by first name ("givenname") in descending order:

"-givenname"
Pass this string to the LDAPSortKey constructor to create a sort key. For example:

LDAPSortKey sortByFirstNameReverse = new LDAPSortKey( "-givenname" );
To sort by more than one attribute, construct more than one LDAPSortKey object and create an array of the objects.

For example, suppose you want to sort the result by last name ("sn") in ascending order. If two or more entries have the same last name, you want to sort the result by first name ("givenname") in ascending order.

To specify this sort order, you construct two LDAPSortKey objects and create an array:

...
LDAPSortKey sortByLastName = new LDAPSortKey( "sn" );
LDAPSortKey sortByFirstName = new LDAPSortKey( "givenname" );
LDAPSortKey[] sortOrder = { sortByLastName, sortByFirstName };
...
If you are using the Netscape Directory Server 3.x, keep the following in mind:

Creating the Control
Next, to create the server-side sorting control, construct a new LDAPSortControl object. Pass the LDAPSortKey object (or the array of LDAPSortKey objects) to the LDAPSortControl constructor.

In the constructor, you can also specify whether or not the control is critical to the search operation. If the control is marked as critical and the server cannot sort the results, the server should not send back any entries. (See "Interpreting the Results" for more information on the effect of a critical control.)

For example, the following section of code creates a server-side sorting control and specifies that the control is critical to the search operation:

LDAPSortKey sortOrder = new LDAPSortKey( "-givenname" );
LDAPSortControl sortCtrl = new LDAPSortControl( sortOrder, true );
Performing the Search
To specify that you want the server to sort the results, do the following:

  1. Get a clone of LDAPSearchConstraints for the current connection by invoking the getSearchConstraints method of the LDAPConnection object.
  2. Invoke the setServerControls method for the copied LDAPSearchConstraints object, and pass in the LDAPSortControl object that you have constructed.
  3. Invoke the search method of the LDAPConnection object, passing in the LDAPSearchConstraints object.

  1. Invoke the getResponseControls method of the LDAPSearchResults object to retrieve any controls sent back by the server in response to the search.

  1. Examine the type of each returned control. If a control is an instance of LDAPSortControl, you can read the result code for the sorting operation using the getResultCode method.
The server can return the following result codes that apply to the sorting operation.

Table 13.2 LDAP result codes for sorting search results
Result Code
Description
LDAPException.SUCCESS
The results were sorted successfully.
LDAPException.
OPERATION_ERROR

An internal server error occurred.
LDAPException.
TIME_LIMIT_EXCEEDED

The maximum time allowed for a search was exceeded before the server finished sorting the results.
LDAPException.
STRONG_AUTH_REQUIRED

The server refused to send back the sorted search results because it requires you to use a stronger authentication method.
LDAPException.
ADMIN_LIMIT_EXCEEDED

There are too many entries for the server to sort.
LDAPException.
NO_SUCH_ATTRIBUTE

The sort key list specifies an attribute that does not exist.
LDAPException.
INAPPROPRIATE_MATCHING

The sort key list specifies a matching rule that is not recognized or appropriate
LDAPException.
INSUFFICIENT_ACCESS_RIGHTS

The server did not send the sorted results because the client has insufficient access rights
LDAPException.BUSY
The server is too busy to sort the results.
LDAPException.
UNWILLING_TO_PERFORM

The server is unable to sort the results.
LDAPException.OTHER
This general result code indicates that the server failed to sort the results for a reason other than the ones listed above.

Interpreting the Results
The following table lists the kinds of results to expect from the LDAP server under different situations.

Does the Server Support the Sort Control?
Is the Sort Control Marked as Critical?
Are There any Other Conditions?
Results from the LDAP Server
No
No
N/A
The server ignores the sorting control and returns the entries unsorted.
No
Yes
N/A
The server does not send back any entries
Yes
No
The server cannot sort the results using the specified sort key list.
Yes
Yes
The server cannot sort the results using the specified sort key list.
Yes
Yes or No (Does not affect the results)
The search itself failed.
Yes
Yes or No (Does not affect the results)
The server successfully sorted the entries.

Known Problems with Server Sorting
The following problems may occur when using the server-side sorting control with the Netscape Directory Server 3.x (most of these problems are fixed in version 4.0 of the server):

Example of Using the Server-Sorting Control
The following program uses the server-sorting control to get a list of all users in the directory, sorted in ascending order by last name, then in descending order by first name.

...
import netscape.ldap.*;
import netscape.ldap.controls.*;
import java.util.*;
...
public class SrchSort {
   public static void main( String[] args ) {
      LDAPConnection ld = new LDAPConnection();
      String hostname = "localhost";
      int portnumber = LDAPv2.DEFAULT_PORT;
      int status = -1;

      try {
         /* Connect to server */
         ld.connect( 3, hostname, portnumber, "", "" );

         /* Search for last names that start with "Wa". */
         String MY_FILTER = "sn=Wa*";
         String MY_BASE = "o=Airius.com";
         String[] attrs = { "sn", "givenname" };

         /* Create sort keys that specify the sort order. */
         LDAPSortKey sortByLastName = new LDAPSortKey( "sn" );
         LDAPSortKey sortByFirstName = new LDAPSortKey( "-givenname" );
         LDAPSortKey[] sortOrder = { sortByLastName, sortByFirstName };

         /* Create a server control using that sort key. */
         LDAPSortControl sortCtrl = new LDAPSortControl(sortOrder,
            true);

         /* Create search constraints to use that control. */
         LDAPSearchConstraints cons = ld.getSearchConstraints();
         cons.setServerControls( sortCtrl );

         /* Perform the search. */
         LDAPSearchResults res = ld.search( MY_BASE,
            LDAPv3.SCOPE_SUB, MY_FILTER, attrs, false, cons );

         /* Loop through the results until finished. */
         System.out.println( "Sorted Results from Server" );
         System.out.println( "==========================" );
         while ( res.hasMoreElements() ) {

            /* Get the next directory entry. */
            LDAPEntry findEntry = null;
            try {
               findEntry = res.next();

            /* Skip any referrals found for now. */
            } catch ( LDAPReferralException e ) {
               continue;
            } catch ( LDAPException e ) {
               System.out.println( "Error: " + e.toString() );
               continue;
            }

            /* Get the set of attributes for that entry. */
            LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
            Enumeration enumAttrs = findAttrs.getAttributes();

            /* Iterate through the attributes. */
            while ( enumAttrs.hasMoreElements() ) {
               LDAPAttribute anAttr =
                  (LDAPAttribute)enumAttrs.nextElement();

               /* Get the set of values for each attribute. */
               Enumeration enumVals = anAttr.getStringValues();
               if ( enumVals == null ) {
                  System.out.println( "\tNo values." );
                  continue;
               }

               /* Iterate through the values and print each value. */
               String aVal = (String)enumVals.nextElement();
               System.out.print( aVal );
               while (enumVals.hasMoreElements() ) {
                  aVal = (String)enumVals.nextElement();
                  System.out.print( ", " + aVal );
               }
               System.out.print( "\t\t" );
            }
         System.out.println( "" );
         }

         /* Determine if the server sent a control back to you. */
         LDAPControl[] returnedControls = res.getResponseControls();
         if ( returnedControls != null ) {
            for ( int i=0; i<returnedControls.length; i++ ){
               if (!(returnedControls[i] instanceof LDAPSortControl)){
                  continue;
               }
               LDAPSortControl sortRsp = (LDAPSortControl)
                                          returnedControls[i];
               int resultCode = sortRsp.getResultCode;

               /*Check if the result code indicated an error occurred.*/
               if ( resultCode != 0 ) {
                  System.out.println( "Result code: " + resultCode );
                  System.out.println(
                     LDAPException.errorCodeToString( resultCode ) );

                  /* If the server specified the attribute that
                  caused the failure, print it out. */
                  String failedAttr = sortRsp.getFailedAttribute();
                  if ( failedAttr != null ) {
                     System.out.println( "Failed on "+failedAttr );
                  } else {
                     System.out.println( "Server did not indicate which
                        " + "attribute caused sorting to fail." );
                  }
               }
            }
         }
         status = 0;
      }
      catch( LDAPException e ) {
         System.out.println( "Error: " + e.toString() );
      }

      /* Done, so disconnect */
      if ( (ld != null) && ld.isConnected() ) {
         try {
            ld.disconnect();
            System.out.println( "" );
         } catch ( LDAPException e ) {
            System.out.println( "Error: " + e.toString() );
         }
   }
      System.exit(status);
   }
}
...

Using the Persistent Search Control
The control with the OID 2.16.840.1.113730.3.4.3 (the constant netscape.ldap.controls.LDAPPersistSearchControl.PERSISTENTSEARCH) is the persistent search control. A persistent search (an ongoing search operation), which allows your LDAP client to get notification of changes to the directory.

The persistent search control is described in the Internet-Draft "Persistent Search: A Simple LDAP Change Notification Mechanism." This document is available at: http://www.ietf.org/internet-drafts/draft-ietf-ldapext-psearch-00.txt

Note. Internet-Drafts expire every six months. If the URL above does not work, try incrementing the number by one. For example, draft-06.txt would become draft-07.txt.

To use persistent searching for change notification, you create a "persistent search" control that specifies the types of changes that you want to track. You include the control in a search request. If an entry in the directory is changed, the server determines if the entry matches the search criteria in your request and if the change is the type of change that you are tracking. If both of these are true, the server sends the entry to your client.

You can use this control in conjunction with an "entry change notification" control (see "Using the Entry Change Notification Control").

The rest of this section describes how to create and use this control.

Creating the Control
To create a persistent search control, you construct a new LDAPPersistSearchControl object. When invoking the LDAPPersistSearchControl constructor, you can specify the following information:

For example, the following section of code

...
/* Track all types of changes. */
int op = LDAPPersistSearchControl.ADD |
   LDAPPersistSearchControl.MODIFY |
   LDAPPersistSearchControl.DELETE |
   LDAPPersistSearchControl.MODDN;

/* Return only entries that have changed. */
boolean changesOnly = true;

/* Return an "entry change notification" control. */
boolean returnControls = true;

/* Mark the control as critical. */
boolean isCritical = true;

/* Create the control. */
LDAPPersistSearchControl persistCtrl = new
   LDAPPersistSearchControl( op, changesOnly,
   returnControls, isCritical );
...
Performing the Search
To specify that you want to start a persistent search, do the following:

  1. Get a clone of LDAPSearchConstraints for the current connection by invoking the getSearchConstraints method of the LDAPConnection object.
  2. Invoke the setServerControls method for the cloned LDAPSearchConstraints object, and pass in the LDAPPersistSearchControl object that you have constructed.
  3. Invoke the search method of the LDAPConnection object, passing in the LDAPSearchConstraints object.
To end the persistent search, you can either invoke the abandon method of the LDAPConnection object to abandon the search operation, or you can invoke the disconnect method to disconnect from the server.

Example of Using the Persistent Search Control
The following program performs a persistent search and receives "entry change notification" controls from the server.

import netscape.ldap.*;
import netscape.ldap.controls.*;
import java.util.*;
public class SrchPrst implements Runnable {
   private String hostname;
   private int portnumber;
   public SrchPrst() {
   }

   public static void main( String[] args ) {
      /* Start up a new thread. */
      Thread th = new Thread( new SrchPrst(), "mainConn" );
      th.start();
      System.out.println( "Main thread started." );
   }

   public void run() {
      LDAPConnection ld = new LDAPConnection();
      String hostname = "localhost";
      int portnumber = LDAPv2.DEFAULT_PORT;
      try {
         /* Connect to server */
         ld.connect( 3, hostname, portnumber, "", "" );
         /* Specify that you want to track changes to all entries. */
         String MY_FILTER = "(objectclass=*)";
         String MY_BASE = "o=Airius.com";

         /* Create a persistent search control. */
         int op = LDAPPersistSearchControl.ADD |
            LDAPPersistSearchControl.MODIFY |
            LDAPPersistSearchControl.DELETE |
            LDAPPersistSearchControl.MODDN;
         boolean changesOnly = true;
         boolean returnControls = true;
         boolean isCritical = true;
         LDAPPersistSearchControl persistCtrl = new
               LDAPPersistSearchControl( op, changesOnly,
               returnControls, isCritical );

         /* Create search constraints to use that control. */
         LDAPSearchConstraints cons = ld.getSearchConstraints();
         cons.setServerControls( persistCtrl );
         /* Start the persistent search. */
         LDAPSearchResults res = ld.search( MY_BASE,
            LDAPv3.SCOPE_SUB, MY_FILTER, null, false, cons );

         /* Loop through the results until finished. */
         while ( res.hasMoreElements() ) {

            /* Print any entries that have changed. */
            System.out.println( "\n======= Changed Entry =======" );

            /* Get the next directory entry. */
            LDAPEntry findEntry = res.next();

            /* Get the set of attributes for that entry. */
            LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
            Enumeration enumAttrs = findAttrs.getAttributes();

            /* Iterate through the attributes. */
            while ( enumAttrs.hasMoreElements() ) {
               LDAPAttribute anAttr =
                  (LDAPAttribute)enumAttrs.nextElement();
               String attrName = anAttr.getName();
               System.out.println( "\t" + attrName );

               /* Get the set of values for each attribute. */
               Enumeration enumVals = anAttr.getStringValues();

               /* Iterate through the values and print each value. */
               while (enumVals.hasMoreElements() ) {
                  String aVal = (String)enumVals.nextElement();
                  System.out.println( "\t\t" + aVal );
               }
            }

            /* Get any entry change controls. */
            LDAPControl[] responseCtrls = res.getResponseControls();
            if ( responseCtrls != null ) {
               for ( int i=0; i<responseCtrls.length; i++ ){
                  if (!(responseCtrls[i] instanceof
                        LDAPEntryChangeControl)){
                     continue;
                  }
                  LDAPEntryChangeControl entryCtrl =
                     (LDAPEntryChangeControl) responseCtrls[i];

                  /* Get information on the type of change made. */
                  int changeType = entryCtrl.getChangeType();
                  if ( changeType != -1 ) {
                     System.out.print( "Change made: " );
                     switch ( changeType ) {
                     case LDAPPersistSearchControl.ADD:
                        System.out.println( "Added new entry." );
                        break;
                     case LDAPPersistSearchControl.MODIFY:
                        System.out.println( "Modified entry." );
                        break;
                     case LDAPPersistSearchControl.DELETE:
                        System.out.println( "Deleted entry." );
                        break;
                     case LDAPPersistSearchControl.MODDN:
                        System.out.println( "Renamed entry." );
                        break;
                     }
                  }

                  /* Get the change log number, if present. */
                  int changeNumber = entryCtrl.getChangeNumber();
                  if ( changeNumber != -1 ) {
                     System.out.println( "Change log number: " +
                        changeNumber );
                  }

                  /* Get the previous DN of the entry,
                     if a modify DN operation was performed. */
                  String oldDN = entryCtrl.getPreviousDN();
                  if ( oldDN != null ) {
                     System.out.println( "Previous DN: " + oldDN );
                  }
               } else {
                  System.out.println( "No entry change control." );
               }
               System.out.println( "\n" );
            }
         }
      }
      catch( LDAPException e ) {
         System.out.println( "Error: " + e.toString() );
      }
   }
}
...

Using the Entry Change Notification Control
The control with the OID 2.16.840.1.113730.3.4.7 (or the constant netscape.ldap.controls.LDAPEntryChangeControl.ENTRYCHANGED) is the "entry change notification" control. These types of controls can be included with entries sent back from the server during a persistent search. (For more information on persistent searches, see "Using the Persistent Search Control".)

The "entry change notification" control is described in the Internet-Draft "Persistent Search: A Simple LDAP Change Notification Mechanism." This document is available at: http://www.ietf.org/internet-drafts/draft-ietf-ldapext-psearch-00.txt

Note. Internet-Drafts expire every six months. If the URL above does not work, try incrementing the number by one. For example, draft-06.txt would become draft-07.txt.

The rest of this section describes how to use these types of controls.

Getting the Control
To get an "entry change notification" control that is included with an entry, do the following:

  1. As you retrieve each entry, invoke the getResponseControls method of the LDAPConnection object to retrieve any response controls sent back from the server.

  1. Pass this array of LDAPControl objects as an argument to the LDAPPersistSearchControl.parseResponse static method to retrieve the "entry change notification" control.
An "entry change notification" control is represented by an object of the LDAPEntryChangeControl class. To get data from this control, you can invoke the accessor methods, such as getChangeNumber, getChangeType, and getPreviousDN.

Working with Change Log Numbers
If the Netscape Directory Server is set up to be a supplier (for replicating changes in the directory to other servers), the server keeps a record of the changes made to the directory in a change log. Each record of a change has a number that identifies it in the log.

You can get the change number for a modified entry from the LDAPEntryChangeControl object.

If you want to look up the record for a particular change log number (to get more information about the change that took place), you can search for the record. In the Netscape Directory Server, the change log is represented by an entry in the directory, and individual change records are represented by entries in a subtree beneath the change log entry.

To determine the DN for the change log entry, search the root DSE and retrieve the changelog attribute. For example, the value of this attribute might be "cn=changelog", which is the DN for the change log entry.

Each change log record is an entry under the change log entry. The change log number is the value of the changenumber attribute of the record. To get a specific change log record, you can search the directory with the base DN "cn=changelog" and with the search filter "changenumber=<value>", where <value> is the change number of the record.

Note that you may need to authenticate as the directory manager to have access to these entries.


Using the Virtual List View Control
The control with the OID 2.16.840.1.113730.3.4.9 (or the constant netscape.ldap.controls.LDAPVirtualListControl.VIRTUALLIST) is a virtual list view control. When you send a search request with this control and with a server-side sorting control to the server, the server should sort the results and return the specified subset of entries back to your client.

The virtual list view control is described in the Internet-Draft "LDAP Extensions for Scrolling View Browsing of Search Results." This document is available at: http://www.ietf.org/internet-drafts/draft-ietf-ldapext-ldapv3-vlv-01.txt

Note. Internet-Drafts expire every six months. If the URL above does not work, try incrementing the number by one. For example, draft-06.txt would become draft-07.txt.

Although Netscape Directory Server 4.x supports this control, not all servers do. For information on determining if a server supports this or other LDAP v3 controls, see "Determining the Controls Supported By the Server".

Note that after you set the list size by invoking the setListSize method of the LDAPVirtualListControl object, you need to invoke the setRange method to recreate the control using the new data. (setRange generates the BER-encoded request to be sent to the server; setListSize does not do this.)


Using the Manage DSA IT Control
The control with the OID 2.16.840.1.113730.3.4.2 (or the constant netscape.ldap.LDAPControl.MANAGEDSAIT) is the manage DSA IT control. You can use this control to manage search references in the directory.

The manage DSA IT control is described in the Internet-Draft "LDAP Control Extension for Server Side Sorting of Search Results." This document is available at: http://www.ietf.org/internet-drafts/draft-ietf-ldapext-sorting-00.txt

Note. Internet-Drafts expire every six months. If the URL above does not work, try incrementing the number by one. For example, draft-06.txt would become draft-07.txt.

To create this control, construct a new LDAPControl object. In the LDAPControl constructor, set the OID of the control to 2.16.840.1.113730.3.4.2.

When you add this control to the array of LDAPControl objects that you pass to a method that performs an LDAP operation, the server treats search references as ordinary entries.

Rather than returning a reference to you, the server returns the entry containing the reference. This allows your client application to manage search references in the directory.


Using Password Policy Controls
The Netscape Directory Server 3.0 and later versions use two server response controls to send information back to a client after an LDAP bind operation:

To get these server response controls when binding, invoke the getResponseControls method of the LDAPConnection object after you attempt to authenticate to the server.


Using the Proxied Authorization Control
The control with the OID 2.16.840.1.113730.3.4.12 (or the constant netscape.ldap.LDAPProxiedAuthControl.PROXIEDAUTHREQUEST) allows LDAP clients to use different credentials, without rebinding, when executing LDAP operations. This is called proxied authorization.

For example, suppose we have a messaging server that stores its user profiles on an LDAP server. For certain types of requests the messaging server needs to use a DN and password other than its own. Doing this without proxied authorization requires the messaging server to rebind, using the different credentials, before executing each operation.

If the messaging server uses the proxied authorization control, it can act as the user when executing an operation, while only maintaining its own binding to the LDAP server. This drastically improves performance, especially when processing a large number of requests.

The control is described more fully in the Internet-Draft "LDAP Proxied Authorization Control." This document is available at: http://www.ietf.org/internet-drafts/draft-weltman-ldapv3-proxy-03.txt.

Note. Internet-Drafts expire every six months. If the URL above does not work, try incrementing the number by one. For example, draft-06.txt would become draft-07.txt.

 

© Copyright 1999 Netscape Communications Corporation. All rights reserved.