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