From 3441a670cdb9b46d3d4afc9c638ef2b41d35c05f Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Mon, 27 May 2013 16:03:13 +0000
Subject: [PATCH] CR-1746 Fix for OPENDJ-857: Dev guide should explain how to use a GenericControl
---
opendj3/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm | 6 +
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java | 150 ++++++++++++++++++++++++++++++
opendj3/src/main/docbkx/dev-guide/chap-controls.xml | 93 ++++++++++++++++++
opendj3/pom.xml | 12 ++
4 files changed, 260 insertions(+), 1 deletions(-)
diff --git a/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java
new file mode 100644
index 0000000..54df59b
--- /dev/null
+++ b/opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java
@@ -0,0 +1,150 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2009-2010 Sun Microsystems, Inc.
+ * Portions copyright 2011-2013 ForgeRock AS
+ */
+
+package org.forgerock.opendj.examples;
+
+import java.io.IOException;
+
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.ErrorResultException;
+import org.forgerock.opendj.ldap.ErrorResultIOException;
+import org.forgerock.opendj.ldap.LDAPConnectionFactory;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.controls.GenericControl;
+import org.forgerock.opendj.ldap.requests.Requests;
+import org.forgerock.opendj.ldap.requests.SearchRequest;
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
+import org.forgerock.opendj.ldap.responses.SearchResultReference;
+import org.forgerock.opendj.ldif.ConnectionEntryReader;
+import org.forgerock.opendj.ldif.LDIFEntryWriter;
+
+/**
+ * An example client application which searches Microsoft Active Directory
+ * synchronously, using {@link GenericControl} to pass the <a
+ * href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms676877(v=vs.85).aspx"
+ * >Microsoft LDAP Notification control</a>.
+ *
+ * <p>This example is a near copy of {@link Search}, but works only with
+ * directory servers like Active Directory that support the control with OID
+ * 1.2.840.113556.1.4.528.
+ *
+ * <p>This example takes the following command line parameters:
+ *
+ * <pre>
+ * <host> <port> <username> <password> <baseDN>
+ * </pre>
+ *
+ * <p>The {@code baseDN} must be the root of a naming context in this example.
+ */
+@SuppressWarnings("resource")
+public final class GetADChangeNotifications {
+ /**
+ * Main method.
+ *
+ * @param args
+ * The command line arguments: host, port, username, password,
+ * base DN, where the base DN is the root of a naming context.
+ */
+ public static void main(final String[] args) {
+ if (args.length < 5) {
+ System.err.println("Usage: host port username password baseDN");
+ System.exit(1);
+ }
+
+ // Parse command line arguments.
+ final String hostName = args[0];
+ final int port = Integer.parseInt(args[1]);
+ final String userName = args[2];
+ final String password = args[3];
+ final String baseDN = args[4];
+
+ // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa772153(v=vs.85).aspx
+ /* --- JCite --- */
+ final SearchScope scope = SearchScope.WHOLE_SUBTREE;
+ final String filter = "(objectclass=*)";
+ final String[] attributes = {
+ "objectclass", "objectGUID", "isDeleted", "uSNChanged"
+ };
+
+ // Create an LDIF writer which will write the search results to stdout.
+ final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
+
+ // Connect and bind to the server.
+ final LDAPConnectionFactory factory =
+ new LDAPConnectionFactory(hostName, port);
+ Connection connection = null;
+
+ try {
+ connection = factory.getConnection();
+ connection.bind(userName, password.toCharArray());
+
+ // Read the entries and output them as LDIF.
+ final SearchRequest request =
+ Requests
+ .newSearchRequest(baseDN, scope, filter, attributes)
+ .addControl(
+ GenericControl
+ .newControl(
+ "1.2.840.113556.1.4.528",
+ true));
+ final ConnectionEntryReader reader = connection.search(request);
+ while (reader.hasNext()) {
+ if (!reader.isReference()) {
+ final SearchResultEntry entry = reader.readEntry();
+ writer.writeComment("Search result entry: "
+ + entry.getName().toString());
+ writer.writeEntry(entry);
+ writer.flush();
+ } else {
+ final SearchResultReference ref = reader.readReference();
+
+ // Got a continuation reference.
+ writer.writeComment("Search result reference: "
+ + ref.getURIs().toString());
+ }
+ }
+ } /* --- JCite --- */ catch (final ErrorResultException e) {
+ System.err.println(e.getMessage());
+ System.exit(e.getResult().getResultCode().intValue());
+ } catch (final ErrorResultIOException e) {
+ System.err.println(e.getMessage());
+ System.exit(e.getCause().getResult().getResultCode().intValue());
+ } catch (final IOException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
+ } finally {
+ if (connection != null) {
+ connection.close();
+ }
+ }
+ }
+
+ private GetADChangeNotifications() {
+ // Not used.
+ }
+}
diff --git a/opendj3/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm b/opendj3/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm
index a941826..eee539b 100644
--- a/opendj3/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm
+++ b/opendj3/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm
@@ -20,7 +20,7 @@
!
! CCPL HEADER END
!
- ! Copyright 2011-2012 ForgeRock AS
+ ! Copyright 2011-2013 ForgeRock AS
!
-->
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -102,6 +102,10 @@
<a href="xref/org/forgerock/opendj/examples/UpdateGroup.html">Update group</a>
- illustrates how to add or remove a member from a static group
</li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/GetADChangeNotifications.html">Use <code>GenericControl</code></a>
+ - illustrates how to use <code>GenericControl</code> to get change notifications from Active Directory
+ </li>
</ul>
</section>
<section name="Get the OpenDJ LDAP SDK Examples">
diff --git a/opendj3/pom.xml b/opendj3/pom.xml
index e471743..311f896 100644
--- a/opendj3/pom.xml
+++ b/opendj3/pom.xml
@@ -170,6 +170,18 @@
</configuration>
<executions>
<execution>
+ <id>run-jcite</id>
+ <phase>pre-site</phase>
+ <configuration>
+ <sourcePaths>
+ <sourcePath>${project.basedir}/opendj-ldap-sdk-examples/src/main/java</sourcePath>
+ </sourcePaths>
+ </configuration>
+ <goals>
+ <goal>jcite</goal>
+ </goals>
+ </execution>
+ <execution>
<id>copy-common</id>
<phase>pre-site</phase>
<goals>
diff --git a/opendj3/src/main/docbkx/dev-guide/chap-controls.xml b/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
index 660f8e8..f00ca2f 100644
--- a/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
+++ b/opendj3/src/main/docbkx/dev-guide/chap-controls.xml
@@ -1343,4 +1343,97 @@
# Entries are sorted.
# Position in list: 92/150</programlisting>
</section>
+
+ <section xml:id="use-generic-control">
+ <title>Using a Generic Control</title>
+ <indexterm>
+ <primary>Controls</primary>
+ <secondary>Generic</secondary>
+ </indexterm>
+
+ <para>OpenDJ LDAP SDK supports many controls, but you might still need to
+ work with additional controls. If so, then in some cases you can use the
+ <literal>GenericControl</literal> class when adding the control to your
+ request.</para>
+
+ <para>For example, the Microsoft <link xlink:show="new"
+ xlink:href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366983(v=vs.85).aspx"
+ >LDAP Server Notification Control</link> with OID
+ <literal>1.2.840.113556.1.4.528</literal> can be used to register a change
+ notification request for a search on Microsoft Active Directory. You can use
+ a <literal>GenericControl.newControl()</literal> static method to add the
+ request control to your search.</para>
+
+ <programlisting language="java"
+ >[jcp:org.forgerock.opendj.examples.GetADChangeNotifications:--- JCite ---]</programlisting>
+
+ <para>When you run the search against Active Directory and then create,
+ update, and delete a new user, in this example
+ <literal>CN=New User,CN=Users,DC=ad,DC=example,DC=com</literal>, Active
+ Directory notifies you of changes to directory data.</para>
+
+ <programlisting language="ldif"
+ ># Search result entry: CN=RID Set,CN=WIN2008R2641,OU=Domain Controllers,
+ DC=ad,DC=example,DC=com
+dn: CN=RID Set,CN=WIN2008R2641,OU=Domain Controllers,DC=ad,DC=example,DC=com
+objectClass: top
+objectClass: rIDSet
+objectGUID:: 178zQQic3EOoBOB1j2QVgQ==
+uSNChanged: 12446
+
+# Search result entry: CN=New User,CN=Users,DC=ad,DC=example,DC=com
+dn: CN=New User,CN=Users,DC=ad,DC=example,DC=com
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: user
+objectGUID:: 7XE/OoJdFEqAegwAi2eNlA==
+uSNChanged: 12753
+
+# Search result entry: CN=New User,CN=Users,DC=ad,DC=example,DC=com
+dn: CN=New User,CN=Users,DC=ad,DC=example,DC=com
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: user
+objectGUID:: 7XE/OoJdFEqAegwAi2eNlA==
+uSNChanged: 12755
+
+# Search result entry: CN=New User,CN=Users,DC=ad,DC=example,DC=com
+dn: CN=New User,CN=Users,DC=ad,DC=example,DC=com
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: user
+objectGUID:: 7XE/OoJdFEqAegwAi2eNlA==
+uSNChanged: 12757
+
+# Search result entry: CN=New User,CN=Users,DC=ad,DC=example,DC=com
+dn: CN=New User,CN=Users,DC=ad,DC=example,DC=com
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: user
+objectGUID:: 7XE/OoJdFEqAegwAi2eNlA==
+uSNChanged: 12758
+
+# Search result entry: CN=New User\0ADEL:3a3f71ed-5d82-4a14-807a-0c008b678d94,
+# CN=Deleted Objects,DC=ad,DC=example,DC=com
+dn: CN=New User\0ADEL:3a3f71ed-5d82-4a14-807a-0c008b678d94,CN=Deleted Objects,
+ DC=ad,DC=example,DC=com
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: user
+objectGUID:: 7XE/OoJdFEqAegwAi2eNlA==
+isDeleted: TRUE
+uSNChanged: 12759
+</programlisting>
+
+ <para>The <literal>GenericControl</literal> class is useful with controls that
+ do not require you to encode complex request values, or decode complex
+ response values. If the control you want to you requires complex encoding
+ or decoding, you might have to implement
+ <literal>org.forgerock.opendj.ldap.controls.Control</literal>.</para>
+ </section>
</chapter>
--
Gitblit v1.10.0