001/* 002 * Copyright 2012-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2019 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.unboundidds; 022 023 024 025import java.util.Date; 026 027import com.unboundid.ldap.sdk.Entry; 028import com.unboundid.ldap.sdk.LDAPException; 029import com.unboundid.ldap.sdk.ReadOnlyEntry; 030import com.unboundid.ldap.sdk.ResultCode; 031import com.unboundid.ldap.sdk.unboundidds.controls. 032 SoftDeletedEntryAccessRequestControl; 033import com.unboundid.util.NotMutable; 034import com.unboundid.util.ThreadSafety; 035import com.unboundid.util.ThreadSafetyLevel; 036 037import static com.unboundid.ldap.sdk.unboundidds.UnboundIDDSMessages.*; 038 039 040 041/** 042 * This class provides a data structure for representing information about a 043 * soft-deleted entry, which results from a soft delete operation that has 044 * caused the entry to be hidden so that it is not accessible to clients under 045 * normal circumstances, rather than causing the entry to be completely removed 046 * from the server. 047 * <BR> 048 * <BLOCKQUOTE> 049 * <B>NOTE:</B> This class, and other classes within the 050 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 051 * supported for use against Ping Identity, UnboundID, and 052 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 053 * for proprietary functionality or for external specifications that are not 054 * considered stable or mature enough to be guaranteed to work in an 055 * interoperable way with other types of LDAP servers. 056 * </BLOCKQUOTE> 057 * <BR> 058 * A soft-deleted entry will have its RDN altered to include the entryUUID for 059 * the original entry, will be updated to include the "ds-soft-delete-entry" 060 * auxiliary object class, and will have additional metadata attributes added to 061 * it which may include: 062 * <UL> 063 * <LI> 064 * ds-soft-delete-from-dn -- This specifies the DN assigned to the entry 065 * before it was converted to a soft-deleted entry. 066 * </LI> 067 * <LI> 068 * ds-soft-delete-timestamp -- This specifies the time that the entry was 069 * converted to a soft-deleted entry. 070 * </LI> 071 * <LI> 072 * ds-soft-delete-requester-dn -- This specifies the DN of the user who 073 * requested the soft delete operation. 074 * </LI> 075 * <LI> 076 * ds-soft-delete-requester-ip-address -- This specifies the IP address of 077 * the client that requested the soft delete operation. 078 * </LI> 079 * </UL> 080 * <BR><BR> 081 * Soft-deleted entries may only be retrieved by users who have the 082 * soft-delete-read privilege, and then only by clients who issue a search 083 * request with one or more of the following characteristics: 084 * <UL> 085 * <LI> 086 * The search operation has a scope of baseObject and a base DN which 087 * specifically targets a soft-deleted entry. 088 * </LI> 089 * <LI> 090 * The search operation includes a filter with a component that will 091 * specifically match entries that have the ds-soft-delete-entry object 092 * class (e.g., "(objectClass=ds-soft-delete-entry)"). 093 * </LI> 094 * <LI> 095 * The search operation includes a 096 * {@link SoftDeletedEntryAccessRequestControl}. 097 * </LI> 098 * </UL> 099 */ 100@NotMutable() 101@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 102public final class SoftDeletedEntry 103 extends ReadOnlyEntry 104{ 105 /** 106 * The name of the attribute that will be included in a soft-deleted entry to 107 * indicate the original DN the entry held before it was converted to a 108 * soft-deleted entry. 109 */ 110 public static final String ATTR_SOFT_DELETE_FROM_DN = 111 "ds-soft-delete-from-dn"; 112 113 114 115 /** 116 * The name of the attribute that will be included in a soft-deleted entry to 117 * indicate the DN of the user that requested the soft delete operation. 118 */ 119 public static final String ATTR_SOFT_DELETE_REQUESTER_DN = 120 "ds-soft-delete-requester-dn"; 121 122 123 124 /** 125 * The name of the attribute that will be included in a soft-deleted entry to 126 * indicate the IP address of the client that requested the soft delete 127 * operation. 128 */ 129 public static final String ATTR_SOFT_DELETE_REQUESTER_IP_ADDRESS = 130 "ds-soft-delete-requester-ip-address"; 131 132 133 134 /** 135 * The name of the attribute that will be included in a soft-deleted entry to 136 * indicate the time it was converted to a soft-deleted entry. 137 */ 138 public static final String ATTR_SOFT_DELETE_TIMESTAMP = 139 "ds-soft-delete-timestamp"; 140 141 142 143 /** 144 * The name of the auxiliary object class that will be used to mark 145 * soft-deleted entries. 146 */ 147 public static final String OC_SOFT_DELETED_ENTRY = "ds-soft-delete-entry"; 148 149 150 151 /** 152 * The serial version UID for this serializable class. 153 */ 154 private static final long serialVersionUID = -3450703461178674797L; 155 156 157 158 // The time the entry was converted to a soft-deleted entry. 159 private final Date softDeleteTimestamp; 160 161 // The DN held by the entry at the time it was converted to a soft-deleted 162 // entry. 163 private final String softDeleteFromDN; 164 165 // The DN of the user that requested the soft delete operation. 166 private final String softDeleteRequesterDN; 167 168 // The IP address of the client that requested the soft delete operation. 169 private final String softDeleteRequesterIPAddress; 170 171 172 173 /** 174 * Creates a soft-deleted entry from the provided entry. 175 * 176 * @param entry The entry to be processed as a soft-deleted entry. It must 177 * not be {@code null}. 178 * 179 * @throws LDAPException If the provided entry does not represent a valid 180 * soft-deleted entry. 181 */ 182 public SoftDeletedEntry(final Entry entry) 183 throws LDAPException 184 { 185 super(entry); 186 187 if (! entry.hasObjectClass(OC_SOFT_DELETED_ENTRY)) 188 { 189 throw new LDAPException(ResultCode.LOCAL_ERROR, 190 ERR_SOFT_DELETED_ENTRY_MISSING_OC.get(entry.getDN())); 191 } 192 193 softDeleteFromDN = entry.getAttributeValue(ATTR_SOFT_DELETE_FROM_DN); 194 softDeleteTimestamp = 195 entry.getAttributeValueAsDate(ATTR_SOFT_DELETE_TIMESTAMP); 196 softDeleteRequesterDN = 197 entry.getAttributeValue(ATTR_SOFT_DELETE_REQUESTER_DN); 198 softDeleteRequesterIPAddress = 199 entry.getAttributeValue(ATTR_SOFT_DELETE_REQUESTER_IP_ADDRESS); 200 201 if (softDeleteFromDN == null) 202 { 203 throw new LDAPException(ResultCode.LOCAL_ERROR, 204 ERR_SOFT_DELETED_ENTRY_MISSING_FROM_DN.get(entry.getDN())); 205 } 206 } 207 208 209 210 /** 211 * Retrieves the DN held by the entry at the time it was converted to a 212 * soft-deleted entry. 213 * 214 * @return The DN held by the entry at the time it was converted to a 215 * soft-deleted entry. 216 */ 217 public String getSoftDeleteFromDN() 218 { 219 return softDeleteFromDN; 220 } 221 222 223 224 /** 225 * Retrieves the time that the entry was converted to a soft-deleted entry, 226 * if available. 227 * 228 * @return The time that the entry was converted to a soft-deleted entry, or 229 * {@code null} if this is not available in the entry. 230 */ 231 public Date getSoftDeleteTimestamp() 232 { 233 return softDeleteTimestamp; 234 } 235 236 237 238 /** 239 * Retrieves the DN of the user that requested the soft delete operation, 240 * if available. 241 * 242 * @return The DN of the user that requested the soft delete operation, or 243 * {@code null} if this is not available in the entry. 244 */ 245 public String getSoftDeleteRequesterDN() 246 { 247 return softDeleteRequesterDN; 248 } 249 250 251 252 /** 253 * Retrieves the IP address of the client that requested the soft delete 254 * operation, if available. 255 * 256 * @return The IP address of the client that requested the soft delete 257 * operation, or {@code null} if this is not available in the entry. 258 */ 259 public String getSoftDeleteRequesterIPAddress() 260 { 261 return softDeleteRequesterIPAddress; 262 } 263 264 265 266 /** 267 * Retrieves a copy of the original entry as it appeared before the soft 268 * delete operation was processed. It will have its original DN and all 269 * soft delete metadata attributes and auxiliary object class removed. 270 * 271 * @return A copy of the original entry as it appeared before the soft delete 272 * operation was processed. 273 */ 274 public ReadOnlyEntry getUndeletedEntry() 275 { 276 final Entry e = duplicate(); 277 278 e.setDN(softDeleteFromDN); 279 280 e.removeAttributeValue("objectClass", OC_SOFT_DELETED_ENTRY); 281 e.removeAttribute(ATTR_SOFT_DELETE_FROM_DN); 282 e.removeAttribute(ATTR_SOFT_DELETE_TIMESTAMP); 283 e.removeAttribute(ATTR_SOFT_DELETE_REQUESTER_DN); 284 e.removeAttribute(ATTR_SOFT_DELETE_REQUESTER_IP_ADDRESS); 285 286 return new ReadOnlyEntry(e); 287 } 288 289 290 291 /** 292 * Indicates whether the provided entry may be parsed as a valid soft-deleted 293 * entry. 294 * 295 * @param entry The entry to be examined. It must not be {@code null}. 296 * 297 * @return {@code true} if the provided entry contains at least a 298 * ds-soft-delete-entry object class and a ds-soft-delete-from-dn 299 * attribute. 300 */ 301 public static boolean isSoftDeletedEntry(final Entry entry) 302 { 303 return (entry.hasObjectClass(OC_SOFT_DELETED_ENTRY) && 304 entry.hasAttribute(ATTR_SOFT_DELETE_FROM_DN)); 305 } 306}