001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2013-2016 ForgeRock AS. 015 */ 016package org.forgerock.opendj.ldap.controls; 017 018import org.forgerock.opendj.ldap.ByteString; 019 020/** 021 * The persistent search request control for Active Directory as defined by 022 * Microsoft. This control allows a client to receive notification of changes 023 * that occur in an Active Directory server. 024 * <br/> 025 * 026 * <pre> 027 * Connection connection = ...; 028 * 029 * SearchRequest request = 030 * Requests.newSearchRequest("dc=example,dc=com", 031 * SearchScope.WHOLE_SUBTREE, "(objectclass=*)", "cn", 032 * "isDeleted", "whenChanged", "whenCreated").addControl( 033 * ADNotificationRequestControl.newControl(true)); 034 * 035 * ConnectionEntryReader reader = connection.search(request); 036 * 037 * while (reader.hasNext()) { 038 * if (!reader.isReference()) { 039 * SearchResultEntry entry = reader.readEntry(); // Entry that changed 040 * 041 * Boolean isDeleted = entry.parseAttribute("isDeleted").asBoolean(); 042 * if (isDeleted != null && isDeleted) { 043 * // Handle entry deletion 044 * } 045 * String whenCreated = entry.parseAttribute("whenCreated").asString(); 046 * String whenChanged = entry.parseAttribute("whenChanged").asString(); 047 * if (whenCreated != null && whenChanged != null) { 048 * if (whenCreated.equals(whenChanged)) { 049 * //Handle entry addition 050 * } else { 051 * //Handle entry modification 052 * } 053 * } 054 * } else { 055 * reader.readReference(); //read and ignore reference 056 * } 057 * } 058 * 059 * </pre> 060 * 061 * @see <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa772153(v=vs.85).aspx"> 062 * Change Notifications in Active Directory Domain Services</a> 063 */ 064public final class ADNotificationRequestControl implements Control { 065 066 /** 067 * The OID for the Microsoft Active Directory persistent search request 068 * control. The control itself is empty and the changes are returned as 069 * attributes, such as "isDeleted", "whenChanged", "whenCreated". 070 */ 071 public static final String OID = "1.2.840.113556.1.4.528"; 072 073 /** 074 * The name of the isDeleted attribute as defined in the Active Directory 075 * schema. If the value of the attribute is <code>TRUE</code>, the object 076 * has been marked for deletion. 077 */ 078 public static final String IS_DELETED_ATTR = "isDeleted"; 079 080 /** 081 * The name of the whenCreated attribute as defined in the Active Directory 082 * schema. Holds the date of the creation of the object in GeneralizedTime 083 * format. 084 */ 085 public static final String WHEN_CREATED_ATTR = "whenCreated"; 086 087 /** 088 * The name of the whenChanged attribute as defined in the Active Directory 089 * schema. Holds the date of the last modification of the object in 090 * GeneralizedTime format. 091 */ 092 public static final String WHEN_CHANGED_ATTR = "whenChanged"; 093 094 /** 095 * The name of the objectGUID attribute as defined in the Active Directory 096 * schema. This is the unique identifier of an object stored in binary 097 * format. 098 */ 099 public static final String OBJECT_GUID_ATTR = "objectGUID"; 100 101 /** 102 * The name of the uSNChanged attribute as defined in the Active Directory 103 * schema. This attribute can be used to determine whether the current 104 * state of the object on the server reflects the latest changes that the 105 * client has received. 106 */ 107 public static final String USN_CHANGED_ATTR = "uSNChanged"; 108 109 private final boolean isCritical; 110 111 private ADNotificationRequestControl(final boolean isCritical) { 112 this.isCritical = isCritical; 113 } 114 115 /** 116 * Creates a new Active Directory change notification request control. 117 * 118 * @param isCritical 119 * {@code true} if it is unacceptable to perform the operation 120 * without applying the semantics of this control, or 121 * {@code false} if it can be ignored 122 * @return The new control. 123 */ 124 public static ADNotificationRequestControl newControl(final boolean isCritical) { 125 return new ADNotificationRequestControl(isCritical); 126 } 127 128 @Override 129 public String getOID() { 130 return OID; 131 } 132 133 @Override 134 public ByteString getValue() { 135 return null; 136 } 137 138 @Override 139 public boolean hasValue() { 140 return false; 141 } 142 143 @Override 144 public boolean isCritical() { 145 return isCritical; 146 } 147 148 @Override 149 public String toString() { 150 final StringBuilder builder = new StringBuilder(); 151 builder.append("ADNotificationRequestControl(oid="); 152 builder.append(getOID()); 153 builder.append(", criticality="); 154 builder.append(isCritical()); 155 builder.append(")"); 156 return builder.toString(); 157 } 158}