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 =
930         System.getProperty(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 default value for the setting that controls the default behavior with
1093   * regard to whether to allow concurrent use of a socket factory to create
1094   * client connections.
1095   */
1096  private static final boolean DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE;
1097  static
1098  {
1099    final String vmVendor =
1100         StaticUtils.toLowerCase(System.getProperty("java.vm.vendor"));
1101    DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE = ((vmVendor != null) &&
1102         (vmVendor.contains("sun microsystems") ||
1103          vmVendor.contains("oracle") ||
1104          vmVendor.contains("apple") ||
1105          vmVendor.contains("azul systems")));
1106  }
1107
1108
1109
1110  /**
1111   * The default {@code SSLSocketVerifier} instance that will be used for
1112   * performing extra validation for {@code SSLSocket} instances.
1113   */
1114  private static final SSLSocketVerifier DEFAULT_SSL_SOCKET_VERIFIER =
1115       TrustAllSSLSocketVerifier.getInstance();
1116
1117
1118
1119  // Indicates whether to send an abandon request for any operation for which no
1120  // response is received in the maximum response timeout.
1121  private boolean abandonOnTimeout;
1122
1123  // Indicates whether to use synchronization prevent concurrent use of the
1124  // socket factory instance associated with a connection or set of connections.
1125  private boolean allowConcurrentSocketFactoryUse;
1126
1127  // Indicates whether the connection should attempt to automatically reconnect
1128  // if the connection to the server is lost.
1129  private boolean autoReconnect;
1130
1131  // Indicates whether to allow simple binds that contain a DN but no password.
1132  private boolean bindWithDNRequiresPassword;
1133
1134  // Indicates whether to capture a thread stack trace whenever an attempt is
1135  // made to establish a connection;
1136  private boolean captureConnectStackTrace;
1137
1138  // Indicates whether to attempt to follow any referrals that are encountered.
1139  private boolean followReferrals;
1140
1141  // Indicates whether to use SO_KEEPALIVE for the underlying sockets.
1142  private boolean useKeepAlive;
1143
1144  // Indicates whether to use SO_LINGER for the underlying sockets.
1145  private boolean useLinger;
1146
1147  // Indicates whether to use SO_REUSEADDR for the underlying sockets.
1148  private boolean useReuseAddress;
1149
1150  // Indicates whether all connections in a connection pool should reference
1151  // the same schema.
1152  private boolean usePooledSchema;
1153
1154  // Indicates whether to try to use schema information when reading data from
1155  // the server.
1156  private boolean useSchema;
1157
1158  // Indicates whether to use synchronous mode in which only a single operation
1159  // may be in progress on associated connections at any given time.
1160  private boolean useSynchronousMode;
1161
1162  // Indicates whether to use TCP_NODELAY for the underlying sockets.
1163  private boolean useTCPNoDelay;
1164
1165  // The disconnect handler for associated connections.
1166  private DisconnectHandler disconnectHandler;
1167
1168  // The connect timeout, in milliseconds.
1169  private int connectTimeoutMillis;
1170
1171  // The linger timeout to use if SO_LINGER is to be used.
1172  private int lingerTimeoutSeconds;
1173
1174  // The maximum message size in bytes that will be allowed when reading data
1175  // from a directory server.
1176  private int maxMessageSizeBytes;
1177
1178  // The socket receive buffer size to request.
1179  private int receiveBufferSizeBytes;
1180
1181  // The referral hop limit to use if referral following is enabled.
1182  private int referralHopLimit;
1183
1184  // The socket send buffer size to request.
1185  private int sendBufferSizeBytes;
1186
1187  // The pooled schema timeout, in milliseconds.
1188  private long pooledSchemaTimeoutMillis;
1189
1190  // The response timeout, in milliseconds.
1191  private long responseTimeoutMillis;
1192
1193  private Map<OperationType,Long> responseTimeoutMillisByOperationType;
1194
1195  private Map<String,Long> responseTimeoutMillisByExtendedOperationType;
1196
1197  // The name resolver that will be used to resolve host names to IP addresses.
1198  private NameResolver nameResolver;
1199
1200  // Tne default referral connector that should be used for associated
1201  // connections.
1202  private ReferralConnector referralConnector;
1203
1204  // The SSLSocketVerifier instance to use to perform extra validation on
1205  // newly-established SSLSocket instances.
1206  private SSLSocketVerifier sslSocketVerifier;
1207
1208  // The unsolicited notification handler for associated connections.
1209  private UnsolicitedNotificationHandler unsolicitedNotificationHandler;
1210
1211
1212
1213  /**
1214   * Creates a new set of LDAP connection options with the default settings.
1215   */
1216  public LDAPConnectionOptions()
1217  {
1218    abandonOnTimeout               = DEFAULT_ABANDON_ON_TIMEOUT;
1219    autoReconnect                  = DEFAULT_AUTO_RECONNECT;
1220    bindWithDNRequiresPassword     = DEFAULT_BIND_WITH_DN_REQUIRES_PASSWORD;
1221    captureConnectStackTrace       = DEFAULT_CAPTURE_CONNECT_STACK_TRACE;
1222    followReferrals                = DEFAULT_FOLLOW_REFERRALS;
1223    nameResolver                   = DEFAULT_NAME_RESOLVER;
1224    useKeepAlive                   = DEFAULT_USE_KEEPALIVE;
1225    useLinger                      = DEFAULT_USE_LINGER;
1226    useReuseAddress                = DEFAULT_USE_REUSE_ADDRESS;
1227    usePooledSchema                = DEFAULT_USE_POOLED_SCHEMA;
1228    useSchema                      = DEFAULT_USE_SCHEMA;
1229    useSynchronousMode             = DEFAULT_USE_SYNCHRONOUS_MODE;
1230    useTCPNoDelay                  = DEFAULT_USE_TCP_NODELAY;
1231    connectTimeoutMillis           = DEFAULT_CONNECT_TIMEOUT_MILLIS;
1232    lingerTimeoutSeconds           = DEFAULT_LINGER_TIMEOUT_SECONDS;
1233    maxMessageSizeBytes            = DEFAULT_MAX_MESSAGE_SIZE_BYTES;
1234    referralHopLimit               = DEFAULT_REFERRAL_HOP_LIMIT;
1235    pooledSchemaTimeoutMillis      = DEFAULT_POOLED_SCHEMA_TIMEOUT_MILLIS;
1236    responseTimeoutMillis          = DEFAULT_RESPONSE_TIMEOUT_MILLIS;
1237    receiveBufferSizeBytes         = DEFAULT_RECEIVE_BUFFER_SIZE_BYTES;
1238    sendBufferSizeBytes            = DEFAULT_SEND_BUFFER_SIZE_BYTES;
1239    disconnectHandler              = null;
1240    referralConnector              = null;
1241    sslSocketVerifier              = DEFAULT_SSL_SOCKET_VERIFIER;
1242    unsolicitedNotificationHandler = null;
1243
1244    responseTimeoutMillisByOperationType =
1245         DEFAULT_RESPONSE_TIMEOUT_MILLIS_BY_OPERATION_TYPE;
1246    responseTimeoutMillisByExtendedOperationType =
1247         DEFAULT_RESPONSE_TIMEOUT_MILLIS_BY_EXTENDED_OPERATION_TYPE;
1248    allowConcurrentSocketFactoryUse =
1249         DEFAULT_ALLOW_CONCURRENT_SOCKET_FACTORY_USE;
1250  }
1251
1252
1253
1254  /**
1255   * Returns a duplicate of this LDAP connection options object that may be
1256   * modified without impacting this instance.
1257   *
1258   * @return  A duplicate of this LDAP connection options object that may be
1259   *          modified without impacting this instance.
1260   */
1261  public LDAPConnectionOptions duplicate()
1262  {
1263    final LDAPConnectionOptions o = new LDAPConnectionOptions();
1264
1265    o.abandonOnTimeout                = abandonOnTimeout;
1266    o.allowConcurrentSocketFactoryUse = allowConcurrentSocketFactoryUse;
1267    o.autoReconnect                   = autoReconnect;
1268    o.bindWithDNRequiresPassword      = bindWithDNRequiresPassword;
1269    o.captureConnectStackTrace        = captureConnectStackTrace;
1270    o.followReferrals                 = followReferrals;
1271    o.nameResolver                    = nameResolver;
1272    o.useKeepAlive                    = useKeepAlive;
1273    o.useLinger                       = useLinger;
1274    o.useReuseAddress                 = useReuseAddress;
1275    o.usePooledSchema                 = usePooledSchema;
1276    o.useSchema                       = useSchema;
1277    o.useSynchronousMode              = useSynchronousMode;
1278    o.useTCPNoDelay                   = useTCPNoDelay;
1279    o.connectTimeoutMillis            = connectTimeoutMillis;
1280    o.lingerTimeoutSeconds            = lingerTimeoutSeconds;
1281    o.maxMessageSizeBytes             = maxMessageSizeBytes;
1282    o.pooledSchemaTimeoutMillis       = pooledSchemaTimeoutMillis;
1283    o.responseTimeoutMillis           = responseTimeoutMillis;
1284    o.referralConnector               = referralConnector;
1285    o.referralHopLimit                = referralHopLimit;
1286    o.disconnectHandler               = disconnectHandler;
1287    o.unsolicitedNotificationHandler  = unsolicitedNotificationHandler;
1288    o.receiveBufferSizeBytes          = receiveBufferSizeBytes;
1289    o.sendBufferSizeBytes             = sendBufferSizeBytes;
1290    o.sslSocketVerifier               = sslSocketVerifier;
1291
1292    o.responseTimeoutMillisByOperationType =
1293         responseTimeoutMillisByOperationType;
1294    o.responseTimeoutMillisByExtendedOperationType =
1295         responseTimeoutMillisByExtendedOperationType;
1296
1297    return o;
1298  }
1299
1300
1301
1302  /**
1303   * Indicates whether associated connections should attempt to automatically
1304   * reconnect to the target server if the connection is lost.  Note that this
1305   * option will not have any effect on pooled connections because defunct
1306   * pooled connections will be replaced by newly-created connections rather
1307   * than attempting to re-establish the existing connection.
1308   * <BR><BR>
1309   * NOTE:  The use of auto-reconnect is strongly discouraged because it is
1310   * inherently fragile and can only work under very limited circumstances.  It
1311   * is strongly recommended that a connection pool be used instead of the
1312   * auto-reconnect option, even in cases where only a single connection is
1313   * desired.
1314   *
1315   * @return  {@code true} if associated connections should attempt to
1316   *          automatically reconnect to the target server if the connection is
1317   *          lost, or {@code false} if not.
1318   *
1319   * @deprecated  The use of auto-reconnect is strongly discouraged because it
1320   *              is inherently fragile and can only work under very limited
1321   *              circumstances.  It is strongly recommended that a connection
1322   *              pool be used instead of the auto-reconnect option, even in
1323   *              cases where only a single connection is desired.
1324   */
1325  @Deprecated()
1326  public boolean autoReconnect()
1327  {
1328    return autoReconnect;
1329  }
1330
1331
1332
1333  /**
1334   * Specifies whether associated connections should attempt to automatically
1335   * reconnect to the target server if the connection is lost.  Note that
1336   * automatic reconnection will only be available for authenticated clients if
1337   * the authentication mechanism used provides support for re-binding on a new
1338   * connection.  Also note that this option will not have any effect on pooled
1339   * connections because defunct pooled connections will be replaced by
1340   * newly-created connections rather than attempting to re-establish the
1341   * existing connection.  Further, auto-reconnect should not be used with
1342   * connections that use StartTLS or some other mechanism to alter the state
1343   * of the connection beyond authentication.
1344   * <BR><BR>
1345   * NOTE:  The use of auto-reconnect is strongly discouraged because it is
1346   * inherently fragile and can only work under very limited circumstances.  It
1347   * is strongly recommended that a connection pool be used instead of the
1348   * auto-reconnect option, even in cases where only a single connection is
1349   * desired.
1350   *
1351   * @param  autoReconnect  Specifies whether associated connections should
1352   *                        attempt to automatically reconnect to the target
1353   *                        server if the connection is lost.
1354   *
1355   * @deprecated  The use of auto-reconnect is strongly discouraged because it
1356   *              is inherently fragile and can only work under very limited
1357   *              circumstances.  It is strongly recommended that a connection
1358   *              pool be used instead of the auto-reconnect option, even in
1359   *              cases where only a single connection is desired.
1360   */
1361  @Deprecated()
1362  public void setAutoReconnect(final boolean autoReconnect)
1363  {
1364    this.autoReconnect = autoReconnect;
1365  }
1366
1367
1368
1369  /**
1370   * Retrieves the name resolver that should be used to resolve host names to IP
1371   * addresses.
1372   *
1373   * @return  The name resolver that should be used to resolve host names to IP
1374   *          addresses.
1375   */
1376  public NameResolver getNameResolver()
1377  {
1378    return nameResolver;
1379  }
1380
1381
1382
1383  /**
1384   * Sets the name resolver that should be used to resolve host names to IP
1385   * addresses.
1386   *
1387   * @param  nameResolver  The name resolver that should be used to resolve host
1388   *                       names to IP addresses.
1389   */
1390  public void setNameResolver(final NameResolver nameResolver)
1391  {
1392    if (nameResolver == null)
1393    {
1394      this.nameResolver = DEFAULT_NAME_RESOLVER;
1395    }
1396    else
1397    {
1398      this.nameResolver = nameResolver;
1399    }
1400  }
1401
1402
1403
1404  /**
1405   * Indicates whether the SDK should allow simple bind operations that contain
1406   * a bind DN but no password.  Binds of this type may represent a security
1407   * vulnerability in client applications because they may cause the client to
1408   * believe that the user is properly authenticated when the server considers
1409   * it to be an unauthenticated connection.
1410   *
1411   * @return  {@code true} if the SDK should allow simple bind operations that
1412   *          contain a bind DN but no password, or {@code false} if not.
1413   */
1414  public boolean bindWithDNRequiresPassword()
1415  {
1416    return bindWithDNRequiresPassword;
1417  }
1418
1419
1420
1421  /**
1422   * Specifies whether the SDK should allow simple bind operations that contain
1423   * a bind DN but no password.
1424   *
1425   * @param  bindWithDNRequiresPassword  Indicates whether the SDK should allow
1426   *                                     simple bind operations that contain a
1427   *                                     bind DN but no password.
1428   */
1429  public void setBindWithDNRequiresPassword(
1430                   final boolean bindWithDNRequiresPassword)
1431  {
1432    this.bindWithDNRequiresPassword = bindWithDNRequiresPassword;
1433  }
1434
1435
1436
1437  /**
1438   * Indicates whether the LDAP SDK should capture a thread stack trace for each
1439   * attempt made to establish a connection.  If this is enabled, then the
1440   * {@link LDAPConnection#getConnectStackTrace()}  method may be used to
1441   * retrieve the stack trace.
1442   *
1443   * @return  {@code true} if a thread stack trace should be captured whenever a
1444   *          connection is established, or {@code false} if not.
1445   */
1446  public boolean captureConnectStackTrace()
1447  {
1448    return captureConnectStackTrace;
1449  }
1450
1451
1452
1453  /**
1454   * Specifies whether the LDAP SDK should capture a thread stack trace for each
1455   * attempt made to establish a connection.
1456   *
1457   * @param  captureConnectStackTrace  Indicates whether to capture a thread
1458   *                                   stack trace for each attempt made to
1459   *                                   establish a connection.
1460   */
1461  public void setCaptureConnectStackTrace(
1462                   final boolean captureConnectStackTrace)
1463  {
1464    this.captureConnectStackTrace = captureConnectStackTrace;
1465  }
1466
1467
1468
1469  /**
1470   * Retrieves the maximum length of time in milliseconds that a connection
1471   * attempt should be allowed to continue before giving up.
1472   *
1473   * @return  The maximum length of time in milliseconds that a connection
1474   *          attempt should be allowed to continue before giving up, or zero
1475   *          to indicate that there should be no connect timeout.
1476   */
1477  public int getConnectTimeoutMillis()
1478  {
1479    return connectTimeoutMillis;
1480  }
1481
1482
1483
1484  /**
1485   * Specifies the maximum length of time in milliseconds that a connection
1486   * attempt should be allowed to continue before giving up.  A value of zero
1487   * indicates that there should be no connect timeout.
1488   *
1489   * @param  connectTimeoutMillis  The maximum length of time in milliseconds
1490   *                               that a connection attempt should be allowed
1491   *                               to continue before giving up.
1492   */
1493  public void setConnectTimeoutMillis(final int connectTimeoutMillis)
1494  {
1495    this.connectTimeoutMillis = connectTimeoutMillis;
1496  }
1497
1498
1499
1500  /**
1501   * Retrieves the maximum length of time in milliseconds that an operation
1502   * should be allowed to block while waiting for a response from the server.
1503   * This may be overridden on a per-operation type basis, so the
1504   * {@link #getResponseTimeoutMillis(OperationType)} method should be used
1505   * instead of this one.
1506   *
1507   * @return  The maximum length of time in milliseconds that an operation
1508   *          should be allowed to block while waiting for a response from the
1509   *          server, or zero if there should not be any default timeout.
1510   */
1511  public long getResponseTimeoutMillis()
1512  {
1513    return responseTimeoutMillis;
1514  }
1515
1516
1517
1518  /**
1519   * Specifies the maximum length of time in milliseconds that an operation
1520   * should be allowed to block while waiting for a response from the server.  A
1521   * value of zero indicates that there should be no timeout.  Note that this
1522   * will override any per-operation type and per-extended operation type
1523   * timeouts that had previously been set.
1524   *
1525   * @param  responseTimeoutMillis  The maximum length of time in milliseconds
1526   *                                that an operation should be allowed to block
1527   *                                while waiting for a response from the
1528   *                                server.
1529   */
1530  public void setResponseTimeoutMillis(final long responseTimeoutMillis)
1531  {
1532    this.responseTimeoutMillis = Math.max(0L, responseTimeoutMillis);
1533    responseTimeoutMillisByExtendedOperationType = Collections.emptyMap();
1534
1535    final EnumMap<OperationType,Long> newOperationTimeouts =
1536         new EnumMap<>(OperationType.class);
1537    for (final OperationType t : OperationType.values())
1538    {
1539      newOperationTimeouts.put(t, this.responseTimeoutMillis);
1540    }
1541    responseTimeoutMillisByOperationType =
1542         Collections.unmodifiableMap(newOperationTimeouts);
1543  }
1544
1545
1546
1547  /**
1548   * Retrieves the maximum length of time in milliseconds that an operation
1549   * of the specified type should be allowed to block while waiting for a
1550   * response from the server.  Note that for extended operations, the response
1551   * timeout may be overridden on a per-request OID basis, so the
1552   * {@link #getExtendedOperationResponseTimeoutMillis(String)} method should be
1553   * used instead of this one for extended operations.
1554   *
1555   * @param  operationType  The operation type for which to make the
1556   *                        determination.  It must not be {@code null}.
1557   *
1558   * @return  The maximum length of time in milliseconds that an operation of
1559   *          the specified type should be allowed to block while waiting for a
1560   *          response from the server, or zero if there should not be any
1561   *          default timeout.
1562   */
1563  public long getResponseTimeoutMillis(final OperationType operationType)
1564  {
1565    return responseTimeoutMillisByOperationType.get(operationType);
1566  }
1567
1568
1569
1570  /**
1571   * Specifies the maximum length of time in milliseconds that an operation of
1572   * the specified type should be allowed to block while waiting for a response
1573   * from the server.  A value of zero indicates that there should be no
1574   * timeout.
1575   *
1576   * @param  operationType          The operation type for which to set the
1577   *                                response timeout.  It must not be
1578   *                                {@code null}.
1579   * @param  responseTimeoutMillis  The maximum length of time in milliseconds
1580   *                                that an operation should be allowed to block
1581   *                                while waiting for a response from the
1582   *                                server.
1583   */
1584  public void setResponseTimeoutMillis(final OperationType operationType,
1585                                       final long responseTimeoutMillis)
1586  {
1587    final EnumMap<OperationType,Long> newOperationTimeouts =
1588         new EnumMap<>(OperationType.class);
1589    newOperationTimeouts.putAll(responseTimeoutMillisByOperationType);
1590    newOperationTimeouts.put(operationType,
1591         Math.max(0L, responseTimeoutMillis));
1592
1593    responseTimeoutMillisByOperationType = Collections.unmodifiableMap(
1594         newOperationTimeouts);
1595  }
1596
1597
1598
1599  /**
1600   * Retrieves the maximum length of time in milliseconds that an extended
1601   * operation with the specified request OID should be allowed to block while
1602   * waiting for a response from the server.
1603   *
1604   * @param  requestOID  The request OID for the extended operation for which to
1605   *                     make the determination.  It must not be {@code null}.
1606   *
1607   * @return  The maximum length of time in milliseconds that the specified type
1608   *          of extended operation should be allowed to block while waiting for
1609   *          a response from the server, or zero if there should not be any
1610   *          default timeout.
1611   */
1612  public long getExtendedOperationResponseTimeoutMillis(final String requestOID)
1613  {
1614    final Long timeout =
1615         responseTimeoutMillisByExtendedOperationType.get(requestOID);
1616    if (timeout == null)
1617    {
1618      return responseTimeoutMillisByOperationType.get(OperationType.EXTENDED);
1619    }
1620    else
1621    {
1622      return timeout;
1623    }
1624  }
1625
1626
1627
1628  /**
1629   * Specifies the maximum length of time in milliseconds that an extended
1630   * operation with the specified request OID should be allowed to block while
1631   * waiting for a response from the server.  A value of zero indicates that
1632   * there should be no timeout.
1633   *
1634   * @param  requestOID             The request OID for the extended operation
1635   *                                type for which to set the response timeout.
1636   *                                It must not be {@code null}.
1637   * @param  responseTimeoutMillis  The maximum length of time in milliseconds
1638   *                                that an operation should be allowed to block
1639   *                                while waiting for a response from the
1640   *                                server.
1641   */
1642  public void setExtendedOperationResponseTimeoutMillis(final String requestOID,
1643                   final long responseTimeoutMillis)
1644  {
1645    final HashMap<String,Long> newExtOpTimeouts =
1646         new HashMap<>(responseTimeoutMillisByExtendedOperationType);
1647    newExtOpTimeouts.put(requestOID, responseTimeoutMillis);
1648    responseTimeoutMillisByExtendedOperationType =
1649         Collections.unmodifiableMap(newExtOpTimeouts);
1650  }
1651
1652
1653
1654  /**
1655   * Indicates whether the LDAP SDK should attempt to abandon any request for
1656   * which no response is received in the maximum response timeout period.
1657   *
1658   * @return  {@code true} if the LDAP SDK should attempt to abandon any request
1659   *          for which no response is received in the maximum response timeout
1660   *          period, or {@code false} if no abandon attempt should be made in
1661   *          this circumstance.
1662   */
1663  public boolean abandonOnTimeout()
1664  {
1665    return abandonOnTimeout;
1666  }
1667
1668
1669
1670  /**
1671   * Specifies whether the LDAP SDK should attempt to abandon any request for
1672   * which no response is received in the maximum response timeout period.
1673   *
1674   * @param  abandonOnTimeout  Indicates whether the LDAP SDK should attempt to
1675   *                           abandon any request for which no response is
1676   *                           received in the maximum response timeout period.
1677   */
1678  public void setAbandonOnTimeout(final boolean abandonOnTimeout)
1679  {
1680    this.abandonOnTimeout = abandonOnTimeout;
1681  }
1682
1683
1684
1685  /**
1686   * Indicates whether to use the SO_KEEPALIVE option for the underlying sockets
1687   * used by associated connections.
1688   *
1689   * @return  {@code true} if the SO_KEEPALIVE option should be used for the
1690   *          underlying sockets, or {@code false} if not.
1691   */
1692  public boolean useKeepAlive()
1693  {
1694    return useKeepAlive;
1695  }
1696
1697
1698
1699  /**
1700   * Specifies whether to use the SO_KEEPALIVE option for the underlying sockets
1701   * used by associated connections.  Changes to this setting will take effect
1702   * only for new sockets, and not for existing sockets.
1703   *
1704   * @param  useKeepAlive  Indicates whether to use the SO_KEEPALIVE option for
1705   *                       the underlying sockets used by associated
1706   *                       connections.
1707   */
1708  public void setUseKeepAlive(final boolean useKeepAlive)
1709  {
1710    this.useKeepAlive = useKeepAlive;
1711  }
1712
1713
1714
1715  /**
1716   * Indicates whether to use the SO_LINGER option for the underlying sockets
1717   * used by associated connections.
1718   *
1719   * @return  {@code true} if the SO_LINGER option should be used for the
1720   *          underlying sockets, or {@code false} if not.
1721   */
1722  public boolean useLinger()
1723  {
1724    return useLinger;
1725  }
1726
1727
1728
1729  /**
1730   * Retrieves the linger timeout in seconds that will be used if the SO_LINGER
1731   * socket option is enabled.
1732   *
1733   * @return  The linger timeout in seconds that will be used if the SO_LINGER
1734   *          socket option is enabled.
1735   */
1736  public int getLingerTimeoutSeconds()
1737  {
1738    return lingerTimeoutSeconds;
1739  }
1740
1741
1742
1743  /**
1744   * Specifies whether to use the SO_LINGER option for the underlying sockets
1745   * used by associated connections.  Changes to this setting will take effect
1746   * only for new sockets, and not for existing sockets.
1747   *
1748   * @param  useLinger             Indicates whether to use the SO_LINGER option
1749   *                               for the underlying sockets used by associated
1750   *                               connections.
1751   * @param  lingerTimeoutSeconds  The linger timeout in seconds that should be
1752   *                               used if this capability is enabled.
1753   */
1754  public void setUseLinger(final boolean useLinger,
1755                           final int lingerTimeoutSeconds)
1756  {
1757    this.useLinger = useLinger;
1758    this.lingerTimeoutSeconds = lingerTimeoutSeconds;
1759  }
1760
1761
1762
1763  /**
1764   * Indicates whether to use the SO_REUSEADDR option for the underlying sockets
1765   * used by associated connections.
1766   *
1767   * @return  {@code true} if the SO_REUSEADDR option should be used for the
1768   *          underlying sockets, or {@code false} if not.
1769   */
1770  public boolean useReuseAddress()
1771  {
1772    return useReuseAddress;
1773  }
1774
1775
1776
1777  /**
1778   * Specifies whether to use the SO_REUSEADDR option for the underlying sockets
1779   * used by associated connections.  Changes to this setting will take effect
1780   * only for new sockets, and not for existing sockets.
1781   *
1782   * @param  useReuseAddress  Indicates whether to use the SO_REUSEADDR option
1783   *                          for the underlying sockets used by associated
1784   *                          connections.
1785   */
1786  public void setUseReuseAddress(final boolean useReuseAddress)
1787  {
1788    this.useReuseAddress = useReuseAddress;
1789  }
1790
1791
1792
1793  /**
1794   * Indicates whether to try to use schema information when reading data from
1795   * the server (e.g., to select the appropriate matching rules for the
1796   * attributes included in a search result entry).
1797   * <BR><BR>
1798   * If the LDAP SDK is configured to make use of schema, then it may be able
1799   * to more accurately perform client-side matching, including methods like
1800   * {@link Filter#matchesEntry(Entry)} or {@link Attribute#hasValue(String)}.
1801   * If both {@code useSchema} and {@code useSPooledSchema} are {@code false},
1802   * then all client-side matching for attribute values will treat them as
1803   * directory string values with a caseIgnoreMatch equality matching rule.  If
1804   * either {@code useSchema} or {@code usePooledSchema} is {@code true}, then
1805   * the LDAP SDK may be able to use the attribute type definitions from that
1806   * schema to determine the appropriate syntax and matching rules to use for
1807   * client-side matching operations involving those attributes.  Any attribute
1808   * types that are not defined in the schema will still be treated as
1809   * case-insensitive directory string values.
1810   *
1811   * @return  {@code true} if schema should be used when reading data from the
1812   *          server, or {@code false} if not.
1813   */
1814  public boolean useSchema()
1815  {
1816    return useSchema;
1817  }
1818
1819
1820
1821  /**
1822   * Specifies whether to try to use schema information when reading data from
1823   * the server (e.g., to select the appropriate matching rules for the
1824   * attributes included in a search result entry).
1825   * <BR><BR>
1826   * If the LDAP SDK is configured to make use of schema, then it may be able
1827   * to more accurately perform client-side matching, including methods like
1828   * {@link Filter#matchesEntry(Entry)} or {@link Attribute#hasValue(String)}.
1829   * If both {@code useSchema} and {@code useSPooledSchema} are {@code false},
1830   * then all client-side matching for attribute values will treat them as
1831   * directory string values with a caseIgnoreMatch equality matching rule.  If
1832   * either {@code useSchema} or {@code usePooledSchema} is {@code true}, then
1833   * the LDAP SDK may be able to use the attribute type definitions from that
1834   * schema to determine the appropriate syntax and matching rules to use for
1835   * client-side matching operations involving those attributes.  Any attribute
1836   * types that are not defined in the schema will still be treated as
1837   * case-insensitive directory string values.
1838   * <BR><BR>
1839   * Note that calling this method with a value of {@code true} will also cause
1840   * the {@code usePooledSchema} setting to be given a value of false, since
1841   * the two values should not both be {@code true} at the same time.
1842   *
1843   * @param  useSchema  Indicates whether to try to use schema information when
1844   *                    reading data from the server.
1845   */
1846  public void setUseSchema(final boolean useSchema)
1847  {
1848    this.useSchema = useSchema;
1849    if (useSchema)
1850    {
1851      usePooledSchema = false;
1852    }
1853  }
1854
1855
1856
1857  /**
1858   * Indicates whether to have connections that are part of a pool try to use
1859   * shared schema information when reading data from the server (e.g., to
1860   * select the appropriate matching rules for the attributes included in a
1861   * search result entry).  If this is {@code true}, then connections in a
1862   * connection pool will share the same cached schema information in a way that
1863   * attempts to reduce network bandwidth and connection establishment time (by
1864   * avoiding the need for each connection to retrieve its own copy of the
1865   * schema).
1866   * <BR><BR>
1867   * If the LDAP SDK is configured to make use of schema, then it may be able
1868   * to more accurately perform client-side matching, including methods like
1869   * {@link Filter#matchesEntry(Entry)} or {@link Attribute#hasValue(String)}.
1870   * If both {@code useSchema} and {@code useSPooledSchema} are {@code false},
1871   * then all client-side matching for attribute values will treat them as
1872   * directory string values with a caseIgnoreMatch equality matching rule.  If
1873   * either {@code useSchema} or {@code usePooledSchema} is {@code true}, then
1874   * the LDAP SDK may be able to use the attribute type definitions from that
1875   * schema to determine the appropriate syntax and matching rules to use for
1876   * client-side matching operations involving those attributes.  Any attribute
1877   * types that are not defined in the schema will still be treated as
1878   * case-insensitive directory string values.
1879   * <BR><BR>
1880   * If pooled schema is to be used, then it may be configured to expire so that
1881   * the schema may be periodically re-retrieved for new connections to allow
1882   * schema updates to be incorporated.  This behavior is controlled by the
1883   * value returned by the {@link #getPooledSchemaTimeoutMillis} method.
1884   *
1885   * @return  {@code true} if all connections in a connection pool should
1886   *          reference the same schema object, or {@code false} if each
1887   *          connection should retrieve its own copy of the schema.
1888   */
1889  public boolean usePooledSchema()
1890  {
1891    return usePooledSchema;
1892  }
1893
1894
1895
1896  /**
1897   * Indicates whether to have connections that are part of a pool try to use
1898   * shared schema information when reading data from the server (e.g., to
1899   * select the appropriate matching rules for the attributes included in a
1900   * search result entry).
1901   * <BR><BR>
1902   * If the LDAP SDK is configured to make use of schema, then it may be able
1903   * to more accurately perform client-side matching, including methods like
1904   * {@link Filter#matchesEntry(Entry)} or {@link Attribute#hasValue(String)}.
1905   * If both {@code useSchema} and {@code useSPooledSchema} are {@code false},
1906   * then all client-side matching for attribute values will treat them as
1907   * directory string values with a caseIgnoreMatch equality matching rule.  If
1908   * either {@code useSchema} or {@code usePooledSchema} is {@code true}, then
1909   * the LDAP SDK may be able to use the attribute type definitions from that
1910   * schema to determine the appropriate syntax and matching rules to use for
1911   * client-side matching operations involving those attributes.  Any attribute
1912   * types that are not defined in the schema will still be treated as
1913   * case-insensitive directory string values.
1914   * <BR><BR>
1915   * Note that calling this method with a value of {@code true} will also cause
1916   * the {@code useSchema} setting to be given a value of false, since the two
1917   * values should not both be {@code true} at the same time.
1918   *
1919   * @param  usePooledSchema  Indicates whether all connections in a connection
1920   *                          pool should reference the same schema object
1921   *                          rather than attempting to retrieve their own copy
1922   *                          of the schema.
1923   */
1924  public void setUsePooledSchema(final boolean usePooledSchema)
1925  {
1926    this.usePooledSchema = usePooledSchema;
1927    if (usePooledSchema)
1928    {
1929      useSchema = false;
1930    }
1931  }
1932
1933
1934
1935  /**
1936   * Retrieves the maximum length of time in milliseconds that a pooled schema
1937   * object should be considered fresh.  If the schema referenced by a
1938   * connection pool is at least this old, then the next connection attempt may
1939   * cause a new version of the schema to be retrieved.
1940   * <BR><BR>
1941   * This will only be used if the {@link #usePooledSchema} method returns
1942   * {@code true}.  A value of zero indicates that the pooled schema will never
1943   * expire.
1944   *
1945   * @return  The maximum length of time, in milliseconds, that a pooled schema
1946   *          object should be considered fresh, or zero if pooled schema
1947   *          objects should never expire.
1948   */
1949  public long getPooledSchemaTimeoutMillis()
1950  {
1951    return pooledSchemaTimeoutMillis;
1952  }
1953
1954
1955
1956  /**
1957   * Specifies the maximum length of time in milliseconds that a pooled schema
1958   * object should be considered fresh.
1959   *
1960   * @param  pooledSchemaTimeoutMillis  The maximum length of time in
1961   *                                    milliseconds that a pooled schema object
1962   *                                    should be considered fresh.  A value
1963   *                                    less than or equal to zero will indicate
1964   *                                    that pooled schema should never expire.
1965   */
1966  public void setPooledSchemaTimeoutMillis(final long pooledSchemaTimeoutMillis)
1967  {
1968    this.pooledSchemaTimeoutMillis = Math.max(0L, pooledSchemaTimeoutMillis);
1969  }
1970
1971
1972
1973  /**
1974   * Indicates whether to operate in synchronous mode, in which at most one
1975   * operation may be in progress at any time on a given connection, which may
1976   * allow it to operate more efficiently and without requiring a separate
1977   * reader thread per connection.  The LDAP SDK will not absolutely enforce
1978   * this restriction, but when operating in this mode correct behavior
1979   * cannot be guaranteed when multiple attempts are made to use a connection
1980   * for multiple concurrent operations.
1981   * <BR><BR>
1982   * Note that if synchronous mode is to be used, then this connection option
1983   * must be set on the connection before any attempt is made to establish the
1984   * connection.  Once the connection has been established, then it will
1985   * continue to operate in synchronous or asynchronous mode based on the
1986   * options in place at the time it was connected.
1987   *
1988   * @return  {@code true} if associated connections should operate in
1989   *          synchronous mode, or {@code false} if not.
1990   */
1991  public boolean useSynchronousMode()
1992  {
1993    return useSynchronousMode;
1994  }
1995
1996
1997
1998  /**
1999   * Specifies whether to operate in synchronous mode, in which at most one
2000   * operation may be in progress at any time on a given connection.
2001   * <BR><BR>
2002   * Note that if synchronous mode is to be used, then this connection option
2003   * must be set on the connection before any attempt is made to establish the
2004   * connection.  Once the connection has been established, then it will
2005   * continue to operate in synchronous or asynchronous mode based on the
2006   * options in place at the time it was connected.
2007   *
2008   * @param  useSynchronousMode  Indicates whether to operate in synchronous
2009   *                             mode.
2010   */
2011  public void setUseSynchronousMode(final boolean useSynchronousMode)
2012  {
2013    this.useSynchronousMode = useSynchronousMode;
2014  }
2015
2016
2017
2018  /**
2019   * Indicates whether to use the TCP_NODELAY option for the underlying sockets
2020   * used by associated connections.
2021   *
2022   * @return  {@code true} if the TCP_NODELAY option should be used for the
2023   *          underlying sockets, or {@code false} if not.
2024   */
2025  public boolean useTCPNoDelay()
2026  {
2027    return useTCPNoDelay;
2028  }
2029
2030
2031
2032  /**
2033   * Specifies whether to use the TCP_NODELAY option for the underlying sockets
2034   * used by associated connections.  Changes to this setting will take effect
2035   * only for new sockets, and not for existing sockets.
2036   *
2037   * @param  useTCPNoDelay  Indicates whether to use the TCP_NODELAY option for
2038   *                        the underlying sockets used by associated
2039   *                        connections.
2040   */
2041  public void setUseTCPNoDelay(final boolean useTCPNoDelay)
2042  {
2043    this.useTCPNoDelay = useTCPNoDelay;
2044  }
2045
2046
2047
2048  /**
2049   * Indicates whether associated connections should attempt to follow any
2050   * referrals that they encounter.
2051   *
2052   * @return  {@code true} if associated connections should attempt to follow
2053   *          any referrals that they encounter, or {@code false} if not.
2054   */
2055  public boolean followReferrals()
2056  {
2057    return followReferrals;
2058  }
2059
2060
2061
2062  /**
2063   * Specifies whether associated connections should attempt to follow any
2064   * referrals that they encounter, using the referral connector for the
2065   * associated connection.
2066   *
2067   * @param  followReferrals  Specifies whether associated connections should
2068   *                          attempt to follow any referrals that they
2069   *                          encounter.
2070   */
2071  public void setFollowReferrals(final boolean followReferrals)
2072  {
2073    this.followReferrals = followReferrals;
2074  }
2075
2076
2077
2078  /**
2079   * Retrieves the maximum number of hops that a connection should take when
2080   * trying to follow a referral.
2081   *
2082   * @return  The maximum number of hops that a connection should take when
2083   *          trying to follow a referral.
2084   */
2085  public int getReferralHopLimit()
2086  {
2087    return referralHopLimit;
2088  }
2089
2090
2091
2092  /**
2093   * Specifies the maximum number of hops that a connection should take when
2094   * trying to follow a referral.
2095   *
2096   * @param  referralHopLimit  The maximum number of hops that a connection
2097   *                           should take when trying to follow a referral.  It
2098   *                           must be greater than zero.
2099   */
2100  public void setReferralHopLimit(final int referralHopLimit)
2101  {
2102    Validator.ensureTrue(referralHopLimit > 0,
2103         "LDAPConnectionOptions.referralHopLimit must be greater than 0.");
2104
2105    this.referralHopLimit = referralHopLimit;
2106  }
2107
2108
2109
2110  /**
2111   * Retrieves the referral connector that will be used to establish and
2112   * optionally authenticate connections to servers when attempting to follow
2113   * referrals, if defined.
2114   *
2115   * @return  The referral connector that will be used to establish and
2116   *          optionally authenticate connections to servers when attempting to
2117   *          follow referrals, or {@code null} if no specific referral
2118   *          connector has been configured and referral connections should be
2119   *          created using the same socket factory and bind request as the
2120   *          connection on which the referral was received.
2121   */
2122  public ReferralConnector getReferralConnector()
2123  {
2124    return referralConnector;
2125  }
2126
2127
2128
2129  /**
2130   * Specifies the referral connector that should be used to establish and
2131   * optionally authenticate connections to servers when attempting to follow
2132   * referrals.
2133   *
2134   * @param  referralConnector  The referral connector that will be used to
2135   *                            establish and optionally authenticate
2136   *                            connections to servers when attempting to follow
2137   *                            referrals.  It may be {@code null} to indicate
2138   *                            that the same socket factory and bind request
2139   *                            as the connection on which the referral was
2140   *                            received should be used to establish and
2141   *                            authenticate connections for following
2142   *                            referrals.
2143   */
2144  public void setReferralConnector(final ReferralConnector referralConnector)
2145  {
2146    this.referralConnector = referralConnector;
2147  }
2148
2149
2150
2151  /**
2152   * Retrieves the maximum size in bytes for an LDAP message that a connection
2153   * will attempt to read from the directory server.  If it encounters an LDAP
2154   * message that is larger than this size, then the connection will be
2155   * terminated.
2156   *
2157   * @return  The maximum size in bytes for an LDAP message that a connection
2158   *          will attempt to read from the directory server, or 0 if no limit
2159   *          will be enforced.
2160   */
2161  public int getMaxMessageSize()
2162  {
2163    return maxMessageSizeBytes;
2164  }
2165
2166
2167
2168  /**
2169   * Specifies the maximum size in bytes for an LDAP message that a connection
2170   * will attempt to read from the directory server.  If it encounters an LDAP
2171   * message that is larger than this size, then the connection will be
2172   * terminated.
2173   *
2174   * @param  maxMessageSizeBytes  The maximum size in bytes for an LDAP message
2175   *                              that a connection will attempt to read from
2176   *                              the directory server.  A value less than or
2177   *                              equal to zero indicates that no limit should
2178   *                              be enforced.
2179   */
2180  public void setMaxMessageSize(final int maxMessageSizeBytes)
2181  {
2182    this.maxMessageSizeBytes = Math.max(0, maxMessageSizeBytes);
2183  }
2184
2185
2186
2187  /**
2188   * Retrieves the disconnect handler to use for associated connections.
2189   *
2190   * @return  the disconnect handler to use for associated connections, or
2191   *          {@code null} if none is defined.
2192   */
2193  public DisconnectHandler getDisconnectHandler()
2194  {
2195    return disconnectHandler;
2196  }
2197
2198
2199
2200  /**
2201   * Specifies the disconnect handler to use for associated connections.
2202   *
2203   * @param  handler  The disconnect handler to use for associated connections.
2204   */
2205  public void setDisconnectHandler(final DisconnectHandler handler)
2206  {
2207    disconnectHandler = handler;
2208  }
2209
2210
2211
2212  /**
2213   * Retrieves the unsolicited notification handler to use for associated
2214   * connections.
2215   *
2216   * @return  The unsolicited notification handler to use for associated
2217   *          connections, or {@code null} if none is defined.
2218   */
2219  public UnsolicitedNotificationHandler getUnsolicitedNotificationHandler()
2220  {
2221    return unsolicitedNotificationHandler;
2222  }
2223
2224
2225
2226  /**
2227   * Specifies the unsolicited notification handler to use for associated
2228   * connections.
2229   *
2230   * @param  handler  The unsolicited notification handler to use for associated
2231   *                  connections.
2232   */
2233  public void setUnsolicitedNotificationHandler(
2234                   final UnsolicitedNotificationHandler handler)
2235  {
2236    unsolicitedNotificationHandler = handler;
2237  }
2238
2239
2240
2241  /**
2242   * Retrieves the socket receive buffer size, in bytes, that should be
2243   * requested when establishing a connection.
2244   *
2245   * @return  The socket receive buffer size, in bytes, that should be requested
2246   *          when establishing a connection, or zero if the JVM's default size
2247   *          should be used.
2248   */
2249  public int getReceiveBufferSize()
2250  {
2251    return receiveBufferSizeBytes;
2252  }
2253
2254
2255
2256  /**
2257   * Specifies the socket receive buffer size, in bytes, that should be
2258   * requested when establishing a connection.
2259   *
2260   * @param  receiveBufferSizeBytes  The socket receive buffer size, in bytes,
2261   *                                 that should be requested when establishing
2262   *                                 a connection, or zero if the JVM's default
2263   *                                 size should be used.
2264   */
2265  public void setReceiveBufferSize(final int receiveBufferSizeBytes)
2266  {
2267    this.receiveBufferSizeBytes = Math.max(0, receiveBufferSizeBytes);
2268  }
2269
2270
2271
2272  /**
2273   * Retrieves the socket send buffer size, in bytes, that should be requested
2274   * when establishing a connection.
2275   *
2276   * @return  The socket send buffer size, in bytes, that should be requested
2277   *          when establishing a connection, or zero if the JVM's default size
2278   *          should be used.
2279   */
2280  public int getSendBufferSize()
2281  {
2282    return sendBufferSizeBytes;
2283  }
2284
2285
2286
2287  /**
2288   * Specifies the socket send buffer size, in bytes, that should be requested
2289   * when establishing a connection.
2290   *
2291   * @param  sendBufferSizeBytes  The socket send buffer size, in bytes, that
2292   *                              should be requested when establishing a
2293   *                              connection, or zero if the JVM's default size
2294   *                              should be used.
2295   */
2296  public void setSendBufferSize(final int sendBufferSizeBytes)
2297  {
2298    this.sendBufferSizeBytes = Math.max(0, sendBufferSizeBytes);
2299  }
2300
2301
2302
2303  /**
2304   * Indicates whether to allow a socket factory instance (which may be shared
2305   * across multiple connections) to be used create multiple sockets
2306   * concurrently.  In general, socket factory implementations are threadsafe
2307   * and can be to create multiple connections simultaneously across separate
2308   * threads, but this is known to not be the case in some VM implementations
2309   * (e.g., SSL socket factories in IBM JVMs).  This setting may be used to
2310   * indicate whether concurrent socket creation attempts should be allowed
2311   * (which may allow for better and more consistent performance, especially in
2312   * cases where a connection attempt fails due to a timeout) or prevented
2313   * (which may be necessary for non-threadsafe socket factory implementations).
2314   *
2315   * @return  {@code true} if multiple threads should be able to concurrently
2316   *          use the same socket factory instance, or {@code false} if Java
2317   *          synchronization should be used to ensure that no more than one
2318   *          thread is allowed to use a socket factory at any given time.
2319   */
2320  public boolean allowConcurrentSocketFactoryUse()
2321  {
2322    return allowConcurrentSocketFactoryUse;
2323  }
2324
2325
2326
2327  /**
2328   * Specifies whether to allow a socket factory instance (which may be shared
2329   * across multiple connections) to be used create multiple sockets
2330   * concurrently.  In general, socket factory implementations are threadsafe
2331   * and can be to create multiple connections simultaneously across separate
2332   * threads, but this is known to not be the case in some VM implementations
2333   * (e.g., SSL socket factories in IBM JVMs).  This setting may be used to
2334   * indicate whether concurrent socket creation attempts should be allowed
2335   * (which may allow for better and more consistent performance, especially in
2336   * cases where a connection attempt fails due to a timeout) or prevented
2337   * (which may be necessary for non-threadsafe socket factory implementations).
2338   *
2339   * @param  allowConcurrentSocketFactoryUse  Indicates whether to allow a
2340   *                                          socket factory instance to be used
2341   *                                          to create multiple sockets
2342   *                                          concurrently.
2343   */
2344  public void setAllowConcurrentSocketFactoryUse(
2345                   final boolean allowConcurrentSocketFactoryUse)
2346  {
2347    this.allowConcurrentSocketFactoryUse = allowConcurrentSocketFactoryUse;
2348  }
2349
2350
2351
2352  /**
2353   * Retrieves the {@link SSLSocketVerifier} that will be used to perform
2354   * additional validation for any newly-created {@code SSLSocket} instances.
2355   *
2356   * @return  The {@code SSLSocketVerifier} that will be used to perform
2357   *          additional validation for any newly-created {@code SSLSocket}
2358   *          instances.
2359   */
2360  public SSLSocketVerifier getSSLSocketVerifier()
2361  {
2362    return sslSocketVerifier;
2363  }
2364
2365
2366
2367  /**
2368   * Specifies the {@link SSLSocketVerifier} that will be used to perform
2369   * additional validation for any newly-created {@code SSLSocket} instances.
2370   *
2371   * @param  sslSocketVerifier  The {@code SSLSocketVerifier} that will be used
2372   *                            to perform additional validation for any
2373   *                            newly-created {@code SSLSocket} instances.
2374   */
2375  public void setSSLSocketVerifier(final SSLSocketVerifier sslSocketVerifier)
2376  {
2377    if (sslSocketVerifier == null)
2378    {
2379      this.sslSocketVerifier = DEFAULT_SSL_SOCKET_VERIFIER;
2380    }
2381    else
2382    {
2383      this.sslSocketVerifier = sslSocketVerifier;
2384    }
2385  }
2386
2387
2388
2389  /**
2390   * Retrieves the value of the specified system property as a boolean.
2391   *
2392   * @param  propertyName  The name of the system property whose value should be
2393   *                       retrieved.
2394   * @param  defaultValue  The default value that will be returned if the system
2395   *                       property is not defined or if its value cannot be
2396   *                       parsed as a boolean.
2397   *
2398   * @return  The value of the specified system property as an boolean, or the
2399   *          default value if the system property is not set with a valid
2400   *          value.
2401   */
2402  static boolean getSystemProperty(final String propertyName,
2403                                   final boolean defaultValue)
2404  {
2405    final String propertyValue = System.getProperty(propertyName);
2406    if (propertyValue == null)
2407    {
2408      if (Debug.debugEnabled())
2409      {
2410        Debug.debug(Level.FINE, DebugType.OTHER,
2411             "Using the default value of " + defaultValue + " for system " +
2412                  "property '" + propertyName + "' that is not set.");
2413      }
2414
2415      return defaultValue;
2416    }
2417
2418    if (propertyValue.equalsIgnoreCase("true"))
2419    {
2420      if (Debug.debugEnabled())
2421      {
2422        Debug.debug(Level.INFO, DebugType.OTHER,
2423             "Using value '" + propertyValue + "' set for system property '" +
2424                  propertyName + "'.");
2425      }
2426
2427      return true;
2428    }
2429    else if (propertyValue.equalsIgnoreCase("false"))
2430    {
2431      if (Debug.debugEnabled())
2432      {
2433        Debug.debug(Level.INFO, DebugType.OTHER,
2434             "Using value '" + propertyValue + "' set for system property '" +
2435                  propertyName + "'.");
2436      }
2437
2438      return false;
2439    }
2440    else
2441    {
2442      if (Debug.debugEnabled())
2443      {
2444        Debug.debug(Level.WARNING, DebugType.OTHER,
2445             "Invalid value '" + propertyValue + "' set for system property '" +
2446                  propertyName + "'.  The value was expected to be either " +
2447                  "'true' or 'false'.  The default value of " + defaultValue +
2448                  " will be used instead of the configured value.");
2449      }
2450
2451      return defaultValue;
2452    }
2453  }
2454
2455
2456
2457  /**
2458   * Retrieves the value of the specified system property as an integer.
2459   *
2460   * @param  propertyName  The name of the system property whose value should be
2461   *                       retrieved.
2462   * @param  defaultValue  The default value that will be returned if the system
2463   *                       property is not defined or if its value cannot be
2464   *                       parsed as an integer.
2465   *
2466   * @return  The value of the specified system property as an integer, or the
2467   *          default value if the system property is not set with a valid
2468   *          value.
2469   */
2470  static int getSystemProperty(final String propertyName,
2471                               final int defaultValue)
2472  {
2473    final String propertyValueString = System.getProperty(propertyName);
2474    if (propertyValueString == null)
2475    {
2476      if (Debug.debugEnabled())
2477      {
2478        Debug.debug(Level.FINE, DebugType.OTHER,
2479             "Using the default value of " + defaultValue + " for system " +
2480                  "property '" + propertyName + "' that is not set.");
2481      }
2482
2483      return defaultValue;
2484    }
2485
2486    try
2487    {
2488      final int propertyValueInt = Integer.parseInt(propertyValueString);
2489      if (Debug.debugEnabled())
2490      {
2491        Debug.debug(Level.INFO, DebugType.OTHER,
2492             "Using value " + propertyValueInt + " set for system property '" +
2493                  propertyName + "'.");
2494      }
2495
2496      return propertyValueInt;
2497    }
2498    catch (final Exception e)
2499    {
2500      if (Debug.debugEnabled())
2501      {
2502        Debug.debugException(e);
2503        Debug.debug(Level.WARNING, DebugType.OTHER,
2504             "Invalid value '" + propertyValueString + "' set for system " +
2505                  "property '" + propertyName + "'.  The value was expected " +
2506                  "to be an integer.  The default value of " + defaultValue +
2507                  "will be used instead of the configured value.",
2508             e);
2509      }
2510
2511      return defaultValue;
2512    }
2513  }
2514
2515
2516
2517  /**
2518   * Retrieves the value of the specified system property as a long.
2519   *
2520   * @param  propertyName  The name of the system property whose value should be
2521   *                       retrieved.
2522   * @param  defaultValue  The default value that will be returned if the system
2523   *                       property is not defined or if its value cannot be
2524   *                       parsed as a long.
2525   *
2526   * @return  The value of the specified system property as a long, or the
2527   *          default value if the system property is not set with a valid
2528   *          value.
2529   */
2530  static Long getSystemProperty(final String propertyName,
2531                                final Long defaultValue)
2532  {
2533    final String propertyValueString = System.getProperty(propertyName);
2534    if (propertyValueString == null)
2535    {
2536      if (Debug.debugEnabled())
2537      {
2538        Debug.debug(Level.FINE, DebugType.OTHER,
2539             "Using the default value of " + defaultValue + " for system " +
2540                  "property '" + propertyName + "' that is not set.");
2541      }
2542
2543      return defaultValue;
2544    }
2545
2546    try
2547    {
2548      final long propertyValueLong = Long.parseLong(propertyValueString);
2549      if (Debug.debugEnabled())
2550      {
2551        Debug.debug(Level.INFO, DebugType.OTHER,
2552             "Using value " + propertyValueLong + " set for system property '" +
2553                  propertyName + "'.");
2554      }
2555
2556      return propertyValueLong;
2557    }
2558    catch (final Exception e)
2559    {
2560      if (Debug.debugEnabled())
2561      {
2562        Debug.debugException(e);
2563        Debug.debug(Level.WARNING, DebugType.OTHER,
2564             "Invalid value '" + propertyValueString + "' set for system " +
2565                  "property '" + propertyName + "'.  The value was expected " +
2566                  "to be a long.  The default value of " + defaultValue +
2567                  "will be used instead of the configured value.",
2568             e);
2569      }
2570
2571      return defaultValue;
2572    }
2573  }
2574
2575
2576
2577  /**
2578   * Retrieves a string representation of this LDAP connection.
2579   *
2580   * @return  A string representation of this LDAP connection.
2581   */
2582  @Override()
2583  public String toString()
2584  {
2585    final StringBuilder buffer = new StringBuilder();
2586    toString(buffer);
2587    return buffer.toString();
2588  }
2589
2590
2591
2592  /**
2593   * Appends a string representation of this LDAP connection to the provided
2594   * buffer.
2595   *
2596   * @param  buffer  The buffer to which to append a string representation of
2597   *                 this LDAP connection.
2598   */
2599  public void toString(final StringBuilder buffer)
2600  {
2601    buffer.append("LDAPConnectionOptions(autoReconnect=");
2602    buffer.append(autoReconnect);
2603    buffer.append(", nameResolver=");
2604    nameResolver.toString(buffer);
2605    buffer.append(", bindWithDNRequiresPassword=");
2606    buffer.append(bindWithDNRequiresPassword);
2607    buffer.append(", followReferrals=");
2608    buffer.append(followReferrals);
2609    if (followReferrals)
2610    {
2611      buffer.append(", referralHopLimit=");
2612      buffer.append(referralHopLimit);
2613    }
2614    if (referralConnector != null)
2615    {
2616      buffer.append(", referralConnectorClass=");
2617      buffer.append(referralConnector.getClass().getName());
2618    }
2619    buffer.append(", useKeepAlive=");
2620    buffer.append(useKeepAlive);
2621    buffer.append(", useLinger=");
2622    if (useLinger)
2623    {
2624      buffer.append("true, lingerTimeoutSeconds=");
2625      buffer.append(lingerTimeoutSeconds);
2626    }
2627    else
2628    {
2629      buffer.append("false");
2630    }
2631    buffer.append(", useReuseAddress=");
2632    buffer.append(useReuseAddress);
2633    buffer.append(", useSchema=");
2634    buffer.append(useSchema);
2635    buffer.append(", usePooledSchema=");
2636    buffer.append(usePooledSchema);
2637    buffer.append(", pooledSchemaTimeoutMillis=");
2638    buffer.append(pooledSchemaTimeoutMillis);
2639    buffer.append(", useSynchronousMode=");
2640    buffer.append(useSynchronousMode);
2641    buffer.append(", useTCPNoDelay=");
2642    buffer.append(useTCPNoDelay);
2643    buffer.append(", captureConnectStackTrace=");
2644    buffer.append(captureConnectStackTrace);
2645    buffer.append(", connectTimeoutMillis=");
2646    buffer.append(connectTimeoutMillis);
2647    buffer.append(", responseTimeoutMillis=");
2648    buffer.append(responseTimeoutMillis);
2649
2650    for (final Map.Entry<OperationType,Long> e :
2651         responseTimeoutMillisByOperationType.entrySet())
2652    {
2653      buffer.append(", responseTimeoutMillis.");
2654      buffer.append(e.getKey().name());
2655      buffer.append('=');
2656      buffer.append(e.getValue());
2657    }
2658
2659    for (final Map.Entry<String,Long> e :
2660         responseTimeoutMillisByExtendedOperationType.entrySet())
2661    {
2662      buffer.append(", responseTimeoutMillis.EXTENDED.");
2663      buffer.append(e.getKey());
2664      buffer.append('=');
2665      buffer.append(e.getValue());
2666    }
2667
2668    buffer.append(", abandonOnTimeout=");
2669    buffer.append(abandonOnTimeout);
2670    buffer.append(", maxMessageSizeBytes=");
2671    buffer.append(maxMessageSizeBytes);
2672    buffer.append(", receiveBufferSizeBytes=");
2673    buffer.append(receiveBufferSizeBytes);
2674    buffer.append(", sendBufferSizeBytes=");
2675    buffer.append(sendBufferSizeBytes);
2676    buffer.append(", allowConcurrentSocketFactoryUse=");
2677    buffer.append(allowConcurrentSocketFactoryUse);
2678    if (disconnectHandler != null)
2679    {
2680      buffer.append(", disconnectHandlerClass=");
2681      buffer.append(disconnectHandler.getClass().getName());
2682    }
2683    if (unsolicitedNotificationHandler != null)
2684    {
2685      buffer.append(", unsolicitedNotificationHandlerClass=");
2686      buffer.append(unsolicitedNotificationHandler.getClass().getName());
2687    }
2688
2689    buffer.append(", sslSocketVerifierClass='");
2690    buffer.append(sslSocketVerifier.getClass().getName());
2691    buffer.append('\'');
2692
2693    buffer.append(')');
2694  }
2695}