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