/*
* 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.
*
* 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
* Example.ldif.
*
*
* - host - host name of the directory server
* - port - port number of the directory server
*
*
* 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() {
@Override
public Promise apply(Connection connection)
throws LdapException {
ShortLifeAsync.connection = connection;
return connection.bindAsync(
Requests.newSimpleBindRequest(adminDn, adminPwd));
}
})
.thenAsync(new AsyncFunction() {
@Override
public Promise apply(BindResult bindResult)
throws LdapException {
log("Adding the entry...");
log(entry);
return connection.addAsync(Requests.newAddRequest(entry));
}
})
.thenAsync(new AsyncFunction() {
@Override
public Promise 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() {
@Override
public Promise 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() {
@Override
public Promise apply(Result result)
throws LdapException {
final String newDn = entryDn.replace("Bob", "Renamed");
log("Deleting " + newDn + "...");
return connection.deleteAsync(
Requests.newDeleteRequest(newDn));
}
})
.thenOnResult(new ResultHandler() {
@Override
public void handleResult(Result result) {
resultCode = result.getResultCode().intValue();
log("... done.");
COMPLETION_LATCH.countDown();
}
})
.thenOnException(new ExceptionHandler() {
@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.
}
}