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 */
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 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 }