<!--

Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
Portions copyright 1999 Netscape Communications Corporation. All
Rights Reserved.

The contents of this document are subject to the terms of the
Creative Commons Attribution-ShareAlike 2.5 license or any later
version (the "License"). You may not use this document except in
compliance with the License.

See the License for the specific language governing
permissions and limitations under the License. You can obtain
a copy of the License at
http://creativecommons.org/licenses/by-sa/2.5/legalcode.

-->
<chapter id="common-classes"><title>Using the LDAP Java Classes</title>
<highlights>
<para>This chapter covers general LDAP Java classes that are commonly used
when writing LDAP clients.</para>
<itemizedlist>
<para>This chapter covers the following topics:</para>
<listitem><para><olink targetptr="jdk-info">Getting Information About Directory
SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="handling-exceptions">Handling Exceptions
With Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="handling-referrals">Handling Referrals With
Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="in-memory-cache">Using In-Memory Cache With
Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="cloning-connection">Cloning a Connection
With Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="handling-dns">Manipulating Distinguished
Names With Directory SDK for Java</olink></para></listitem>
</itemizedlist>
</highlights>
<sect1 id="jdk-info"><title>Getting Information About &DirectorySDKForJava;</title>
<indexterm>
<primary>&DirectorySDKForJava;</primary>
<secondary>getting information about</secondary>
</indexterm>
<para>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.</para>
<para>To get this information, use the <literal>getProperty</literal> method
of the <classname>LDAPConnection</classname> object.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
try {
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("LDAP Java Classes Version: " +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Float) ld.getProperty(LDAPConnection.LDAP_PROPERTY_SDK));
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Highest version of LDAP supported: " +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Float) ld.getProperty(LDAPConnection.LDAP_PROPERTY_PROTOCOL));
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Authentication methods supported: " +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(String) ld.getProperty(LDAPConnection.LDAP_PROPERTY_SECURITY));
} catch (LDAPException e) {
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Could not get SDK properties.");
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Error: " + e.toString());
}</programlisting>
<para>Although a <literal>setProperty</literal> method is provided, currently
no properties exist that you can set. If you invoke the <literal>setProperty</literal> method,
the method returns an <classname>LDAPException</classname>.</para></sect1>
<sect1 id="handling-exceptions"><title>Handling Exceptions With &DirectorySDKForJava;</title>
<indexterm>
<primary>exceptions</primary>
<secondary>handling</secondary>
</indexterm>
<para>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 <returnvalue>0</returnvalue> indicates
that the operation was successful. A non zero result code usually indicates
that an error occurred.</para>
<sect2 id="getting-info"><title>Getting Information About the Error</title>
<indexterm>
<primary>exceptions</primary>
<secondary>getting information about</secondary>
</indexterm><indexterm>
<primary>LDAP result code</primary>
</indexterm>
<para>In the LDAP Java classes, when an error occurs, an <classname>LDAPException
</classname> is returned. Referrals cause an <classname>LDAPReferralException</classname> to
be returned as described in <olink targetptr="handling-referrals">Handling
Referrals With Directory SDK for Java</olink>.</para>
<itemizedlist>
<para>An <classname>LDAPException</classname> contains the following information:
</para>
<listitem><para>The LDAP result code for the error that occurred</para>
</listitem>
<listitem><para>A message that contains any additional information about the
error from the server</para></listitem>
</itemizedlist>
<para>An error can occur when an entry specified by a DN cannot be found.
The <classname>LDAPException</classname> then also contains the DN of the <firstterm>
closest matching entry</firstterm> that can be found.</para>
<itemizedlist>
<para>To get information from the <classname>LDAPException</classname>, use
one of the following methods:</para>
<listitem><para>To get the string representation of the exception, use the <literal>
toString</literal> method.</para></listitem>
<listitem><para>To get the LDAP result code, use the <literal>getLDAPResultCode</literal> method.
</para></listitem>
<listitem><para>To get any additional information sent by the server, use
the <literal>getLDAPErrorMessage</literal> method.</para></listitem>
<listitem><para>To get the closest matching DN in cases where your client
specified a DN to a nonexistent entry, use the <literal>getMatchedDN</literal> method.
</para></listitem>
</itemizedlist>
<para>To get the error message describing the LDAP result code, use the <literal>
errorCodeToString</literal> method, as described in <olink
targetptr="error-message">Getting the Error Message</olink>.</para>
<para>The following section of code gets and prints information about an <classname>
LDAPException</classname>.</para>
<programlisting>try {
&nbsp;&nbsp;&nbsp;&nbsp;/* Attempt to perform an LDAP operation here. */
} catch (LDAPException e) {
&nbsp;&nbsp;&nbsp;&nbsp;/* Get and print the result code and any other info. */
&nbsp;&nbsp;&nbsp;&nbsp;int resultCode = e.getLDAPResultCode();
&nbsp;&nbsp;&nbsp;&nbsp;String serverInfo = e.getLDAPErrorMessage();
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("LDAP Result Code: " + resultCode);
&nbsp;&nbsp;&nbsp;&nbsp;if (serverInfo != null) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Additional Info: " + serverInfo);
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;/*
&nbsp;&nbsp;&nbsp;&nbsp; * If the exception was returned because an entry was
     * not found, print the DN of the closest entry found.
&nbsp;&nbsp;&nbsp;&nbsp; */
&nbsp;&nbsp;&nbsp;&nbsp;switch (resultCode) {
&nbsp;&nbsp;&nbsp;&nbsp;case LDAPException.NO_SUCH_OBJECT:
&nbsp;&nbsp;&nbsp;&nbsp;case LDAPException.ALIAS_PROBLEM:
&nbsp;&nbsp;&nbsp;&nbsp;case LDAPException.INVALID_DN_SYNTAX:
&nbsp;&nbsp;&nbsp;&nbsp;case LDAPException.ALIAS_DEREFERENCING_PROBLEM:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String matchedDN = e.getMatchedDN();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (matchedDN != null) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Closest Entry: " + matchedDN);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;default:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;}
}</programlisting>
</sect2>
<sect2 id="error-message"><title>Getting the Error Message</title>
<indexterm>
<primary>LDAP result code</primary>
<secondary>string description for</secondary>
</indexterm>
<para>To get the error message for an LDAP result code, use the <literal>errorCodeToString
</literal> method.</para>
<programlisting>try {
&nbsp;&nbsp;&nbsp;&nbsp;/* Attempt to perform an LDAP operation here. */
} catch (LDAPException e) {
&nbsp;&nbsp;&nbsp;&nbsp;/* Get and print the error message. */
&nbsp;&nbsp;&nbsp;&nbsp;int resultCode = e.getLDAPResultCode();
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Error: " + e.errorCodeToString(resultCode));
}</programlisting>
<para>Error messages corresponding to each LDAP result code are located either
inside the <filename>ldapjdk.jar</filename> file or under another directory
in your <envar>CLASSPATH</envar>, in a properties file named <filename>netscape/ldap/errors/ErrorCodes.props
</filename> or <filename>netscape/ldap/errors/ErrorCodes_<replaceable>locale</replaceable>.props
</filename>. <replaceable>locale</replaceable> can be a two-letter version
of the locale, such as <literal>de</literal>, <literal>fr</literal>, or <literal>
ja</literal>, or it can be a full version of the locale, such as <literal>en_US</literal>.
</para>
<para>When you invoke the <literal>errorCodeToString</literal> method of an <classname>
LDAPException</classname>, 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 <literal>errorCodeToString</literal> method
looks for locale-specific properties files in the following order, retrieving
the first property that is found:</para>
<programlisting>netscape/ldap/error/ErrorCodes_<replaceable>language</replaceable>_<replaceable>
country</replaceable>.props
netscape/ldap/error/ErrorCodes_<replaceable>language</replaceable>.props
netscape/ldap/error/ErrorCodes.props</programlisting>
</sect2>
</sect1>
<sect1 id="handling-referrals"><title>Handling Referrals With &DirectorySDKForJava;</title>
<indexterm>
<primary>referrals</primary>
</indexterm>
<para>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 <firstterm>referral</firstterm>.
This section explains how to set up your LDAP client to handle referrals automatically.
</para>
<sect2 id="understanding-referrals"><title>Understanding Referrals</title>
<itemizedlist>
<para>Suppose an LDAP server has a directory that starts under <literal>dc=example,dc=com
</literal>. Your client might send the server a request to modify the entry
with the DN <literal>uid=bjensen,ou=People,o=example.com</literal>. The entry
is not under <literal>dc=example,dc=com</literal>. One of the following can
occur.</para>
<listitem><para>If the server is not configured to send a referral, an <classname>
LDAPException</classname> is returned with the LDAP result code <constant>LDAPException.NO_SUCH_OBJECT
</constant>.</para></listitem>
<listitem><para>If the server is configured to refer you to another LDAP server,
the server sends a referral back to your client.</para>
<itemizedlist>
<para>Depending on how your LDAP client is configured, one of the following
can occur:</para>
<listitem><para>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 <olink targetptr="enabling-referrals">Enabling or Disabling
Referral Handling</olink>.</para></listitem>
<listitem><para>If your client does not handle referrals automatically, an <classname>
LDAPReferralException</classname> is returned. You can get the LDAP URL specified
in the referral by catching the exception, and then invoking the <literal>getURLs
</literal> method.</para></listitem>
</itemizedlist>
<para>By default, clients built with &DirectorySDKForJava; are configured
to follow referrals automatically.</para></listitem>
</itemizedlist>
<para>Another concept that is similar to a referral is a search reference.
A <firstterm>search reference</firstterm> is an entry with the object class <literal>
referral</literal>. The <literal>ref</literal> attribute of this object contains
an LDAP URL that points to another LDAP server.</para>
<para>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 <classname>LDAPReferralException</classname> is then returned.</para></sect2>
<sect2 id="enabling-referrals"><title>Enabling or Disabling Referral Handling</title>
<indexterm>
<primary>referrals</primary>
<secondary>handling automatically</secondary>
</indexterm>
<para>By default, clients built with &DirectorySDKForJava; automatically
follow referrals to other servers.</para>
<itemizedlist>
<para>To change the way your client handles referrals, use one of two methods.
Use the <literal>setOption</literal> method of the <classname>LDAPConnection</classname> object
to change the behavior for all LDAP operations. Alternatively, use the <literal>setReferrals
</literal> method of the <classname>LDAPConstraints</classname> object to
change the behavior for a specific search request.</para>
<listitem><para>To prevent the client from automatically following referrals,
pass <literal>LDAPv3.REFERRALS</literal> and <literal>false</literal> as arguments
to the <literal>setOption</literal> method. Alternatively, pass <literal>false</literal> as
the argument to the <literal>setReferrals</literal> method.</para></listitem>
<listitem><para>To enable the client to follow referrals automatically again,
pass <literal>LDAPv3.REFERRALS</literal> and <literal>true</literal> as arguments
to the <literal>setOption</literal> method. Alternatively, pass <literal>true</literal> as
the argument to the <literal>setReferrals</literal> method.</para></listitem>
</itemizedlist>
</sect2>
<sect2 id="limiting-referral-hops"><title>Limiting Referral Hops</title>
<indexterm>
<primary>referrals</primary>
<secondary>specifying maximum hops</secondary>
</indexterm>
<para>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 <firstterm>referral hop limit</firstterm>.</para>
<para>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.</para>
<para>If the referral hop limit is exceeded, an <classname>LDAPReferralException</classname> is
returned.</para>
<para>To set the referral hop limit, use either of two methods. Use the <literal>
LDAPv3.REFERRALS_HOP_LIMIT</literal> preference with the <literal>setOption</literal> method
of the <classname>LDAPConnection</classname> object to change the behavior
for all LDAP operations. Alternatively, use the <literal>setHopLimit</literal> method
of the <classname>LDAPConstraints</classname> object to change the behavior
for a specific search request.</para>
<para>By default, the maximum number of referral hops is 10.</para></sect2>
<sect2 id="referral-bind"><title>Binding When Following Referrals</title>
<indexterm>
<primary>authentication</primary>
<secondary>authenticating during referrals</secondary>
</indexterm><indexterm>
<primary>referrals</primary>
<secondary>authenticating</secondary>
</indexterm>
<para>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.</para>
<para>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 <classname>LDAPRebind</classname> interface. Then, specify
an object of this new class with either of two methods. Use  the <literal>LDAPv3.REFERRALS_REBIND_PROC
</literal> preference with the <literal>setOption</literal> method of the <classname>
LDAPConnection</classname> object to set the preference for all LDAP operations.
Alternatively, use the <literal>setRebindProc</literal> method of the <classname>
LDAPConstraints</classname> object to change the behavior for a specific search
request.</para>
<para>The <classname>LDAPRebind</classname> interface specifies a <literal>getRebindAuthentication
</literal> method that returns an <classname>LDAPRebindAuth</classname> object.
The <literal>getRebindAuthentication</literal> method and the <classname>LDAPRebindAuth
</classname> object that the method returns are used to get the DN and password
for authentication.</para>
<orderedlist>
<para>The following steps explain how this works.</para>
<listitem><para>The LDAP server sends a referral back to the client. The referral
contains an LDAP URL that points to another LDAP server.</para></listitem>
<listitem><para>The client creates a new <classname>LDAPConnection</classname> object.
</para></listitem>
<listitem><para>The client connects to the host and port specified in the
LDAP URL.</para></listitem>
<listitem><para>You can use the <literal>getRebindProc</literal> method to
find your object, the object that implements the <classname>LDAPRebind</classname> interface.
The client then invokes the <literal>getRebindAuthentication</literal> method,
passing in the host and port specified in the LDAP URL.</para></listitem>
<listitem><para>The <literal>getRebindAuthentication</literal> method in your
object returns an <classname>LDAPRebindAuth</classname> object.</para>
</listitem>
<listitem><para>The client invokes the <literal>getDN</literal> and <literal>getPassword
</literal> methods of the returned <classname>LDAPRebindAuth</classname> object
to get the DN and password to use for authentication.</para></listitem>
<listitem><para>The client invokes the authenticate method of the <classname>LDAPConnection
</classname> object and passes the DN and password to authenticate to the
server.</para></listitem>
</orderedlist>
<itemizedlist>
<para>Basically, you need to define the following:</para>
<listitem><para>A class that implements the <classname>LDAPRebind</classname> interface
</para></listitem>
<listitem><para>A <literal>getRebindAuthentication</literal> that takes a
host name and port number. </para></listitem>
<listitem><para>This method creates an <classname>LDAPRebindAuth</classname> object
that specifies the DN and password to use for authentication.</para></listitem>
</itemizedlist>
</sect2>
</sect1>
<sect1 id="in-memory-cache"><title>Using In-Memory Cache With &DirectorySDKForJava;</title>
<indexterm>
<primary>cache</primary>
</indexterm><indexterm>
<primary>in-memory cache</primary>
</indexterm><indexterm>
<primary>connection</primary>
<secondary>caching results</secondary>
</indexterm><indexterm>
<primary>LDAP session</primary>
<secondary>caching results</secondary>
</indexterm><indexterm>
<primary>search results</primary>
<secondary>caching</secondary>
</indexterm>
<para>&DirectorySDKForJava; includes an <classname>LDAPCache</classname> 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.</para>
<sect2 id="understanding-cache"><title>How the Cache Operates</title>
<itemizedlist>
<para>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.</para>
<listitem><para>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.</para>
</listitem>
<listitem><para>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.</para></listitem>
</itemizedlist>
<itemizedlist>
<para>Each item is uniquely identified by the search criteria, which includes
the following:</para>
<listitem><para>Host name and port number of the LDAP server</para></listitem>
<listitem><para>Base DN of the search</para></listitem>
<listitem><para>Search filter</para></listitem>
<listitem><para>Scope of the search</para></listitem>
<listitem><para>Attributes to be returned in the search results</para>
</listitem>
<listitem><para>DN used to authenticate the client when binding to the server</para>
</listitem>
<listitem><para>LDAP v3 controls specified in the search request</para>
</listitem>
</itemizedlist>
<para>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.</para>
<para>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.</para>
<para>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 <literal>
ou=People,dc=example,dc=com</literal> as a base DN to cache, your client caches
search requests where the base DN is <literal>ou=People,dc=example,dc=com</literal>.
</para></sect2>
<sect2 id="cache-setup"><title>Setting Up an In-Memory Cache</title>
<indexterm>
<primary>cache</primary>
<secondary>setting up</secondary>
</indexterm>
<orderedlist>
<para>To set up a cache for your connection, do the following:</para>
<listitem><para>Construct a new <classname>LDAPCache</classname> object that
represents the cache.</para></listitem>
<listitem><para>Invoke the <literal>setCache</literal> method of an <classname>LDAPConnection
</classname> object to associate the cache with the connection.</para>
</listitem>
</orderedlist>
<para>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.</para>
<programlisting>try {
&nbsp;&nbsp;&nbsp;&nbsp;LDAPConnection ld = new LDAPConnection();

&nbsp;&nbsp;&nbsp;&nbsp;/* Create a cache for the connection */
&nbsp;&nbsp;&nbsp;&nbsp;int MAX_TIME_CACHED = 3600; // 3600 seconds == 1 hour
&nbsp;&nbsp;&nbsp;&nbsp;int MAX_SIZE = 1000000;&nbsp;&nbsp;&nbsp;&nbsp; // 1000000 bytes == 1 MB
&nbsp;&nbsp;&nbsp;&nbsp;LDAPCache myCache = new LDAPCache(MAX_TIME_CACHED, MAX_SIZE);
&nbsp;&nbsp;&nbsp;&nbsp;ld.setCache(myCache);

&nbsp;&nbsp;&nbsp;&nbsp;/* Connect to server */
&nbsp;&nbsp;&nbsp;&nbsp;ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT);

&nbsp;&nbsp;&nbsp;&nbsp;/*
&nbsp;&nbsp;&nbsp;&nbsp; * Perform operations...
&nbsp;&nbsp;&nbsp;&nbsp; */
} catch (LDAPException e) {
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Error: " + e.toString());
}</programlisting>
</sect2>
<sect2 id="caching-basedn"><title>Caching Requests by Base DN</title>
<para>If you do not want all search requests cached, specify an array of base
DNs for search requests to cache in the <classname>LDAPCache</classname> constructor.
</para>
<para>For example, the following section of code constructs a cache that only
tracks search requests that specify the base DNs <literal>ou=People,dc=example,dc=com
</literal> and <literal>ou=Groups,dc=example,dc=com</literal>.</para>
<programlisting>/* 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",
&nbsp;&nbsp;&nbsp;&nbsp;"ou=Groups,dc=example,dc=com"};
LDAPCache myCache = new LDAPCache(MAX_TIME_CACHED, MAX_SIZE,
&nbsp;&nbsp;&nbsp;&nbsp;BASE_DN_CACHED);</programlisting>
</sect2>
<sect2 id="sharing-cache"><title>Sharing a Cache Among Connections</title>
<indexterm>
<primary>cache</primary>
<secondary>sharing between connections</secondary>
</indexterm>
<para>You can also share the same in-memory cache among different connections.</para>
<itemizedlist>
<listitem><para>Invoke the <literal>getCache</literal> method of an <classname>LDAPConnection
</classname> object to get the <classname>LDAPCache</classname> object that
is used.</para></listitem>
<listitem><para>Invoke the <literal>setCache</literal> method of a different <classname>
LDAPConnection</classname> object to associate the retrieved <classname>LDAPCache
</classname> object with the connection.</para></listitem>
</itemizedlist>
<para>When you clone an <classname>LDAPConnection</classname> object, the
new object automatically shares the same <classname>LDAPCache</classname> object
with the original object.</para></sect2>
<sect2 id="flushing-cache"><title>Flushing the Cache</title>
<indexterm>
<primary>cache</primary>
<secondary>flushing</secondary>
</indexterm>
<para>To flush items from the cache, invoke the <literal>flushEntries</literal> method
of the <classname>LDAPCache</classname> object. You can flush either selected
items or all items from the cache.</para>
<itemizedlist>
<listitem><para>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 <literal>flushEntries</literal> method. If the base DN
of a cached search request falls within the scope you specified, the search
request is flushed from the cache.</para></listitem>
</itemizedlist>
<para>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 <literal>ou=People,dc=example,dc=com
</literal> subtree, the item is removed from the cache.</para>
<programlisting>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",
&nbsp;&nbsp;&nbsp;&nbsp;LDAPConnection.SCOPE_SUB);</programlisting>
<itemizedlist>
<listitem><para>To flush all items from the cache, pass <literal>null</literal> as
the first argument of the <literal>flushEntries</literal> method:</para>
</listitem>
</itemizedlist>
<programlisting>myCache.flushEntries(null, 0);</programlisting>
</sect2>
<sect2 id="cache-stats"><title>Getting Cache Statistics</title>
<indexterm>
<primary>cache</primary>
<secondary>getting statistics</secondary>
</indexterm>
<itemizedlist>
<para>You can invoke the following methods of the <classname>LDAPCache</classname> object
to get statistics on the cache.</para>
<listitem><para>To get the total amount of available space in bytes that are
left in the cache, invoke the <literal>getAvailableSize</literal> method.</para>
</listitem>
<listitem><para>To get the array of base DNs of the search requests to be
cached, invoke the <literal>getBaseDNs</literal> method.</para></listitem>
<listitem><para>To get the total number of items that have been flushed from
the cache, not including items flushed when invoking the <literal>flushEntries</literal> method,
invoke the <literal>getNumFlushes</literal> method.</para></listitem>
<listitem><para>To get the maximum size of the cache in bytes, invoke the <literal>
getSize</literal> method.</para></listitem>
<listitem><para>To get the maximum amount of time that an item can be cached
in seconds, get the <literal>getTimeToLive</literal> method.</para></listitem>
</itemizedlist>
<itemizedlist>
<para>You can also get a running count of the number of requests that access
the cache.</para>
<listitem><para>To get the total number of requests for retrieving items from
the cache, invoke the <literal>getTotalOperation</literal> method.</para>
</listitem>
<listitem><para>To get the total number of requests that retrieved an item
from the cache, invoke the <literal>getNumHits</literal> method.</para>
</listitem>
<listitem><para>To get the total number of requests that failed to find and
retrieve an item from the cache, invoke the <literal>getNumMisses</literal> method.
</para></listitem>
</itemizedlist>
<para>For example, the following section of code gets and prints cache statistics.
</para>
<programlisting>LDAPConnection ld;

if ((ld != null) &amp;&amp; ld.isConnected()) {
&nbsp;&nbsp;&nbsp;&nbsp;LDAPCache connCache = ld.getCache();
&nbsp;&nbsp;&nbsp;&nbsp;if (connCache != null) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Cache size:\t\t" +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connCache.getSize()/1000 + " kbytes");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Available:\t\t" +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connCache.getAvailableSize()/1000 + " kbytes");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "Maximum age:\t\t" + 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connCache.getTimeToLive()/1000 + " seconds");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Total hits:\t\t" +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connCache.getNumHits() + " hits" );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Total misses:\t\t" +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connCache.getNumMisses() + " misses" );
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Total requests:\t\t" +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connCache.getTotalOperations() + " requests");
&nbsp;&nbsp;&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"No cache associated with the connection.");
&nbsp;&nbsp;&nbsp;&nbsp;}
}</programlisting>
</sect2>
</sect1>
<sect1 id="cloning-connection"><title>Cloning a Connection With &DirectorySDKForJava;</title>
<indexterm>
<primary>connection</primary>
<secondary>cloning</secondary>
</indexterm>
<para>You can create several <classname>LDAPConnection</classname> objects
that share a single physical network connection to the LDAP server by invoking
the <literal>LDAPConnection.clone</literal> method.</para>
<itemizedlist>
<para>Clones have the following properties:</para>
<listitem><para>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.</para></listitem>
<listitem><para>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.</para>
</listitem>
<listitem><para>If the clone disconnects or reconnects, the clone is completely
dissociated from the source object and other clones.</para></listitem>
<listitem><para>A cloned <classname>LDAPConnection</classname> object has
a separate set of session preferences and constraints. In other words, the
clone is associated with its own <classname>LDAPSearchConstraints</classname> object.
Changes to an option or to a search constraint only affect requests issued
using that object.</para><para>For example, suppose an <classname>LDAPConnection</classname> object
allows a maximum of 100 results to be returned from a search. If you clone
an <classname>LDAPConnection</classname> 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.</para></listitem>
<listitem><para>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 <classname>LDAPConnection
</classname> object is no longer a clone of another <classname>LDAPConnection</classname> object.
</para></listitem>
</itemizedlist>
</sect1>
<sect1 id="handling-dns"><title>Manipulating Distinguished Names With &DirectorySDKForJava;</title>
<indexterm>
<primary>distinguished names</primary>
<secondary>manipulating</secondary>
</indexterm>
<para>A distinguished name (DN) uniquely identifies an entry in the directory
tree. You can get the DN for an entry as explained in <olink
type="auto-generated" targetptr="searching-results-dns">Getting Distinguished
Names</olink>. Alternatively, you can specify a DN to read an entry from the
directory as explained in <olink type="auto-generated" targetptr="searching-read">
Reading an Entry With Directory SDK for Java</olink>. &DirectorySDKForJava; includes
a utility class, <classname>LDAPDN</classname>, that provides
methods for manipulating DNs.</para>
<para>If you want to access individual components of a distinguished name
or a relative distinguished name, invoke the <literal>LDAPDN.explodeDN</literal> method
or the <literal>LDAPDN.explodeRDN</literal> method.</para>
<para>Both methods return an array of <classname>String</classname> objects
that represent the individual components of the distinguished name.</para>
<para>You can specify whether or not you want the names of the components
included in the array by using the <parameter>notypes</parameter> parameter.</para>
<itemizedlist>
<listitem><para>Set <parameter>notypes</parameter> to <literal>false</literal> if
you want to include component attribute types in the array.</para>
<programlisting>LDAPDN.explodeDN("uid=bjensen,ou=People,dc=example,dc=com", false);
</programlisting>
<para>The method returns the array <literal>{"uid=bjensen", "ou=People", "dc=example",
"dc=com"}</literal>.</para></listitem>
<listitem><para>Set <parameter>notypes</parameter> to <literal>true</literal> if
you do not want component attribute types returned in the array.</para>
<programlisting>LDAPDN.explodeDN("uid=bjensen,ou=People,dc=example,dc=com", true);
</programlisting>
<para>The method returns the array <literal>{"bjensen", "People", "example",
"com"}</literal>.</para></listitem>
</itemizedlist>
</sect1>
</chapter>
