<!--

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="writing-client"><title>Writing an LDAP Client With &DirectorySDKForJava;</title>
<highlights>
<para>This chapter describes the general process of writing an LDAP client.
The chapter covers the procedures for connecting to an LDAP server. It covers
authentication, requesting operations, and disconnecting from the server. </para>
<itemizedlist>
<para>The chapter covers the following topics:</para>
<listitem><para><olink targetptr="designing-client">Designing an LDAP Java
Client</olink></para></listitem>
<listitem><para><olink targetptr="prepare-client">Creating a Connection and
Setting Preferences With Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="connect-client">Connecting to an LDAP Server
With Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="bind-client">Binding and Authenticating
to an LDAP Server With Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="ldapops-client">Performing LDAP Operations
With Directory SDK for Java</olink></para></listitem>
<listitem><para><olink targetptr="close-client">Closing the Connection to
an LDAP Server With Directory SDK for Java</olink></para></listitem>
</itemizedlist>
</highlights>
<sect1 id="designing-client"><title>Designing an LDAP Java Client</title>
<para>The following steps outline the typical process of communicating with
an LDAP server. Follow these steps when writing your LDAP client.</para>
<orderedlist>
<listitem><para>Create a new <classname>LDAPConnection</classname> object,
and set any preferences that you want applied to all LDAP operations.</para>
</listitem>
<listitem><para>Connect to an LDAP server.</para></listitem>
<listitem><para>If necessary, bind to the LDAP server, specifying the version
of LDAP supported by your client.</para></listitem>
<listitem><para>Perform the LDAP operations, such as searching the directory
or modifying entries in the directory.</para></listitem>
<listitem><para>When finished performing operations, disconnect from the LDAP
server.</para></listitem>
</orderedlist>
<para>The following example LDAP client follows these steps to search a directory.
The client connects to the LDAP server running on the local host at port <literal>
389</literal>. The client then searches the directory for entries with the
surname <literal>Jensen</literal>. Finally, the client displays the DNs of
matching entries.</para>
<programlisting>import netscape.ldap.*;
import java.util.*;
 
public class Search {
    public static void main(String[] args) {
        try {
            UserArgs userArgs = new UserArgs("Search", args, false);
            LDAPConnection ld = new LDAPConnection();
            ld.connect(userArgs.getHost(), userArgs.getPort());
 
            /* search for all entries with surname of Jensen */
            String MY_FILTER = "sn=Jensen";
            String MY_SEARCHBASE = "dc=example,dc=com";
 
            LDAPSearchConstraints cons = ld.getSearchConstraints();
            /* Setting the batchSize to one will cause the result
               enumeration below to block on one result at a time,
               enabling an update of a list or other things as
               results come in. */
            /* This could be set to 0 in order to get all
               results and to block until then. */
            cons.setBatchSize(1);
            LDAPSearchResults res = ld.search(MY_SEARCHBASE,
                LDAPConnection.SCOPE_SUB, MY_FILTER, null, false, cons);
 
            /* Loop on results until finished */
            while (res.hasMoreElements()) {
                LDAPEntry findEntry = null;
                try {
                    findEntry = res.next();
                } catch (LDAPReferralException e) {
                    System.out.println("Search reference: ");
                    LDAPUrl refUrls[] = e.getURLs();
                    for (int i=0; i&lt;refUrls.length; i++) {
                        System.out.println("\t" + refUrls[i].getUrl());
                    }
                    continue;
                } catch (LDAPException e) {
                    System.out.println("Error: " + e.toString());
                    continue;
                }
                System.out.println(findEntry.getDN());
 
                /* Get the attributes of the entry */
                LDAPAttributeSet findAttrs = findEntry.getAttributeSet();
                Enumeration enumAttrs = findAttrs.getAttributes();
                System.out.println("\tAttributes: ");
 
                /* Loop on attributes */
                while (enumAttrs.hasMoreElements()) {
                    LDAPAttribute anAttr =
                        (LDAPAttribute)enumAttrs.nextElement();
                    String attrName = anAttr.getName();
                    System.out.println("\t\t" + attrName);
 
                    /* Loop on values for this attribute */
                    Enumeration enumVals = anAttr.getStringValues();
                    if (enumVals != null) {
                        while (enumVals.hasMoreElements()) {
                            String aVal = (String)enumVals.nextElement();
                            System.out.println("\t\t\t" + aVal);
                        }
                    }
                }
            }
            ld.disconnect();
        } catch(LDAPException e) {
            System.out.println("Error: " + e.toString());
        }
    }
}</programlisting>
</sect1>
<sect1 id="prepare-client"><title>Creating a Connection and Setting Preferences
With &DirectorySDKForJava;</title>
<indexterm>
<primary>connection</primary>
<secondary>creating</secondary>
</indexterm><indexterm>
<primary>connection</primary>
<secondary>setting preferences</secondary>
</indexterm><indexterm>
<primary>LDAP session</primary>
<secondary>setting preferences</secondary>
</indexterm>
<para>The first step in writing an LDAP client is creating an <classname>LDAPConnection
</classname> object. This object represents the connection to an LDAP server.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();</programlisting>
<note><para>If you plan to connect to the LDAP server over the <firstterm>Secure
Sockets Layer</firstterm> (SSL) protocol, you need to specify a class that
implements SSL sockets. Refer to <olink type="auto-generated" targetptr="ssl">Chapter&nbsp;9,
SSL Connections With Directory SDK for Java</olink> for details.</para></note>
<para>The <classname>LDAPConnection</classname> object also contains preferences
for the LDAP session, such as whether referrals are or are not followed automatically.
To get or set the value of a preference, invoke the <literal>getOption</literal> method
or the <literal>setOption</literal> method as described in the API specification.
</para></sect1>
<sect1 id="connect-client"><title>Connecting to an LDAP Server With &DirectorySDKForJava;</title>
<indexterm>
<primary>LDAP servers</primary>
<secondary>connecting to</secondary>
</indexterm><indexterm>
<primary>LDAP clients</primary>
<secondary>connection to a server</secondary>
</indexterm><indexterm>
<primary>connection</primary>
<secondary>establishing</secondary>
</indexterm><indexterm>
<primary>session</primary>
<secondary>starting</secondary>
</indexterm>
<para>To connect to an LDAP server, use the <literal>connect</literal> method
of the <classname>LDAPConnection</classname> object.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT);</programlisting>
<para><literal>DEFAULT_PORT</literal> specifies the default LDAP port, port
389. You can also specify a list of LDAP servers to attempt to connect to.
If the first LDAP server in the list does not respond, the client attempts
to connect to the next server in the list.</para>
<para><indexterm>
<primary>connection</primary>
<secondary>specifying multiple LDAP servers</secondary>
</indexterm><indexterm>
<primary>failover support</primary>
</indexterm>Use a space-delimited list of the host names as the first argument
of the connect method. If the server is not using the default LDAP port, specify
the port number in <replaceable>hostname</replaceable><literal>:</literal><replaceable>
portnumber</replaceable> format.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
ld.connect("ldap1.example.com ldap2.example.com:3890
    ldap3.example.com:3900", LDAPv3.DEFAULT_PORT);</programlisting>
</sect1>
<sect1 id="bind-client"><title>Binding and Authenticating to an LDAP Server
With &DirectorySDKForJava;</title>
<indexterm>
<primary>LDAP clients</primary>
<secondary>authenticating with LDAP servers</secondary>
</indexterm><indexterm>
<primary>LDAP servers</primary>
<secondary>authenticating to</secondary>
</indexterm><indexterm>
<primary>bind operation</primary>
</indexterm>
<para>When connecting to the LDAP server, your client might need to send a
bind operation request to the server. This operation is also called binding
to the server.</para>
<itemizedlist>
<para>An LDAP bind request contains the following information:</para>
<listitem><para>LDAP version of the client</para></listitem>
<listitem><para>DN that is used to authenticate</para></listitem>
<listitem><para>Authentication method that is requested</para></listitem>
<listitem><para>Credentials that are used to authenticate</para></listitem>
</itemizedlist>
<itemizedlist>
<para>The client should send a bind request to the server in the following
situations:</para>
<listitem><para>You want to authenticate to the server.</para><para>For example,
if you want to add or modify entries in the directory, you need to authenticate
as a user with access privileges.</para></listitem>
<listitem><para>You are connecting to an LDAP v2 server.</para><para>LDAP
v2 servers typically require clients to bind before any operations can be
performed.</para></listitem>
</itemizedlist>
<para>An LDAP client can also bind as an anonymous client. For example, the
LDAP server might not require authentication if your client is only searching
the directory.</para>
<para>This section explains how to set up your client to bind to an LDAP server.</para>
<sect2 id="simple-auth-client"><title>Using Simple Authentication</title>
<para>Simple authentication can be used when security is not a concern. If
you plan to use simple authentication, use the <literal>authenticate</literal> method
of the <classname>LDAPConnection</classname> object.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT);
ld.authenticate("uid=bjensen,ou=People,cd=example,dc=com", "hifalutin");</programlisting>
<para>The server to which you bind might send back a special control to indicate
that your password has expired. The server might also send back a control
to indicate that your password is to expire in the near future. Refer to <olink
type="auto-generated" targetptr="controls">Chapter&nbsp;10, LDAP Controls
With Directory SDK for Java</olink> for details.</para></sect2>
<sect2 id="anonymous-bind-client"><title>Binding Anonymously</title>
<indexterm>
<primary>anonymous bind</primary>
</indexterm><indexterm>
<primary>binding</primary>
<secondary>anonymously</secondary>
</indexterm>
<para>In some cases, you might not need to authenticate to the LDAP server.
For example, the directory that you search might not require special access
permissions for searches. Therefore, you might not need to authenticate before
performing the search operation. In LDAP v3, the server no longer expects
the client to send a bind request in this type of situation. In LDAP v2, the
server expects the client to send a bind request, even if the operation does
not require the client to authenticate.</para>
<para>In this kind of situation, use the <literal>authenticate</literal> method.
Specify <literal>null</literal> for the DN and password.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); 
ld.authenticate(null, null);</programlisting>
</sect2>
<sect2 id="ldap-version-client"><title>Specifying the LDAP Version</title>
<indexterm>
<primary>LDAP clients</primary>
<secondary>specifying protocol version</secondary>
</indexterm>
<para>As part of the bind request sent to the server, the client includes
the version of the LDAP protocol that the client supports. By default, clients
built with the&DirectorySDKForJava; identify themselves as LDAP v2 clients.
Therefore, explicitly identify your client as an LDAP v3 client.</para>
<itemizedlist>
<para>To identify your client as an LDAP v3 client, do one of the following:</para>
<listitem><para>Specify version 3 when invoking the <literal>authenticate</literal> method.
</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); 
ld.authenticate(3, null, null);</programlisting>
</listitem>
<listitem><para>Invoke the <literal>setOption</literal> method of the <classname>
LDAPConnection</classname> object to set the <literal>LDAPv3.PROTOCOL_VERSION</literal> preference
to <literal>3</literal>, then invoke the <literal>authenticate</literal> method.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); 
ld.setOption(LDAPv3.PROTOCOL_VERSION, 3);
ld.authenticate(null, null);</programlisting>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="connect-method-client"><title>Authenticating With the <literal>connect
</literal> Method</title>
<para>The <literal>connect</literal> method of the <classname>LDAPConnection</classname> object
has a signature that allows you to authenticate and specify the LDAP version
supported by your client.</para>
<para>You can specify all of this information using one method, rather than
invoking several methods.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
ld.connect(3, "ldap.example.com", LDAPv3.DEFAULT_PORT,
&nbsp;&nbsp;&nbsp;&nbsp;"uid=bjensen,ou=People,cd=example,dc=com", "hifalutin");</programlisting>
</sect2>
</sect1>
<sect1 id="ldapops-client"><title>Performing LDAP Operations With &DirectorySDKForJava;</title>
<indexterm>
<primary>LDAP operations</primary>
</indexterm>
<para>First, you initialize a session with an LDAP server. Next, you complete
the authentication process. After authentication, you can perform LDAP operations.
For example, you can search the directory, add new entries, update entries
that exist, and remove entries. You can perform the operations provided that
the server access control allows you to request the operations.</para>
<itemizedlist>
<para>To perform LDAP operations, invoke these methods of the <classname>LDAPConnection
</classname> object:</para>
<listitem><para>To search for entries in the directory, use the <literal>search</literal> method
as explained in <olink targetptr="searching">Chapter&nbsp;4, Searching the
Directory With Directory SDK for Java</olink>.</para></listitem>
<listitem><para>To retrieve a single entry in the directory, use the <literal>read
</literal> method as explained in <olink targetptr="searching">Chapter&nbsp;4,
Searching the Directory With Directory SDK for Java</olink>.</para></listitem>
<listitem><para>To determine whether an attribute contains a certain value,
use the <literal>compare</literal> method as explained in <olink
targetptr="comparing">Chapter&nbsp;6, Comparing Attribute Values With Directory
SDK for Java</olink>.</para></listitem>
<listitem><para>To add entries to the directory, use the <literal>add</literal> method
as explained in <olink targetptr="adding">Chapter&nbsp;5, Adding, Updating,
and Deleting Entries With Directory SDK for Java</olink>.</para></listitem>
<listitem><para>To modify entries in the directory, use the <literal>modify</literal> method
as explained in <olink targetptr="adding">Chapter&nbsp;5, Adding, Updating,
and Deleting Entries With Directory SDK for Java</olink>.</para></listitem>
<listitem><para>To delete entries from the directory, use the <literal>delete</literal> method
as explained in <olink targetptr="adding">Chapter&nbsp;5, Adding, Updating,
and Deleting Entries With Directory SDK for Java</olink>.</para></listitem>
<listitem><para>To rename entries in the directory, use the <literal>rename</literal> method
as explained in <olink targetptr="adding">Chapter&nbsp;5, Adding, Updating,
and Deleting Entries With Directory SDK for Java</olink>.</para></listitem>
</itemizedlist>
</sect1>
<sect1 id="close-client"><title>Closing the Connection to an LDAP Server With &DirectorySDKForJava;</title>
<indexterm>
<primary>ending an LDAP session</primary>
</indexterm><indexterm>
<primary>LDAP session</primary>
<secondary>ending</secondary>
</indexterm><indexterm>
<primary>closing an LDAP connection</primary>
</indexterm><indexterm>
<primary>LDAP servers</primary>
<secondary>closing connection from client</secondary>
</indexterm><indexterm>
<primary>LDAP clients</primary>
<secondary>closing connection to server</secondary>
</indexterm><indexterm>
<primary>connection</primary>
<secondary>closing</secondary>
</indexterm>
<para>When you have finished performing all necessary LDAP operations, close
the connection to the LDAP server. Use the <literal>disconnect</literal> method
of the <classname>LDAPConnection</classname> object to disconnect from the
LDAP server.</para>
<programlisting>LDAPConnection ld = new LDAPConnection();
ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); 
/*
&nbsp;* Authenticate and perform LDAP operations.
&nbsp;*/
ld.disconnect();</programlisting>
</sect1>
</chapter>
