001/* 002 * Copyright 2012-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2012-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) 2012-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.extensions; 037 038 039 040import java.util.ArrayList; 041import java.util.Collection; 042import java.util.Collections; 043import java.util.Iterator; 044import java.util.List; 045 046import com.unboundid.asn1.ASN1Element; 047import com.unboundid.asn1.ASN1Enumerated; 048import com.unboundid.asn1.ASN1OctetString; 049import com.unboundid.asn1.ASN1Sequence; 050import com.unboundid.ldap.sdk.Control; 051import com.unboundid.ldap.sdk.ExtendedRequest; 052import com.unboundid.ldap.sdk.LDAPException; 053import com.unboundid.ldap.sdk.ResultCode; 054import com.unboundid.util.Debug; 055import com.unboundid.util.NotMutable; 056import com.unboundid.util.NotNull; 057import com.unboundid.util.Nullable; 058import com.unboundid.util.StaticUtils; 059import com.unboundid.util.ThreadSafety; 060import com.unboundid.util.ThreadSafetyLevel; 061import com.unboundid.util.Validator; 062 063import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 064 065 066 067/** 068 * This class provides an implementation of an extended request that may be used 069 * to set the accessibility of one or more subtrees in the Ping Identity, 070 * UnboundID, or Nokia/Alcatel-Lucent 8661 Directory Server. It may be used to 071 * indicate that a specified set of entries and all their subordinates should be 072 * invisible or read-only, or to restore it to full accessibility. 073 * <BR> 074 * <BLOCKQUOTE> 075 * <B>NOTE:</B> This class, and other classes within the 076 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 077 * supported for use against Ping Identity, UnboundID, and 078 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 079 * for proprietary functionality or for external specifications that are not 080 * considered stable or mature enough to be guaranteed to work in an 081 * interoperable way with other types of LDAP servers. 082 * </BLOCKQUOTE> 083 * <BR> 084 * The OID for this request is 1.3.6.1.4.1.30221.2.6.19, and the 085 * value must have the encoding specified below. Note that the initial 086 * specification for this extended request only allowed for the specification of 087 * a single subtree, whereas it is now possible to affect the accessibility of 088 * multiple subtrees in a single request. In order to preserve compatibility 089 * with the original encoding, if there is more than one target subtree, then 090 * the first subtree must be specified as the first element in the value 091 * sequence and the remaining subtrees must be specified in the 092 * additionalSubtreeBaseDNs element. 093 * <BR><BR> 094 * <PRE> 095 * SetSubtreeAccessibilityRequestValue ::= SEQUENCE { 096 * subtreeBaseDN LDAPDN, 097 * subtreeAccessibility ENUMERATED { 098 * accessible (0), 099 * read-only-bind-allowed (1), 100 * read-only-bind-denied (2), 101 * hidden (3), 102 * to-be-deleted (4), 103 * ... }, 104 * bypassUserDN [0] LDAPDN OPTIONAL, 105 * additionalSubtreeBaseDNs [1] SEQUENCE OF LDAPDN OPTIONAL, 106 * ... } 107 * </PRE> 108 */ 109@NotMutable() 110@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 111public final class SetSubtreeAccessibilityExtendedRequest 112 extends ExtendedRequest 113{ 114 /** 115 * The OID (1.3.6.1.4.1.30221.2.6.19) for the set subtree accessibility 116 * extended request. 117 */ 118 @NotNull public static final String SET_SUBTREE_ACCESSIBILITY_REQUEST_OID = 119 "1.3.6.1.4.1.30221.2.6.19"; 120 121 122 123 /** 124 * The BER type for the bypass user DN element of the request. 125 */ 126 private static final byte TYPE_BYPASS_USER_DN = (byte) 0x80; 127 128 129 130 /** 131 * The BER type for the set of additional subtree base DNs. 132 */ 133 private static final byte TYPE_ADDITIONAL_SUBTREE_BASE_DNS = (byte) 0xA1; 134 135 136 137 /** 138 * The serial version UID for this serializable class. 139 */ 140 private static final long serialVersionUID = -6619215987488239440L; 141 142 143 144 // The set of subtree base DNs included in the request. 145 @NotNull private final List<String> subtreeBaseDNs; 146 147 // The DN of a user who will be exempted from the restrictions. This is not 148 // applicable for a subtree accessibility of ACCESSIBLE. 149 @Nullable private final String bypassUserDN; 150 151 // The accessibility state to use for the target subtrees. 152 @NotNull private final SubtreeAccessibilityState accessibilityState; 153 154 155 156 /** 157 * Creates a new set subtree accessibility extended request with the provided 158 * information. 159 * 160 * @param subtreeBaseDNs The set of base DNs for the target subtree. 161 * It must not be {@code null} or empty. 162 * @param accessibilityState The accessibility state to use for the target 163 * subtrees. 164 * @param bypassUserDN The DN of a user that will be allowed to bypass 165 * restrictions on the target subtrees. 166 * @param controls The set of controls to include in the request. 167 */ 168 private SetSubtreeAccessibilityExtendedRequest( 169 @NotNull final Collection<String> subtreeBaseDNs, 170 @NotNull final SubtreeAccessibilityState accessibilityState, 171 @Nullable final String bypassUserDN, 172 @Nullable final Control... controls) 173 { 174 super(SET_SUBTREE_ACCESSIBILITY_REQUEST_OID, 175 encodeValue(subtreeBaseDNs, accessibilityState, bypassUserDN), 176 controls); 177 178 this.subtreeBaseDNs = Collections.unmodifiableList( 179 new ArrayList<>(subtreeBaseDNs)); 180 this.accessibilityState = accessibilityState; 181 this.bypassUserDN = bypassUserDN; 182 } 183 184 185 186 /** 187 * Encodes the provided information for use as the extended request value. 188 * 189 * @param subtreeBaseDNs The set of base DNs for the target subtrees. 190 * It must not be {@code null} or empty. 191 * @param accessibilityState The accessibility state to use for the target 192 * subtrees. 193 * @param bypassUserDN The DN of a user that will be allowed to bypass 194 * restrictions on the target subtrees. 195 * 196 * @return An ASN.1 octet string containing the encoded value. 197 */ 198 @NotNull() 199 private static ASN1OctetString encodeValue( 200 @NotNull final Collection<String> subtreeBaseDNs, 201 @NotNull final SubtreeAccessibilityState accessibilityState, 202 @Nullable final String bypassUserDN) 203 { 204 final Iterator<String> dnIterator = subtreeBaseDNs.iterator(); 205 final String subtreeBaseDN = dnIterator.next(); 206 Validator.ensureNotNull(subtreeBaseDN); 207 208 final ArrayList<ASN1Element> elements = new ArrayList<>(4); 209 elements.add(new ASN1OctetString(subtreeBaseDN)); 210 elements.add(new ASN1Enumerated(accessibilityState.intValue())); 211 212 if (bypassUserDN != null) 213 { 214 elements.add(new ASN1OctetString(TYPE_BYPASS_USER_DN, bypassUserDN)); 215 } 216 217 if (dnIterator.hasNext()) 218 { 219 final ArrayList<ASN1Element> additionalDNElements = 220 new ArrayList<>(subtreeBaseDNs.size()-1); 221 while (dnIterator.hasNext()) 222 { 223 final String additionalDN = dnIterator.next(); 224 Validator.ensureNotNull(additionalDN); 225 additionalDNElements.add(new ASN1OctetString(additionalDN)); 226 } 227 elements.add(new ASN1Sequence(TYPE_ADDITIONAL_SUBTREE_BASE_DNS, 228 additionalDNElements)); 229 } 230 231 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 232 } 233 234 235 236 /** 237 * Creates a new set subtree accessibility extended request from the provided 238 * generic extended request. 239 * 240 * @param extendedRequest The generic extended request to use to create this 241 * set subtree accessibility extended request. 242 * 243 * @throws LDAPException If a problem occurs while decoding the request. 244 */ 245 public SetSubtreeAccessibilityExtendedRequest( 246 @NotNull final ExtendedRequest extendedRequest) 247 throws LDAPException 248 { 249 super(extendedRequest); 250 251 final ASN1OctetString value = extendedRequest.getValue(); 252 if (value == null) 253 { 254 throw new LDAPException(ResultCode.DECODING_ERROR, 255 ERR_SET_SUBTREE_ACCESSIBILITY_NO_VALUE.get()); 256 } 257 258 try 259 { 260 final ASN1Element[] elements = 261 ASN1Sequence.decodeAsSequence(value.getValue()).elements(); 262 263 final List<String> baseDNs = new ArrayList<>(10); 264 baseDNs.add(ASN1OctetString.decodeAsOctetString( 265 elements[0]).stringValue()); 266 267 final int accessibilityStateValue = 268 ASN1Enumerated.decodeAsEnumerated(elements[1]).intValue(); 269 accessibilityState = 270 SubtreeAccessibilityState.valueOf(accessibilityStateValue); 271 if (accessibilityState == null) 272 { 273 throw new LDAPException(ResultCode.DECODING_ERROR, 274 ERR_SET_SUBTREE_ACCESSIBILITY_INVALID_ACCESSIBILITY_STATE.get( 275 accessibilityStateValue)); 276 } 277 278 String bypassDN = null; 279 for (int i=2; i < elements.length; i++) 280 { 281 switch (elements[i].getType()) 282 { 283 case TYPE_BYPASS_USER_DN: 284 bypassDN = 285 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 286 break; 287 288 case TYPE_ADDITIONAL_SUBTREE_BASE_DNS: 289 for (final ASN1Element e : 290 ASN1Sequence.decodeAsSequence(elements[i]).elements()) 291 { 292 baseDNs.add(ASN1OctetString.decodeAsOctetString(e).stringValue()); 293 } 294 break; 295 296 default: 297 throw new LDAPException(ResultCode.DECODING_ERROR, 298 ERR_SET_SUBTREE_ACCESSIBILITY_INVALID_ELEMENT_TYPE.get( 299 StaticUtils.toHex(elements[i].getType()))); 300 } 301 } 302 bypassUserDN = bypassDN; 303 subtreeBaseDNs = Collections.unmodifiableList(baseDNs); 304 } 305 catch (final LDAPException le) 306 { 307 Debug.debugException(le); 308 throw le; 309 } 310 catch (final Exception e) 311 { 312 Debug.debugException(e); 313 throw new LDAPException(ResultCode.DECODING_ERROR, 314 ERR_SET_SUBTREE_ACCESSIBILITY_CANNOT_DECODE.get( 315 StaticUtils.getExceptionMessage(e)), 316 e); 317 } 318 319 320 if ((accessibilityState == SubtreeAccessibilityState.ACCESSIBLE) && 321 (bypassUserDN != null)) 322 { 323 throw new LDAPException(ResultCode.DECODING_ERROR, 324 ERR_SET_SUBTREE_ACCESSIBILITY_UNEXPECTED_BYPASS_DN.get( 325 accessibilityState.getStateName())); 326 } 327 328 if ((accessibilityState == SubtreeAccessibilityState.TO_BE_DELETED) && 329 (bypassUserDN == null)) 330 { 331 throw new LDAPException(ResultCode.DECODING_ERROR, 332 ERR_SET_SUBTREE_ACCESSIBILITY_MISSING_BYPASS_DN.get( 333 accessibilityState.getStateName())); 334 } 335 } 336 337 338 339 /** 340 * Creates a new set subtree accessibility extended request that will make the 341 * specified subtree accessible. 342 * 343 * @param subtreeBaseDN The base DN for the subtree to make accessible. It 344 * must not be {@code null}. 345 * @param controls The set of controls to include in the request. It 346 * may be {@code null} or empty if no controls are 347 * needed. 348 * 349 * @return The set subtree accessibility extended request that was created. 350 */ 351 @NotNull() 352 public static SetSubtreeAccessibilityExtendedRequest 353 createSetAccessibleRequest(@NotNull final String subtreeBaseDN, 354 @Nullable final Control... controls) 355 { 356 Validator.ensureNotNull(subtreeBaseDN); 357 358 return new SetSubtreeAccessibilityExtendedRequest( 359 Collections.singletonList(subtreeBaseDN), 360 SubtreeAccessibilityState.ACCESSIBLE, null, controls); 361 } 362 363 364 365 /** 366 * Creates a new set subtree accessibility extended request that will make the 367 * specified subtrees accessible. 368 * 369 * @param subtreeBaseDNs The base DNs for the subtrees to make accessible. 370 * It must not be {@code null} or empty. If multiple 371 * base DNs are specified, then all must reside below 372 * the same backend base DN. 373 * @param controls The set of controls to include in the request. It 374 * may be {@code null} or empty if no controls are 375 * needed. 376 * 377 * @return The set subtree accessibility extended request that was created. 378 */ 379 @NotNull() 380 public static SetSubtreeAccessibilityExtendedRequest 381 createSetAccessibleRequest( 382 @NotNull final Collection<String> subtreeBaseDNs, 383 @Nullable final Control... controls) 384 { 385 Validator.ensureNotNull(subtreeBaseDNs); 386 Validator.ensureFalse(subtreeBaseDNs.isEmpty()); 387 388 return new SetSubtreeAccessibilityExtendedRequest(subtreeBaseDNs, 389 SubtreeAccessibilityState.ACCESSIBLE, null, controls); 390 } 391 392 393 394 /** 395 * Creates a new set subtree accessibility extended request that will make the 396 * specified subtree read-only. 397 * 398 * @param subtreeBaseDN The base DN for the subtree to make read-only. It 399 * must not be {@code null}. 400 * @param allowBind Indicates whether users within the specified subtree 401 * will be allowed to bind. 402 * @param bypassUserDN The DN of a user that will be allowed to perform 403 * write (add, delete, modify, and modify DN) 404 * operations in the specified subtree. It may be 405 * {@code null} if no bypass user is needed. 406 * @param controls The set of controls to include in the request. It 407 * may be {@code null} or empty if no controls are 408 * needed. 409 * 410 * @return The set subtree accessibility extended request that was created. 411 */ 412 @NotNull() 413 public static SetSubtreeAccessibilityExtendedRequest 414 createSetReadOnlyRequest(@NotNull final String subtreeBaseDN, 415 final boolean allowBind, 416 @Nullable final String bypassUserDN, 417 @Nullable final Control... controls) 418 { 419 Validator.ensureNotNull(subtreeBaseDN); 420 421 if (allowBind) 422 { 423 return new SetSubtreeAccessibilityExtendedRequest( 424 Collections.singletonList(subtreeBaseDN), 425 SubtreeAccessibilityState.READ_ONLY_BIND_ALLOWED, bypassUserDN, 426 controls); 427 } 428 else 429 { 430 return new SetSubtreeAccessibilityExtendedRequest( 431 Collections.singletonList(subtreeBaseDN), 432 SubtreeAccessibilityState.READ_ONLY_BIND_DENIED, bypassUserDN, 433 controls); 434 } 435 } 436 437 438 439 /** 440 * Creates a new set subtree accessibility extended request that will make the 441 * specified subtrees read-only. 442 * 443 * @param subtreeBaseDNs The base DNs for the subtrees to make read-only. 444 * It must not be {@code null} or empty. If multiple 445 * base DNs are specified, then all must reside below 446 * the same backend base DN. 447 * @param allowBind Indicates whether users within the specified 448 * subtrees will be allowed to bind. 449 * @param bypassUserDN The DN of a user that will be allowed to perform 450 * write (add, delete, modify, and modify DN) 451 * operations in the specified subtrees. It may be 452 * {@code null} if no bypass user is needed. 453 * @param controls The set of controls to include in the request. It 454 * may be {@code null} or empty if no controls are 455 * needed. 456 * 457 * @return The set subtree accessibility extended request that was created. 458 */ 459 @NotNull() 460 public static SetSubtreeAccessibilityExtendedRequest 461 createSetReadOnlyRequest( 462 @NotNull final Collection<String> subtreeBaseDNs, 463 final boolean allowBind, 464 @Nullable final String bypassUserDN, 465 @Nullable final Control... controls) 466 { 467 Validator.ensureNotNull(subtreeBaseDNs); 468 Validator.ensureFalse(subtreeBaseDNs.isEmpty()); 469 470 if (allowBind) 471 { 472 return new SetSubtreeAccessibilityExtendedRequest(subtreeBaseDNs, 473 SubtreeAccessibilityState.READ_ONLY_BIND_ALLOWED, bypassUserDN, 474 controls); 475 } 476 else 477 { 478 return new SetSubtreeAccessibilityExtendedRequest(subtreeBaseDNs, 479 SubtreeAccessibilityState.READ_ONLY_BIND_DENIED, bypassUserDN, 480 controls); 481 } 482 } 483 484 485 486 /** 487 * Creates a new set subtree accessibility extended request that will make the 488 * specified subtree hidden. 489 * 490 * @param subtreeBaseDN The base DN for the subtree to make hidden. It must 491 * not be {@code null}. 492 * @param bypassUserDN The DN of a user that will be allowed to perform 493 * write (add, delete, modify, and modify DN) 494 * operations in the specified subtree. It may be 495 * {@code null} if no bypass user is needed. 496 * @param controls The set of controls to include in the request. It 497 * may be {@code null} or empty if no controls are 498 * needed. 499 * 500 * @return The set subtree accessibility extended request that was created. 501 */ 502 @NotNull() 503 public static SetSubtreeAccessibilityExtendedRequest 504 createSetHiddenRequest(@NotNull final String subtreeBaseDN, 505 @Nullable final String bypassUserDN, 506 @Nullable final Control... controls) 507 { 508 Validator.ensureNotNull(subtreeBaseDN); 509 510 return new SetSubtreeAccessibilityExtendedRequest( 511 Collections.singletonList(subtreeBaseDN), 512 SubtreeAccessibilityState.HIDDEN, bypassUserDN, controls); 513 } 514 515 516 517 /** 518 * Creates a new set subtree accessibility extended request that will make the 519 * specified subtrees hidden. 520 * 521 * @param subtreeBaseDNs The base DNs for the subtrees to make hidden. It 522 * must not be {@code null} or empty. If multiple 523 * base DNs are specified, then all must reside below 524 * the same backend base DN. 525 * @param bypassUserDN The DN of a user that will be allowed to perform 526 * write (add, delete, modify, and modify DN) 527 * operations in the specified subtrees. It may be 528 * {@code null} if no bypass user is needed. 529 * @param controls The set of controls to include in the request. It 530 * may be {@code null} or empty if no controls are 531 * needed. 532 * 533 * @return The set subtree accessibility extended request that was created. 534 */ 535 @NotNull() 536 public static SetSubtreeAccessibilityExtendedRequest 537 createSetHiddenRequest( 538 @NotNull final Collection<String> subtreeBaseDNs, 539 @Nullable final String bypassUserDN, 540 @Nullable final Control... controls) 541 { 542 Validator.ensureNotNull(subtreeBaseDNs); 543 Validator.ensureFalse(subtreeBaseDNs.isEmpty()); 544 545 return new SetSubtreeAccessibilityExtendedRequest(subtreeBaseDNs, 546 SubtreeAccessibilityState.HIDDEN, bypassUserDN, controls); 547 } 548 549 550 551 /** 552 * Creates a new set subtree accessibility extended request that will place 553 * the specified subtree in a to-be-deleted state. In this state, the 554 * subtree will exhibit the same characteristics as a hidden subtree, but with 555 * the added restriction that the accessibility state cannot be changed, and 556 * the restriction will only be removed when the base entry of the target 557 * subtree has been deleted. 558 * 559 * @param subtreeBaseDN The base DN for the subtree to mark as 560 * to-be-deleted. It must not be {@code null}. 561 * @param bypassUserDN The DN of a user that will be allowed to perform 562 * write (add, delete, modify, and modify DN) 563 * operations in the specified subtree. It must not be 564 * {@code null}. 565 * @param controls The set of controls to include in the request. It 566 * may be {@code null} or empty if no controls are 567 * needed. 568 * 569 * @return The set subtree accessibility extended request that was created. 570 */ 571 @NotNull() 572 public static SetSubtreeAccessibilityExtendedRequest 573 createSetToBeDeletedRequest(@NotNull final String subtreeBaseDN, 574 @NotNull final String bypassUserDN, 575 @Nullable final Control... controls) 576 { 577 Validator.ensureNotNull(subtreeBaseDN); 578 Validator.ensureNotNull(bypassUserDN); 579 580 return new SetSubtreeAccessibilityExtendedRequest( 581 Collections.singletonList(subtreeBaseDN), 582 SubtreeAccessibilityState.TO_BE_DELETED, bypassUserDN, controls); 583 } 584 585 586 587 /** 588 * Creates a new set subtree accessibility extended request that will place 589 * the specified subtrees in a to-be-deleted state. In this state, the 590 * subtrees will exhibit the same characteristics as hidden subtrees, but with 591 * the added restriction that the accessibility state cannot be changed, and 592 * the restriction will only be removed when the base entry of the target 593 * subtree has been deleted. 594 * 595 * @param subtreeBaseDNs The base DNs for the subtrees to make hidden. It 596 * must not be {@code null} or empty. If multiple 597 * base DNs are specified, then all must reside below 598 * the same backend base DN. 599 * @param bypassUserDN The DN of a user that will be allowed to perform 600 * write (add, delete, modify, and modify DN) 601 * operations in the specified subtrees. It must not 602 * be {@code null}. 603 * @param controls The set of controls to include in the request. It 604 * may be {@code null} or empty if no controls are 605 * needed. 606 * 607 * @return The set subtree accessibility extended request that was created. 608 */ 609 @NotNull() 610 public static SetSubtreeAccessibilityExtendedRequest 611 createSetToBeDeletedRequest( 612 @NotNull final Collection<String> subtreeBaseDNs, 613 @NotNull final String bypassUserDN, 614 @Nullable final Control... controls) 615 { 616 Validator.ensureNotNull(subtreeBaseDNs); 617 Validator.ensureFalse(subtreeBaseDNs.isEmpty()); 618 619 Validator.ensureNotNull(bypassUserDN); 620 621 return new SetSubtreeAccessibilityExtendedRequest(subtreeBaseDNs, 622 SubtreeAccessibilityState.TO_BE_DELETED, bypassUserDN, controls); 623 } 624 625 626 627 /** 628 * Retrieves the base DN for the target subtree. Note that if multiple 629 * base DNs are defined, this will only retrieve the first. The 630 * {@link #getSubtreeBaseDNs()} method should be used to get the complete set 631 * of target subtree base DNs. 632 * 633 * @return The base DN for the target subtree. 634 */ 635 @NotNull() 636 public String getSubtreeBaseDN() 637 { 638 return subtreeBaseDNs.get(0); 639 } 640 641 642 643 /** 644 * Retrieves the base DNs for all target subtrees. 645 * 646 * @return The base DNs for all target subtrees. 647 */ 648 @NotNull() 649 public List<String> getSubtreeBaseDNs() 650 { 651 return subtreeBaseDNs; 652 } 653 654 655 656 /** 657 * Retrieves the accessibility state to apply to the target subtrees. 658 * 659 * @return The accessibility state to apply to the target subtrees. 660 */ 661 @NotNull() 662 public SubtreeAccessibilityState getAccessibilityState() 663 { 664 return accessibilityState; 665 } 666 667 668 669 /** 670 * Retrieves the DN of the user that will be allowed to bypass the 671 * restrictions imposed on the target subtrees for all other users. 672 * 673 * @return The DN of the user that will be allowed to bypass the restrictions 674 * imposed on the target subtrees for all other users, or 675 * {@code null} if there are no restrictions to be imposed on the 676 * target subtrees or if no bypass user is defined for those 677 * subtrees. 678 */ 679 @Nullable() 680 public String getBypassUserDN() 681 { 682 return bypassUserDN; 683 } 684 685 686 687 /** 688 * {@inheritDoc} 689 */ 690 @Override() 691 @NotNull() 692 public SetSubtreeAccessibilityExtendedRequest duplicate() 693 { 694 return duplicate(getControls()); 695 } 696 697 698 699 /** 700 * {@inheritDoc} 701 */ 702 @Override() 703 @NotNull() 704 public SetSubtreeAccessibilityExtendedRequest duplicate( 705 @Nullable final Control[] controls) 706 { 707 final SetSubtreeAccessibilityExtendedRequest r = 708 new SetSubtreeAccessibilityExtendedRequest(subtreeBaseDNs, 709 accessibilityState, bypassUserDN, controls); 710 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 711 r.setIntermediateResponseListener(getIntermediateResponseListener()); 712 r.setReferralDepth(getReferralDepth()); 713 r.setReferralConnector(getReferralConnectorInternal()); 714 return r; 715 } 716 717 718 719 /** 720 * {@inheritDoc} 721 */ 722 @Override() 723 @NotNull() 724 public String getExtendedRequestName() 725 { 726 return INFO_EXTENDED_REQUEST_NAME_SET_SUBTREE_ACCESSIBILITY.get(); 727 } 728 729 730 731 /** 732 * {@inheritDoc} 733 */ 734 @Override() 735 public void toString(@NotNull final StringBuilder buffer) 736 { 737 buffer.append("SetSubtreeAccessibilityExtendedRequest(baseDNs={"); 738 739 final Iterator<String> dnIterator = subtreeBaseDNs.iterator(); 740 while (dnIterator.hasNext()) 741 { 742 buffer.append('"'); 743 buffer.append(dnIterator.next()); 744 buffer.append('"'); 745 746 if (dnIterator.hasNext()) 747 { 748 buffer.append(", "); 749 } 750 } 751 752 buffer.append("}, accessibilityType=\""); 753 buffer.append(accessibilityState.getStateName()); 754 buffer.append('"'); 755 756 if (bypassUserDN != null) 757 { 758 buffer.append(", bypassUserDN=\""); 759 buffer.append(bypassUserDN); 760 buffer.append('"'); 761 } 762 763 final Control[] controls = getControls(); 764 if (controls.length > 0) 765 { 766 buffer.append(", controls={"); 767 for (int i=0; i < controls.length; i++) 768 { 769 if (i > 0) 770 { 771 buffer.append(", "); 772 } 773 774 buffer.append(controls[i]); 775 } 776 buffer.append('}'); 777 } 778 779 buffer.append(')'); 780 } 781}