001/* 002 * Copyright 2007-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-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; 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.Debug; 042import com.unboundid.util.InternalUseOnly; 043import com.unboundid.util.LDAPSDKUsageException; 044import com.unboundid.util.NotMutable; 045import com.unboundid.util.StaticUtils; 046import com.unboundid.util.ThreadSafety; 047import com.unboundid.util.ThreadSafetyLevel; 048 049import static com.unboundid.ldap.sdk.LDAPMessages.*; 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<>(); 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 Debug.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 // See if a bind DN was provided without a password. If that is the case 517 // and this should not be allowed, then throw an exception. 518 if (password != null) 519 { 520 if ((bindDN.getValue().length > 0) && (password.getValue().length == 0) && 521 connection.getConnectionOptions().bindWithDNRequiresPassword()) 522 { 523 final LDAPException le = new LDAPException(ResultCode.PARAM_ERROR, 524 ERR_SIMPLE_BIND_DN_WITHOUT_PASSWORD.get()); 525 Debug.debugCodingError(le); 526 throw le; 527 } 528 } 529 530 531 if (connection.synchronousMode()) 532 { 533 @SuppressWarnings("deprecation") 534 final boolean autoReconnect = 535 connection.getConnectionOptions().autoReconnect(); 536 return processSync(connection, autoReconnect); 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 final long responseTimeout = getResponseTimeoutMillis(connection); 553 Debug.debugLDAPRequest(Level.INFO, this, messageID, connection); 554 final long requestTime = System.nanoTime(); 555 connection.getConnectionStatistics().incrementNumBindRequests(); 556 connection.sendMessage(message, responseTimeout); 557 558 // Wait for and process the response. 559 final LDAPResponse response; 560 try 561 { 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 Debug.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 // Send the request to the server. 617 final long requestTime = System.nanoTime(); 618 Debug.debugLDAPRequest(Level.INFO, this, messageID, connection); 619 connection.getConnectionStatistics().incrementNumBindRequests(); 620 try 621 { 622 connection.sendMessage(message, getResponseTimeoutMillis(connection)); 623 } 624 catch (final LDAPException le) 625 { 626 Debug.debugException(le); 627 628 if (allowRetry) 629 { 630 final BindResult bindResult = reconnectAndRetry(connection, 631 le.getResultCode()); 632 if (bindResult != null) 633 { 634 return bindResult; 635 } 636 } 637 638 throw le; 639 } 640 641 while (true) 642 { 643 final LDAPResponse response = connection.readResponse(messageID); 644 if (response instanceof IntermediateResponse) 645 { 646 final IntermediateResponseListener listener = 647 getIntermediateResponseListener(); 648 if (listener != null) 649 { 650 listener.intermediateResponseReturned( 651 (IntermediateResponse) response); 652 } 653 } 654 else 655 { 656 return handleResponse(connection, response, requestTime, allowRetry); 657 } 658 } 659 } 660 661 662 663 /** 664 * Performs the necessary processing for handling a response. 665 * 666 * @param connection The connection used to read the response. 667 * @param response The response to be processed. 668 * @param requestTime The time the request was sent to the server. 669 * @param allowRetry Indicates whether the request may be re-tried on a 670 * re-established connection if the initial attempt fails 671 * in a way that indicates the connection is no longer 672 * valid and autoReconnect is true. 673 * 674 * @return The bind result. 675 * 676 * @throws LDAPException If a problem occurs. 677 */ 678 private BindResult handleResponse(final LDAPConnection connection, 679 final LDAPResponse response, 680 final long requestTime, 681 final boolean allowRetry) 682 throws LDAPException 683 { 684 if (response == null) 685 { 686 final long waitTime = 687 StaticUtils.nanosToMillis(System.nanoTime() - requestTime); 688 throw new LDAPException(ResultCode.TIMEOUT, 689 ERR_SIMPLE_BIND_CLIENT_TIMEOUT.get(waitTime, messageID, 690 bindDN.stringValue(), connection.getHostPort())); 691 } 692 693 connection.getConnectionStatistics().incrementNumBindResponses( 694 System.nanoTime() - requestTime); 695 if (response instanceof ConnectionClosedResponse) 696 { 697 // The connection was closed while waiting for the response. 698 if (allowRetry) 699 { 700 final BindResult retryResult = reconnectAndRetry(connection, 701 ResultCode.SERVER_DOWN); 702 if (retryResult != null) 703 { 704 return retryResult; 705 } 706 } 707 708 final ConnectionClosedResponse ccr = (ConnectionClosedResponse) response; 709 final String message = ccr.getMessage(); 710 if (message == null) 711 { 712 throw new LDAPException(ccr.getResultCode(), 713 ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE.get( 714 connection.getHostPort(), toString())); 715 } 716 else 717 { 718 throw new LDAPException(ccr.getResultCode(), 719 ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE_WITH_MESSAGE.get( 720 connection.getHostPort(), toString(), message)); 721 } 722 } 723 724 final BindResult bindResult = (BindResult) response; 725 if (allowRetry) 726 { 727 final BindResult retryResult = reconnectAndRetry(connection, 728 bindResult.getResultCode()); 729 if (retryResult != null) 730 { 731 return retryResult; 732 } 733 } 734 735 return bindResult; 736 } 737 738 739 740 /** 741 * Attempts to re-establish the connection and retry processing this request 742 * on it. 743 * 744 * @param connection The connection to be re-established. 745 * @param resultCode The result code for the previous operation attempt. 746 * 747 * @return The result from re-trying the bind, or {@code null} if it could 748 * not be re-tried. 749 */ 750 private BindResult reconnectAndRetry(final LDAPConnection connection, 751 final ResultCode resultCode) 752 { 753 try 754 { 755 // We will only want to retry for certain result codes that indicate a 756 // connection problem. 757 switch (resultCode.intValue()) 758 { 759 case ResultCode.SERVER_DOWN_INT_VALUE: 760 case ResultCode.DECODING_ERROR_INT_VALUE: 761 case ResultCode.CONNECT_ERROR_INT_VALUE: 762 connection.reconnect(); 763 return processSync(connection, false); 764 } 765 } 766 catch (final Exception e) 767 { 768 Debug.debugException(e); 769 } 770 771 return null; 772 } 773 774 775 776 /** 777 * {@inheritDoc} 778 */ 779 @Override() 780 public SimpleBindRequest getRebindRequest(final String host, final int port) 781 { 782 return new SimpleBindRequest(bindDN, password, passwordProvider, 783 getControls()); 784 } 785 786 787 788 /** 789 * {@inheritDoc} 790 */ 791 @InternalUseOnly() 792 @Override() 793 public void responseReceived(final LDAPResponse response) 794 throws LDAPException 795 { 796 try 797 { 798 responseQueue.put(response); 799 } 800 catch (final Exception e) 801 { 802 Debug.debugException(e); 803 804 if (e instanceof InterruptedException) 805 { 806 Thread.currentThread().interrupt(); 807 } 808 809 throw new LDAPException(ResultCode.LOCAL_ERROR, 810 ERR_EXCEPTION_HANDLING_RESPONSE.get( 811 StaticUtils.getExceptionMessage(e)), 812 e); 813 } 814 } 815 816 817 818 /** 819 * {@inheritDoc} 820 */ 821 @Override() 822 public String getBindType() 823 { 824 return "SIMPLE"; 825 } 826 827 828 829 /** 830 * {@inheritDoc} 831 */ 832 @Override() 833 public int getLastMessageID() 834 { 835 return messageID; 836 } 837 838 839 840 /** 841 * {@inheritDoc} 842 */ 843 @Override() 844 public SimpleBindRequest duplicate() 845 { 846 return duplicate(getControls()); 847 } 848 849 850 851 /** 852 * {@inheritDoc} 853 */ 854 @Override() 855 public SimpleBindRequest duplicate(final Control[] controls) 856 { 857 final SimpleBindRequest bindRequest = 858 new SimpleBindRequest(bindDN, password, passwordProvider, controls); 859 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 860 return bindRequest; 861 } 862 863 864 865 /** 866 * {@inheritDoc} 867 */ 868 @Override() 869 public void toString(final StringBuilder buffer) 870 { 871 buffer.append("SimpleBindRequest(dn='"); 872 buffer.append(bindDN); 873 buffer.append('\''); 874 875 final Control[] controls = getControls(); 876 if (controls.length > 0) 877 { 878 buffer.append(", controls={"); 879 for (int i=0; i < controls.length; i++) 880 { 881 if (i > 0) 882 { 883 buffer.append(", "); 884 } 885 886 buffer.append(controls[i]); 887 } 888 buffer.append('}'); 889 } 890 891 buffer.append(')'); 892 } 893 894 895 896 /** 897 * {@inheritDoc} 898 */ 899 @Override() 900 public void toCode(final List<String> lineList, final String requestID, 901 final int indentSpaces, final boolean includeProcessing) 902 { 903 // Create the request variable. 904 final ArrayList<ToCodeArgHelper> constructorArgs = new ArrayList<>(3); 905 constructorArgs.add(ToCodeArgHelper.createString(bindDN.stringValue(), 906 "Bind DN")); 907 constructorArgs.add(ToCodeArgHelper.createString("---redacted-password---", 908 "Bind Password")); 909 910 final Control[] controls = getControls(); 911 if (controls.length > 0) 912 { 913 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 914 "Bind Controls")); 915 } 916 917 ToCodeHelper.generateMethodCall(lineList, indentSpaces, "SimpleBindRequest", 918 requestID + "Request", "new SimpleBindRequest", constructorArgs); 919 920 921 // Add lines for processing the request and obtaining the result. 922 if (includeProcessing) 923 { 924 // Generate a string with the appropriate indent. 925 final StringBuilder buffer = new StringBuilder(); 926 for (int i=0; i < indentSpaces; i++) 927 { 928 buffer.append(' '); 929 } 930 final String indent = buffer.toString(); 931 932 lineList.add(""); 933 lineList.add(indent + "try"); 934 lineList.add(indent + '{'); 935 lineList.add(indent + " BindResult " + requestID + 936 "Result = connection.bind(" + requestID + "Request);"); 937 lineList.add(indent + " // The bind was processed successfully."); 938 lineList.add(indent + '}'); 939 lineList.add(indent + "catch (LDAPException e)"); 940 lineList.add(indent + '{'); 941 lineList.add(indent + " // The bind failed. Maybe the following will " + 942 "help explain why."); 943 lineList.add(indent + " // Note that the connection is now likely in " + 944 "an unauthenticated state."); 945 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 946 lineList.add(indent + " String message = e.getMessage();"); 947 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 948 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 949 lineList.add(indent + " Control[] responseControls = " + 950 "e.getResponseControls();"); 951 lineList.add(indent + '}'); 952 } 953 } 954}