001/* 002 * Copyright 2007-2016 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2016 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 throw new LDAPException(ResultCode.LOCAL_ERROR, 571 ERR_BIND_INTERRUPTED.get(connection.getHostPort()), ie); 572 } 573 574 return handleResponse(connection, response, requestTime, false); 575 } 576 finally 577 { 578 connection.deregisterResponseAcceptor(messageID); 579 } 580 } 581 582 583 584 /** 585 * Processes this bind operation in synchronous mode, in which the same 586 * thread will send the request and read the response. 587 * 588 * @param connection The connection to use to communicate with the directory 589 * server. 590 * @param allowRetry Indicates whether the request may be re-tried on a 591 * re-established connection if the initial attempt fails 592 * in a way that indicates the connection is no longer 593 * valid and autoReconnect is true. 594 * 595 * @return An LDAP result object that provides information about the result 596 * of the bind processing. 597 * 598 * @throws LDAPException If a problem occurs while sending the request or 599 * reading the response. 600 */ 601 private BindResult processSync(final LDAPConnection connection, 602 final boolean allowRetry) 603 throws LDAPException 604 { 605 // Create the LDAP message. 606 messageID = connection.nextMessageID(); 607 final LDAPMessage message = 608 new LDAPMessage(messageID, this, getControls()); 609 610 611 // Set the appropriate timeout on the socket. 612 try 613 { 614 connection.getConnectionInternals(true).getSocket().setSoTimeout( 615 (int) getResponseTimeoutMillis(connection)); 616 } 617 catch (Exception e) 618 { 619 debugException(e); 620 } 621 622 623 // Send the request to the server. 624 final long requestTime = System.nanoTime(); 625 debugLDAPRequest(this); 626 connection.getConnectionStatistics().incrementNumBindRequests(); 627 try 628 { 629 connection.sendMessage(message); 630 } 631 catch (final LDAPException le) 632 { 633 debugException(le); 634 635 if (allowRetry) 636 { 637 final BindResult bindResult = reconnectAndRetry(connection, 638 le.getResultCode()); 639 if (bindResult != null) 640 { 641 return bindResult; 642 } 643 } 644 } 645 646 while (true) 647 { 648 final LDAPResponse response = connection.readResponse(messageID); 649 if (response instanceof IntermediateResponse) 650 { 651 final IntermediateResponseListener listener = 652 getIntermediateResponseListener(); 653 if (listener != null) 654 { 655 listener.intermediateResponseReturned( 656 (IntermediateResponse) response); 657 } 658 } 659 else 660 { 661 return handleResponse(connection, response, requestTime, allowRetry); 662 } 663 } 664 } 665 666 667 668 /** 669 * Performs the necessary processing for handling a response. 670 * 671 * @param connection The connection used to read the response. 672 * @param response The response to be processed. 673 * @param requestTime The time the request was sent to the server. 674 * @param allowRetry Indicates whether the request may be re-tried on a 675 * re-established connection if the initial attempt fails 676 * in a way that indicates the connection is no longer 677 * valid and autoReconnect is true. 678 * 679 * @return The bind result. 680 * 681 * @throws LDAPException If a problem occurs. 682 */ 683 private BindResult handleResponse(final LDAPConnection connection, 684 final LDAPResponse response, 685 final long requestTime, 686 final boolean allowRetry) 687 throws LDAPException 688 { 689 if (response == null) 690 { 691 final long waitTime = nanosToMillis(System.nanoTime() - requestTime); 692 throw new LDAPException(ResultCode.TIMEOUT, 693 ERR_SIMPLE_BIND_CLIENT_TIMEOUT.get(waitTime, messageID, 694 bindDN.stringValue(), connection.getHostPort())); 695 } 696 697 connection.getConnectionStatistics().incrementNumBindResponses( 698 System.nanoTime() - requestTime); 699 if (response instanceof ConnectionClosedResponse) 700 { 701 // The connection was closed while waiting for the response. 702 if (allowRetry) 703 { 704 final BindResult retryResult = reconnectAndRetry(connection, 705 ResultCode.SERVER_DOWN); 706 if (retryResult != null) 707 { 708 return retryResult; 709 } 710 } 711 712 final ConnectionClosedResponse ccr = (ConnectionClosedResponse) response; 713 final String message = ccr.getMessage(); 714 if (message == null) 715 { 716 throw new LDAPException(ccr.getResultCode(), 717 ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE.get( 718 connection.getHostPort(), toString())); 719 } 720 else 721 { 722 throw new LDAPException(ccr.getResultCode(), 723 ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE_WITH_MESSAGE.get( 724 connection.getHostPort(), toString(), message)); 725 } 726 } 727 728 final BindResult bindResult = (BindResult) response; 729 if (allowRetry) 730 { 731 final BindResult retryResult = reconnectAndRetry(connection, 732 bindResult.getResultCode()); 733 if (retryResult != null) 734 { 735 return retryResult; 736 } 737 } 738 739 return bindResult; 740 } 741 742 743 744 /** 745 * Attempts to re-establish the connection and retry processing this request 746 * on it. 747 * 748 * @param connection The connection to be re-established. 749 * @param resultCode The result code for the previous operation attempt. 750 * 751 * @return The result from re-trying the bind, or {@code null} if it could 752 * not be re-tried. 753 */ 754 private BindResult reconnectAndRetry(final LDAPConnection connection, 755 final ResultCode resultCode) 756 { 757 try 758 { 759 // We will only want to retry for certain result codes that indicate a 760 // connection problem. 761 switch (resultCode.intValue()) 762 { 763 case ResultCode.SERVER_DOWN_INT_VALUE: 764 case ResultCode.DECODING_ERROR_INT_VALUE: 765 case ResultCode.CONNECT_ERROR_INT_VALUE: 766 connection.reconnect(); 767 return processSync(connection, false); 768 } 769 } 770 catch (final Exception e) 771 { 772 debugException(e); 773 } 774 775 return null; 776 } 777 778 779 780 /** 781 * {@inheritDoc} 782 */ 783 @Override() 784 public SimpleBindRequest getRebindRequest(final String host, final int port) 785 { 786 return new SimpleBindRequest(bindDN, password, passwordProvider, 787 getControls()); 788 } 789 790 791 792 /** 793 * {@inheritDoc} 794 */ 795 @InternalUseOnly() 796 public void responseReceived(final LDAPResponse response) 797 throws LDAPException 798 { 799 try 800 { 801 responseQueue.put(response); 802 } 803 catch (Exception e) 804 { 805 debugException(e); 806 throw new LDAPException(ResultCode.LOCAL_ERROR, 807 ERR_EXCEPTION_HANDLING_RESPONSE.get(getExceptionMessage(e)), e); 808 } 809 } 810 811 812 813 /** 814 * {@inheritDoc} 815 */ 816 @Override() 817 public String getBindType() 818 { 819 return "SIMPLE"; 820 } 821 822 823 824 /** 825 * {@inheritDoc} 826 */ 827 @Override() 828 public int getLastMessageID() 829 { 830 return messageID; 831 } 832 833 834 835 /** 836 * {@inheritDoc} 837 */ 838 @Override() 839 public SimpleBindRequest duplicate() 840 { 841 return duplicate(getControls()); 842 } 843 844 845 846 /** 847 * {@inheritDoc} 848 */ 849 @Override() 850 public SimpleBindRequest duplicate(final Control[] controls) 851 { 852 final SimpleBindRequest bindRequest = 853 new SimpleBindRequest(bindDN, password, passwordProvider, controls); 854 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 855 return bindRequest; 856 } 857 858 859 860 /** 861 * {@inheritDoc} 862 */ 863 @Override() 864 public void toString(final StringBuilder buffer) 865 { 866 buffer.append("SimpleBindRequest(dn='"); 867 buffer.append(bindDN); 868 buffer.append('\''); 869 870 final Control[] controls = getControls(); 871 if (controls.length > 0) 872 { 873 buffer.append(", controls={"); 874 for (int i=0; i < controls.length; i++) 875 { 876 if (i > 0) 877 { 878 buffer.append(", "); 879 } 880 881 buffer.append(controls[i]); 882 } 883 buffer.append('}'); 884 } 885 886 buffer.append(')'); 887 } 888 889 890 891 /** 892 * {@inheritDoc} 893 */ 894 public void toCode(final List<String> lineList, final String requestID, 895 final int indentSpaces, final boolean includeProcessing) 896 { 897 // Create the request variable. 898 final ArrayList<ToCodeArgHelper> constructorArgs = 899 new ArrayList<ToCodeArgHelper>(3); 900 constructorArgs.add(ToCodeArgHelper.createString(bindDN.stringValue(), 901 "Bind DN")); 902 constructorArgs.add(ToCodeArgHelper.createString("---redacted-password---", 903 "Bind Password")); 904 905 final Control[] controls = getControls(); 906 if (controls.length > 0) 907 { 908 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 909 "Bind Controls")); 910 } 911 912 ToCodeHelper.generateMethodCall(lineList, indentSpaces, "SimpleBindRequest", 913 requestID + "Request", "new SimpleBindRequest", constructorArgs); 914 915 916 // Add lines for processing the request and obtaining the result. 917 if (includeProcessing) 918 { 919 // Generate a string with the appropriate indent. 920 final StringBuilder buffer = new StringBuilder(); 921 for (int i=0; i < indentSpaces; i++) 922 { 923 buffer.append(' '); 924 } 925 final String indent = buffer.toString(); 926 927 lineList.add(""); 928 lineList.add(indent + "try"); 929 lineList.add(indent + '{'); 930 lineList.add(indent + " BindResult " + requestID + 931 "Result = connection.bind(" + requestID + "Request);"); 932 lineList.add(indent + " // The bind was processed successfully."); 933 lineList.add(indent + '}'); 934 lineList.add(indent + "catch (LDAPException e)"); 935 lineList.add(indent + '{'); 936 lineList.add(indent + " // The bind failed. Maybe the following will " + 937 "help explain why."); 938 lineList.add(indent + " // Note that the connection is now likely in " + 939 "an unauthenticated state."); 940 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 941 lineList.add(indent + " String message = e.getMessage();"); 942 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 943 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 944 lineList.add(indent + " Control[] responseControls = " + 945 "e.getResponseControls();"); 946 lineList.add(indent + '}'); 947 } 948 } 949}