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