001/* 002 * Copyright 2007-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2017 UnboundID Corp. 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 public byte getProtocolOpType() 434 { 435 return LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST; 436 } 437 438 439 440 /** 441 * {@inheritDoc} 442 */ 443 public void writeTo(final ASN1Buffer buffer) 444 { 445 final ASN1BufferSequence requestSequence = 446 buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST); 447 buffer.addElement(VERSION_ELEMENT); 448 buffer.addElement(bindDN); 449 450 if (passwordProvider == null) 451 { 452 buffer.addElement(password); 453 } 454 else 455 { 456 byte[] pwBytes; 457 try 458 { 459 pwBytes = passwordProvider.getPasswordBytes(); 460 } 461 catch (final LDAPException le) 462 { 463 debugException(le); 464 throw new LDAPRuntimeException(le); 465 } 466 467 final ASN1OctetString pw = new ASN1OctetString(CRED_TYPE_SIMPLE, pwBytes); 468 buffer.addElement(pw); 469 buffer.setZeroBufferOnClear(); 470 Arrays.fill(pwBytes, (byte) 0x00); 471 } 472 473 requestSequence.end(); 474 } 475 476 477 478 /** 479 * {@inheritDoc} 480 * Use of this method is only supported if the bind request was created with a 481 * static password. It is not allowed if the password will be obtained 482 * through a password provider. 483 * 484 * @throws LDAPSDKUsageException If this bind request was created with a 485 * password provider rather than a static 486 * password. 487 */ 488 public ASN1Element encodeProtocolOp() 489 throws LDAPSDKUsageException 490 { 491 if (password == null) 492 { 493 throw new LDAPSDKUsageException( 494 ERR_SIMPLE_BIND_ENCODE_PROTOCOL_OP_WITH_PROVIDER.get()); 495 } 496 497 return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST, 498 new ASN1Integer(3), 499 bindDN, 500 password); 501 } 502 503 504 505 /** 506 * {@inheritDoc} 507 */ 508 @Override() 509 protected BindResult process(final LDAPConnection connection, final int depth) 510 throws LDAPException 511 { 512 if (connection.synchronousMode()) 513 { 514 @SuppressWarnings("deprecation") 515 final boolean autoReconnect = 516 connection.getConnectionOptions().autoReconnect(); 517 return processSync(connection, autoReconnect); 518 } 519 520 // See if a bind DN was provided without a password. If that is the case 521 // and this should not be allowed, then throw an exception. 522 if (password != null) 523 { 524 if ((bindDN.getValue().length > 0) && (password.getValue().length == 0) && 525 connection.getConnectionOptions().bindWithDNRequiresPassword()) 526 { 527 final LDAPException le = new LDAPException(ResultCode.PARAM_ERROR, 528 ERR_SIMPLE_BIND_DN_WITHOUT_PASSWORD.get()); 529 debugCodingError(le); 530 throw le; 531 } 532 } 533 534 535 // Create the LDAP message. 536 messageID = connection.nextMessageID(); 537 final LDAPMessage message = new LDAPMessage(messageID, this, getControls()); 538 539 540 // Register with the connection reader to be notified of responses for the 541 // request that we've created. 542 connection.registerResponseAcceptor(messageID, this); 543 544 545 try 546 { 547 // Send the request to the server. 548 debugLDAPRequest(this); 549 final long requestTime = System.nanoTime(); 550 connection.getConnectionStatistics().incrementNumBindRequests(); 551 connection.sendMessage(message); 552 553 // Wait for and process the response. 554 final LDAPResponse response; 555 try 556 { 557 final long responseTimeout = getResponseTimeoutMillis(connection); 558 if (responseTimeout > 0) 559 { 560 response = responseQueue.poll(responseTimeout, TimeUnit.MILLISECONDS); 561 } 562 else 563 { 564 response = responseQueue.take(); 565 } 566 } 567 catch (InterruptedException ie) 568 { 569 debugException(ie); 570 Thread.currentThread().interrupt(); 571 throw new LDAPException(ResultCode.LOCAL_ERROR, 572 ERR_BIND_INTERRUPTED.get(connection.getHostPort()), ie); 573 } 574 575 return handleResponse(connection, response, requestTime, false); 576 } 577 finally 578 { 579 connection.deregisterResponseAcceptor(messageID); 580 } 581 } 582 583 584 585 /** 586 * Processes this bind operation in synchronous mode, in which the same 587 * thread will send the request and read the response. 588 * 589 * @param connection The connection to use to communicate with the directory 590 * server. 591 * @param allowRetry Indicates whether the request may be re-tried on a 592 * re-established connection if the initial attempt fails 593 * in a way that indicates the connection is no longer 594 * valid and autoReconnect is true. 595 * 596 * @return An LDAP result object that provides information about the result 597 * of the bind processing. 598 * 599 * @throws LDAPException If a problem occurs while sending the request or 600 * reading the response. 601 */ 602 private BindResult processSync(final LDAPConnection connection, 603 final boolean allowRetry) 604 throws LDAPException 605 { 606 // Create the LDAP message. 607 messageID = connection.nextMessageID(); 608 final LDAPMessage message = 609 new LDAPMessage(messageID, this, getControls()); 610 611 612 // Set the appropriate timeout on the socket. 613 try 614 { 615 connection.getConnectionInternals(true).getSocket().setSoTimeout( 616 (int) getResponseTimeoutMillis(connection)); 617 } 618 catch (Exception e) 619 { 620 debugException(e); 621 } 622 623 624 // Send the request to the server. 625 final long requestTime = System.nanoTime(); 626 debugLDAPRequest(this); 627 connection.getConnectionStatistics().incrementNumBindRequests(); 628 try 629 { 630 connection.sendMessage(message); 631 } 632 catch (final LDAPException le) 633 { 634 debugException(le); 635 636 if (allowRetry) 637 { 638 final BindResult bindResult = reconnectAndRetry(connection, 639 le.getResultCode()); 640 if (bindResult != null) 641 { 642 return bindResult; 643 } 644 } 645 } 646 647 while (true) 648 { 649 final LDAPResponse response = connection.readResponse(messageID); 650 if (response instanceof IntermediateResponse) 651 { 652 final IntermediateResponseListener listener = 653 getIntermediateResponseListener(); 654 if (listener != null) 655 { 656 listener.intermediateResponseReturned( 657 (IntermediateResponse) response); 658 } 659 } 660 else 661 { 662 return handleResponse(connection, response, requestTime, allowRetry); 663 } 664 } 665 } 666 667 668 669 /** 670 * Performs the necessary processing for handling a response. 671 * 672 * @param connection The connection used to read the response. 673 * @param response The response to be processed. 674 * @param requestTime The time the request was sent to the server. 675 * @param allowRetry Indicates whether the request may be re-tried on a 676 * re-established connection if the initial attempt fails 677 * in a way that indicates the connection is no longer 678 * valid and autoReconnect is true. 679 * 680 * @return The bind result. 681 * 682 * @throws LDAPException If a problem occurs. 683 */ 684 private BindResult handleResponse(final LDAPConnection connection, 685 final LDAPResponse response, 686 final long requestTime, 687 final boolean allowRetry) 688 throws LDAPException 689 { 690 if (response == null) 691 { 692 final long waitTime = nanosToMillis(System.nanoTime() - requestTime); 693 throw new LDAPException(ResultCode.TIMEOUT, 694 ERR_SIMPLE_BIND_CLIENT_TIMEOUT.get(waitTime, messageID, 695 bindDN.stringValue(), connection.getHostPort())); 696 } 697 698 connection.getConnectionStatistics().incrementNumBindResponses( 699 System.nanoTime() - requestTime); 700 if (response instanceof ConnectionClosedResponse) 701 { 702 // The connection was closed while waiting for the response. 703 if (allowRetry) 704 { 705 final BindResult retryResult = reconnectAndRetry(connection, 706 ResultCode.SERVER_DOWN); 707 if (retryResult != null) 708 { 709 return retryResult; 710 } 711 } 712 713 final ConnectionClosedResponse ccr = (ConnectionClosedResponse) response; 714 final String message = ccr.getMessage(); 715 if (message == null) 716 { 717 throw new LDAPException(ccr.getResultCode(), 718 ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE.get( 719 connection.getHostPort(), toString())); 720 } 721 else 722 { 723 throw new LDAPException(ccr.getResultCode(), 724 ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE_WITH_MESSAGE.get( 725 connection.getHostPort(), toString(), message)); 726 } 727 } 728 729 final BindResult bindResult = (BindResult) response; 730 if (allowRetry) 731 { 732 final BindResult retryResult = reconnectAndRetry(connection, 733 bindResult.getResultCode()); 734 if (retryResult != null) 735 { 736 return retryResult; 737 } 738 } 739 740 return bindResult; 741 } 742 743 744 745 /** 746 * Attempts to re-establish the connection and retry processing this request 747 * on it. 748 * 749 * @param connection The connection to be re-established. 750 * @param resultCode The result code for the previous operation attempt. 751 * 752 * @return The result from re-trying the bind, or {@code null} if it could 753 * not be re-tried. 754 */ 755 private BindResult reconnectAndRetry(final LDAPConnection connection, 756 final ResultCode resultCode) 757 { 758 try 759 { 760 // We will only want to retry for certain result codes that indicate a 761 // connection problem. 762 switch (resultCode.intValue()) 763 { 764 case ResultCode.SERVER_DOWN_INT_VALUE: 765 case ResultCode.DECODING_ERROR_INT_VALUE: 766 case ResultCode.CONNECT_ERROR_INT_VALUE: 767 connection.reconnect(); 768 return processSync(connection, false); 769 } 770 } 771 catch (final Exception e) 772 { 773 debugException(e); 774 } 775 776 return null; 777 } 778 779 780 781 /** 782 * {@inheritDoc} 783 */ 784 @Override() 785 public SimpleBindRequest getRebindRequest(final String host, final int port) 786 { 787 return new SimpleBindRequest(bindDN, password, passwordProvider, 788 getControls()); 789 } 790 791 792 793 /** 794 * {@inheritDoc} 795 */ 796 @InternalUseOnly() 797 public void responseReceived(final LDAPResponse response) 798 throws LDAPException 799 { 800 try 801 { 802 responseQueue.put(response); 803 } 804 catch (Exception e) 805 { 806 debugException(e); 807 808 if (e instanceof InterruptedException) 809 { 810 Thread.currentThread().interrupt(); 811 } 812 813 throw new LDAPException(ResultCode.LOCAL_ERROR, 814 ERR_EXCEPTION_HANDLING_RESPONSE.get(getExceptionMessage(e)), e); 815 } 816 } 817 818 819 820 /** 821 * {@inheritDoc} 822 */ 823 @Override() 824 public String getBindType() 825 { 826 return "SIMPLE"; 827 } 828 829 830 831 /** 832 * {@inheritDoc} 833 */ 834 @Override() 835 public int getLastMessageID() 836 { 837 return messageID; 838 } 839 840 841 842 /** 843 * {@inheritDoc} 844 */ 845 @Override() 846 public SimpleBindRequest duplicate() 847 { 848 return duplicate(getControls()); 849 } 850 851 852 853 /** 854 * {@inheritDoc} 855 */ 856 @Override() 857 public SimpleBindRequest duplicate(final Control[] controls) 858 { 859 final SimpleBindRequest bindRequest = 860 new SimpleBindRequest(bindDN, password, passwordProvider, controls); 861 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 862 return bindRequest; 863 } 864 865 866 867 /** 868 * {@inheritDoc} 869 */ 870 @Override() 871 public void toString(final StringBuilder buffer) 872 { 873 buffer.append("SimpleBindRequest(dn='"); 874 buffer.append(bindDN); 875 buffer.append('\''); 876 877 final Control[] controls = getControls(); 878 if (controls.length > 0) 879 { 880 buffer.append(", controls={"); 881 for (int i=0; i < controls.length; i++) 882 { 883 if (i > 0) 884 { 885 buffer.append(", "); 886 } 887 888 buffer.append(controls[i]); 889 } 890 buffer.append('}'); 891 } 892 893 buffer.append(')'); 894 } 895 896 897 898 /** 899 * {@inheritDoc} 900 */ 901 public void toCode(final List<String> lineList, final String requestID, 902 final int indentSpaces, final boolean includeProcessing) 903 { 904 // Create the request variable. 905 final ArrayList<ToCodeArgHelper> constructorArgs = 906 new ArrayList<ToCodeArgHelper>(3); 907 constructorArgs.add(ToCodeArgHelper.createString(bindDN.stringValue(), 908 "Bind DN")); 909 constructorArgs.add(ToCodeArgHelper.createString("---redacted-password---", 910 "Bind Password")); 911 912 final Control[] controls = getControls(); 913 if (controls.length > 0) 914 { 915 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 916 "Bind Controls")); 917 } 918 919 ToCodeHelper.generateMethodCall(lineList, indentSpaces, "SimpleBindRequest", 920 requestID + "Request", "new SimpleBindRequest", constructorArgs); 921 922 923 // Add lines for processing the request and obtaining the result. 924 if (includeProcessing) 925 { 926 // Generate a string with the appropriate indent. 927 final StringBuilder buffer = new StringBuilder(); 928 for (int i=0; i < indentSpaces; i++) 929 { 930 buffer.append(' '); 931 } 932 final String indent = buffer.toString(); 933 934 lineList.add(""); 935 lineList.add(indent + "try"); 936 lineList.add(indent + '{'); 937 lineList.add(indent + " BindResult " + requestID + 938 "Result = connection.bind(" + requestID + "Request);"); 939 lineList.add(indent + " // The bind was processed successfully."); 940 lineList.add(indent + '}'); 941 lineList.add(indent + "catch (LDAPException e)"); 942 lineList.add(indent + '{'); 943 lineList.add(indent + " // The bind failed. Maybe the following will " + 944 "help explain why."); 945 lineList.add(indent + " // Note that the connection is now likely in " + 946 "an unauthenticated state."); 947 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 948 lineList.add(indent + " String message = e.getMessage();"); 949 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 950 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 951 lineList.add(indent + " Control[] responseControls = " + 952 "e.getResponseControls();"); 953 lineList.add(indent + '}'); 954 } 955 } 956}