Mozilla LDAP SDK Programmer's Guide/LDAP Controls With LDAP Java SDK

From MozillaWiki
Jump to: navigation, search

This section explains how LDAP controls work and how to use the LDAP controls.

How LDAP Controls Work With LDAP Java SDK

LDAP 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. The control indicates 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 server can send a control back to a client during the authentication process. The control can indicate that the client password has expired. The control can alternatively indicate that the client password is going to expire. A control specifies the following information:

  • A unique object identifier (OID)
  • An indication of whether the control is critical to the operation
  • Optional data related to the control, such as the server-side sorting control, where attributes used for sorting search results are needed

The OID identifies the control. If you plan to use a control, you need to make sure that the server supports the control. Refer to Determining the Controls Supported the Server With LDAP Java SDK for instructions.

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

  • If the server supports this control and if the control is appropriate, the server should use the control when performing the operation.
  • If the server does not support the control type or if the control is not appropriate, the server should do one of the following:
    • If the control is marked as critical to the operation, the server should not perform the operation. Instead, the server should send an unavailable critical extension result code. When receiving this result code, your client returns an LDAPException with the result code LDAPException.UNAVAILABLE_CRITICAL_EXTENSION.
    • If the control is marked as not critical to the operation, the server should ignore the control. The server should proceed to perform the operation.

Servers can also send controls back to clients. Two types of controls exist:

  • Server controls can be included in requests sent by clients and in responses sent by servers.
  • Client controls affect the behavior of the LDAP Java classes only and are never sent to the server.
    LDAP Java SDK does not support client controls.

Using Controls in the LDAP Java Classes

This section describes how controls are implemented in the LDAP Java classes. This section also describes which methods to use to create, send, and parse data from LDAP controls.

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

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

  • Invoke the getSearchConstraints method of the LDAPConnection object to get a clone of LDAPSearchConstraints for this connection.
  • Invoke the setServerControls method of the cloned constraints object, passing in the LDAPControl object that represents the control to include.
  • 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. Pass the search constraints as an argument.

You can also include controls by invoking the setServerControls method for the default set of search constraints. Alternatively, invoke the setOption method to set the LDAPv3.SERVERCONTROLS option.

These controls are sent to the server with every request, however. In general, controls tend to be specific to a type of operation. Include a control in a request only for the operation to which the control applies.

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

Determining the Controls Supported the Server With LDAP Java SDK

LDAP v3 states that servers should list any controls that servers support in the supportedControl attribute in the root DSE. The following OIDs have corresponding constants that are defined in the LDAP Java classes.

  • 1.2.840.113556.1.4.473netscape.ldap.controls.LDAPSortControl.SORTREQUEST: For instructions on using this control, refer to Using the Server-Side Sorting Control With LDAP Java SDK.
  • 2.16.840.1.113730.3.4.2netscape.ldap.LDAPControl.MANAGEDSAIT: For instructions on using this control, refer to Using the Manage DSA IT Control With LDAP Java SDK.
  • 2.16.840.1.113730.3.4.3netscape.ldap.controls.LDAPPersistSearchControl.PERSISTENTSEARCH: For instructions on using this control, refer to Using the Persistent Search Control With LDAP Java SDK.
  • 2.16.840.1.113730.3.4.4netscape.ldap.LDAPControl.PWEXPIRED: For instructions on using this control, refer to Using Password Policy Controls With LDAP Java SDK.
  • 2.16.840.1.113730.3.4.5netscape.ldap.LDAPControl.PWEXPIRING: For instructions on using this control, refer to Using Password Policy Controls With LDAP Java SDK.
  • 2.16.840.1.113730.3.4.9netscape.ldap.controls.LDAPVirtualListControl.VIRTUALLIST: For instructions on using this control, refer to Using the Virtual List Control With LDAP Java SDK.
  • 2.16.840.1.113730.3.4.12netscape.ldap.controls.LDAPProxiedAuthControl.PROXIEDAUTHREQUEST: For instructions on using this control, refer to Using the Proxied Authorization Control With LDAP Java SDK.

The following example searches for the root DSE. Then the example 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 controls to a description */
        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");

        try {
            UserArgs userArgs = new UserArgs("ListCtrl", args, false);
            LDAPConnection ld = new LDAPConnection();
            ld.connect(userArgs.getHost(), userArgs.getPort());

            /* Retreive the list of supported controls from the DSE. */
            String getAttrs[] = {"supportedControl"};
            LDAPSearchResults res = ld.search("", LDAPv3.SCOPE_BASE,
                "(objectclass=*)", getAttrs, false);
            LDAPEntry DSE = (LDAPEntry)res.nextElement();
            LDAPAttributeSet findAttrs = DSE.getAttributeSet();
            Enumeration enumAttrs = findAttrs.getAttributes();

            while (enumAttrs.hasMoreElements()) {
                LDAPAttribute anAttr =
                    (LDAPAttribute)enumAttrs.nextElement();
                String attrName = anAttr.getName();
                System.out.println(attrName);

                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 its description in the hash table.
                     */
                    String aDesc = (String)knownControls.get(aVal);
                    if (aDesc != null) {
                        System.out.println("\t" + aDesc+ " (" + aVal + ")");
                    } else {
                        System.out.println("\t" + aVal);
                    }
                }
            }

            ld.disconnect();
        } catch(LDAPException e) {
            System.out.println("Error: " + e.toString());
        }
    }
}

Using the Server-Side Sorting Control With LDAP Java SDK

The control represented with the OID that corresponds to the constant netscape.ldap.LDAPControl.SORTREQUEST is a server-side sorting control. The server-side sorting control is defined in RFC 2891. When you send a search request with this control to the server, the server should sort the results before sending them back to you.

Specifying the Server-Side Sort Order With LDAP Java SDK

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

[-]''attrName''[:''matchingRuleOID'']

Here, attrName represents the name of the attribute to use for sorting. matchingRuleOID represents the optional OID of the matching rule to use for sorting. The optional 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:

LDAPSortKey reverseSortByFirstName = 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. Then create an array:

LDAPSortKey sortByLastName = new LDAPSortKey("sn");
LDAPSortKey sortByFirstName = new LDAPSortKey("givenname");
LDAPSortKey[] sortOrder = { sortByLastName, sortByFirstName };

Creating the Server-Side Sorting Control With LDAP Java SDK

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. The control can be marked as critical, but the server cannot sort the results. If the situation occurs, the server should not send back any entries.

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

LDAPSortKey sortOrder = new LDAPSortKey("-givenname");
LDAPSortControl sortCtrl = new LDAPSortControl(sortOrder, true);

Performing the Server—Side Sort With LDAP Java SDK

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.
    The server returns a result for the search operation and a response control. The response control indicates the success or failure of the sorting.
  4. Invoke the getResponseControls method of the LDAPSearchResults object to retrieve any controls sent back by the server in response to the search.
    Response controls are passed back as an array of LDAPControl objects.
  5. 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 with the getResultCode method.
    If the sorting operation failed, the server can also return the name of the attribute that caused the failure. You can read the name of this attribute with the getFailedAttribute method.

The server can return the following result codes that apply to the sorting operation.

  • LDAPException.ADMIN_LIMIT_EXCEEDED: Too many entries exist for the server to sort.
  • LDAPException.BUSY: The server is too busy to sort the results.
  • 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.NO_SUCH_ATTRIBUTE: The sort key list specifies an attribute that does not exist.
  • LDAPException.OPERATION_ERROR: An internal server error occurred.
  • LDAPException.OTHER: This general result code indicates that the server failed to sort the results for a reason other than the results listed here.
  • LDAPException.STRONG_AUTH_REQUIRED: The server refused to send back the sorted search results because the server requires that you use a stronger authentication method.
  • LDAPException.SUCCESS: The results were sorted successfully.
  • LDAPException.TIME_LIMIT_EXCEEDED: The maximum time allowed for a search was exceeded beforethe server finished sorting the results.
  • LDAPException.UNWILLING_TO_PERFORM: The server is unable to sort the results.

Interpreting the Server-Side Sort Results With LDAP Java SDK

The following table shows the kinds of results to expect from the LDAP server under different conditions.

Server Responses to Sort Controls
Supports sort control? Sort control marked critical? Any other conditions? Results From LDAP Server
Server does not support sort control. Control is not marked as critical. Not applicable The server ignores the sorting control. The server returns the entries unsorted.
Server does not support sort control. Control is marked as critical. Not applicable The server does not send back any entries.
Server does support sort control. Control is not marked as critical. The server cannot sort the results with the specified sort key list.
  • The server returns the entries unsorted.
  • The server sends back the sorting response control. The response control specifies the result code of the sort attempt and, optionally, the attribute type that caused the error.
Server does support sort control. Control is marked as critical. The server cannot sort the results with the specified sort key list.
  • The server does not return any entries.
  • The server sends back the sorting response control. The response control specifies the result code of the sort attempt and, optionally, the attribute type that caused the error.
Server does support sort control. has no effect on results The search failed.
  • The server returns a result code for the search operation.
  • The server does not send back the sorting response control.
Server does support sort control. has no effect on results The server successfully sorted the entries.
  • The server returns the entries in sorted order.
  • The server sends back the sorting response control, which specifies the result code of the sort attempt as LDAPException.SUCCESS.

Example of Using Server-Side Sorting With LDAP Java SDK

The following sample program uses the server-side sorting control to get a list of all users in the directory. The list is 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) {
        try {
            UserArgs userArgs = new UserArgs("SrchSort", args, false);
            LDAPConnection ld = new LDAPConnection();
            ld.connect(userArgs.getHost(), userArgs.getPort());
            ld.authenticate(3, null, null); // Anonymous bind, LDAP v3

            String filter = "sn=Jen*";
            String baseDN = "ou=People,dc=example,dc=com";
            String[] attrs = {"sn", "givenname"};

            /* Sort by last name, then in reverse by first name. */
            LDAPSortKey sortByLastName = new LDAPSortKey("sn");
            LDAPSortKey sortByFirstName = new LDAPSortKey("-givenname");
            LDAPSortKey[] sortOrder = {sortByLastName, sortByFirstName};

            LDAPSortControl sortCtrl = new LDAPSortControl(sortOrder, true);
            LDAPSearchConstraints cons = ld.getSearchConstraints();
            cons.setServerControls(sortCtrl);

            /* Perform the search using the control. */
            LDAPSearchResults res = ld.search(baseDN, LDAPv3.SCOPE_SUB,
                filter, attrs, false, cons);

            /* Display the results. */
            System.out.println("Sorted results from server");
            System.out.println("==========================");
            while (res.hasMoreElements()) {
                LDAPEntry resEntry = null;
                try {
                    resEntry = res.next();
                } catch (LDAPReferralException e) {
                    continue; // Skip referrals for now.
                } catch (LDAPException e) {
                    System.err.println("Error:" + e.toString());
                    continue;
                }

                LDAPAttributeSet resAttrs = resEntry.getAttributeSet();
                Enumeration enumAttrs = resAttrs.getAttributes();

                while (enumAttrs.hasMoreElements()) {
                    LDAPAttribute attr =
                        (LDAPAttribute)enumAttrs.nextElement();
                    Enumeration enumVals =  attr.getStringValues();
                    if (enumVals == null) {
                        System.out.println("\tNo values.");
                        continue;
                    }
                    while (enumVals.hasMoreElements()) {
                        String val = (String)enumVals.nextElement();
                        System.out.print(val);
                    }
                    System.out.print(", ");
                }
                System.out.println("");
            }

            /* Check whether the server sent back a control. */
            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 the result for errors. */
                    if (resultCode != 0) {
                        System.err.println("Result code: " + resultCode);
                        System.err.println(
                            LDAPException.errorCodeToString(resultCode));

                        /* Report attribute that caused the failure. */
                        String failedAttr = sortRsp.getFailedAttribute();
                        if (failedAttr != null) {
                            System.err.println("Failed on: " + failedAttr);
                        } else {
                            System.err.println("Server did not indicate " +
                                "which attribute caused sorting to fail.");
                        }
                    }
                }
            }

            ld.disconnect();
        } catch(LDAPException e) {
            System.out.println("Error: " + e.toString());
        }
    }
}

Using the Persistent Search Control With LDAP Java SDK

The control represented with the OID that corresponds to the constant netscape.ldap.LDAPControl.PERSISTENTSEARCH is a persistent search control. A persistent search, an ongoing search operation, allows your LDAP client to get notification of changes to the directory. 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. The server also determines if the change is the type of change that you are tracking. If both of the conditions are true, the server sends the entry to your client.

You can use this control in conjunction with an entry change notification control, as described in Using the Entry Change Notification Control With LDAP Java SDK.

Creating the Persistent Search Control With LDAP Java SDK

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

  • The type of change you want to track. You can specify any of the following, or any combination of the following, using a bitwise OR (|) operator:
    • ADD indicates that you want to track added entries.
    • DELETE indicates that you want to track deleted entries.
    • MODDN indicates that you want to track renamed entries.
    • MODIFY indicates that you want to track modified entries.
  • A preference indicating whether you want the server to return all entries that initially matched the search criteria
  • A preference indicating whether or not you want entry change notification controls included with every modified entry returned by the server

This code excerpt shows an example of creating a persistent search control.

/* 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 Persistent Search With LDAP Java SDK

To specify that you want to start a persistent search, do the following:

  • Get a clone of LDAPSearchConstraints for the current connection by invoking the getSearchConstraints method of the LDAPConnection object.
  • Invoke the setServerControls method for the cloned LDAPSearchConstraints object, and pass in the LDAPPersistSearchControl object that you have constructed.
  • Invoke the search method of the LDAPConnection object, passing in the LDAPSearchConstraints object.

The server returns entries that match as the entries change. If you specified that you wanted an entry change notification control included with each entry, you can get these controls from the server's results. For instructions, refer to Using the Entry Change Notification Control With LDAP Java SDK.

To end the persistent search, invoke the abandon method of the LDAPConnection object. Alternatively, invoke the disconnect method to disconnect from the server.

Example of Using the Persistent Search Control With LDAP Java SDK

The following example performs a persistent search. The example receives entry change notification controls from the server.

import netscape.ldap.*;
import netscape.ldap.controls.*;
import java.util.*;

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

    public void run() {
        try {
            UserArgs userArgs = new UserArgs("SrchPrst", cliArgs, true);
            LDAPConnection ld = new LDAPConnection();
            ld.connect(userArgs.getHost(), userArgs.getPort());
            ld.authenticate(3, userArgs.getBindDN(),userArgs.getPassword());

            /* Create the control and search constraints. */
            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);
            LDAPSearchConstraints cons = ld.getSearchConstraints();
            cons.setServerControls(persistCtrl);

            /* Track changes on all entries. */
            String filter = "(objectclass=*)";
            String baseDN = "dc=example,dc=com";
            /* Start the search. */
            LDAPSearchResults res =
                ld.search(
                    baseDN, LDAPv3.SCOPE_SUB, filter, null, false, cons);

            /* Loop through the results until finished. */
            while (res.hasMoreElements()) {
                System.out.println("\n===== Changed Entry =====");
                LDAPEntry findEntry = res.next();
                LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
                Enumeration enumAttrs = findAttrs.getAttributes();
                while (enumAttrs.hasMoreElements()) {
                    LDAPAttribute anAttr =
                        (LDAPAttribute)enumAttrs.nextElement();
                    String attrName = anAttr.getName();
                    System.out.println("\t" + attrName);

                    Enumeration enumVals = anAttr.getStringValues();
                    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 */
                        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;
                                default:
                                    System.out.println(
                                         "Unknown change type.");
                                    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 rename operation was performed. */
                        String oldDN = entryCtrl.getPreviousDN();
                        if (oldDN != null) {
                            System.out.println("Previous DN: " + oldDN);
                        }
                    }
                    System.out.println("\n");
                }
            }
        } catch(LDAPException e) {
            System.out.println("Error: " + e.toString());
        }
    }
}

Using the Entry Change Notification Control With LDAP Java SDK

The control represented with the OID that corresponds to the constant netscape.ldap.LDAPEntryChangeControl.ENTRYCHANGED is an entry change notification control. These types of controls can be included with entries sent back from the server during a persistent search.

Getting the Entry Change Notification Control With LDAP Java SDK

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.
    Response controls are passed back as an array of LDAPControl objects.
  2. 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 With LDAP Java SDK

If the directory server is set up to be a supplier, the server is capable of replicating changes in the directory to other servers. The server therefore keeps a record of the changes made to the directory in a change log. Each record of a change has a number that identifies the change in the log. You can get the change number for a modified entry from the LDAPEntryChangeControl object.

To look up the record for a particular change log number to get more information about the change that took place, search for the record. With Directory Server, the change log is represented by an entry in the directory. 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 to 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, search with base DN cn=changelog and filter changenumber=value. Here, value is the change number of the record.

Using the Virtual List Control With LDAP Java SDK

The control represented with the OID that corresponds to the constant netscape.ldap.controls.LDAPVirtualListControl.VIRTUALLIST is a virtual list 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.

After you set the list size with the setListSize method of the LDAPVirtualListControl object, invoke the setRange method. The method recreates the control with the new data. setRange generates the BER-encoded request to be sent to the server. setListSize does not generate the request.

Using the Manage DSA IT Control With LDAP Java SDK

The control represented with the OID that corresponds to the constant netscape.ldap.controls.LDAPControl.MANAGEDSAIT is a manage DSA IT control. The control is for managing search references in the directory and is defined in RFC 3296.

To create this control, construct a new LDAPControl object. In the LDAPControl constructor, set the OID of the control to netscape.ldap.controls.LDAPControl.MANAGEDSAIT.

Add this control to the array of LDAPControl objects. When you pass the array 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 that contains the reference. This mechanism allows your client application to manage search references in the directory.

Using Password Policy Controls With LDAP Java SDK

Directory Server uses two server response controls to send information back to a client after an LDAP bind operation.

  • The control represented with the OID that corresponds to the constant netscape.ldap.controls.LDAPControl.PWEXPIRED is the expired password control.
    This control is used if the server is configured to require users to change their passwords on first login. The control is also used whenever the passwords are reset.
    The user might be logging in for the first time. The user password might have been reset. In either circumstance, the server sends the control to indicate that the client needs to change the password immediately. When receiving this control, the only operation that the client can perform is to change the user's password. If the client requests any other LDAP operation, the server sends back an LDAP_UNWILLING_TO_PERFORM result code with an expired password control.
  • The control represented with the OID that corresponds to the constant netscape.ldap.controls.LDAPControl.PWEXPIRING is the password expiring warning control.
    This control is used if the server is configured to expire user passwords after a certain amount of time.
    The server sends this control back to the client if the client binds with a password that is soon to expire. If you invoke the getValue method for this LDAPControl object, the method returns the number of seconds before the password expires.

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 With LDAP Java SDK

The control represented with the OID that corresponds to the constant netscape.ldap.controls.LDAPProxiedAuthControl.PROXIEDAUTHREQUEST is a proxied authorization control. It allows LDAP clients to use different credentials, without rebinding, when executing LDAP operations.

For example, suppose a messaging server 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. To use another DN and password 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, the server can act as the user when executing an operation. The messaging server maintains only its own binding to the LDAP server. This mechanism drastically improves performance, especially when processing a large number of requests.