001/*
002 * Copyright 2007-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2008-2018 Ping Identity Corporation
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 java.util.Arrays;
026import java.util.Collections;
027import java.util.EnumMap;
028import java.util.HashMap;
029import java.util.Map;
030import java.util.logging.Level;
031
032import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedRequest;
033import com.unboundid.ldap.sdk.extensions.StartTLSExtendedRequest;
034import com.unboundid.ldap.sdk.extensions.WhoAmIExtendedRequest;
035import com.unboundid.ldap.sdk.unboundidds.extensions.
036            DeregisterYubiKeyOTPDeviceExtendedRequest;
037import com.unboundid.ldap.sdk.unboundidds.extensions.
038            EndAdministrativeSessionExtendedRequest;
039import com.unboundid.ldap.sdk.unboundidds.extensions.
040            GenerateTOTPSharedSecretExtendedRequest;
041import com.unboundid.ldap.sdk.unboundidds.extensions.
042            GetConnectionIDExtendedRequest;
043import com.unboundid.ldap.sdk.unboundidds.extensions.
044            GetPasswordQualityRequirementsExtendedRequest;
045import com.unboundid.ldap.sdk.unboundidds.extensions.
046            PasswordPolicyStateExtendedRequest;
047import com.unboundid.ldap.sdk.unboundidds.extensions.
048            RegisterYubiKeyOTPDeviceExtendedRequest;
049import com.unboundid.ldap.sdk.unboundidds.extensions.
050            RevokeTOTPSharedSecretExtendedRequest;
051import com.unboundid.ldap.sdk.unboundidds.extensions.
052            StartAdministrativeSessionExtendedRequest;
053import com.unboundid.ldap.sdk.unboundidds.extensions.
054            ValidateTOTPPasswordExtendedRequest;
055import com.unboundid.util.Debug;
056import com.unboundid.util.DebugType;
057import com.unboundid.util.Mutable;
058import com.unboundid.util.StaticUtils;
059import com.unboundid.util.ThreadSafety;
060import com.unboundid.util.ThreadSafetyLevel;
061import com.unboundid.util.Validator;
062import com.unboundid.util.ssl.SSLSocketVerifier;
063import com.unboundid.util.ssl.TrustAllSSLSocketVerifier;
064
065
066
067/**
068 * This class provides a data structure that may be used to configure a number
069 * of connection-related properties.  Elements included in the set of connection
070 * options include:
071 * <UL>
072 *   <LI>A flag that indicates whether the SDK should attempt to automatically
073 *       re-establish a connection if it is unexpectedly closed.  By default,
074 *       it will not attempt to do so.</LI>
075 *   <LI>A flag that indicates whether simple bind attempts that contain a
076 *       non-empty DN will be required to have a non-empty password.  By
077 *       default, a password will be required in such cases.</LI>
078 *   <LI>A flag that indicates whether to automatically attempt to follow any
079 *       referrals that may be returned by the server.  By default, it will not
080 *       automatically attempt to follow referrals.</LI>
081 *   <LI>A referral hop limit, which indicates the maximum number of hops that
082 *       the connection may take when trying to follow a referral.  The default
083 *       referral hop limit is five.</LI>
084 *   <LI>The referral connector that should be used to create and optionally
085 *       authenticate connections used to follow referrals encountered during
086 *       processing.  By default, referral connections will use the same socket
087 *       factory and bind request as the client connection on which the referral
088 *       was received.</LI>
089 *   <LI>A flag that indicates whether to use the SO_KEEPALIVE socket option to
090 *       attempt to more quickly detect when idle TCP connections have been lost
091 *       or to prevent them from being unexpectedly closed by intermediate
092 *       network hardware.  By default, the SO_KEEPALIVE socket option will be
093 *       used.</LI>
094 *   <LI>A flag that indicates whether to use the SO_LINGER socket option to
095 *       indicate how long a connection should linger after it has been closed,
096 *       and a value that specifies the length of time that it should linger.
097 *       By default, the SO_LINGER option will be used with a timeout of 5
098 *       seconds.</LI>
099 *   <LI>A flag that indicates whether to use the SO_REUSEADDR socket option to
100 *       indicate that a socket in a TIME_WAIT state may be reused.  By default,
101 *       the SO_REUSEADDR socket option will be used.</LI>
102 *   <LI>A flag that indicates whether to operate in synchronous mode, in which
103 *       connections may exhibit better performance and will not require a
104 *       separate reader thread, but will not allow multiple concurrent
105 *       operations to be used on the same connection.</LI>
106 *   <LI>A flag that indicates whether to use the TCP_NODELAY socket option to
107 *       indicate that any data written to the socket will be sent immediately
108 *       rather than delaying for a short amount of time to see if any more data
109 *       is to be sent that could potentially be included in the same packet.
110 *       By default, the TCP_NODELAY socket option will be used.</LI>
111 *   <LI>A value that specifies the maximum length of time in milliseconds that
112 *       an attempt to establish a connection should be allowed to block before
113 *       failing.  By default, a timeout of 10,000 milliseconds (10 seconds)
114 *       will be used.</LI>
115 *   <LI>A value that specifies the default timeout in milliseconds that the SDK
116 *       should wait for a response from the server before failing.  This can be
117 *       defined on a per-operation-type basis, with a default of 300,000
118 *       milliseconds (5 minutes) for search and extended operations, and a
119 *       default timeout of 30,000 milliseconds (30 seconds) for all other types
120 *       of operations.  Further, the extended operation timeout can be
121 *       customized on a per-operation-type basis, and a number of extended
122 *       operation types have been configured with a 30,000 millisecond timeout
123 *       by default.  Individual requests can also be configured with their own
124 *       response timeouts, and if provided, that timeout will override the
125 *       default timeout from the connection options.</LI>
126 *   <LI>A flag that indicates whether to attempt to abandon any request for
127 *       which no response is received after waiting for the maximum response
128 *       timeout.  By default, no abandon request will be sent.</LI>
129 *   <LI>A value which specifies the largest LDAP message size that the SDK will
130 *       be willing to read from the directory server.  By default, the SDK will
131 *       not allow responses larger than 20,971,520 bytes (20MB).  If it
132 *       encounters a message that may be larger than the maximum allowed
133 *       message size, then the SDK will terminate the connection to the
134 *       server.</LI>
135 *   <LI>The {@link DisconnectHandler} that should be used to receive
136 *       notification if connection is disconnected for any reason.  By default,
137 *       no {@code DisconnectHandler} will be used.</LI>
138 *   <LI>The {@link UnsolicitedNotificationHandler} that should be used to
139 *       receive notification about any unsolicited notifications returned by
140 *       the server.  By default, no {@code UnsolicitedNotificationHandler} will
141 *       be used.</LI>
142 *   <LI>A flag that indicates whether to capture a thread stack trace whenever
143 *       a new connection is established.  Capturing a thread stack trace when
144 *       establishing a connection may be marginally expensive, but can be
145 *       useful for debugging certain kinds of problems like leaked connections
146 *       (connections that are established but never explicitly closed).  By
147 *       default, connect stack traces will not be captured.</LI>
148 *   <LI>A flag that indicates whether connections should try to retrieve schema
149 *       information from the server, which may be used to better determine
150 *       which matching rules should be used when comparing attribute values.
151 *       By default, server schema information will not be retrieved.</LI>
152 *   <LI>The size of the socket receive buffer, which may be used for
153 *       temporarily holding data received from the directory server until it
154 *       can be read and processed by the LDAP SDK.  By default, the receive
155 *       buffer size will be automatically determined by the JVM based on the
156 *       underlying system settings.</LI>
157 *   <LI>The size of the socket send buffer, which may be used for temporarily
158 *       holding data to be sent to the directory server until it can actually
159 *       be transmitted over the network.  By default, the send buffer size will
160 *       be automatically determined by the JVM based on the underlying system
161 *       settings.</LI>
162 *  <LI>A flag which indicates whether to allow a single socket factory instance
163 *      (which may be shared across multiple connections) to be used to create
164 *      multiple concurrent connections.  This offers better and more
165 *      predictable performance on some JVM implementations (especially when
166 *      connection attempts fail as a result of a connection timeout), but some
167 *      JVMs are known to use non-threadsafe socket factory implementations and
168 *      may fail from concurrent use (for example, at least some IBM JVMs
169 *      exhibit this behavior).  By default, Sun/Oracle JVMs will allow
170 *      concurrent socket factory use, but JVMs from other vendors will use
171 *      synchronization to ensure that a socket factory will only be allowed to
172 *      create one connection at a time.</LI>
173 *  <LI>A class that may be used to perform additional verification (e.g.,
174 *      hostname validation) for any {@code SSLSocket} instances created.  By
175 *      default, no special verification will be performed.</LI>
176 * </UL>
177 */
178@Mutable()
179@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
180public final class LDAPConnectionOptions
181{
182  /**
183   * The prefix that will be used in conjunction with all system properties.
184   */
185  private static final String PROPERTY_PREFIX =
186       LDAPConnectionOptions.class.getName() + '.';
187
188
189
190  /**
191   * The name of a system property that can be used to specify the initial
192   * default value for the "abandon on timeout" behavior.  If this property is
193   * set at the time that this class is loaded, then its value must be either
194   * "true" or "false".  If this property is not set, then a default value of
195   * "false" will be assumed.
196   * <BR><BR>
197   * The full name for this system property is
198   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultAbandonTimeout".
199   */
200  public static final String PROPERTY_DEFAULT_ABANDON_ON_TIMEOUT =
201       PROPERTY_PREFIX + "defaultAbandonOnTimeout";
202
203
204
205  /**
206   * The default value for the setting that controls whether to automatically
207   * attempt to abandon any request for which no response is received within the
208   * maximum response timeout.  If the
209   * {@link #PROPERTY_DEFAULT_ABANDON_ON_TIMEOUT} system property is set at the
210   * time this class is loaded, then its value will be used.  Otherwise, a
211   * default of {@code false} will be used.
212   */
213  private static final boolean DEFAULT_ABANDON_ON_TIMEOUT =
214       getSystemProperty(PROPERTY_DEFAULT_ABANDON_ON_TIMEOUT, false);
215
216
217
218  /**
219   * The default value ({@code false}) for the setting that controls whether to
220   * automatically attempt to reconnect if a connection is unexpectedly lost.
221   */
222  private static final boolean DEFAULT_AUTO_RECONNECT = false;
223
224
225
226  /**
227   * The name of a system property that can be used to specify the initial
228   * default value for the "bind with DN requires password" behavior.  If this
229   * property is set at the time that this class is loaded, then its value must
230   * be either "true" or "false".  If this property is not set, then a default
231   * value of "true" will be assumed.
232   * <BR><BR>
233   * The full name for this system property is
234   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.
235   * defaultBindWithDNRequiresPassword".
236   */
237  public static final String PROPERTY_DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD =
238       PROPERTY_PREFIX + "defaultBindWithDNRequiresPassword";
239
240
241
242  /**
243   * The default value for the setting that controls whether simple bind
244   * requests with a DN will also be required to contain a password.  If the
245   * {@link #PROPERTY_DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD} system property is
246   * set at the time this class is loaded, then its value will be used.
247   * Otherwise, a default of {@code true} will be used.
248   */
249  private static final boolean DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD =
250       getSystemProperty(PROPERTY_DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD, true);
251
252
253
254  /**
255   * The name of a system property that can be used to specify the initial
256   * default value for the "capture connect stack trace" behavior.  If this
257   * property is set at the time that this class is loaded, then its value must
258   * be either "true" or "false".  If this property is not set, then a default
259   * value of "false" will be assumed.
260   * <BR><BR>
261   * The full name for this system property is "com.unboundid.ldap.sdk.
262   * LDAPConnectionOptions.defaultCaptureConnectStackTrace".
263   */
264  public static final String PROPERTY_DEFAULT_CAPTURE_CONNECT_STACK_TRACE =
265       PROPERTY_PREFIX + "defaultCaptureConnectStackTrace";
266
267
268
269  /**
270   * The default value for the setting that controls whether to capture a thread
271   * stack trace whenever an attempt is made to establish a connection.  If the
272   * {@link #PROPERTY_DEFAULT_CAPTURE_CONNECT_STACK_TRACE} system property is
273   * set at the time this class is loaded, then its value will be used.
274   * Otherwise, a default of {@code false} will be used.
275   */
276  private static final boolean DEFAULT_CAPTURE_CONNECT_STACK_TRACE =
277       getSystemProperty(PROPERTY_DEFAULT_CAPTURE_CONNECT_STACK_TRACE, false);
278
279
280
281  /**
282   * The name of a system property that can be used to specify the initial
283   * default value for the "follow referrals" behavior.  If this property is set
284   * at the time that this class is loaded, then its value must be either
285   * "true" or "false".  If this property is not set, then a default value of
286   * "false" will be assumed.
287   * <BR><BR>
288   * The full name for this system property is
289   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultFollowReferrals".
290   */
291  public static final String PROPERTY_DEFAULT_FOLLOW_REFERRALS =
292       PROPERTY_PREFIX + "defaultFollowReferrals";
293
294
295
296  /**
297   * The default value for the setting that controls whether to attempt to
298   * automatically follow referrals.  If the
299   * {@link #PROPERTY_DEFAULT_FOLLOW_REFERRALS} system property is set at the
300   * time this class is loaded, then its value will be used.  Otherwise, a
301   * default of {@code false} will be used.
302   */
303  private static final boolean DEFAULT_FOLLOW_REFERRALS =
304       getSystemProperty(PROPERTY_DEFAULT_FOLLOW_REFERRALS, false);
305
306
307
308  /**
309   * The name of a system property that can be used to specify the maximum
310   * number of hops to make when following a referral.  If this property is set
311   * at the time that this class is loaded, then its value must be parseable as
312   * an integer.  If this property is not set, then a default value of "5" will
313   * be assumed.
314   * <BR><BR>
315   * The full name for this system property is
316   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultReferralHopLimit".
317   */
318  public static final String PROPERTY_DEFAULT_REFERRAL_HOP_LIMIT =
319       PROPERTY_PREFIX + "defaultReferralHopLimit";
320
321
322
323  /**
324   * The default value for the setting that controls the referral hop limit.  If
325   * the {@link #PROPERTY_DEFAULT_REFERRAL_HOP_LIMIT} system property is set at
326   * the time this class is loaded, then its value will be used.  Otherwise, a
327   * default value of 5 will be used.
328   */
329  private static final int DEFAULT_REFERRAL_HOP_LIMIT =
330       getSystemProperty(PROPERTY_DEFAULT_REFERRAL_HOP_LIMIT, 5);
331
332
333
334  /**
335   * The name of a system property that can be used to specify the initial
336   * default value for the "use schema" behavior.  If this property is set at
337   * the time that this class is loaded, then its value must be either "true" or
338   * "false".  If this property is not set, then a default value of "false" will
339   * be assumed.
340   * <BR><BR>
341   * The full name for this system property is
342   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultUseSchema".
343   */
344  public static final String PROPERTY_DEFAULT_USE_SCHEMA =
345       PROPERTY_PREFIX + "defaultUseSchema";
346
347
348
349  /**
350   * The default value for the setting that controls whether to use schema when
351   * reading data from the server.  If the {@link #PROPERTY_DEFAULT_USE_SCHEMA}
352   * system property is set at the time this class is loaded, then its value
353   * will be used.  Otherwise, a default value of {@code false} will be used.
354   */
355  private static final boolean DEFAULT_USE_SCHEMA =
356       getSystemProperty(PROPERTY_DEFAULT_USE_SCHEMA, false);
357
358
359
360  /**
361   * The name of a system property that can be used to specify the initial
362   * default value for the "use pooled schema" behavior.  If this property is
363   * set at the time that this class is loaded, then its value must be either
364   * "true" or "false".  If this property is not set, then a default value of
365   * "false" will be assumed.
366   * <BR><BR>
367   * The full name for this system property is
368   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultUsePooledSchema".
369   */
370  public static final String PROPERTY_DEFAULT_USE_POOLED_SCHEMA =
371       PROPERTY_PREFIX + "defaultUsePooledSchema";
372
373
374
375  /**
376   * The default value for the setting that controls whether all connections in
377   * a connection pool should use the same cached schema object.  If the
378   * {@link #PROPERTY_DEFAULT_USE_POOLED_SCHEMA} system property is set at the
379   * time this class is loaded, then its value will be used.  Otherwise, a
380   * default of {@code false} will be used.
381   */
382  private static final boolean DEFAULT_USE_POOLED_SCHEMA =
383       getSystemProperty(PROPERTY_DEFAULT_USE_POOLED_SCHEMA, false);
384
385
386
387  /**
388   * The name of a system property that can be used to specify the initial
389   * default value for the pooled schema timeout, in milliseconds.  If this
390   * property is set at the time that this class is loaded, then its value must
391   * be parseable as an integer.  If this property is not set, then a default
392   * value of "3600000" (3,600,000 milliseconds, or 1 hour) will be assumed.
393   * <BR><BR>
394   * The full name for this system property is "com.unboundid.ldap.sdk.
395   * LDAPConnectionOptions.defaultPooledSchemaTimeoutMillis".
396   */
397  public static final String PROPERTY_DEFAULT_POOLED_SCHEMA_TIMEOUT_MILLIS =
398       PROPERTY_PREFIX + "defaultPooledSchemaTimeoutMillis";
399
400
401
402  /**
403   * The default value for the setting that controls the default pooled schema
404   * timeout.  If the {@link #PROPERTY_DEFAULT_POOLED_SCHEMA_TIMEOUT_MILLIS}
405   * system property is set at the time this class is loaded, then its value
406   * will be used.  Otherwise, a default of 3,600,000 milliseconds (1 hour) will
407   * be used.
408   */
409  private static final long DEFAULT_POOLED_SCHEMA_TIMEOUT_MILLIS = 3_600_000L;
410
411
412
413  /**
414   * The name of a system property that can be used to specify the initial
415   * default value for the "use keepalive" behavior.  If this property is set at
416   * the time that this class is loaded, then its value must be either "true" or
417   * "false".  If this property is not set, then a default value of "true" will
418   * be assumed.
419   * <BR><BR>
420   * The full name for this system property is
421   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultUseKeepalive".
422   */
423  public static final String PROPERTY_DEFAULT_USE_KEEPALIVE =
424       PROPERTY_PREFIX + "defaultUseKeepalive";
425
426
427
428  /**
429   * The default value for the setting that controls whether to use the
430   * {@code SO_KEEPALIVE} socket option.  If the
431   * {@link #PROPERTY_DEFAULT_USE_KEEPALIVE} system property is set at the time
432   * this class is loaded, then its value will be used.  Otherwise, a default of
433   * {@code true} will be used.
434   */
435  private static final boolean DEFAULT_USE_KEEPALIVE =
436       getSystemProperty(PROPERTY_DEFAULT_USE_KEEPALIVE, true);
437
438
439
440  /**
441   * The name of a system property that can be used to specify the initial
442   * default value for the "use linger" behavior.  If this property is set at
443   * the time that this class is loaded, then its value must be either "true" or
444   * "false".  If this property is not set, then a default value of "true" will
445   * be assumed.
446   * <BR><BR>
447   * The full name for this system property is
448   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultUseLinger".
449   */
450  public static final String PROPERTY_DEFAULT_USE_LINGER =
451       PROPERTY_PREFIX + "defaultUseLinger";
452
453
454
455  /**
456   * The default value for the setting that controls whether to use the
457   * {@code SO_LINGER} socket option.  If the
458   * {@link #PROPERTY_DEFAULT_USE_LINGER} system property is set at the time
459   * this class is loaded, then its value will be used.  Otherwise, a default of
460   * {@code true} will be used.
461   */
462  private static final boolean DEFAULT_USE_LINGER =
463       getSystemProperty(PROPERTY_DEFAULT_USE_LINGER, true);
464
465
466
467  /**
468   * The name of a system property that can be used to specify the initial
469   * default value for the linger timeout, in seconds.  If this property is set
470   * at the time that this class is loaded, then its value must be parseable as
471   * an integer.  If this property is not set, then a default value of "5" (5
472   * seconds) will be assumed.
473   * <BR><BR>
474   * The full name for this system property is
475   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultLingerTimeoutSeconds".
476   */
477  public static final String PROPERTY_DEFAULT_LINGER_TIMEOUT_SECONDS =
478       PROPERTY_PREFIX + "defaultLingerTimeoutSeconds";
479
480
481
482  /**
483   * The default value for the setting that controls the timeout in seconds that
484   * will be used with the {@code SO_LINGER} socket option.  If the
485   * {@link #PROPERTY_DEFAULT_LINGER_TIMEOUT_SECONDS} property is set at the
486   * time this class is loaded, then its value will be used.  Otherwise, a
487   * default linger timeout of 5 seconds will be used.
488   */
489  private static final int DEFAULT_LINGER_TIMEOUT_SECONDS =
490       getSystemProperty(PROPERTY_DEFAULT_LINGER_TIMEOUT_SECONDS, 5);
491
492
493
494  /**
495   * The name of a system property that can be used to specify the initial
496   * default value for the "use reuse address" behavior.  If this property is
497   * set at the time that this class is loaded, then its value must be either
498   * "true" or "false".  If this property is not set, then a default value of
499   * "true" will be assumed.
500   * <BR><BR>
501   * The full name for this system property is
502   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultUseReuseAddress".
503   */
504  public static final String PROPERTY_DEFAULT_USE_REUSE_ADDRESS =
505       PROPERTY_PREFIX + "defaultUseReuseAddress";
506
507
508
509  /**
510   * The default value for the setting that controls whether to use the
511   * {@code SO_REUSEADDR} socket option.  If the
512   * {@link #PROPERTY_DEFAULT_USE_REUSE_ADDRESS} system property is set at the
513   * time this class is loaded, then its value will be used.  Otherwise, a
514   * default value of {@code true} will be used.
515   */
516  private static final boolean DEFAULT_USE_REUSE_ADDRESS =
517       getSystemProperty(PROPERTY_DEFAULT_USE_REUSE_ADDRESS, true);
518
519
520
521  /**
522   * The name of a system property that can be used to specify the initial
523   * default value for the "use synchronous mode" behavior.  If this property is
524   * set at the time that this class is loaded, then its value must be either
525   * "true" or "false".  If this property is not set, then a default value of
526   * "false" will be assumed.
527   * <BR><BR>
528   * The full name for this system property is
529   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultUseSynchronousMode".
530   */
531  public static final String PROPERTY_DEFAULT_USE_SYNCHRONOUS_MODE =
532       PROPERTY_PREFIX + "defaultUseSynchronousMode";
533
534
535
536  /**
537   * The default value for the setting that controls whether to operate in
538   * synchronous mode, in which only a single outstanding operation may be in
539   * progress on an associated connection at any given time.  If the
540   * {@link #PROPERTY_DEFAULT_USE_SYNCHRONOUS_MODE} system property is set at
541   * the time this class is loaded, then its value will be used.  Otherwise, a
542   * default value of {@code false} will be used.
543   */
544  private static final boolean DEFAULT_USE_SYNCHRONOUS_MODE =
545       getSystemProperty(PROPERTY_DEFAULT_USE_SYNCHRONOUS_MODE, false);
546
547
548
549  /**
550   * The name of a system property that can be used to specify the initial
551   * default value for the "use TCP nodelay" behavior.  If this property is set
552   * at the time that this class is loaded, then its value must be either "true"
553   * or "false".  If this property is not set, then a default value of "true"
554   * will be assumed.
555   * <BR><BR>
556   * The full name for this system property is
557   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultUseTCPNoDelay".
558   */
559  public static final String PROPERTY_DEFAULT_USE_TCP_NODELAY =
560       PROPERTY_PREFIX + "defaultUseTCPNoDelay";
561
562
563
564  /**
565   * The default value for the setting that controls whether to use the
566   * {@code TCP_NODELAY} socket option.  If the
567   * {@link #PROPERTY_DEFAULT_USE_TCP_NODELAY} system property is set at the
568   * time this class is loaded, then its value will be used.  Otherwise, a
569   * default value of {@code true} will be used.
570   */
571  private static final boolean DEFAULT_USE_TCP_NODELAY =
572       getSystemProperty(PROPERTY_DEFAULT_USE_TCP_NODELAY, true);
573
574
575
576  /**
577   * The name of a system property that can be used to specify the initial
578   * default connect timeout, in milliseconds.  If this property is set at the
579   * time that this class is loaded, then its value must be parseable as an
580   * integer.  If this property is not set then a default value of "10000"
581   * (10,000 milliseconds, or ten seconds) will be assumed.
582   * <BR><BR>
583   * The full name for this system property is
584   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultConnectTimeoutMillis".
585   */
586  public static final String PROPERTY_DEFAULT_CONNECT_TIMEOUT_MILLIS =
587       PROPERTY_PREFIX + "defaultConnectTimeoutMillis";
588
589
590
591  /**
592   * The default value for the setting that controls the timeout in milliseconds
593   * when trying to establish a new connection.  If the
594   * {@link #PROPERTY_DEFAULT_CONNECT_TIMEOUT_MILLIS} system property is set at
595   * the time this class is loaded, then its value will be used.  Otherwise, a
596   * default of 10,000 milliseconds (10 seconds) will be used.
597   */
598  private static final int DEFAULT_CONNECT_TIMEOUT_MILLIS =
599       getSystemProperty(PROPERTY_DEFAULT_CONNECT_TIMEOUT_MILLIS, 10_000);
600
601
602
603  /**
604   * The name of a system property that can be used to specify the initial
605   * default value for the maximum message size, in bytes.  If this property is
606   * set at the time that this class is loaded, then its value must be parseable
607   * as an integer.  If this property is not set, then a default value of
608   * "20971520" (20 megabytes) will be assumed.
609   * <BR><BR>
610   * The full name for this system property is
611   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultMaxMessageSizeBytes".
612   */
613  public static final String PROPERTY_DEFAULT_MAX_MESSAGE_SIZE_BYTES =
614       PROPERTY_PREFIX + "defaultMaxMessageSizeBytes";
615
616
617
618  /**
619   * The default value for the setting that controls the maximum LDAP message
620   * size in bytes that will be allowed when reading data from a directory
621   * server.  If the {@link #PROPERTY_DEFAULT_MAX_MESSAGE_SIZE_BYTES} system
622   * property is set at the time this class is loaded, then its value will be
623   * used.  Otherwise, a default value of 20,971,520 bytes (20 megabytes) will
624   * be used.
625   */
626  private static final int DEFAULT_MAX_MESSAGE_SIZE_BYTES =
627       getSystemProperty(PROPERTY_DEFAULT_MAX_MESSAGE_SIZE_BYTES, 20_971_520);
628
629
630
631  /**
632   * The name of a system property that can be used to specify the initial
633   * default value for the receive buffer size, in bytes.  If this property is
634   * set at the time that this class is loaded, then its value must be parseable
635   * as an integer.  If this property is not set, then a default value of "0"
636   * (indicating that the JVM's default receive buffer size) will be assumed.
637   * <BR><BR>
638   * The full name for this system property is "com.unboundid.ldap.sdk.
639   * LDAPConnectionOptions.defaultReceiveBufferSizeBytes".
640   */
641  public static final String PROPERTY_DEFAULT_RECEIVE_BUFFER_SIZE_BYTES =
642       PROPERTY_PREFIX + "defaultReceiveBufferSizeBytes";
643
644
645
646  /**
647   * The default size, in bytes, to use for the receive buffer.  If the
648   * {@link #PROPERTY_DEFAULT_RECEIVE_BUFFER_SIZE_BYTES} system property is set
649   * at the time this class is loaded, then its value will be used.  Otherwise,
650   * a default value of 0 will be used to indicate that the JVM's default
651   * receive buffer size should be used.
652   */
653  private static final int DEFAULT_RECEIVE_BUFFER_SIZE_BYTES =
654       getSystemProperty(PROPERTY_DEFAULT_RECEIVE_BUFFER_SIZE_BYTES, 0);
655
656
657
658  /**
659   * The name of a system property that can be used to specify the initial
660   * default value for the send buffer size, in bytes.  If this property is set
661   * at the time that this class is loaded, then its value must be parseable as
662   * an integer.  If this property is not set, then a default value of "0"
663   * (indicating that the JVM's default send buffer size) will be assumed.
664   * <BR><BR>
665   * The full name for this system property is
666   * "com.unboundid.ldap.sdk.LDAPConnectionOptions.defaultSendBufferSizeBytes".
667   */
668  public static final String PROPERTY_DEFAULT_SEND_BUFFER_SIZE_BYTES =
669       PROPERTY_PREFIX + "defaultSendBufferSizeBytes";
670
671
672
673  /**
674   * The default size, in bytes, to use for the send buffer.  If the
675   * {@link #PROPERTY_DEFAULT_SEND_BUFFER_SIZE_BYTES} system property is set at
676   * the time this class is loaded, then its value will be used.  Otherwise, a
677   * default value of 0 will be used to indicate that the JVM's default send
678   * buffer size should be used.
679   */
680  private static final int DEFAULT_SEND_BUFFER_SIZE_BYTES =
681       getSystemProperty(PROPERTY_DEFAULT_SEND_BUFFER_SIZE_BYTES, 0);
682
683
684
685  /**
686   * The name of a system property that can be used to specify the initial
687   * default value for response timeouts, in milliseconds, for all types of
688   * operations.  If this property is set at the time that this class is loaded,
689   * then its value must be parseable as an integer, and that value will
690   * override the values of any operation-specific properties.  If this property
691   * is not set, then a default value of "300000" (300,000 milliseconds, or
692   * 5 minutes) will be assumed, but that may be overridden by
693   * operation-specific properties.
694   * <BR><BR>
695   * The full name for this system property is "com.unboundid.ldap.sdk.
696   * LDAPConnectionOptions.defaultResponseTimeoutMillis".
697   */
698  public static final String PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS =
699       PROPERTY_PREFIX + "defaultResponseTimeoutMillis";
700
701
702
703  /**
704   * The name of a system property that can be used to specify the initial
705   * default value for response timeouts, in milliseconds, for add operations.
706   * If this property is set at the time that this class is loaded, then
707   * its value must be parseable as an integer.  It will only be used if the
708   * {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} system property is not
709   * set, as that property will override this one.  If neither of those
710   * properties is set, then a default value of "30000" (30,000 milliseconds, or
711   * 30 seconds) will be assumed.
712   * <BR><BR>
713   * The full name for this system property is "com.unboundid.ldap.sdk.
714   * LDAPConnectionOptions.defaultAddResponseTimeoutMillis".
715   */
716  public static final String PROPERTY_DEFAULT_ADD_RESPONSE_TIMEOUT_MILLIS =
717       PROPERTY_PREFIX + "defaultAddResponseTimeoutMillis";
718
719
720
721  /**
722   * The name of a system property that can be used to specify the initial
723   * default value for response timeouts, in milliseconds, for bind operations.
724   * If this property is set at the time that this class is loaded, then
725   * its value must be parseable as an integer.  It will only be used if the
726   * {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} system property is not
727   * set, as that property will override this one.  If neither of those
728   * properties is set, then a default value of "30000" (30,000 milliseconds, or
729   * 30 seconds) will be assumed.
730   * <BR><BR>
731   * The full name for this system property is "com.unboundid.ldap.sdk.
732   * LDAPConnectionOptions.defaultBindResponseTimeoutMillis".
733   */
734  public static final String PROPERTY_DEFAULT_BIND_RESPONSE_TIMEOUT_MILLIS =
735       PROPERTY_PREFIX + "defaultBindResponseTimeoutMillis";
736
737
738
739  /**
740   * The name of a system property that can be used to specify the initial
741   * default value for response timeouts, in milliseconds, for compare
742   * operations.  If this property is set at the time that this class is
743   * loaded, then its value must be parseable as an integer.  It will only be
744   * used if the {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} system
745   * property is not set, as that property will override this one.  If neither
746   * of those properties is set, then a default value of "30000" (30,000
747   * milliseconds, or 30 seconds) will be assumed.
748   * <BR><BR>
749   * The full name for this system property is "com.unboundid.ldap.sdk.
750   * LDAPConnectionOptions.defaultCompareResponseTimeoutMillis".
751   */
752  public static final String PROPERTY_DEFAULT_COMPARE_RESPONSE_TIMEOUT_MILLIS =
753       PROPERTY_PREFIX + "defaultCompareResponseTimeoutMillis";
754
755
756
757  /**
758   * The name of a system property that can be used to specify the initial
759   * default value for response timeouts, in milliseconds, for delete
760   * operations.  If this property is set at the time that this class is
761   * loaded, then its value must be parseable as an integer.  It will only be
762   * used if the {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} system
763   * property is not set, as that property will override this one.  If neither
764   * of those properties is set, then a default value of "30000" (30,000
765   * milliseconds, or 30 seconds) will be assumed.
766   * <BR><BR>
767   * The full name for this system property is "com.unboundid.ldap.sdk.
768   * LDAPConnectionOptions.defaultDeleteResponseTimeoutMillis".
769   */
770  public static final String PROPERTY_DEFAULT_DELETE_RESPONSE_TIMEOUT_MILLIS =
771       PROPERTY_PREFIX + "defaultDeleteResponseTimeoutMillis";
772
773
774
775  /**
776   * The name of a system property that can be used to specify the initial
777   * default value for response timeouts, in milliseconds, for extended
778   * operations.  If this property is set at the time that this class is
779   * loaded, then its value must be parseable as an integer.  It will only be
780   * used if the {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} system
781   * property is not set, as that property will override this one.  If neither
782   * of those properties is set, then a default value of "300000" (300,000
783   * milliseconds, or 5 minutes) will be assumed.
784   * <BR><BR>
785   * The full name for this system property is "com.unboundid.ldap.sdk.
786   * LDAPConnectionOptions.defaultExtendedResponseTimeoutMillis".
787   * <BR><BR>
788   * Note that different timeouts may be set for specific types using a system
789   * property with this name immediately followed by a period and the request
790   * OID for the desired extended operation type.  For example, the system
791   * property named "com.unboundid.ldap.sdk.LDAPConnectionOptions.
792   * defaultExtendedResponseTimeoutMillis.1.3.6.1.4.1.1466.20037" can be used to
793   * set a default response timeout for StartTLS extended operations.
794   * <BR><BR>
795   * If neither the {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} nor the
796   * {@code PROPERTY_DEFAULT_EXTENDED_RESPONSE_TIMEOUT_MILLIS} property is set,
797   * then the following standard extended operation types will have a default
798   * timeout of 30,000 milliseconds (30 seconds) instead of 300,000 milliseconds
799   * (5 minutes), unless a property is defined to override the timeout for that
800   * specific type of extended operation:
801   * <BR>
802   * <UL>
803   *   <LI>Password Modify (1.3.6.1.4.1.4203.1.11.1)</LI>
804   *   <LI>StartTLS (1.3.6.1.4.1.1466.20037)</LI>
805   *   <LI>Who Am I? (1.3.6.1.4.1.4203.1.11.3)</LI>
806   * </UL>
807   * <BR>
808   * The same will also be true for the following extended operations specific
809   * to the UnboundID/Ping Identity Directory Server:
810   * <BR>
811   * <UL>
812   *   <LI>Deregister YubiKey OTP Device (1.3.6.1.4.1.30221.2.6.55)</LI>
813   *   <LI>End Administrative Session (1.3.6.1.4.1.30221.2.6.14)</LI>
814   *   <LI>Generate TOTP Shared Secret (1.3.6.1.4.1.30221.2.6.56)</LI>
815   *   <LI>Get Connection ID (1.3.6.1.4.1.30221.1.6.2)</LI>
816   *   <LI>Get Password Quality Requirements (1.3.6.1.4.1.30221.2.6.43)</LI>
817   *   <LI>Password Policy State (1.3.6.1.4.1.30221.1.6.1)</LI>
818   *   <LI>Register YubiKey OTP Device (1.3.6.1.4.1.30221.2.6.54)</LI>
819   *   <LI>Revoke TOTP Shared Secret (1.3.6.1.4.1.30221.2.6.58)</LI>
820   *   <LI>Start Administrative Session (1.3.6.1.4.1.30221.2.6.13)</LI>
821   *   <LI>Validate TOTP Password (1.3.6.1.4.1.30221.2.6.15)</LI>
822   * </UL>
823   */
824  public static final String PROPERTY_DEFAULT_EXTENDED_RESPONSE_TIMEOUT_MILLIS =
825       PROPERTY_PREFIX + "defaultExtendedResponseTimeoutMillis";
826
827
828
829  /**
830   * The name of a system property that can be used to specify the initial
831   * default value for response timeouts, in milliseconds, for modify
832   * operations.  If this property is set at the time that this class is
833   * loaded, then its value must be parseable as an integer.  It will only be
834   * used if the {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} system
835   * property is not set, as that property will override this one.  If neither
836   * of those properties is set, then a default value of "30000" (30,000
837   * milliseconds, or 30 seconds) will be assumed.
838   * <BR><BR>
839   * The full name for this system property is "com.unboundid.ldap.sdk.
840   * LDAPConnectionOptions.defaultModifyResponseTimeoutMillis".
841   */
842  public static final String PROPERTY_DEFAULT_MODIFY_RESPONSE_TIMEOUT_MILLIS =
843       PROPERTY_PREFIX + "defaultModifyResponseTimeoutMillis";
844
845
846
847  /**
848   * The name of a system property that can be used to specify the initial
849   * default value for response timeouts, in milliseconds, for modify DN
850   * operations.  If this property is set at the time that this class is
851   * loaded, then its value must be parseable as an integer.  It will only be
852   * used if the {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} system
853   * property is not set, as that property will override this one.  If neither
854   * of those properties is set, then a default value of "30000" (30,000
855   * milliseconds, or 30 seconds) will be assumed.
856   * <BR><BR>
857   * The full name for this system property is "com.unboundid.ldap.sdk.
858   * LDAPConnectionOptions.defaultModifyDNResponseTimeoutMillis".
859   */
860  public static final String
861       PROPERTY_DEFAULT_MODIFY_DN_RESPONSE_TIMEOUT_MILLIS =
862            PROPERTY_PREFIX + "defaultModifyDNResponseTimeoutMillis";
863
864
865
866  /**
867   * The name of a system property that can be used to specify the initial
868   * default value for response timeouts, in milliseconds, for search
869   * operations.  If this property is set at the time that this class is
870   * loaded, then its value must be parseable as an integer.  It will only be
871   * used if the {@link #PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS} system
872   * property is not set, as that property will override this one.  If neither
873   * of those properties is set, then a default value of "300000" (300,000
874   * milliseconds, or 5 minutes) will be assumed.
875   * <BR><BR>
876   * The full name for this system property is "com.unboundid.ldap.sdk.
877   * LDAPConnectionOptions.defaultSearchResponseTimeoutMillis".
878   */
879  public static final String PROPERTY_DEFAULT_SEARCH_RESPONSE_TIMEOUT_MILLIS =
880       PROPERTY_PREFIX + "defaultSearchResponseTimeoutMillis";
881
882
883
884  /**
885   * The default value for the setting that controls the default response
886   * timeout, in milliseconds, for all types of operations.
887   */
888  private static final long DEFAULT_RESPONSE_TIMEOUT_MILLIS;
889
890
891
892  /**
893   * A map that holds the default values for the settings that control the
894   * default response timeouts, in milliseconds, for each type of operation.
895   */
896  private static final Map<OperationType,Long>
897       DEFAULT_RESPONSE_TIMEOUT_MILLIS_BY_OPERATION_TYPE;
898
899
900
901  /**
902   * A map that holds the default values for the settings that control the
903   * default response timeouts, in milliseconds, for specific types of extended
904   * operations.
905   */
906  private static final Map<String,Long>
907       DEFAULT_RESPONSE_TIMEOUT_MILLIS_BY_EXTENDED_OPERATION_TYPE;
908
909
910
911  static
912  {
913    Long allOpsTimeout = null;
914    final EnumMap<OperationType,Long> timeoutsByOpType =
915         new EnumMap<>(OperationType.class);
916    final HashMap<String,Long> timeoutsByExtOpType = new HashMap<>(10);
917
918    final String allOpsPropertyValue =
919         System.getProperty(PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS);
920    if (allOpsPropertyValue != null)
921    {
922      try
923      {
924        allOpsTimeout = Math.max(0L, Long.parseLong(allOpsPropertyValue));
925        for (final OperationType ot : OperationType.values())
926        {
927          timeoutsByOpType.put(ot, allOpsTimeout);
928        }
929
930        if (Debug.debugEnabled())
931        {
932          Debug.debug(Level.INFO, DebugType.OTHER,
933               "Using value " + allOpsTimeout + " set for system property '" +
934                  PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS + "'.  This " +
935                    "timeout will be used for all operation types.");
936        }
937      }
938      catch (final Exception e)
939      {
940        if (Debug.debugEnabled())
941        {
942          Debug.debugException(e);
943          Debug.debug(Level.WARNING, DebugType.OTHER,
944               "Invalid value '" + allOpsPropertyValue + "' set for system " +
945                    "property '" + PROPERTY_DEFAULT_RESPONSE_TIMEOUT_MILLIS +
946                    "'.  The value was expected to be a long.  Ignoring " +
947                    "this property and proceeding as if it had not been set.");
948        }
949      }
950    }
951
952    if (allOpsTimeout == null)
953    {
954      allOpsTimeout = 300_000L;
955
956      // Use hard-coded response timeouts of 10 seconds for abandon and unbind
957      // operations.  There is no response for these operations, but the timeout
958      // is also used for sending the request.
959      timeoutsByOpType.put(OperationType.ABANDON, 10_000L);
960      timeoutsByOpType.put(OperationType.UNBIND, 10_000L);
961
962      timeoutsByOpType.put(OperationType.ADD,
963           getSystemProperty(PROPERTY_DEFAULT_ADD_RESPONSE_TIMEOUT_MILLIS,
964                30_000L));
965      timeoutsByOpType.put(OperationType.BIND,
966           getSystemProperty(PROPERTY_DEFAULT_BIND_RESPONSE_TIMEOUT_MILLIS,
967                30_000L));
968      timeoutsByOpType.put(OperationType.COMPARE,
969           getSystemProperty(PROPERTY_DEFAULT_COMPARE_RESPONSE_TIMEOUT_MILLIS,
970                30_000L));
971      timeoutsByOpType.put(OperationType.DELETE,
972           getSystemProperty(PROPERTY_DEFAULT_DELETE_RESPONSE_TIMEOUT_MILLIS,
973                30_000L));
974      timeoutsByOpType.put(OperationType.MODIFY,
975           getSystemProperty(PROPERTY_DEFAULT_MODIFY_RESPONSE_TIMEOUT_MILLIS,
976                30_000L));
977      timeoutsByOpType.put(OperationType.MODIFY_DN,
978           getSystemProperty(PROPERTY_DEFAULT_MODIFY_DN_RESPONSE_TIMEOUT_MILLIS,
979                30_000L));
980      timeoutsByOpType.put(OperationType.SEARCH,
981           getSystemProperty(PROPERTY_DEFAULT_SEARCH_RESPONSE_TIMEOUT_MILLIS,
982                300_000L));
983
984      final String extendedOperationTypePrefix =
985           PROPERTY_DEFAULT_EXTENDED_RESPONSE_TIMEOUT_MILLIS + '.';
986      for (final String propertyName :
987           System.getProperties().stringPropertyNames())
988      {
989        if (propertyName.startsWith(extendedOperationTypePrefix))
990        {
991          final Long value = getSystemProperty(propertyName, null);
992          if (value != null)
993          {
994            final String oid = propertyName.substring(
995                 extendedOperationTypePrefix.length());
996            timeoutsByExtOpType.put(oid, value);
997          }
998        }
999      }
1000
1001      final Long extendedOpTimeout = getSystemProperty(
1002           PROPERTY_DEFAULT_EXTENDED_RESPONSE_TIMEOUT_MILLIS, null);
1003      if (extendedOpTimeout == null)
1004      {
1005        timeoutsByOpType.put(OperationType.EXTENDED, 300_000L);
1006
1007        for (final String oid :
1008          Arrays.asList(
1009               PasswordModifyExtendedRequest.PASSWORD_MODIFY_REQUEST_OID,
1010               StartTLSExtendedRequest.STARTTLS_REQUEST_OID,
1011               WhoAmIExtendedRequest.WHO_AM_I_REQUEST_OID,
1012               DeregisterYubiKeyOTPDeviceExtendedRequest.
1013                    DEREGISTER_YUBIKEY_OTP_DEVICE_REQUEST_OID,
1014               EndAdministrativeSessionExtendedRequest.
1015                    END_ADMIN_SESSION_REQUEST_OID,
1016               GenerateTOTPSharedSecretExtendedRequest.
1017                    GENERATE_TOTP_SHARED_SECRET_REQUEST_OID,
1018               GetConnectionIDExtendedRequest.GET_CONNECTION_ID_REQUEST_OID,
1019               GetPasswordQualityRequirementsExtendedRequest.
1020                    OID_GET_PASSWORD_QUALITY_REQUIREMENTS_REQUEST,
1021               PasswordPolicyStateExtendedRequest.
1022                    PASSWORD_POLICY_STATE_REQUEST_OID,
1023               RegisterYubiKeyOTPDeviceExtendedRequest.
1024                    REGISTER_YUBIKEY_OTP_DEVICE_REQUEST_OID,
1025               RevokeTOTPSharedSecretExtendedRequest.
1026                    REVOKE_TOTP_SHARED_SECRET_REQUEST_OID,
1027               StartAdministrativeSessionExtendedRequest.
1028                    START_ADMIN_SESSION_REQUEST_OID,
1029               ValidateTOTPPasswordExtendedRequest.
1030                    VALIDATE_TOTP_PASSWORD_REQUEST_OID))
1031        {
1032          if (! timeoutsByExtOpType.containsKey(oid))
1033          {
1034            timeoutsByExtOpType.put(oid, 30_000L);
1035          }
1036        }
1037      }
1038      else
1039      {
1040        timeoutsByOpType.put(OperationType.EXTENDED, extendedOpTimeout);
1041      }
1042    }
1043
1044    DEFAULT_RESPONSE_TIMEOUT_MILLIS = allOpsTimeout;
1045    DEFAULT_RESPONSE_TIMEOUT_MILLIS_BY_OPERATION_TYPE =
1046         Collections.unmodifiableMap(timeoutsByOpType);
1047    DEFAULT_RESPONSE_TIMEOUT_MILLIS_BY_EXTENDED_OPERATION_TYPE =
1048         Collections.unmodifiableMap(timeoutsByExtOpType);
1049  }
1050
1051
1052
1053  /**
1054   * The default value for the setting that controls the default behavior with
1055   * regard to whether to allow concurrent use of a socket factory to create
1056   * client connections.
1057   */
1058  private static final boolean DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE;
1059  static
1060  {
1061    final String vmVendor =
1062         StaticUtils.toLowerCase(System.getProperty("java.vm.vendor"));
1063    DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE = ((vmVendor != null) &&
1064         (vmVendor.contains("sun microsystems") ||
1065          vmVendor.contains("oracle") ||
1066          vmVendor.contains("apple") ||
1067          vmVendor.contains("azul systems")));
1068  }
1069
1070
1071
1072  /**
1073   * The default {@code SSLSocketVerifier} instance that will be used for
1074   * performing extra validation for {@code SSLSocket} instances.
1075   */
1076  private static final SSLSocketVerifier DEFAULT_SSL_SOCKET_VERIFIER =
1077       TrustAllSSLSocketVerifier.getInstance();
1078
1079
1080
1081  // Indicates whether to send an abandon request for any operation for which no
1082  // response is received in the maximum response timeout.
1083  private boolean abandonOnTimeout;
1084
1085  // Indicates whether to use synchronization prevent concurrent use of the
1086  // socket factory instance associated with a connection or set of connections.
1087  private boolean allowConcurrentSocketFactoryUse;
1088
1089  // Indicates whether the connection should attempt to automatically reconnect
1090  // if the connection to the server is lost.
1091  private boolean autoReconnect;
1092
1093  // Indicates whether to allow simple binds that contain a DN but no password.
1094  private boolean bindWithDNRequiresPassword;
1095
1096  // Indicates whether to capture a thread stack trace whenever an attempt is
1097  // made to establish a connection;
1098  private boolean captureConnectStackTrace;
1099
1100  // Indicates whether to attempt to follow any referrals that are encountered.
1101  private boolean followReferrals;
1102
1103  // Indicates whether to use SO_KEEPALIVE for the underlying sockets.
1104  private boolean useKeepAlive;
1105
1106  // Indicates whether to use SO_LINGER for the underlying sockets.
1107  private boolean useLinger;
1108
1109  // Indicates whether to use SO_REUSEADDR for the underlying sockets.
1110  private boolean useReuseAddress;
1111
1112  // Indicates whether all connections in a connection pool should reference
1113  // the same schema.
1114  private boolean usePooledSchema;
1115
1116  // Indicates whether to try to use schema information when reading data from
1117  // the server.
1118  private boolean useSchema;
1119
1120  // Indicates whether to use synchronous mode in which only a single operation
1121  // may be in progress on associated connections at any given time.
1122  private boolean useSynchronousMode;
1123
1124  // Indicates whether to use TCP_NODELAY for the underlying sockets.
1125  private boolean useTCPNoDelay;
1126
1127  // The disconnect handler for associated connections.
1128  private DisconnectHandler disconnectHandler;
1129
1130  // The connect timeout, in milliseconds.
1131  private int connectTimeoutMillis;
1132
1133  // The linger timeout to use if SO_LINGER is to be used.
1134  private int lingerTimeoutSeconds;
1135
1136  // The maximum message size in bytes that will be allowed when reading data
1137  // from a directory server.
1138  private int maxMessageSizeBytes;
1139
1140  // The socket receive buffer size to request.
1141  private int receiveBufferSizeBytes;
1142
1143  // The referral hop limit to use if referral following is enabled.
1144  private int referralHopLimit;
1145
1146  // The socket send buffer size to request.
1147  private int sendBufferSizeBytes;
1148
1149  // The pooled schema timeout, in milliseconds.
1150  private long pooledSchemaTimeoutMillis;
1151
1152  // The response timeout, in milliseconds.
1153  private long responseTimeoutMillis;
1154
1155  private Map<OperationType,Long> responseTimeoutMillisByOperationType;
1156
1157  private Map<String,Long> responseTimeoutMillisByExtendedOperationType;
1158
1159  // Tne default referral connector that should be used for associated
1160  // connections.
1161  private ReferralConnector referralConnector;
1162
1163  // The SSLSocketVerifier instance to use to perform extra validation on
1164  // newly-established SSLSocket instances.
1165  private SSLSocketVerifier sslSocketVerifier;
1166
1167  // The unsolicited notification handler for associated connections.
1168  private UnsolicitedNotificationHandler unsolicitedNotificationHandler;
1169
1170
1171
1172  /**
1173   * Creates a new set of LDAP connection options with the default settings.
1174   */
1175  public LDAPConnectionOptions()
1176  {
1177    abandonOnTimeout               = DEFAULT_ABANDON_ON_TIMEOUT;
1178    autoReconnect                  = DEFAULT_AUTO_RECONNECT;
1179    bindWithDNRequiresPassword     = DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD;
1180    captureConnectStackTrace       = DEFAULT_CAPTURE_CONNECT_STACK_TRACE;
1181    followReferrals                = DEFAULT_FOLLOW_REFERRALS;
1182    useKeepAlive                   = DEFAULT_USE_KEEPALIVE;
1183    useLinger                      = DEFAULT_USE_LINGER;
1184    useReuseAddress                = DEFAULT_USE_REUSE_ADDRESS;
1185    usePooledSchema                = DEFAULT_USE_POOLED_SCHEMA;
1186    useSchema                      = DEFAULT_USE_SCHEMA;
1187    useSynchronousMode             = DEFAULT_USE_SYNCHRONOUS_MODE;
1188    useTCPNoDelay                  = DEFAULT_USE_TCP_NODELAY;
1189    connectTimeoutMillis           = DEFAULT_CONNECT_TIMEOUT_MILLIS;
1190    lingerTimeoutSeconds           = DEFAULT_LINGER_TIMEOUT_SECONDS;
1191    maxMessageSizeBytes            = DEFAULT_MAX_MESSAGE_SIZE_BYTES;
1192    referralHopLimit               = DEFAULT_REFERRAL_HOP_LIMIT;
1193    pooledSchemaTimeoutMillis      = DEFAULT_POOLED_SCHEMA_TIMEOUT_MILLIS;
1194    responseTimeoutMillis          = DEFAULT_RESPONSE_TIMEOUT_MILLIS;
1195    receiveBufferSizeBytes         = DEFAULT_RECEIVE_BUFFER_SIZE_BYTES;
1196    sendBufferSizeBytes            = DEFAULT_SEND_BUFFER_SIZE_BYTES;
1197    disconnectHandler              = null;
1198    referralConnector              = null;
1199    sslSocketVerifier              = DEFAULT_SSL_SOCKET_VERIFIER;
1200    unsolicitedNotificationHandler = null;
1201
1202    responseTimeoutMillisByOperationType =
1203         DEFAULT_RESPONSE_TIMEOUT_MILLIS_BY_OPERATION_TYPE;
1204    responseTimeoutMillisByExtendedOperationType =
1205         DEFAULT_RESPONSE_TIMEOUT_MILLIS_BY_EXTENDED_OPERATION_TYPE;
1206    allowConcurrentSocketFactoryUse =
1207         DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE;
1208  }
1209
1210
1211
1212  /**
1213   * Returns a duplicate of this LDAP connection options object that may be
1214   * modified without impacting this instance.
1215   *
1216   * @return  A duplicate of this LDAP connection options object that may be
1217   *          modified without impacting this instance.
1218   */
1219  public LDAPConnectionOptions duplicate()
1220  {
1221    final LDAPConnectionOptions o = new LDAPConnectionOptions();
1222
1223    o.abandonOnTimeout                = abandonOnTimeout;
1224    o.allowConcurrentSocketFactoryUse = allowConcurrentSocketFactoryUse;
1225    o.autoReconnect                   = autoReconnect;
1226    o.bindWithDNRequiresPassword      = bindWithDNRequiresPassword;
1227    o.captureConnectStackTrace        = captureConnectStackTrace;
1228    o.followReferrals                 = followReferrals;
1229    o.useKeepAlive                    = useKeepAlive;
1230    o.useLinger                       = useLinger;
1231    o.useReuseAddress                 = useReuseAddress;
1232    o.usePooledSchema                 = usePooledSchema;
1233    o.useSchema                       = useSchema;
1234    o.useSynchronousMode              = useSynchronousMode;
1235    o.useTCPNoDelay                   = useTCPNoDelay;
1236    o.connectTimeoutMillis            = connectTimeoutMillis;
1237    o.lingerTimeoutSeconds            = lingerTimeoutSeconds;
1238    o.maxMessageSizeBytes             = maxMessageSizeBytes;
1239    o.pooledSchemaTimeoutMillis       = pooledSchemaTimeoutMillis;
1240    o.responseTimeoutMillis            = responseTimeoutMillis;
1241    o.referralConnector               = referralConnector;
1242    o.referralHopLimit                = referralHopLimit;
1243    o.disconnectHandler               = disconnectHandler;
1244    o.unsolicitedNotificationHandler  = unsolicitedNotificationHandler;
1245    o.receiveBufferSizeBytes          = receiveBufferSizeBytes;
1246    o.sendBufferSizeBytes             = sendBufferSizeBytes;
1247    o.sslSocketVerifier               = sslSocketVerifier;
1248
1249    o.responseTimeoutMillisByOperationType =
1250         responseTimeoutMillisByOperationType;
1251    o.responseTimeoutMillisByExtendedOperationType =
1252         responseTimeoutMillisByExtendedOperationType;
1253
1254    return o;
1255  }
1256
1257
1258
1259  /**
1260   * Indicates whether associated connections should attempt to automatically
1261   * reconnect to the target server if the connection is lost.  Note that this
1262   * option will not have any effect on pooled connections because defunct
1263   * pooled connections will be replaced by newly-created connections rather
1264   * than attempting to re-establish the existing connection.
1265   * <BR><BR>
1266   * NOTE:  The use of auto-reconnect is strongly discouraged because it is
1267   * inherently fragile and can only work under very limited circumstances.  It
1268   * is strongly recommended that a connection pool be used instead of the
1269   * auto-reconnect option, even in cases where only a single connection is
1270   * desired.
1271   *
1272   * @return  {@code true} if associated connections should attempt to
1273   *          automatically reconnect to the target server if the connection is
1274   *          lost, or {@code false} if not.
1275   *
1276   * @deprecated  The use of auto-reconnect is strongly discouraged because it
1277   *              is inherently fragile and can only work under very limited
1278   *              circumstances.  It is strongly recommended that a connection
1279   *              pool be used instead of the auto-reconnect option, even in
1280   *              cases where only a single connection is desired.
1281   */
1282  @Deprecated()
1283  public boolean autoReconnect()
1284  {
1285    return autoReconnect;
1286  }
1287
1288
1289
1290  /**
1291   * Specifies whether associated connections should attempt to automatically
1292   * reconnect to the target server if the connection is lost.  Note that
1293   * automatic reconnection will only be available for authenticated clients if
1294   * the authentication mechanism used provides support for re-binding on a new
1295   * connection.  Also note that this option will not have any effect on pooled
1296   * connections because defunct pooled connections will be replaced by
1297   * newly-created connections rather than attempting to re-establish the
1298   * existing connection.  Further, auto-reconnect should not be used with
1299   * connections that use StartTLS or some other mechanism to alter the state
1300   * of the connection beyond authentication.
1301   * <BR><BR>
1302   * NOTE:  The use of auto-reconnect is strongly discouraged because it is
1303   * inherently fragile and can only work under very limited circumstances.  It
1304   * is strongly recommended that a connection pool be used instead of the
1305   * auto-reconnect option, even in cases where only a single connection is
1306   * desired.
1307   *
1308   * @param  autoReconnect  Specifies whether associated connections should
1309   *                        attempt to automatically reconnect to the target
1310   *                        server if the connection is lost.
1311   *
1312   * @deprecated  The use of auto-reconnect is strongly discouraged because it
1313   *              is inherently fragile and can only work under very limited
1314   *              circumstances.  It is strongly recommended that a connection
1315   *              pool be used instead of the auto-reconnect option, even in
1316   *              cases where only a single connection is desired.
1317   */
1318  @Deprecated()
1319  public void setAutoReconnect(final boolean autoReconnect)
1320  {
1321    this.autoReconnect = autoReconnect;
1322  }
1323
1324
1325
1326  /**
1327   * Indicates whether the SDK should allow simple bind operations that contain
1328   * a bind DN but no password.  Binds of this type may represent a security
1329   * vulnerability in client applications because they may cause the client to
1330   * believe that the user is properly authenticated when the server considers
1331   * it to be an unauthenticated connection.
1332   *
1333   * @return  {@code true} if the SDK should allow simple bind operations that
1334   *          contain a bind DN but no password, or {@code false} if not.
1335   */
1336  public boolean bindWithDNRequiresPassword()
1337  {
1338    return bindWithDNRequiresPassword;
1339  }
1340
1341
1342
1343  /**
1344   * Specifies whether the SDK should allow simple bind operations that contain
1345   * a bind DN but no password.
1346   *
1347   * @param  bindWithDNRequiresPassword  Indicates whether the SDK should allow
1348   *                                     simple bind operations that contain a
1349   *                                     bind DN but no password.
1350   */
1351  public void setBindWithDNRequiresPassword(
1352                   final boolean bindWithDNRequiresPassword)
1353  {
1354    this.bindWithDNRequiresPassword = bindWithDNRequiresPassword;
1355  }
1356
1357
1358
1359  /**
1360   * Indicates whether the LDAP SDK should capture a thread stack trace for each
1361   * attempt made to establish a connection.  If this is enabled, then the
1362   * {@link LDAPConnection#getConnectStackTrace()}  method may be used to
1363   * retrieve the stack trace.
1364   *
1365   * @return  {@code true} if a thread stack trace should be captured whenever a
1366   *          connection is established, or {@code false} if not.
1367   */
1368  public boolean captureConnectStackTrace()
1369  {
1370    return captureConnectStackTrace;
1371  }
1372
1373
1374
1375  /**
1376   * Specifies whether the LDAP SDK should capture a thread stack trace for each
1377   * attempt made to establish a connection.
1378   *
1379   * @param  captureConnectStackTrace  Indicates whether to capture a thread
1380   *                                   stack trace for each attempt made to
1381   *                                   establish a connection.
1382   */
1383  public void setCaptureConnectStackTrace(
1384                   final boolean captureConnectStackTrace)
1385  {
1386    this.captureConnectStackTrace = captureConnectStackTrace;
1387  }
1388
1389
1390
1391  /**
1392   * Retrieves the maximum length of time in milliseconds that a connection
1393   * attempt should be allowed to continue before giving up.
1394   *
1395   * @return  The maximum length of time in milliseconds that a connection
1396   *          attempt should be allowed to continue before giving up, or zero
1397   *          to indicate that there should be no connect timeout.
1398   */
1399  public int getConnectTimeoutMillis()
1400  {
1401    return connectTimeoutMillis;
1402  }
1403
1404
1405
1406  /**
1407   * Specifies the maximum length of time in milliseconds that a connection
1408   * attempt should be allowed to continue before giving up.  A value of zero
1409   * indicates that there should be no connect timeout.
1410   *
1411   * @param  connectTimeoutMillis  The maximum length of time in milliseconds
1412   *                               that a connection attempt should be allowed
1413   *                               to continue before giving up.
1414   */
1415  public void setConnectTimeoutMillis(final int connectTimeoutMillis)
1416  {
1417    this.connectTimeoutMillis = connectTimeoutMillis;
1418  }
1419
1420
1421
1422  /**
1423   * Retrieves the maximum length of time in milliseconds that an operation
1424   * should be allowed to block while waiting for a response from the server.
1425   * This may be overridden on a per-operation type basis, so the
1426   * {@link #getResponseTimeoutMillis(OperationType)} method should be used
1427   * instead of this one.
1428   *
1429   * @return  The maximum length of time in milliseconds that an operation
1430   *          should be allowed to block while waiting for a response from the
1431   *          server, or zero if there should not be any default timeout.
1432   */
1433  public long getResponseTimeoutMillis()
1434  {
1435    return responseTimeoutMillis;
1436  }
1437
1438
1439
1440  /**
1441   * Specifies the maximum length of time in milliseconds that an operation
1442   * should be allowed to block while waiting for a response from the server.  A
1443   * value of zero indicates that there should be no timeout.  Note that this
1444   * will override any per-operation type and per-extended operation type
1445   * timeouts that had previously been set.
1446   *
1447   * @param  responseTimeoutMillis  The maximum length of time in milliseconds
1448   *                                that an operation should be allowed to block
1449   *                                while waiting for a response from the
1450   *                                server.
1451   */
1452  public void setResponseTimeoutMillis(final long responseTimeoutMillis)
1453  {
1454    this.responseTimeoutMillis = Math.max(0L, responseTimeoutMillis);
1455    responseTimeoutMillisByExtendedOperationType = Collections.emptyMap();
1456
1457    final EnumMap<OperationType,Long> newOperationTimeouts =
1458         new EnumMap<>(OperationType.class);
1459    for (final OperationType t : OperationType.values())
1460    {
1461      newOperationTimeouts.put(t, this.responseTimeoutMillis);
1462    }
1463    responseTimeoutMillisByOperationType =
1464         Collections.unmodifiableMap(newOperationTimeouts);
1465  }
1466
1467
1468
1469  /**
1470   * Retrieves the maximum length of time in milliseconds that an operation
1471   * of the specified type should be allowed to block while waiting for a
1472   * response from the server.  Note that for extended operations, the response
1473   * timeout may be overridden on a per-request OID basis, so the
1474   * {@link #getExtendedOperationResponseTimeoutMillis(String)} method should be
1475   * used instead of this one for extended operations.
1476   *
1477   * @param  operationType  The operation type for which to make the
1478   *                        determination.  It must not be {@code null}.
1479   *
1480   * @return  The maximum length of time in milliseconds that an operation of
1481   *          the specified type should be allowed to block while waiting for a
1482   *          response from the server, or zero if there should not be any
1483   *          default timeout.
1484   */
1485  public long getResponseTimeoutMillis(final OperationType operationType)
1486  {
1487    return responseTimeoutMillisByOperationType.get(operationType);
1488  }
1489
1490
1491
1492  /**
1493   * Specifies the maximum length of time in milliseconds that an operation of
1494   * the specified type should be allowed to block while waiting for a response
1495   * from the server.  A value of zero indicates that there should be no
1496   * timeout.
1497   *
1498   * @param  operationType          The operation type for which to set the
1499   *                                response timeout.  It must not be
1500   *                                {@code null}.
1501   * @param  responseTimeoutMillis  The maximum length of time in milliseconds
1502   *                                that an operation should be allowed to block
1503   *                                while waiting for a response from the
1504   *                                server.
1505   */
1506  public void setResponseTimeoutMillis(final OperationType operationType,
1507                                       final long responseTimeoutMillis)
1508  {
1509    final EnumMap<OperationType,Long> newOperationTimeouts =
1510         new EnumMap<>(OperationType.class);
1511    newOperationTimeouts.putAll(responseTimeoutMillisByOperationType);
1512    newOperationTimeouts.put(operationType,
1513         Math.max(0L, responseTimeoutMillis));
1514
1515    responseTimeoutMillisByOperationType = Collections.unmodifiableMap(
1516         newOperationTimeouts);
1517  }
1518
1519
1520
1521  /**
1522   * Retrieves the maximum length of time in milliseconds that an extended
1523   * operation with the specified request OID should be allowed to block while
1524   * waiting for a response from the server.
1525   *
1526   * @param  requestOID  The request OID for the extended operation for which to
1527   *                     make the determination.  It must not be {@code null}.
1528   *
1529   * @return  The maximum length of time in milliseconds that the specified type
1530   *          of extended operation should be allowed to block while waiting for
1531   *          a response from the server, or zero if there should not be any
1532   *          default timeout.
1533   */
1534  public long getExtendedOperationResponseTimeoutMillis(final String requestOID)
1535  {
1536    final Long timeout =
1537         responseTimeoutMillisByExtendedOperationType.get(requestOID);
1538    if (timeout == null)
1539    {
1540      return responseTimeoutMillisByOperationType.get(OperationType.EXTENDED);
1541    }
1542    else
1543    {
1544      return timeout;
1545    }
1546  }
1547
1548
1549
1550  /**
1551   * Specifies the maximum length of time in milliseconds that an extended
1552   * operation with the specified request OID should be allowed to block while
1553   * waiting for a response from the server.  A value of zero indicates that
1554   * there should be no timeout.
1555   *
1556   * @param  requestOID             The request OID for the extended operation
1557   *                                type for which to set the response timeout.
1558   *                                It must not be {@code null}.
1559   * @param  responseTimeoutMillis  The maximum length of time in milliseconds
1560   *                                that an operation should be allowed to block
1561   *                                while waiting for a response from the
1562   *                                server.
1563   */
1564  public void setExtendedOperationResponseTimeoutMillis(final String requestOID,
1565                   final long responseTimeoutMillis)
1566  {
1567    final HashMap<String,Long> newExtOpTimeouts =
1568         new HashMap<>(responseTimeoutMillisByExtendedOperationType);
1569    newExtOpTimeouts.put(requestOID, responseTimeoutMillis);
1570    responseTimeoutMillisByExtendedOperationType =
1571         Collections.unmodifiableMap(newExtOpTimeouts);
1572  }
1573
1574
1575
1576  /**
1577   * Indicates whether the LDAP SDK should attempt to abandon any request for
1578   * which no response is received in the maximum response timeout period.
1579   *
1580   * @return  {@code true} if the LDAP SDK should attempt to abandon any request
1581   *          for which no response is received in the maximum response timeout
1582   *          period, or {@code false} if no abandon attempt should be made in
1583   *          this circumstance.
1584   */
1585  public boolean abandonOnTimeout()
1586  {
1587    return abandonOnTimeout;
1588  }
1589
1590
1591
1592  /**
1593   * Specifies whether the LDAP SDK should attempt to abandon any request for
1594   * which no response is received in the maximum response timeout period.
1595   *
1596   * @param  abandonOnTimeout  Indicates whether the LDAP SDK should attempt to
1597   *                           abandon any request for which no response is
1598   *                           received in the maximum response timeout period.
1599   */
1600  public void setAbandonOnTimeout(final boolean abandonOnTimeout)
1601  {
1602    this.abandonOnTimeout = abandonOnTimeout;
1603  }
1604
1605
1606
1607  /**
1608   * Indicates whether to use the SO_KEEPALIVE option for the underlying sockets
1609   * used by associated connections.
1610   *
1611   * @return  {@code true} if the SO_KEEPALIVE option should be used for the
1612   *          underlying sockets, or {@code false} if not.
1613   */
1614  public boolean useKeepAlive()
1615  {
1616    return useKeepAlive;
1617  }
1618
1619
1620
1621  /**
1622   * Specifies whether to use the SO_KEEPALIVE option for the underlying sockets
1623   * used by associated connections.  Changes to this setting will take effect
1624   * only for new sockets, and not for existing sockets.
1625   *
1626   * @param  useKeepAlive  Indicates whether to use the SO_KEEPALIVE option for
1627   *                       the underlying sockets used by associated
1628   *                       connections.
1629   */
1630  public void setUseKeepAlive(final boolean useKeepAlive)
1631  {
1632    this.useKeepAlive = useKeepAlive;
1633  }
1634
1635
1636
1637  /**
1638   * Indicates whether to use the SO_LINGER option for the underlying sockets
1639   * used by associated connections.
1640   *
1641   * @return  {@code true} if the SO_LINGER option should be used for the
1642   *          underlying sockets, or {@code false} if not.
1643   */
1644  public boolean useLinger()
1645  {
1646    return useLinger;
1647  }
1648
1649
1650
1651  /**
1652   * Retrieves the linger timeout in seconds that will be used if the SO_LINGER
1653   * socket option is enabled.
1654   *
1655   * @return  The linger timeout in seconds that will be used if the SO_LINGER
1656   *          socket option is enabled.
1657   */
1658  public int getLingerTimeoutSeconds()
1659  {
1660    return lingerTimeoutSeconds;
1661  }
1662
1663
1664
1665  /**
1666   * Specifies whether to use the SO_LINGER option for the underlying sockets
1667   * used by associated connections.  Changes to this setting will take effect
1668   * only for new sockets, and not for existing sockets.
1669   *
1670   * @param  useLinger             Indicates whether to use the SO_LINGER option
1671   *                               for the underlying sockets used by associated
1672   *                               connections.
1673   * @param  lingerTimeoutSeconds  The linger timeout in seconds that should be
1674   *                               used if this capability is enabled.
1675   */
1676  public void setUseLinger(final boolean useLinger,
1677                           final int lingerTimeoutSeconds)
1678  {
1679    this.useLinger = useLinger;
1680    this.lingerTimeoutSeconds = lingerTimeoutSeconds;
1681  }
1682
1683
1684
1685  /**
1686   * Indicates whether to use the SO_REUSEADDR option for the underlying sockets
1687   * used by associated connections.
1688   *
1689   * @return  {@code true} if the SO_REUSEADDR option should be used for the
1690   *          underlying sockets, or {@code false} if not.
1691   */
1692  public boolean useReuseAddress()
1693  {
1694    return useReuseAddress;
1695  }
1696
1697
1698
1699  /**
1700   * Specifies whether to use the SO_REUSEADDR option for the underlying sockets
1701   * used by associated connections.  Changes to this setting will take effect
1702   * only for new sockets, and not for existing sockets.
1703   *
1704   * @param  useReuseAddress  Indicates whether to use the SO_REUSEADDR option
1705   *                          for the underlying sockets used by associated
1706   *                          connections.
1707   */
1708  public void setUseReuseAddress(final boolean useReuseAddress)
1709  {
1710    this.useReuseAddress = useReuseAddress;
1711  }
1712
1713
1714
1715  /**
1716   * Indicates whether to try to use schema information when reading data from
1717   * the server (e.g., to select the appropriate matching rules for the
1718   * attributes included in a search result entry).
1719   *
1720   * @return  {@code true} if schema should be used when reading data from the
1721   *          server, or {@code false} if not.
1722   */
1723  public boolean useSchema()
1724  {
1725    return useSchema;
1726  }
1727
1728
1729
1730  /**
1731   * Specifies whether to try to use schema information when reading data from
1732   * the server (e.g., to select the appropriate matching rules for the
1733   * attributes included in a search result entry).
1734   * <BR><BR>
1735   * Note that calling this method with a value of {@code true} will also cause
1736   * the {@code usePooledSchema} setting to be given a value of false, since
1737   * the two values should not both be {@code true} at the same time.
1738   *
1739   * @param  useSchema  Indicates whether to try to use schema information when
1740   *                    reading data from the server.
1741   */
1742  public void setUseSchema(final boolean useSchema)
1743  {
1744    this.useSchema = useSchema;
1745    if (useSchema)
1746    {
1747      usePooledSchema = false;
1748    }
1749  }
1750
1751
1752
1753  /**
1754   * Indicates whether to have connections that are part of a pool try to use
1755   * shared schema information when reading data from the server (e.g., to
1756   * select the appropriate matching rules for the attributes included in a
1757   * search result entry).  If this is {@code true}, then connections in a
1758   * connection pool will share the same cached schema information in a way that
1759   * attempts to reduce network bandwidth and connection establishment time (by
1760   * avoiding the need for each connection to retrieve its own copy of the
1761   * schema).
1762   * <BR><BR>
1763   * If pooled schema is to be used, then it may be configured to expire so that
1764   * the schema may be periodically re-retrieved for new connections to allow
1765   * schema updates to be incorporated.  This behavior is controlled by the
1766   * value returned by the {@link #getPooledSchemaTimeoutMillis} method.
1767   *
1768   * @return  {@code true} if all connections in a connection pool should
1769   *          reference the same schema object, or {@code false} if each
1770   *          connection should retrieve its own copy of the schema.
1771   */
1772  public boolean usePooledSchema()
1773  {
1774    return usePooledSchema;
1775  }
1776
1777
1778
1779  /**
1780   * Indicates whether to have connections that are part of a pool try to use
1781   * shared schema information when reading data from the server (e.g., to
1782   * select the appropriate matching rules for the attributes included in a
1783   * search result entry).
1784   * <BR><BR>
1785   * Note that calling this method with a value of {@code true} will also cause
1786   * the {@code useSchema} setting to be given a value of false, since the two
1787   * values should not both be {@code true} at the same time.
1788   *
1789   * @param  usePooledSchema  Indicates whether all connections in a connection
1790   *                          pool should reference the same schema object
1791   *                          rather than attempting to retrieve their own copy
1792   *                          of the schema.
1793   */
1794  public void setUsePooledSchema(final boolean usePooledSchema)
1795  {
1796    this.usePooledSchema = usePooledSchema;
1797    if (usePooledSchema)
1798    {
1799      useSchema = false;
1800    }
1801  }
1802
1803
1804
1805  /**
1806   * Retrieves the maximum length of time in milliseconds that a pooled schema
1807   * object should be considered fresh.  If the schema referenced by a
1808   * connection pool is at least this old, then the next connection attempt may
1809   * cause a new version of the schema to be retrieved.
1810   * <BR><BR>
1811   * This will only be used if the {@link #usePooledSchema} method returns
1812   * {@code true}.  A value of zero indicates that the pooled schema will never
1813   * expire.
1814   *
1815   * @return  The maximum length of time, in milliseconds, that a pooled schema
1816   *          object should be considered fresh, or zero if pooled schema
1817   *          objects should never expire.
1818   */
1819  public long getPooledSchemaTimeoutMillis()
1820  {
1821    return pooledSchemaTimeoutMillis;
1822  }
1823
1824
1825
1826  /**
1827   * Specifies the maximum length of time in milliseconds that a pooled schema
1828   * object should be considered fresh.
1829   *
1830   * @param  pooledSchemaTimeoutMillis  The maximum length of time in
1831   *                                    milliseconds that a pooled schema object
1832   *                                    should be considered fresh.  A value
1833   *                                    less than or equal to zero will indicate
1834   *                                    that pooled schema should never expire.
1835   */
1836  public void setPooledSchemaTimeoutMillis(final long pooledSchemaTimeoutMillis)
1837  {
1838    this.pooledSchemaTimeoutMillis = Math.max(0L, pooledSchemaTimeoutMillis);
1839  }
1840
1841
1842
1843  /**
1844   * Indicates whether to operate in synchronous mode, in which at most one
1845   * operation may be in progress at any time on a given connection, which may
1846   * allow it to operate more efficiently and without requiring a separate
1847   * reader thread per connection.  The LDAP SDK will not absolutely enforce
1848   * this restriction, but when operating in this mode correct behavior
1849   * cannot be guaranteed when multiple attempts are made to use a connection
1850   * for multiple concurrent operations.
1851   * <BR><BR>
1852   * Note that if synchronous mode is to be used, then this connection option
1853   * must be set on the connection before any attempt is made to establish the
1854   * connection.  Once the connection has been established, then it will
1855   * continue to operate in synchronous or asynchronous mode based on the
1856   * options in place at the time it was connected.
1857   *
1858   * @return  {@code true} if associated connections should operate in
1859   *          synchronous mode, or {@code false} if not.
1860   */
1861  public boolean useSynchronousMode()
1862  {
1863    return useSynchronousMode;
1864  }
1865
1866
1867
1868  /**
1869   * Specifies whether to operate in synchronous mode, in which at most one
1870   * operation may be in progress at any time on a given connection.
1871   * <BR><BR>
1872   * Note that if synchronous mode is to be used, then this connection option
1873   * must be set on the connection before any attempt is made to establish the
1874   * connection.  Once the connection has been established, then it will
1875   * continue to operate in synchronous or asynchronous mode based on the
1876   * options in place at the time it was connected.
1877   *
1878   * @param  useSynchronousMode  Indicates whether to operate in synchronous
1879   *                             mode.
1880   */
1881  public void setUseSynchronousMode(final boolean useSynchronousMode)
1882  {
1883    this.useSynchronousMode = useSynchronousMode;
1884  }
1885
1886
1887
1888  /**
1889   * Indicates whether to use the TCP_NODELAY option for the underlying sockets
1890   * used by associated connections.
1891   *
1892   * @return  {@code true} if the TCP_NODELAY option should be used for the
1893   *          underlying sockets, or {@code false} if not.
1894   */
1895  public boolean useTCPNoDelay()
1896  {
1897    return useTCPNoDelay;
1898  }
1899
1900
1901
1902  /**
1903   * Specifies whether to use the TCP_NODELAY option for the underlying sockets
1904   * used by associated connections.  Changes to this setting will take effect
1905   * only for new sockets, and not for existing sockets.
1906   *
1907   * @param  useTCPNoDelay  Indicates whether to use the TCP_NODELAY option for
1908   *                        the underlying sockets used by associated
1909   *                        connections.
1910   */
1911  public void setUseTCPNoDelay(final boolean useTCPNoDelay)
1912  {
1913    this.useTCPNoDelay = useTCPNoDelay;
1914  }
1915
1916
1917
1918  /**
1919   * Indicates whether associated connections should attempt to follow any
1920   * referrals that they encounter.
1921   *
1922   * @return  {@code true} if associated connections should attempt to follow
1923   *          any referrals that they encounter, or {@code false} if not.
1924   */
1925  public boolean followReferrals()
1926  {
1927    return followReferrals;
1928  }
1929
1930
1931
1932  /**
1933   * Specifies whether associated connections should attempt to follow any
1934   * referrals that they encounter, using the referral connector for the
1935   * associated connection.
1936   *
1937   * @param  followReferrals  Specifies whether associated connections should
1938   *                          attempt to follow any referrals that they
1939   *                          encounter.
1940   */
1941  public void setFollowReferrals(final boolean followReferrals)
1942  {
1943    this.followReferrals = followReferrals;
1944  }
1945
1946
1947
1948  /**
1949   * Retrieves the maximum number of hops that a connection should take when
1950   * trying to follow a referral.
1951   *
1952   * @return  The maximum number of hops that a connection should take when
1953   *          trying to follow a referral.
1954   */
1955  public int getReferralHopLimit()
1956  {
1957    return referralHopLimit;
1958  }
1959
1960
1961
1962  /**
1963   * Specifies the maximum number of hops that a connection should take when
1964   * trying to follow a referral.
1965   *
1966   * @param  referralHopLimit  The maximum number of hops that a connection
1967   *                           should take when trying to follow a referral.  It
1968   *                           must be greater than zero.
1969   */
1970  public void setReferralHopLimit(final int referralHopLimit)
1971  {
1972    Validator.ensureTrue(referralHopLimit > 0,
1973         "LDAPConnectionOptions.referralHopLimit must be greater than 0.");
1974
1975    this.referralHopLimit = referralHopLimit;
1976  }
1977
1978
1979
1980  /**
1981   * Retrieves the referral connector that will be used to establish and
1982   * optionally authenticate connections to servers when attempting to follow
1983   * referrals, if defined.
1984   *
1985   * @return  The referral connector that will be used to establish and
1986   *          optionally authenticate connections to servers when attempting to
1987   *          follow referrals, or {@code null} if no specific referral
1988   *          connector has been configured and referral connections should be
1989   *          created using the same socket factory and bind request as the
1990   *          connection on which the referral was received.
1991   */
1992  public ReferralConnector getReferralConnector()
1993  {
1994    return referralConnector;
1995  }
1996
1997
1998
1999  /**
2000   * Specifies the referral connector that should be used to establish and
2001   * optionally authenticate connections to servers when attempting to follow
2002   * referrals.
2003   *
2004   * @param  referralConnector  The referral connector that will be used to
2005   *                            establish and optionally authenticate
2006   *                            connections to servers when attempting to follow
2007   *                            referrals.  It may be {@code null} to indicate
2008   *                            that the same socket factory and bind request
2009   *                            as the connection on which the referral was
2010   *                            received should be used to establish and
2011   *                            authenticate connections for following
2012   *                            referrals.
2013   */
2014  public void setReferralConnector(final ReferralConnector referralConnector)
2015  {
2016    this.referralConnector = referralConnector;
2017  }
2018
2019
2020
2021  /**
2022   * Retrieves the maximum size in bytes for an LDAP message that a connection
2023   * will attempt to read from the directory server.  If it encounters an LDAP
2024   * message that is larger than this size, then the connection will be
2025   * terminated.
2026   *
2027   * @return  The maximum size in bytes for an LDAP message that a connection
2028   *          will attempt to read from the directory server, or 0 if no limit
2029   *          will be enforced.
2030   */
2031  public int getMaxMessageSize()
2032  {
2033    return maxMessageSizeBytes;
2034  }
2035
2036
2037
2038  /**
2039   * Specifies the maximum size in bytes for an LDAP message that a connection
2040   * will attempt to read from the directory server.  If it encounters an LDAP
2041   * message that is larger than this size, then the connection will be
2042   * terminated.
2043   *
2044   * @param  maxMessageSizeBytes  The maximum size in bytes for an LDAP message
2045   *                              that a connection will attempt to read from
2046   *                              the directory server.  A value less than or
2047   *                              equal to zero indicates that no limit should
2048   *                              be enforced.
2049   */
2050  public void setMaxMessageSize(final int maxMessageSizeBytes)
2051  {
2052    this.maxMessageSizeBytes = Math.max(0, maxMessageSizeBytes);
2053  }
2054
2055
2056
2057  /**
2058   * Retrieves the disconnect handler to use for associated connections.
2059   *
2060   * @return  the disconnect handler to use for associated connections, or
2061   *          {@code null} if none is defined.
2062   */
2063  public DisconnectHandler getDisconnectHandler()
2064  {
2065    return disconnectHandler;
2066  }
2067
2068
2069
2070  /**
2071   * Specifies the disconnect handler to use for associated connections.
2072   *
2073   * @param  handler  The disconnect handler to use for associated connections.
2074   */
2075  public void setDisconnectHandler(final DisconnectHandler handler)
2076  {
2077    disconnectHandler = handler;
2078  }
2079
2080
2081
2082  /**
2083   * Retrieves the unsolicited notification handler to use for associated
2084   * connections.
2085   *
2086   * @return  The unsolicited notification handler to use for associated
2087   *          connections, or {@code null} if none is defined.
2088   */
2089  public UnsolicitedNotificationHandler getUnsolicitedNotificationHandler()
2090  {
2091    return unsolicitedNotificationHandler;
2092  }
2093
2094
2095
2096  /**
2097   * Specifies the unsolicited notification handler to use for associated
2098   * connections.
2099   *
2100   * @param  handler  The unsolicited notification handler to use for associated
2101   *                  connections.
2102   */
2103  public void setUnsolicitedNotificationHandler(
2104                   final UnsolicitedNotificationHandler handler)
2105  {
2106    unsolicitedNotificationHandler = handler;
2107  }
2108
2109
2110
2111  /**
2112   * Retrieves the socket receive buffer size, in bytes, that should be
2113   * requested when establishing a connection.
2114   *
2115   * @return  The socket receive buffer size, in bytes, that should be requested
2116   *          when establishing a connection, or zero if the JVM's default size
2117   *          should be used.
2118   */
2119  public int getReceiveBufferSize()
2120  {
2121    return receiveBufferSizeBytes;
2122  }
2123
2124
2125
2126  /**
2127   * Specifies the socket receive buffer size, in bytes, that should be
2128   * requested when establishing a connection.
2129   *
2130   * @param  receiveBufferSizeBytes  The socket receive buffer size, in bytes,
2131   *                                 that should be requested when establishing
2132   *                                 a connection, or zero if the JVM's default
2133   *                                 size should be used.
2134   */
2135  public void setReceiveBufferSize(final int receiveBufferSizeBytes)
2136  {
2137    this.receiveBufferSizeBytes = Math.max(0, receiveBufferSizeBytes);
2138  }
2139
2140
2141
2142  /**
2143   * Retrieves the socket send buffer size, in bytes, that should be requested
2144   * when establishing a connection.
2145   *
2146   * @return  The socket send buffer size, in bytes, that should be requested
2147   *          when establishing a connection, or zero if the JVM's default size
2148   *          should be used.
2149   */
2150  public int getSendBufferSize()
2151  {
2152    return sendBufferSizeBytes;
2153  }
2154
2155
2156
2157  /**
2158   * Specifies the socket send buffer size, in bytes, that should be requested
2159   * when establishing a connection.
2160   *
2161   * @param  sendBufferSizeBytes  The socket send buffer size, in bytes, that
2162   *                              should be requested when establishing a
2163   *                              connection, or zero if the JVM's default size
2164   *                              should be used.
2165   */
2166  public void setSendBufferSize(final int sendBufferSizeBytes)
2167  {
2168    this.sendBufferSizeBytes = Math.max(0, sendBufferSizeBytes);
2169  }
2170
2171
2172
2173  /**
2174   * Indicates whether to allow a socket factory instance (which may be shared
2175   * across multiple connections) to be used create multiple sockets
2176   * concurrently.  In general, socket factory implementations are threadsafe
2177   * and can be to create multiple connections simultaneously across separate
2178   * threads, but this is known to not be the case in some VM implementations
2179   * (e.g., SSL socket factories in IBM JVMs).  This setting may be used to
2180   * indicate whether concurrent socket creation attempts should be allowed
2181   * (which may allow for better and more consistent performance, especially in
2182   * cases where a connection attempt fails due to a timeout) or prevented
2183   * (which may be necessary for non-threadsafe socket factory implementations).
2184   *
2185   * @return  {@code true} if multiple threads should be able to concurrently
2186   *          use the same socket factory instance, or {@code false} if Java
2187   *          synchronization should be used to ensure that no more than one
2188   *          thread is allowed to use a socket factory at any given time.
2189   */
2190  public boolean allowConcurrentSocketFactoryUse()
2191  {
2192    return allowConcurrentSocketFactoryUse;
2193  }
2194
2195
2196
2197  /**
2198   * Specifies whether to allow a socket factory instance (which may be shared
2199   * across multiple connections) to be used create multiple sockets
2200   * concurrently.  In general, socket factory implementations are threadsafe
2201   * and can be to create multiple connections simultaneously across separate
2202   * threads, but this is known to not be the case in some VM implementations
2203   * (e.g., SSL socket factories in IBM JVMs).  This setting may be used to
2204   * indicate whether concurrent socket creation attempts should be allowed
2205   * (which may allow for better and more consistent performance, especially in
2206   * cases where a connection attempt fails due to a timeout) or prevented
2207   * (which may be necessary for non-threadsafe socket factory implementations).
2208   *
2209   * @param  allowConcurrentSocketFactoryUse  Indicates whether to allow a
2210   *                                          socket factory instance to be used
2211   *                                          to create multiple sockets
2212   *                                          concurrently.
2213   */
2214  public void setAllowConcurrentSocketFactoryUse(
2215                   final boolean allowConcurrentSocketFactoryUse)
2216  {
2217    this.allowConcurrentSocketFactoryUse = allowConcurrentSocketFactoryUse;
2218  }
2219
2220
2221
2222  /**
2223   * Retrieves the {@link SSLSocketVerifier} that will be used to perform
2224   * additional validation for any newly-created {@code SSLSocket} instances.
2225   *
2226   * @return  The {@code SSLSocketVerifier} that will be used to perform
2227   *          additional validation for any newly-created {@code SSLSocket}
2228   *          instances.
2229   */
2230  public SSLSocketVerifier getSSLSocketVerifier()
2231  {
2232    return sslSocketVerifier;
2233  }
2234
2235
2236
2237  /**
2238   * Specifies the {@link SSLSocketVerifier} that will be used to perform
2239   * additional validation for any newly-created {@code SSLSocket} instances.
2240   *
2241   * @param  sslSocketVerifier  The {@code SSLSocketVerifier} that will be used
2242   *                            to perform additional validation for any
2243   *                            newly-created {@code SSLSocket} instances.
2244   */
2245  public void setSSLSocketVerifier(final SSLSocketVerifier sslSocketVerifier)
2246  {
2247    if (sslSocketVerifier == null)
2248    {
2249      this.sslSocketVerifier = DEFAULT_SSL_SOCKET_VERIFIER;
2250    }
2251    else
2252    {
2253      this.sslSocketVerifier = sslSocketVerifier;
2254    }
2255  }
2256
2257
2258
2259  /**
2260   * Retrieves the value of the specified system property as a boolean.
2261   *
2262   * @param  propertyName  The name of the system property whose value should be
2263   *                       retrieved.
2264   * @param  defaultValue  The default value that will be returned if the system
2265   *                       property is not defined or if its value cannot be
2266   *                       parsed as a boolean.
2267   *
2268   * @return  The value of the specified system property as an boolean, or the
2269   *          default value if the system property is not set with a valid
2270   *          value.
2271   */
2272  static boolean getSystemProperty(final String propertyName,
2273                                   final boolean defaultValue)
2274  {
2275    final String propertyValue = System.getProperty(propertyName);
2276    if (propertyValue == null)
2277    {
2278      if (Debug.debugEnabled())
2279      {
2280        Debug.debug(Level.FINE, DebugType.OTHER,
2281             "Using the default value of " + defaultValue + " for system " +
2282                  "property '" + propertyName + "' that is not set.");
2283      }
2284
2285      return defaultValue;
2286    }
2287
2288    if (propertyValue.equalsIgnoreCase("true"))
2289    {
2290      if (Debug.debugEnabled())
2291      {
2292        Debug.debug(Level.INFO, DebugType.OTHER,
2293             "Using value '" + propertyValue + "' set for system property '" +
2294                  propertyName + "'.");
2295      }
2296
2297      return true;
2298    }
2299    else if (propertyValue.equalsIgnoreCase("false"))
2300    {
2301      if (Debug.debugEnabled())
2302      {
2303        Debug.debug(Level.INFO, DebugType.OTHER,
2304             "Using value '" + propertyValue + "' set for system property '" +
2305                  propertyName + "'.");
2306      }
2307
2308      return false;
2309    }
2310    else
2311    {
2312      if (Debug.debugEnabled())
2313      {
2314        Debug.debug(Level.WARNING, DebugType.OTHER,
2315             "Invalid value '" + propertyValue + "' set for system property '" +
2316                  propertyName + "'.  The value was expected to be either " +
2317                  "'true' or 'false'.  The default value of " + defaultValue +
2318                  " will be used instead of the configured value.");
2319      }
2320
2321      return defaultValue;
2322    }
2323  }
2324
2325
2326
2327  /**
2328   * Retrieves the value of the specified system property as an integer.
2329   *
2330   * @param  propertyName  The name of the system property whose value should be
2331   *                       retrieved.
2332   * @param  defaultValue  The default value that will be returned if the system
2333   *                       property is not defined or if its value cannot be
2334   *                       parsed as an integer.
2335   *
2336   * @return  The value of the specified system property as an integer, or the
2337   *          default value if the system property is not set with a valid
2338   *          value.
2339   */
2340  static int getSystemProperty(final String propertyName,
2341                               final int defaultValue)
2342  {
2343    final String propertyValueString = System.getProperty(propertyName);
2344    if (propertyValueString == null)
2345    {
2346      if (Debug.debugEnabled())
2347      {
2348        Debug.debug(Level.FINE, DebugType.OTHER,
2349             "Using the default value of " + defaultValue + " for system " +
2350                  "property '" + propertyName + "' that is not set.");
2351      }
2352
2353      return defaultValue;
2354    }
2355
2356    try
2357    {
2358      final int propertyValueInt = Integer.parseInt(propertyValueString);
2359      if (Debug.debugEnabled())
2360      {
2361        Debug.debug(Level.INFO, DebugType.OTHER,
2362             "Using value " + propertyValueInt + " set for system property '" +
2363                  propertyName + "'.");
2364      }
2365
2366      return propertyValueInt;
2367    }
2368    catch (final Exception e)
2369    {
2370      if (Debug.debugEnabled())
2371      {
2372        Debug.debugException(e);
2373        Debug.debug(Level.WARNING, DebugType.OTHER,
2374             "Invalid value '" + propertyValueString + "' set for system " +
2375                  "property '" + propertyName + "'.  The value was expected " +
2376                  "to be an integer.  The default value of " + defaultValue +
2377                  "will be used instead of the configured value.",
2378             e);
2379      }
2380
2381      return defaultValue;
2382    }
2383  }
2384
2385
2386
2387  /**
2388   * Retrieves the value of the specified system property as a long.
2389   *
2390   * @param  propertyName  The name of the system property whose value should be
2391   *                       retrieved.
2392   * @param  defaultValue  The default value that will be returned if the system
2393   *                       property is not defined or if its value cannot be
2394   *                       parsed as a long.
2395   *
2396   * @return  The value of the specified system property as a long, or the
2397   *          default value if the system property is not set with a valid
2398   *          value.
2399   */
2400  static Long getSystemProperty(final String propertyName,
2401                                final Long defaultValue)
2402  {
2403    final String propertyValueString = System.getProperty(propertyName);
2404    if (propertyValueString == null)
2405    {
2406      if (Debug.debugEnabled())
2407      {
2408        Debug.debug(Level.FINE, DebugType.OTHER,
2409             "Using the default value of " + defaultValue + " for system " +
2410                  "property '" + propertyName + "' that is not set.");
2411      }
2412
2413      return defaultValue;
2414    }
2415
2416    try
2417    {
2418      final long propertyValueLong = Long.parseLong(propertyValueString);
2419      if (Debug.debugEnabled())
2420      {
2421        Debug.debug(Level.INFO, DebugType.OTHER,
2422             "Using value " + propertyValueLong + " set for system property '" +
2423                  propertyName + "'.");
2424      }
2425
2426      return propertyValueLong;
2427    }
2428    catch (final Exception e)
2429    {
2430      if (Debug.debugEnabled())
2431      {
2432        Debug.debugException(e);
2433        Debug.debug(Level.WARNING, DebugType.OTHER,
2434             "Invalid value '" + propertyValueString + "' set for system " +
2435                  "property '" + propertyName + "'.  The value was expected " +
2436                  "to be a long.  The default value of " + defaultValue +
2437                  "will be used instead of the configured value.",
2438             e);
2439      }
2440
2441      return defaultValue;
2442    }
2443  }
2444
2445
2446
2447  /**
2448   * Retrieves a string representation of this LDAP connection.
2449   *
2450   * @return  A string representation of this LDAP connection.
2451   */
2452  @Override()
2453  public String toString()
2454  {
2455    final StringBuilder buffer = new StringBuilder();
2456    toString(buffer);
2457    return buffer.toString();
2458  }
2459
2460
2461
2462  /**
2463   * Appends a string representation of this LDAP connection to the provided
2464   * buffer.
2465   *
2466   * @param  buffer  The buffer to which to append a string representation of
2467   *                 this LDAP connection.
2468   */
2469  public void toString(final StringBuilder buffer)
2470  {
2471    buffer.append("LDAPConnectionOptions(autoReconnect=");
2472    buffer.append(autoReconnect);
2473    buffer.append(", bindWithDNRequiresPassword=");
2474    buffer.append(bindWithDNRequiresPassword);
2475    buffer.append(", followReferrals=");
2476    buffer.append(followReferrals);
2477    if (followReferrals)
2478    {
2479      buffer.append(", referralHopLimit=");
2480      buffer.append(referralHopLimit);
2481    }
2482    if (referralConnector != null)
2483    {
2484      buffer.append(", referralConnectorClass=");
2485      buffer.append(referralConnector.getClass().getName());
2486    }
2487    buffer.append(", useKeepAlive=");
2488    buffer.append(useKeepAlive);
2489    buffer.append(", useLinger=");
2490    if (useLinger)
2491    {
2492      buffer.append("true, lingerTimeoutSeconds=");
2493      buffer.append(lingerTimeoutSeconds);
2494    }
2495    else
2496    {
2497      buffer.append("false");
2498    }
2499    buffer.append(", useReuseAddress=");
2500    buffer.append(useReuseAddress);
2501    buffer.append(", useSchema=");
2502    buffer.append(useSchema);
2503    buffer.append(", usePooledSchema=");
2504    buffer.append(usePooledSchema);
2505    buffer.append(", pooledSchemaTimeoutMillis=");
2506    buffer.append(pooledSchemaTimeoutMillis);
2507    buffer.append(", useSynchronousMode=");
2508    buffer.append(useSynchronousMode);
2509    buffer.append(", useTCPNoDelay=");
2510    buffer.append(useTCPNoDelay);
2511    buffer.append(", captureConnectStackTrace=");
2512    buffer.append(captureConnectStackTrace);
2513    buffer.append(", connectTimeoutMillis=");
2514    buffer.append(connectTimeoutMillis);
2515    buffer.append(", responseTimeoutMillis=");
2516    buffer.append(responseTimeoutMillis);
2517
2518    for (final Map.Entry<OperationType,Long> e :
2519         responseTimeoutMillisByOperationType.entrySet())
2520    {
2521      buffer.append(", responseTimeoutMillis.");
2522      buffer.append(e.getKey().name());
2523      buffer.append('=');
2524      buffer.append(e.getValue());
2525    }
2526
2527    for (final Map.Entry<String,Long> e :
2528         responseTimeoutMillisByExtendedOperationType.entrySet())
2529    {
2530      buffer.append(", responseTimeoutMillis.EXTENDED.");
2531      buffer.append(e.getKey());
2532      buffer.append('=');
2533      buffer.append(e.getValue());
2534    }
2535
2536    buffer.append(", abandonOnTimeout=");
2537    buffer.append(abandonOnTimeout);
2538    buffer.append(", maxMessageSizeBytes=");
2539    buffer.append(maxMessageSizeBytes);
2540    buffer.append(", receiveBufferSizeBytes=");
2541    buffer.append(receiveBufferSizeBytes);
2542    buffer.append(", sendBufferSizeBytes=");
2543    buffer.append(sendBufferSizeBytes);
2544    buffer.append(", allowConcurrentSocketFactoryUse=");
2545    buffer.append(allowConcurrentSocketFactoryUse);
2546    if (disconnectHandler != null)
2547    {
2548      buffer.append(", disconnectHandlerClass=");
2549      buffer.append(disconnectHandler.getClass().getName());
2550    }
2551    if (unsolicitedNotificationHandler != null)
2552    {
2553      buffer.append(", unsolicitedNotificationHandlerClass=");
2554      buffer.append(unsolicitedNotificationHandler.getClass().getName());
2555    }
2556
2557    buffer.append(", sslSocketVerifierClass='");
2558    buffer.append(sslSocketVerifier.getClass().getName());
2559    buffer.append('\'');
2560
2561    buffer.append(')');
2562  }
2563}