001/* 002 * Copyright 2007-2017 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2017 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; 022 023 024 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.List; 028import java.util.concurrent.LinkedBlockingQueue; 029import java.util.concurrent.TimeUnit; 030import java.util.logging.Level; 031 032import com.unboundid.asn1.ASN1Buffer; 033import com.unboundid.asn1.ASN1BufferSequence; 034import com.unboundid.asn1.ASN1Element; 035import com.unboundid.asn1.ASN1Integer; 036import com.unboundid.asn1.ASN1OctetString; 037import com.unboundid.asn1.ASN1Sequence; 038import com.unboundid.ldap.protocol.LDAPMessage; 039import com.unboundid.ldap.protocol.LDAPResponse; 040import com.unboundid.ldap.protocol.ProtocolOp; 041import com.unboundid.util.InternalUseOnly; 042import com.unboundid.util.LDAPSDKUsageException; 043import com.unboundid.util.NotMutable; 044import com.unboundid.util.ThreadSafety; 045import com.unboundid.util.ThreadSafetyLevel; 046 047import static com.unboundid.ldap.sdk.LDAPMessages.*; 048import static com.unboundid.util.Debug.*; 049import static com.unboundid.util.StaticUtils.*; 050 051 052 053/** 054 * This class implements the processing necessary to perform an LDAPv3 simple 055 * bind operation, which authenticates using a bind DN and password. 056 */ 057@NotMutable() 058@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 059public final class SimpleBindRequest 060 extends BindRequest 061 implements ResponseAcceptor, ProtocolOp 062{ 063 /** 064 * The BER type to use for the credentials element in a simple bind request 065 * protocol op. 066 */ 067 private static final byte CRED_TYPE_SIMPLE = (byte) 0x80; 068 069 070 071 /** 072 * The ASN.1 octet string that will be used for the bind DN if none was 073 * provided. 074 */ 075 private static final ASN1OctetString NO_BIND_DN = new ASN1OctetString(); 076 077 078 079 /** 080 * The ASN.1 octet string that will be used for the bind password if none was 081 * provided. 082 */ 083 private static final ASN1OctetString NO_PASSWORD = 084 new ASN1OctetString(CRED_TYPE_SIMPLE); 085 086 087 088 /** 089 * The serial version UID for this serializable class. 090 */ 091 private static final long serialVersionUID = 4725871243149974407L; 092 093 094 095 // The message ID from the last LDAP message sent from this request. 096 private int messageID = -1; 097 098 // The bind DN for this simple bind request. 099 private final ASN1OctetString bindDN; 100 101 // The password for this simple bind request. 102 private final ASN1OctetString password; 103 104 // The queue that will be used to receive response messages from the server. 105 private final LinkedBlockingQueue<LDAPResponse> responseQueue = 106 new LinkedBlockingQueue<LDAPResponse>(); 107 108 // The password provider that should be used to obtain the password for this 109 // simple bind request. 110 private final PasswordProvider passwordProvider; 111 112 113 114 /** 115 * Creates a new simple bind request that may be used to perform an anonymous 116 * bind to the directory server (i.e., with a zero-length bind DN and a 117 * zero-length password). 118 */ 119 public SimpleBindRequest() 120 { 121 this(NO_BIND_DN, NO_PASSWORD, null, NO_CONTROLS); 122 } 123 124 125 126 /** 127 * Creates a new simple bind request with the provided bind DN and password. 128 * 129 * @param bindDN The bind DN for this simple bind request. 130 * @param password The password for this simple bind request. 131 */ 132 public SimpleBindRequest(final String bindDN, final String password) 133 { 134 this(bindDN, password, NO_CONTROLS); 135 } 136 137 138 139 /** 140 * Creates a new simple bind request with the provided bind DN and password. 141 * 142 * @param bindDN The bind DN for this simple bind request. 143 * @param password The password for this simple bind request. 144 */ 145 public SimpleBindRequest(final String bindDN, final byte[] password) 146 { 147 this(bindDN, password, NO_CONTROLS); 148 } 149 150 151 152 /** 153 * Creates a new simple bind request with the provided bind DN and password. 154 * 155 * @param bindDN The bind DN for this simple bind request. 156 * @param password The password for this simple bind request. 157 */ 158 public SimpleBindRequest(final DN bindDN, final String password) 159 { 160 this(bindDN, password, NO_CONTROLS); 161 } 162 163 164 165 /** 166 * Creates a new simple bind request with the provided bind DN and password. 167 * 168 * @param bindDN The bind DN for this simple bind request. 169 * @param password The password for this simple bind request. 170 */ 171 public SimpleBindRequest(final DN bindDN, final byte[] password) 172 { 173 this(bindDN, password, NO_CONTROLS); 174 } 175 176 177 178 /** 179 * Creates a new simple bind request with the provided bind DN and password. 180 * 181 * @param bindDN The bind DN for this simple bind request. 182 * @param password The password for this simple bind request. 183 * @param controls The set of controls for this simple bind request. 184 */ 185 public SimpleBindRequest(final String bindDN, final String password, 186 final Control... controls) 187 { 188 super(controls); 189 190 if (bindDN == null) 191 { 192 this.bindDN = NO_BIND_DN; 193 } 194 else 195 { 196 this.bindDN = new ASN1OctetString(bindDN); 197 } 198 199 if (password == null) 200 { 201 this.password = NO_PASSWORD; 202 } 203 else 204 { 205 this.password = new ASN1OctetString(CRED_TYPE_SIMPLE, password); 206 } 207 208 passwordProvider = null; 209 } 210 211 212 213 /** 214 * Creates a new simple bind request with the provided bind DN and password. 215 * 216 * @param bindDN The bind DN for this simple bind request. 217 * @param password The password for this simple bind request. 218 * @param controls The set of controls for this simple bind request. 219 */ 220 public SimpleBindRequest(final String bindDN, final byte[] password, 221 final Control... controls) 222 { 223 super(controls); 224 225 if (bindDN == null) 226 { 227 this.bindDN = NO_BIND_DN; 228 } 229 else 230 { 231 this.bindDN = new ASN1OctetString(bindDN); 232 } 233 234 if (password == null) 235 { 236 this.password = NO_PASSWORD; 237 } 238 else 239 { 240 this.password = new ASN1OctetString(CRED_TYPE_SIMPLE, password); 241 } 242 243 passwordProvider = null; 244 } 245 246 247 248 /** 249 * Creates a new simple bind request with the provided bind DN and password. 250 * 251 * @param bindDN The bind DN for this simple bind request. 252 * @param password The password for this simple bind request. 253 * @param controls The set of controls for this simple bind request. 254 */ 255 public SimpleBindRequest(final DN bindDN, final String password, 256 final Control... controls) 257 { 258 super(controls); 259 260 if (bindDN == null) 261 { 262 this.bindDN = NO_BIND_DN; 263 } 264 else 265 { 266 this.bindDN = new ASN1OctetString(bindDN.toString()); 267 } 268 269 if (password == null) 270 { 271 this.password = NO_PASSWORD; 272 } 273 else 274 { 275 this.password = new ASN1OctetString(CRED_TYPE_SIMPLE, password); 276 } 277 278 passwordProvider = null; 279 } 280 281 282 283 /** 284 * Creates a new simple bind request with the provided bind DN and password. 285 * 286 * @param bindDN The bind DN for this simple bind request. 287 * @param password The password for this simple bind request. 288 * @param controls The set of controls for this simple bind request. 289 */ 290 public SimpleBindRequest(final DN bindDN, final byte[] password, 291 final Control... controls) 292 { 293 super(controls); 294 295 if (bindDN == null) 296 { 297 this.bindDN = NO_BIND_DN; 298 } 299 else 300 { 301 this.bindDN = new ASN1OctetString(bindDN.toString()); 302 } 303 304 if (password == null) 305 { 306 this.password = NO_PASSWORD; 307 } 308 else 309 { 310 this.password = new ASN1OctetString(CRED_TYPE_SIMPLE, password); 311 } 312 313 passwordProvider = null; 314 } 315 316 317 318 /** 319 * Creates a new simple bind request with the provided bind DN and that will 320 * use a password provider in order to obtain the bind password. 321 * 322 * @param bindDN The bind DN for this simple bind request. It 323 * must not be {@code null}. 324 * @param passwordProvider The password provider that will be used to obtain 325 * the password for this simple bind request. It 326 * must not be {@code null}. 327 * @param controls The set of controls for this simple bind request. 328 */ 329 public SimpleBindRequest(final String bindDN, 330 final PasswordProvider passwordProvider, 331 final Control... controls) 332 { 333 super(controls); 334 335 this.bindDN = new ASN1OctetString(bindDN); 336 this.passwordProvider = passwordProvider; 337 338 password = null; 339 } 340 341 342 343 /** 344 * Creates a new simple bind request with the provided bind DN and that will 345 * use a password provider in order to obtain the bind password. 346 * 347 * @param bindDN The bind DN for this simple bind request. It 348 * must not be {@code null}. 349 * @param passwordProvider The password provider that will be used to obtain 350 * the password for this simple bind request. It 351 * must not be {@code null}. 352 * @param controls The set of controls for this simple bind request. 353 */ 354 public SimpleBindRequest(final DN bindDN, 355 final PasswordProvider passwordProvider, 356 final Control... controls) 357 { 358 super(controls); 359 360 this.bindDN = new ASN1OctetString(bindDN.toString()); 361 this.passwordProvider = passwordProvider; 362 363 password = null; 364 } 365 366 367 368 /** 369 * Creates a new simple bind request with the provided bind DN and password. 370 * 371 * @param bindDN The bind DN for this simple bind request. 372 * @param password The password for this simple bind request. 373 * @param passwordProvider The password provider that will be used to obtain 374 * the password to use for the bind request. 375 * @param controls The set of controls for this simple bind request. 376 */ 377 private SimpleBindRequest(final ASN1OctetString bindDN, 378 final ASN1OctetString password, 379 final PasswordProvider passwordProvider, 380 final Control... controls) 381 { 382 super(controls); 383 384 this.bindDN = bindDN; 385 this.password = password; 386 this.passwordProvider = passwordProvider; 387 } 388 389 390 391 /** 392 * Retrieves the bind DN for this simple bind request. 393 * 394 * @return The bind DN for this simple bind request. 395 */ 396 public String getBindDN() 397 { 398 return bindDN.stringValue(); 399 } 400 401 402 403 /** 404 * Retrieves the password for this simple bind request, if no password 405 * provider has been configured. 406 * 407 * @return The password for this simple bind request, or {@code null} if a 408 * password provider will be used to obtain the password. 409 */ 410 public ASN1OctetString getPassword() 411 { 412 return password; 413 } 414 415 416 417 /** 418 * Retrieves the password provider for this simple bind request, if defined. 419 * 420 * @return The password provider for this simple bind request, or 421 * {@code null} if this bind request was created with an explicit 422 * password rather than a password provider. 423 */ 424 public PasswordProvider getPasswordProvider() 425 { 426 return passwordProvider; 427 } 428 429 430 431 /** 432 * {@inheritDoc} 433 */ 434 @Override() 435 public byte getProtocolOpType() 436 { 437 return LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST; 438 } 439 440 441 442 /** 443 * {@inheritDoc} 444 */ 445 @Override() 446 public void writeTo(final ASN1Buffer buffer) 447 { 448 final ASN1BufferSequence requestSequence = 449 buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST); 450 buffer.addElement(VERSION_ELEMENT); 451 buffer.addElement(bindDN); 452 453 if (passwordProvider == null) 454 { 455 buffer.addElement(password); 456 } 457 else 458 { 459 final byte[] pwBytes; 460 try 461 { 462 pwBytes = passwordProvider.getPasswordBytes(); 463 } 464 catch (final LDAPException le) 465 { 466 debugException(le); 467 throw new LDAPRuntimeException(le); 468 } 469 470 final ASN1OctetString pw = new ASN1OctetString(CRED_TYPE_SIMPLE, pwBytes); 471 buffer.addElement(pw); 472 buffer.setZeroBufferOnClear(); 473 Arrays.fill(pwBytes, (byte) 0x00); 474 } 475 476 requestSequence.end(); 477 } 478 479 480 481 /** 482 * {@inheritDoc} 483 * Use of this method is only supported if the bind request was created with a 484 * static password. It is not allowed if the password will be obtained 485 * through a password provider. 486 * 487 * @throws LDAPSDKUsageException If this bind request was created with a 488 * password provider rather than a static 489 * password. 490 */ 491 @Override() 492 public ASN1Element encodeProtocolOp() 493 throws LDAPSDKUsageException 494 { 495 if (password == null) 496 { 497 throw new LDAPSDKUsageException( 498 ERR_SIMPLE_BIND_ENCODE_PROTOCOL_OP_WITH_PROVIDER.get()); 499 } 500 501 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST, 502 new ASN1Integer(3), 503 bindDN, 504 password); 505 } 506 507 508 509 /** 510 * {@inheritDoc} 511 */ 512 @Override() 513 protected BindResult process(final LDAPConnection connection, final int depth) 514 throws LDAPException 515 { 516 if (connection.synchronousMode()) 517 { 518 @SuppressWarnings("deprecation") 519 final boolean autoReconnect = 520 connection.getConnectionOptions().autoReconnect(); 521 return processSync(connection, autoReconnect); 522 } 523 524 // See if a bind DN was provided without a password. If that is the case 525 // and this should not be allowed, then throw an exception. 526 if (password != null) 527 { 528 if ((bindDN.getValue().length > 0) && (password.getValue().length == 0) && 529 connection.getConnectionOptions().bindWithDNRequiresPassword()) 530 { 531 final LDAPException le = new LDAPException(ResultCode.PARAM_ERROR, 532 ERR_SIMPLE_BIND_DN_WITHOUT_PASSWORD.get()); 533 debugCodingError(le); 534 throw le; 535 } 536 } 537 538 539 // Create the LDAP message. 540 messageID = connection.nextMessageID(); 541 final LDAPMessage message = new LDAPMessage(messageID, this, getControls()); 542 543 544 // Register with the connection reader to be notified of responses for the 545 // request that we've created. 546 connection.registerResponseAcceptor(messageID, this); 547 548 549 try 550 { 551 // Send the request to the server. 552 debugLDAPRequest(Level.INFO, this, messageID, connection); 553 final long requestTime = System.nanoTime(); 554 connection.getConnectionStatistics().incrementNumBindRequests(); 555 connection.sendMessage(message); 556 557 // Wait for and process the response. 558 final LDAPResponse response; 559 try 560 { 561 final long responseTimeout = getResponseTimeoutMillis(connection); 562 if (responseTimeout > 0) 563 { 564 response = responseQueue.poll(responseTimeout, TimeUnit.MILLISECONDS); 565 } 566 else 567 { 568 response = responseQueue.take(); 569 } 570 } 571 catch (final InterruptedException ie) 572 { 573 debugException(ie); 574 Thread.currentThread().interrupt(); 575 throw new LDAPException(ResultCode.LOCAL_ERROR, 576 ERR_BIND_INTERRUPTED.get(connection.getHostPort()), ie); 577 } 578 579 return handleResponse(connection, response, requestTime, false); 580 } 581 finally 582 { 583 connection.deregisterResponseAcceptor(messageID); 584 } 585 } 586 587 588 589 /** 590 * Processes this bind operation in synchronous mode, in which the same 591 * thread will send the request and read the response. 592 * 593 * @param connection The connection to use to communicate with the directory 594 * server. 595 * @param allowRetry Indicates whether the request may be re-tried on a 596 * re-established connection if the initial attempt fails 597 * in a way that indicates the connection is no longer 598 * valid and autoReconnect is true. 599 * 600 * @return An LDAP result object that provides information about the result 601 * of the bind processing. 602 * 603 * @throws LDAPException If a problem occurs while sending the request or 604 * reading the response. 605 */ 606 private BindResult processSync(final LDAPConnection connection, 607 final boolean allowRetry) 608 throws LDAPException 609 { 610 // Create the LDAP message. 611 messageID = connection.nextMessageID(); 612 final LDAPMessage message = 613 new LDAPMessage(messageID, this, getControls()); 614 615 616 // Set the appropriate timeout on the socket. 617 try 618 { 619 InternalSDKHelper.setSoTimeout(connection, 620 (int) getResponseTimeoutMillis(connection)); 621 } 622 catch (final Exception e) 623 { 624 debugException(e); 625 } 626 627 628 // Send the request to the server. 629 final long requestTime = System.nanoTime(); 630 debugLDAPRequest(Level.INFO, this, messageID, connection); 631 connection.getConnectionStatistics().incrementNumBindRequests(); 632 try 633 { 634 connection.sendMessage(message); 635 } 636 catch (final LDAPException le) 637 { 638 debugException(le); 639 640 if (allowRetry) 641 { 642 final BindResult bindResult = reconnectAndRetry(connection, 643 le.getResultCode()); 644 if (bindResult != null) 645 { 646 return bindResult; 647 } 648 } 649 650 throw le; 651 } 652 653 while (true) 654 { 655 final LDAPResponse response = connection.readResponse(messageID); 656 if (response instanceof IntermediateResponse) 657 { 658 final IntermediateResponseListener listener = 659 getIntermediateResponseListener(); 660 if (listener != null) 661 { 662 listener.intermediateResponseReturned( 663 (IntermediateResponse) response); 664 } 665 } 666 else 667 { 668 return handleResponse(connection, response, requestTime, allowRetry); 669 } 670 } 671 } 672 673 674 675 /** 676 * Performs the necessary processing for handling a response. 677 * 678 * @param connection The connection used to read the response. 679 * @param response The response to be processed. 680 * @param requestTime The time the request was sent to the server. 681 * @param allowRetry Indicates whether the request may be re-tried on a 682 * re-established connection if the initial attempt fails 683 * in a way that indicates the connection is no longer 684 * valid and autoReconnect is true. 685 * 686 * @return The bind result. 687 * 688 * @throws LDAPException If a problem occurs. 689 */ 690 private BindResult handleResponse(final LDAPConnection connection, 691 final LDAPResponse response, 692 final long requestTime, 693 final boolean allowRetry) 694 throws LDAPException 695 { 696 if (response == null) 697 { 698 final long waitTime = nanosToMillis(System.nanoTime() - requestTime); 699 throw new LDAPException(ResultCode.TIMEOUT, 700 ERR_SIMPLE_BIND_CLIENT_TIMEOUT.get(waitTime, messageID, 701 bindDN.stringValue(), connection.getHostPort())); 702 } 703 704 connection.getConnectionStatistics().incrementNumBindResponses( 705 System.nanoTime() - requestTime); 706 if (response instanceof ConnectionClosedResponse) 707 { 708 // The connection was closed while waiting for the response. 709 if (allowRetry) 710 { 711 final BindResult retryResult = reconnectAndRetry(connection, 712 ResultCode.SERVER_DOWN); 713 if (retryResult != null) 714 { 715 return retryResult; 716 } 717 } 718 719 final ConnectionClosedResponse ccr = (ConnectionClosedResponse) response; 720 final String message = ccr.getMessage(); 721 if (message == null) 722 { 723 throw new LDAPException(ccr.getResultCode(), 724 ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE.get( 725 connection.getHostPort(), toString())); 726 } 727 else 728 { 729 throw new LDAPException(ccr.getResultCode(), 730 ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE_WITH_MESSAGE.get( 731 connection.getHostPort(), toString(), message)); 732 } 733 } 734 735 final BindResult bindResult = (BindResult) response; 736 if (allowRetry) 737 { 738 final BindResult retryResult = reconnectAndRetry(connection, 739 bindResult.getResultCode()); 740 if (retryResult != null) 741 { 742 return retryResult; 743 } 744 } 745 746 return bindResult; 747 } 748 749 750 751 /** 752 * Attempts to re-establish the connection and retry processing this request 753 * on it. 754 * 755 * @param connection The connection to be re-established. 756 * @param resultCode The result code for the previous operation attempt. 757 * 758 * @return The result from re-trying the bind, or {@code null} if it could 759 * not be re-tried. 760 */ 761 private BindResult reconnectAndRetry(final LDAPConnection connection, 762 final ResultCode resultCode) 763 { 764 try 765 { 766 // We will only want to retry for certain result codes that indicate a 767 // connection problem. 768 switch (resultCode.intValue()) 769 { 770 case ResultCode.SERVER_DOWN_INT_VALUE: 771 case ResultCode.DECODING_ERROR_INT_VALUE: 772 case ResultCode.CONNECT_ERROR_INT_VALUE: 773 connection.reconnect(); 774 return processSync(connection, false); 775 } 776 } 777 catch (final Exception e) 778 { 779 debugException(e); 780 } 781 782 return null; 783 } 784 785 786 787 /** 788 * {@inheritDoc} 789 */ 790 @Override() 791 public SimpleBindRequest getRebindRequest(final String host, final int port) 792 { 793 return new SimpleBindRequest(bindDN, password, passwordProvider, 794 getControls()); 795 } 796 797 798 799 /** 800 * {@inheritDoc} 801 */ 802 @InternalUseOnly() 803 @Override() 804 public void responseReceived(final LDAPResponse response) 805 throws LDAPException 806 { 807 try 808 { 809 responseQueue.put(response); 810 } 811 catch (final Exception e) 812 { 813 debugException(e); 814 815 if (e instanceof InterruptedException) 816 { 817 Thread.currentThread().interrupt(); 818 } 819 820 throw new LDAPException(ResultCode.LOCAL_ERROR, 821 ERR_EXCEPTION_HANDLING_RESPONSE.get(getExceptionMessage(e)), e); 822 } 823 } 824 825 826 827 /** 828 * {@inheritDoc} 829 */ 830 @Override() 831 public String getBindType() 832 { 833 return "SIMPLE"; 834 } 835 836 837 838 /** 839 * {@inheritDoc} 840 */ 841 @Override() 842 public int getLastMessageID() 843 { 844 return messageID; 845 } 846 847 848 849 /** 850 * {@inheritDoc} 851 */ 852 @Override() 853 public SimpleBindRequest duplicate() 854 { 855 return duplicate(getControls()); 856 } 857 858 859 860 /** 861 * {@inheritDoc} 862 */ 863 @Override() 864 public SimpleBindRequest duplicate(final Control[] controls) 865 { 866 final SimpleBindRequest bindRequest = 867 new SimpleBindRequest(bindDN, password, passwordProvider, controls); 868 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 869 return bindRequest; 870 } 871 872 873 874 /** 875 * {@inheritDoc} 876 */ 877 @Override() 878 public void toString(final StringBuilder buffer) 879 { 880 buffer.append("SimpleBindRequest(dn='"); 881 buffer.append(bindDN); 882 buffer.append('\''); 883 884 final Control[] controls = getControls(); 885 if (controls.length > 0) 886 { 887 buffer.append(", controls={"); 888 for (int i=0; i < controls.length; i++) 889 { 890 if (i > 0) 891 { 892 buffer.append(", "); 893 } 894 895 buffer.append(controls[i]); 896 } 897 buffer.append('}'); 898 } 899 900 buffer.append(')'); 901 } 902 903 904 905 /** 906 * {@inheritDoc} 907 */ 908 @Override() 909 public void toCode(final List<String> lineList, final String requestID, 910 final int indentSpaces, final boolean includeProcessing) 911 { 912 // Create the request variable. 913 final ArrayList<ToCodeArgHelper> constructorArgs = 914 new ArrayList<ToCodeArgHelper>(3); 915 constructorArgs.add(ToCodeArgHelper.createString(bindDN.stringValue(), 916 "Bind DN")); 917 constructorArgs.add(ToCodeArgHelper.createString("---redacted-password---", 918 "Bind Password")); 919 920 final Control[] controls = getControls(); 921 if (controls.length > 0) 922 { 923 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 924 "Bind Controls")); 925 } 926 927 ToCodeHelper.generateMethodCall(lineList, indentSpaces, "SimpleBindRequest", 928 requestID + "Request", "new SimpleBindRequest", constructorArgs); 929 930 931 // Add lines for processing the request and obtaining the result. 932 if (includeProcessing) 933 { 934 // Generate a string with the appropriate indent. 935 final StringBuilder buffer = new StringBuilder(); 936 for (int i=0; i < indentSpaces; i++) 937 { 938 buffer.append(' '); 939 } 940 final String indent = buffer.toString(); 941 942 lineList.add(""); 943 lineList.add(indent + "try"); 944 lineList.add(indent + '{'); 945 lineList.add(indent + " BindResult " + requestID + 946 "Result = connection.bind(" + requestID + "Request);"); 947 lineList.add(indent + " // The bind was processed successfully."); 948 lineList.add(indent + '}'); 949 lineList.add(indent + "catch (LDAPException e)"); 950 lineList.add(indent + '{'); 951 lineList.add(indent + " // The bind failed. Maybe the following will " + 952 "help explain why."); 953 lineList.add(indent + " // Note that the connection is now likely in " + 954 "an unauthenticated state."); 955 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 956 lineList.add(indent + " String message = e.getMessage();"); 957 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 958 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 959 lineList.add(indent + " Control[] responseControls = " + 960 "e.getResponseControls();"); 961 lineList.add(indent + '}'); 962 } 963 } 964}