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