001/* 002 * Copyright 2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.unboundidds; 037 038 039 040import com.unboundid.ldap.sdk.DN; 041import com.unboundid.ldap.sdk.LDAPException; 042import com.unboundid.ldap.sdk.unboundidds.controls. 043 OperationPurposeRequestControl; 044import com.unboundid.ldap.sdk.unboundidds.extensions.SubtreeAccessibilityState; 045import com.unboundid.util.Mutable; 046import com.unboundid.util.NotNull; 047import com.unboundid.util.Nullable; 048import com.unboundid.util.ThreadSafety; 049import com.unboundid.util.ThreadSafetyLevel; 050import com.unboundid.util.Validator; 051 052 053 054/** 055 * This class defines a number of properties that can be used when attempting to 056 * move a subtree from one Ping Identity Directory Server instance to another 057 * Ping Identity Directory Server instance using restricted subtree 058 * accessibility. 059 * <BR> 060 * <BLOCKQUOTE> 061 * <B>NOTE:</B> This class, and other classes within the 062 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 063 * supported for use against Ping Identity, UnboundID, and 064 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 065 * for proprietary functionality or for external specifications that are not 066 * considered stable or mature enough to be guaranteed to work in an 067 * interoperable way with other types of LDAP servers. 068 * </BLOCKQUOTE> 069 */ 070@Mutable() 071@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 072public final class MoveSubtreeProperties 073{ 074 // Indicates whether to suppress referential integrity processing on the 075 // source server. 076 private boolean suppressReferentialIntegrityUpdates; 077 078 // Indicates whether to use the to-be-deleted subtree accessibility state 079 // (rather than the hidden state) when beginning to remove entries from the 080 // source server. 081 private boolean useToBeDeletedAccessibilityState; 082 083 // The base DN for the subtree to move. 084 @NotNull private DN baseDN; 085 086 // The maximum number of entries allowed in the subtree to move. 087 private int maximumAllowedSubtreeSize; 088 089 // An optional listener that may be invoked during the course of moving 090 // entries from the source server to the target server. 091 @Nullable private MoveSubtreeListener listener; 092 093 // An optional operation purpose request control to include in all requests 094 // sent to the source and target servers. 095 @Nullable private OperationPurposeRequestControl 096 operationPurposeRequestControl; 097 098 099 100 /** 101 * Creates a new set of properties that can be used when moving the specified 102 * subtree from one server to another. 103 * 104 * @param baseDN The base DN for the subtree to be moved. It must not be 105 * {@code null}, and it must represent a valid DN with one or 106 * more RDN components. 107 * 108 * @throws LDAPException If the provided string cannot be parsed as a valid 109 * DN. 110 */ 111 public MoveSubtreeProperties(@NotNull final String baseDN) 112 throws LDAPException 113 { 114 this(new DN(baseDN)); 115 } 116 117 118 119 /** 120 * Creates a new set of properties that can be used when moving the specified 121 * subtree from one server to another. 122 * 123 * @param baseDN The base DN for the subtree to be moved. It must not be 124 * {@code null}, and it must have one or more RDN components. 125 */ 126 public MoveSubtreeProperties(@NotNull final DN baseDN) 127 { 128 setBaseDN(baseDN); 129 130 suppressReferentialIntegrityUpdates = false; 131 useToBeDeletedAccessibilityState = false; 132 maximumAllowedSubtreeSize = 0; 133 listener = null; 134 operationPurposeRequestControl = null; 135 } 136 137 138 139 /** 140 * Creates a new set of properties that is a copy of the provided properties 141 * object. 142 * 143 * @param properties The properties object to use to create the new 144 * properties. 145 */ 146 public MoveSubtreeProperties(@NotNull final MoveSubtreeProperties properties) 147 { 148 baseDN = properties.baseDN; 149 suppressReferentialIntegrityUpdates = 150 properties.suppressReferentialIntegrityUpdates; 151 useToBeDeletedAccessibilityState = 152 properties.useToBeDeletedAccessibilityState; 153 maximumAllowedSubtreeSize = properties.maximumAllowedSubtreeSize; 154 listener = properties.listener; 155 operationPurposeRequestControl = properties.operationPurposeRequestControl; 156 } 157 158 159 160 /** 161 * Retrieves the base DN of the subtree to move. 162 * 163 * @return The base DN of the subtree to move. 164 */ 165 @NotNull() 166 public DN getBaseDN() 167 { 168 return baseDN; 169 } 170 171 172 173 /** 174 * Specifies the base DN of the subtree to move. 175 * 176 * @param baseDN The base DN for the subtree to be moved. It must not be 177 * {@code null}, and it must represent a valid DN with one or 178 * more RDN components. 179 * 180 * @throws LDAPException If the provided string cannot be parsed as a valid 181 * DN. 182 */ 183 public void setBaseDN(@NotNull final String baseDN) 184 throws LDAPException 185 { 186 setBaseDN(new DN(baseDN)); 187 } 188 189 190 191 /** 192 * Specifies the base DN of the subtree to move. 193 * 194 * @param baseDN The base DN for the subtree to be moved. It must not be 195 * {@code null}, and it must have one or more RDN components. 196 */ 197 public void setBaseDN(@NotNull final DN baseDN) 198 { 199 Validator.ensureNotNullWithMessage(baseDN, 200 "MoveSubtreeProperties.baseDN must not be null."); 201 Validator.ensureTrue((baseDN.getRDNs().length > 0), 202 "MoveSubtreeProperties.baseDN must include one or more RDN " + 203 "components."); 204 205 this.baseDN = baseDN; 206 } 207 208 209 210 /** 211 * Retrieves the maximum number of entries that the target subtree may contain 212 * for it to be moved from one server to another. 213 * 214 * @return The maximum number of entries that the target subtree may contain 215 * for it to be moved from one server to another, or zero if no 216 * client-side size limit should be enforced (although the server may 217 * still impose its own size limit). 218 */ 219 public int getMaximumAllowedSubtreeSize() 220 { 221 return maximumAllowedSubtreeSize; 222 } 223 224 225 226 /** 227 * Specifies the maximum number of entries that the target subtree may contain 228 * for it to be moved from one server to another. If the subtree contains 229 * more than the maximum number of entries, then the attempt to move it will 230 * be aborted before any changes are applied to the data in either server. 231 * 232 * @param sizeLimit The maximum number of entries tht the target subtree may 233 * contain for it to be moved from one server to another. 234 * A value that is less than or equal to zero indicates 235 * that no client-side size limit should be imposed. Note 236 * that the server may also impose a size limit, and the 237 * smaller of the client-side and server-side limits will 238 * be in effect. 239 */ 240 public void setMaximumAllowedSubtreeSize(final int sizeLimit) 241 { 242 if (sizeLimit > 0) 243 { 244 maximumAllowedSubtreeSize = sizeLimit; 245 } 246 else 247 { 248 maximumAllowedSubtreeSize = 0; 249 } 250 } 251 252 253 254 /** 255 * Indicates whether to use the 256 * {@link SubtreeAccessibilityState#TO_BE_DELETED} subtree accessibility state 257 * (as opposed to the {@code HIDDEN} state) for the target subtree on the 258 * source server before beginning to remove entries from it. 259 * 260 * @return {@code true} if the {@code TO_BE_DELETED} subtree accessibility 261 * state should be used, or {@code false} if the {@code HIDDEN} state 262 * should be used. 263 */ 264 public boolean useToBeDeletedAccessibilityState() 265 { 266 return useToBeDeletedAccessibilityState; 267 } 268 269 270 271 /** 272 * Specifies whether to use the 273 * {@link SubtreeAccessibilityState#TO_BE_DELETED} subtree accessibility state 274 * (as opposed to the {@code HIDDEN} state) for the target subtree on the 275 * source server before beginning to remove entries from it. Both the 276 * {@code TO_BE_DELETED} and {@code HIDDEN} subtree accessibility states will 277 * completely hide the target subtree from all clients expect those 278 * authenticated as a designated bypass-user account, but the key differences 279 * between these states include: 280 * <UL> 281 * <LI> 282 * In some cases, the server may be able to process delete requests for 283 * entries in {@code TO_BE_DELETED} subtrees than for entries in subtrees 284 * with other accessibility states, including the {@code HIDDEN} state. 285 * </LI> 286 * <LI> 287 * Support for the {@code TO_BE_DELETED} subtree accessibility state was 288 * added to the Directory Server more recently than support for the 289 * {@code HIDDEN} state. Older Directory Server instances may not support 290 * the {@code TO_BE_DELETED} state. 291 * </LI> 292 * <LI> 293 * A {@code HIDDEN} subtree can be updated to give it a different 294 * accessibility state, but once a subtree has been placed in a 295 * {@code TO_BE_DELETED} accessibility state, its state cannot be manually 296 * updated. 297 * </LI> 298 * <LI> 299 * The {@code TO_BE_DELETED} accessibility state will automatically be 300 * removed from a subtree once all entries have been removed from that 301 * subtree, while the {@code HIDDEN} state needs to be manually removed 302 * if it is no longer desired. 303 * </LI> 304 * </UL> 305 * 306 * @param useToBeDeletedState Indicates whether to use the 307 * {@code TO_BE_DELETED} subtree accessibility 308 * state instead of the {@code HIDDEN} state for 309 * the target subtree on the source server before 310 * beginning to remove entries from it. 311 */ 312 public void setUseToBeDeletedAccessibilityState( 313 final boolean useToBeDeletedState) 314 { 315 useToBeDeletedAccessibilityState = useToBeDeletedState; 316 } 317 318 319 320 /** 321 * Indicates whether to suppress referential integrity updates when removing 322 * entries from the source server. 323 * 324 * @return {@code true} if referential integrity updates should be suppressed 325 * when removing entries from the source server, or {@code false} if 326 * not. 327 */ 328 public boolean suppressReferentialIntegrityUpdates() 329 { 330 return suppressReferentialIntegrityUpdates; 331 } 332 333 334 335 /** 336 * Specifies whether to suppress referential integrity updates when removing 337 * entries from the source server. By default, if the referential integrity 338 * plugin is enabled, then removing a user entry will automatically remove 339 * references to it from other entries, including things like static group 340 * membership. However, when moving entries from one server to another, and 341 * especially in cases where the associated references are in other entries 342 * that are also being moved, it may be desirable to suppress those 343 * referential integrity updates. 344 * 345 * @param suppressUpdates Indicates whether to suppress referential 346 * integrity updates when removing entries from the 347 * source server. 348 */ 349 public void setSuppressReferentialIntegrityUpdates( 350 final boolean suppressUpdates) 351 { 352 suppressReferentialIntegrityUpdates = suppressUpdates; 353 } 354 355 356 357 /** 358 * Retrieves an operation purpose request control that should be included in 359 * all requests sent to the source and target servers, if any. 360 * 361 * @return An operation purpose request control that should be included in 362 * all requests sent ot the source and target servers, or 363 * {@code null} if no operation purpose request control should be 364 * used. 365 */ 366 @Nullable() 367 public OperationPurposeRequestControl getOperationPurposeRequestControl() 368 { 369 return operationPurposeRequestControl; 370 } 371 372 373 374 /** 375 * Specifies an operation purpose request control that should be included in 376 * all requests sent to the source and target servers. 377 * 378 * @param control An operation purpose request control that should be 379 * included in all requests sent to the source and target 380 * servers. It may be {@code null} if no operation purpose 381 * request control should be used. 382 */ 383 public void setOperationPurposeRequestControl( 384 @Nullable final OperationPurposeRequestControl control) 385 { 386 operationPurposeRequestControl = control; 387 } 388 389 390 391 392 /** 393 * Retrieves the listener that may be invoked during the course of moving 394 * entries from the source server to the target server, if any. 395 * 396 * @return The listener that may be invoked during the course of moving 397 * entries from the source server to the target server, or 398 * {@code null} if no move subtree listener has been configured. 399 */ 400 @Nullable() 401 public MoveSubtreeListener getMoveSubtreeListener() 402 { 403 return listener; 404 } 405 406 407 408 409 /** 410 * Specifies a listener that may be invoked during the course of moving 411 * entries from the source server to the target server. The listener will be 412 * invoked before and after adding an entry to the target server, and it will 413 * be invoked before and after removing an entry from the source server. 414 * 415 * @param listener A listener that may be invoked during the course of 416 * moving entries from the source server to the target 417 * server. It may be {@code null} if no listener is needed. 418 */ 419 public void setMoveSubtreeListener( 420 @Nullable final MoveSubtreeListener listener) 421 { 422 this.listener = listener; 423 } 424 425 426 427 /** 428 * Retrieves a string representation of the properties. 429 * 430 * @return A string representation of the proprties. 431 */ 432 @Override() 433 @NotNull() 434 public String toString() 435 { 436 final StringBuilder buffer = new StringBuilder(); 437 toString(buffer); 438 return buffer.toString(); 439 } 440 441 442 443 /** 444 * Appends a string representation of the properties to the provided buffer. 445 * 446 * @param buffer The buffer to which the information should be appended. It 447 * must not be {@code null}. 448 */ 449 public void toString(@NotNull final StringBuilder buffer) 450 { 451 buffer.append("MoveSubtreeProperties(baseDN='"); 452 buffer.append(baseDN); 453 buffer.append("', maximumAllowedSubtreeSize="); 454 buffer.append(maximumAllowedSubtreeSize); 455 buffer.append(", useToBeDeletedAccessibilityState="); 456 buffer.append(useToBeDeletedAccessibilityState); 457 buffer.append(", suppressReferentialIntegrityUpdates="); 458 buffer.append(suppressReferentialIntegrityUpdates); 459 buffer.append(", operationPurposeRequestControl="); 460 buffer.append(operationPurposeRequestControl); 461 buffer.append(", moveSubtreeListener="); 462 buffer.append(listener); 463 buffer.append(')'); 464 } 465}