<?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-2013 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>
|
|
<indexterm>
|
<primary>Adds</primary>
|
</indexterm>
|
<indexterm>
|
<primary>Modifications</primary>
|
</indexterm>
|
<indexterm>
|
<primary>Renames</primary>
|
</indexterm>
|
<indexterm>
|
<primary>Deletes</primary>
|
</indexterm>
|
<indexterm>
|
<primary>Authorizations</primary>
|
</indexterm>
|
|
<itemizedlist>
|
<listitem>
|
<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>
|
<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>
|
|
<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.</para>
|
</listitem>
|
|
<listitem>
|
<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>
|
|
<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"
|
>[jcp:org.forgerock.opendj.examples.ShortLife:--- JCite add ---]</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. To build a <literal>ModifyRequest</literal>, you can
|
either specify individual changes, or derive the modifications from the
|
differences between the original entry and a modified copy, as in the
|
following excerpt. This is not always a particularly efficient method, but
|
it can be easy to use in some cases.</para>
|
|
<programlisting language="java"
|
>[jcp:org.forgerock.opendj.examples.ShortLife:--- JCite modify ---]</programlisting>
|
|
<para>Especially when working with large entries, a more efficient choice is
|
to construct a <literal>ModifyRequest</literal> without copying the entire
|
entry, but instead by specifying individual changes. See a demonstration
|
of this technique in <xref linkend="updating-static-groups" />.</para>
|
|
<indexterm>
|
<primary>Passwords</primary>
|
</indexterm>
|
|
<para>You can also construct a <literal>ModifyRequest</literal> for example
|
to change a user password in Active Directory, as demonstrated in the
|
following excerpt. When working with OpenDJ directory server, consider using
|
the LDAP Password Modify extended operation instead as shown in the section,
|
<link xlink:show="new" xlink:href="dev-guide#use-password-modify-extended-operation"
|
xlink:role="http://docbook.org/xlink/role/olink"><citetitle>Password Modify
|
Extended Operation</citetitle></link>.</para>
|
|
<programlisting language="java"
|
>[jcp:org.forgerock.opendj.examples.PasswordResetForAD:--- JCite main ---]</programlisting>
|
|
<para>To make the modification, the example connects to Active Directory over
|
LDAPS, and provides the password value in UTF-16LE format.</para>
|
|
<programlisting language="java"
|
>[jcp:org.forgerock.opendj.examples.PasswordResetForAD:--- JCite encodePassword ---]</programlisting>
|
|
<para>If the modifications are easier to construct in LDIF, you can write the
|
LDIF to the directory server as shown in the chapter, <link xlink:show="new"
|
xlink:href="dev-guide#chap-ldif" xlink:role="http://docbook.org/xlink/role/olink"
|
><citetitle>Working With LDIF</citetitle></link>.</para>
|
</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"
|
>[jcp:org.forgerock.opendj.examples.ShortLife:--- JCite rename ---]</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"
|
>[jcp:org.forgerock.opendj.examples.ShortLife:--- JCite delete ---]</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>
|
|
<section xml:id="updating-static-groups">
|
<title>Updating Static Groups</title>
|
<indexterm>
|
<primary>Modifications</primary>
|
<secondary>Static groups</secondary>
|
</indexterm>
|
|
<para>Static groups enumerate user entries. Static groups can grow large.
|
For an example, see the group entry at the end of <link xlink:show="new"
|
xlink:href="http://opendj.forgerock.org/big-group.ldif">big-group.ldif</link>:</para>
|
|
<programlisting language="ldif">dn: cn=Static,ou=Groups,dc=example,dc=com
|
objectClass: top
|
objectClass: groupofnames
|
cn: Static
|
member: uid=user.0,ou=People,dc=example,dc=com
|
member: uid=user.1,ou=People,dc=example,dc=com
|
member: uid=user.2,ou=People,dc=example,dc=com
|
...
|
member: uid=user.10000,ou=People,dc=example,dc=com</programlisting>
|
|
<para>To update a static group, you either add members or remove members.
|
For sample code, see <link
|
xlink:href="http://opendj.forgerock.org/opendj-ldap-sdk-examples/xref/org/forgerock/opendj/examples/UpdateGroup.html"
|
xlink:show="new">UpdateGroup.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>
|
|
<para>The <literal>UpdateGroup</literal> example checks that the directory
|
server supports the Permissive Modify control. With directory servers such
|
as OpenDJ that support the LDAP Permissive Modify control, you can use the
|
control to avoid having to determine whether a given member is already in the
|
group before performing the operation. Instead you can simply request an
|
add or a delete modification for the member.</para>
|
|
<example xml:id="update-group-with-permissive-modify"><?dbfo keep-together="auto"?>
|
<title>Updating a Group With Permissive Modify</title>
|
<programlisting language="java"
|
>[jcp:org.forgerock.opendj.examples.UpdateGroup:--- JCite permissive ---]</programlisting>
|
</example>
|
|
<para>If the directory server does not support the Permissive Modify control,
|
then the example checks whether the member is present in the group by using
|
an LDAP compare operation. If a member to be added does not yet belong to the
|
group, the example requests an add modification. If a member to be deleted
|
does belong to the group, the example requests a delete modification.</para>
|
|
<example xml:id="update-group-with-compare-and-modify"><?dbfo keep-together="auto"?>
|
<title>Updating a Group With Compare & Modify</title>
|
<programlisting language="java"
|
>[jcp:org.forgerock.opendj.examples.UpdateGroup:--- JCite without permissive ---]</programlisting>
|
|
<para>You can change multiple member values with a single modification. The
|
final argument of this form of the
|
<literal>ModifyRequest.addModification()</literal> method takes a series
|
of one or more values. So if you have multiple group members to add or
|
delete, you can loop over your list to perform compare individual compare
|
requests, then construct a single modify request to add or delete the
|
group members. In other words, if you have three members to add, you can
|
list the three member DNs as arguments of
|
<literal>addModification</literal>.</para>
|
|
<programlisting language="java"
|
>String member1 = "uid=user1,ou=people,dc=example,dc=com";
|
String member2 = "uid=user1,ou=people,dc=example,dc=com";
|
String member3 = "uid=user1,ou=people,dc=example,dc=com";
|
final ModifyRequest addMember =
|
Requests.newModifyRequest(groupDN)
|
.addModification(modType, "member", member1, member2, member3);
|
connection.modify(addMember);</programlisting>
|
</example>
|
|
<para>To try the example, download and import
|
<filename>big-group.ldif</filename> into your directory server, and then
|
run the sample. For example, if OpenDJ is set up to with directory manager
|
as <literal>cn=Directory Manager</literal>, password
|
<literal>password</literal> listening on <literal>localhost</literal> port
|
<literal>1389</literal>, and you run the example with arguments
|
<literal>localhost 1389 cn=Static,ou=Groups,dc=example,dc=com
|
uid=user.5150,ou=People,dc=example,dc=com del</literal>, the resulting output
|
is <literal>The entry with DN uid=user.5150,ou=People,dc=example,dc=com has
|
been deleted from the group with DN
|
cn=Static,ou=Groups,dc=example,dc=com.</literal>.</para>
|
</section>
|
</chapter>
|