CR-7880 OPENDJ-1608 Provide asynchronous examples
This patch adds some new examples using the asynchronous APIs:
* ModifyAsync.java
* SearchBindAsync.java
* ShortLifeAsync.java
* SimpleAuthAsync.java
* UpdateGroupAsync.java
* UseSchemaAsync.java
The examples also tend to be written in fluent style,
which in some cases looks a bit cluttered due to inline declarations.
16 files modified
6 files added
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2014 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * <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. |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2014 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * 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 { |
| New file |
| | |
| | | /* |
| | | * 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. |
| | | } |
| | | } |
| | |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * Copyright 2013-2014 ForgeRock AS |
| | | * Copyright 2013-2015 ForgeRock AS. |
| | | * |
| | | */ |
| | | |
| | |
| | | /** |
| | | * 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), |
| | |
| | | |
| | | /** |
| | | * Reset a user password in Microsoft Active Directory. |
| | | * <p> |
| | | * <br> |
| | | * The connection should be LDAPS, not LDAP, in order to perform the |
| | | * modification. |
| | | * |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2015 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * 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 { |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2015 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * 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> { |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2014 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * This example takes the following command line parameters: |
| | | * |
| | | * <pre> |
| | | * <host> <port> <username> <password> |
| | | * {@code <host> <port> <username> <password>} |
| | | * </pre> |
| | | */ |
| | | public final class ReadSchema { |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2015 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * 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 |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2011-2014 ForgeRock AS |
| | | * Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | /** |
| | |
| | | * 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> |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2014 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * 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 { |
| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2014 ForgeRock AS |
| | | * Copyright 2015 ForgeRock AS. |
| | | */ |
| | | package org.forgerock.opendj.examples; |
| | | |
| | |
| | | * 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 { |
| | |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * Copyright 2012-2014 ForgeRock AS |
| | | * Copyright 2012-2015 ForgeRock AS. |
| | | * |
| | | */ |
| | | |
| | |
| | | * 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. |
| New file |
| | |
| | | /* |
| | | * 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 |
| | | } |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2015 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * 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 { |
| | |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * Copyright 2012-2014 ForgeRock AS |
| | | * Copyright 2012-2015 ForgeRock AS. |
| | | * |
| | | */ |
| | | |
| | |
| | | * |
| | | * <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. |
| | | */ |
| New file |
| | |
| | | /* |
| | | * 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. |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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. |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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. |
| | | } |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2014 ForgeRock AS |
| | | * Portions Copyright 2011-2015 ForgeRock AS. |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | |
| | | * 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 { |
| | | /** |
| | |
| | | * 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. |
| New file |
| | |
| | | /* |
| | | * 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. |
| | | } |
| | | } |
| | |
| | | <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> |
| | |
| | | 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 |
| | |
| | | - 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> |
| | |
| | | <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> |
| | |
| | | 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> |
| | |
| | | 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> |