mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Mark Craig
27.03.2013 3441a670cdb9b46d3d4afc9c638ef2b41d35c05f
CR-1746 Fix for OPENDJ-857: Dev guide should explain how to use a GenericControl
1 files added
3 files modified
261 ■■■■■ changed files
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java 150 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm 6 ●●●● patch | view | raw | blame | history
opendj3/pom.xml 12 ●●●●● patch | view | raw | blame | history
opendj3/src/main/docbkx/dev-guide/chap-controls.xml 93 ●●●●● patch | view | raw | blame | history
opendj3/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java
New file
@@ -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>
 *  &lt;host> &lt;port> &lt;username> &lt;password> &lt;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.
    }
}
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">
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>
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>