From c447661328ddf21ffc5c3c4f1928d0f7db4ca764 Mon Sep 17 00:00:00 2001
From: Peter Major <peter.major@forgerock.com>
Date: Mon, 16 Dec 2013 17:26:25 +0000
Subject: [PATCH] Implementation for OPENDJ-1254 - review: CR-2722 Adding built-in support for Active Directory Change Notifications
---
opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PersistentSearchRequestControl.java | 7 -
opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ADNotificationRequestControl.java | 182 +++++++++++++++++++++++++++++++++++++++++++++
opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPSearchFutureResultImpl.java | 3
3 files changed, 184 insertions(+), 8 deletions(-)
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ADNotificationRequestControl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ADNotificationRequestControl.java
new file mode 100644
index 0000000..1a43255
--- /dev/null
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ADNotificationRequestControl.java
@@ -0,0 +1,182 @@
+/*
+ * 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 2013 ForgeRock AS
+ */
+package org.forgerock.opendj.ldap.controls;
+
+import org.forgerock.opendj.ldap.ByteString;
+
+/**
+ * The persistent search request control for Active Directory as defined by
+ * Microsoft. This control allows a client to receive notification of changes
+ * that occur in an Active Directory server.
+ * <br/>
+ *
+ * <pre>
+ * Connection connection = ...;
+ *
+ * SearchRequest request =
+ * Requests.newSearchRequest("dc=example,dc=com",
+ * SearchScope.WHOLE_SUBTREE, "(objectclass=*)", "cn",
+ * "isDeleted", "whenChanged", "whenCreated").addControl(
+ * ADNotificationRequestControl.newControl(true));
+ *
+ * ConnectionEntryReader reader = connection.search(request);
+ *
+ * while (reader.hasNext()) {
+ * if (!reader.isReference()) {
+ * SearchResultEntry entry = reader.readEntry(); // Entry that changed
+ *
+ * Boolean isDeleted = entry.parseAttribute("isDeleted").asBoolean();
+ * if (isDeleted != null && isDeleted) {
+ * // Handle entry deletion
+ * }
+ * String whenCreated = entry.parseAttribute("whenCreated").asString();
+ * String whenChanged = entry.parseAttribute("whenChanged").asString();
+ * if (whenCreated != null && whenChanged != null) {
+ * if (whenCreated.equals(whenChanged)) {
+ * //Handle entry addition
+ * } else {
+ * //Handle entry modification
+ * }
+ * }
+ * } else {
+ * reader.readReference(); //read and ignore reference
+ * }
+ * }
+ *
+ * </pre>
+ *
+ * @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa772153(v=vs.85).aspx">
+ * Change Notifications in Active Directory Domain Services</a>
+ */
+public final class ADNotificationRequestControl implements Control {
+
+ /**
+ * The OID for the Microsoft Active Directory persistent search request
+ * control. The control itself is empty and the changes are returned as
+ * attributes, such as "isDeleted", "whenChanged", "whenCreated".
+ */
+ public static final String OID = "1.2.840.113556.1.4.528";
+
+ /**
+ * The name of the isDeleted attribute as defined in the Active Directory
+ * schema. If the value of the attribute is <code>TRUE</code>, the object
+ * has been marked for deletion.
+ */
+ public static final String IS_DELETED_ATTR = "isDeleted";
+
+ /**
+ * The name of the whenCreated attribute as defined in the Active Directory
+ * schema. Holds the date of the creation of the object in GeneralizedTime
+ * format.
+ */
+ public static final String WHEN_CREATED_ATTR = "whenCreated";
+
+ /**
+ * The name of the whenChanged attribute as defined in the Active Directory
+ * schema. Holds the date of the last modification of the object in
+ * GeneralizedTime format.
+ */
+ public static final String WHEN_CHANGED_ATTR = "whenChanged";
+
+ /**
+ * The name of the objectGUID attribute as defined in the Active Directory
+ * schema. This is the unique identifier of an object stored in binary
+ * format.
+ */
+ public static final String OBJECT_GUID_ATTR = "objectGUID";
+
+ /**
+ * The name of the uSNChanged attribute as defined in the Active Directory
+ * schema. This attribute can be used to determine whether the current
+ * state of the object on the server reflects the latest changes that the
+ * client has received.
+ */
+ public static final String USN_CHANGED_ATTR = "uSNChanged";
+
+ private final boolean isCritical;
+
+ private ADNotificationRequestControl(final boolean isCritical) {
+ this.isCritical = isCritical;
+ }
+
+ /**
+ * Creates a new Active Directory change notification request control.
+ *
+ * @param isCritical
+ * {@code true} if it is unacceptable to perform the operation
+ * without applying the semantics of this control, or
+ * {@code false} if it can be ignored
+ * @return The new control.
+ */
+ public static ADNotificationRequestControl newControl(final boolean isCritical) {
+ return new ADNotificationRequestControl(isCritical);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getOID() {
+ return OID;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ByteString getValue() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean hasValue() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCritical() {
+ return isCritical;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("ADNotificationRequestControl(oid=");
+ builder.append(getOID());
+ builder.append(", criticality=");
+ builder.append(isCritical());
+ builder.append(")");
+ return builder.toString();
+ }
+}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PersistentSearchRequestControl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PersistentSearchRequestControl.java
index 6f30c07..bdb6dad 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PersistentSearchRequestControl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PersistentSearchRequestControl.java
@@ -106,13 +106,6 @@
public static final String OID = "2.16.840.1.113730.3.4.3";
/**
- * The OID for the Microsoft Active Directory persistent search request
- * control. The control itself is empty and the changes are returned in the
- * following attributes "isDeleted", "whenChanged", "whenCreated".
- */
- public static final String ACTIVE_DIRECTORY_OID = "1.2.840.113556.1.4.528";
-
- /**
* A decoder which can be used for decoding the persistent search request
* control.
*/
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPSearchFutureResultImpl.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPSearchFutureResultImpl.java
index 216ed6c..d1a700b 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPSearchFutureResultImpl.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPSearchFutureResultImpl.java
@@ -31,6 +31,7 @@
import org.forgerock.opendj.ldap.IntermediateResponseHandler;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchResultHandler;
+import org.forgerock.opendj.ldap.controls.ADNotificationRequestControl;
import org.forgerock.opendj.ldap.controls.PersistentSearchRequestControl;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.Responses;
@@ -70,7 +71,7 @@
this.request = request;
this.searchResultHandler = resultHandler;
this.isPersistentSearch = request.containsControl(PersistentSearchRequestControl.OID)
- || request.containsControl(PersistentSearchRequestControl.ACTIVE_DIRECTORY_OID);
+ || request.containsControl(ADNotificationRequestControl.OID);
}
/** {@inheritDoc} */
--
Gitblit v1.10.0