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: Using the LDAP Java Classes
Previous Next Contents Index


Chapter 5 Using the LDAP Java Classes

This chapter covers some of the general LDAP Java classes that are commonly used when writing LDAP clients.

This chapter covers the following topics:


Getting Information About the SDK
You can get version information about the Netscape Directory SDK for Java that you are using (for example, the version of the LDAP Java classes or the highest version of the LDAP protocol that it supports).

To get this information, use the getProperty method of the LDAPConnection object. For a complete list of the SDK properties you can get, see the documentation on the getProperty method.

For example, the following section of code lists the properties of the SDK:

LDAPConnection ld = new LDAPConnection();
try {
   System.out.println( "LDAP Java Classes Version: " +
      (Float)ld.getProperty(LDAPConnection.LDAP_PROPERTY_SDK) );
   System.out.println( "Highest version of LDAP supported: " +
      (Float)ld.getProperty(LDAPConnection.LDAP_PROPERTY_PROTOCOL) );
   System.out.println( "Authentication methods supported: " +
      (String)ld.getProperty(LDAPConnection.LDAP_PROPERTY_SECURITY) );
} catch (LDAPException e) {
   System.out.println( "Could not get SDK properties." );
   System.out.println( "Error: " + e.toString() );
}
...
For information on the different versions of the LDAP Java classes, see the documentation on LDAP_PROPERTY_SDK.

Note that although a setProperty method is listed as one of the available methods, there are currently no properties that you can set. Invoking this method throws an LDAPException.


Handling Exceptions
In the LDAP protocol, the success or failure of an operation is specified by an LDAP result code sent back to the client. (For example, the result code 0 indicates that the operation was successful, and a non-zero result code usually indicates that an error occurred.)

The following sections explain more about exceptions in the LDAP Java classes.

Getting Information About the Error
In the LDAP Java classes, when an error occurs, an LDAPException is thrown. (Note that referrals cause an LDAPReferralException to be thrown. For details, see "Handling Referrals".)

An LDAPException contains the following information:

If the error occurred because an entry specified by a DN could not be found, the LDAPException also contains the DN of the "closest matching entry" that could be found.

To get information from the LDAPException, use one of the following methods:

Note that you can also get the error message describing the LDAP result code by using the errorCodeToString method. (See the section "Getting the Error Message" for details.)

The Directory SDK for Java's JavaDocs include a listing and descriptions of the different LDAP result codes. For information on using these JavaDocs, see "Where to Find Reference Information".

The following section of code gets and prints information about an LDAPException:

...
try {
/* Attempt to perform an LDAP operation here. */
} catch( LDAPException e ) {
   /* Get and print the result code and any other info. */
   int resultCode = e.getLDAPResultCode();
   String serverInfo = e.getLDAPErrorMessage();
   System.out.println( "LDAP Result Code: " + resultCode );
   if ( serverInfo != null ) {
      System.out.println( "Additional Info: " + serverInfo );
   }
   /* If the exception was thrown because an entry
       was not found, print the DN of the closest entry found. */
   switch( resultCode ) {
      case LDAPException.NO_SUCH_OBJECT:
      case LDAPException.ALIAS_PROBLEM:
      case LDAPException.INVALID_DN_SYNTAX:
      case LDAPException.ALIAS_DEREFERENCING_PROBLEM:
         String matchedDN = e.getMatchedDN();
         if ( matchedDN != null ) {
            System.out.println( "Closest Entry: " + matchedDN );
         }
         break;
      default:
         break;
   }
}
...
Getting the Error Message
To get the error message for an LDAP result code, use the errorCodeToString method. For example:

...
try {
/* Attempt to perform an LDAP operation here. */
} catch( LDAPException e ) {
   /* Get and print the error message. */
   int resultCode = e.getLDAPResultCode();
   System.out.println( "Error: " + e.errorCodeToString( resultCode ) );
}
...
Error messages corresponding to each LDAP result code are stored in files in the following location:

dir_root/netscape/ldap/error/ErrorCodes_locale_name.props

where dir_root is a directory that is in your CLASSPATH, and locale_name is the language and country (concatenated and delimited by an underscore) of the current locale.

For example:

netscape/ldap/error/ErrorCodes_en_US.props 
netscape/ldap/error/ErrorCodes_en.props
A default error messages file is provided in the following location:

netscape/ldap/error/ErrorCodes.props 
The result codes and their corresponding descriptions have the following format in the file:

resultcode=errormessage 
For example:

0=Success
1=Operations error
2=Protocol error
3=Timelimit exceeded
4=Sizelimit exceeded
5=Compare false
6=Compare true
...
When you invoke the errorCodeToString method of an LDAPException, the method retrieves the error messages file for the specified locale (or the default locale, if no locale is specified) and reads the error message from the file.

The method searches for the error messages file in the following locations in this order (if no file is found, the method tries to find the next file in this list):

netscape/ldap/error/ErrorCodes_language_country.props
netscape/ldap/error/ErrorCodes_language.props
netscape/ldap/error/ErrorCodes.props

Handling Referrals
If an LDAP server receives a request for a DN that is not under its directory tree, it can refer clients to another LDAP server that may contain that DN. This is known as a referral.

This section explains how to set up your LDAP client to handle referrals automatically. The following topics are covered:

Understanding Referrals
Suppose an LDAP server has a directory that starts under "o=Airius.com". If your client sends the server a request to modify the entry with the DN "uid=bjensen,ou=People,o=AiriusWest.com" (an entry that is not under "o=Airius.com"), one of the following may occur:

Another concept similar to a referral is a search reference. A search reference is an entry with the object class "referral". The "ref" attribute of this object contains an LDAP URL that identifies another LDAP server.

When your client searches a subtree of the directory that contains search references, the server returns a mix of matching entries and search references. As you iterate through the enumeration of search results, if you encounter a search reference and your client does not handle referrals automatically, an LDAPReferralException is thrown.

Enabling or Disabling Referral Handling
By default, clients built with the Netscape Directory SDK for Java automatically follow these referrals to other servers.

To change the way your client handles referrals, use the setOption method of the LDAPConnection object (to change the behavior for all LDAP operations) or the setReferrals method of the LDAPConstraints object (to change the behavior for a specific search request):

Limiting Referral Hops
As a preference for the connection (or as a search constraint for specific search operations), you can specify the maximum number of referral hops that should be followed in a sequence of referrals. This is called the referral hop limit.

For example, suppose you set a limit of 2 referral hops. If your client is referred from LDAP server A to LDAP server B, from LDAP server B to LDAP server C, and from LDAP server C to LDAP server D, your client is being referred 3 times in a row, and it will not follow the referral to LDAP server D because this exceeds the referral hop limit.

If the referral hop limit is exceeded, an LDAPReferralException is thrown.

To set the referral hop limit, use the LDAPv2.REFERRALS_HOP_LIMIT preference with the setOption methodof the LDAPConnection object (to change the behavior for all LDAP operations) or the setHopLimit method of the LDAPConstraints object (to change the behavior for a specific search request).

By default, the maximum number of referral hops is 10.

Binding When Following Referrals
If the connection is set up so that referrals are always followed (see "Enabling or Disabling Referral Handling" for more information), the LDAP server that you connect to may refer you to another LDAP server. By default, the client binds anonymously (no username or password are specified) when following referrals.

If you want your client to authenticate to the LDAP server that it is referred to, you need to specify a way to get the DN and password to be used for authentication. You need to define a class that implements the LDAPRebind interface. Then, you specify an object of this new class using the LDAPv2.REFERRALS_REBIND_PROC preference with the setOption method of the LDAPConnection object (to set this for all LDAP operations) or the setRebindProc method of the LDAPConstraints object (to change the behavior for a specific search request).

The LDAPRebind interfacespecifies a getRebindAuthentication method that returns an LDAPRebindAuth object. The getRebindAuthentication method and the LDAPRebindAuth object it returns are used to get the DN and password for authentication.

The following steps explain how this works:

  1. The LDAP server sends a referral back to the client. The referral contains an LDAP URL that identifies another LDAP server.
  2. The client creates a new LDAPConnection object.
  3. The client connects to the host and port specified in the LDAP URL.
  4. Using the getRebindProc method to find your object (the one that implements the LDAPRebind interface), the client invokes the getRebindAuthentication method, passing in the host and port specified in the LDAP URL.
  5. The getRebindAuthentication method in your object returns an LDAPRebindAuth object.
  6. The client invokes the getDN and getPassword methods of the returned LDAPRebindAuth object to get the DN and password to use for authentication.
  7. The client invokes the authenticate method of the LDAPConnection object and passes the DN and password to authenticate to the server.
Basically, you need to define the following:


Using an In-Memory Cache
The Netscape Directory SDK for Java includes an LDAPCache class that allows you to create an in-memory cache of search results for your client. When send a search request and receive results, the search request and its results are cached. The next time your client issues the same search request, the results are read from the cache.

This section covers the following topics:

How the Cache Operates
Each item in the cache represents a search request and its results. When you create the cache, you can specify the maximum size of the cache and the maximum amount of time that an item can be cached:

Each item is uniquely identified by the search criteria, which includes:

Once a search request is cached, if your client performs the same search again, the results are read from the cache instead of from the server.

Note that if any part of a search request differs from a cached search request (for example, if a different DN is used when authenticating to the server or if the search request specifies that a different set of attributes should be returned), the results are not read from the cache and the search request is sent to the server.

Finally, when creating the cache, you can specify a list of the base DNs in search requests that you want to cache. For example, if you specify "ou=People, o=Airius.com" as a base DN to cache, your client caches search requests where the base DN is "ou=People, o=Airius.com".

Setting Up an In-Memory Cache
To set up a cache for your connection, do the following:

  1. Construct a new LDAPCache object which represents the cache.
  2. Invoke the setCache method of an LDAPConnection object to associate the cache with the connection.
For example, the following section of code creates a cache with the maximum size of 1MB. Items in the cache expire and are automatically removed after 1 hour.

...
import netscape.ldap.*;
import java.util.*;
...
LDAPConnection ld = null;
int status = -1;
String MY_HOST = "localhost";

try {
   ld = new LDAPConnection();

   /* Create a cache for the connection */
   int MAX_TIME_CACHED = 3600;
   int MAX_SIZE = 1000000;
   LDAPCache myCache = new LDAPCache( MAX_TIME_CACHED, MAX_SIZE );
   ld.setCache( myCache );

   /* Connect to server */
   ld.connect( MY_HOST, LDAP_PORT );
   ...
} catch( LDAPException e ) {
   System.out.println( "Error: " + e.toString() );
}
...
Caching Requests by Base DN
If you do not want all search requests cached, you can specify a set of base DNs for search requests that you want cached in the LDAPCache constructor.

For example, the following section of code constructs a cache that only tracks search requests that specify the base DNs "ou=People, o=Airius.com" and "ou=Groups,o=Airius.com".

...
/* Create a cache for the connection */
int MAX_TIME_CACHED = 3600;
int MAX_SIZE = 1000000;
String [] BASE_DN_CACHED = {"ou=People,o=Airius.com",
   "ou=Groups,o=Airius.com"};
LDAPCache myCache = new LDAPCache( MAX_TIME_CACHED, MAX_SIZE,
   BASE_DN_CACHED );
...
Sharing a Cache Between Connections
You can also share the same in-memory cache among different connections. To do this:

  1. Invoke the getCache methodof an LDAPConnection object to get the LDAPCache object associated with it.
  2. Invoke the setCache methodof a different LDAPConnection object to associate the retrieved LDAPCache object with it.
Note that when you clone an LDAPConnection object, the new object automatically shares the same LDAPCache object with the original object.

Flushing the Cache
To flush items from the cached, invoke the flushEntries method of the LDAPCache object. You can either flush selected items from the cache or all items from the cache.

To flush selected items from the cache, specify the base DN of the search requests that you want to flush. To do this, you can specify a DN and search scope as arguments to the flushEntries method. If the base DN of a cached search request falls within the scope you've specified, the search request is flushed from the cache.

For example, the following section of code flushes selected search requests from the cache. If the base DN of a search request falls under the "ou=People,o=Airius.com" subtree, the item is removed from the cache.

...
import netscape.ldap.*;
import java.util.*;
...
LDAPCache myCache;
...
/* Perform search requests. */
...
/* Flush items from the cache. Flush the
   search requests that have base DNs under the
   "ou=People, o=Airius.com" subtree. */
myCache.flushEntries( "ou=People, o=Airius.com",
   LDAPConnection.SCOPE_SUB );
...
To flush all items from the cache, pass null for the first argument of the flushEntries method:

myCache.flushEntries( null, 0 ); 
Getting Cache Statistics
You can invoke the following methods of the LDAPCache object to get statistics on the cache:

You can also get a running count of the number of requests that access the cache:

For example, the following section of code gets and prints cache statistics.

...
import netscape.ldap.*;
import java.util.*;
...
import netscape.ldap.*;
import java.util.*;
...
LDAPConnection ld;
...
if ( (ld != null) && ld.isConnected() ) {
   LDAPCache connCache = ld.getCache();
   if ( connCache != null ) {
      System.out.println( "Cache size:\t\t" +
         connCache.getSize()/1000 + " kbytes" );
      System.out.println( "Available:\t\t" +
         connCache.getAvailableSize()/1000 + " kbytes" );
      System.out.println( "Maximum age:\t\t" +
         connCache.getTimeToLive()/1000 + " seconds" );
      System.out.println( "Total hits:\t\t" +
         connCache.getNumHits() + " hits" );
      System.out.println( "Total misses:\t\t" +
         connCache.getNumMisses() + " misses" );
      System.out.println( "Total requests:\t\t" +
         connCache.getTotalOperations() + " requests" );
} else {
      System.out.println( "No cache associated with the connection." );
...

Cloning a Connection
You can create several LDAPConnection objects that share a single physical network connection to the LDAP server by invoking the LDAPConnection.clone method. (Note, however, that if you clone an object before a connection is made to the server, the cloned object does not share the same connection as the original object.)

Each clone can disconnect from the server without affecting the connection for the other clones. The network connection remains open until all clones have disconnected or gone out of scope.

If the clone disconnects or reconnects, it is completely dissociated from the source object and other clones.

Note the following:


Manipulating Distinguished Names
A distinguished name (DN) uniquely identifies an entry in the directory tree. You can get the DN for an entry (see "Getting Distinguished Names from the Results") or specify a DN to read an entry from the directory (see "Reading an Entry").

The Netscape Directory SDK for Java contains a utility class, LDAPDN, that provides methods for manipulating DNs.

Getting the Components of a Distinguished Name
If you want to access individual components of a distinguished name or a relative distinguished name, invoke the LDAPDN.explodeDN method or the LDAPDN.explodeRDN method.

Both functions return an array of strings representing the individual components of the distinguished name.

You can specify whether or not you want the names of the components included in the array by using the notypes parameter.

 

© Copyright 1999 Netscape Communications Corporation. All rights reserved.