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