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