001/* 002 * Copyright 2009-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2009-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.migrate.ldapjdk; 037 038 039 040import com.unboundid.asn1.ASN1OctetString; 041import com.unboundid.ldap.sdk.AddRequest; 042import com.unboundid.ldap.sdk.AsyncRequestID; 043import com.unboundid.ldap.sdk.BindResult; 044import com.unboundid.ldap.sdk.CompareRequest; 045import com.unboundid.ldap.sdk.CompareResult; 046import com.unboundid.ldap.sdk.Control; 047import com.unboundid.ldap.sdk.DeleteRequest; 048import com.unboundid.ldap.sdk.DereferencePolicy; 049import com.unboundid.ldap.sdk.ExtendedRequest; 050import com.unboundid.ldap.sdk.ExtendedResult; 051import com.unboundid.ldap.sdk.Filter; 052import com.unboundid.ldap.sdk.InternalSDKHelper; 053import com.unboundid.ldap.sdk.LDAPConnectionOptions; 054import com.unboundid.ldap.sdk.LDAPResult; 055import com.unboundid.ldap.sdk.Modification; 056import com.unboundid.ldap.sdk.ModifyDNRequest; 057import com.unboundid.ldap.sdk.ModifyRequest; 058import com.unboundid.ldap.sdk.ResultCode; 059import com.unboundid.ldap.sdk.SearchRequest; 060import com.unboundid.ldap.sdk.SearchResult; 061import com.unboundid.ldap.sdk.SearchScope; 062import com.unboundid.ldap.sdk.SimpleBindRequest; 063import com.unboundid.ldap.sdk.UpdatableLDAPRequest; 064import com.unboundid.util.Debug; 065import com.unboundid.util.Mutable; 066import com.unboundid.util.NotExtensible; 067import com.unboundid.util.NotNull; 068import com.unboundid.util.Nullable; 069import com.unboundid.util.ThreadSafety; 070import com.unboundid.util.ThreadSafetyLevel; 071 072 073 074/** 075 * This class provides an object that may be used to communicate with an LDAP 076 * directory server. 077 * <BR><BR> 078 * This class is primarily intended to be used in the process of updating 079 * applications which use the Netscape Directory SDK for Java to switch to or 080 * coexist with the UnboundID LDAP SDK for Java. For applications not written 081 * using the Netscape Directory SDK for Java, the 082 * {@link com.unboundid.ldap.sdk.LDAPConnection} class should be used instead. 083 */ 084@Mutable() 085@NotExtensible() 086@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 087public class LDAPConnection 088{ 089 /** 090 * The integer value for the DEREF_NEVER dereference policy. 091 */ 092 public static final int DEREF_NEVER = DereferencePolicy.NEVER.intValue(); 093 094 095 096 /** 097 * The integer value for the DEREF_SEARCHING dereference policy. 098 */ 099 public static final int DEREF_SEARCHING = 100 DereferencePolicy.SEARCHING.intValue(); 101 102 103 104 /** 105 * The integer value for the DEREF_FINDING dereference policy. 106 */ 107 public static final int DEREF_FINDING = 108 DereferencePolicy.FINDING.intValue(); 109 110 111 112 /** 113 * The integer value for the DEREF_ALWAYS dereference policy. 114 */ 115 public static final int DEREF_ALWAYS = 116 DereferencePolicy.ALWAYS.intValue(); 117 118 119 120 /** 121 * The integer value for the SCOPE_BASE search scope. 122 */ 123 public static final int SCOPE_BASE = SearchScope.BASE_INT_VALUE; 124 125 126 127 /** 128 * The integer value for the SCOPE_ONE search scope. 129 */ 130 public static final int SCOPE_ONE = SearchScope.ONE_INT_VALUE; 131 132 133 134 /** 135 * The integer value for the SCOPE_SUB search scope. 136 */ 137 public static final int SCOPE_SUB = SearchScope.SUB_INT_VALUE; 138 139 140 141 // The connection used to perform the actual communication with the server. 142 @NotNull private volatile com.unboundid.ldap.sdk.LDAPConnection conn; 143 144 // The default constraints that will be used for non-search operations. 145 @NotNull private LDAPConstraints constraints; 146 147 // The set of controls returned from the last operation. 148 @Nullable private LDAPControl[] responseControls; 149 150 // The default constraints that will be used for search operations. 151 @NotNull private LDAPSearchConstraints searchConstraints; 152 153 // The socket factory for this connection. 154 @Nullable private LDAPSocketFactory socketFactory; 155 156 // The DN last used to bind to the server. 157 @Nullable private String authDN; 158 159 // The password last used to bind to the server. 160 @Nullable private String authPW; 161 162 163 164 /** 165 * Creates a new LDAP connection which will use the default socket factory. 166 */ 167 public LDAPConnection() 168 { 169 this(null); 170 } 171 172 173 174 /** 175 * Creates a new LDAP connection which will use the provided socket factory. 176 * 177 * @param socketFactory The socket factory to use when creating the socket 178 * to use for communicating with the server. 179 */ 180 public LDAPConnection(@Nullable final LDAPSocketFactory socketFactory) 181 { 182 this.socketFactory = socketFactory; 183 if (socketFactory == null) 184 { 185 conn = new com.unboundid.ldap.sdk.LDAPConnection(); 186 } 187 else 188 { 189 190 conn = new com.unboundid.ldap.sdk.LDAPConnection( 191 new LDAPToJavaSocketFactory(socketFactory)); 192 } 193 194 authDN = null; 195 authPW = null; 196 197 constraints = new LDAPConstraints(); 198 searchConstraints = new LDAPSearchConstraints(); 199 } 200 201 202 203 /** 204 * Closes the connection to the server if the client forgets to do so. 205 * 206 * @throws Throwable If a problem occurs. 207 */ 208 @Override() 209 protected void finalize() 210 throws Throwable 211 { 212 conn.close(); 213 214 super.finalize(); 215 } 216 217 218 219 /** 220 * Retrieves the {@link com.unboundid.ldap.sdk.LDAPConnection} object used to 221 * back this connection. 222 * 223 * @return The {@code com.unboundid.ldap.sdk.LDAPConnection} object used to 224 * back this connection. 225 */ 226 @NotNull() 227 public com.unboundid.ldap.sdk.LDAPConnection getSDKConnection() 228 { 229 return conn; 230 } 231 232 233 234 /** 235 * Retrieves the address to which the connection is established. 236 * 237 * @return The address to which the connection is established. 238 */ 239 @Nullable() 240 public String getHost() 241 { 242 return conn.getConnectedAddress(); 243 } 244 245 246 247 /** 248 * Retrieves the port to which the connection is established. 249 * 250 * @return The port to which the connection is established. 251 */ 252 public int getPort() 253 { 254 return conn.getConnectedPort(); 255 } 256 257 258 259 /** 260 * Retrieves the DN of the user that last authenticated on this connection. 261 * 262 * @return The DN of the user that last authenticated on this connection, 263 * or {@code null} if it is not available. 264 */ 265 @Nullable() 266 public String getAuthenticationDN() 267 { 268 return authDN; 269 } 270 271 272 273 /** 274 * Retrieves the password of the user that last authenticated on this 275 * connection. 276 * 277 * @return The password of the user that last authenticated on this 278 * connection, or {@code null} if it is not available. 279 */ 280 @Nullable() 281 public String getAuthenticationPassword() 282 { 283 return authPW; 284 } 285 286 287 288 /** 289 * Retrieves the maximum length of time to wait for the connection to be 290 * established, in seconds. 291 * 292 * @return The maximum length of time to wait for the connection to be 293 * established. 294 */ 295 public int getConnectTimeout() 296 { 297 final int connectTimeoutMillis = 298 conn.getConnectionOptions().getConnectTimeoutMillis(); 299 if (connectTimeoutMillis > 0) 300 { 301 return Math.max(1, (connectTimeoutMillis / 1000)); 302 } 303 else 304 { 305 return 0; 306 } 307 } 308 309 310 311 /** 312 * Specifies the maximum length of time to wait for the connection to be 313 * established, in seconds. 314 * 315 * @param timeout The maximum length of time to wait for the connection to 316 * be established. 317 */ 318 public void setConnectTimeout(final int timeout) 319 { 320 final LDAPConnectionOptions options = conn.getConnectionOptions(); 321 322 if (timeout > 0) 323 { 324 options.setConnectTimeoutMillis(1000 * timeout); 325 } 326 else 327 { 328 options.setConnectTimeoutMillis(0); 329 } 330 331 conn.setConnectionOptions(options); 332 } 333 334 335 336 /** 337 * Retrieves the socket factory for this LDAP connection, if specified. 338 * 339 * @return The socket factory for this LDAP connection, or {@code null} if 340 * none has been provided. 341 */ 342 @Nullable() 343 public LDAPSocketFactory getSocketFactory() 344 { 345 return socketFactory; 346 } 347 348 349 350 /** 351 * Sets the socket factory for this LDAP connection. 352 * 353 * @param socketFactory The socket factory for this LDAP connection. 354 */ 355 public void setSocketFactory(@Nullable final LDAPSocketFactory socketFactory) 356 { 357 this.socketFactory = socketFactory; 358 359 if (socketFactory == null) 360 { 361 conn.setSocketFactory(null); 362 } 363 else 364 { 365 conn.setSocketFactory(new LDAPToJavaSocketFactory(socketFactory)); 366 } 367 } 368 369 370 371 /** 372 * Retrieves the constraints for this connection. 373 * 374 * @return The constraints for this connection. 375 */ 376 @NotNull() 377 public LDAPConstraints getConstraints() 378 { 379 return constraints; 380 } 381 382 383 384 /** 385 * Updates the constraints for this connection. 386 * 387 * @param constraints The constraints for this connection. 388 */ 389 public void setConstraints(@Nullable final LDAPConstraints constraints) 390 { 391 if (constraints == null) 392 { 393 this.constraints = new LDAPConstraints(); 394 } 395 else 396 { 397 this.constraints = constraints; 398 } 399 } 400 401 402 403 /** 404 * Retrieves the search constraints for this connection. 405 * 406 * @return The search constraints for this connection. 407 */ 408 @NotNull() 409 public LDAPSearchConstraints getSearchConstraints() 410 { 411 return searchConstraints; 412 } 413 414 415 416 /** 417 * Updates the search constraints for this connection. 418 * 419 * @param searchConstraints The search constraints for this connection. 420 */ 421 public void setSearchConstraints( 422 @Nullable final LDAPSearchConstraints searchConstraints) 423 { 424 if (searchConstraints == null) 425 { 426 this.searchConstraints = new LDAPSearchConstraints(); 427 } 428 else 429 { 430 this.searchConstraints = searchConstraints; 431 } 432 } 433 434 435 436 /** 437 * Retrieves the response controls from the last operation processed on this 438 * connection. 439 * 440 * @return The response controls from the last operation processed on this 441 * connection, or {@code null} if there were none. 442 */ 443 @Nullable() 444 public LDAPControl[] getResponseControls() 445 { 446 return responseControls; 447 } 448 449 450 451 /** 452 * Indicates whether this connection is currently established. 453 * 454 * @return {@code true} if this connection is currently established, or 455 * {@code false} if not. 456 */ 457 public boolean isConnected() 458 { 459 return conn.isConnected(); 460 } 461 462 463 464 /** 465 * Attempts to establish this connection with the provided information. 466 * 467 * @param host The address of the server to which the connection should be 468 * established. 469 * @param port The port of the server to which the connection should be 470 * established. 471 * 472 * @throws LDAPException If a problem occurs while attempting to establish 473 * this connection. 474 */ 475 public void connect(@NotNull final String host, final int port) 476 throws LDAPException 477 { 478 authDN = null; 479 authPW = null; 480 responseControls = null; 481 482 try 483 { 484 conn.close(); 485 if (socketFactory == null) 486 { 487 conn = new com.unboundid.ldap.sdk.LDAPConnection(host, port); 488 } 489 else 490 { 491 492 conn = new com.unboundid.ldap.sdk.LDAPConnection( 493 new LDAPToJavaSocketFactory(socketFactory), host, port); 494 } 495 } 496 catch (final com.unboundid.ldap.sdk.LDAPException le) 497 { 498 Debug.debugException(le); 499 throw new LDAPException(le); 500 } 501 } 502 503 504 505 /** 506 * Attempts to establish and authenticate this connection with the provided 507 * information. 508 * 509 * @param host The address of the server to which the connection should 510 * be established. 511 * @param port The port of the server to which the connection should be 512 * established. 513 * @param dn The DN to use to bind to the server. 514 * @param password The password to use to bind to the server. 515 * 516 * @throws LDAPException If a problem occurs while attempting to establish 517 * or authenticate this connection. If an exception 518 * is thrown, then the connection will not be 519 * established. 520 */ 521 public void connect(@NotNull final String host, final int port, 522 @Nullable final String dn, 523 @Nullable final String password) 524 throws LDAPException 525 { 526 connect(3, host, port, dn, password, null); 527 } 528 529 530 531 /** 532 * Attempts to establish and authenticate this connection with the provided 533 * information. 534 * 535 * @param host The address of the server to which the connection 536 * should be established. 537 * @param port The port of the server to which the connection should 538 * be established. 539 * @param dn The DN to use to bind to the server. 540 * @param password The password to use to bind to the server. 541 * @param constraints The constraints to use when processing the bind. 542 * 543 * @throws LDAPException If a problem occurs while attempting to establish 544 * or authenticate this connection. If an exception 545 * is thrown, then the connection will not be 546 * established. 547 */ 548 public void connect(@NotNull final String host, final int port, 549 @Nullable final String dn, 550 @Nullable final String password, 551 @Nullable final LDAPConstraints constraints) 552 throws LDAPException 553 { 554 connect(3, host, port, dn, password, constraints); 555 } 556 557 558 559 /** 560 * Attempts to establish and authenticate this connection with the provided 561 * information. 562 * 563 * @param version The LDAP protocol version to use for the connection. 564 * This will be ignored, since this implementation only 565 * supports LDAPv3. 566 * @param host The address of the server to which the connection should 567 * be established. 568 * @param port The port of the server to which the connection should be 569 * established. 570 * @param dn The DN to use to bind to the server. 571 * @param password The password to use to bind to the server. 572 * 573 * @throws LDAPException If a problem occurs while attempting to establish 574 * or authenticate this connection. If an exception 575 * is thrown, then the connection will not be 576 * established. 577 */ 578 public void connect(final int version, @NotNull final String host, 579 final int port, @Nullable final String dn, 580 @Nullable final String password) 581 throws LDAPException 582 { 583 connect(version, host, port, dn, password, null); 584 } 585 586 587 588 /** 589 * Attempts to establish and authenticate this connection with the provided 590 * information. 591 * 592 * @param version The LDAP protocol version to use for the connection. 593 * This will be ignored, since this implementation only 594 * supports LDAPv3. 595 * @param host The address of the server to which the connection 596 * should be established. 597 * @param port The port of the server to which the connection should 598 * be established. 599 * @param dn The DN to use to bind to the server. 600 * @param password The password to use to bind to the server. 601 * @param constraints The constraints to use when processing the bind. 602 * 603 * @throws LDAPException If a problem occurs while attempting to establish 604 * or authenticate this connection. If an exception 605 * is thrown, then the connection will not be 606 * established. 607 */ 608 public void connect(final int version, @NotNull final String host, 609 final int port, @Nullable final String dn, 610 @Nullable final String password, 611 @Nullable final LDAPConstraints constraints) 612 throws LDAPException 613 { 614 connect(host, port); 615 616 try 617 { 618 if ((dn != null) && (password != null)) 619 { 620 bind(version, dn, password, constraints); 621 } 622 } 623 catch (final LDAPException le) 624 { 625 conn.close(); 626 throw le; 627 } 628 } 629 630 631 632 /** 633 * Unbinds and disconnects from the directory server. 634 * 635 * @throws LDAPException If a problem occurs. 636 */ 637 public void disconnect() 638 throws LDAPException 639 { 640 authDN = null; 641 authPW = null; 642 643 conn.close(); 644 if (socketFactory == null) 645 { 646 conn = new com.unboundid.ldap.sdk.LDAPConnection(); 647 } 648 else 649 { 650 651 conn = new com.unboundid.ldap.sdk.LDAPConnection( 652 new LDAPToJavaSocketFactory(socketFactory)); 653 } 654 } 655 656 657 658 /** 659 * Disconnects from the directory server and attempts to re-connect and 660 * re-authenticate. 661 * 662 * @throws LDAPException If a problem occurs. If an exception is thrown, 663 * the connection will have been closed. 664 */ 665 public void reconnect() 666 throws LDAPException 667 { 668 final String host = getHost(); 669 final int port = getPort(); 670 final String dn = authDN; 671 final String pw = authPW; 672 673 if ((dn == null) || (pw == null)) 674 { 675 connect(host, port); 676 } 677 else 678 { 679 connect(host, port, dn, pw); 680 } 681 } 682 683 684 685 /** 686 * Sends a request to abandon the request with the specified message ID. 687 * 688 * @param id The message ID of the operation to abandon. 689 * 690 * @throws LDAPException If a problem occurs while sending the request. 691 */ 692 public void abandon(final int id) 693 throws LDAPException 694 { 695 try 696 { 697 conn.abandon(InternalSDKHelper.createAsyncRequestID(id, conn), 698 getControls(null)); 699 } 700 catch (final com.unboundid.ldap.sdk.LDAPException le) 701 { 702 Debug.debugException(le); 703 throw new LDAPException(le); 704 } 705 } 706 707 708 709 /** 710 * Sends a request to abandon the provided search operation. 711 * 712 * @param searchResults The search results object for the search to abandon. 713 * 714 * @throws LDAPException If a problem occurs while sending the request. 715 */ 716 public void abandon(@NotNull final LDAPSearchResults searchResults) 717 throws LDAPException 718 { 719 try 720 { 721 final AsyncRequestID requestID = searchResults.getAsyncRequestID(); 722 if (requestID != null) 723 { 724 searchResults.setAbandoned(); 725 conn.abandon(requestID); 726 } 727 else 728 { 729 // This should never happen. 730 throw new LDAPException( 731 "The search request has not been sent to the server", 732 LDAPException.PARAM_ERROR); 733 } 734 } 735 catch (final com.unboundid.ldap.sdk.LDAPException le) 736 { 737 Debug.debugException(le); 738 throw new LDAPException(le); 739 } 740 } 741 742 743 744 /** 745 * Adds the provided entry to the directory. 746 * 747 * @param entry The entry to be added. 748 * 749 * @throws LDAPException If a problem occurs while adding the entry. 750 */ 751 public void add(@NotNull final LDAPEntry entry) 752 throws LDAPException 753 { 754 add(entry, null); 755 } 756 757 758 759 /** 760 * Adds the provided entry to the directory. 761 * 762 * @param entry The entry to be added. 763 * @param constraints The constraints to use for the add operation. 764 * 765 * @throws LDAPException If a problem occurs while adding the entry. 766 */ 767 public void add(@NotNull final LDAPEntry entry, 768 @Nullable final LDAPConstraints constraints) 769 throws LDAPException 770 { 771 final AddRequest addRequest = new AddRequest(entry.toEntry()); 772 update(addRequest, constraints); 773 774 try 775 { 776 final LDAPResult result = conn.add(addRequest); 777 setResponseControls(result); 778 } 779 catch (final com.unboundid.ldap.sdk.LDAPException le) 780 { 781 Debug.debugException(le); 782 setResponseControls(le); 783 throw new LDAPException(le); 784 } 785 } 786 787 788 789 /** 790 * Authenticates to the directory server using a simple bind with the provided 791 * information. 792 * 793 * @param dn The DN of the user for the bind. 794 * @param password The password to use for the bind. 795 * 796 * @throws LDAPException If the bind attempt fails. 797 */ 798 public void authenticate(@Nullable final String dn, 799 @Nullable final String password) 800 throws LDAPException 801 { 802 bind(3, dn, password, null); 803 } 804 805 806 807 /** 808 * Authenticates to the directory server using a simple bind with the provided 809 * information. 810 * 811 * @param dn The DN of the user for the bind. 812 * @param password The password to use for the bind. 813 * @param constraints The constraints to use for the bind operation. 814 * 815 * @throws LDAPException If the bind attempt fails. 816 */ 817 public void authenticate(@Nullable final String dn, 818 @Nullable final String password, 819 @Nullable final LDAPConstraints constraints) 820 throws LDAPException 821 { 822 bind(3, dn, password, constraints); 823 } 824 825 826 827 /** 828 * Authenticates to the directory server using a simple bind with the provided 829 * information. 830 * 831 * @param version The LDAP protocol version to use. This will be ignored, 832 * since this implementation only supports LDAPv3. 833 * @param dn The DN of the user for the bind. 834 * @param password The password to use for the bind. 835 * 836 * @throws LDAPException If the bind attempt fails. 837 */ 838 public void authenticate(final int version, @Nullable final String dn, 839 @Nullable final String password) 840 throws LDAPException 841 { 842 bind(version, dn, password, null); 843 } 844 845 846 847 /** 848 * Authenticates to the directory server using a simple bind with the provided 849 * information. 850 * 851 * @param version The LDAP protocol version to use. This will be 852 * ignored, since this implementation only supports 853 * LDAPv3. 854 * @param dn The DN of the user for the bind. 855 * @param password The password to use for the bind. 856 * @param constraints The constraints to use for the bind operation. 857 * 858 * @throws LDAPException If the bind attempt fails. 859 */ 860 public void authenticate(final int version, @Nullable final String dn, 861 @Nullable final String password, 862 @Nullable final LDAPConstraints constraints) 863 throws LDAPException 864 { 865 bind(version, dn, password, constraints); 866 } 867 868 869 870 /** 871 * Authenticates to the directory server using a simple bind with the provided 872 * information. 873 * 874 * @param dn The DN of the user for the bind. 875 * @param password The password to use for the bind. 876 * 877 * @throws LDAPException If the bind attempt fails. 878 */ 879 public void bind(@Nullable final String dn, @Nullable final String password) 880 throws LDAPException 881 { 882 bind(3, dn, password, null); 883 } 884 885 886 887 /** 888 * Authenticates to the directory server using a simple bind with the provided 889 * information. 890 * 891 * @param dn The DN of the user for the bind. 892 * @param password The password to use for the bind. 893 * @param constraints The constraints to use for the bind operation. 894 * 895 * @throws LDAPException If the bind attempt fails. 896 */ 897 public void bind(@Nullable final String dn, @Nullable final String password, 898 @Nullable final LDAPConstraints constraints) 899 throws LDAPException 900 { 901 bind(3, dn, password, constraints); 902 } 903 904 905 906 /** 907 * Authenticates to the directory server using a simple bind with the provided 908 * information. 909 * 910 * @param version The LDAP protocol version to use. This will be ignored, 911 * since this implementation only supports LDAPv3. 912 * @param dn The DN of the user for the bind. 913 * @param password The password to use for the bind. 914 * 915 * @throws LDAPException If the bind attempt fails. 916 */ 917 public void bind(final int version, @Nullable final String dn, 918 @Nullable final String password) 919 throws LDAPException 920 { 921 bind(version, dn, password, null); 922 } 923 924 925 926 /** 927 * Authenticates to the directory server using a simple bind with the provided 928 * information. 929 * 930 * @param version The LDAP protocol version to use. This will be 931 * ignored, since this implementation only supports 932 * LDAPv3. 933 * @param dn The DN of the user for the bind. 934 * @param password The password to use for the bind. 935 * @param constraints The constraints to use for the bind operation. 936 * 937 * @throws LDAPException If the bind attempt fails. 938 */ 939 public void bind(final int version, @Nullable final String dn, 940 @Nullable final String password, 941 @Nullable final LDAPConstraints constraints) 942 throws LDAPException 943 { 944 final SimpleBindRequest bindRequest = 945 new SimpleBindRequest(dn, password, getControls(constraints)); 946 authDN = null; 947 authPW = null; 948 949 try 950 { 951 final BindResult bindResult = conn.bind(bindRequest); 952 setResponseControls(bindResult); 953 if (bindResult.getResultCode() == ResultCode.SUCCESS) 954 { 955 authDN = dn; 956 authPW = password; 957 } 958 } 959 catch (final com.unboundid.ldap.sdk.LDAPException le) 960 { 961 Debug.debugException(le); 962 setResponseControls(le); 963 throw new LDAPException(le); 964 } 965 } 966 967 968 969 /** 970 * Indicates whether the specified entry has the given attribute value. 971 * 972 * @param dn The DN of the entry to compare. 973 * @param attribute The attribute (which must have exactly one value) to use 974 * for the comparison. 975 * 976 * @return {@code true} if the compare matched the target entry, or 977 * {@code false} if not. 978 * 979 * @throws LDAPException If a problem occurs while processing the compare. 980 */ 981 public boolean compare(@NotNull final String dn, 982 @NotNull final LDAPAttribute attribute) 983 throws LDAPException 984 { 985 return compare(dn, attribute, null); 986 } 987 988 989 990 /** 991 * Indicates whether the specified entry has the given attribute value. 992 * 993 * @param dn The DN of the entry to compare. 994 * @param attribute The attribute (which must have exactly one value) to 995 * use for the comparison. 996 * @param constraints The constraints to use for the compare operation. 997 * 998 * @return {@code true} if the compare matched the target entry, or 999 * {@code false} if not. 1000 * 1001 * @throws LDAPException If a problem occurs while processing the compare. 1002 */ 1003 public boolean compare(@NotNull final String dn, 1004 @NotNull final LDAPAttribute attribute, 1005 @Nullable final LDAPConstraints constraints) 1006 throws LDAPException 1007 { 1008 final CompareRequest compareRequest = new CompareRequest(dn, 1009 attribute.getName(), attribute.getByteValueArray()[0]); 1010 update(compareRequest, constraints); 1011 1012 try 1013 { 1014 final CompareResult result = conn.compare(compareRequest); 1015 setResponseControls(result); 1016 return result.compareMatched(); 1017 } 1018 catch (final com.unboundid.ldap.sdk.LDAPException le) 1019 { 1020 Debug.debugException(le); 1021 setResponseControls(le); 1022 throw new LDAPException(le); 1023 } 1024 } 1025 1026 1027 1028 /** 1029 * Removes an entry from the directory. 1030 * 1031 * @param dn The DN of the entry to delete. 1032 * 1033 * @throws LDAPException If a problem occurs while processing the delete. 1034 */ 1035 public void delete(@NotNull final String dn) 1036 throws LDAPException 1037 { 1038 delete(dn, null); 1039 } 1040 1041 1042 1043 /** 1044 * Removes an entry from the directory. 1045 * 1046 * @param dn The DN of the entry to delete. 1047 * @param constraints The constraints to use for the delete operation. 1048 * 1049 * @throws LDAPException If a problem occurs while processing the delete. 1050 */ 1051 public void delete(@NotNull final String dn, 1052 @Nullable final LDAPConstraints constraints) 1053 throws LDAPException 1054 { 1055 final DeleteRequest deleteRequest = new DeleteRequest(dn); 1056 update(deleteRequest, constraints); 1057 1058 try 1059 { 1060 final LDAPResult result = conn.delete(deleteRequest); 1061 setResponseControls(result); 1062 } 1063 catch (final com.unboundid.ldap.sdk.LDAPException le) 1064 { 1065 Debug.debugException(le); 1066 setResponseControls(le); 1067 throw new LDAPException(le); 1068 } 1069 } 1070 1071 1072 1073 /** 1074 * Processes an extended operation in the directory. 1075 * 1076 * @param extendedOperation The extended operation to process. 1077 * 1078 * @return The result returned from the extended operation. 1079 * 1080 * @throws LDAPException If a problem occurs while processing the operation. 1081 */ 1082 @NotNull() 1083 public LDAPExtendedOperation extendedOperation( 1084 @NotNull final LDAPExtendedOperation extendedOperation) 1085 throws LDAPException 1086 { 1087 return extendedOperation(extendedOperation, null); 1088 } 1089 1090 1091 1092 /** 1093 * Processes an extended operation in the directory. 1094 * 1095 * @param extendedOperation The extended operation to process. 1096 * @param constraints The constraints to use for the operation. 1097 * 1098 * @return The result returned from the extended operation. 1099 * 1100 * @throws LDAPException If a problem occurs while processing the operation. 1101 */ 1102 @NotNull() 1103 public LDAPExtendedOperation extendedOperation( 1104 @NotNull final LDAPExtendedOperation extendedOperation, 1105 @Nullable final LDAPConstraints constraints) 1106 throws LDAPException 1107 { 1108 final ExtendedRequest extendedRequest = new ExtendedRequest( 1109 extendedOperation.getID(), 1110 new ASN1OctetString(extendedOperation.getValue()), 1111 getControls(constraints)); 1112 1113 try 1114 { 1115 final ExtendedResult result = 1116 conn.processExtendedOperation(extendedRequest); 1117 setResponseControls(result); 1118 1119 if (result.getResultCode() != ResultCode.SUCCESS) 1120 { 1121 throw new LDAPException(result.getDiagnosticMessage(), 1122 result.getResultCode().intValue(), result.getDiagnosticMessage(), 1123 result.getMatchedDN()); 1124 } 1125 1126 final byte[] valueBytes; 1127 final ASN1OctetString value = result.getValue(); 1128 if (value == null) 1129 { 1130 valueBytes = null; 1131 } 1132 else 1133 { 1134 valueBytes = value.getValue(); 1135 } 1136 1137 return new LDAPExtendedOperation(result.getOID(), valueBytes); 1138 } 1139 catch (final com.unboundid.ldap.sdk.LDAPException le) 1140 { 1141 Debug.debugException(le); 1142 setResponseControls(le); 1143 throw new LDAPException(le); 1144 } 1145 } 1146 1147 1148 1149 /** 1150 * Modifies an entry in the directory. 1151 * 1152 * @param dn The DN of the entry to modify. 1153 * @param mod The modification to apply to the entry. 1154 * 1155 * @throws LDAPException If a problem occurs while processing the delete. 1156 */ 1157 public void modify(@NotNull final String dn, 1158 @NotNull final LDAPModification mod) 1159 throws LDAPException 1160 { 1161 modify(dn, new LDAPModification[] { mod }, null); 1162 } 1163 1164 1165 1166 /** 1167 * Modifies an entry in the directory. 1168 * 1169 * @param dn The DN of the entry to modify. 1170 * @param mods The modifications to apply to the entry. 1171 * 1172 * @throws LDAPException If a problem occurs while processing the delete. 1173 */ 1174 public void modify(@NotNull final String dn, 1175 @NotNull final LDAPModification[] mods) 1176 throws LDAPException 1177 { 1178 modify(dn, mods, null); 1179 } 1180 1181 1182 1183 /** 1184 * Modifies an entry in the directory. 1185 * 1186 * @param dn The DN of the entry to modify. 1187 * @param mod The modification to apply to the entry. 1188 * @param constraints The constraints to use for the modify operation. 1189 * 1190 * @throws LDAPException If a problem occurs while processing the delete. 1191 */ 1192 public void modify(@NotNull final String dn, 1193 @NotNull final LDAPModification mod, 1194 @Nullable final LDAPConstraints constraints) 1195 throws LDAPException 1196 { 1197 modify(dn, new LDAPModification[] { mod }, constraints); 1198 } 1199 1200 1201 1202 /** 1203 * Modifies an entry in the directory. 1204 * 1205 * @param dn The DN of the entry to modify. 1206 * @param mods The modifications to apply to the entry. 1207 * @param constraints The constraints to use for the modify operation. 1208 * 1209 * @throws LDAPException If a problem occurs while processing the delete. 1210 */ 1211 public void modify(@NotNull final String dn, 1212 @NotNull final LDAPModification[] mods, 1213 @Nullable final LDAPConstraints constraints) 1214 throws LDAPException 1215 { 1216 final Modification[] m = new Modification[mods.length]; 1217 for (int i=0; i < mods.length; i++) 1218 { 1219 m[i] = mods[i].toModification(); 1220 } 1221 1222 final ModifyRequest modifyRequest = new ModifyRequest(dn, m); 1223 update(modifyRequest, constraints); 1224 1225 try 1226 { 1227 final LDAPResult result = conn.modify(modifyRequest); 1228 setResponseControls(result); 1229 } 1230 catch (final com.unboundid.ldap.sdk.LDAPException le) 1231 { 1232 Debug.debugException(le); 1233 setResponseControls(le); 1234 throw new LDAPException(le); 1235 } 1236 } 1237 1238 1239 1240 /** 1241 * Modifies an entry in the directory. 1242 * 1243 * @param dn The DN of the entry to modify. 1244 * @param mods The modifications to apply to the entry. 1245 * 1246 * @throws LDAPException If a problem occurs while processing the delete. 1247 */ 1248 public void modify(@NotNull final String dn, 1249 @NotNull final LDAPModificationSet mods) 1250 throws LDAPException 1251 { 1252 modify(dn, mods.toArray(), null); 1253 } 1254 1255 1256 1257 /** 1258 * Modifies an entry in the directory. 1259 * 1260 * @param dn The DN of the entry to modify. 1261 * @param mods The modifications to apply to the entry. 1262 * @param constraints The constraints to use for the modify operation. 1263 * 1264 * @throws LDAPException If a problem occurs while processing the delete. 1265 */ 1266 public void modify(@NotNull final String dn, 1267 @NotNull final LDAPModificationSet mods, 1268 @Nullable final LDAPConstraints constraints) 1269 throws LDAPException 1270 { 1271 modify(dn, mods.toArray(), constraints); 1272 } 1273 1274 1275 1276 /** 1277 * Retrieves an entry from the directory server. 1278 * 1279 * @param dn The DN of the entry to retrieve. 1280 * 1281 * @return The entry that was read. 1282 * 1283 * @throws LDAPException If a problem occurs while performing the search. 1284 */ 1285 @NotNull() 1286 public LDAPEntry read(@NotNull final String dn) 1287 throws LDAPException 1288 { 1289 return read(dn, null, null); 1290 } 1291 1292 1293 1294 /** 1295 * Retrieves an entry from the directory server. 1296 * 1297 * @param dn The DN of the entry to retrieve. 1298 * @param constraints The constraints to use for the search operation. 1299 * 1300 * @return The entry that was read. 1301 * 1302 * @throws LDAPException If a problem occurs while performing the search. 1303 */ 1304 @NotNull() 1305 public LDAPEntry read(@NotNull final String dn, 1306 @Nullable final LDAPSearchConstraints constraints) 1307 throws LDAPException 1308 { 1309 return read(dn, null, constraints); 1310 } 1311 1312 1313 1314 /** 1315 * Retrieves an entry from the directory server. 1316 * 1317 * @param dn The DN of the entry to retrieve. 1318 * @param attrs The set of attributes to request. 1319 * 1320 * @return The entry that was read. 1321 * 1322 * @throws LDAPException If a problem occurs while performing the search. 1323 */ 1324 @NotNull() 1325 public LDAPEntry read(@NotNull final String dn, 1326 @Nullable final String[] attrs) 1327 throws LDAPException 1328 { 1329 return read(dn, attrs, null); 1330 } 1331 1332 1333 1334 /** 1335 * Retrieves an entry from the directory server. 1336 * 1337 * @param dn The DN of the entry to retrieve. 1338 * @param attrs The set of attributes to request. 1339 * @param constraints The constraints to use for the search operation. 1340 * 1341 * @return The entry that was read. 1342 * 1343 * @throws LDAPException If a problem occurs while performing the search. 1344 */ 1345 @NotNull() 1346 public LDAPEntry read(@NotNull final String dn, 1347 @Nullable final String[] attrs, 1348 @Nullable final LDAPSearchConstraints constraints) 1349 throws LDAPException 1350 { 1351 final Filter filter = Filter.createORFilter( 1352 Filter.createPresenceFilter("objectClass"), 1353 Filter.createEqualityFilter("objectClass", "ldapSubentry")); 1354 1355 final SearchRequest searchRequest = 1356 new SearchRequest(dn, SearchScope.BASE, filter, attrs); 1357 update(searchRequest, constraints); 1358 1359 try 1360 { 1361 final SearchResult searchResult = conn.search(searchRequest); 1362 setResponseControls(searchResult); 1363 1364 if (searchResult.getEntryCount() != 1) 1365 { 1366 throw new LDAPException(null, LDAPException.NO_RESULTS_RETURNED); 1367 } 1368 1369 return new LDAPEntry(searchResult.getSearchEntries().get(0)); 1370 } 1371 catch (final com.unboundid.ldap.sdk.LDAPException le) 1372 { 1373 Debug.debugException(le); 1374 setResponseControls(le); 1375 throw new LDAPException(le); 1376 } 1377 } 1378 1379 1380 1381 /** 1382 * Alters the DN of an entry in the directory. 1383 * 1384 * @param dn The DN of the entry to modify. 1385 * @param newRDN The new RDN to use for the entry. 1386 * @param deleteOldRDN Indicates whether to remove the old RDN value(s). 1387 * 1388 * @throws LDAPException If a problem occurs while processing the delete. 1389 */ 1390 public void rename(@NotNull final String dn, @NotNull final String newRDN, 1391 final boolean deleteOldRDN) 1392 throws LDAPException 1393 { 1394 rename(dn, newRDN, null, deleteOldRDN, null); 1395 } 1396 1397 1398 1399 /** 1400 * Alters the DN of an entry in the directory. 1401 * 1402 * @param dn The DN of the entry to modify. 1403 * @param newRDN The new RDN to use for the entry. 1404 * @param deleteOldRDN Indicates whether to remove the old RDN value(s). 1405 * @param constraints The constraints to use for the modify operation. 1406 * 1407 * @throws LDAPException If a problem occurs while processing the delete. 1408 */ 1409 public void rename(@NotNull final String dn, @NotNull final String newRDN, 1410 final boolean deleteOldRDN, 1411 @Nullable final LDAPConstraints constraints) 1412 throws LDAPException 1413 { 1414 rename(dn, newRDN, null, deleteOldRDN, constraints); 1415 } 1416 1417 1418 1419 /** 1420 * Alters the DN of an entry in the directory. 1421 * 1422 * @param dn The DN of the entry to modify. 1423 * @param newRDN The new RDN to use for the entry. 1424 * @param newParentDN The DN of the new parent, or {@code null} if it 1425 * should not be moved below a new parent. 1426 * @param deleteOldRDN Indicates whether to remove the old RDN value(s). 1427 * 1428 * @throws LDAPException If a problem occurs while processing the delete. 1429 */ 1430 public void rename(@NotNull final String dn, @NotNull final String newRDN, 1431 @Nullable final String newParentDN, 1432 final boolean deleteOldRDN) 1433 throws LDAPException 1434 { 1435 rename(dn, newRDN, newParentDN, deleteOldRDN, null); 1436 } 1437 1438 1439 1440 /** 1441 * Alters the DN of an entry in the directory. 1442 * 1443 * @param dn The DN of the entry to modify. 1444 * @param newRDN The new RDN to use for the entry. 1445 * @param newParentDN The DN of the new parent, or {@code null} if it 1446 * should not be moved below a new parent. 1447 * @param deleteOldRDN Indicates whether to remove the old RDN value(s). 1448 * @param constraints The constraints to use for the modify operation. 1449 * 1450 * @throws LDAPException If a problem occurs while processing the delete. 1451 */ 1452 public void rename(@NotNull final String dn, @NotNull final String newRDN, 1453 @Nullable final String newParentDN, 1454 final boolean deleteOldRDN, 1455 @Nullable final LDAPConstraints constraints) 1456 throws LDAPException 1457 { 1458 final ModifyDNRequest modifyDNRequest = 1459 new ModifyDNRequest(dn, newRDN, deleteOldRDN, newParentDN); 1460 update(modifyDNRequest, constraints); 1461 1462 try 1463 { 1464 final LDAPResult result = conn.modifyDN(modifyDNRequest); 1465 setResponseControls(result); 1466 } 1467 catch (final com.unboundid.ldap.sdk.LDAPException le) 1468 { 1469 Debug.debugException(le); 1470 setResponseControls(le); 1471 throw new LDAPException(le); 1472 } 1473 } 1474 1475 1476 1477 /** 1478 * Processes a search in the directory server. 1479 * 1480 * @param baseDN The base DN for the search. 1481 * @param scope The scope for the search. 1482 * @param filter The filter for the search. 1483 * @param attributes The set of attributes to request. 1484 * @param typesOnly Indicates whether to return attribute types only or 1485 * both types and values. 1486 * 1487 * @return The entry that was read. 1488 * 1489 * @throws LDAPException If a problem occurs while performing the search. 1490 */ 1491 @NotNull() 1492 public LDAPSearchResults search(@NotNull final String baseDN, final int scope, 1493 @NotNull final String filter, 1494 @Nullable final String[] attributes, 1495 final boolean typesOnly) 1496 throws LDAPException 1497 { 1498 return search(baseDN, scope, filter, attributes, typesOnly, null); 1499 } 1500 1501 1502 1503 /** 1504 * Processes a search in the directory server. 1505 * 1506 * @param baseDN The base DN for the search. 1507 * @param scope The scope for the search. 1508 * @param filter The filter for the search. 1509 * @param attributes The set of attributes to request. 1510 * @param typesOnly Indicates whether to return attribute types only or 1511 * both types and values. 1512 * @param constraints The constraints to use for the search operation. 1513 * 1514 * @return The entry that was read. 1515 * 1516 * @throws LDAPException If a problem occurs while performing the search. 1517 */ 1518 @NotNull() 1519 public LDAPSearchResults search(@NotNull final String baseDN, final int scope, 1520 @NotNull final String filter, 1521 @Nullable final String[] attributes, 1522 final boolean typesOnly, 1523 @Nullable final LDAPSearchConstraints constraints) 1524 throws LDAPException 1525 { 1526 final LDAPSearchResults results; 1527 final LDAPSearchConstraints c = 1528 (constraints == null) ? searchConstraints : constraints; 1529 results = new LDAPSearchResults(c.getTimeLimit()); 1530 1531 try 1532 { 1533 final SearchRequest searchRequest = new SearchRequest(results, baseDN, 1534 SearchScope.valueOf(scope), filter, attributes); 1535 1536 searchRequest.setDerefPolicy( 1537 DereferencePolicy.valueOf(c.getDereference())); 1538 searchRequest.setSizeLimit(c.getMaxResults()); 1539 searchRequest.setTimeLimitSeconds(c.getServerTimeLimit()); 1540 searchRequest.setTypesOnly(typesOnly); 1541 1542 update(searchRequest, constraints); 1543 1544 results.setAsyncRequestID(conn.asyncSearch(searchRequest)); 1545 return results; 1546 } 1547 catch (final com.unboundid.ldap.sdk.LDAPException le) 1548 { 1549 Debug.debugException(le); 1550 setResponseControls(le); 1551 throw new LDAPException(le); 1552 } 1553 } 1554 1555 1556 1557 /** 1558 * Retrieves the set of controls to use in a request. 1559 * 1560 * @param c The constraints to be applied. 1561 * 1562 * @return The set of controls to use in a request. 1563 */ 1564 @NotNull() 1565 private Control[] getControls(@Nullable final LDAPConstraints c) 1566 { 1567 Control[] controls = null; 1568 if (c != null) 1569 { 1570 controls = LDAPControl.toControls(c.getServerControls()); 1571 } 1572 else if (constraints != null) 1573 { 1574 controls = LDAPControl.toControls(constraints.getServerControls()); 1575 } 1576 1577 if (controls == null) 1578 { 1579 return new Control[0]; 1580 } 1581 else 1582 { 1583 return controls; 1584 } 1585 } 1586 1587 1588 1589 /** 1590 * Updates the provided request to account for the given set of constraints. 1591 * 1592 * @param request The request to be updated. 1593 * @param constraints The constraints to be applied. 1594 */ 1595 private void update(@NotNull final UpdatableLDAPRequest request, 1596 @Nullable final LDAPConstraints constraints) 1597 { 1598 final LDAPConstraints c = 1599 (constraints == null) ? this.constraints : constraints; 1600 1601 request.setControls(LDAPControl.toControls(c.getServerControls())); 1602 request.setResponseTimeoutMillis(c.getTimeLimit()); 1603 request.setFollowReferrals(c.getReferrals()); 1604 } 1605 1606 1607 1608 /** 1609 * Sets the response controls for this connection. 1610 * 1611 * @param ldapResult The result containing the controls to use. 1612 */ 1613 private void setResponseControls(@NotNull final LDAPResult ldapResult) 1614 { 1615 if (ldapResult.hasResponseControl()) 1616 { 1617 responseControls = 1618 LDAPControl.toLDAPControls(ldapResult.getResponseControls()); 1619 } 1620 else 1621 { 1622 responseControls = null; 1623 } 1624 } 1625 1626 1627 1628 /** 1629 * Sets the response controls for this connection. 1630 * 1631 * @param ldapException The exception containing the controls to use. 1632 */ 1633 private void setResponseControls( 1634 @NotNull final com.unboundid.ldap.sdk.LDAPException ldapException) 1635 { 1636 if (ldapException.hasResponseControl()) 1637 { 1638 responseControls = 1639 LDAPControl.toLDAPControls(ldapException.getResponseControls()); 1640 } 1641 else 1642 { 1643 responseControls = null; 1644 } 1645 } 1646}