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