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 */
021 package com.unboundid.ldap.sdk;
022
023
024
025 import java.util.ArrayList;
026 import java.util.Arrays;
027 import java.util.List;
028 import java.util.concurrent.LinkedBlockingQueue;
029 import java.util.concurrent.TimeUnit;
030
031 import com.unboundid.asn1.ASN1Buffer;
032 import com.unboundid.asn1.ASN1BufferSequence;
033 import com.unboundid.asn1.ASN1Element;
034 import com.unboundid.asn1.ASN1Integer;
035 import com.unboundid.asn1.ASN1OctetString;
036 import com.unboundid.asn1.ASN1Sequence;
037 import com.unboundid.ldap.protocol.LDAPMessage;
038 import com.unboundid.ldap.protocol.LDAPResponse;
039 import com.unboundid.ldap.protocol.ProtocolOp;
040 import com.unboundid.util.InternalUseOnly;
041 import com.unboundid.util.LDAPSDKUsageException;
042 import com.unboundid.util.NotMutable;
043 import com.unboundid.util.ThreadSafety;
044 import com.unboundid.util.ThreadSafetyLevel;
045
046 import static com.unboundid.ldap.sdk.LDAPMessages.*;
047 import static com.unboundid.util.Debug.*;
048 import 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)
058 public 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 }