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 2010 Sun Microsystems, Inc. 015 * Portions copyright 2011-2015 ForgeRock AS. 016 */ 017 018package org.forgerock.opendj.ldap.requests; 019 020import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES; 021import static com.forgerock.opendj.util.StaticUtils.getBytes; 022import static com.forgerock.opendj.ldap.CoreMessages.WARN_READ_LDIF_RECORD_CHANGE_RECORD_WRONG_TYPE; 023 024import javax.net.ssl.SSLContext; 025import javax.security.auth.Subject; 026 027import org.forgerock.i18n.LocalizableMessage; 028import org.forgerock.i18n.LocalizedIllegalArgumentException; 029import org.forgerock.opendj.ldap.AttributeDescription; 030import org.forgerock.opendj.ldap.ByteString; 031import org.forgerock.opendj.ldap.DN; 032import org.forgerock.opendj.ldap.Entries; 033import org.forgerock.opendj.ldap.Entry; 034import org.forgerock.opendj.ldap.Filter; 035import org.forgerock.opendj.ldap.LinkedHashMapEntry; 036import org.forgerock.opendj.ldap.ModificationType; 037import org.forgerock.opendj.ldap.RDN; 038import org.forgerock.opendj.ldap.SearchScope; 039import org.forgerock.opendj.ldif.ChangeRecord; 040import org.forgerock.opendj.ldif.LDIFChangeRecordReader; 041import org.forgerock.util.Reject; 042 043/** 044 * This class contains various methods for creating and manipulating requests. 045 * <p> 046 * All copy constructors of the form {@code copyOfXXXRequest} perform deep 047 * copies of their request parameter. More specifically, any controls, 048 * modifications, and attributes contained within the response will be 049 * duplicated. 050 * <p> 051 * Similarly, all unmodifiable views of request returned by methods of the form 052 * {@code unmodifiableXXXRequest} return deep unmodifiable views of their 053 * request parameter. More specifically, any controls, modifications, and 054 * attributes contained within the returned request will be unmodifiable. 055 */ 056public final class Requests { 057 058 // TODO: search request from LDAP URL. 059 060 // TODO: update request from persistent search result. 061 062 // TODO: synchronized requests? 063 064 /** 065 * Creates a new abandon request that is an exact copy of the provided 066 * request. 067 * 068 * @param request 069 * The abandon request to be copied. 070 * @return The new abandon request. 071 * @throws NullPointerException 072 * If {@code request} was {@code null} 073 */ 074 public static AbandonRequest copyOfAbandonRequest(final AbandonRequest request) { 075 return new AbandonRequestImpl(request); 076 } 077 078 /** 079 * Creates a new add request that is an exact copy of the provided request. 080 * 081 * @param request 082 * The add request to be copied. 083 * @return The new add request. 084 * @throws NullPointerException 085 * If {@code request} was {@code null} . 086 */ 087 public static AddRequest copyOfAddRequest(final AddRequest request) { 088 return new AddRequestImpl(request); 089 } 090 091 /** 092 * Creates a new anonymous SASL bind request that is an exact copy of the 093 * provided request. 094 * 095 * @param request 096 * The anonymous SASL bind request to be copied. 097 * @return The new anonymous SASL bind request. 098 * @throws NullPointerException 099 * If {@code request} was {@code null} . 100 */ 101 public static AnonymousSASLBindRequest copyOfAnonymousSASLBindRequest( 102 final AnonymousSASLBindRequest request) { 103 return new AnonymousSASLBindRequestImpl(request); 104 } 105 106 /** 107 * Creates a new cancel extended request that is an exact copy of the 108 * provided request. 109 * 110 * @param request 111 * The cancel extended request to be copied. 112 * @return The new cancel extended request. 113 * @throws NullPointerException 114 * If {@code request} was {@code null} . 115 */ 116 public static CancelExtendedRequest copyOfCancelExtendedRequest( 117 final CancelExtendedRequest request) { 118 return new CancelExtendedRequestImpl(request); 119 } 120 121 /** 122 * Creates a new compare request that is an exact copy of the provided 123 * request. 124 * 125 * @param request 126 * The compare request to be copied. 127 * @return The new compare request. 128 * @throws NullPointerException 129 * If {@code request} was {@code null} . 130 */ 131 public static CompareRequest copyOfCompareRequest(final CompareRequest request) { 132 return new CompareRequestImpl(request); 133 } 134 135 /** 136 * Creates a new CRAM MD5 SASL bind request that is an exact copy of the 137 * provided request. 138 * 139 * @param request 140 * The CRAM MD5 SASL bind request to be copied. 141 * @return The new CRAM-MD5 SASL bind request. 142 * @throws NullPointerException 143 * If {@code request} was {@code null}. 144 */ 145 public static CRAMMD5SASLBindRequest copyOfCRAMMD5SASLBindRequest( 146 final CRAMMD5SASLBindRequest request) { 147 return new CRAMMD5SASLBindRequestImpl(request); 148 } 149 150 /** 151 * Creates a new delete request that is an exact copy of the provided 152 * request. 153 * 154 * @param request 155 * The add request to be copied. 156 * @return The new delete request. 157 * @throws NullPointerException 158 * If {@code request} was {@code null}. 159 */ 160 public static DeleteRequest copyOfDeleteRequest(final DeleteRequest request) { 161 return new DeleteRequestImpl(request); 162 } 163 164 /** 165 * Creates a new digest MD5 SASL bind request that is an exact copy of the 166 * provided request. 167 * 168 * @param request 169 * The digest MD5 SASL bind request to be copied. 170 * @return The new DIGEST-MD5 SASL bind request. 171 * @throws NullPointerException 172 * If {@code request} was {@code null}. 173 */ 174 public static DigestMD5SASLBindRequest copyOfDigestMD5SASLBindRequest( 175 final DigestMD5SASLBindRequest request) { 176 return new DigestMD5SASLBindRequestImpl(request); 177 } 178 179 /** 180 * Creates a new external SASL bind request that is an exact copy of the 181 * provided request. 182 * 183 * @param request 184 * The external SASL bind request to be copied. 185 * @return The new External SASL bind request. 186 * @throws NullPointerException 187 * If {@code request} was {@code null} . 188 */ 189 public static ExternalSASLBindRequest copyOfExternalSASLBindRequest( 190 final ExternalSASLBindRequest request) { 191 return new ExternalSASLBindRequestImpl(request); 192 } 193 194 /** 195 * Creates a new generic bind request that is an exact copy of the provided 196 * request. 197 * 198 * @param request 199 * The generic bind request to be copied. 200 * @return The new generic bind request. 201 * @throws NullPointerException 202 * If {@code request} was {@code null} . 203 */ 204 public static GenericBindRequest copyOfGenericBindRequest(final GenericBindRequest request) { 205 return new GenericBindRequestImpl(request); 206 } 207 208 /** 209 * Creates a new generic extended request that is an exact copy of the 210 * provided request. 211 * 212 * @param request 213 * The generic extended request to be copied. 214 * @return The new generic extended request. 215 * @throws NullPointerException 216 * If {@code request} was {@code null} . 217 */ 218 public static GenericExtendedRequest copyOfGenericExtendedRequest( 219 final GenericExtendedRequest request) { 220 return new GenericExtendedRequestImpl(request); 221 } 222 223 /** 224 * Creates a new GSSAPI SASL bind request that is an exact copy of the 225 * provided request. 226 * 227 * @param request 228 * The GSSAPI SASL bind request to be copied. 229 * @return The new GSSAPI SASL bind request. 230 * @throws NullPointerException 231 * If {@code request} was {@code null}. 232 */ 233 public static GSSAPISASLBindRequest copyOfGSSAPISASLBindRequest( 234 final GSSAPISASLBindRequest request) { 235 return new GSSAPISASLBindRequestImpl(request); 236 } 237 238 /** 239 * Creates a new modify DN request that is an exact copy of the provided 240 * request. 241 * 242 * @param request 243 * The modify DN request to be copied. 244 * @return The new modify DN request. 245 * @throws NullPointerException 246 * If {@code request} was {@code null} . 247 */ 248 public static ModifyDNRequest copyOfModifyDNRequest(final ModifyDNRequest request) { 249 return new ModifyDNRequestImpl(request); 250 } 251 252 /** 253 * Creates a new modify request that is an exact copy of the provided 254 * request. 255 * 256 * @param request 257 * The modify request to be copied. 258 * @return The new modify request. 259 * @throws NullPointerException 260 * If {@code request} was {@code null} . 261 */ 262 public static ModifyRequest copyOfModifyRequest(final ModifyRequest request) { 263 return new ModifyRequestImpl(request); 264 } 265 266 /** 267 * Creates a new password modify extended request that is an exact copy of 268 * the provided request. 269 * 270 * @param request 271 * The password modify extended request to be copied. 272 * @return The new password modify extended request. 273 * @throws NullPointerException 274 * If {@code request} was {@code null} . 275 */ 276 public static PasswordModifyExtendedRequest copyOfPasswordModifyExtendedRequest( 277 final PasswordModifyExtendedRequest request) { 278 return new PasswordModifyExtendedRequestImpl(request); 279 } 280 281 /** 282 * Creates a new plain SASL bind request that is an exact copy of the 283 * provided request. 284 * 285 * @param request 286 * The plain SASL bind request to be copied. 287 * @return The new Plain SASL bind request. 288 * @throws NullPointerException 289 * If {@code request} was {@code null} . 290 */ 291 public static PlainSASLBindRequest copyOfPlainSASLBindRequest(final PlainSASLBindRequest request) { 292 return new PlainSASLBindRequestImpl(request); 293 } 294 295 /** 296 * Creates a new search request that is an exact copy of the provided 297 * request. 298 * 299 * @param request 300 * The search request to be copied. 301 * @return The new search request. 302 * @throws NullPointerException 303 * If {@code request} was {@code null} . 304 */ 305 public static SearchRequest copyOfSearchRequest(final SearchRequest request) { 306 return new SearchRequestImpl(request); 307 } 308 309 /** 310 * Creates a new simple bind request that is an exact copy of the provided 311 * request. 312 * 313 * @param request 314 * The simple bind request to be copied. 315 * @return The new simple bind request. 316 * @throws NullPointerException 317 * If {@code request} was {@code null} . 318 */ 319 public static SimpleBindRequest copyOfSimpleBindRequest(final SimpleBindRequest request) { 320 return new SimpleBindRequestImpl(request); 321 } 322 323 /** 324 * Creates a new startTLS extended request that is an exact copy of the 325 * provided request. 326 * 327 * @param request 328 * The startTLS extended request to be copied. 329 * @return The new start TLS extended request. 330 * @throws NullPointerException 331 * If {@code request} was {@code null} . 332 */ 333 public static StartTLSExtendedRequest copyOfStartTLSExtendedRequest( 334 final StartTLSExtendedRequest request) { 335 return new StartTLSExtendedRequestImpl(request); 336 } 337 338 /** 339 * Creates a new unbind request that is an exact copy of the provided 340 * request. 341 * 342 * @param request 343 * The unbind request to be copied. 344 * @return The new unbind request. 345 * @throws NullPointerException 346 * If {@code request} was {@code null} . 347 */ 348 public static UnbindRequest copyOfUnbindRequest(final UnbindRequest request) { 349 return new UnbindRequestImpl(request); 350 } 351 352 /** 353 * Creates a new Who Am I extended request that is an exact copy of the 354 * provided request. 355 * 356 * @param request 357 * The who Am I extended request to be copied. 358 * @return The new Who Am I extended request. 359 * @throws NullPointerException 360 * If {@code request} was {@code null} . 361 */ 362 public static WhoAmIExtendedRequest copyOfWhoAmIExtendedRequest( 363 final WhoAmIExtendedRequest request) { 364 return new WhoAmIExtendedRequestImpl(request); 365 } 366 367 /** 368 * Creates a new abandon request using the provided message ID. 369 * 370 * @param requestID 371 * The request ID of the request to be abandoned. 372 * @return The new abandon request. 373 */ 374 public static AbandonRequest newAbandonRequest(final int requestID) { 375 return new AbandonRequestImpl(requestID); 376 } 377 378 /** 379 * Creates a new add request using the provided distinguished name. 380 * 381 * @param name 382 * The distinguished name of the entry to be added. 383 * @return The new add request. 384 * @throws NullPointerException 385 * If {@code name} was {@code null}. 386 */ 387 public static AddRequest newAddRequest(final DN name) { 388 final Entry entry = new LinkedHashMapEntry().setName(name); 389 return new AddRequestImpl(entry); 390 } 391 392 /** 393 * Creates a new add request backed by the provided entry. Modifications 394 * made to {@code entry} will be reflected in the returned add request. The 395 * returned add request supports updates to its list of controls, as well as 396 * updates to the name and attributes if the underlying entry allows. 397 * 398 * @param entry 399 * The entry to be added. 400 * @return The new add request. 401 * @throws NullPointerException 402 * If {@code entry} was {@code null} . 403 */ 404 public static AddRequest newAddRequest(final Entry entry) { 405 Reject.ifNull(entry); 406 return new AddRequestImpl(entry); 407 } 408 409 /** 410 * Creates a new add request using the provided distinguished name decoded 411 * using the default schema. 412 * 413 * @param name 414 * The distinguished name of the entry to be added. 415 * @return The new add request. 416 * @throws LocalizedIllegalArgumentException 417 * If {@code name} could not be decoded using the default 418 * schema. 419 * @throws NullPointerException 420 * If {@code name} was {@code null}. 421 */ 422 public static AddRequest newAddRequest(final String name) { 423 final Entry entry = new LinkedHashMapEntry().setName(name); 424 return new AddRequestImpl(entry); 425 } 426 427 /** 428 * Creates a new add request using the provided lines of LDIF decoded using 429 * the default schema. 430 * 431 * @param ldifLines 432 * Lines of LDIF containing an LDIF add change record or an LDIF 433 * entry record. 434 * @return The new add request. 435 * @throws LocalizedIllegalArgumentException 436 * If {@code ldifLines} was empty, or contained invalid LDIF, or 437 * could not be decoded using the default schema. 438 * @throws NullPointerException 439 * If {@code ldifLines} was {@code null} . 440 */ 441 public static AddRequest newAddRequest(final String... ldifLines) { 442 // LDIF change record reader is tolerant to missing change types. 443 final ChangeRecord record = LDIFChangeRecordReader.valueOfLDIFChangeRecord(ldifLines); 444 445 if (record instanceof AddRequest) { 446 return (AddRequest) record; 447 } else { 448 // Wrong change type. 449 final LocalizableMessage message = 450 WARN_READ_LDIF_RECORD_CHANGE_RECORD_WRONG_TYPE.get("add"); 451 throw new LocalizedIllegalArgumentException(message); 452 } 453 } 454 455 /** 456 * Creates a new anonymous SASL bind request having the provided trace 457 * string. 458 * 459 * @param traceString 460 * The trace information, which has no semantic value, and can be 461 * used by administrators in order to identify the user. 462 * @return The new anonymous SASL bind request. 463 * @throws NullPointerException 464 * If {@code traceString} was {@code null}. 465 */ 466 public static AnonymousSASLBindRequest newAnonymousSASLBindRequest(final String traceString) { 467 return new AnonymousSASLBindRequestImpl(traceString); 468 } 469 470 /** 471 * Creates a new cancel extended request using the provided message ID. 472 * 473 * @param requestID 474 * The request ID of the request to be abandoned. 475 * @return The new cancel extended request. 476 */ 477 public static CancelExtendedRequest newCancelExtendedRequest(final int requestID) { 478 return new CancelExtendedRequestImpl(requestID); 479 } 480 481 /** 482 * Creates a new change record (an add, delete, modify, or modify DN 483 * request) using the provided lines of LDIF decoded using the default 484 * schema. 485 * 486 * @param ldifLines 487 * Lines of LDIF containing an LDIF change record or an LDIF 488 * entry record. 489 * @return The new change record. 490 * @throws LocalizedIllegalArgumentException 491 * If {@code ldifLines} was empty, or contained invalid LDIF, or 492 * could not be decoded using the default schema. 493 * @throws NullPointerException 494 * If {@code ldifLines} was {@code null} . 495 */ 496 public static ChangeRecord newChangeRecord(final String... ldifLines) { 497 // LDIF change record reader is tolerant to missing change types. 498 return LDIFChangeRecordReader.valueOfLDIFChangeRecord(ldifLines); 499 } 500 501 /** 502 * Creates a new compare request using the provided distinguished name, 503 * attribute name, and assertion value. 504 * <p> 505 * If the assertion value is not an instance of {@code ByteString} then it 506 * will be converted using the {@link ByteString#valueOfObject(Object)} method. 507 * 508 * @param name 509 * The distinguished name of the entry to be compared. 510 * @param attributeDescription 511 * The name of the attribute to be compared. 512 * @param assertionValue 513 * The assertion value to be compared. 514 * @return The new compare request. 515 * @throws NullPointerException 516 * If {@code name}, {@code attributeDescription}, or 517 * {@code assertionValue} was {@code null}. 518 */ 519 public static CompareRequest newCompareRequest(final DN name, 520 final AttributeDescription attributeDescription, final Object assertionValue) { 521 Reject.ifNull(name, attributeDescription, assertionValue); 522 return new CompareRequestImpl(name, attributeDescription, ByteString 523 .valueOfObject(assertionValue)); 524 } 525 526 /** 527 * Creates a new compare request using the provided distinguished name, 528 * attribute name, and assertion value decoded using the default schema. 529 * <p> 530 * If the assertion value is not an instance of {@code ByteString} then it 531 * will be converted using the {@link ByteString#valueOfObject(Object)} method. 532 * 533 * @param name 534 * The distinguished name of the entry to be compared. 535 * @param attributeDescription 536 * The name of the attribute to be compared. 537 * @param assertionValue 538 * The assertion value to be compared. 539 * @return The new compare request. 540 * @throws LocalizedIllegalArgumentException 541 * If {@code name} or {@code attributeDescription} could not be 542 * decoded using the default schema. 543 * @throws NullPointerException 544 * If {@code name}, {@code attributeDescription}, or 545 * {@code assertionValue} was {@code null}. 546 */ 547 public static CompareRequest newCompareRequest(final String name, 548 final String attributeDescription, final Object assertionValue) { 549 Reject.ifNull(name, attributeDescription, assertionValue); 550 return new CompareRequestImpl(DN.valueOf(name), AttributeDescription 551 .valueOf(attributeDescription), ByteString.valueOfObject(assertionValue)); 552 } 553 554 /** 555 * Creates a new CRAM-MD5 SASL bind request having the provided 556 * authentication ID and password. 557 * 558 * @param authenticationID 559 * The authentication ID of the user. The authentication ID 560 * usually has the form "dn:" immediately followed by the 561 * distinguished name of the user, or "u:" followed by a user ID 562 * string, but other forms are permitted. 563 * @param password 564 * The password of the user that the client wishes to bind as. 565 * @return The new CRAM-MD5 SASL bind request. 566 * @throws NullPointerException 567 * If {@code authenticationID} or {@code password} was 568 * {@code null}. 569 */ 570 public static CRAMMD5SASLBindRequest newCRAMMD5SASLBindRequest(final String authenticationID, 571 final byte[] password) { 572 return new CRAMMD5SASLBindRequestImpl(authenticationID, password); 573 } 574 575 /** 576 * Creates a new CRAM-MD5 SASL bind request having the provided 577 * authentication ID and password. 578 * 579 * @param authenticationID 580 * The authentication ID of the user. The authentication ID 581 * usually has the form "dn:" immediately followed by the 582 * distinguished name of the user, or "u:" followed by a user ID 583 * string, but other forms are permitted. 584 * @param password 585 * The password of the user that the client wishes to bind as. 586 * The password will be converted to a UTF-8 octet string. 587 * @return The new CRAM-MD5 SASL bind request. 588 * @throws NullPointerException 589 * If {@code authenticationID} or {@code password} was 590 * {@code null}. 591 */ 592 public static CRAMMD5SASLBindRequest newCRAMMD5SASLBindRequest(final String authenticationID, 593 final char[] password) { 594 return new CRAMMD5SASLBindRequestImpl(authenticationID, getBytes(password)); 595 } 596 597 /** 598 * Creates a new delete request using the provided distinguished name. 599 * 600 * @param name 601 * The distinguished name of the entry to be deleted. 602 * @return The new delete request. 603 * @throws NullPointerException 604 * If {@code name} was {@code null}. 605 */ 606 public static DeleteRequest newDeleteRequest(final DN name) { 607 Reject.ifNull(name); 608 return new DeleteRequestImpl(name); 609 } 610 611 /** 612 * Creates a new delete request using the provided distinguished name 613 * decoded using the default schema. 614 * 615 * @param name 616 * The distinguished name of the entry to be deleted. 617 * @return The new delete request. 618 * @throws LocalizedIllegalArgumentException 619 * If {@code name} could not be decoded using the default 620 * schema. 621 * @throws NullPointerException 622 * If {@code name} was {@code null}. 623 */ 624 public static DeleteRequest newDeleteRequest(final String name) { 625 Reject.ifNull(name); 626 return new DeleteRequestImpl(DN.valueOf(name)); 627 } 628 629 /** 630 * Creates a new DIGEST-MD5 SASL bind request having the provided 631 * authentication ID and password, but no realm or authorization ID. 632 * 633 * @param authenticationID 634 * The authentication ID of the user. The authentication ID 635 * usually has the form "dn:" immediately followed by the 636 * distinguished name of the user, or "u:" followed by a user ID 637 * string, but other forms are permitted. 638 * @param password 639 * The password of the user that the client wishes to bind as. 640 * @return The new DIGEST-MD5 SASL bind request. 641 * @throws NullPointerException 642 * If {@code authenticationID} or {@code password} was 643 * {@code null}. 644 */ 645 public static DigestMD5SASLBindRequest newDigestMD5SASLBindRequest( 646 final String authenticationID, final byte[] password) { 647 return new DigestMD5SASLBindRequestImpl(authenticationID, password); 648 } 649 650 /** 651 * Creates a new DIGEST-MD5 SASL bind request having the provided 652 * authentication ID and password, but no realm or authorization ID. 653 * 654 * @param authenticationID 655 * The authentication ID of the user. The authentication ID 656 * usually has the form "dn:" immediately followed by the 657 * distinguished name of the user, or "u:" followed by a user ID 658 * string, but other forms are permitted. 659 * @param password 660 * The password of the user that the client wishes to bind as. 661 * The password will be converted to a UTF-8 octet string. 662 * @return The new DIGEST-MD5 SASL bind request. 663 * @throws NullPointerException 664 * If {@code authenticationID} or {@code password} was 665 * {@code null}. 666 */ 667 public static DigestMD5SASLBindRequest newDigestMD5SASLBindRequest( 668 final String authenticationID, final char[] password) { 669 return new DigestMD5SASLBindRequestImpl(authenticationID, getBytes(password)); 670 } 671 672 /** 673 * Creates a new External SASL bind request with no authorization ID. 674 * 675 * @return The new External SASL bind request. 676 */ 677 public static ExternalSASLBindRequest newExternalSASLBindRequest() { 678 return new ExternalSASLBindRequestImpl(); 679 } 680 681 /** 682 * Creates a new generic bind request using an empty distinguished name, 683 * authentication type, and authentication information. 684 * 685 * @param authenticationType 686 * The authentication mechanism identifier for this generic bind 687 * request. 688 * @param authenticationValue 689 * The authentication information for this generic bind request 690 * in a form defined by the authentication mechanism. 691 * @return The new generic bind request. 692 * @throws NullPointerException 693 * If {@code authenticationValue} was {@code null}. 694 */ 695 public static GenericBindRequest newGenericBindRequest(final byte authenticationType, 696 final byte[] authenticationValue) { 697 Reject.ifNull(authenticationValue); 698 return new GenericBindRequestImpl("", authenticationType, authenticationValue); 699 } 700 701 /** 702 * Creates a new generic bind request using the provided name, 703 * authentication type, and authentication information. 704 * <p> 705 * The LDAP protocol defines the Bind name to be a distinguished name, 706 * however some LDAP implementations have relaxed this constraint and allow 707 * other identities to be used, such as the user's email address. 708 * 709 * @param name 710 * The name of the Directory object that the client wishes to 711 * bind as (may be empty). 712 * @param authenticationType 713 * The authentication mechanism identifier for this generic bind 714 * request. 715 * @param authenticationValue 716 * The authentication information for this generic bind request 717 * in a form defined by the authentication mechanism. 718 * @return The new generic bind request. 719 * @throws NullPointerException 720 * If {@code name} or {@code authenticationValue} was 721 * {@code null}. 722 */ 723 public static GenericBindRequest newGenericBindRequest(final String name, 724 final byte authenticationType, final byte[] authenticationValue) { 725 Reject.ifNull(name, authenticationValue); 726 return new GenericBindRequestImpl(name, authenticationType, authenticationValue); 727 } 728 729 /** 730 * Creates a new generic extended request using the provided name and no 731 * value. 732 * 733 * @param requestName 734 * The dotted-decimal representation of the unique OID 735 * corresponding to this extended request. 736 * @return The new generic extended request. 737 * @throws NullPointerException 738 * If {@code requestName} was {@code null}. 739 */ 740 public static GenericExtendedRequest newGenericExtendedRequest(final String requestName) { 741 Reject.ifNull(requestName); 742 return new GenericExtendedRequestImpl(requestName); 743 } 744 745 /** 746 * Creates a new generic extended request using the provided name and 747 * optional value. 748 * <p> 749 * If the request value is not an instance of {@code ByteString} then it 750 * will be converted using the {@link ByteString#valueOfObject(Object)} method. 751 * 752 * @param requestName 753 * The dotted-decimal representation of the unique OID 754 * corresponding to this extended request. 755 * @param requestValue 756 * The content of this generic extended request in a form defined 757 * by the extended operation, or {@code null} if there is no 758 * content. 759 * @return The new generic extended request. 760 * @throws NullPointerException 761 * If {@code requestName} was {@code null}. 762 */ 763 public static GenericExtendedRequest newGenericExtendedRequest(final String requestName, 764 final Object requestValue) { 765 Reject.ifNull(requestName); 766 return new GenericExtendedRequestImpl(requestName).setValue(requestValue); 767 } 768 769 /** 770 * Creates a new GSSAPI SASL bind request having the provided authentication 771 * ID and password, but no realm, KDC address, or authorization ID. 772 * 773 * @param authenticationID 774 * The authentication ID of the user. The authentication ID 775 * usually has the form "dn:" immediately followed by the 776 * distinguished name of the user, or "u:" followed by a user ID 777 * string, but other forms are permitted. 778 * @param password 779 * The password of the user that the client wishes to bind as. 780 * @return The new GSSAPI SASL bind request. 781 * @throws NullPointerException 782 * If {@code authenticationID} or {@code password} was 783 * {@code null}. 784 */ 785 public static GSSAPISASLBindRequest newGSSAPISASLBindRequest(final String authenticationID, 786 final byte[] password) { 787 return new GSSAPISASLBindRequestImpl(authenticationID, password); 788 } 789 790 /** 791 * Creates a new GSSAPI SASL bind request having the provided authentication 792 * ID and password, but no realm, KDC address, or authorization ID. 793 * 794 * @param authenticationID 795 * The authentication ID of the user. The authentication ID 796 * usually has the form "dn:" immediately followed by the 797 * distinguished name of the user, or "u:" followed by a user ID 798 * string, but other forms are permitted. 799 * @param password 800 * The password of the user that the client wishes to bind as. 801 * The password will be converted to a UTF-8 octet string. 802 * @return The new GSSAPI SASL bind request. 803 * @throws NullPointerException 804 * If {@code authenticationID} or {@code password} was 805 * {@code null}. 806 */ 807 public static GSSAPISASLBindRequest newGSSAPISASLBindRequest(final String authenticationID, 808 final char[] password) { 809 return new GSSAPISASLBindRequestImpl(authenticationID, getBytes(password)); 810 } 811 812 /** 813 * Creates a new GSSAPI SASL bind request having the provided subject, but 814 * no authorization ID. 815 * 816 * @param subject 817 * The Kerberos subject of the user to be authenticated. 818 * @return The new GSSAPI SASL bind request. 819 * @throws NullPointerException 820 * If {@code subject} was {@code null}. 821 */ 822 public static GSSAPISASLBindRequest newGSSAPISASLBindRequest(final Subject subject) { 823 return new GSSAPISASLBindRequestImpl(subject); 824 } 825 826 /** 827 * Creates a new modify DN request using the provided distinguished name and 828 * new RDN. The new superior will be {@code null}, indicating that the 829 * renamed entry will remain under the same parent entry, and the old RDN 830 * attribute values will not be deleted. 831 * 832 * @param name 833 * The distinguished name of the entry to be renamed. 834 * @param newRDN 835 * The new RDN of the entry. 836 * @return The new modify DN request. 837 * @throws NullPointerException 838 * If {@code name} or {@code newRDN} was {@code null}. 839 */ 840 public static ModifyDNRequest newModifyDNRequest(final DN name, final RDN newRDN) { 841 Reject.ifNull(name); 842 Reject.ifNull(newRDN); 843 return new ModifyDNRequestImpl(name, newRDN); 844 } 845 846 /** 847 * Creates a new modify DN request using the provided distinguished name and 848 * new RDN decoded using the default schema. The new superior will be 849 * {@code null}, indicating that the renamed entry will remain under the 850 * same parent entry, and the old RDN attribute values will not be deleted. 851 * 852 * @param name 853 * The distinguished name of the entry to be renamed. 854 * @param newRDN 855 * The new RDN of the entry. 856 * @return The new modify DN request. 857 * @throws LocalizedIllegalArgumentException 858 * If {@code name} or {@code newRDN} could not be decoded using 859 * the default schema. 860 * @throws NullPointerException 861 * If {@code name} or {@code newRDN} was {@code null}. 862 */ 863 public static ModifyDNRequest newModifyDNRequest(final String name, final String newRDN) { 864 Reject.ifNull(name, newRDN); 865 return new ModifyDNRequestImpl(DN.valueOf(name), RDN.valueOf(newRDN)); 866 } 867 868 /** 869 * Creates a new modify request using the provided distinguished name. 870 * 871 * @param name 872 * The distinguished name of the entry to be modified. 873 * @return The new modify request. 874 * @throws NullPointerException 875 * If {@code name} was {@code null}. 876 */ 877 public static ModifyRequest newModifyRequest(final DN name) { 878 Reject.ifNull(name); 879 return new ModifyRequestImpl(name); 880 } 881 882 /** 883 * Creates a new modify request containing a list of modifications which can 884 * be used to transform {@code fromEntry} into entry {@code toEntry}. 885 * <p> 886 * The changes will be generated using a default set of 887 * {@link org.forgerock.opendj.ldap.Entries.DiffOptions options}. More 888 * specifically, only user attributes will be compared, attributes will be 889 * compared using their matching rules, and all generated changes will be 890 * reversible: it will contain only modifications of type 891 * {@link ModificationType#DELETE DELETE} then {@link ModificationType#ADD 892 * ADD}. 893 * <p> 894 * Finally, the modify request will use the distinguished name taken from 895 * {@code fromEntry}. Moreover, this method will not check to see if both 896 * {@code fromEntry} and {@code toEntry} have the same distinguished name. 897 * <p> 898 * This method is equivalent to: 899 * 900 * <pre> 901 * ModifyRequest request = Entries.diffEntries(fromEntry, toEntry); 902 * </pre> 903 * 904 * Or: 905 * 906 * <pre> 907 * ModifyRequest request = Entries.diffEntries(fromEntry, toEntry, Entries.diffOptions()); 908 * </pre> 909 * 910 * @param fromEntry 911 * The source entry. 912 * @param toEntry 913 * The destination entry. 914 * @return A modify request containing a list of modifications which can be 915 * used to transform {@code fromEntry} into entry {@code toEntry}. 916 * The returned request will always be non-{@code null} but may not 917 * contain any modifications. 918 * @throws NullPointerException 919 * If {@code fromEntry} or {@code toEntry} were {@code null}. 920 * @see Entries#diffEntries(Entry, Entry) 921 */ 922 public static ModifyRequest newModifyRequest(final Entry fromEntry, final Entry toEntry) { 923 return Entries.diffEntries(fromEntry, toEntry); 924 } 925 926 /** 927 * Creates a new modify request using the provided distinguished name 928 * decoded using the default schema. 929 * 930 * @param name 931 * The distinguished name of the entry to be modified. 932 * @return The new modify request. 933 * @throws LocalizedIllegalArgumentException 934 * If {@code name} could not be decoded using the default 935 * schema. 936 * @throws NullPointerException 937 * If {@code name} was {@code null}. 938 */ 939 public static ModifyRequest newModifyRequest(final String name) { 940 Reject.ifNull(name); 941 return new ModifyRequestImpl(DN.valueOf(name)); 942 } 943 944 /** 945 * Creates a new modify request using the provided lines of LDIF decoded 946 * using the default schema. 947 * 948 * @param ldifLines 949 * Lines of LDIF containing a single LDIF modify change record. 950 * @return The new modify request. 951 * @throws LocalizedIllegalArgumentException 952 * If {@code ldifLines} was empty, or contained invalid LDIF, or 953 * could not be decoded using the default schema. 954 * @throws NullPointerException 955 * If {@code ldifLines} was {@code null} . 956 */ 957 public static ModifyRequest newModifyRequest(final String... ldifLines) { 958 // LDIF change record reader is tolerant to missing change types. 959 final ChangeRecord record = LDIFChangeRecordReader.valueOfLDIFChangeRecord(ldifLines); 960 961 if (record instanceof ModifyRequest) { 962 return (ModifyRequest) record; 963 } else { 964 // Wrong change type. 965 final LocalizableMessage message = 966 WARN_READ_LDIF_RECORD_CHANGE_RECORD_WRONG_TYPE.get("modify"); 967 throw new LocalizedIllegalArgumentException(message); 968 } 969 } 970 971 /** 972 * Creates a new password modify extended request, with no user identity, 973 * old password, or new password. 974 * 975 * @return The new password modify extended request. 976 */ 977 public static PasswordModifyExtendedRequest newPasswordModifyExtendedRequest() { 978 return new PasswordModifyExtendedRequestImpl(); 979 } 980 981 /** 982 * Creates a new Plain SASL bind request having the provided authentication 983 * ID and password, but no authorization ID. 984 * 985 * @param authenticationID 986 * The authentication ID of the user. The authentication ID 987 * usually has the form "dn:" immediately followed by the 988 * distinguished name of the user, or "u:" followed by a user ID 989 * string, but other forms are permitted. 990 * @param password 991 * The password of the user that the client wishes to bind as. 992 * @return The new Plain SASL bind request. 993 * @throws NullPointerException 994 * If {@code authenticationID} or {@code password} was 995 * {@code null}. 996 */ 997 public static PlainSASLBindRequest newPlainSASLBindRequest(final String authenticationID, 998 final byte[] password) { 999 return new PlainSASLBindRequestImpl(authenticationID, password); 1000 } 1001 1002 /** 1003 * Creates a new Plain SASL bind request having the provided authentication 1004 * ID and password, but no authorization ID. 1005 * 1006 * @param authenticationID 1007 * The authentication ID of the user. The authentication ID 1008 * usually has the form "dn:" immediately followed by the 1009 * distinguished name of the user, or "u:" followed by a user ID 1010 * string, but other forms are permitted. 1011 * @param password 1012 * The password of the user that the client wishes to bind as. 1013 * The password will be converted to a UTF-8 octet string. 1014 * @return The new Plain SASL bind request. 1015 * @throws NullPointerException 1016 * If {@code authenticationID} or {@code password} was 1017 * {@code null}. 1018 */ 1019 public static PlainSASLBindRequest newPlainSASLBindRequest(final String authenticationID, 1020 final char[] password) { 1021 return new PlainSASLBindRequestImpl(authenticationID, getBytes(password)); 1022 } 1023 1024 /** 1025 * Creates a new search request using the provided distinguished name, 1026 * scope, and filter. 1027 * 1028 * @param name 1029 * The distinguished name of the base entry relative to which the 1030 * search is to be performed. 1031 * @param scope 1032 * The scope of the search. 1033 * @param filter 1034 * The filter that defines the conditions that must be fulfilled 1035 * in order for an entry to be returned. 1036 * @param attributeDescriptions 1037 * The names of the attributes to be included with each entry. 1038 * @return The new search request. 1039 * @throws NullPointerException 1040 * If the {@code name}, {@code scope}, or {@code filter} were 1041 * {@code null}. 1042 */ 1043 public static SearchRequest newSearchRequest(final DN name, final SearchScope scope, 1044 final Filter filter, final String... attributeDescriptions) { 1045 Reject.ifNull(name, scope, filter); 1046 final SearchRequest request = new SearchRequestImpl(name, scope, filter); 1047 for (final String attributeDescription : attributeDescriptions) { 1048 request.addAttribute(attributeDescription); 1049 } 1050 return request; 1051 } 1052 1053 /** 1054 * Creates a new search request using the provided distinguished name, 1055 * scope, and filter, decoded using the default schema. 1056 * 1057 * @param name 1058 * The distinguished name of the base entry relative to which the 1059 * search is to be performed. 1060 * @param scope 1061 * The scope of the search. 1062 * @param filter 1063 * The filter that defines the conditions that must be fulfilled 1064 * in order for an entry to be returned. 1065 * @param attributeDescriptions 1066 * The names of the attributes to be included with each entry. 1067 * @return The new search request. 1068 * @throws LocalizedIllegalArgumentException 1069 * If {@code name} could not be decoded using the default 1070 * schema, or if {@code filter} is not a valid LDAP string 1071 * representation of a filter. 1072 * @throws NullPointerException 1073 * If the {@code name}, {@code scope}, or {@code filter} were 1074 * {@code null}. 1075 */ 1076 public static SearchRequest newSearchRequest(final String name, final SearchScope scope, 1077 final String filter, final String... attributeDescriptions) { 1078 Reject.ifNull(name, scope, filter); 1079 final SearchRequest request = 1080 new SearchRequestImpl(DN.valueOf(name), scope, Filter.valueOf(filter)); 1081 for (final String attributeDescription : attributeDescriptions) { 1082 request.addAttribute(attributeDescription); 1083 } 1084 return request; 1085 } 1086 1087 /** 1088 * Creates a new search request for a single entry, using the provided distinguished name, 1089 * scope, and filter. 1090 * 1091 * @param name 1092 * The distinguished name of the base entry relative to which the 1093 * search is to be performed. 1094 * @param scope 1095 * The scope of the search. 1096 * @param filter 1097 * The filter that defines the conditions that must be fulfilled 1098 * in order for an entry to be returned. 1099 * @param attributeDescriptions 1100 * The names of the attributes to be included with each entry. 1101 * @return The new search request. 1102 * @throws NullPointerException 1103 * If the {@code name}, {@code scope}, or {@code filter} were 1104 * {@code null}. 1105 */ 1106 public static SearchRequest newSingleEntrySearchRequest(final DN name, final SearchScope scope, 1107 final Filter filter, final String... attributeDescriptions) { 1108 return newSearchRequest(name, scope, filter, attributeDescriptions).setSizeLimit(1); 1109 } 1110 1111 /** 1112 * Creates a new search request for a single entry, using the provided distinguished name, 1113 * scope, and filter, decoded using the default schema. 1114 * 1115 * @param name 1116 * The distinguished name of the base entry relative to which the 1117 * search is to be performed. 1118 * @param scope 1119 * The scope of the search. 1120 * @param filter 1121 * The filter that defines the conditions that must be fulfilled 1122 * in order for an entry to be returned. 1123 * @param attributeDescriptions 1124 * The names of the attributes to be included with each entry. 1125 * @return The new search request. 1126 * @throws LocalizedIllegalArgumentException 1127 * If {@code name} could not be decoded using the default 1128 * schema, or if {@code filter} is not a valid LDAP string 1129 * representation of a filter. 1130 * @throws NullPointerException 1131 * If the {@code name}, {@code scope}, or {@code filter} were 1132 * {@code null}. 1133 */ 1134 public static SearchRequest newSingleEntrySearchRequest(final String name, final SearchScope scope, 1135 final String filter, final String... attributeDescriptions) { 1136 return newSearchRequest(name, scope, filter, attributeDescriptions).setSizeLimit(1); 1137 } 1138 1139 /** 1140 * Creates a new simple bind request having an empty name and password 1141 * suitable for anonymous authentication. 1142 * 1143 * @return The new simple bind request. 1144 */ 1145 public static SimpleBindRequest newSimpleBindRequest() { 1146 return new SimpleBindRequestImpl("", EMPTY_BYTES); 1147 } 1148 1149 /** 1150 * Creates a new simple bind request having the provided name and password 1151 * suitable for name/password authentication. The name will be decoded using 1152 * the default schema. 1153 * <p> 1154 * The LDAP protocol defines the Bind name to be a distinguished name, 1155 * however some LDAP implementations have relaxed this constraint and allow 1156 * other identities to be used, such as the user's email address. 1157 * 1158 * @param name 1159 * The name of the Directory object that the client wishes to 1160 * bind as, which may be empty. 1161 * @param password 1162 * The password of the Directory object that the client wishes to 1163 * bind as, which may be empty indicating that an unauthenticated 1164 * bind is to be performed. 1165 * @return The new simple bind request. 1166 * @throws NullPointerException 1167 * If {@code name} or {@code password} was {@code null}. 1168 */ 1169 public static SimpleBindRequest newSimpleBindRequest(final String name, final byte[] password) { 1170 Reject.ifNull(name, password); 1171 return new SimpleBindRequestImpl(name, password); 1172 } 1173 1174 /** 1175 * Creates a new simple bind request having the provided name and password 1176 * suitable for name/password authentication. The name will be decoded using 1177 * the default schema. 1178 * <p> 1179 * The LDAP protocol defines the Bind name to be a distinguished name, 1180 * however some LDAP implementations have relaxed this constraint and allow 1181 * other identities to be used, such as the user's email address. 1182 * 1183 * @param name 1184 * The name of the Directory object that the client wishes to 1185 * bind as, which may be empty. 1186 * @param password 1187 * The password of the Directory object that the client wishes to 1188 * bind as, which may be empty indicating that an unauthenticated 1189 * bind is to be performed. The password will be converted to a 1190 * UTF-8 octet string. 1191 * @return The new simple bind request. 1192 * @throws NullPointerException 1193 * If {@code name} or {@code password} was {@code null}. 1194 */ 1195 public static SimpleBindRequest newSimpleBindRequest(final String name, final char[] password) { 1196 Reject.ifNull(name, password); 1197 return new SimpleBindRequestImpl(name, getBytes(password)); 1198 } 1199 1200 /** 1201 * Creates a new start TLS extended request which will use the provided SSL 1202 * context. 1203 * 1204 * @param sslContext 1205 * The SSLContext that should be used when installing the TLS 1206 * layer. 1207 * @return The new start TLS extended request. 1208 * @throws NullPointerException 1209 * If {@code sslContext} was {@code null}. 1210 */ 1211 public static StartTLSExtendedRequest newStartTLSExtendedRequest(final SSLContext sslContext) { 1212 return new StartTLSExtendedRequestImpl(sslContext); 1213 } 1214 1215 /** 1216 * Creates a new unbind request. 1217 * 1218 * @return The new unbind request. 1219 */ 1220 public static UnbindRequest newUnbindRequest() { 1221 return new UnbindRequestImpl(); 1222 } 1223 1224 /** 1225 * Creates a new Who Am I extended request. 1226 * 1227 * @return The new Who Am I extended request. 1228 */ 1229 public static WhoAmIExtendedRequest newWhoAmIExtendedRequest() { 1230 return new WhoAmIExtendedRequestImpl(); 1231 } 1232 1233 /** 1234 * Creates an unmodifiable abandon request of the provided request. 1235 * 1236 * @param request 1237 * The abandon request to be copied. 1238 * @return The new abandon request. 1239 * @throws NullPointerException 1240 * If {@code request} was {@code null} 1241 */ 1242 public static AbandonRequest unmodifiableAbandonRequest(final AbandonRequest request) { 1243 if (request instanceof UnmodifiableAbandonRequestImpl) { 1244 return request; 1245 } 1246 return new UnmodifiableAbandonRequestImpl(request); 1247 } 1248 1249 /** 1250 * Creates an unmodifiable add request of the provided request. 1251 * 1252 * @param request 1253 * The add request to be copied. 1254 * @return The new add request. 1255 * @throws NullPointerException 1256 * If {@code request} was {@code null} . 1257 */ 1258 public static AddRequest unmodifiableAddRequest(final AddRequest request) { 1259 if (request instanceof UnmodifiableAddRequestImpl) { 1260 return request; 1261 } 1262 return new UnmodifiableAddRequestImpl(request); 1263 } 1264 1265 /** 1266 * Creates an unmodifiable anonymous SASL bind request of the provided 1267 * request. 1268 * 1269 * @param request 1270 * The anonymous SASL bind request to be copied. 1271 * @return The new anonymous SASL bind request. 1272 * @throws NullPointerException 1273 * If {@code request} was {@code null} . 1274 */ 1275 public static AnonymousSASLBindRequest unmodifiableAnonymousSASLBindRequest( 1276 final AnonymousSASLBindRequest request) { 1277 if (request instanceof UnmodifiableAnonymousSASLBindRequestImpl) { 1278 return request; 1279 } 1280 return new UnmodifiableAnonymousSASLBindRequestImpl(request); 1281 } 1282 1283 /** 1284 * Creates an unmodifiable cancel extended request of the provided request. 1285 * 1286 * @param request 1287 * The cancel extended request to be copied. 1288 * @return The new cancel extended request. 1289 * @throws NullPointerException 1290 * If {@code request} was {@code null} . 1291 */ 1292 public static CancelExtendedRequest unmodifiableCancelExtendedRequest( 1293 final CancelExtendedRequest request) { 1294 if (request instanceof UnmodifiableCancelExtendedRequestImpl) { 1295 return request; 1296 } 1297 return new UnmodifiableCancelExtendedRequestImpl(request); 1298 } 1299 1300 /** 1301 * Creates an unmodifiable compare request of the provided request. 1302 * 1303 * @param request 1304 * The compare request to be copied. 1305 * @return The new compare request. 1306 * @throws NullPointerException 1307 * If {@code request} was {@code null} . 1308 */ 1309 public static CompareRequest unmodifiableCompareRequest(final CompareRequest request) { 1310 if (request instanceof UnmodifiableCompareRequestImpl) { 1311 return request; 1312 } 1313 return new UnmodifiableCompareRequestImpl(request); 1314 } 1315 1316 /** 1317 * Creates an unmodifiable CRAM MD5 SASL bind request of the provided 1318 * request. 1319 * <p> 1320 * The returned bind request creates defensive copies of the password in 1321 * order to maintain immutability. 1322 * 1323 * @param request 1324 * The CRAM MD5 SASL bind request to be copied. 1325 * @return The new CRAM-MD5 SASL bind request. 1326 * @throws NullPointerException 1327 * If {@code request} was {@code null}. 1328 */ 1329 public static CRAMMD5SASLBindRequest unmodifiableCRAMMD5SASLBindRequest( 1330 final CRAMMD5SASLBindRequest request) { 1331 if (request instanceof UnmodifiableCRAMMD5SASLBindRequestImpl) { 1332 return request; 1333 } 1334 return new UnmodifiableCRAMMD5SASLBindRequestImpl(request); 1335 } 1336 1337 /** 1338 * Creates an unmodifiable delete request of the provided request. 1339 * 1340 * @param request 1341 * The add request to be copied. 1342 * @return The new delete request. 1343 * @throws NullPointerException 1344 * If {@code request} was {@code null}. 1345 */ 1346 public static DeleteRequest unmodifiableDeleteRequest(final DeleteRequest request) { 1347 if (request instanceof UnmodifiableDeleteRequestImpl) { 1348 return request; 1349 } 1350 return new UnmodifiableDeleteRequestImpl(request); 1351 } 1352 1353 /** 1354 * Creates an unmodifiable digest MD5 SASL bind request of the provided 1355 * request. 1356 * <p> 1357 * The returned bind request creates defensive copies of the password in 1358 * order to maintain immutability. 1359 * 1360 * @param request 1361 * The digest MD5 SASL bind request to be copied. 1362 * @return The new DIGEST-MD5 SASL bind request. 1363 * @throws NullPointerException 1364 * If {@code request} was {@code null}. 1365 */ 1366 public static DigestMD5SASLBindRequest unmodifiableDigestMD5SASLBindRequest( 1367 final DigestMD5SASLBindRequest request) { 1368 if (request instanceof UnmodifiableDigestMD5SASLBindRequestImpl) { 1369 return request; 1370 } 1371 return new UnmodifiableDigestMD5SASLBindRequestImpl(request); 1372 } 1373 1374 /** 1375 * Creates an unmodifiable external SASL bind request of the provided 1376 * request. 1377 * 1378 * @param request 1379 * The external SASL bind request to be copied. 1380 * @return The new External SASL bind request. 1381 * @throws NullPointerException 1382 * If {@code request} was {@code null} . 1383 */ 1384 public static ExternalSASLBindRequest unmodifiableExternalSASLBindRequest( 1385 final ExternalSASLBindRequest request) { 1386 if (request instanceof UnmodifiableExternalSASLBindRequestImpl) { 1387 return request; 1388 } 1389 return new UnmodifiableExternalSASLBindRequestImpl(request); 1390 } 1391 1392 /** 1393 * Creates an unmodifiable generic bind request of the provided request. 1394 * <p> 1395 * The returned bind request creates defensive copies of the authentication 1396 * value in order to maintain immutability. 1397 * 1398 * @param request 1399 * The generic bind request to be copied. 1400 * @return The new generic bind request. 1401 * @throws NullPointerException 1402 * If {@code request} was {@code null} . 1403 */ 1404 public static GenericBindRequest unmodifiableGenericBindRequest(final GenericBindRequest request) { 1405 if (request instanceof UnmodifiableGenericBindRequestImpl) { 1406 return request; 1407 } 1408 return new UnmodifiableGenericBindRequestImpl(request); 1409 } 1410 1411 /** 1412 * Creates an unmodifiable generic extended request of the provided request. 1413 * 1414 * @param request 1415 * The generic extended request to be copied. 1416 * @return The new generic extended request. 1417 * @throws NullPointerException 1418 * If {@code request} was {@code null} . 1419 */ 1420 public static GenericExtendedRequest unmodifiableGenericExtendedRequest( 1421 final GenericExtendedRequest request) { 1422 if (request instanceof UnmodifiableGenericExtendedRequestImpl) { 1423 return request; 1424 } 1425 return new UnmodifiableGenericExtendedRequestImpl(request); 1426 } 1427 1428 /** 1429 * Creates an unmodifiable GSSAPI SASL bind request of the provided request. 1430 * <p> 1431 * The returned bind request creates defensive copies of the password in 1432 * order to maintain immutability. 1433 * 1434 * @param request 1435 * The GSSAPI SASL bind request to be copied. 1436 * @return The new GSSAPI SASL bind request. 1437 * @throws NullPointerException 1438 * If {@code request} was {@code null}. 1439 */ 1440 public static GSSAPISASLBindRequest unmodifiableGSSAPISASLBindRequest( 1441 final GSSAPISASLBindRequest request) { 1442 if (request instanceof UnmodifiableGSSAPISASLBindRequestImpl) { 1443 return request; 1444 } 1445 return new UnmodifiableGSSAPISASLBindRequestImpl(request); 1446 } 1447 1448 /** 1449 * Creates an unmodifiable modify DN request of the provided request. 1450 * 1451 * @param request 1452 * The modify DN request to be copied. 1453 * @return The new modify DN request. 1454 * @throws NullPointerException 1455 * If {@code request} was {@code null} . 1456 */ 1457 public static ModifyDNRequest unmodifiableModifyDNRequest(final ModifyDNRequest request) { 1458 if (request instanceof UnmodifiableModifyDNRequestImpl) { 1459 return request; 1460 } 1461 return new UnmodifiableModifyDNRequestImpl(request); 1462 } 1463 1464 /** 1465 * Creates an unmodifiable modify request of the provided request. 1466 * 1467 * @param request 1468 * The modify request to be copied. 1469 * @return The new modify request. 1470 * @throws NullPointerException 1471 * If {@code request} was {@code null} . 1472 */ 1473 public static ModifyRequest unmodifiableModifyRequest(final ModifyRequest request) { 1474 if (request instanceof UnmodifiableModifyRequestImpl) { 1475 return request; 1476 } 1477 return new UnmodifiableModifyRequestImpl(request); 1478 } 1479 1480 /** 1481 * Creates an unmodifiable password modify extended request of the provided 1482 * request. 1483 * 1484 * @param request 1485 * The password modify extended request to be copied. 1486 * @return The new password modify extended request. 1487 * @throws NullPointerException 1488 * If {@code request} was {@code null} . 1489 */ 1490 public static PasswordModifyExtendedRequest unmodifiablePasswordModifyExtendedRequest( 1491 final PasswordModifyExtendedRequest request) { 1492 if (request instanceof UnmodifiablePasswordModifyExtendedRequestImpl) { 1493 return request; 1494 } 1495 return new UnmodifiablePasswordModifyExtendedRequestImpl(request); 1496 } 1497 1498 /** 1499 * Creates an unmodifiable plain SASL bind request of the provided request. 1500 * <p> 1501 * The returned bind request creates defensive copies of the password in 1502 * order to maintain immutability. 1503 * 1504 * @param request 1505 * The plain SASL bind request to be copied. 1506 * @return The new Plain SASL bind request. 1507 * @throws NullPointerException 1508 * If {@code request} was {@code null} . 1509 */ 1510 public static PlainSASLBindRequest unmodifiablePlainSASLBindRequest( 1511 final PlainSASLBindRequest request) { 1512 if (request instanceof UnmodifiablePlainSASLBindRequestImpl) { 1513 return request; 1514 } 1515 return new UnmodifiablePlainSASLBindRequestImpl(request); 1516 } 1517 1518 /** 1519 * Creates an unmodifiable search request of the provided request. 1520 * 1521 * @param request 1522 * The search request to be copied. 1523 * @return The new search request. 1524 * @throws NullPointerException 1525 * If {@code request} was {@code null} . 1526 */ 1527 public static SearchRequest unmodifiableSearchRequest(final SearchRequest request) { 1528 if (request instanceof UnmodifiableSearchRequestImpl) { 1529 return request; 1530 } 1531 return new UnmodifiableSearchRequestImpl(request); 1532 } 1533 1534 /** 1535 * Creates an unmodifiable simple bind request of the provided request. 1536 * <p> 1537 * The returned bind request creates defensive copies of the password in 1538 * order to maintain immutability. 1539 * 1540 * @param request 1541 * The simple bind request to be copied. 1542 * @return The new simple bind request. 1543 * @throws NullPointerException 1544 * If {@code request} was {@code null} . 1545 */ 1546 public static SimpleBindRequest unmodifiableSimpleBindRequest(final SimpleBindRequest request) { 1547 if (request instanceof UnmodifiableSimpleBindRequestImpl) { 1548 return request; 1549 } 1550 return new UnmodifiableSimpleBindRequestImpl(request); 1551 } 1552 1553 /** 1554 * Creates an unmodifiable startTLS extended request of the provided 1555 * request. 1556 * 1557 * @param request 1558 * The startTLS extended request to be copied. 1559 * @return The new start TLS extended request. 1560 * @throws NullPointerException 1561 * If {@code request} was {@code null} . 1562 */ 1563 public static StartTLSExtendedRequest unmodifiableStartTLSExtendedRequest( 1564 final StartTLSExtendedRequest request) { 1565 if (request instanceof UnmodifiableStartTLSExtendedRequestImpl) { 1566 return request; 1567 } 1568 return new UnmodifiableStartTLSExtendedRequestImpl(request); 1569 } 1570 1571 /** 1572 * Creates an unmodifiable unbind request of the provided request. 1573 * 1574 * @param request 1575 * The unbind request to be copied. 1576 * @return The new unbind request. 1577 * @throws NullPointerException 1578 * If {@code request} was {@code null} . 1579 */ 1580 public static UnbindRequest unmodifiableUnbindRequest(final UnbindRequest request) { 1581 if (request instanceof UnmodifiableUnbindRequestImpl) { 1582 return request; 1583 } 1584 return new UnmodifiableUnbindRequestImpl(request); 1585 } 1586 1587 /** 1588 * Creates an unmodifiable new Who Am I extended request of the provided 1589 * request. 1590 * 1591 * @param request 1592 * The who Am I extended request to be copied. 1593 * @return The new Who Am I extended request. 1594 * @throws NullPointerException 1595 * If {@code request} was {@code null} . 1596 */ 1597 public static WhoAmIExtendedRequest unmodifiableWhoAmIExtendedRequest( 1598 final WhoAmIExtendedRequest request) { 1599 if (request instanceof UnmodifiableWhoAmIExtendedRequestImpl) { 1600 return request; 1601 } 1602 return new UnmodifiableWhoAmIExtendedRequestImpl(request); 1603 } 1604 1605 private Requests() { 1606 // Prevent instantiation. 1607 } 1608}