From 41a1efcbe052305b1d542e74bd86756a8a953c37 Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Wed, 12 Aug 2015 12:04:14 +0000
Subject: [PATCH] CR-7880 OPENDJ-1608 Provide asynchronous examples
---
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/PasswordResetForAD.java | 6
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ReadSchema.java | 4
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SASLAuth.java | 4
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLifeAsync.java | 227 +++++++++
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchema.java | 2
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/RewriterProxy.java | 4
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseGenericControl.java | 10
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ProxyBackend.java | 13
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Modify.java | 4
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBindAsync.java | 183 +++++++
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Proxy.java | 6
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBind.java | 4
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Search.java | 6
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLife.java | 4
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchemaAsync.java | 183 +++++++
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchAsync.java | 7
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ModifyAsync.java | 177 +++++++
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UpdateGroupAsync.java | 233 +++++++++
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java | 4
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SimpleAuthAsync.java | 268 +++++++++++
opendj-sdk/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm | 75 ++
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java | 4
22 files changed, 1,372 insertions(+), 56 deletions(-)
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java
index 215e805..2ace9cc 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -55,7 +55,7 @@
* <p>This example takes the following command line parameters:
*
* <pre>
- * <host> <port> <username> <password> <baseDN>
+ * {@code <host> <port> <username> <password> <baseDN>}
* </pre>
*
* <p>The {@code baseDN} must be the root of a naming context in this example.
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Modify.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Modify.java
index 35adca5..0a6af91 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Modify.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Modify.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -47,7 +47,7 @@
* parameters (it will read from stdin if no LDIF file is provided):
*
* <pre>
- * <host> <port> <username> <password> [<ldifFile>]
+ * {@code <host> <port> <username> <password> [<ldifFile>]}
* </pre>
*/
public final class Modify {
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ModifyAsync.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ModifyAsync.java
new file mode 100644
index 0000000..f834ce1
--- /dev/null
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ModifyAsync.java
@@ -0,0 +1,177 @@
+/*
+ * 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 2015 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.examples;
+
+import static org.forgerock.util.Utils.closeSilently;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.LDAPConnectionFactory;
+import org.forgerock.opendj.ldap.LdapException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.requests.Requests;
+import org.forgerock.opendj.ldap.responses.BindResult;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.util.AsyncFunction;
+import org.forgerock.util.promise.ExceptionHandler;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.ResultHandler;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * An example client application which applies update operations to a directory server
+ * using the asynchronous APIs.
+ * The update operations are read from an LDIF file, or stdin if no filename is provided.
+ * This example takes the following command line parameters,
+ * reading from stdin if no LDIF file is provided:
+ *
+ * <pre>
+ * {@code <host> <port> <username> <password> [<ldifFile>]}
+ * </pre>
+ */
+public final class ModifyAsync {
+ /** Connection to the LDAP server. */
+ private static Connection connection;
+ /** Result for the modify operation. */
+ private static int resultCode;
+ /** Count down latch to wait for modify operation to complete. */
+ private static final CountDownLatch COMPLETION_LATCH = new CountDownLatch(1);
+
+ /**
+ * Main method.
+ *
+ * @param args
+ * The command line arguments: host, port, username, password,
+ * LDIF file name containing the update operations.
+ * Stdin is used if no LDIF file name is provided.
+ */
+ public static void main(final String[] args) {
+ if (args.length < 4 || args.length > 5) {
+ System.err.println("Usage: host port username password [ldifFileName]");
+ 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 char[] password = args[3].toCharArray();
+
+ // Create the LDIF reader using either the named file, if provided, or stdin.
+ InputStream ldif;
+ if (args.length > 4) {
+ try {
+ ldif = new FileInputStream(args[4]);
+ } catch (final FileNotFoundException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue());
+ return;
+ }
+ } else {
+ ldif = System.in;
+ }
+ final String[] ldifLines = getInputLines(ldif);
+
+ // Connect to the server, bind, and request the modifications.
+ new LDAPConnectionFactory(hostName, port)
+ .getConnectionAsync()
+ .thenAsync(new AsyncFunction<Connection, BindResult, LdapException>() {
+ @Override
+ public Promise<BindResult, LdapException> apply(Connection connection)
+ throws LdapException {
+ ModifyAsync.connection = connection;
+ return connection.bindAsync(
+ Requests.newSimpleBindRequest(userName, password));
+ }
+ })
+ .thenAsync(new AsyncFunction<BindResult, Result, LdapException>() {
+ @Override
+ public Promise<Result, LdapException> apply(BindResult bindResult)
+ throws LdapException {
+ return connection.modifyAsync(
+ Requests.newModifyRequest(ldifLines));
+ }
+ })
+ .thenOnResult(new ResultHandler<Result>() {
+ @Override
+ public void handleResult(Result result) {
+ resultCode = result.getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ })
+ .thenOnException(new ExceptionHandler<LdapException>() {
+ @Override
+ public void handleException(LdapException e) {
+ System.err.println(e.getMessage());
+ resultCode = e.getResult().getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ });
+
+ try {
+ COMPLETION_LATCH.await();
+ } catch (InterruptedException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
+ return;
+ }
+
+ closeSilently(connection);
+ System.exit(resultCode);
+ }
+
+ /**
+ * Returns the lines from the input stream.
+ * @param in The input stream.
+ * @return The lines from the input stream.
+ */
+ private static String[] getInputLines(final InputStream in) {
+ String line;
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ final List<String> lines = new ArrayList<>();
+ try {
+ while ((line = reader.readLine()) != null) {
+ lines.add(line);
+ }
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
+ }
+ return lines.toArray(new String[lines.size()]);
+ }
+
+ private ModifyAsync() {
+ // Not used.
+ }
+}
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/PasswordResetForAD.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/PasswordResetForAD.java
index 6e7a79d..3b75ce3 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/PasswordResetForAD.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/PasswordResetForAD.java
@@ -20,7 +20,7 @@
*
* CDDL HEADER END
*
- * Copyright 2013-2014 ForgeRock AS
+ * Copyright 2013-2015 ForgeRock AS.
*
*/
@@ -45,7 +45,7 @@
/**
* This command-line client demonstrates how to reset a user password in
* Microsoft Active Directory.
- * <p>
+ * <br>
* The client takes as arguments the host and port of the Active Directory
* server, a flag indicating whether this is a self-reset (user changing own
* password) or an administrative reset (administrator changing a password),
@@ -56,7 +56,7 @@
/**
* Reset a user password in Microsoft Active Directory.
- * <p>
+ * <br>
* The connection should be LDAPS, not LDAP, in order to perform the
* modification.
*
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Proxy.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Proxy.java
index c7da549..41c413f 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Proxy.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Proxy.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -57,8 +57,8 @@
* This example takes the following command line parameters:
*
* <pre>
- * <listenAddress> <listenPort> <proxyDN> <proxyPassword> <remoteAddress1> <remotePort1>
- * [<remoteAddress2> <remotePort2> ...]
+ * {@code <listenAddress> <listenPort> <proxyDN> <proxyPassword> <remoteAddress1> <remotePort1>
+ * [<remoteAddress2> <remotePort2> ...]}
* </pre>
*/
public final class Proxy {
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ProxyBackend.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ProxyBackend.java
index 56ad3af..b9dfdf9 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ProxyBackend.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ProxyBackend.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -78,15 +78,16 @@
* client connection. The following code illustrates how this may be achieved:
*
* <pre>
- * final RequestHandlerFactory<LDAPClientContext, RequestContext> proxyFactory =
- * new RequestHandlerFactory<LDAPClientContext, RequestContext>() {
- * @Override
+ * {@code
+ * final RequestHandlerFactory<LDAPClientContext, RequestContext> proxyFactory =
+ * new RequestHandlerFactory<LDAPClientContext, RequestContext>() {
+ * @Override
* public ProxyBackend handleAccept(LDAPClientContext clientContext) throws LdapException {
* return new ProxyBackend(factory, bindFactory);
* }
* };
- * final ServerConnectionFactory<LDAPClientContext, Integer> connectionHandler = Connections
- * .newServerConnectionFactory(proxyFactory);
+ * final ServerConnectionFactory<LDAPClientContext, Integer> connectionHandler = Connections
+ * .newServerConnectionFactory(proxyFactory);}
* </pre>
*/
final class ProxyBackend implements RequestHandler<RequestContext> {
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ReadSchema.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ReadSchema.java
index a3c29f9..592b728 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ReadSchema.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ReadSchema.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -44,7 +44,7 @@
* This example takes the following command line parameters:
*
* <pre>
- * <host> <port> <username> <password>
+ * {@code <host> <port> <username> <password>}
* </pre>
*/
public final class ReadSchema {
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/RewriterProxy.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/RewriterProxy.java
index 0f5a780..8efd1dc 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/RewriterProxy.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/RewriterProxy.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -98,7 +98,7 @@
* This example takes the following command line parameters:
*
* <pre>
- * <localAddress> <localPort> <proxyDN> <proxyPassword> <serverAddress> <serverPort>
+ * {@code <localAddress> <localPort> <proxyDN> <proxyPassword> <serverAddress> <serverPort>}
* </pre>
*
* If you have imported the users from <a
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SASLAuth.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SASLAuth.java
index 50ae094..7567ff8 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SASLAuth.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SASLAuth.java
@@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
- * Copyright 2011-2014 ForgeRock AS
+ * Copyright 2011-2015 ForgeRock AS.
*/
/**
@@ -52,7 +52,7 @@
* command line parameters:
* <ul>
* <li>host - host name of the directory server</li>
- * <li>port - port number of the directory server for StartTLS, e.g. 1389</li>
+ * <li>port - port number of the directory server for StartTLS</li>
* <li>authzid - (Optional) Authorization identity</li>
* <li>authcid - Authentication identity</li>
* <li>passwd - Password of the user to authenticate</li>
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Search.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Search.java
index 9a70944..e4ff1f5 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Search.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Search.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -45,8 +45,8 @@
* takes the following command line parameters:
*
* <pre>
- * <host> <port> <username> <password>
- * <baseDN> <scope> <filter> [<attibute> <attribute> ...]
+ * {@code <host> <port> <username> <password>
+ * <baseDN> <scope> <filter> [<attribute> <attribute> ...]}
* </pre>
*/
public final class Search {
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchAsync.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchAsync.java
index 9825710..8ab1d6a 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchAsync.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchAsync.java
@@ -21,8 +21,7 @@
* CDDL HEADER END
*
*
- * Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS
+ * Copyright 2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -55,8 +54,8 @@
* asynchronous APIs. This example takes the following command line parameters:
*
* <pre>
- * <host> <port> <username> <password>
- * <baseDN> <scope> <filter> [<attibute> <attribute> ...]
+ * {@code <host> <port> <username> <password>
+ * <baseDN> <scope> <filter> [<attribute> <attribute> ...]}
* </pre>
*/
public final class SearchAsync {
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBind.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBind.java
index 67db44b..07ae6e8 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBind.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBind.java
@@ -20,7 +20,7 @@
*
* CDDL HEADER END
*
- * Copyright 2012-2014 ForgeRock AS
+ * Copyright 2012-2015 ForgeRock AS.
*
*/
@@ -44,7 +44,7 @@
* entry.
* <ul>
* <li>host - host name of the directory server</li>
- * <li>port - port number of the directory server, e.g. 1389, 1636</li>
+ * <li>port - port number of the directory server</li>
* <li>base-dn - base DN for the search, e.g. dc=example,dc=com</li>
* </ul>
* All arguments are required.
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBindAsync.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBindAsync.java
new file mode 100644
index 0000000..c226616
--- /dev/null
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBindAsync.java
@@ -0,0 +1,183 @@
+/*
+ * 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 2015 ForgeRock AS.
+ *
+ */
+
+package org.forgerock.opendj.examples;
+
+import static org.forgerock.util.Utils.closeSilently;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.Filter;
+import org.forgerock.opendj.ldap.LDAPConnectionFactory;
+import org.forgerock.opendj.ldap.LdapException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.requests.Requests;
+import org.forgerock.opendj.ldap.responses.BindResult;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
+import org.forgerock.util.AsyncFunction;
+import org.forgerock.util.promise.ExceptionHandler;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.ResultHandler;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * An interactive command-line client that performs a search and simple bind
+ * using the asynchronous APIs.
+ * <br>
+ * The client prompts for email address and for a password,
+ * and then searches based on the email address,
+ * to bind as the user with the password.
+ * <br>
+ * If successful, the client displays the common name from the user's entry.
+ * <ul>
+ * <li>host - host name of the directory server</li>
+ * <li>port - port number of the directory server</li>
+ * <li>base-dn - base DN for the search, e.g. dc=example,dc=com</li>
+ * </ul>
+ * All arguments are required.
+ */
+public final class SearchBindAsync {
+ /** Connection to the LDAP server. */
+ private static Connection connection;
+ /** Email address provided by user. */
+ private static String mail;
+ /** Password provided by user. */
+ private static char[] password;
+ /** Bind DN returned by the search. */
+ private static String bindDn;
+ /** Result for the operation. */
+ private static int resultCode;
+ /** Count down latch to wait for modify operation to complete. */
+ private static final CountDownLatch COMPLETION_LATCH = new CountDownLatch(1);
+
+ /**
+ * Prompts for email and password, search and bind, then display message.
+ *
+ * @param args
+ * The command line arguments: host, port, base-dn.
+ */
+ public static void main(final String[] args) {
+ if (args.length != 3) {
+ System.err.println("Usage: host port base-dn");
+ System.err.println("For example: localhost 1389 dc=example,dc=com");
+ System.exit(1);
+ }
+ final String host = args[0];
+ final int port = Integer.parseInt(args[1]);
+ final String baseDn = args[2];
+
+ // Prompt for email address and password.
+ try {
+ mail = getInputLine("Email address:");
+ password = getInputLine("Password:").toCharArray();
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue());
+ return;
+ }
+
+ // Connect to the server, search for the user entry based on email address, and bind.
+ new LDAPConnectionFactory(host, port)
+ .getConnectionAsync()
+ .thenAsync(new AsyncFunction<Connection, SearchResultEntry, LdapException>() {
+ @Override
+ public Promise<SearchResultEntry, LdapException> apply(Connection connection)
+ throws LdapException {
+ SearchBindAsync.connection = connection;
+ return connection.searchSingleEntryAsync(
+ Requests.newSingleEntrySearchRequest(
+ baseDn,
+ SearchScope.WHOLE_SUBTREE,
+ Filter.equality("mail", mail).toString(),
+ "cn"));
+ }
+ })
+ .thenAsync(new AsyncFunction<SearchResultEntry, BindResult, LdapException>() {
+ @Override
+ public Promise<BindResult, LdapException> apply(SearchResultEntry searchResultEntry)
+ throws LdapException {
+ SearchBindAsync.bindDn = searchResultEntry.getName().toString();
+ return SearchBindAsync.connection.bindAsync(
+ Requests.newSimpleBindRequest(bindDn, password));
+ }
+ })
+ .thenOnResult(new ResultHandler<Result>() {
+ @Override
+ public void handleResult(Result result) {
+ if (result.getResultCode() == ResultCode.SUCCESS) {
+ System.out.println("Authenticated as " + SearchBindAsync.bindDn + ".");
+ }
+ resultCode = result.getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ })
+ .thenOnException(new ExceptionHandler<LdapException>() {
+ @Override
+ public void handleException(LdapException e) {
+ System.err.println(e.getMessage());
+ resultCode = e.getResult().getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ });
+
+ try {
+ COMPLETION_LATCH.await();
+ } catch (InterruptedException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
+ return;
+ }
+
+ closeSilently(connection);
+ System.exit(resultCode);
+ }
+
+ /**
+ * Returns an input string from System.in, after prompting on System.out.
+ * <br>
+ * Note: The input is echoed to the display.
+ *
+ * @param prompt The prompt asking for input.
+ * @return An input string from System.in.
+ * @throws IOException Failed to read from System.in.
+ */
+ private static String getInputLine(final String prompt) throws IOException {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+ System.out.print(prompt + " ");
+ return reader.readLine();
+ }
+
+ /**
+ * Constructor not used.
+ */
+ private SearchBindAsync() {
+ // Not used
+ }
+}
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java
index 746d594..64ef308 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -57,7 +57,7 @@
* This example takes the following command line parameters:
*
* <pre>
- * <listenAddress> <listenPort> <ldifFile> [<keyStoreFile> <keyStorePassword> <certNickname>]
+ * {@code <listenAddress> <listenPort> <ldifFile> [<keyStoreFile> <keyStorePassword> <certNickname>]}
* </pre>
*/
public final class Server {
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLife.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLife.java
index 6c5d881..831ab65 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLife.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLife.java
@@ -20,7 +20,7 @@
*
* CDDL HEADER END
*
- * Copyright 2012-2014 ForgeRock AS
+ * Copyright 2012-2015 ForgeRock AS.
*
*/
@@ -49,7 +49,7 @@
*
* <ul>
* <li>host - host name of the directory server</li>
- * <li>port - port number of the directory server, e.g. 1389, 1636</li>
+ * <li>port - port number of the directory server</li>
* </ul>
* All arguments are required.
*/
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLifeAsync.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLifeAsync.java
new file mode 100644
index 0000000..c0c82a3
--- /dev/null
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLifeAsync.java
@@ -0,0 +1,227 @@
+/*
+ * 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 2015 ForgeRock AS.
+ *
+ */
+
+package org.forgerock.opendj.examples;
+
+import static org.forgerock.util.Utils.closeSilently;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.Entries;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.LDAPConnectionFactory;
+import org.forgerock.opendj.ldap.LdapException;
+import org.forgerock.opendj.ldap.LinkedHashMapEntry;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.TreeMapEntry;
+import org.forgerock.opendj.ldap.requests.ModifyRequest;
+import org.forgerock.opendj.ldap.requests.Requests;
+import org.forgerock.opendj.ldap.responses.BindResult;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.opendj.ldif.LDIFEntryWriter;
+import org.forgerock.util.AsyncFunction;
+import org.forgerock.util.promise.ExceptionHandler;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.ResultHandler;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A command-line client that creates, updates, renames, and deletes a
+ * short-lived entry in order to demonstrate LDAP write operations
+ * using the asynchronous APIs.
+ * <br>
+ * The client takes as arguments the host and port for the directory server,
+ * and expects to find the entries and access control instructions as defined in
+ * <a href="http://opendj.forgerock.org/Example.ldif">Example.ldif</a>.
+ *
+ * <ul>
+ * <li>host - host name of the directory server</li>
+ * <li>port - port number of the directory server</li>
+ * </ul>
+ *
+ * All arguments are required.
+ */
+public final class ShortLifeAsync {
+ /** The short-lived entry. */
+ private static Entry entry;
+ /** Writer for displaying LDIF to System.out. */
+ private static LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
+ /** Connection to the LDAP server. */
+ private static Connection connection;
+ /** Result for the operation. */
+ private static int resultCode;
+ /** Count down latch to wait for modify operation to complete. */
+ private static final CountDownLatch COMPLETION_LATCH = new CountDownLatch(1);
+
+ /**
+ * Adds, modifies, renames, and deletes an entry.
+ *
+ * @param args
+ * The command line arguments: host, port
+ */
+ public static void main(final String[] args) {
+ if (args.length != 2) {
+ System.err.println("Usage: host port");
+ System.err.println("For example: localhost 1389");
+ System.exit(1);
+ }
+ final String host = args[0];
+ final int port = Integer.parseInt(args[1]);
+
+ // User credentials of a "Directory Administrators" group member.
+ // Kirsten Vaughan is authorized to create, update, and delete entries.
+ //
+ // Alternatively, prompt an administrator user for credentials,
+ // or get the application its own account with access to update data.
+ final String adminDn = "uid=kvaughan,ou=people,dc=example,dc=com";
+ final char[] adminPwd = "bribery".toCharArray();
+
+ // Prepare an entry to add to the directory.
+ final String entryDn = "cn=Bob,ou=People,dc=example,dc=com";
+ entry = new LinkedHashMapEntry(entryDn)
+ .addAttribute("cn", "Bob")
+ .addAttribute("objectclass", "top")
+ .addAttribute("objectclass", "person")
+ .addAttribute("objectclass", "organizationalPerson")
+ .addAttribute("objectclass", "inetOrgPerson")
+ .addAttribute("mail", "subgenius@example.com")
+ .addAttribute("sn", "Dobbs");
+
+ new LDAPConnectionFactory(host, port)
+ .getConnectionAsync()
+ .thenAsync(new AsyncFunction<Connection, BindResult, LdapException>() {
+ @Override
+ public Promise<BindResult, LdapException> apply(Connection connection)
+ throws LdapException {
+ ShortLifeAsync.connection = connection;
+ return connection.bindAsync(
+ Requests.newSimpleBindRequest(adminDn, adminPwd));
+ }
+ })
+ .thenAsync(new AsyncFunction<BindResult, Result, LdapException>() {
+ @Override
+ public Promise<Result, LdapException> apply(BindResult bindResult)
+ throws LdapException {
+ log("Adding the entry...");
+ log(entry);
+ return connection.addAsync(Requests.newAddRequest(entry));
+ }
+ })
+ .thenAsync(new AsyncFunction<Result, Result, LdapException>() {
+ @Override
+ public Promise<Result, LdapException> apply(Result result)
+ throws LdapException {
+ Entry old = TreeMapEntry.deepCopyOfEntry(entry);
+ entry = entry
+ .replaceAttribute("mail", "spammer@example.com")
+ .addAttribute("description", "Good user gone bad");
+ log("Updating mail address, adding description...");
+ log(entry);
+ ModifyRequest request = Entries.diffEntries(old, entry);
+ return connection.modifyAsync(request);
+ }
+ })
+ .thenAsync(new AsyncFunction<Result, Result, LdapException>() {
+ @Override
+ public Promise<Result, LdapException> apply(Result result)
+ throws LdapException {
+ entry = entry.setName("cn=Renamed,ou=People,dc=example,dc=com");
+ log("Renaming the entry...");
+ log(entry);
+ return connection.modifyDNAsync(
+ Requests.newModifyDNRequest(entryDn, "cn=Renamed"));
+ }
+ })
+ .thenAsync(new AsyncFunction<Result, Result, LdapException>() {
+ @Override
+ public Promise<Result, LdapException> apply(Result result)
+ throws LdapException {
+ final String newDn = entryDn.replace("Bob", "Renamed");
+ log("Deleting " + newDn + "...");
+ return connection.deleteAsync(
+ Requests.newDeleteRequest(newDn));
+ }
+ })
+ .thenOnResult(new ResultHandler<Result>() {
+ @Override
+ public void handleResult(Result result) {
+ resultCode = result.getResultCode().intValue();
+ log("... done.");
+ COMPLETION_LATCH.countDown();
+ }
+ })
+ .thenOnException(new ExceptionHandler<LdapException>() {
+ @Override
+ public void handleException(LdapException e) {
+ System.err.println(e.getMessage());
+ resultCode = e.getResult().getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ });
+
+ try {
+ COMPLETION_LATCH.await();
+ } catch (InterruptedException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
+ return;
+ }
+
+ closeSilently(connection);
+ System.exit(resultCode);
+ }
+
+ /**
+ * Log a message to System.out.
+ *
+ * @param message The message to write to the console.
+ */
+ private static void log(final String message) {
+ System.out.println(message);
+ }
+
+ /**
+ * Log an entry in LDIF form.
+ *
+ * @param entry The entry to log.
+ */
+ private static void log(final Entry entry) {
+ try {
+ writer.writeEntry(entry);
+ writer.flush();
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
+ }
+ }
+
+ /**
+ * Constructor not used.
+ */
+ private ShortLifeAsync() {
+ // Not used.
+ }
+}
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SimpleAuthAsync.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SimpleAuthAsync.java
new file mode 100644
index 0000000..c82c3d6
--- /dev/null
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SimpleAuthAsync.java
@@ -0,0 +1,268 @@
+/*
+ * 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 2015 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.examples;
+
+import static org.forgerock.util.Utils.closeSilently;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.LDAPConnectionFactory;
+import org.forgerock.opendj.ldap.LDAPOptions;
+import org.forgerock.opendj.ldap.LdapException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.SSLContextBuilder;
+import org.forgerock.opendj.ldap.TrustManagers;
+import org.forgerock.opendj.ldap.requests.Requests;
+import org.forgerock.opendj.ldap.responses.BindResult;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.util.AsyncFunction;
+import org.forgerock.util.promise.ExceptionHandler;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.ResultHandler;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import java.io.File;
+import java.security.GeneralSecurityException;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * An example client application which performs simple authentication to a
+ * directory server using the asynchronous APIs.
+ * <br>
+ * This example takes the following command line parameters:
+ * <ul>
+ * <li>host - host name of the directory server</li>
+ * <li>port - port number of the directory server</li>
+ * <li>bind-dn - DN of the user to authenticate</li>
+ * <li>bind-password - Password of the user to authenticate</li>
+ * <li>use-starttls - (Optional) connect with StartTLS</li>
+ * <li>use-ssl - (Optional) connect over SSL</li>
+ * </ul>
+ * The host, port, bind-dn, and bind-password arguments are required.
+ * The use-starttls and use-ssl arguments are optional and mutually exclusive.
+ * <br>
+ * If the server certificate is self-signed,
+ * or otherwise not trusted out-of-the-box,
+ * then set the trust store by using the JSSE system property
+ * {@code -Djavax.net.ssl.trustStore=/path/to/opendj/config/keystore}
+ * and the trust store password if necessary by using the JSSE system property
+ * {@code -Djavax.net.ssl.trustStorePassword=`cat /path/to/opendj/config/keystore.pin`}.
+ */
+public final class SimpleAuthAsync {
+ /** Connection to the LDAP server. */
+ private static Connection connection;
+ /** Result for the modify operation. */
+ private static int resultCode;
+ /** Count down latch to wait for modify operation to complete. */
+ private static final CountDownLatch COMPLETION_LATCH = new CountDownLatch(1);
+
+ /**
+ * Authenticate to the directory either over LDAP, over LDAPS, or using
+ * StartTLS.
+ *
+ * @param args
+ * The command line arguments
+ */
+ public static void main(final String[] args) {
+ parseArgs(args);
+
+ // Connect and bind.
+ // Pass getTrustAllOptions() instead of getTrustOptions()
+ // to the connection factory constructor
+ // if you want to trust all certificates blindly.
+ new LDAPConnectionFactory(host, port, getTrustOptions(host, keystore, storepass))
+ .getConnectionAsync()
+ .thenAsync(new AsyncFunction<Connection, BindResult, LdapException>() {
+ @Override
+ public Promise<BindResult, LdapException> apply(Connection connection)
+ throws LdapException {
+ SimpleAuthAsync.connection = connection;
+ return connection.bindAsync(
+ Requests.newSimpleBindRequest(bindDN, bindPassword.toCharArray()));
+ }
+ })
+ .thenOnResult(new ResultHandler<Result>() {
+ @Override
+ public void handleResult(Result result) {
+ resultCode = result.getResultCode().intValue();
+ System.out.println("Authenticated as " + bindDN + ".");
+ COMPLETION_LATCH.countDown();
+ }
+ })
+ .thenOnException(new ExceptionHandler<LdapException>() {
+ @Override
+ public void handleException(LdapException e) {
+ System.err.println(e.getMessage());
+ resultCode = e.getResult().getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ });
+
+ try {
+ COMPLETION_LATCH.await();
+ } catch (InterruptedException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
+ return;
+ }
+
+ closeSilently(connection);
+ System.exit(resultCode);
+ }
+
+ /**
+ * For StartTLS and SSL the connection factory needs SSL context options.
+ * In the general case, a trust manager in the SSL context serves
+ * to check server certificates, and a key manager handles client keys
+ * when the server checks certificates from our client.
+ * <br>
+ * This sample checks the server certificate,
+ * verifying that the certificate is currently valid,
+ * and that the host name of the server matches that of the certificate,
+ * based on a Java Key Store-format trust store.
+ * This sample does not present a client certificate.
+ *
+ * @param hostname Host name expected in the server certificate
+ * @param truststore Path to trust store file for the trust manager
+ * @param storepass Password for the trust store
+ * @return SSL context options if SSL or StartTLS is used.
+ */
+ private static LDAPOptions getTrustOptions(final String hostname,
+ final String truststore,
+ final String storepass) {
+ LDAPOptions lo = new LDAPOptions();
+ if (useSSL || useStartTLS) {
+ TrustManager trustManager = null;
+ try {
+ trustManager = TrustManagers.checkValidityDates(
+ TrustManagers.checkHostName(hostname,
+ TrustManagers.checkUsingTrustStore(
+ truststore, storepass.toCharArray(), null)));
+ if (trustManager != null) {
+ SSLContext sslContext = new SSLContextBuilder()
+ .setTrustManager(trustManager).getSSLContext();
+ lo.setSSLContext(sslContext);
+ }
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_CONNECT_ERROR.intValue());
+ }
+ lo.setUseStartTLS(useStartTLS);
+ }
+ return lo;
+ }
+
+ /**
+ * For StartTLS and SSL the connection factory needs SSL context options. In
+ * the general case, a trust manager in the SSL context serves to check
+ * server certificates, and a key manager handles client keys when the
+ * server checks certificates from our client.
+ * <br>
+ * OpenDJ directory server lets you install by default with a self-signed
+ * certificate that is not in the system trust store. To simplify this
+ * implementation trusts all server certificates.
+ *
+ * @return SSL context options to trust all certificates without checking.
+ */
+ private static LDAPOptions getTrustAllOptions() {
+ LDAPOptions lo = new LDAPOptions();
+ try {
+ SSLContext sslContext =
+ new SSLContextBuilder().setTrustManager(TrustManagers.trustAll())
+ .getSSLContext();
+ lo.setSSLContext(sslContext);
+ lo.setUseStartTLS(useStartTLS);
+ } catch (GeneralSecurityException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_CONNECT_ERROR.intValue());
+ }
+ return lo;
+ }
+
+ private static String host;
+ private static int port;
+ private static String bindDN;
+ private static String bindPassword;
+ private static boolean useStartTLS;
+ private static boolean useSSL;
+ private static String keystore;
+ private static String storepass;
+
+ /**
+ * Parse command line arguments.
+ *
+ * @param args
+ * host port bind-dn bind-password [ use-starttls | use-ssl ]
+ */
+ private static void parseArgs(String[] args) {
+ if (args.length < 4 || args.length > 5) {
+ giveUp();
+ }
+
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+ bindDN = args[2];
+ bindPassword = args[3];
+
+ if (args.length == 5) {
+ if ("use-starttls".equals(args[4].toLowerCase())) {
+ useStartTLS = true;
+ useSSL = false;
+ } else if ("use-ssl".equals(args[4].toLowerCase())) {
+ useStartTLS = false;
+ useSSL = true;
+ } else {
+ giveUp();
+ }
+ }
+
+ keystore = System.getProperty("javax.net.ssl.trustStore");
+ storepass = System.getProperty("javax.net.ssl.trustStorePassword");
+ if (keystore == null) { // Try to use Java's cacerts trust store.
+ keystore = System.getProperty("java.home") + File.separator
+ + "lib" + File.separator
+ + "security" + File.separator
+ + "cacerts";
+ storepass = "changeit"; // Default password
+ }
+ }
+
+ private static void giveUp() {
+ printUsage();
+ System.exit(1);
+ }
+
+ private static void printUsage() {
+ System.err.println("Usage: host port bind-dn bind-password [ use-starttls | use-ssl ]");
+ System.err.println("\thost, port, bind-dn, and bind-password arguments are required.");
+ System.err.println("\tuse-starttls and use-ssl are optional and mutually exclusive.");
+ System.err.println("\tOptionally set javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword.");
+ }
+
+ private SimpleAuthAsync() {
+ // Not used.
+ }
+}
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UpdateGroupAsync.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UpdateGroupAsync.java
new file mode 100644
index 0000000..0233413
--- /dev/null
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UpdateGroupAsync.java
@@ -0,0 +1,233 @@
+/*
+ * 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 2015 ForgeRock AS.
+ *
+ */
+
+package org.forgerock.opendj.examples;
+
+import static org.forgerock.util.Utils.closeSilently;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.LDAPConnectionFactory;
+import org.forgerock.opendj.ldap.LdapException;
+import org.forgerock.opendj.ldap.ModificationType;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.RootDSE;
+import org.forgerock.opendj.ldap.controls.PermissiveModifyRequestControl;
+import org.forgerock.opendj.ldap.requests.Requests;
+import org.forgerock.opendj.ldap.responses.BindResult;
+import org.forgerock.opendj.ldap.responses.CompareResult;
+import org.forgerock.opendj.ldap.responses.Responses;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.util.AsyncFunction;
+import org.forgerock.util.promise.ExceptionHandler;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.Promises;
+import org.forgerock.util.promise.ResultHandler;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * This command-line client demonstrates adding and removing a member from a
+ * (potentially large) static group using the asynchronous APIs.
+ *
+ * The client takes as arguments the host and port of the directory server, the
+ * group DN, the member DN, and whether to "add" or "del" the specified member
+ * from the group. The client uses the Permissive Modify control if it is
+ * available to avoid having to check whether the member belongs to the group or
+ * not.
+ *
+ * This client expects a group that is a <code>groupOfNames</code> such as:
+ *
+ * <pre>
+ * dn: cn=My Static Group,ou=Groups,dc=example,dc=com
+ * cn: My Static Group
+ * objectClass: groupOfNames
+ * objectClass: top
+ * ou: Groups
+ * member: uid=ahunter,ou=People,dc=example,dc=com
+ * member: uid=bjensen,ou=People,dc=example,dc=com
+ * member: uid=tmorris,ou=People,dc=example,dc=com
+ * </pre>
+ *
+ * This client connects as <code>cn=Directory Manager</code> with password
+ * <code>password</code>. Not a best practice; in real code use application
+ * specific credentials to connect, and ensure that your application has access
+ * to use the Permissive Modify control if your directory server supports it.
+ */
+public final class UpdateGroupAsync {
+ /** Connection to the LDAP server. */
+ private static Connection connection;
+ /** Result for the operation. */
+ private static int resultCode;
+ /** Count down latch to wait for modify operation to complete. */
+ private static final CountDownLatch COMPLETION_LATCH = new CountDownLatch(1);
+
+ /**
+ * Updates the group as necessary.
+ *
+ * @param args
+ * The command line arguments: host, port, group-dn, member-dn, (add|del)
+ */
+ public static void main(String[] args) {
+ if (args.length != 5) {
+ printUsage();
+ }
+ final String host = args[0];
+ final int port = Integer.parseInt(args[1]);
+ final String groupDn = args[2];
+ final String memberDn = args[3];
+ final ModificationType modType = getModificationType(args[4]);
+
+ // Connect, bind, update group.
+ new LDAPConnectionFactory(host, port)
+ .getConnectionAsync()
+ .thenAsync(new AsyncFunction<Connection, BindResult, LdapException>() {
+ @Override
+ public Promise<BindResult, LdapException> apply(Connection connection)
+ throws LdapException {
+ UpdateGroupAsync.connection = connection;
+ return connection.bindAsync(
+ Requests.newSimpleBindRequest("cn=Directory Manager", "password".toCharArray()));
+ }
+ })
+ .thenAsync(new AsyncFunction<BindResult, RootDSE, LdapException>() {
+ @Override
+ public Promise<RootDSE, LdapException> apply(BindResult bindResult)
+ throws LdapException {
+ return RootDSE.readRootDSEAsync(connection, null);
+ }
+ })
+ .thenAsync(new AsyncFunction<RootDSE, Result, LdapException>() {
+ @Override
+ public Promise<Result, LdapException> apply(RootDSE rootDSE) throws LdapException {
+ // If the directory supports the Permissive Modify request control,
+ // then the modification type does not matter.
+ if (rootDSE.getSupportedControls().contains(PermissiveModifyRequestControl.OID)) {
+ log("Updating group membership.");
+ return connection.modifyAsync(
+ Requests.newModifyRequest(groupDn)
+ .addControl(PermissiveModifyRequestControl.newControl(true))
+ .addModification(modType, "member", memberDn));
+ } else {
+ return connection
+ // Check whether the member is present.
+ .compareAsync(Requests.newCompareRequest(groupDn, "member", memberDn))
+ .thenAsync(new AsyncFunction<CompareResult, Result, LdapException>() {
+ @Override
+ public Promise<Result, LdapException> apply(CompareResult compareResult)
+ throws LdapException {
+ ResultCode rc = compareResult.getResultCode();
+ // Only add the member if missing from the group.
+ if (modType.equals(ModificationType.ADD)
+ && rc.equals(ResultCode.COMPARE_FALSE)) {
+ log("Adding " + memberDn + " to " + groupDn + ".");
+ return connection.modifyAsync(
+ Requests.newModifyRequest(groupDn)
+ .addModification(modType, "member", memberDn));
+ // Only delete if present in the group.
+ } else if (modType.equals(ModificationType.DELETE)
+ && rc.equals(ResultCode.COMPARE_TRUE)) {
+ log("Deleting " + memberDn + " from " + groupDn + ".");
+ return connection.modifyAsync(
+ Requests.newModifyRequest(groupDn)
+ .addModification(modType, "member", memberDn));
+ } else {
+ return Promises.newResultPromise(
+ Responses.newResult(ResultCode.SUCCESS));
+ }
+ }
+ });
+ }
+ }
+ })
+ .thenOnResult(new ResultHandler<Result>() {
+ @Override
+ public void handleResult(Result result) {
+ final String op = (modType == ModificationType.ADD) ? "added to" : "deleted from";
+ log(memberDn + " has been " + op + " the group " + groupDn + ".");
+ resultCode = result.getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ })
+ .thenOnException(new ExceptionHandler<LdapException>() {
+ @Override
+ public void handleException(LdapException e) {
+ System.err.println(e.getMessage());
+ resultCode = e.getResult().getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ });
+
+ try {
+ COMPLETION_LATCH.await();
+ } catch (InterruptedException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
+ return;
+ }
+
+ closeSilently(connection);
+ System.exit(resultCode);
+ }
+
+ /**
+ * Print usage then exit.
+ */
+ private static void printUsage() {
+ System.err.println("Usage: host port group-dn member-dn {add|del}");
+ System.err.println("For example: localhost 1389 "
+ + "cn=Static,ou=Groups,dc=example,dc=com "
+ + "uid=user.5150,ou=People,dc=example,dc=com "
+ + "del");
+ System.exit(1);
+ }
+
+ /**
+ * Return the modification type for the update operation.
+ * @param operation Operation specified as an argument (add or del).
+ */
+ private static ModificationType getModificationType(String operation) {
+ final boolean isAdd = "add".equalsIgnoreCase(operation);
+ if (!isAdd && !"del".equalsIgnoreCase(operation)) {
+ printUsage();
+ }
+ return isAdd ? ModificationType.ADD : ModificationType.DELETE;
+ }
+
+ /**
+ * Log a message to System.out.
+ *
+ * @param message The message to write to the console.
+ */
+ private static void log(final String message) {
+ System.out.println(message);
+ }
+
+ /**
+ * Constructor not used.
+ */
+ private UpdateGroupAsync() {
+ // Not used.
+ }
+}
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseGenericControl.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseGenericControl.java
index 2ccdf53..be5993d 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseGenericControl.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseGenericControl.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2014 ForgeRock AS
+ * Portions Copyright 2011-2015 ForgeRock AS.
*/
package org.forgerock.opendj.examples;
@@ -54,14 +54,14 @@
* pre-read request control from <a href="http://tools.ietf.org/html/rfc4527"
* >RFC 4527 - Lightweight Directory Access Protocol (LDAP) Read Entry Controls</a>.
*
- * <p>This example takes the following command line parameters:
+ * <br>This example takes the following command line parameters:
*
* <pre>
- * <host> <port> <username> <password> <userDN>
+ * {@code <host> <port> <username> <password> <userDN>}
* </pre>
*
- * <p>This example modifies the description attribute of an entry that
- * you specify in the <userDN> command line parameter.
+ * <br>This example modifies the description attribute of an entry that
+ * you specify in the {@code <userDN>} command line parameter.
*/
public final class UseGenericControl {
/**
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchema.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchema.java
index b25a370..e9563b1 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchema.java
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchema.java
@@ -53,7 +53,7 @@
* This example takes the following command line parameters:
*
* <pre>
- * <host> <port> <bindDN> <bindPassword>
+ * {@code <host> <port> <bindDN> <bindPassword>}
* </pre>
*
* Then it reads an entry to add from System.in.
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchemaAsync.java b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchemaAsync.java
new file mode 100644
index 0000000..6666da9
--- /dev/null
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchemaAsync.java
@@ -0,0 +1,183 @@
+/*
+ * 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 2015 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.examples;
+
+import static org.forgerock.util.Utils.closeSilently;
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.LDAPConnectionFactory;
+import org.forgerock.opendj.ldap.LdapException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.requests.Requests;
+import org.forgerock.opendj.ldap.responses.BindResult;
+import org.forgerock.opendj.ldap.responses.Result;
+import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldap.schema.SchemaValidationPolicy;
+import org.forgerock.opendj.ldif.LDIFEntryReader;
+import org.forgerock.util.AsyncFunction;
+import org.forgerock.util.promise.ExceptionHandler;
+import org.forgerock.util.promise.Promise;
+import org.forgerock.util.promise.Promises;
+import org.forgerock.util.promise.ResultHandler;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * This example command-line client application validates an entry
+ * against the directory server schema before adding it
+ * using the asynchronous APIs.
+ *
+ * <br>
+ *
+ * This example takes the following command line parameters:
+ *
+ * <pre>
+ * {@code <host> <port> <bindDN> <bindPassword>}
+ * </pre>
+ *
+ * Then it reads an entry to add from System.in.
+ * If the entry is valid according to the directory schema,
+ * it tries to add the entry to the directory.
+ */
+public final class UseSchemaAsync {
+ /** Connection to the LDAP server. */
+ private static Connection connection;
+ /** Result for the operation. */
+ private static int resultCode;
+ /** Count down latch to wait for modify operation to complete. */
+ private static final CountDownLatch COMPLETION_LATCH = new CountDownLatch(1);
+
+ /**
+ * Main method.
+ *
+ * @param args
+ * The command line arguments: host, port, bindDN, bindPassword.
+ */
+ public static void main(final String[] args) {
+ if (args.length != 4) {
+ System.err.println("Usage: host port bindDN bindPassword");
+ System.exit(1);
+ }
+
+ // Parse command line arguments.
+ final String host = args[0];
+ final int port = Integer.parseInt(args[1]);
+ final String bindDn = args[2];
+ final char[] bindPassword = args[3].toCharArray();
+
+ // Read an entry from System.in.
+ final Entry entry;
+ try {
+ System.out.println("Enter entry to add in LDIF format:");
+ entry = new LDIFEntryReader(System.in).readEntry();
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
+ return;
+ }
+ final String entryDn = entry.getName().toString();
+
+ // Connect, bind, read schema, and add entry if valid according to schema.
+ new LDAPConnectionFactory(host, port)
+ .getConnectionAsync()
+ .thenAsync(new AsyncFunction<Connection, BindResult, LdapException>() {
+ @Override
+ public Promise<BindResult, LdapException> apply(Connection connection)
+ throws LdapException {
+ UseSchemaAsync.connection = connection;
+ return connection.bindAsync(
+ Requests.newSimpleBindRequest(bindDn, bindPassword));
+ }
+ })
+ .thenAsync(new AsyncFunction<BindResult, Schema, LdapException>() {
+ @Override
+ public Promise<Schema, LdapException> apply(BindResult bindResult)
+ throws LdapException {
+ return Schema.readSchemaForEntryAsync(connection, DN.rootDN());
+ }
+ })
+ .thenAsync(new AsyncFunction<Schema, Result, LdapException>() {
+ @Override
+ public Promise<Result, LdapException> apply(Schema schema)
+ throws LdapException {
+ final List<LocalizableMessage> schemaErrors = new LinkedList<>();
+ boolean isValid = schema.validateEntry(
+ entry,
+ SchemaValidationPolicy.defaultPolicy(),
+ schemaErrors);
+ if (isValid) {
+ System.out.println("Processing ADD request for " + entryDn);
+ return connection.addAsync(Requests.newAddRequest(entry));
+ } else {
+ for (LocalizableMessage error : schemaErrors) {
+ System.err.println(error);
+ }
+ return Promises.newExceptionPromise(
+ LdapException.newLdapException(
+ ResultCode.CLIENT_SIDE_PARAM_ERROR,
+ "Entry does not conform to schema."));
+ }
+ }
+ })
+ .thenOnResult(new ResultHandler<Result>() {
+ @Override
+ public void handleResult(Result result) {
+ System.out.println("ADD operation successful for DN " + entryDn);
+ resultCode = result.getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ })
+ .thenOnException(new ExceptionHandler<LdapException>() {
+ @Override
+ public void handleException(LdapException e) {
+ System.err.println(e.getMessage());
+ resultCode = e.getResult().getResultCode().intValue();
+ COMPLETION_LATCH.countDown();
+ }
+ });
+
+ try {
+ COMPLETION_LATCH.await();
+ } catch (InterruptedException e) {
+ System.err.println(e.getMessage());
+ System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
+ return;
+ }
+
+ closeSilently(connection);
+ System.exit(resultCode);
+ }
+
+ private UseSchemaAsync() {
+ // Not used.
+ }
+}
diff --git a/opendj-sdk/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm b/opendj-sdk/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm
index 70b7509..4f8a072 100644
--- a/opendj-sdk/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm
+++ b/opendj-sdk/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm
@@ -31,7 +31,12 @@
<body>
<section name="About ${project.name}">
<p>This module contains example LDAP applications implemented using the
- OpenDJ LDAP SDK:</p>
+ OpenDJ LDAP SDK.</p>
+
+ <p>
+ The following examples use the synchronous APIs:
+ </p>
+
<ul>
<li>
<a href="xref/org/forgerock/opendj/examples/Search.html">LDAP search</a>
@@ -39,11 +44,6 @@
synchronous APIs
</li>
<li>
- <a href="xref/org/forgerock/opendj/examples/SearchAsync.html">LDAP asynchronous search</a>
- - illustrates how to perform an LDAP search operation using the
- asynchronous APIs
- </li>
- <li>
<a href="xref/org/forgerock/opendj/examples/Modify.html">LDAP modify</a>
- illustrates how to perform an LDAP modify operation using the
synchronous APIs
@@ -53,12 +53,8 @@
- illustrates how to implement a very simple LDAP server
</li>
<li>
- <a href="xref/org/forgerock/opendj/examples/Proxy.html">LDAP proxy</a>
- - illustrates how to implement a very simple LDAP proxy
- </li>
- <li>
<a href="xref/org/forgerock/opendj/examples/SimpleAuth.html">LDAP bind</a>
- - illustrates how to bind to an LDAP server
+ - illustrates how to bind to an LDAP server using the synchronous APIs
</li>
<li>
<a href="xref/org/forgerock/opendj/examples/SASLAuth.html">LDAP SASL bind</a>
@@ -79,14 +75,17 @@
<li>
<a href="xref/org/forgerock/opendj/examples/SearchBind.html">Search & bind</a>
- illustrates how to authenticate given a mail address and a password
+ using the synchronous APIs
</li>
<li>
<a href="xref/org/forgerock/opendj/examples/ShortLife.html">Short life</a>
- illustrates how to create, update, rename, and delete an entry
+ using the synchronous APIs
</li>
<li>
<a href="xref/org/forgerock/opendj/examples/UseSchema.html">Use LDAP Schema</a>
- illustrates how to validate an entry using the directory server LDAP schema
+ using the synchronous APIs
</li>
<li>
<a href="xref/org/forgerock/opendj/examples/Controls.html">Use LDAP Controls</a>
@@ -98,12 +97,9 @@
operations
</li>
<li>
- <a href="xref/org/forgerock/opendj/examples/RewriterProxy.html">Rewrite proxy</a>
- - illustrates how to rewrite DNs and attribute names in a proxy layer
- </li>
- <li>
<a href="xref/org/forgerock/opendj/examples/UpdateGroup.html">Update group</a>
- illustrates how to add or remove a member from a static group
+ using the synchronous APIs
</li>
<li>
<a href="xref/org/forgerock/opendj/examples/UseGenericControl.html">Use <code>GenericControl</code></a>
@@ -119,6 +115,55 @@
or change the password as the user
</li>
</ul>
+
+ <p>
+ The following examples use the asynchronous APIs:
+ </p>
+
+ <ul>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/SearchAsync.html">LDAP search (async)</a>
+ - illustrates how to perform an LDAP search operation using the
+ asynchronous APIs
+ </li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/ModifyAsync.html">LDAP modify (async)</a>
+ - illustrates how to perform an LDAP modify operation using the
+ asynchronous APIs
+ </li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/Proxy.html">LDAP proxy</a>
+ - illustrates how to implement a very simple LDAP proxy
+ </li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/SimpleAuthAsync.html">LDAP bind (async)</a>
+ - illustrates how to bind to an LDAP server using the asynchronous APIs
+ </li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/SearchBindAsync.html">Search & bind (async)</a>
+ - illustrates how to authenticate given a mail address and a password
+ using the asynchronous APIs
+ </li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/ShortLifeAsync.html">Short life (async)</a>
+ - illustrates how to create, update, rename, and delete an entry
+ using the asynchronous APIs
+ </li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/UseSchemaAsync.html">Use LDAP Schema (async)</a>
+ - illustrates how to validate an entry using the directory server LDAP schema
+ using the asynchronous APIs
+ </li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/RewriterProxy.html">Rewrite proxy</a>
+ - illustrates how to rewrite DNs and attribute names in a proxy layer
+ </li>
+ <li>
+ <a href="xref/org/forgerock/opendj/examples/UpdateGroupAsync.html">Update group (async)</a>
+ - illustrates how to add or remove a member from a static group
+ using the asynchronous APIs
+ </li>
+ </ul>
</section>
<section name="Documentation for ${project.name}">
<p>
--
Gitblit v1.10.0