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