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