<?xml version="1.0" encoding="UTF-8"?>
|
<!--
|
! CCPL HEADER START
|
!
|
! This work is licensed under the Creative Commons
|
! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
|
! To view a copy of this license, visit
|
! http://creativecommons.org/licenses/by-nc-nd/3.0/
|
! or send a letter to Creative Commons, 444 Castro Street,
|
! Suite 900, Mountain View, California, 94041, USA.
|
!
|
! You can also obtain a copy of the license at
|
! trunk/opendj3/legal-notices/CC-BY-NC-ND.txt.
|
! See the License for the specific language governing permissions
|
! and limitations under the License.
|
!
|
! If applicable, add the following below this CCPL HEADER, with the fields
|
! enclosed by brackets "[]" replaced with your own identifying information:
|
! Portions Copyright [yyyy] [name of copyright owner]
|
!
|
! CCPL HEADER END
|
!
|
! Copyright 2011-2012 ForgeRock AS
|
!
|
-->
|
<chapter xml:id='chap-writing'
|
xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
|
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
|
xsi:schemaLocation='http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd'
|
xmlns:xlink='http://www.w3.org/1999/xlink'
|
xmlns:xinclude='http://www.w3.org/2001/XInclude'>
|
<title>Updating Directory Data</title>
|
|
<para>Modern directory servers like OpenDJ can handle a high load of write
|
requests, replicating changes quickly both on the LAN and over the WAN.</para>
|
|
<para>For a complete example corresponding to the excerpts shown below, see
|
<link
|
xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/xref/org/forgerock/opendj/examples/ShortLife.html"
|
xlink:show="new">ShortLife.java</link>, one of the <link
|
xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/"
|
xlink:show="new">OpenDJ LDAP SDK examples</link>.</para>
|
|
<section xml:id="about-writes">
|
<title>About Add, Modify, Rename, & Delete</title>
|
|
<para>The four basic CRUD operations — create, read, update, and delete
|
— correspond to the LDAP operations add, search, modify (or modify DN),
|
and delete.<footnote><para>The LDAP bind operation can potentially result in
|
an update. Some directory servers can be configured to write time stamps in
|
order to track successful or failed binds for password policy reasons.</para>
|
</footnote></para>
|
|
<itemizedlist>
|
<listitem>
|
<indexterm>
|
<primary>Adds</primary>
|
</indexterm>
|
|
<para>An add request is used to create a new entry in an LDAP directory.
|
The entry must have a unique distinguished name that belongs under a base
|
DN served by the directory. The entry must have a list of attributes that
|
are valid according to the directory schema.</para>
|
</listitem>
|
|
<listitem>
|
<para>Search requests are described in the chapter on <link
|
xlink:href="dev-guide#chap-reading"
|
xlink:role="http://docbook.org/xlink/role/olink"><citetitle>Searching &
|
Comparing Directory Data</citetitle></link>.</para>
|
</listitem>
|
|
<listitem>
|
<indexterm>
|
<primary>Modifications</primary>
|
</indexterm>
|
<para>A modify request is used to add, delete, or replace attribute values
|
on an entry in an LDAP directory. The resulting entry must be valid
|
according to the directory schema.</para>
|
|
<indexterm>
|
<primary>Renames</primary>
|
</indexterm>
|
<para>A modify DN request is used to rename or move a directory entry.
|
In both cases the distinguished name changes. Renaming involves changing
|
the relative distinguished name, for example from
|
<literal>cn=Bob,ou=People,dc=example,dc=com</literal> to
|
<literal>cn=Ted,ou=People,dc=example,dc=com</literal>. Moving
|
involves changing the container where the entry is found, for example from
|
<literal>cn=Barbara Jensen,ou=People,dc=Old Company,dc=com</literal> to
|
<literal>cn=Barbara Jensen,ou=People,dc=New Company,dc=com</literal>.</para>
|
|
<para>Although they are both considered modify DN operations, renaming a
|
leaf entry is generally much simpler than moving a container entry that has
|
child entries. Not all modify DN operations mobilize equivalent resources
|
on the directory server.</para>
|
</listitem>
|
|
<listitem>
|
<indexterm>
|
<primary>Deletes</primary>
|
</indexterm>
|
|
<para>A delete request is used to remove an entry from an LDAP
|
directory.</para>
|
|
<para>Directory servers can restrict deletes to leaf entries, so that you
|
cannot remove an entry that has other child entries. For example, you have
|
to delete <literal>uid=bjensen,ou=People,dc=example,dc=com</literal> and
|
other peer entries before you delete
|
<literal>ou=People,dc=example,dc=com</literal> unless you send a subtree
|
delete request control.</para>
|
</listitem>
|
</itemizedlist>
|
|
<indexterm>
|
<primary>Authorizations</primary>
|
</indexterm>
|
<para>As a rule, your client application must be authorized to create,
|
update, and delete directory data. Therefore to prepare to change directory
|
data, you first get a connection, and then bind on that connection as a
|
user who is authorized to make the changes you plan to request.</para>
|
</section>
|
|
<section xml:id="adding-entries">
|
<title>Adding Directory Entries</title>
|
<indexterm>
|
<primary>Adds</primary>
|
</indexterm>
|
|
<para>The <literal>Connection.add()</literal> methods let you provide the
|
entry to add as an <literal>AddRequest</literal>, an <literal>Entry</literal>,
|
or as LDIF. If the changes to make are already expressed in LDIF, then
|
you can also use <literal>ChangeRecordReader</literal>s,
|
<literal>ChangeRecord</literal>s, and <literal>ChangeRecordWriter</literal>s
|
to handle the changes.</para>
|
|
<para>The following excerpt demonstrates how to add a simple user entry under
|
<literal>ou=People,dc=example,dc=com</literal>.</para>
|
|
<programlisting language="java">// An entry to add to the directory
|
DN entryDN = DN.valueOf("cn=Bob,ou=People,dc=example,dc=com");
|
Entry entry = new LinkedHashMapEntry(entryDN.toString())
|
.addAttribute("cn", "Bob")
|
.addAttribute("objectclass", "top")
|
.addAttribute("objectclass", "person")
|
.addAttribute("objectclass", "organizationalPerson")
|
.addAttribute("objectclass", "inetOrgPerson")
|
.addAttribute("mail", "subgenius@example.com")
|
.addAttribute("sn", "Dobbs");
|
|
final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
|
Connection connection = null;
|
try {
|
connection = factory.getConnection();
|
// Bind as a user who has the right to add entries.
|
connection.bind(adminDN, adminPwd);
|
|
connection.add(entry);
|
|
} catch (final ErrorResultException e) {
|
System.err.println(e.getMessage());
|
System.exit(e.getResult().getResultCode().intValue());
|
return;
|
} finally {
|
if (connection != null) {
|
connection.close();
|
}
|
}</programlisting>
|
</section>
|
|
<section xml:id="modifying-attr-values">
|
<title>Modifying Directory Entry Attribute Values</title>
|
<indexterm>
|
<primary>Modifications</primary>
|
</indexterm>
|
|
<para>The <literal>Connection.modify()</literal> methods let you add, replace,
|
and delete attributes values on an entry. Either the modifications are
|
expressed in LDIF, or you build a <literal>ModifyRequest</literal> to
|
express the changes.</para>
|
|
<para>The following excerpt demonstrates how to replace one attribute value
|
and to add another.</para>
|
|
<programlisting language="java"
|
>final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
|
Connection connection = null;
|
try {
|
connection = factory.getConnection();
|
// Bind as a user who has the right to modify entries.
|
connection.bind(adminDN, adminPwd);
|
|
// Here, entry is a user entry with DN cn=Bob,ou=People,dc=example,dc=com.
|
Entry old = TreeMapEntry.deepCopyOfEntry(entry);
|
entry = entry.replaceAttribute("mail", "spammer@example.com")
|
.addAttribute("description", "I see the fnords.");
|
ModifyRequest request = Entries.diffEntries(old, entry);
|
|
connection.modify(request);
|
|
} catch (final ErrorResultException e) {
|
System.err.println(e.getMessage());
|
System.exit(e.getResult().getResultCode().intValue());
|
return;
|
} finally {
|
if (connection != null) {
|
connection.close();
|
}
|
}</programlisting>
|
</section>
|
|
<section xml:id="renaming-entries">
|
<title>Renaming Directory Entries</title>
|
<indexterm>
|
<primary>Renames</primary>
|
</indexterm>
|
|
<para>The <literal>Connection.modifyDN()</literal> methods serve to rename
|
entries and to move them around.</para>
|
|
<para>The following excerpt demonstrates how to rename an entry.</para>
|
|
<programlisting language="java"
|
>final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
|
Connection connection = null;
|
try {
|
connection = factory.getConnection();
|
// Bind as a user who has the right to rename entries.
|
connection.bind(adminDN, adminPwd);
|
|
// Here, entryDN contains cn=Bob,ou=People,dc=example,dc=com.
|
// The second argument is the new relative distinguished name.
|
connection.modifyDN(entryDN.toString(), "cn=Ted");
|
|
} catch (final ErrorResultException e) {
|
System.err.println(e.getMessage());
|
System.exit(e.getResult().getResultCode().intValue());
|
return;
|
} finally {
|
if (connection != null) {
|
connection.close();
|
}
|
}</programlisting>
|
|
<para>If you must move rather than rename entries, have a look at the methods
|
for <literal>ModifyDNRequest</literal>. You can get a new request by using
|
<literal>Requests</literal> static methods.</para>
|
</section>
|
|
<section xml:id="deleting-entries">
|
<title>Deleting Directory Entries</title>
|
<indexterm>
|
<primary>Deletes</primary>
|
</indexterm>
|
|
<para>The following excerpt demonstrates how to delete an entry with DN
|
<literal>cn=Ted,ou=People,dc=example,dc=com</literal>.</para>
|
|
<programlisting language="java"
|
>final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
|
Connection connection = null;
|
try {
|
connection = factory.getConnection();
|
// Bind as a user who has the right to delete entries.
|
connection.bind(adminDN, adminPwd);
|
|
connection.delete("cn=Ted,ou=People,dc=example,dc=com");
|
|
} catch (final ErrorResultException e) {
|
System.err.println(e.getMessage());
|
System.exit(e.getResult().getResultCode().intValue());
|
return;
|
} finally {
|
if (connection != null) {
|
connection.close();
|
}
|
}</programlisting>
|
|
<para>If you must delete an entire branch of entries instead of a single
|
leaf entry, build a <literal>DeleteRequest</literal> that includes the
|
<literal>SubtreeDeleteRequestControl</literal>, as described in the
|
section, <link xlink:href="dev-guide#use-subtree-delete-control"
|
xlink:role="http://docbook.org/xlink/role/olink"><citetitle>Subtree Delete
|
Request Control</citetitle></link>.</para>
|
</section>
|
</chapter>
|