001    /*
002     * Copyright 2007-2012 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2012 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 true}) for the setting that controls whether to
183       * use the {@code SO_KEEPALIVE} socket option.
184       */
185      static final boolean DEFAULT_USE_KEEPALIVE = true;
186    
187    
188    
189      /**
190       * The default value ({@code true}) for the setting that controls whether to
191       * use the {@code SO_LINGER} socket option.
192       */
193      static final boolean DEFAULT_USE_LINGER = true;
194    
195    
196    
197      /**
198       * The default value ({@code true}) for the setting that controls whether to
199       * use the {@code SO_REUSEADDR} socket option.
200       */
201      static final boolean DEFAULT_USE_REUSE_ADDRESS = true;
202    
203    
204    
205      /**
206       * The default value ({@code false}) for the setting that controls whether to
207       * use schema when reading data from the server.
208       */
209      static final boolean DEFAULT_USE_SCHEMA = false;
210    
211    
212    
213      /**
214       * The default value ({@code false}) for the setting that controls whether to
215       * operate in synchronous mode, in which only a single outstanding operation
216       * may be in progress on an associated connection at any given time.
217       */
218      static final boolean DEFAULT_USE_SYNCHRONOUS_MODE = false;
219    
220    
221    
222      /**
223       * The default value ({@code true}) for the setting that controls whether to
224       * use the {@code TCP_NODELAY} socket option.
225       */
226      static final boolean DEFAULT_USE_TCP_NODELAY = true;
227    
228    
229    
230      /**
231       * The default value (60000) for the setting that controls the timeout in
232       * milliseconds when trying to establish a new connection.
233       */
234      static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 60000;
235    
236    
237    
238      /**
239       * The default value (5) for the setting that controls the timeout in seconds
240       * that will be used with the {@code SO_LINGER} socket option.
241       */
242      static final int DEFAULT_LINGER_TIMEOUT_SECONDS = 5;
243    
244    
245    
246      /**
247       * The default value (20971520 bytes, or 20MB) for the setting that controls
248       * the maximum LDAP message size in bytes that will be allowed when reading
249       * data from a directory server.
250       */
251      static final int DEFAULT_MAX_MESSAGE_SIZE = 20971520;
252    
253    
254    
255      /**
256       * The default size to use for the receive buffer.
257       */
258      static final int DEFAULT_RECEIVE_BUFFER_SIZE = 0;
259    
260    
261    
262      /**
263       * The default value (5) for the setting that controls the referral hop limit.
264       */
265      static final int DEFAULT_REFERRAL_HOP_LIMIT = 5;
266    
267    
268    
269      /**
270       * The default size to use for the send buffer.
271       */
272      static final int DEFAULT_SEND_BUFFER_SIZE = 0;
273    
274    
275    
276      /**
277       * The default value (300000) for the setting that controls the default
278       * response timeout in milliseconds.
279       */
280      static final long DEFAULT_RESPONSE_TIMEOUT_MILLIS = 300000L;
281    
282    
283    
284      /**
285       * The default value for the setting that controls the default behavior with
286       * regard to whether to allow concurrent use of a socket factory to create
287       * client connections.
288       */
289      static final boolean DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE;
290      static
291      {
292        final String vmVendor =
293             StaticUtils.toLowerCase(System.getProperty("java.vm.vendor"));
294        DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE = ((vmVendor != null) &&
295             (vmVendor.contains("sun microsystems") ||
296              vmVendor.contains("oracle") ||
297              vmVendor.contains("apple")));
298      }
299    
300    
301    
302      // Indicates whether to send an abandon request for any operation for which no
303      // response is received in the maximum response timeout.
304      private boolean abandonOnTimeout;
305    
306      // Indicates whether the connection should attempt to automatically reconnect
307      // if the connection to the server is lost.
308      private boolean autoReconnect;
309    
310      // Indicates whether to allow simple binds that contain a DN but no password.
311      private boolean bindWithDNRequiresPassword;
312    
313      // Indicates whether to capture a thread stack trace whenever an attempt is
314      // made to establish a connection;
315      private boolean captureConnectStackTrace;
316    
317      // Indicates whether to attempt to follow any referrals that are encountered.
318      private boolean followReferrals;
319    
320      // Indicates whether to use synchronization prevent concurrent use of the
321      // socket factory instance associated with a connection or set of connections.
322      private boolean allowConcurrentSocketFactoryUse;
323    
324      // Indicates whether to use SO_KEEPALIVE for the underlying sockets.
325      private boolean useKeepAlive;
326    
327      // Indicates whether to use SO_LINGER for the underlying sockets.
328      private boolean useLinger;
329    
330      // Indicates whether to use SO_REUSEADDR for the underlying sockets.
331      private boolean useReuseAddress;
332    
333      // Indicates whether to try to use schema information when reading data from
334      // the server.
335      private boolean useSchema;
336    
337      // Indicates whether to use synchronous mode in which only a single operation
338      // may be in progress on associated connections at any given time.
339      private boolean useSynchronousMode;
340    
341      // Indicates whether to use TCP_NODELAY for the underlying sockets.
342      private boolean useTCPNoDelay;
343    
344      // The disconnect handler for associated connections.
345      private DisconnectHandler disconnectHandler;
346    
347      // The connect timeout, in milliseconds.
348      private int connectTimeout;
349    
350      // The linger timeout to use if SO_LINGER is to be used.
351      private int lingerTimeout;
352    
353      // The maximum message size in bytes that will be allowed when reading data
354      // from a directory server.
355      private int maxMessageSize;
356    
357      // The socket receive buffer size to request.
358      private int receiveBufferSize;
359    
360      // The referral hop limit to use if referral following is enabled.
361      private int referralHopLimit;
362    
363      // The socket send buffer size to request.
364      private int sendBufferSize;
365    
366      // The response timeout, in milliseconds.
367      private long responseTimeout;
368    
369      // Tne default referral connector that should be used for associated
370      // connections.
371      private ReferralConnector referralConnector;
372    
373      // The unsolicited notification handler for associated connections.
374      private UnsolicitedNotificationHandler unsolicitedNotificationHandler;
375    
376    
377    
378      /**
379       * Creates a new set of LDAP connection options with the default settings.
380       */
381      public LDAPConnectionOptions()
382      {
383        abandonOnTimeout               = DEFAULT_ABANDON_ON_TIMEOUT;
384        autoReconnect                  = DEFAULT_AUTO_RECONNECT;
385        bindWithDNRequiresPassword     = DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD;
386        captureConnectStackTrace       = DEFAULT_CAPTURE_CONNECT_STACK_TRACE;
387        followReferrals                = DEFAULT_FOLLOW_REFERRALS;
388        useKeepAlive                   = DEFAULT_USE_KEEPALIVE;
389        useLinger                      = DEFAULT_USE_LINGER;
390        useReuseAddress                = DEFAULT_USE_REUSE_ADDRESS;
391        useSchema                      = DEFAULT_USE_SCHEMA;
392        useSynchronousMode             = DEFAULT_USE_SYNCHRONOUS_MODE;
393        useTCPNoDelay                  = DEFAULT_USE_TCP_NODELAY;
394        connectTimeout                 = DEFAULT_CONNECT_TIMEOUT_MILLIS;
395        lingerTimeout                  = DEFAULT_LINGER_TIMEOUT_SECONDS;
396        maxMessageSize                 = DEFAULT_MAX_MESSAGE_SIZE;
397        referralHopLimit               = DEFAULT_REFERRAL_HOP_LIMIT;
398        responseTimeout                = DEFAULT_RESPONSE_TIMEOUT_MILLIS;
399        receiveBufferSize              = DEFAULT_RECEIVE_BUFFER_SIZE;
400        sendBufferSize                 = DEFAULT_SEND_BUFFER_SIZE;
401        disconnectHandler              = null;
402        referralConnector              = null;
403        unsolicitedNotificationHandler = null;
404    
405        allowConcurrentSocketFactoryUse =
406             DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE;
407      }
408    
409    
410    
411      /**
412       * Returns a duplicate of this LDAP connection options object that may be
413       * modified without impacting this instance.
414       *
415       * @return  A duplicate of this LDAP connection options object that may be
416       *          modified without impacting this instance.
417       */
418      public LDAPConnectionOptions duplicate()
419      {
420        final LDAPConnectionOptions o = new LDAPConnectionOptions();
421    
422        o.abandonOnTimeout                = abandonOnTimeout;
423        o.allowConcurrentSocketFactoryUse = allowConcurrentSocketFactoryUse;
424        o.autoReconnect                   = autoReconnect;
425        o.bindWithDNRequiresPassword      = bindWithDNRequiresPassword;
426        o.captureConnectStackTrace        = captureConnectStackTrace;
427        o.followReferrals                 = followReferrals;
428        o.useKeepAlive                    = useKeepAlive;
429        o.useLinger                       = useLinger;
430        o.useReuseAddress                 = useReuseAddress;
431        o.useSchema                       = useSchema;
432        o.useSynchronousMode              = useSynchronousMode;
433        o.useTCPNoDelay                   = useTCPNoDelay;
434        o.connectTimeout                  = connectTimeout;
435        o.lingerTimeout                   = lingerTimeout;
436        o.maxMessageSize                  = maxMessageSize;
437        o.responseTimeout                 = responseTimeout;
438        o.referralConnector               = referralConnector;
439        o.referralHopLimit                = referralHopLimit;
440        o.disconnectHandler               = disconnectHandler;
441        o.unsolicitedNotificationHandler  = unsolicitedNotificationHandler;
442        o.receiveBufferSize               = receiveBufferSize;
443        o.sendBufferSize                  = sendBufferSize;
444    
445        return o;
446      }
447    
448    
449    
450      /**
451       * Indicates whether associated connections should attempt to automatically
452       * reconnect to the target server if the connection is lost.  Note that this
453       * option will not have any effect on pooled connections because defunct
454       * pooled connections will be replaced by newly-created connections rather
455       * than attempting to re-establish the existing connection.
456       *
457       * @return  {@code true} if associated connections should attempt to
458       *          automatically reconnect to the target server if the connection is
459       *          lost, or {@code false} if not.
460       */
461      public boolean autoReconnect()
462      {
463        return autoReconnect;
464      }
465    
466    
467    
468      /**
469       * Specifies whether associated connections should attempt to automatically
470       * reconnect to the target server if the connection is lost.  Note that
471       * automatic reconnection will only be available for authenticated clients if
472       * the authentication mechanism used provides support for re-binding on a new
473       * connection.  Also note that this option will not have any effect on pooled
474       * connections because defunct pooled connections will be replaced by
475       * newly-created connections rather than attempting to re-establish the
476       * existing connection.
477       *
478       * @param  autoReconnect  Specifies whether associated connections should
479       *                        attempt to automatically reconnect to the target
480       *                        server if the connection is lost.
481       */
482      public void setAutoReconnect(final boolean autoReconnect)
483      {
484        this.autoReconnect = autoReconnect;
485      }
486    
487    
488    
489      /**
490       * Indicates whether the SDK should allow simple bind operations that contain
491       * a bind DN but no password.  Binds of this type may represent a security
492       * vulnerability in client applications because they may cause the client to
493       * believe that the user is properly authenticated when the server considers
494       * it to be an unauthenticated connection.
495       *
496       * @return  {@code true} if the SDK should allow simple bind operations that
497       *          contain a bind DN but no password, or {@code false} if not.
498       */
499      public boolean bindWithDNRequiresPassword()
500      {
501        return bindWithDNRequiresPassword;
502      }
503    
504    
505    
506      /**
507       * Specifies whether the SDK should allow simple bind operations that contain
508       * a bind DN but no password.
509       *
510       * @param  bindWithDNRequiresPassword  Indicates whether the SDK should allow
511       *                                     simple bind operations that contain a
512       *                                     bind DN but no password.
513       */
514      public void setBindWithDNRequiresPassword(
515                       final boolean bindWithDNRequiresPassword)
516      {
517        this.bindWithDNRequiresPassword = bindWithDNRequiresPassword;
518      }
519    
520    
521    
522      /**
523       * Indicates whether the LDAP SDK should capture a thread stack trace for each
524       * attempt made to establish a connection.  If this is enabled, then the
525       * {@link LDAPConnection#getConnectStackTrace()}  method may be used to
526       * retrieve the stack trace.
527       *
528       * @return  {@code true} if a thread stack trace should be captured whenever a
529       *          connection is established, or {@code false} if not.
530       */
531      public boolean captureConnectStackTrace()
532      {
533        return captureConnectStackTrace;
534      }
535    
536    
537    
538      /**
539       * Specifies whether the LDAP SDK should capture a thread stack trace for each
540       * attempt made to establish a connection.
541       *
542       * @param  captureConnectStackTrace  Indicates whether to capture a thread
543       *                                   stack trace for each attempt made to
544       *                                   establish a connection.
545       */
546      public void setCaptureConnectStackTrace(
547                       final boolean captureConnectStackTrace)
548      {
549        this.captureConnectStackTrace = captureConnectStackTrace;
550      }
551    
552    
553    
554      /**
555       * Retrieves the maximum length of time in milliseconds that a connection
556       * attempt should be allowed to continue before giving up.
557       *
558       * @return  The maximum length of time in milliseconds that a connection
559       *          attempt should be allowed to continue before giving up, or zero
560       *          to indicate that there should be no connect timeout.
561       */
562      public int getConnectTimeoutMillis()
563      {
564        return connectTimeout;
565      }
566    
567    
568    
569      /**
570       * Specifies the maximum length of time in milliseconds that a connection
571       * attempt should be allowed to continue before giving up.  A value of zero
572       * indicates that there should be no connect timeout.
573       *
574       * @param  connectTimeout  The maximum length of time in milliseconds that a
575       *                         connection attempt should be allowed to continue
576       *                         before giving up.
577       */
578      public void setConnectTimeoutMillis(final int connectTimeout)
579      {
580        this.connectTimeout = connectTimeout;
581      }
582    
583    
584    
585      /**
586       * Retrieves the maximum length of time in milliseconds that an operation
587       * should be allowed to block while waiting for a response from the server.
588       * This may be overridden on a per-operation basis.
589       *
590       * @return  The maximum length of time in milliseconds that an operation
591       *          should be allowed to block while waiting for a response from the
592       *          server, or zero if there should not be any default timeout.
593       */
594      public long getResponseTimeoutMillis()
595      {
596        return responseTimeout;
597      }
598    
599    
600    
601      /**
602       * Specifies the maximum length of time in milliseconds that an operation
603       * should be allowed to block while waiting for a response from the server.  A
604       * value of zero indicates that there should be no timeout.
605       *
606       * @param  responseTimeout  The maximum length of time in milliseconds that an
607       *                          operation should be allowed to block while waiting
608       *                          for a response from the server.
609       *
610       */
611      public void setResponseTimeoutMillis(final long responseTimeout)
612      {
613        if (responseTimeout < 0)
614        {
615          this.responseTimeout = 0L;
616        }
617        else
618        {
619          this.responseTimeout = responseTimeout;
620        }
621      }
622    
623    
624    
625      /**
626       * Indicates whether the LDAP SDK should attempt to abandon any request for
627       * which no response is received in the maximum response timeout period.
628       *
629       * @return  {@code true} if the LDAP SDK should attempt to abandon any request
630       *          for which no response is received in the maximum response timeout
631       *          period, or {@code false} if no abandon attempt should be made in
632       *          this circumstance.
633       */
634      public boolean abandonOnTimeout()
635      {
636        return abandonOnTimeout;
637      }
638    
639    
640    
641      /**
642       * Specifies whether the LDAP SDK should attempt to abandon any request for
643       * which no response is received in the maximum response timeout period.
644       *
645       * @param  abandonOnTimeout  Indicates whether the LDAP SDK should attempt to
646       *                           abandon any request for which no response is
647       *                           received in the maximum response timeout period.
648       */
649      public void setAbandonOnTimeout(final boolean abandonOnTimeout)
650      {
651        this.abandonOnTimeout = abandonOnTimeout;
652      }
653    
654    
655    
656      /**
657       * Indicates whether to use the SO_KEEPALIVE option for the underlying sockets
658       * used by associated connections.
659       *
660       * @return  {@code true} if the SO_KEEPALIVE option should be used for the
661       *          underlying sockets, or {@code false} if not.
662       */
663      public boolean useKeepAlive()
664      {
665        return useKeepAlive;
666      }
667    
668    
669    
670      /**
671       * Specifies whether to use the SO_KEEPALIVE option for the underlying sockets
672       * used by associated connections.  Changes to this setting will take effect
673       * only for new sockets, and not for existing sockets.
674       *
675       * @param  useKeepAlive  Indicates whether to use the SO_KEEPALIVE option for
676       *                       the underlying sockets used by associated
677       *                       connections.
678       */
679      public void setUseKeepAlive(final boolean useKeepAlive)
680      {
681        this.useKeepAlive = useKeepAlive;
682      }
683    
684    
685    
686      /**
687       * Indicates whether to use the SO_LINGER option for the underlying sockets
688       * used by associated connections.
689       *
690       * @return  {@code true} if the SO_LINGER option should be used for the
691       *          underlying sockets, or {@code false} if not.
692       */
693      public boolean useLinger()
694      {
695        return useLinger;
696      }
697    
698    
699    
700      /**
701       * Retrieves the linger timeout in seconds that will be used if the SO_LINGER
702       * socket option is enabled.
703       *
704       * @return  The linger timeout in seconds that will be used if the SO_LINGER
705       *          socket option is enabled.
706       */
707      public int getLingerTimeoutSeconds()
708      {
709        return lingerTimeout;
710      }
711    
712    
713    
714      /**
715       * Specifies whether to use the SO_LINGER option for the underlying sockets
716       * used by associated connections.  Changes to this setting will take effect
717       * only for new sockets, and not for existing sockets.
718       *
719       * @param  useLinger      Indicates whether to use the SO_LINGER option for
720       *                        the underlying sockets used by associated
721       *                        connections.
722       * @param  lingerTimeout  The linger timeout in seconds that should be used if
723       *                        this capability is enabled.
724       */
725      public void setUseLinger(final boolean useLinger, final int lingerTimeout)
726      {
727        this.useLinger     = useLinger;
728        this.lingerTimeout = lingerTimeout;
729      }
730    
731    
732    
733      /**
734       * Indicates whether to use the SO_REUSEADDR option for the underlying sockets
735       * used by associated connections.
736       *
737       * @return  {@code true} if the SO_REUSEADDR option should be used for the
738       *          underlying sockets, or {@code false} if not.
739       */
740      public boolean useReuseAddress()
741      {
742        return useReuseAddress;
743      }
744    
745    
746    
747      /**
748       * Specifies whether to use the SO_KEEPALIVE option for the underlying sockets
749       * used by associated connections.  Changes to this setting will take effect
750       * only for new sockets, and not for existing sockets.
751       *
752       * @param  useReuseAddress  Indicates whether to use the SO_REUSEADDR option
753       *                          for the underlying sockets used by associated
754       *                          connections.
755       */
756      public void setUseReuseAddress(final boolean useReuseAddress)
757      {
758        this.useReuseAddress = useReuseAddress;
759      }
760    
761    
762    
763      /**
764       * Indicates whether to try to use schema information when reading data from
765       * the server (e.g., to select the appropriate matching rules for the
766       * attributes included in a search result entry).
767       *
768       * @return  {@code true} if schema should be used when reading data from the
769       *          server, or {@code false} if not.
770       */
771      public boolean useSchema()
772      {
773        return useSchema;
774      }
775    
776    
777    
778      /**
779       * Specifies whether to try to use schema information when reading data from
780       * the server  (e.g., to select the appropriate matching rules for the
781       * attributes included in a search result entry).
782       *
783       * @param  useSchema  Indicates whether to try to use schema information when
784       *                    reading data from the server.
785       */
786      public void setUseSchema(final boolean useSchema)
787      {
788        this.useSchema = useSchema;
789      }
790    
791    
792    
793      /**
794       * Indicates whether to operate in synchronous mode, in which at most one
795       * operation may be in progress at any time on a given connection, which may
796       * allow it to operate more efficiently and without requiring a separate
797       * reader thread per connection.  The LDAP SDK will not absolutely enforce
798       * this restriction, but when operating in this mode correct behavior
799       * cannot be guaranteed when multiple attempts are made to use a connection
800       * for multiple concurrent operations.
801       * <BR><BR>
802       * Note that if synchronous mode is to be used, then this connection option
803       * must be set on the connection before any attempt is made to establish the
804       * connection.  Once the connection has been established, then it will
805       * continue to operate in synchronous or asynchronous mode based on the
806       * options in place at the time it was connected.
807       *
808       * @return  {@code true} if associated connections should operate in
809       *          synchronous mode, or {@code false} if not.
810       */
811      public boolean useSynchronousMode()
812      {
813        return useSynchronousMode;
814      }
815    
816    
817    
818      /**
819       * Specifies whether to operate in synchronous mode, in which at most one
820       * operation may be in progress at any time on a given connection.
821       * <BR><BR>
822       * Note that if synchronous mode is to be used, then this connection option
823       * must be set on the connection before any attempt is made to establish the
824       * connection.  Once the connection has been established, then it will
825       * continue to operate in synchronous or asynchronous mode based on the
826       * options in place at the time it was connected.
827       *
828       * @param  useSynchronousMode  Indicates whether to operate in synchronous
829       *                             mode.
830       */
831      public void setUseSynchronousMode(final boolean useSynchronousMode)
832      {
833        this.useSynchronousMode = useSynchronousMode;
834      }
835    
836    
837    
838      /**
839       * Indicates whether to use the TCP_NODELAY option for the underlying sockets
840       * used by associated connections.
841       *
842       * @return  {@code true} if the TCP_NODELAY option should be used for the
843       *          underlying sockets, or {@code false} if not.
844       */
845      public boolean useTCPNoDelay()
846      {
847        return useTCPNoDelay;
848      }
849    
850    
851    
852      /**
853       * Specifies whether to use the SO_KEEPALIVE option for the underlying sockets
854       * used by associated connections.  Changes to this setting will take effect
855       * only for new sockets, and not for existing sockets.
856       *
857       * @param  useTCPNoDelay  Indicates whether to use the TCP_NODELAY option for
858       *                        the underlying sockets used by associated
859       *                        connections.
860       */
861      public void setUseTCPNoDelay(final boolean useTCPNoDelay)
862      {
863        this.useTCPNoDelay = useTCPNoDelay;
864      }
865    
866    
867    
868      /**
869       * Indicates whether associated connections should attempt to follow any
870       * referrals that they encounter.
871       *
872       * @return  {@code true} if associated connections should attempt to follow
873       *          any referrals that they encounter, or {@code false} if not.
874       */
875      public boolean followReferrals()
876      {
877        return followReferrals;
878      }
879    
880    
881    
882      /**
883       * Specifies whether associated connections should attempt to follow any
884       * referrals that they encounter, using the referral connector for the
885       * associated connection.
886       *
887       * @param  followReferrals  Specifies whether associated connections should
888       *                          attempt to follow any referrals that they
889       *                          encounter.
890       */
891      public void setFollowReferrals(final boolean followReferrals)
892      {
893        this.followReferrals = followReferrals;
894      }
895    
896    
897    
898      /**
899       * Retrieves the maximum number of hops that a connection should take when
900       * trying to follow a referral.
901       *
902       * @return  The maximum number of hops that a connection should take when
903       *          trying to follow a referral.
904       */
905      public int getReferralHopLimit()
906      {
907        return referralHopLimit;
908      }
909    
910    
911    
912      /**
913       * Specifies the maximum number of hops that a connection should take when
914       * trying to follow a referral.
915       *
916       * @param  referralHopLimit  The maximum number of hops that a connection
917       *                           should take when trying to follow a referral.  It
918       *                           must be greater than zero.
919       */
920      public void setReferralHopLimit(final int referralHopLimit)
921      {
922        ensureTrue(referralHopLimit > 0,
923             "LDAPConnectionOptions.referralHopLimit must be greater than 0.");
924    
925        this.referralHopLimit = referralHopLimit;
926      }
927    
928    
929    
930      /**
931       * Retrieves the referral connector that will be used to establish and
932       * optionally authenticate connections to servers when attempting to follow
933       * referrals, if defined.
934       *
935       * @return  The referral connector that will be used to establish and
936       *          optionally authenticate connections to servers when attempting to
937       *          follow referrals, or {@code null} if no specific referral
938       *          connector has been configured and referral connections should be
939       *          created using the same socket factory and bind request as the
940       *          connection on which the referral was received.
941       */
942      public ReferralConnector getReferralConnector()
943      {
944        return referralConnector;
945      }
946    
947    
948    
949      /**
950       * Specifies the referral connector that should be used to establish and
951       * optionally authenticate connections to servers when attempting to follow
952       * referrals.
953       *
954       * @param  referralConnector  The referral connector that will be used to
955       *                            establish and optionally authenticate
956       *                            connections to servers when attempting to follow
957       *                            referrals.  It may be {@code null} to indicate
958       *                            that the same socket factory and bind request
959       *                            as the connection on which the referral was
960       *                            received should be used to establish and
961       *                            authenticate connections for following
962       *                            referrals.
963       */
964      public void setReferralConnector(final ReferralConnector referralConnector)
965      {
966        this.referralConnector = referralConnector;
967      }
968    
969    
970    
971      /**
972       * Retrieves the maximum size in bytes for an LDAP message that a connection
973       * will attempt to read from the directory server.  If it encounters an LDAP
974       * message that is larger than this size, then the connection will be
975       * terminated.
976       *
977       * @return  The maximum size in bytes for an LDAP message that a connection
978       *          will attempt to read from the directory server, or 0 if no limit
979       *          will be enforced.
980       */
981      public int getMaxMessageSize()
982      {
983        return maxMessageSize;
984      }
985    
986    
987    
988      /**
989       * Specifies the maximum size in bytes for an LDAP message that a connection
990       * will attempt to read from the directory server.  If it encounters an LDAP
991       * message that is larger than this size, then the connection will be
992       * terminated.
993       *
994       * @param  maxMessageSize  The maximum size in bytes for an LDAP message that
995       *                         a connection will attempt to read from the
996       *                         directory server.  A value less than or equal to
997       *                         zero indicates that no limit should be enforced.
998       */
999      public void setMaxMessageSize(final int maxMessageSize)
1000      {
1001        if (maxMessageSize > 0)
1002        {
1003          this.maxMessageSize = maxMessageSize;
1004        }
1005        else
1006        {
1007          this.maxMessageSize = 0;
1008        }
1009      }
1010    
1011    
1012    
1013      /**
1014       * Retrieves the disconnect handler to use for associated connections.
1015       *
1016       * @return  the disconnect handler to use for associated connections, or
1017       *          {@code null} if none is defined.
1018       */
1019      public DisconnectHandler getDisconnectHandler()
1020      {
1021        return disconnectHandler;
1022      }
1023    
1024    
1025    
1026      /**
1027       * Specifies the disconnect handler to use for associated connections.
1028       *
1029       * @param  handler  The disconnect handler to use for associated connections.
1030       */
1031      public void setDisconnectHandler(final DisconnectHandler handler)
1032      {
1033        disconnectHandler = handler;
1034      }
1035    
1036    
1037    
1038      /**
1039       * Retrieves the unsolicited notification handler to use for associated
1040       * connections.
1041       *
1042       * @return  The unsolicited notification handler to use for associated
1043       *          connections, or {@code null} if none is defined.
1044       */
1045      public UnsolicitedNotificationHandler getUnsolicitedNotificationHandler()
1046      {
1047        return unsolicitedNotificationHandler;
1048      }
1049    
1050    
1051    
1052      /**
1053       * Specifies the unsolicited notification handler to use for associated
1054       * connections.
1055       *
1056       * @param  handler  The unsolicited notification handler to use for associated
1057       *                  connections.
1058       */
1059      public void setUnsolicitedNotificationHandler(
1060                       final UnsolicitedNotificationHandler handler)
1061      {
1062        unsolicitedNotificationHandler = handler;
1063      }
1064    
1065    
1066    
1067      /**
1068       * Retrieves the socket receive buffer size that should be requested when
1069       * establishing a connection.
1070       *
1071       * @return  The socket receive buffer size that should be requested when
1072       *          establishing a connection, or zero if the default size should be
1073       *          used.
1074       */
1075      public int getReceiveBufferSize()
1076      {
1077        return receiveBufferSize;
1078      }
1079    
1080    
1081    
1082      /**
1083       * Specifies the socket receive buffer size that should be requested when
1084       * establishing a connection.
1085       *
1086       * @param  receiveBufferSize  The socket receive buffer size that should be
1087       *                            requested when establishing a connection, or
1088       *                            zero if the default size should be used.
1089       */
1090      public void setReceiveBufferSize(final int receiveBufferSize)
1091      {
1092        if (receiveBufferSize < 0)
1093        {
1094          this.receiveBufferSize = 0;
1095        }
1096        else
1097        {
1098          this.receiveBufferSize = receiveBufferSize;
1099        }
1100      }
1101    
1102    
1103    
1104      /**
1105       * Retrieves the socket send buffer size that should be requested when
1106       * establishing a connection.
1107       *
1108       * @return  The socket send buffer size that should be requested when
1109       *          establishing a connection, or zero if the default size should be
1110       *          used.
1111       */
1112      public int getSendBufferSize()
1113      {
1114        return sendBufferSize;
1115      }
1116    
1117    
1118    
1119      /**
1120       * Specifies the socket send buffer size that should be requested when
1121       * establishing a connection.
1122       *
1123       * @param  sendBufferSize  The socket send buffer size that should be
1124       *                         requested when establishing a connection, or zero
1125       *                         if the default size should be used.
1126       */
1127      public void setSendBufferSize(final int sendBufferSize)
1128      {
1129        if (sendBufferSize < 0)
1130        {
1131          this.sendBufferSize = 0;
1132        }
1133        else
1134        {
1135          this.sendBufferSize = sendBufferSize;
1136        }
1137      }
1138    
1139    
1140    
1141      /**
1142       * Indicates whether to allow a socket factory instance (which may be shared
1143       * across multiple connections) to be used create multiple sockets
1144       * concurrently.  In general, socket factory implementations are threadsafe
1145       * and can be to create multiple connections simultaneously across separate
1146       * threads, but this is known to not be the case in some VM implementations
1147       * (e.g., SSL socket factories in IBM JVMs).  This setting may be used to
1148       * indicate whether concurrent socket creation attempts should be allowed
1149       * (which may allow for better and more consistent performance, especially in
1150       * cases where a connection attempt fails due to a timeout) or prevented
1151       * (which may be necessary for non-threadsafe socket factory implementations).
1152       *
1153       * @return  {@code true} if multiple threads should be able to concurrently
1154       *          use the same socket factory instance, or {@code false} if Java
1155       *          synchronization should be used to ensure that no more than one
1156       *          thread is allowed to use a socket factory at any given time.
1157       */
1158      public boolean allowConcurrentSocketFactoryUse()
1159      {
1160        return allowConcurrentSocketFactoryUse;
1161      }
1162    
1163    
1164    
1165      /**
1166       * Specifies whether to allow a socket factory instance (which may be shared
1167       * across multiple connections) to be used create multiple sockets
1168       * concurrently.  In general, socket factory implementations are threadsafe
1169       * and can be to create multiple connections simultaneously across separate
1170       * threads, but this is known to not be the case in some VM implementations
1171       * (e.g., SSL socket factories in IBM JVMs).  This setting may be used to
1172       * indicate whether concurrent socket creation attempts should be allowed
1173       * (which may allow for better and more consistent performance, especially in
1174       * cases where a connection attempt fails due to a timeout) or prevented
1175       * (which may be necessary for non-threadsafe socket factory implementations).
1176       *
1177       * @param  allowConcurrentSocketFactoryUse  Indicates whether to allow a
1178       *                                          socket factory instance to be used
1179       *                                          to create multiple sockets
1180       *                                          concurrently.
1181       */
1182      public void setAllowConcurrentSocketFactoryUse(
1183                       final boolean allowConcurrentSocketFactoryUse)
1184      {
1185        this.allowConcurrentSocketFactoryUse = allowConcurrentSocketFactoryUse;
1186      }
1187    
1188    
1189    
1190      /**
1191       * Retrieves a string representation of this LDAP connection.
1192       *
1193       * @return  A string representation of this LDAP connection.
1194       */
1195      @Override()
1196      public String toString()
1197      {
1198        final StringBuilder buffer = new StringBuilder();
1199        toString(buffer);
1200        return buffer.toString();
1201      }
1202    
1203    
1204    
1205      /**
1206       * Appends a string representation of this LDAP connection to the provided
1207       * buffer.
1208       *
1209       * @param  buffer  The buffer to which to append a string representation of
1210       *                 this LDAP connection.
1211       */
1212      public void toString(final StringBuilder buffer)
1213      {
1214        buffer.append("LDAPConnectionOptions(autoReconnect=");
1215        buffer.append(autoReconnect);
1216        buffer.append(", bindWithDNRequiresPassword=");
1217        buffer.append(bindWithDNRequiresPassword);
1218        buffer.append(", followReferrals=");
1219        buffer.append(followReferrals);
1220        if (followReferrals)
1221        {
1222          buffer.append(", referralHopLimit=");
1223          buffer.append(referralHopLimit);
1224        }
1225        if (referralConnector != null)
1226        {
1227          buffer.append(", referralConnectorClass=");
1228          buffer.append(referralConnector.getClass().getName());
1229        }
1230        buffer.append(", useKeepAlive=");
1231        buffer.append(useKeepAlive);
1232        buffer.append(", useLinger=");
1233        if (useLinger)
1234        {
1235          buffer.append("true, lingerTimeoutSeconds=");
1236          buffer.append(lingerTimeout);
1237        }
1238        else
1239        {
1240          buffer.append("false");
1241        }
1242        buffer.append(", useReuseAddress=");
1243        buffer.append(useReuseAddress);
1244        buffer.append(", useSchema=");
1245        buffer.append(useSchema);
1246        buffer.append(", useSynchronousMode=");
1247        buffer.append(useSynchronousMode);
1248        buffer.append(", useTCPNoDelay=");
1249        buffer.append(useTCPNoDelay);
1250        buffer.append(", captureConnectStackTrace=");
1251        buffer.append(captureConnectStackTrace);
1252        buffer.append(", connectTimeoutMillis=");
1253        buffer.append(connectTimeout);
1254        buffer.append(", responseTimeoutMillis=");
1255        buffer.append(responseTimeout);
1256        buffer.append(", abandonOnTimeout=");
1257        buffer.append(abandonOnTimeout);
1258        buffer.append(", maxMessageSize=");
1259        buffer.append(maxMessageSize);
1260        buffer.append(", receiveBufferSize=");
1261        buffer.append(receiveBufferSize);
1262        buffer.append(", sendBufferSize=");
1263        buffer.append(sendBufferSize);
1264        buffer.append(", allowConcurrentSocketFactoryUse=");
1265        buffer.append(allowConcurrentSocketFactoryUse);
1266        if (disconnectHandler != null)
1267        {
1268          buffer.append(", disconnectHandlerClass=");
1269          buffer.append(disconnectHandler.getClass().getName());
1270        }
1271        if (unsolicitedNotificationHandler != null)
1272        {
1273          buffer.append(", unsolicitedNotificationHandlerClass=");
1274          buffer.append(unsolicitedNotificationHandler.getClass().getName());
1275        }
1276        buffer.append(')');
1277      }
1278    }