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 com.unboundid.util.Mutable;
026    import com.unboundid.util.StaticUtils;
027    import com.unboundid.util.ThreadSafety;
028    import com.unboundid.util.ThreadSafetyLevel;
029    import com.unboundid.util.ssl.SSLSocketVerifier;
030    import com.unboundid.util.ssl.TrustAllSSLSocketVerifier;
031    
032    import static com.unboundid.util.Validator.*;
033    
034    
035    
036    /**
037     * This class provides a data structure that may be used to configure a number
038     * of connection-related properties.  Elements included in the set of connection
039     * options include:
040     * <UL>
041     *   <LI>A flag that indicates whether the SDK should attempt to automatically
042     *       re-establish a connection if it is unexpectedly closed.  By default,
043     *       it will not attempt to do so.</LI>
044     *   <LI>A flag that indicates whether simple bind attempts that contain a
045     *       non-empty DN will be required to have a non-empty password.  By
046     *       default, a password will be required in such cases.</LI>
047     *   <LI>A flag that indicates whether to automatically attempt to follow any
048     *       referrals that may be returned by the server.  By default, it will not
049     *       automatically attempt to follow referrals.</LI>
050     *   <LI>A referral hop limit, which indicates the maximum number of hops that
051     *       the connection may take when trying to follow a referral.  The default
052     *       referral hop limit is five.</LI>
053     *   <LI>The referral connector that should be used to create and optionally
054     *       authenticate connections used to follow referrals encountered during
055     *       processing.  By default, referral connections will use the same socket
056     *       factory and bind request as the client connection on which the referral
057     *       was received.</LI>
058     *   <LI>A flag that indicates whether to use the SO_KEEPALIVE socket option to
059     *       attempt to more quickly detect when idle TCP connections have been lost
060     *       or to prevent them from being unexpectedly closed by intermediate
061     *       network hardware.  By default, the SO_KEEPALIVE socket option will be
062     *       used.</LI>
063     *   <LI>A flag that indicates whether to use the SO_LINGER socket option to
064     *       indicate how long a connection should linger after it has been closed,
065     *       and a value that specifies the length of time that it should linger.
066     *       By default, the SO_LINGER option will be used with a timeout of 5
067     *       seconds.</LI>
068     *   <LI>A flag that indicates whether to use the SO_REUSEADDR socket option to
069     *       indicate that a socket in a TIME_WAIT state may be reused.  By default,
070     *       the SO_REUSEADDR socket option will be used.</LI>
071     *   <LI>A flag that indicates whether to operate in synchronous mode, in which
072     *       connections may exhibit better performance and will not require a
073     *       separate reader thread, but will not allow multiple concurrent
074     *       operations to be used on the same connection.</LI>
075     *   <LI>A flag that indicates whether to use the TCP_NODELAY socket option to
076     *       indicate that any data written to the socket will be sent immediately
077     *       rather than delaying for a short amount of time to see if any more data
078     *       is to be sent that could potentially be included in the same packet.
079     *       By default, the TCP_NODELAY socket option will be used.</LI>
080     *   <LI>A value which specifies the maximum length of time in milliseconds that
081     *       an attempt to establish a connection should be allowed to block before
082     *       failing.  By default, a timeout of 60,000 milliseconds (1 minute) will
083     *       be used.</LI>
084     *   <LI>A value which specifies the default timeout in milliseconds that the
085     *       SDK should wait for a response from the server before failing.  By
086     *       default, a timeout of 300,000 milliseconds (5 minutes) will be
087     *       used.</LI>
088     *   <LI>A flag that indicates whether to attempt to abandon any request for
089     *       which no response is received after waiting for the maximum response
090     *       timeout.  By default, no abandon request will be sent.</LI>
091     *   <LI>A value which specifies the largest LDAP message size that the SDK will
092     *       be willing to read from the directory server.  By default, the SDK will
093     *       not allow responses larger than 20971520 bytes (20MB).  If it
094     *       encounters a message that may be larger than the maximum allowed
095     *       message size, then the SDK will terminate the connection to the
096     *       server.</LI>
097     *   <LI>The {@link DisconnectHandler} that should be used to receive
098     *       notification if connection is disconnected for any reason.  By default,
099     *       no {@code DisconnectHandler} will be used.</LI>
100     *   <LI>The {@link UnsolicitedNotificationHandler} that should be used to
101     *       receive notification about any unsolicited notifications returned by
102     *       the server.  By default, no {@code UnsolicitedNotificationHandler} will
103     *       be used.</LI>
104     *   <LI>A flag that indicates whether to capture a thread stack trace whenever
105     *       a new connection is established.  Capturing a thread stack trace when
106     *       establishing a connection may be marginally expensive, but can be
107     *       useful for debugging certain kinds of problems like leaked connections
108     *       (connections that are established but never explicitly closed).  By
109     *       default, connect stack traces will not be captured.</LI>
110     *   <LI>A flag that indicates whether connections should try to retrieve schema
111     *       information from the server, which may be used to better determine
112     *       which matching rules should be used when comparing attribute values.
113     *       By default, server schema information will not be retrieved.</LI>
114     *   <LI>The size of the socket receive buffer, which may be used for
115     *       temporarily holding data received from the directory server until it
116     *       can be read and processed by the LDAP SDK.  By default, the receive
117     *       buffer size will be automatically determined by the JVM based on the
118     *       underlying system settings.</LI>
119     *   <LI>The size of the socket send buffer, which may be used for temporarily
120     *       holding data to be sent to the directory server until it can actually
121     *       be transmitted over the network.  By default, the send buffer size will
122     *       be automatically determined by the JVM based on the underlying system
123     *       settings.</LI>
124     *  <LI>A flag which indicates whether to allow a single socket factory instance
125     *      (which may be shared across multiple connections) to be used to create
126     *      multiple concurrent connections.  This offers better and more
127     *      predictable performance on some JVM implementations (especially when
128     *      connection attempts fail as a result of a connection timeout), but some
129     *      JVMs are known to use non-threadsafe socket factory implementations and
130     *      may fail from concurrent use (for example, at least some IBM JVMs
131     *      exhibit this behavior).  By default, Sun/Oracle JVMs will allow
132     *      concurrent socket factory use, but JVMs from other vendors will use
133     *      synchronization to ensure that a socket factory will only be allowed to
134     *      create one connection at a time.</LI>
135     *  <LI>A class that may be used to perform additional verification (e.g.,
136     *      hostname validation) for any {@code SSLSocket} instances created.  By
137     *      default, no special verification will be performed.</LI>
138     * </UL>
139     */
140    @Mutable()
141    @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
142    public final class LDAPConnectionOptions
143    {
144      /**
145       * The default value ({@code false}) for the setting that controls whether to
146       * attempt to abandon any request for which no response is received within the
147       * maximum response timeout.
148       */
149      static final boolean DEFAULT_ABANDON_ON_TIMEOUT = false;
150    
151    
152    
153      /**
154       * The default value ({@code false}) for the setting that controls whether to
155       * automatically attempt to reconnect if a connection is unexpectedly lost.
156       */
157      static final boolean DEFAULT_AUTO_RECONNECT = false;
158    
159    
160    
161      /**
162       * The default value ({@code true}) for the setting that controls whether
163       * simple bind requests with a DN are also required to contain a password.
164       */
165      static final boolean DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD = true;
166    
167    
168    
169      /**
170       * The default value ({@code false}) for the setting that controls whether to
171       * capture a thread stack trace whenever an attempt is made to establish a
172       * connection.
173       */
174      static final boolean DEFAULT_CAPTURE_CONNECT_STACK_TRACE = false;
175    
176    
177    
178      /**
179       * The default value ({@code false}) for the setting that controls whether to
180       * attempt to automatically follow referrals.
181       */
182      static final boolean DEFAULT_FOLLOW_REFERRALS = false;
183    
184    
185    
186      /**
187       * The default value ({@code false}) for the setting that controls whether all
188       * connections in a connection pool should use the same cached schema object.
189       */
190      static final boolean DEFAULT_USE_POOLED_SCHEMA = false;
191    
192    
193    
194      /**
195       * The default value ({@code true}) for the setting that controls whether to
196       * use the {@code SO_KEEPALIVE} socket option.
197       */
198      static final boolean DEFAULT_USE_KEEPALIVE = true;
199    
200    
201    
202      /**
203       * The default value ({@code true}) for the setting that controls whether to
204       * use the {@code SO_LINGER} socket option.
205       */
206      static final boolean DEFAULT_USE_LINGER = true;
207    
208    
209    
210      /**
211       * The default value ({@code true}) for the setting that controls whether to
212       * use the {@code SO_REUSEADDR} socket option.
213       */
214      static final boolean DEFAULT_USE_REUSE_ADDRESS = true;
215    
216    
217    
218      /**
219       * The default value ({@code false}) for the setting that controls whether to
220       * use schema when reading data from the server.
221       */
222      static final boolean DEFAULT_USE_SCHEMA = false;
223    
224    
225    
226      /**
227       * The default value ({@code false}) for the setting that controls whether to
228       * operate in synchronous mode, in which only a single outstanding operation
229       * may be in progress on an associated connection at any given time.
230       */
231      static final boolean DEFAULT_USE_SYNCHRONOUS_MODE = false;
232    
233    
234    
235      /**
236       * The default value ({@code true}) for the setting that controls whether to
237       * use the {@code TCP_NODELAY} socket option.
238       */
239      static final boolean DEFAULT_USE_TCP_NODELAY = true;
240    
241    
242    
243      /**
244       * The default value (60000) for the setting that controls the timeout in
245       * milliseconds when trying to establish a new connection.
246       */
247      static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 60000;
248    
249    
250    
251      /**
252       * The default value (5) for the setting that controls the timeout in seconds
253       * that will be used with the {@code SO_LINGER} socket option.
254       */
255      static final int DEFAULT_LINGER_TIMEOUT_SECONDS = 5;
256    
257    
258    
259      /**
260       * The default value (20971520 bytes, or 20MB) for the setting that controls
261       * the maximum LDAP message size in bytes that will be allowed when reading
262       * data from a directory server.
263       */
264      static final int DEFAULT_MAX_MESSAGE_SIZE = 20971520;
265    
266    
267    
268      /**
269       * The default size to use for the receive buffer.
270       */
271      static final int DEFAULT_RECEIVE_BUFFER_SIZE = 0;
272    
273    
274    
275      /**
276       * The default value (5) for the setting that controls the referral hop limit.
277       */
278      static final int DEFAULT_REFERRAL_HOP_LIMIT = 5;
279    
280    
281    
282      /**
283       * The default size to use for the send buffer.
284       */
285      static final int DEFAULT_SEND_BUFFER_SIZE = 0;
286    
287    
288    
289      /**
290       * The default value (3600000 milliseconds, or one hour) for the setting that
291       * controls the default pooled schema timeout.
292       */
293      static final long DEFAULT_POOLED_SCHEMA_TIMEOUT_MILLIS = 3600000L;
294    
295    
296    
297      /**
298       * The default value (300000) for the setting that controls the default
299       * response timeout in milliseconds.
300       */
301      static final long DEFAULT_RESPONSE_TIMEOUT_MILLIS = 300000L;
302    
303    
304    
305      /**
306       * The default value for the setting that controls the default behavior with
307       * regard to whether to allow concurrent use of a socket factory to create
308       * client connections.
309       */
310      static final boolean DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE;
311      static
312      {
313        final String vmVendor =
314             StaticUtils.toLowerCase(System.getProperty("java.vm.vendor"));
315        DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE = ((vmVendor != null) &&
316             (vmVendor.contains("sun microsystems") ||
317              vmVendor.contains("oracle") ||
318              vmVendor.contains("apple") ||
319              vmVendor.contains("azul systems")));
320      }
321    
322    
323    
324      /**
325       * The default {@code SSLSocketVerifier} instance that will be used for
326       * performing extra validation for {@code SSLSocket} instances.
327       */
328      static final SSLSocketVerifier DEFAULT_SSL_SOCKET_VERIFIER =
329           TrustAllSSLSocketVerifier.getInstance();
330    
331    
332    
333      // Indicates whether to send an abandon request for any operation for which no
334      // response is received in the maximum response timeout.
335      private boolean abandonOnTimeout;
336    
337      // Indicates whether to use synchronization prevent concurrent use of the
338      // socket factory instance associated with a connection or set of connections.
339      private boolean allowConcurrentSocketFactoryUse;
340    
341      // Indicates whether the connection should attempt to automatically reconnect
342      // if the connection to the server is lost.
343      private boolean autoReconnect;
344    
345      // Indicates whether to allow simple binds that contain a DN but no password.
346      private boolean bindWithDNRequiresPassword;
347    
348      // Indicates whether to capture a thread stack trace whenever an attempt is
349      // made to establish a connection;
350      private boolean captureConnectStackTrace;
351    
352      // Indicates whether to attempt to follow any referrals that are encountered.
353      private boolean followReferrals;
354    
355      // Indicates whether to use SO_KEEPALIVE for the underlying sockets.
356      private boolean useKeepAlive;
357    
358      // Indicates whether to use SO_LINGER for the underlying sockets.
359      private boolean useLinger;
360    
361      // Indicates whether to use SO_REUSEADDR for the underlying sockets.
362      private boolean useReuseAddress;
363    
364      // Indicates whether all connections in a connection pool should reference
365      // the same schema.
366      private boolean usePooledSchema;
367    
368      // Indicates whether to try to use schema information when reading data from
369      // the server.
370      private boolean useSchema;
371    
372      // Indicates whether to use synchronous mode in which only a single operation
373      // may be in progress on associated connections at any given time.
374      private boolean useSynchronousMode;
375    
376      // Indicates whether to use TCP_NODELAY for the underlying sockets.
377      private boolean useTCPNoDelay;
378    
379      // The disconnect handler for associated connections.
380      private DisconnectHandler disconnectHandler;
381    
382      // The connect timeout, in milliseconds.
383      private int connectTimeout;
384    
385      // The linger timeout to use if SO_LINGER is to be used.
386      private int lingerTimeout;
387    
388      // The maximum message size in bytes that will be allowed when reading data
389      // from a directory server.
390      private int maxMessageSize;
391    
392      // The socket receive buffer size to request.
393      private int receiveBufferSize;
394    
395      // The referral hop limit to use if referral following is enabled.
396      private int referralHopLimit;
397    
398      // The socket send buffer size to request.
399      private int sendBufferSize;
400    
401      // The pooled schema timeout, in milliseconds.
402      private long pooledSchemaTimeout;
403    
404      // The response timeout, in milliseconds.
405      private long responseTimeout;
406    
407      // Tne default referral connector that should be used for associated
408      // connections.
409      private ReferralConnector referralConnector;
410    
411      // The SSLSocketVerifier instance to use to perform extra validation on
412      // newly-established SSLSocket instances.
413      private SSLSocketVerifier sslSocketVerifier;
414    
415      // The unsolicited notification handler for associated connections.
416      private UnsolicitedNotificationHandler unsolicitedNotificationHandler;
417    
418    
419    
420      /**
421       * Creates a new set of LDAP connection options with the default settings.
422       */
423      public LDAPConnectionOptions()
424      {
425        abandonOnTimeout               = DEFAULT_ABANDON_ON_TIMEOUT;
426        autoReconnect                  = DEFAULT_AUTO_RECONNECT;
427        bindWithDNRequiresPassword     = DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD;
428        captureConnectStackTrace       = DEFAULT_CAPTURE_CONNECT_STACK_TRACE;
429        followReferrals                = DEFAULT_FOLLOW_REFERRALS;
430        useKeepAlive                   = DEFAULT_USE_KEEPALIVE;
431        useLinger                      = DEFAULT_USE_LINGER;
432        useReuseAddress                = DEFAULT_USE_REUSE_ADDRESS;
433        usePooledSchema                = DEFAULT_USE_POOLED_SCHEMA;
434        useSchema                      = DEFAULT_USE_SCHEMA;
435        useSynchronousMode             = DEFAULT_USE_SYNCHRONOUS_MODE;
436        useTCPNoDelay                  = DEFAULT_USE_TCP_NODELAY;
437        connectTimeout                 = DEFAULT_CONNECT_TIMEOUT_MILLIS;
438        lingerTimeout                  = DEFAULT_LINGER_TIMEOUT_SECONDS;
439        maxMessageSize                 = DEFAULT_MAX_MESSAGE_SIZE;
440        referralHopLimit               = DEFAULT_REFERRAL_HOP_LIMIT;
441        pooledSchemaTimeout            = DEFAULT_POOLED_SCHEMA_TIMEOUT_MILLIS;
442        responseTimeout                = DEFAULT_RESPONSE_TIMEOUT_MILLIS;
443        receiveBufferSize              = DEFAULT_RECEIVE_BUFFER_SIZE;
444        sendBufferSize                 = DEFAULT_SEND_BUFFER_SIZE;
445        disconnectHandler              = null;
446        referralConnector              = null;
447        sslSocketVerifier              = DEFAULT_SSL_SOCKET_VERIFIER;
448        unsolicitedNotificationHandler = null;
449    
450        allowConcurrentSocketFactoryUse =
451             DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE;
452      }
453    
454    
455    
456      /**
457       * Returns a duplicate of this LDAP connection options object that may be
458       * modified without impacting this instance.
459       *
460       * @return  A duplicate of this LDAP connection options object that may be
461       *          modified without impacting this instance.
462       */
463      public LDAPConnectionOptions duplicate()
464      {
465        final LDAPConnectionOptions o = new LDAPConnectionOptions();
466    
467        o.abandonOnTimeout                = abandonOnTimeout;
468        o.allowConcurrentSocketFactoryUse = allowConcurrentSocketFactoryUse;
469        o.autoReconnect                   = autoReconnect;
470        o.bindWithDNRequiresPassword      = bindWithDNRequiresPassword;
471        o.captureConnectStackTrace        = captureConnectStackTrace;
472        o.followReferrals                 = followReferrals;
473        o.useKeepAlive                    = useKeepAlive;
474        o.useLinger                       = useLinger;
475        o.useReuseAddress                 = useReuseAddress;
476        o.usePooledSchema                 = usePooledSchema;
477        o.useSchema                       = useSchema;
478        o.useSynchronousMode              = useSynchronousMode;
479        o.useTCPNoDelay                   = useTCPNoDelay;
480        o.connectTimeout                  = connectTimeout;
481        o.lingerTimeout                   = lingerTimeout;
482        o.maxMessageSize                  = maxMessageSize;
483        o.pooledSchemaTimeout             = pooledSchemaTimeout;
484        o.responseTimeout                 = responseTimeout;
485        o.referralConnector               = referralConnector;
486        o.referralHopLimit                = referralHopLimit;
487        o.disconnectHandler               = disconnectHandler;
488        o.unsolicitedNotificationHandler  = unsolicitedNotificationHandler;
489        o.receiveBufferSize               = receiveBufferSize;
490        o.sendBufferSize                  = sendBufferSize;
491        o.sslSocketVerifier               = sslSocketVerifier;
492    
493        return o;
494      }
495    
496    
497    
498      /**
499       * Indicates whether associated connections should attempt to automatically
500       * reconnect to the target server if the connection is lost.  Note that this
501       * option will not have any effect on pooled connections because defunct
502       * pooled connections will be replaced by newly-created connections rather
503       * than attempting to re-establish the existing connection.
504       * <BR><BR>
505       * NOTE:  The use of auto-reconnect is strongly discouraged because it is
506       * inherently fragile and can only work under very limited circumstances.  It
507       * is strongly recommended that a connection pool be used instead of the
508       * auto-reconnect option, even in cases where only a single connection is
509       * desired.
510       *
511       * @return  {@code true} if associated connections should attempt to
512       *          automatically reconnect to the target server if the connection is
513       *          lost, or {@code false} if not.
514       *
515       * @deprecated  The use of auto-reconnect is strongly discouraged because it
516       *              is inherently fragile and can only work under very limited
517       *              circumstances.  It is strongly recommended that a connection
518       *              pool be used instead of the auto-reconnect option, even in
519       *              cases where only a single connection is desired.
520       */
521      @Deprecated()
522      public boolean autoReconnect()
523      {
524        return autoReconnect;
525      }
526    
527    
528    
529      /**
530       * Specifies whether associated connections should attempt to automatically
531       * reconnect to the target server if the connection is lost.  Note that
532       * automatic reconnection will only be available for authenticated clients if
533       * the authentication mechanism used provides support for re-binding on a new
534       * connection.  Also note that this option will not have any effect on pooled
535       * connections because defunct pooled connections will be replaced by
536       * newly-created connections rather than attempting to re-establish the
537       * existing connection.  Further, auto-reconnect should not be used with
538       * connections that use StartTLS or some other mechanism to alter the state
539       * of the connection beyond authentication.
540       * <BR><BR>
541       * NOTE:  The use of auto-reconnect is strongly discouraged because it is
542       * inherently fragile and can only work under very limited circumstances.  It
543       * is strongly recommended that a connection pool be used instead of the
544       * auto-reconnect option, even in cases where only a single connection is
545       * desired.
546       *
547       * @param  autoReconnect  Specifies whether associated connections should
548       *                        attempt to automatically reconnect to the target
549       *                        server if the connection is lost.
550       *
551       * @deprecated  The use of auto-reconnect is strongly discouraged because it
552       *              is inherently fragile and can only work under very limited
553       *              circumstances.  It is strongly recommended that a connection
554       *              pool be used instead of the auto-reconnect option, even in
555       *              cases where only a single connection is desired.
556       */
557      @Deprecated()
558      public void setAutoReconnect(final boolean autoReconnect)
559      {
560        this.autoReconnect = autoReconnect;
561      }
562    
563    
564    
565      /**
566       * Indicates whether the SDK should allow simple bind operations that contain
567       * a bind DN but no password.  Binds of this type may represent a security
568       * vulnerability in client applications because they may cause the client to
569       * believe that the user is properly authenticated when the server considers
570       * it to be an unauthenticated connection.
571       *
572       * @return  {@code true} if the SDK should allow simple bind operations that
573       *          contain a bind DN but no password, or {@code false} if not.
574       */
575      public boolean bindWithDNRequiresPassword()
576      {
577        return bindWithDNRequiresPassword;
578      }
579    
580    
581    
582      /**
583       * Specifies whether the SDK should allow simple bind operations that contain
584       * a bind DN but no password.
585       *
586       * @param  bindWithDNRequiresPassword  Indicates whether the SDK should allow
587       *                                     simple bind operations that contain a
588       *                                     bind DN but no password.
589       */
590      public void setBindWithDNRequiresPassword(
591                       final boolean bindWithDNRequiresPassword)
592      {
593        this.bindWithDNRequiresPassword = bindWithDNRequiresPassword;
594      }
595    
596    
597    
598      /**
599       * Indicates whether the LDAP SDK should capture a thread stack trace for each
600       * attempt made to establish a connection.  If this is enabled, then the
601       * {@link LDAPConnection#getConnectStackTrace()}  method may be used to
602       * retrieve the stack trace.
603       *
604       * @return  {@code true} if a thread stack trace should be captured whenever a
605       *          connection is established, or {@code false} if not.
606       */
607      public boolean captureConnectStackTrace()
608      {
609        return captureConnectStackTrace;
610      }
611    
612    
613    
614      /**
615       * Specifies whether the LDAP SDK should capture a thread stack trace for each
616       * attempt made to establish a connection.
617       *
618       * @param  captureConnectStackTrace  Indicates whether to capture a thread
619       *                                   stack trace for each attempt made to
620       *                                   establish a connection.
621       */
622      public void setCaptureConnectStackTrace(
623                       final boolean captureConnectStackTrace)
624      {
625        this.captureConnectStackTrace = captureConnectStackTrace;
626      }
627    
628    
629    
630      /**
631       * Retrieves the maximum length of time in milliseconds that a connection
632       * attempt should be allowed to continue before giving up.
633       *
634       * @return  The maximum length of time in milliseconds that a connection
635       *          attempt should be allowed to continue before giving up, or zero
636       *          to indicate that there should be no connect timeout.
637       */
638      public int getConnectTimeoutMillis()
639      {
640        return connectTimeout;
641      }
642    
643    
644    
645      /**
646       * Specifies the maximum length of time in milliseconds that a connection
647       * attempt should be allowed to continue before giving up.  A value of zero
648       * indicates that there should be no connect timeout.
649       *
650       * @param  connectTimeout  The maximum length of time in milliseconds that a
651       *                         connection attempt should be allowed to continue
652       *                         before giving up.
653       */
654      public void setConnectTimeoutMillis(final int connectTimeout)
655      {
656        this.connectTimeout = connectTimeout;
657      }
658    
659    
660    
661      /**
662       * Retrieves the maximum length of time in milliseconds that an operation
663       * should be allowed to block while waiting for a response from the server.
664       * This may be overridden on a per-operation basis.
665       *
666       * @return  The maximum length of time in milliseconds that an operation
667       *          should be allowed to block while waiting for a response from the
668       *          server, or zero if there should not be any default timeout.
669       */
670      public long getResponseTimeoutMillis()
671      {
672        return responseTimeout;
673      }
674    
675    
676    
677      /**
678       * Specifies the maximum length of time in milliseconds that an operation
679       * should be allowed to block while waiting for a response from the server.  A
680       * value of zero indicates that there should be no timeout.
681       *
682       * @param  responseTimeout  The maximum length of time in milliseconds that an
683       *                          operation should be allowed to block while waiting
684       *                          for a response from the server.
685       *
686       */
687      public void setResponseTimeoutMillis(final long responseTimeout)
688      {
689        if (responseTimeout < 0)
690        {
691          this.responseTimeout = 0L;
692        }
693        else
694        {
695          this.responseTimeout = responseTimeout;
696        }
697      }
698    
699    
700    
701      /**
702       * Indicates whether the LDAP SDK should attempt to abandon any request for
703       * which no response is received in the maximum response timeout period.
704       *
705       * @return  {@code true} if the LDAP SDK should attempt to abandon any request
706       *          for which no response is received in the maximum response timeout
707       *          period, or {@code false} if no abandon attempt should be made in
708       *          this circumstance.
709       */
710      public boolean abandonOnTimeout()
711      {
712        return abandonOnTimeout;
713      }
714    
715    
716    
717      /**
718       * Specifies whether the LDAP SDK should attempt to abandon any request for
719       * which no response is received in the maximum response timeout period.
720       *
721       * @param  abandonOnTimeout  Indicates whether the LDAP SDK should attempt to
722       *                           abandon any request for which no response is
723       *                           received in the maximum response timeout period.
724       */
725      public void setAbandonOnTimeout(final boolean abandonOnTimeout)
726      {
727        this.abandonOnTimeout = abandonOnTimeout;
728      }
729    
730    
731    
732      /**
733       * Indicates whether to use the SO_KEEPALIVE option for the underlying sockets
734       * used by associated connections.
735       *
736       * @return  {@code true} if the SO_KEEPALIVE option should be used for the
737       *          underlying sockets, or {@code false} if not.
738       */
739      public boolean useKeepAlive()
740      {
741        return useKeepAlive;
742      }
743    
744    
745    
746      /**
747       * Specifies whether to use the SO_KEEPALIVE option for the underlying sockets
748       * used by associated connections.  Changes to this setting will take effect
749       * only for new sockets, and not for existing sockets.
750       *
751       * @param  useKeepAlive  Indicates whether to use the SO_KEEPALIVE option for
752       *                       the underlying sockets used by associated
753       *                       connections.
754       */
755      public void setUseKeepAlive(final boolean useKeepAlive)
756      {
757        this.useKeepAlive = useKeepAlive;
758      }
759    
760    
761    
762      /**
763       * Indicates whether to use the SO_LINGER option for the underlying sockets
764       * used by associated connections.
765       *
766       * @return  {@code true} if the SO_LINGER option should be used for the
767       *          underlying sockets, or {@code false} if not.
768       */
769      public boolean useLinger()
770      {
771        return useLinger;
772      }
773    
774    
775    
776      /**
777       * Retrieves the linger timeout in seconds that will be used if the SO_LINGER
778       * socket option is enabled.
779       *
780       * @return  The linger timeout in seconds that will be used if the SO_LINGER
781       *          socket option is enabled.
782       */
783      public int getLingerTimeoutSeconds()
784      {
785        return lingerTimeout;
786      }
787    
788    
789    
790      /**
791       * Specifies whether to use the SO_LINGER option for the underlying sockets
792       * used by associated connections.  Changes to this setting will take effect
793       * only for new sockets, and not for existing sockets.
794       *
795       * @param  useLinger      Indicates whether to use the SO_LINGER option for
796       *                        the underlying sockets used by associated
797       *                        connections.
798       * @param  lingerTimeout  The linger timeout in seconds that should be used if
799       *                        this capability is enabled.
800       */
801      public void setUseLinger(final boolean useLinger, final int lingerTimeout)
802      {
803        this.useLinger     = useLinger;
804        this.lingerTimeout = lingerTimeout;
805      }
806    
807    
808    
809      /**
810       * Indicates whether to use the SO_REUSEADDR option for the underlying sockets
811       * used by associated connections.
812       *
813       * @return  {@code true} if the SO_REUSEADDR option should be used for the
814       *          underlying sockets, or {@code false} if not.
815       */
816      public boolean useReuseAddress()
817      {
818        return useReuseAddress;
819      }
820    
821    
822    
823      /**
824       * Specifies whether to use the SO_REUSEADDR option for the underlying sockets
825       * used by associated connections.  Changes to this setting will take effect
826       * only for new sockets, and not for existing sockets.
827       *
828       * @param  useReuseAddress  Indicates whether to use the SO_REUSEADDR option
829       *                          for the underlying sockets used by associated
830       *                          connections.
831       */
832      public void setUseReuseAddress(final boolean useReuseAddress)
833      {
834        this.useReuseAddress = useReuseAddress;
835      }
836    
837    
838    
839      /**
840       * Indicates whether to try to use schema information when reading data from
841       * the server (e.g., to select the appropriate matching rules for the
842       * attributes included in a search result entry).
843       *
844       * @return  {@code true} if schema should be used when reading data from the
845       *          server, or {@code false} if not.
846       */
847      public boolean useSchema()
848      {
849        return useSchema;
850      }
851    
852    
853    
854      /**
855       * Specifies whether to try to use schema information when reading data from
856       * the server (e.g., to select the appropriate matching rules for the
857       * attributes included in a search result entry).
858       * <BR><BR>
859       * Note that calling this method with a value of {@code true} will also cause
860       * the {@code usePooledSchema} setting to be given a value of false, since
861       * the two values should not both be {@code true} at the same time.
862       *
863       * @param  useSchema  Indicates whether to try to use schema information when
864       *                    reading data from the server.
865       */
866      public void setUseSchema(final boolean useSchema)
867      {
868        this.useSchema = useSchema;
869        if (useSchema)
870        {
871          usePooledSchema = false;
872        }
873      }
874    
875    
876    
877      /**
878       * Indicates whether to have connections that are part of a pool try to use
879       * shared schema information when reading data from the server (e.g., to
880       * select the appropriate matching rules for the attributes included in a
881       * search result entry).  If this is {@code true}, then connections in a
882       * connection pool will share the same cached schema information in a way that
883       * attempts to reduce network bandwidth and connection establishment time (by
884       * avoiding the need for each connection to retrieve its own copy of the
885       * schema).
886       * <BR><BR>
887       * If pooled schema is to be used, then it may be configured to expire so that
888       * the schema may be periodically re-retrieved for new connections to allow
889       * schema updates to be incorporated.  This behavior is controlled by the
890       * value returned by the {@link #getPooledSchemaTimeoutMillis} method.
891       *
892       * @return  {@code true} if all connections in a connection pool should
893       *          reference the same schema object, or {@code false} if each
894       *          connection should retrieve its own copy of the schema.
895       */
896      public boolean usePooledSchema()
897      {
898        return usePooledSchema;
899      }
900    
901    
902    
903      /**
904       * Indicates whether to have connections that are part of a pool try to use
905       * shared schema information when reading data from the server (e.g., to
906       * select the appropriate matching rules for the attributes included in a
907       * search result entry).
908       * <BR><BR>
909       * Note that calling this method with a value of {@code true} will also cause
910       * the {@code useSchema} setting to be given a value of false, since the two
911       * values should not both be {@code true} at the same time.
912       *
913       * @param  usePooledSchema  Indicates whether all connections in a connection
914       *                          pool should reference the same schema object
915       *                          rather than attempting to retrieve their own copy
916       *                          of the schema.
917       */
918      public void setUsePooledSchema(final boolean usePooledSchema)
919      {
920        this.usePooledSchema = usePooledSchema;
921        if (usePooledSchema)
922        {
923          useSchema = false;
924        }
925      }
926    
927    
928    
929      /**
930       * Retrieves the maximum length of time in milliseconds that a pooled schema
931       * object should be considered fresh.  If the schema referenced by a
932       * connection pool is at least this old, then the next connection attempt may
933       * cause a new version of the schema to be retrieved.
934       * <BR><BR>
935       * This will only be used if the {@link #usePooledSchema} method returns
936       * {@code true}.  A value of zero indicates that the pooled schema will never
937       * expire.
938       *
939       * @return  The maximum length of time, in milliseconds, that a pooled schema
940       *          object should be considered fresh, or zero if pooled schema
941       *          objects should never expire.
942       */
943      public long getPooledSchemaTimeoutMillis()
944      {
945        return pooledSchemaTimeout;
946      }
947    
948    
949    
950      /**
951       * Specifies the maximum length of time in milliseconds that a pooled schema
952       * object should be considered fresh.
953       *
954       * @param  pooledSchemaTimeout  The maximum length of time in milliseconds
955       *                              that a pooled schema object should be
956       *                              considered fresh.  A value less than or equal
957       *                              to zero will indicate that pooled schema
958       *                              should never expire.
959       */
960      public void setPooledSchemaTimeoutMillis(final long pooledSchemaTimeout)
961      {
962        if (pooledSchemaTimeout < 0)
963        {
964          this.pooledSchemaTimeout = 0L;
965        }
966        else
967        {
968          this.pooledSchemaTimeout = pooledSchemaTimeout;
969        }
970      }
971    
972    
973    
974      /**
975       * Indicates whether to operate in synchronous mode, in which at most one
976       * operation may be in progress at any time on a given connection, which may
977       * allow it to operate more efficiently and without requiring a separate
978       * reader thread per connection.  The LDAP SDK will not absolutely enforce
979       * this restriction, but when operating in this mode correct behavior
980       * cannot be guaranteed when multiple attempts are made to use a connection
981       * for multiple concurrent operations.
982       * <BR><BR>
983       * Note that if synchronous mode is to be used, then this connection option
984       * must be set on the connection before any attempt is made to establish the
985       * connection.  Once the connection has been established, then it will
986       * continue to operate in synchronous or asynchronous mode based on the
987       * options in place at the time it was connected.
988       *
989       * @return  {@code true} if associated connections should operate in
990       *          synchronous mode, or {@code false} if not.
991       */
992      public boolean useSynchronousMode()
993      {
994        return useSynchronousMode;
995      }
996    
997    
998    
999      /**
1000       * Specifies whether to operate in synchronous mode, in which at most one
1001       * operation may be in progress at any time on a given connection.
1002       * <BR><BR>
1003       * Note that if synchronous mode is to be used, then this connection option
1004       * must be set on the connection before any attempt is made to establish the
1005       * connection.  Once the connection has been established, then it will
1006       * continue to operate in synchronous or asynchronous mode based on the
1007       * options in place at the time it was connected.
1008       *
1009       * @param  useSynchronousMode  Indicates whether to operate in synchronous
1010       *                             mode.
1011       */
1012      public void setUseSynchronousMode(final boolean useSynchronousMode)
1013      {
1014        this.useSynchronousMode = useSynchronousMode;
1015      }
1016    
1017    
1018    
1019      /**
1020       * Indicates whether to use the TCP_NODELAY option for the underlying sockets
1021       * used by associated connections.
1022       *
1023       * @return  {@code true} if the TCP_NODELAY option should be used for the
1024       *          underlying sockets, or {@code false} if not.
1025       */
1026      public boolean useTCPNoDelay()
1027      {
1028        return useTCPNoDelay;
1029      }
1030    
1031    
1032    
1033      /**
1034       * Specifies whether to use the TCP_NODELAY option for the underlying sockets
1035       * used by associated connections.  Changes to this setting will take effect
1036       * only for new sockets, and not for existing sockets.
1037       *
1038       * @param  useTCPNoDelay  Indicates whether to use the TCP_NODELAY option for
1039       *                        the underlying sockets used by associated
1040       *                        connections.
1041       */
1042      public void setUseTCPNoDelay(final boolean useTCPNoDelay)
1043      {
1044        this.useTCPNoDelay = useTCPNoDelay;
1045      }
1046    
1047    
1048    
1049      /**
1050       * Indicates whether associated connections should attempt to follow any
1051       * referrals that they encounter.
1052       *
1053       * @return  {@code true} if associated connections should attempt to follow
1054       *          any referrals that they encounter, or {@code false} if not.
1055       */
1056      public boolean followReferrals()
1057      {
1058        return followReferrals;
1059      }
1060    
1061    
1062    
1063      /**
1064       * Specifies whether associated connections should attempt to follow any
1065       * referrals that they encounter, using the referral connector for the
1066       * associated connection.
1067       *
1068       * @param  followReferrals  Specifies whether associated connections should
1069       *                          attempt to follow any referrals that they
1070       *                          encounter.
1071       */
1072      public void setFollowReferrals(final boolean followReferrals)
1073      {
1074        this.followReferrals = followReferrals;
1075      }
1076    
1077    
1078    
1079      /**
1080       * Retrieves the maximum number of hops that a connection should take when
1081       * trying to follow a referral.
1082       *
1083       * @return  The maximum number of hops that a connection should take when
1084       *          trying to follow a referral.
1085       */
1086      public int getReferralHopLimit()
1087      {
1088        return referralHopLimit;
1089      }
1090    
1091    
1092    
1093      /**
1094       * Specifies the maximum number of hops that a connection should take when
1095       * trying to follow a referral.
1096       *
1097       * @param  referralHopLimit  The maximum number of hops that a connection
1098       *                           should take when trying to follow a referral.  It
1099       *                           must be greater than zero.
1100       */
1101      public void setReferralHopLimit(final int referralHopLimit)
1102      {
1103        ensureTrue(referralHopLimit > 0,
1104             "LDAPConnectionOptions.referralHopLimit must be greater than 0.");
1105    
1106        this.referralHopLimit = referralHopLimit;
1107      }
1108    
1109    
1110    
1111      /**
1112       * Retrieves the referral connector that will be used to establish and
1113       * optionally authenticate connections to servers when attempting to follow
1114       * referrals, if defined.
1115       *
1116       * @return  The referral connector that will be used to establish and
1117       *          optionally authenticate connections to servers when attempting to
1118       *          follow referrals, or {@code null} if no specific referral
1119       *          connector has been configured and referral connections should be
1120       *          created using the same socket factory and bind request as the
1121       *          connection on which the referral was received.
1122       */
1123      public ReferralConnector getReferralConnector()
1124      {
1125        return referralConnector;
1126      }
1127    
1128    
1129    
1130      /**
1131       * Specifies the referral connector that should be used to establish and
1132       * optionally authenticate connections to servers when attempting to follow
1133       * referrals.
1134       *
1135       * @param  referralConnector  The referral connector that will be used to
1136       *                            establish and optionally authenticate
1137       *                            connections to servers when attempting to follow
1138       *                            referrals.  It may be {@code null} to indicate
1139       *                            that the same socket factory and bind request
1140       *                            as the connection on which the referral was
1141       *                            received should be used to establish and
1142       *                            authenticate connections for following
1143       *                            referrals.
1144       */
1145      public void setReferralConnector(final ReferralConnector referralConnector)
1146      {
1147        this.referralConnector = referralConnector;
1148      }
1149    
1150    
1151    
1152      /**
1153       * Retrieves the maximum size in bytes for an LDAP message that a connection
1154       * will attempt to read from the directory server.  If it encounters an LDAP
1155       * message that is larger than this size, then the connection will be
1156       * terminated.
1157       *
1158       * @return  The maximum size in bytes for an LDAP message that a connection
1159       *          will attempt to read from the directory server, or 0 if no limit
1160       *          will be enforced.
1161       */
1162      public int getMaxMessageSize()
1163      {
1164        return maxMessageSize;
1165      }
1166    
1167    
1168    
1169      /**
1170       * Specifies the maximum size in bytes for an LDAP message that a connection
1171       * will attempt to read from the directory server.  If it encounters an LDAP
1172       * message that is larger than this size, then the connection will be
1173       * terminated.
1174       *
1175       * @param  maxMessageSize  The maximum size in bytes for an LDAP message that
1176       *                         a connection will attempt to read from the
1177       *                         directory server.  A value less than or equal to
1178       *                         zero indicates that no limit should be enforced.
1179       */
1180      public void setMaxMessageSize(final int maxMessageSize)
1181      {
1182        if (maxMessageSize > 0)
1183        {
1184          this.maxMessageSize = maxMessageSize;
1185        }
1186        else
1187        {
1188          this.maxMessageSize = 0;
1189        }
1190      }
1191    
1192    
1193    
1194      /**
1195       * Retrieves the disconnect handler to use for associated connections.
1196       *
1197       * @return  the disconnect handler to use for associated connections, or
1198       *          {@code null} if none is defined.
1199       */
1200      public DisconnectHandler getDisconnectHandler()
1201      {
1202        return disconnectHandler;
1203      }
1204    
1205    
1206    
1207      /**
1208       * Specifies the disconnect handler to use for associated connections.
1209       *
1210       * @param  handler  The disconnect handler to use for associated connections.
1211       */
1212      public void setDisconnectHandler(final DisconnectHandler handler)
1213      {
1214        disconnectHandler = handler;
1215      }
1216    
1217    
1218    
1219      /**
1220       * Retrieves the unsolicited notification handler to use for associated
1221       * connections.
1222       *
1223       * @return  The unsolicited notification handler to use for associated
1224       *          connections, or {@code null} if none is defined.
1225       */
1226      public UnsolicitedNotificationHandler getUnsolicitedNotificationHandler()
1227      {
1228        return unsolicitedNotificationHandler;
1229      }
1230    
1231    
1232    
1233      /**
1234       * Specifies the unsolicited notification handler to use for associated
1235       * connections.
1236       *
1237       * @param  handler  The unsolicited notification handler to use for associated
1238       *                  connections.
1239       */
1240      public void setUnsolicitedNotificationHandler(
1241                       final UnsolicitedNotificationHandler handler)
1242      {
1243        unsolicitedNotificationHandler = handler;
1244      }
1245    
1246    
1247    
1248      /**
1249       * Retrieves the socket receive buffer size that should be requested when
1250       * establishing a connection.
1251       *
1252       * @return  The socket receive buffer size that should be requested when
1253       *          establishing a connection, or zero if the default size should be
1254       *          used.
1255       */
1256      public int getReceiveBufferSize()
1257      {
1258        return receiveBufferSize;
1259      }
1260    
1261    
1262    
1263      /**
1264       * Specifies the socket receive buffer size that should be requested when
1265       * establishing a connection.
1266       *
1267       * @param  receiveBufferSize  The socket receive buffer size that should be
1268       *                            requested when establishing a connection, or
1269       *                            zero if the default size should be used.
1270       */
1271      public void setReceiveBufferSize(final int receiveBufferSize)
1272      {
1273        if (receiveBufferSize < 0)
1274        {
1275          this.receiveBufferSize = 0;
1276        }
1277        else
1278        {
1279          this.receiveBufferSize = receiveBufferSize;
1280        }
1281      }
1282    
1283    
1284    
1285      /**
1286       * Retrieves the socket send buffer size that should be requested when
1287       * establishing a connection.
1288       *
1289       * @return  The socket send buffer size that should be requested when
1290       *          establishing a connection, or zero if the default size should be
1291       *          used.
1292       */
1293      public int getSendBufferSize()
1294      {
1295        return sendBufferSize;
1296      }
1297    
1298    
1299    
1300      /**
1301       * Specifies the socket send buffer size that should be requested when
1302       * establishing a connection.
1303       *
1304       * @param  sendBufferSize  The socket send buffer size that should be
1305       *                         requested when establishing a connection, or zero
1306       *                         if the default size should be used.
1307       */
1308      public void setSendBufferSize(final int sendBufferSize)
1309      {
1310        if (sendBufferSize < 0)
1311        {
1312          this.sendBufferSize = 0;
1313        }
1314        else
1315        {
1316          this.sendBufferSize = sendBufferSize;
1317        }
1318      }
1319    
1320    
1321    
1322      /**
1323       * Indicates whether to allow a socket factory instance (which may be shared
1324       * across multiple connections) to be used create multiple sockets
1325       * concurrently.  In general, socket factory implementations are threadsafe
1326       * and can be to create multiple connections simultaneously across separate
1327       * threads, but this is known to not be the case in some VM implementations
1328       * (e.g., SSL socket factories in IBM JVMs).  This setting may be used to
1329       * indicate whether concurrent socket creation attempts should be allowed
1330       * (which may allow for better and more consistent performance, especially in
1331       * cases where a connection attempt fails due to a timeout) or prevented
1332       * (which may be necessary for non-threadsafe socket factory implementations).
1333       *
1334       * @return  {@code true} if multiple threads should be able to concurrently
1335       *          use the same socket factory instance, or {@code false} if Java
1336       *          synchronization should be used to ensure that no more than one
1337       *          thread is allowed to use a socket factory at any given time.
1338       */
1339      public boolean allowConcurrentSocketFactoryUse()
1340      {
1341        return allowConcurrentSocketFactoryUse;
1342      }
1343    
1344    
1345    
1346      /**
1347       * Specifies whether to allow a socket factory instance (which may be shared
1348       * across multiple connections) to be used create multiple sockets
1349       * concurrently.  In general, socket factory implementations are threadsafe
1350       * and can be to create multiple connections simultaneously across separate
1351       * threads, but this is known to not be the case in some VM implementations
1352       * (e.g., SSL socket factories in IBM JVMs).  This setting may be used to
1353       * indicate whether concurrent socket creation attempts should be allowed
1354       * (which may allow for better and more consistent performance, especially in
1355       * cases where a connection attempt fails due to a timeout) or prevented
1356       * (which may be necessary for non-threadsafe socket factory implementations).
1357       *
1358       * @param  allowConcurrentSocketFactoryUse  Indicates whether to allow a
1359       *                                          socket factory instance to be used
1360       *                                          to create multiple sockets
1361       *                                          concurrently.
1362       */
1363      public void setAllowConcurrentSocketFactoryUse(
1364                       final boolean allowConcurrentSocketFactoryUse)
1365      {
1366        this.allowConcurrentSocketFactoryUse = allowConcurrentSocketFactoryUse;
1367      }
1368    
1369    
1370    
1371      /**
1372       * Retrieves the {@link SSLSocketVerifier} that will be used to perform
1373       * additional validation for any newly-created {@code SSLSocket} instances.
1374       *
1375       * @return  The {@code SSLSocketVerifier} that will be used to perform
1376       *          additional validation for any newly-created {@code SSLSocket}
1377       *          instances.
1378       */
1379      public SSLSocketVerifier getSSLSocketVerifier()
1380      {
1381        return sslSocketVerifier;
1382      }
1383    
1384    
1385    
1386      /**
1387       * Specifies the {@link SSLSocketVerifier} that will be used to perform
1388       * additional validation for any newly-created {@code SSLSocket} instances.
1389       *
1390       * @param  sslSocketVerifier  The {@code SSLSocketVerifier} that will be used
1391       *                            to perform additional validation for any
1392       *                            newly-created {@code SSLSocket} instances.
1393       */
1394      public void setSSLSocketVerifier(final SSLSocketVerifier sslSocketVerifier)
1395      {
1396        if (sslSocketVerifier == null)
1397        {
1398          this.sslSocketVerifier = DEFAULT_SSL_SOCKET_VERIFIER;
1399        }
1400        else
1401        {
1402          this.sslSocketVerifier = sslSocketVerifier;
1403        }
1404      }
1405    
1406    
1407    
1408      /**
1409       * Retrieves a string representation of this LDAP connection.
1410       *
1411       * @return  A string representation of this LDAP connection.
1412       */
1413      @Override()
1414      public String toString()
1415      {
1416        final StringBuilder buffer = new StringBuilder();
1417        toString(buffer);
1418        return buffer.toString();
1419      }
1420    
1421    
1422    
1423      /**
1424       * Appends a string representation of this LDAP connection to the provided
1425       * buffer.
1426       *
1427       * @param  buffer  The buffer to which to append a string representation of
1428       *                 this LDAP connection.
1429       */
1430      public void toString(final StringBuilder buffer)
1431      {
1432        buffer.append("LDAPConnectionOptions(autoReconnect=");
1433        buffer.append(autoReconnect);
1434        buffer.append(", bindWithDNRequiresPassword=");
1435        buffer.append(bindWithDNRequiresPassword);
1436        buffer.append(", followReferrals=");
1437        buffer.append(followReferrals);
1438        if (followReferrals)
1439        {
1440          buffer.append(", referralHopLimit=");
1441          buffer.append(referralHopLimit);
1442        }
1443        if (referralConnector != null)
1444        {
1445          buffer.append(", referralConnectorClass=");
1446          buffer.append(referralConnector.getClass().getName());
1447        }
1448        buffer.append(", useKeepAlive=");
1449        buffer.append(useKeepAlive);
1450        buffer.append(", useLinger=");
1451        if (useLinger)
1452        {
1453          buffer.append("true, lingerTimeoutSeconds=");
1454          buffer.append(lingerTimeout);
1455        }
1456        else
1457        {
1458          buffer.append("false");
1459        }
1460        buffer.append(", useReuseAddress=");
1461        buffer.append(useReuseAddress);
1462        buffer.append(", useSchema=");
1463        buffer.append(useSchema);
1464        buffer.append(", usePooledSchema=");
1465        buffer.append(usePooledSchema);
1466        buffer.append(", pooledSchemaTimeoutMillis=");
1467        buffer.append(pooledSchemaTimeout);
1468        buffer.append(", useSynchronousMode=");
1469        buffer.append(useSynchronousMode);
1470        buffer.append(", useTCPNoDelay=");
1471        buffer.append(useTCPNoDelay);
1472        buffer.append(", captureConnectStackTrace=");
1473        buffer.append(captureConnectStackTrace);
1474        buffer.append(", connectTimeoutMillis=");
1475        buffer.append(connectTimeout);
1476        buffer.append(", responseTimeoutMillis=");
1477        buffer.append(responseTimeout);
1478        buffer.append(", abandonOnTimeout=");
1479        buffer.append(abandonOnTimeout);
1480        buffer.append(", maxMessageSize=");
1481        buffer.append(maxMessageSize);
1482        buffer.append(", receiveBufferSize=");
1483        buffer.append(receiveBufferSize);
1484        buffer.append(", sendBufferSize=");
1485        buffer.append(sendBufferSize);
1486        buffer.append(", allowConcurrentSocketFactoryUse=");
1487        buffer.append(allowConcurrentSocketFactoryUse);
1488        if (disconnectHandler != null)
1489        {
1490          buffer.append(", disconnectHandlerClass=");
1491          buffer.append(disconnectHandler.getClass().getName());
1492        }
1493        if (unsolicitedNotificationHandler != null)
1494        {
1495          buffer.append(", unsolicitedNotificationHandlerClass=");
1496          buffer.append(unsolicitedNotificationHandler.getClass().getName());
1497        }
1498    
1499        buffer.append(", sslSocketVerifierClass='");
1500        buffer.append(sslSocketVerifier.getClass().getName());
1501        buffer.append('\'');
1502    
1503        buffer.append(')');
1504      }
1505    }