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