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