Using the LDAP Java Classes
This chapter covers general LDAP Java classes that are commonly used
when writing LDAP clients.
This chapter covers the following topics:
Getting Information About Directory
SDK for Java
Handling Exceptions
With Directory SDK for Java
Handling Referrals With
Directory SDK for Java
Using In-Memory Cache With
Directory SDK for Java
Cloning a Connection
With Directory SDK for Java
Manipulating Distinguished
Names With Directory SDK for Java
Getting Information About &DirectorySDKForJava;
&DirectorySDKForJava;
getting information about
You can get information about the version of &DirectorySDKForJava; that
you are using. Version information tells you the version of the LDAP Java
classes. Version information can also tell you the highest version of the
LDAP protocol that &DirectorySDKForJava; supports.
To get this information, use the getProperty method
of the LDAPConnection object.
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());
}
Although a setProperty method is provided, currently
no properties exist that you can set. If you invoke the setProperty method,
the method returns an LDAPException.
Handling Exceptions With &DirectorySDKForJava;
exceptions
handling
In LDAP, 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. A non zero result code usually indicates
that an error occurred.
Getting Information About the Error
exceptions
getting information about
LDAP result code
In the LDAP Java classes, when an error occurs, an LDAPException
is returned. Referrals cause an LDAPReferralException to
be returned as described in Handling
Referrals With Directory SDK for Java.
An LDAPException contains the following information:
The LDAP result code for the error that occurred
A message that contains any additional information about the
error from the server
An error can occur when an entry specified by a DN cannot be found.
The LDAPException then also contains the DN of the
closest matching entry that can be found.
To get information from the LDAPException, use
one of the following methods:
To get the string representation of the exception, use the
toString method.
To get the LDAP result code, use the getLDAPResultCode method.
To get any additional information sent by the server, use
the getLDAPErrorMessage method.
To get the closest matching DN in cases where your client
specified a DN to a nonexistent entry, use the getMatchedDN method.
To get the error message describing the LDAP result code, use the
errorCodeToString method, as described in Getting the Error Message.
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 returned 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
LDAP result code
string description for
To get the error message for an LDAP result code, use the errorCodeToString
method.
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 located either
inside the ldapjdk.jar file or under another directory
in your CLASSPATH, in a properties file named netscape/ldap/errors/ErrorCodes.props
or netscape/ldap/errors/ErrorCodes_locale.props
. locale can be a two-letter version
of the locale, such as de, fr, or
ja, or it can be a full version of the locale, such as en_US.
When you invoke the errorCodeToString method of an
LDAPException, the method retrieves the error message string for
the specified locale. If no locale is specified, the method retrieves the
default locale from the properties file. The errorCodeToString method
looks for locale-specific properties files in the following order, retrieving
the first property that is found:
netscape/ldap/error/ErrorCodes_language_
country.props
netscape/ldap/error/ErrorCodes_language.props
netscape/ldap/error/ErrorCodes.props
Handling Referrals With &DirectorySDKForJava;
referrals
An LDAP server can receive a request for a DN that is not under its
directory tree. The server can then refer clients to another LDAP server that
might contain that DN. The response is known as a referral.
This section explains how to set up your LDAP client to handle referrals automatically.
Understanding Referrals
Suppose an LDAP server has a directory that starts under dc=example,dc=com
. Your client might send the server a request to modify the entry
with the DN uid=bjensen,ou=People,o=example.com. The entry
is not under dc=example,dc=com. One of the following can
occur.
If the server is not configured to send a referral, an
LDAPException is returned with the LDAP result code LDAPException.NO_SUCH_OBJECT
.
If the server is configured to refer you to another LDAP server,
the server sends a referral back to your client.
Depending on how your LDAP client is configured, one of the following
can occur:
If your client handles referrals automatically, your client
connects to the LDAP server specified in the referral and requests to modify
the entry. The client binds anonymously to that server. To bind as a specific
user, refer to Enabling or Disabling
Referral Handling.
If your client does not handle referrals automatically, an
LDAPReferralException is returned. You can get the LDAP URL specified
in the referral by catching the exception, and then invoking the getURLs
method.
By default, clients built with &DirectorySDKForJava; are configured
to follow referrals automatically.
Another concept that is 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 points to 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, you can encounter
a search reference although your client does not handle referrals automatically.
An LDAPReferralException is then returned.
Enabling or Disabling Referral Handling
referrals
handling automatically
By default, clients built with &DirectorySDKForJava; automatically
follow referrals to other servers.
To change the way your client handles referrals, use one of two methods.
Use the setOption method of the LDAPConnection object
to change the behavior for all LDAP operations. Alternatively, use the setReferrals
method of the LDAPConstraints object to
change the behavior for a specific search request.
To prevent the client from automatically following referrals,
pass LDAPv3.REFERRALS and false as arguments
to the setOption method. Alternatively, pass false as
the argument to the setReferrals method.
To enable the client to follow referrals automatically again,
pass LDAPv3.REFERRALS and true as arguments
to the setOption method. Alternatively, pass true as
the argument to the setReferrals method.
Limiting Referral Hops
referrals
specifying maximum hops
You can specify the maximum number of referral hops that should be followed
in a sequence of referrals. You can set the preference for the connection.
You can also set the maximum as a constraint for specific search operations.
The maximum is called the referral hop limit.
For example, suppose you set a limit of two referral hops. If LDAP server
A refers to server B, B to C, and C to D, your client is being referred three
times in a row. Your client does not follow the referral to LDAP server D
because this referral exceeds the referral hop limit.
If the referral hop limit is exceeded, an LDAPReferralException is
returned.
To set the referral hop limit, use either of two methods. Use the
LDAPv3.REFERRALS_HOP_LIMIT preference with the setOption method
of the LDAPConnection object to change the behavior
for all LDAP operations. Alternatively, use 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
authentication
authenticating during referrals
referrals
authenticating
If the connection is set up so that referrals are always followed, the
LDAP server that you connect to can refer you to another server. By default,
the client binds anonymously such that no user names or passwords are specified
when following referrals.
To authenticate to the LDAP server that you are referred to, specify
how to get the DN and password for authentication. You need to define a class
that implements the LDAPRebind interface. Then, specify
an object of this new class with either of two methods. Use the LDAPv3.REFERRALS_REBIND_PROC
preference with the setOption method of the
LDAPConnection object to set the preference for all LDAP operations.
Alternatively, use the setRebindProc method of the
LDAPConstraints object to change the behavior for a specific search
request.
The LDAPRebind interface specifies a getRebindAuthentication
method that returns an LDAPRebindAuth object.
The getRebindAuthentication method and the LDAPRebindAuth
object that the method returns are used to get the DN and password
for authentication.
The following steps explain how this works.
The LDAP server sends a referral back to the client. The referral
contains an LDAP URL that points to another LDAP server.
The client creates a new LDAPConnection object.
The client connects to the host and port specified in the
LDAP URL.
You can use the getRebindProc method to
find your object, the object that implements the LDAPRebind interface.
The client then invokes the getRebindAuthentication method,
passing in the host and port specified in the LDAP URL.
The getRebindAuthentication method in your
object returns an LDAPRebindAuth object.
The client invokes the getDN and getPassword
methods of the returned LDAPRebindAuth object
to get the DN and password to use for authentication.
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:
A class that implements the LDAPRebind interface
A getRebindAuthentication that takes a
host name and port number.
This method creates an LDAPRebindAuth object
that specifies the DN and password to use for authentication.
Using In-Memory Cache With &DirectorySDKForJava;
cache
in-memory cache
connection
caching results
LDAP session
caching results
search results
caching
&DirectorySDKForJava; includes an LDAPCache class
that allows you to create an in-memory cache of search results for your client.
When you send a search request, you receive results. The search request and
its results are then cached. The next time your client issues the same search
request, the results are read from the cache.
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.
You can also specify the maximum amount of time that an item can be cached.
When an item's age exceeds that time limit, the item is removed
from the cache. The cache is checked once a minute for expired items.
If adding a new item causes the cache to exceed its maximum
size, items are removed from the cache. Removal makes space for the new item.
Items are removed on a first in, first out basis.
Each item is uniquely identified by the search criteria, which includes
the following:
Host name and port number of the LDAP server
Base DN of the search
Search filter
Scope of the search
Attributes to be returned in the search results
DN used to authenticate the client when binding to the server
LDAP v3 controls specified in the search request
After 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, the results are read from the server. For example, a different DN
might be used when authenticating to the server. Alternatively, the search
request might specify that a different set of attributes should be returned.
In either case, the results are not read from the cache. Instead, 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,dc=example,dc=com as a base DN to cache, your client caches
search requests where the base DN is ou=People,dc=example,dc=com.
Setting Up an In-Memory Cache
cache
setting up
To set up a cache for your connection, do the following:
Construct a new LDAPCache object that
represents the cache.
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 1 Mbyte. Items in the cache expire and are automatically removed
after one hour.
try {
LDAPConnection ld = new LDAPConnection();
/* Create a cache for the connection */
int MAX_TIME_CACHED = 3600; // 3600 seconds == 1 hour
int MAX_SIZE = 1000000; // 1000000 bytes == 1 MB
LDAPCache myCache = new LDAPCache(MAX_TIME_CACHED, MAX_SIZE);
ld.setCache(myCache);
/* Connect to server */
ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT);
/*
* Perform operations...
*/
} catch (LDAPException e) {
System.out.println("Error: " + e.toString());
}
Caching Requests by Base DN
If you do not want all search requests cached, specify an array of base
DNs for search requests to cache 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,dc=example,dc=com
and ou=Groups,dc=example,dc=com.
/* Create a cache for the connection */
int MAX_TIME_CACHED = 3600;
int MAX_SIZE = 1000000;
String [] BASE_DN_CACHED = {"ou=People,dc=example,dc=com",
"ou=Groups,dc=example,dc=com"};
LDAPCache myCache = new LDAPCache(MAX_TIME_CACHED, MAX_SIZE,
BASE_DN_CACHED);
Sharing a Cache Among Connections
cache
sharing between connections
You can also share the same in-memory cache among different connections.
Invoke the getCache method of an LDAPConnection
object to get the LDAPCache object that
is used.
Invoke the setCache method of a different
LDAPConnection object to associate the retrieved LDAPCache
object with the connection.
When you clone an LDAPConnection object, the
new object automatically shares the same LDAPCache object
with the original object.
Flushing the Cache
cache
flushing
To flush items from the cache, invoke the flushEntries method
of the LDAPCache object. You can flush either selected
items 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. 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 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,dc=example,dc=com
subtree, the item is removed from the cache.
LDAPCache myCache;
/* Perform search requests... */
/*
* Flush search requests with base DNs under
* ou=People,dc=example,dc=com.
*/
myCache.flushEntries("ou=People,dc=example,dc=com",
LDAPConnection.SCOPE_SUB);
To flush all items from the cache, pass null as
the first argument of the flushEntries method:
myCache.flushEntries(null, 0);
Getting Cache Statistics
cache
getting statistics
You can invoke the following methods of the LDAPCache object
to get statistics on the cache.
To get the total amount of available space in bytes that are
left in the cache, invoke the getAvailableSize method.
To get the array of base DNs of the search requests to be
cached, invoke the getBaseDNs method.
To get the total number of items that have been flushed from
the cache, not including items flushed when invoking the flushEntries method,
invoke the getNumFlushes method.
To get the maximum size of the cache in bytes, invoke the
getSize method.
To get the maximum amount of time that an item can be cached
in seconds, get the getTimeToLive method.
You can also get a running count of the number of requests that access
the cache.
To get the total number of requests for retrieving items from
the cache, invoke the getTotalOperation method.
To get the total number of requests that retrieved an item
from the cache, invoke the getNumHits method.
To get the total number of requests that failed to find and
retrieve an item from the cache, invoke the getNumMisses method.
For example, the following section of code gets and prints cache statistics.
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 With &DirectorySDKForJava;
connection
cloning
You can create several LDAPConnection objects
that share a single physical network connection to the LDAP server by invoking
the LDAPConnection.clone method.
Clones have the following properties:
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 in an
open state until all clones have either disconnected or gone out of scope.
If the clone disconnects or reconnects, the clone is completely
dissociated from the source object and other clones.
A cloned LDAPConnection object has
a separate set of session preferences and constraints. In other words, the
clone is associated with its own LDAPSearchConstraints object.
Changes to an option or to a search constraint only affect requests issued
using that object.For example, suppose an LDAPConnection object
allows a maximum of 100 results to be returned from a search. If you clone
an LDAPConnection object, you can change the maximum
number of results in the clone from 100 to 200. Yet, the initial object still
allows only 100 results to be returned.
All clones are authenticated to the server as the same user.
If you authenticate again to the server as a different user, the current clone
is disconnected. The clone connects separately to the server. The LDAPConnection
object is no longer a clone of another LDAPConnection object.
Manipulating Distinguished Names With &DirectorySDKForJava;
distinguished names
manipulating
A distinguished name (DN) uniquely identifies an entry in the directory
tree. You can get the DN for an entry as explained in Getting Distinguished
Names. Alternatively, you can specify a DN to read an entry from the
directory as explained in
Reading an Entry With Directory SDK for Java. &DirectorySDKForJava; includes
a utility class, LDAPDN, that provides
methods for manipulating DNs.
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 methods return an array of String objects
that represent 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.
Set notypes to false if
you want to include component attribute types in the array.
LDAPDN.explodeDN("uid=bjensen,ou=People,dc=example,dc=com", false);
The method returns the array {"uid=bjensen", "ou=People", "dc=example",
"dc=com"}.
Set notypes to true if
you do not want component attribute types returned in the array.
LDAPDN.explodeDN("uid=bjensen,ou=People,dc=example,dc=com", true);
The method returns the array {"bjensen", "People", "example",
"com"}.