001/*
002 * Copyright 2015-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.util.json;
022
023
024
025import java.io.BufferedReader;
026import java.io.File;
027import java.io.FileInputStream;
028import java.io.FileReader;
029import java.io.InputStream;
030import java.io.IOException;
031import java.util.Arrays;
032import java.util.HashSet;
033
034import com.unboundid.ldap.sdk.BindRequest;
035import com.unboundid.ldap.sdk.LDAPConnection;
036import com.unboundid.ldap.sdk.LDAPConnectionPool;
037import com.unboundid.ldap.sdk.LDAPException;
038import com.unboundid.ldap.sdk.ResultCode;
039import com.unboundid.ldap.sdk.ServerSet;
040import com.unboundid.util.ByteStringBuffer;
041import com.unboundid.util.Debug;
042import com.unboundid.util.NotMutable;
043import com.unboundid.util.StaticUtils;
044import com.unboundid.util.ThreadSafety;
045import com.unboundid.util.ThreadSafetyLevel;
046
047import static com.unboundid.util.json.JSONMessages.*;
048
049
050
051/**
052 * This class provides a utility that may be used to obtain information that may
053 * be used to create LDAP connections to one or more servers from a definition
054 * contained in a JSON object.  This makes it easier to create applications that
055 * provide the information necessary for creating LDAP connections and
056 * connection pools in a JSON-formatted configuration file.
057 * <BR><BR>
058 * The JSON-based specification is organized into five sections:
059 * <OL>
060 *   <LI>
061 *     A "server-details" section that provides information about the directory
062 *     server(s) to access.  The specification supports accessing a single
063 *     server, as well as a number of schemes for establishing connections
064 *     across multiple servers.
065 *   </LI>
066 *   <LI>
067 *     A "communication-security" section that provides information that may be
068 *     used to secure communication using SSL or StartTLS.
069 *   </LI>
070 *   <LI>
071 *     A "connection-options" section that can be used customize a number of
072 *     connection-related options, like connect and response timeouts, whether
073 *     to follow referrals, whether to retrieve schema from the backend server
074 *     for client-side use, and whether to use synchronous mode for more
075 *     efficient communication if connections will not be used in an
076 *     asynchronous manner.
077 *   </LI>
078 *   <LI>
079 *     An "authentication-details" section that provides information for
080 *     authenticating connections using a number of mechanisms.
081 *   </LI>
082 *   <LI>
083 *     A "connection-pool-options" section that provides information to use to
084 *     customize the behavior to use for connection pools created from this
085 *     specification.
086 *   </LI>
087 * </OL>
088 * Each of these sections will be described in more detail below.
089 * <BR><BR>
090 * <H2>The "server-details" Section</H2>
091 * The JSON object that comprises the LDAP connection details specification must
092 * have a top-level "server-details" field whose value is a JSON object that
093 * provides information about the server(s) to which connections may be
094 * established.  The value of the "server-details" field must itself be a JSON
095 * object, and that object must have exactly one field, which depends on the
096 * mechanism that the LDAP SDK should use to select the target directory
097 * servers.
098 * <BR><BR>
099 * <B>The "server-details" Section for Connecting to a Single Server</B>
100 * <BR>
101 * When establishing a connection to a single server, the "server-details"
102 * value should be a JSON object that contains a "single-server" field whose
103 * value is a JSON object with "address" and "port" fields.  For example, the
104 * following is a valid specification that may be used to establish connections
105 * to the server at ldap.example.com on port 389:
106 * <PRE>
107 *   {
108 *     "server-details":
109 *     {
110 *       "single-server":
111 *       {
112 *         "address":"ldap.example.com",
113 *         "port":389
114 *       }
115 *     }
116 *   }
117 * </PRE>
118 * <BR>
119 * <B>The "server-details" Section for Selecting from a Set of Servers in a
120 * Round-Robin Manner</B>
121 * <BR>
122 * If you have a set of servers that you want to connect to in a round-robin
123 * manner (in which the LDAP SDK will maintain a circular list of servers and
124 * each new connection will go to the next server in the list), the
125 * "server-details" value should be a JSON object that contains a
126 * "round-robin-set" field whose value is a JSON object that contains a "server"
127 * field with an array of JSON objects, each of which contains "address" and
128 * "port" fields for a target server.  For example, the following is a valid
129 * specification that may be used to establish connections across the servers
130 * ldap1.example.com, ldap2.example.com, and ldap3.example.com, all on port 389:
131 * <PRE>
132 *   {
133 *     "server-details":
134 *     {
135 *       "round-robin-set":
136 *       {
137 *         "servers":
138 *         [
139 *           {
140 *             "address":"ldap1.example.com",
141 *             "port":389
142 *           },
143 *           {
144 *             "address":"ldap2.example.com",
145 *             "port":389
146 *           },
147 *           {
148 *             "address":"ldap2.example.com",
149 *             "port":389
150 *           }
151 *         ]
152 *       }
153 *     }
154 *   }
155 * </PRE>
156 * <BR>
157 * <B>The "server-details" Section for Selecting from a Set of Servers in a
158 * Fewest Connections Manner</B>
159 * <BR>
160 * If you have a set of servers that you want to connect to in a manner that
161 * selects the server with the fewest established connections (at least
162 * connections created from this specification), the "server-details" value
163 * should be a JSON object that contains a "fewest-connections-set" field whose
164 * value is a JSON object that contains a "server" field with an array of JSON
165 * objects, each of which contains "address" and "port" fields for a target
166 * server.  For example, the following is a valid specification that may be used
167 * to establish connections across the servers ldap1.example.com,
168 * ldap2.example.com, and ldap3.example.com, all on port 389:
169 * <PRE>
170 *   {
171 *     "server-details":
172 *     {
173 *       "fewest-connections-set":
174 *       {
175 *         "servers":
176 *         [
177 *           {
178 *             "address":"ldap1.example.com",
179 *             "port":389
180 *           },
181 *           {
182 *             "address":"ldap2.example.com",
183 *             "port":389
184 *           },
185 *           {
186 *             "address":"ldap2.example.com",
187 *             "port":389
188 *           }
189 *         ]
190 *       }
191 *     }
192 *   }
193 * </PRE>
194 * <BR>
195 * <B>The "server-details" Section for Selecting from a Set of Servers in a
196 * Fastest Connect Manner</B>
197 * <BR>
198 * If you have a set of servers that you want to connect to in a manner that
199 * attempts to minimize the time required to establish new connections (by
200 * simultaneously attempting to create connections to every server in the set
201 * and taking the first connection to be established), the "server-details"
202 * value should be a JSON object that contains a "fastest-connect-set" field
203 * whose value is a JSON object that contains a "server" field with an array of
204 * JSON objects, each of which contains "address" and "port" fields for a target
205 * server.  For example, the following is a valid specification that may be used
206 * to establish connections across the servers ldap1.example.com,
207 * ldap2.example.com, and ldap3.example.com, all on port 389:
208 * <PRE>
209 *   {
210 *     "server-details":
211 *     {
212 *       "fastest-connect-set":
213 *       {
214 *         "servers":
215 *         [
216 *           {
217 *             "address":"ldap1.example.com",
218 *             "port":389
219 *           },
220 *           {
221 *             "address":"ldap2.example.com",
222 *             "port":389
223 *           },
224 *           {
225 *             "address":"ldap2.example.com",
226 *             "port":389
227 *           }
228 *         ]
229 *       }
230 *     }
231 *   }
232 * </PRE>
233 * <BR>
234 * <B>The "server-details" Section for Selecting from a Set of Servers in a
235 * Failover Manner</B>
236 * <BR>
237 * If you have a set of servers that you want to connect to in a manner that
238 * attempts to consistently establish connections to the same server (as long as
239 * it is available, and use a consistent failover order if the preferred server
240 * isn't available), the "server-details" value should be a JSON object that
241 * contains a "failover-set" field whose value is a JSON object that contains a
242 * "failover-order" field that provides a list of the details to use in order
243 * to establish the connections.  For example, the following is a valid
244 * specification that may be used to always try to establish connections to
245 * ldap1.example.com:389, then try ldap2.example.com:389, and then try
246 * ldap3.example.com:389:
247 * <PRE>
248 *   {
249 *     "server-details":
250 *     {
251 *       "failover-set":
252 *       {
253 *         "failover-order":
254 *         [
255 *           {
256 *             "single-server":
257 *             {
258 *               "address":"ldap1.example.com",
259 *               "port":389
260 *             }
261 *           },
262 *           {
263 *             "single-server":
264 *             {
265 *               "address":"ldap2.example.com",
266 *               "port":389
267 *             }
268 *           },
269 *           {
270 *             "single-server":
271 *             {
272 *               "address":"ldap2.example.com",
273 *               "port":389
274 *             }
275 *           }
276 *         ]
277 *       }
278 *     }
279 *   }
280 * </PRE>
281 * The failover set actually has the ability to perform failover across any kind
282 * of set.  This is a powerful capability that can be useful to define a
283 * hierarchy of sets, for example for sets referring to servers in different
284 * data centers (e.g., to prefer connecting to one of the servers in the local
285 * data center over servers in a remote data center).  For example, the
286 * following is a valid specification that may be used to connect to the server
287 * with the fewest connections in the east data center, but if no east servers
288 * are available then it will fail over to select the server with the fewest
289 * connections in the west data center:
290 * <PRE>
291 *   {
292 *     "server-details":
293 *     {
294 *       "failover-set":
295 *       {
296 *         "failover-order":
297 *         [
298 *           {
299 *             "fewest-connections-set":
300 *             {
301 *               "servers":
302 *               [
303 *                 {
304 *                   "address":"ldap1.east.example.com",
305 *                   "port":389
306 *                 },
307 *                 {
308 *                   "address":"ldap2.east.example.com",
309 *                   "port":389
310 *                 }
311 *               ]
312 *             }
313 *           },
314 *           {
315 *             "fewest-connections-set":
316 *             {
317 *               "servers":
318 *               [
319 *                 {
320 *                   "address":"ldap1.west.example.com",
321 *                   "port":389
322 *                 },
323 *                 {
324 *                   "address":"ldap2.west.example.com",
325 *                   "port":389
326 *                 }
327 *               ]
328 *             }
329 *           }
330 *         ]
331 *       }
332 *     }
333 *   }
334 * </PRE>
335 * For connections that are part of a connection pool, failover sets have the
336 * ability to assign a different maximum connection age to connections created
337 * to a non-preferred server.  This can help allow failover connections to be
338 * migrated back to the preferred server more quickly once that server is
339 * available again.  If you wish to specify an alternate maximum connection age
340 * for connections to a non-preferred server, you may include the
341 * "maximum-failover-connection-age-millis" field in the "failover-set" object.
342 * The value of this field should be a number that is greater than zero to
343 * specify the maximum age (in milliseconds) for those connections, or a value
344 * of zero to indicate that they should not be subject to a maximum age.  If
345 * this field is not present, then these connections will be assigned the
346 * default maximum connection age configured for the pool.
347 * <BR><BR>
348 * <H2>The "communication-security" Section</H2>
349 * This section may be used to provide information about the type of security to
350 * use to protect communication with directory servers.  If the specification
351 * includes information about multiple servers, then all servers will use the
352 * same type of security.
353 * <BR><BR>
354 * If present, the "communication-security" field should have a value that is a
355 * JSON object.  This object must have a "security-type" field with one of the
356 * following values:
357 * <UL>
358 *   <LI>
359 *     "none" -- Indicates that no communication security should be used.  The
360 *     communication will not be encrypted.
361 *   </LI>
362 *   <LI>
363 *     "SSL" -- Indicates that all communication should be encrypted with the
364 *     SSL (secure sockets layer) protocol, or more likely its more secure
365 *     successor TLS (transport-layer security) protocol.  You can also specify
366 *     a value of "TLS" to use this type of security.
367 *   </LI>
368 *   <LI>
369 *     "StartTLS" -- Indicates that the connection will be initially established
370 *     in a non-secure manner, but will be immediately secured with the StartTLS
371 *     extended operation.
372 *   </LI>
373 * </UL>
374 * If you do not wish to use any form of communication security, then the
375 * "security-type" field is the only one that should be present.  For example,
376 * the following is a valid specification that will use unencrypted
377 * communication to the server ldap.example.com on port 389:
378 * <PRE>
379 *   {
380 *     "server-details":
381 *     {
382 *       "single-server":
383 *       {
384 *         "address":"ldap.example.com",
385 *         "port":389
386 *       }
387 *     },
388 *     "communication-security":
389 *     {
390 *       "security-type":"none"
391 *     }
392 *   }
393 * </PRE>
394 * <BR>
395 * If you wish to secure the communication with either SSL or StartTLS, then
396 * there are a number of other options that may be specified using fields in the
397 * "communication-security" object.  Those options fall into two basic
398 * categories:  fields that provide information about how the client should
399 * determine whether to trust the certificate presented by the server, and
400 * fields that provide information about whether the client should present its
401 * own certificate to the server.  The fields related to client trust include:
402 * <UL>
403 *   <LI>
404 *     "trust-all-certificates" -- Indicates whether the client should blindly
405 *     trust any certificate that the server presents to it.  Using blind trust
406 *     is convenient for testing and troubleshooting purposes, but is not
407 *     recommended for production use because it can leave the communication
408 *     susceptible to man-in-the-middle attacks.  If this field is present, then
409 *     it should have a boolean value.  If it is not present, a default value
410 *     of {@code false} will be assumed.  If it is present with a value of
411 *     {@code true}, then the "trust-store-file", "trust-store-type",
412 *     "trust-store-pin", and "trust-store-pin-file" fields should not be used.
413 *   </LI>
414 *   <LI>
415 *     "trust-store-file" -- Specifies the path to a trust store file (in JKS
416 *     or PKCS#12 format).  If this is present, then the presented certificate
417 *     will only be trusted if the trust store file contains information about
418 *     all of the issuers in the certificate chain.
419 *   </LI>
420 *   <LI>
421 *     "trust-store-type"  -- Indicates the format for the trust store file.
422 *     If this is present, then its value should be a string that is either
423 *     "JKS" or "PKCS12".  If it is not present, then a default trust store type
424 *     of "JKS" will be assumed.
425 *   </LI>
426 *   <LI>
427 *     "trust-store-pin" -- Specifies the PIN that should be used to access the
428 *     contents of the trust store.  If this field is present, then its value
429 *     should be a string that is the clear-text PIN.  If it is not present,
430 *     then the PIN may be read from a file specified using the
431 *     "trust-store-pin-file" field.  If neither the "trust-store-pin" field nor
432 *     the "trust-store-pin-file" field is present, then no PIN will be used
433 *     when attempting to access the trust store (and in many cases, no trust
434 *     store PIN will be required).
435 *   </LI>
436 *   <LI>
437 *     "trust-store-pin-file" -- Specifies the path to a file that contains the
438 *     PIN to use to access the contents of the trust store.  If this field is
439 *     present, then its value must be the path to a file containing a single
440 *     line, which is the clear-text PIN.  If it is not present, then the PIN
441 *     may be obtained from the "trust-store-pin" field.  If neither the
442 *     "trust-store-pin" field nor the "trust-store-pin-file" field is present,
443 *     then no PIN will be used when attempting to access the trust store (and
444 *     in many cases, no trust store PIN will be required).
445 *   </LI>
446 *   <LI>
447 *     "trust-expired-certificates" -- Indicates whether the client should
448 *     trust certificates that are not yet valid or that have expired.  If this
449 *     field is present, then its value must be a boolean.  If the value is
450 *     {@code true}, then the certificate validity dates will not be taken into
451 *     consideration when deciding whether to trust a certificate.  If the value
452 *     is {@code false}, then any certificate whose validity window does not
453 *     include the current time will not be trusted (even if
454 *     "trust-all-certificates" is {@code true}).  If this field is not present,
455 *     then a default of {@code false} will be assumed.
456 *   </LI>
457 *   <LI>
458 *     "verify-address-in-certificate" -- Indicates whether the client should
459 *     examine the information contained in the certificate to verify that the
460 *     address the client used to connect to the server matches address
461 *     information contained in the certificate (whether in the CN attribute of
462 *     the certificate's subject, or in a subjectAltName extension of type
463 *     dNSName, uniformResourceIdentifier, or iPAddress).  If this field is
464 *     present, then its value must be a boolean.  If it is absent, then a
465 *     default value of {@code false} will be assumed.
466 *   </LI>
467 * </UL>
468 * If none of the above fields are provided, then the JVM's default trust
469 * mechanism will be used.  This will generally only trust certificates signed
470 * by a well-known certification authority.
471 * <BR><BR>
472 * The fields related to presenting a client certificate include:
473 * <UL>
474 *   <LI>
475 *     "key-store-file" -- Specifies the path to a key store file (in JKS or
476 *     PKCS#12 format) that contains the certificate that the client should
477 *     present to the server.  If this is present, then the value must be a
478 *     string that is the path to the key store file.  If it is not present,
479 *     then no key store file will be used.
480 *   </LI>
481 *   <LI>
482 *     "key-store-type" -- Specifies the type of key store that should be used.
483 *     If this is present, then its value must be a string, and that string
484 *     should be "JKS" or "PKCS12" (if a "key-store-file" value is present), or
485 *     "PKCS11" (if the client certificate is contained in a security module
486 *     accessible via the PKCS#11 API.  If this field is not present but a
487 *     "key-store-file" value is provided, then a default value of "JKS" will be
488 *     assumed.
489 *   </LI>
490 *   <LI>
491 *     "key-store-pin" -- Specifies the PIN that should be used to access the
492 *     contents of the key store.  If this field is present, then its value
493 *     should be a string that is the clear-text PIN.  If it is not present,
494 *     then the PIN may be read from a file specified using the
495 *     "key-store-pin-file" field.  If neither the "key-store-pin" field nor the
496 *     "key-store-pin-file" field is present, then no PIN will be used when
497 *     attempting to access the key store (although key stores generally require
498 *     a PIN in order to access private key information).
499 *   </LI>
500 *   <LI>
501 *     "key-store-pin-file" -- Specifies the path to a file containing the PIN
502 *     that should be used to access the contents of the key store.  If this
503 *     field is present, then its value should be the path to a file containing
504 *     the clear-text PIN.  If it is not present, then the PIN may be obtained
505 *     from the "key-store-pin" field.  If neither the "key-store-pin" field nor
506 *     the "key-store-pin-file" field is present, then no PIN will be used when
507 *     attempting to access the key store (although key stores generally require
508 *     a PIN in order to access private key information).
509 *   </LI>
510 *   <LI>
511 *     "client-certificate-alias" -- Specifies the alias (also known as the
512 *     nickname) of the client certificate that should be presented to the
513 *     directory server.  If this field is present, then its value should be a
514 *     string that is the alias for a valid certificate that exists in the
515 *     key store.  If this field is not present, then the JVM will automatically
516 *     attempt to select a suitable client certificate.
517 *   </LI>
518 * </UL>
519 * If none of the above fields are provided, then the client will not attempt to
520 * present a certificate to the server.
521 * <BR><BR>
522 * The following example demonstrates a simple specification that can be used to
523 * establish SSL-based connections to a single server.  The client will use a
524 * trust store to determine whether to trust the certificate presented by the
525 * server, and will not attempt to present its own certificate to the server.
526 * <PRE>
527 *   {
528 *     "server-details":
529 *     {
530 *       "single-server":
531 *       {
532 *         "address":"ldap.example.com",
533 *         "port":636
534 *       }
535 *     },
536 *     "communication-security":
537 *     {
538 *       "security-type":"SSL",
539 *       "trust-store-file":"/path/to/trust-store.jks",
540 *       "trust-store-type":"JKS",
541 *       "verify-address-in-certificate":true
542 *     }
543 *   }
544 * </PRE>
545 * <BR>
546 * The "communication-security" field is optional, and if it is omitted from the
547 * specification then it will be equivalent to including it with a
548 * "security-type" value of "none".
549 * <BR><BR>
550 * <H2>The "connection-options" Section</H2>
551 * The "connection-options" section may be used to provide information about a
552 * number of settings that may be used in the course of establishing a
553 * connection, or that may affect the behavior of the connection.  The value
554 * of the "connection-options" field must be a JSON object, and the following
555 * fields may appear in that object:
556 * <UL>
557 *   <LI>
558 *     "connect-timeout-millis" -- Specifies the maximum length of time (in
559 *     milliseconds) that a connection attempt may block while waiting for the
560 *     connection to be established.  If this field is present, then its value
561 *     must be a positive integer to specify the timeout, or a value of zero to
562 *     indicate that no timeout should be enforced by the LDAP SDK.  Note that
563 *     the underlying operating system may enforce its own connect timeout, and
564 *     if that value is smaller than the LDAP SDK timeout then the operating
565 *     system's timeout value will be used.  If this field is not present, then
566 *     a default of 60000 (1 minute) will be used.
567 *   </LI>
568 *   <LI>
569 *     "default-response-timeout-millis" -- Specifies the default timeout (in
570 *     milliseconds) that will be used when waiting for a response to a request
571 *     sent to the server.  If this field is present, then its value must be a
572 *     positive integer to specify the timeout, or a value of zero to indicate
573 *     that no timeout should be enforced.  If this field is not present, then a
574 *     default of 300000 (5 minutes) will be used.  Note that this default
575 *     response timeout can be overridden on a per-request basis using the
576 *     {@code setResponseTimeoutMillis} method provided by the request object.
577 *   </LI>
578 *   <LI>
579 *     "follow-referrals" -- Indicates whether the LDAP SDK should automatically
580 *     attempt to follow any referrals that are returned during processing.  If
581 *     this field is present, the value should be a boolean.  If it is absent,
582 *     then a default  of {@code false} will be assumed.
583 *   </LI>
584 *   <LI>
585 *     "use-schema" -- Indicates whether the LDAP SDK should attempt to retrieve
586 *     schema information from the directory server upon establishing a
587 *     connection to that server, and should then use that schema information
588 *     for more accurate client-side matching operations.  If present, this
589 *     field should have a boolean value.  If it is not present, then a default
590 *     value of {@code false} will be used.
591 *   </LI>
592 *   <LI>
593 *     "use-synchronous-mode" -- Indicates whether connections should be created
594 *     in synchronous mode, which may be more efficient and less resource
595 *     intensive than connections not created in synchronous mode, but may only
596 *     be used if no attempt will be made to issue asynchronous requests over
597 *     the connection, or to attempt to use the connection simultaneously by
598 *     multiple threads.  If this field is present, then its value must be a
599 *     boolean.  If it is not present, then a default value of {@code false}
600 *     will be used.
601 *   </LI>
602 * </UL>
603 * <BR>
604 * The "connection-options" field is optional, and if it is omitted from the
605 * specification then the default values will be used for all options.
606 * <BR><BR>
607 * <H2>The "authentication-details" Section</H2>
608 * The "authentication-details" section may be used to provide information for
609 * authenticating the connections that are created.  The value of the
610 * "authentication-details" field must be a JSON object, and it must include an
611 * "authentication-type" field to specify the mechanism to use to authenticate.
612 * The selected authentication type dictates the other fields that may be
613 * present in the object.
614 * <BR><BR>
615 * <B>The "none" Authentication Type</B>
616 * <BR>
617 * If no authentication should be performed, then the "authentication-type"
618 * value should be "none".  No other fields should be specified in the
619 * "authentication-details".  For example:
620 * <PRE>
621 *   {
622 *     "server-details":
623 *     {
624 *       "single-server":
625 *       {
626 *         "address":"ldap.example.com",
627 *         "port":389
628 *       }
629 *     },
630 *     "authentication-details":
631 *     {
632 *       "authentication-type":"none"
633 *     }
634 *   }
635 * </PRE>
636 * <BR>
637 * <B>The "simple" Authentication Type</B>
638 * <BR>
639 * If you wish to authenticate connections with an LDAP simple bind, then you
640 * can specify an "authentication-type" value of "simple".  The following
641 * additional fields may be included in the "authentication-details" object for
642 * this authentication type:
643 * <UL>
644 *   <LI>
645 *     "dn" -- The DN to use to bind to the server.  This field must be present,
646 *     and its value must be a string containing the bind DN, or an empty string
647 *     to indicate anonymous simple authentication.
648 *   </LI>
649 *   <LI>
650 *     "password" -- The password to use to bind to the server.  If this field
651 *     is present, then its value must be a string that contains the clear-text
652 *     password, or an empty string to indicate anonymous simple
653 *     authentication.  If it is not provided, then the "password-file" field
654 *     must be used to specify the path to a file containing the bind password.
655 *   </LI>
656 *   <LI>
657 *     "password-file" -- The path to a file containing the password to use to
658 *     bind to the server.  If this field is present, then its value must be a
659 *     string that represents the path to a file containing a single line that
660 *     contains the clear-text password.  If it is not provided, then the
661 *     "password" field must be used to specify the password.
662 *   </LI>
663 * </UL>
664 * For example:
665 * <PRE>
666 *   {
667 *     "server-details":
668 *     {
669 *       "single-server":
670 *       {
671 *         "address":"ldap.example.com",
672 *         "port":389
673 *       }
674 *     },
675 *     "authentication-details":
676 *     {
677 *       "authentication-type":"simple",
678 *       "dn":"uid=john.doe,ou=People,dc=example,dc=com",
679 *       "password-file":"/path/to/password.txt"
680 *     }
681 *   }
682 * </PRE>
683 * <BR>
684 * <B>The "CRAM-MD5" Authentication Type</B>
685 * If you wish to authenticate connections with the CRAM-MD5 SASL mechanism,
686 * then you can specify an "authentication-type" value of "CRAM-MD5".  The
687 * following additional fields may be included in the "authentication-details"
688 * object for this authentication type:
689 * <UL>
690 *   <LI>
691 *     "authentication-id" -- The authentication ID to use to bind.  This field
692 *     must be present, and its value must be a string containing the
693 *     authentication ID.  Authentication ID values typically take the form
694 *     "dn:" followed by the user DN, or "u:" followed by the username.
695 *   </LI>
696 *   <LI>
697 *     "password" -- The password to use to bind to the server.  If this field
698 *     is present, then its value must be a string that contains the clear-text
699 *     password, or an empty string to indicate anonymous simple
700 *     authentication.  If it is not provided, then the "password-file" field
701 *     must be used to specify the path to a file containing the bind password.
702 *   </LI>
703 *   <LI>
704 *     "password-file" -- The path to a file containing the password to use to
705 *     bind to the server.  If this field is present, then its value must be a
706 *     string that represents the path to a file containing a single line that
707 *     contains the clear-text password.  If it is not provided, then the
708 *     "password" field must be used to specify the password.
709 *   </LI>
710 * </UL>
711 * For Example:
712 * <PRE>
713 *   {
714 *     "server-details":
715 *     {
716 *       "single-server":
717 *       {
718 *         "address":"ldap.example.com",
719 *         "port":389
720 *       }
721 *     },
722 *     "authentication-details":
723 *     {
724 *       "authentication-type":"CRAM-MD5",
725 *       "authentication-id":"u:john.doe",
726 *       "password-file":"/path/to/password.txt"
727 *     }
728 *   }
729 * </PRE>
730 * <BR>
731 * <B>The "DIGEST-MD5" Authentication Type</B>
732 * If you wish to authenticate connections with the DIGEST-MD5 SASL mechanism,
733 * then you can specify an "authentication-type" value of "DIGEST-MD5".  The
734 * following additional fields may be included in the "authentication-details"
735 * object for this authentication type:
736 * <UL>
737 *   <LI>
738 *     "authentication-id" -- The authentication ID to use to bind.  This field
739 *     must be present, and its value must be a string containing the
740 *     authentication ID.  Authentication ID values typically take the form
741 *     "dn:" followed by the user DN, or "u:" followed by the username.
742 *   </LI>
743 *   <LI>
744 *     "authorization-id" -- The alternate authorization identity to use for the
745 *     connection after the bind has completed.  If present, the value must be
746 *     a string containing the desired authorization identity.  If this field is
747 *     absent, then no alternate authorization identity will be used.
748 *   </LI>
749 *   <LI>
750 *     "password" -- The password to use to bind to the server.  If this field
751 *     is present, then its value must be a string that contains the clear-text
752 *     password, or an empty string to indicate anonymous simple
753 *     authentication.  If it is not provided, then the "password-file" field
754 *     must be used to specify the path to a file containing the bind password.
755 *   </LI>
756 *   <LI>
757 *     "password-file" -- The path to a file containing the password to use to
758 *     bind to the server.  If this field is present, then its value must be a
759 *     string that represents the path to a file containing a single line that
760 *     contains the clear-text password.  If it is not provided, then the
761 *     "password" field must be used to specify the password.
762 *   </LI>
763 *   <LI>
764 *     "realm" -- The realm to use for the bind request.  If this field is
765 *     present, then its value must be a string containing the name of the
766 *     realm.  If it is not provided, then the realm will not be included in the
767 *     bind request.
768 *   </LI>
769 *   <LI>
770 *     "qop" -- The allowed quality of protection value(s) that may be used for
771 *     the bind operation.  If this field is present, then its value may be a
772 *     single string or an array of strings indicating the allowed QoP values.
773 *     Allowed values include "auth" (for just authentication), "auth-int" (for
774 *     authentication followed by integrity protection for subsequent
775 *     communication on the connection), and "auth-conf" (for authentication
776 *     followed by confidentiality for subsequent communication on the
777 *     connection).  If this field is not present, then a default value of
778 *     "auth" will be assumed.
779 *   </LI>
780 * </UL>
781 * For Example:
782 * <PRE>
783 *   {
784 *     "server-details":
785 *     {
786 *       "single-server":
787 *       {
788 *         "address":"ldap.example.com",
789 *         "port":389
790 *       }
791 *     },
792 *     "authentication-details":
793 *     {
794 *       "authentication-type":"DIGEST-MD5",
795 *       "authentication-id":"u:john.doe",
796 *       "password-file":"/path/to/password.txt"
797 *     }
798 *   }
799 * </PRE>
800 * <BR>
801 * <B>The "EXTERNAL" Authentication Type</B>
802 * If you wish to authenticate connections with the EXTERNAL SASL mechanism,
803 * then you can specify an "authentication-type" value of "EXTERNAL".  The
804 * connection must be secured with SSL or StartTLS, and the following additional
805 * field may be present in the "authentication-details" object:
806 * <UL>
807 *   <LI>
808 *     "authorization-id" -- The authorization identity for the bind request.
809 *     If this field is present, then it must be a string containing the
810 *     desired authorization ID, or an empty string if the server should
811 *     determine the authorization identity.  If this field is omitted, then
812 *     the bind request will not include any SASL credentials, which may be
813 *     required for use with some servers that cannot handle the possibility of
814 *     an authorization ID in the bind request.
815 *   </LI>
816 * </UL>
817 * For Example:
818 * <PRE>
819 *   {
820 *     "server-details":
821 *     {
822 *       "single-server":
823 *       {
824 *         "address":"ldap.example.com",
825 *         "port":636
826 *       }
827 *     },
828 *     "communication-security":
829 *     {
830 *       "security-type":"SSL",
831 *       "trust-store-file":"/path/to/trust-store.jks",
832 *       "trust-store-type":"JKS",
833 *       "verify-address-in-certificate":true
834 *     },
835 *     "authentication-details":
836 *     {
837 *       "authentication-type":"EXTERNAL",
838 *       "authorization-id":""
839 *     }
840 *   }
841 * </PRE>
842 * <BR>
843 * <B>The "GSSAPI" Authentication Type</B>
844 * If you wish to authenticate connections with the GSSAPI SASL mechanism,
845 * then you can specify an "authentication-type" value of "GSSAPI".  The
846 * following additional fields may be included in the "authentication-details"
847 * object for this authentication type:
848 * <UL>
849 *   <LI>
850 *     "authentication-id" -- The authentication ID to use to bind.  This field
851 *     must be present, and its value must be a string containing the
852 *     authentication ID.  Authentication ID values for a GSSAPI bind request
853 *     are typically the Kerberos principal for the user to authenticate.
854 *   </LI>
855 *   <LI>
856 *     "authorization-id" -- The alternate authorization identity to use for the
857 *     connection after the bind has completed.  If present, the value must be
858 *     a string containing the desired authorization identity.  If this field is
859 *     absent, then no alternate authorization identity will be used.
860 *   </LI>
861 *   <LI>
862 *     "password" -- The password to use to bind to the server.  If this field
863 *     is present, then its value must be a string that contains the clear-text
864 *     password, or an empty string to indicate anonymous simple
865 *     authentication.  If it is not provided, then the "password-file" field
866 *     may be used to specify the path to a file containing the bind password.
867 *     If authentication will require the use of cached credentials, then the
868 *     password may be omitted.
869 *   </LI>
870 *   <LI>
871 *     "password-file" -- The path to a file containing the password to use to
872 *     bind to the server.  If this field is present, then its value must be a
873 *     string that represents the path to a file containing a single line that
874 *     contains the clear-text password.  If it is not provided, then the
875 *     "password" field may be used to specify the password.  If authentication
876 *     will require the use of cached credentials, then the password may be
877 *     omitted.
878 *   </LI>
879 *   <LI>
880 *     "realm" -- The realm to use for the bind request.  If this field is
881 *     present, then its value must be a string containing the name of the
882 *     realm.  If it is not provided, then the JVM will attempt to determine the
883 *     realm from the underlying system configuration.
884 *   </LI>
885 *   <LI>
886 *     "qop" -- The allowed quality of protection value(s) that may be used for
887 *     the bind operation.  If this field is present, then its value may be a
888 *     single string or an array of strings indicating the allowed QoP values.
889 *     Allowed values include "auth" (for just authentication), "auth-int" (for
890 *     authentication followed by integrity protection for subsequent
891 *     communication on the connection), and "auth-conf" (for authentication
892 *     followed by confidentiality for subsequent communication on the
893 *     connection).  If this field is not present, then a default value of
894 *     "auth" will be assumed.
895 *   </LI>
896 *   <LI>
897 *     "kdc-address" -- The address of the Kerberos KDC to use during
898 *     authentication.  If this field is present, then its value must be a
899 *     string containing the target address.  If it is not provided, then the
900 *     JVM will attempt to determine the address of the KDC from the underlying
901 *     system configuration.
902 *   </LI>
903 *   <LI>
904 *     "config-file-path" --  The path to a JAAS configuration file to use for
905 *     bind processing.  If this field is present, then its value must be a
906 *     string containing the path to a valid JAAS configuration file.  If it is
907 *     not provided, a temporary JAAS configuration file will be created for the
908 *     bind operation.
909 *   </LI>
910 *   <LI>
911 *     "renew-tgt" -- Indicates whether successful authentication should attempt
912 *     to renew the ticket-granting ticket for an existing session.  If this
913 *     field is present, then its value must be a boolean.  If it is not
914 *     provided, then a default of {@code false} will be assumed.
915 *   </LI>
916 *   <LI>
917 *     "require-cached-credentials" -- Indicates whether the authentication
918 *     process should require the use of cached credentials leveraged from an
919 *     existing Kerberos session rather than try to create a new session.  if
920 *     this field is present, then its value must be a boolean.  If it is not
921 *     provided, then a default of {@code false} will be assumed.
922 *   </LI>
923 *   <LI>
924 *     "use-ticket-cache" -- Indicates whether the authentication process should
925 *     leverage a ticket cache in order to leverage an existing Kerberos
926 *     session if the user has already authenticated to the KDC.  If present,
927 *     then its value must be a boolean.  If it is not provided, then a default
928 *     of {@code true} will be used.
929 *   </LI>
930 *   <LI>
931 *     "ticket-cache-path" -- Specifies the path to the Kerberos ticket cache to
932 *     use.  If this is provided, its value must be a string with the path to
933 *     the desired ticket cache.  If it is not provided, then the JVM will
934 *     attempt to determine the appropriate ticket cache from the underlying
935 *     system configuration.
936 *   </LI>
937 *   <LI>
938 *     "use-subject-credentials-only" -- Indicates whether authentication should
939 *     require the client will be required to use credentials that match the
940 *     current subject.  If it is provided, then the value must be a boolean.
941 *     If it is not provided, then a default of {@code true} will be assumed.
942 *   </LI>
943 * </UL>
944 * For Example:
945 * <PRE>
946 *   {
947 *     "server-details":
948 *     {
949 *       "single-server":
950 *       {
951 *         "address":"ldap.example.com",
952 *         "port":389
953 *       }
954 *     },
955 *     "authentication-details":
956 *     {
957 *       "authentication-type":"GSSAPI",
958 *       "authentication-id":"john.doe@EXAMPLE.COM",
959 *       "password-file":"/path/to/password.txt",
960 *       "renew-tgt":true
961 *     }
962 *   }
963 * </PRE>
964 * <BR>
965 * <B>The "PLAIN" Authentication Type</B>
966 * If you wish to authenticate connections with the PLAIN SASL mechanism,
967 * then you can specify an "authentication-type" value of "PLAIN".  The
968 * following additional fields may be included in the "authentication-details"
969 * object for this authentication type:
970 * <UL>
971 *   <LI>
972 *     "authentication-id" -- The authentication ID to use to bind.  This field
973 *     must be present, and its value must be a string containing the
974 *     authentication ID.  Authentication ID values typically take the form
975 *     "dn:" followed by the user DN, or "u:" followed by the username.
976 *   </LI>
977 *   <LI>
978 *     "authorization-id" -- The alternate authorization identity to use for the
979 *     connection after the bind has completed.  If present, the value must be
980 *     a string containing the desired authorization identity.  If this field is
981 *     absent, then no alternate authorization identity will be used.
982 *   </LI>
983 *   <LI>
984 *     "password" -- The password to use to bind to the server.  If this field
985 *     is present, then its value must be a string that contains the clear-text
986 *     password, or an empty string to indicate anonymous simple
987 *     authentication.  If it is not provided, then the "password-file" field
988 *     must be used to specify the path to a file containing the bind password.
989 *   </LI>
990 *   <LI>
991 *     "password-file" -- The path to a file containing the password to use to
992 *     bind to the server.  If this field is present, then its value must be a
993 *     string that represents the path to a file containing a single line that
994 *     contains the clear-text password.  If it is not provided, then the
995 *     "password" field must be used to specify the password.
996 *   </LI>
997 * </UL>
998 * For Example:
999 * <PRE>
1000 *   {
1001 *     "server-details":
1002 *     {
1003 *       "single-server":
1004 *       {
1005 *         "address":"ldap.example.com",
1006 *         "port":389
1007 *       }
1008 *     },
1009 *     "authentication-details":
1010 *     {
1011 *       "authentication-type":"PLAIN",
1012 *       "authentication-id":"dn:uid=john.doe,ou=People,dc=example,dc=com",
1013 *       "password-file":"/path/to/password.txt"
1014 *     }
1015 *   }
1016 * </PRE>
1017 * <BR>
1018 * The "authentication-details" field is optional, and if it is omitted from the
1019 *  specification then no authentication will be performed.
1020 * <BR><BR>
1021 * <H2>The "connection-pool-options" Section</H2>
1022 * The "connection-pool-options" section may be used to provide information
1023 * about a number of settings that may be used in the course of creating or
1024 * maintaining a connection pool.  The value of the "connection-pool-options"
1025 * field must be a JSON object, and the following fields may appear in that
1026 * object:
1027 * <UL>
1028 *   <LI>
1029 *     "create-if-necessary" -- Indicates whether the connection pool should
1030 *     create a new connection if one is needed but none are available.  If
1031 *     present, the value must be a boolean.  If it is absent, then a default
1032 *     of {@code true} will be assumed.
1033 *   </LI>
1034 *   <LI>
1035 *     "health-check-get-entry-dn" -- The DN of an entry that should be
1036 *     retrieved during health check processing.  If present, the value must be
1037 *     a string that represents the DN of the entry to retrieve, or an empty
1038 *     string to indicate that the server root DSE should be retrieved.  If this
1039 *     field is absent, then no entry will be retrieved during health check
1040 *     processing.
1041 *   </LI>
1042 *   <LI>
1043 *     "health-check-get-entry-maximum-response-time-millis" -- The maximum
1044 *     length of time in milliseconds to wait for the entry to be returned in a
1045 *     get entry health check.  If present, the value must be a positive
1046 *     integer.  If it is not provided, then a default of 10000 (ten seconds)
1047 *     will be used.
1048 *   </LI>
1049 *   <LI>
1050 *     "initial-connect-threads" -- The number of threads to use when creating
1051 *     the initial set of connections for the pool.  If this field is present,
1052 *     then the value must be a positive integer, with a value of one indicating
1053 *     that connection should be created in a single-threaded manner, and a
1054 *     value greater than one indicating that the initial connections should be
1055 *     established in parallel.  If it is not provided, then a default of one
1056 *     will be used.
1057 *   </LI>
1058 *   <LI>
1059 *     "invoke-background-health-checks" -- Indicates whether the connection
1060 *     pool should periodically invoke health check processing on idle
1061 *     connections.  If this field is present, then its value must be a boolean.
1062 *     If it is not present, then a default of {@code true} will be assumed.
1063 *   </LI>
1064 *   <LI>
1065 *     "invoke-checkout-health-checks" -- Indicates whether the connection pool
1066 *     should invoke health check processing on connections just before they are
1067 *     checked out of the pool to ensure that they are valid.  If this field is
1068 *     present, then its value must be a boolean.  If it is not present, then a
1069 *     default of {@code false} will be assumed.
1070 *   </LI>
1071 *   <LI>
1072 *     "invoke-create-health-checks" -- Indicates whether the connection pool
1073 *     should invoke health check processing on connections just after they are
1074 *     created.  If this field is present, then its value must be a boolean.  If
1075 *     it is not present, then a default of {@code false} will be assumed.
1076 *   </LI>
1077 *   <LI>
1078 *     "invoke-authentication-health-checks" -- Indicates whether the connection
1079 *     pool should invoke health check processing on connections just after they
1080 *     have been authenticated.  This includes after a successful bind on a
1081 *     newly-created connection, and after calls to the connection pool's
1082 *     {@code bindAndRevertAuthentication} and
1083 *     {@code releaseAndReAuthenticateConnection} methods.  If this field is
1084 *     present, then its value must be a boolean.  If it is not present, then a
1085 *     default of {@code false} will be assumed.
1086 *   </LI>
1087 *   <LI>
1088 *     "invoke-exception-health-checks" -- Indicates whether the connection pool
1089 *     should invoke health check processing on connections just after an
1090 *     exception is caught that might indicate that the connection is no longer
1091 *     valid.  Note that this only applies to exceptions caught during
1092 *     operations processed directly against the connection pool and not to
1093 *     exceptions caught on a connection checked out of the pool.  If this field
1094 *     is present, then its value must be a boolean.  If it is not present, then
1095 *     a default of {@code true} will be assumed.
1096 *   </LI>
1097 *   <LI>
1098 *     "invoke-release-health-checks" -- Indicates whether the connection pool
1099 *     should invoke health check processing on connections just before they are
1100 *     released back to the pool to ensure that they are valid.  If this field
1101 *     is present, then its value must be a boolean.  If it is not present, then
1102 *     a default of {@code false} will be assumed.
1103 *   </LI>
1104 *   <LI>
1105 *     "maximum-connection-age-millis" -- Specifies the maximum length of time
1106 *     (in milliseconds) that a connection should be allowed to remain
1107 *     established before it is eligible to be closed and replaced with a
1108 *     newly-created connection.  If present, then the value must be a positive
1109 *     integer to specify the maximum age, or zero to indicate that no maximum
1110 *     age should be applied.  If it is not present, then a default value of
1111 *     zero will be used.
1112 *   </LI>
1113 *   <LI>
1114 *     "maximum-defunct-replacement-connection-age-millis" -- Specifies the
1115 *     maximum connection age (in milliseconds) that should be used for
1116 *     connections created to replace a defunct connection.  If present, then
1117 *     the value must be a positive integer to specify the maximum age, or zero
1118 *     to indicate that no maximum age should be applied.  If it is not present,
1119 *     then the value of the "maximum-connection-age-millis" field will be used
1120 *     for connections created as replacements for defunct connections.
1121 *   </LI>
1122 *   <LI>
1123 *     "maximum-wait-time-millis" -- Specifies the maximum length of time (in
1124 *     milliseconds) that the pool should wait for a connection to be released
1125 *     if one is needed but none are immediately available.  If present, then
1126 *     this value must be a positive integer to specify the length of time to
1127 *     wait, or zero to indicate that it should not wait at all.  If it is not
1128 *     provided, then a default value of zero will be used.
1129 *   </LI>
1130 *   <LI>
1131 *     "retry-failed-operations-due-to-invalid-connections" -- Indicates whether
1132 *     the pool should automatically attempt to retry operations attempted
1133 *     directly against the pool (but not for connections checked out of the
1134 *     pool) if the initial attempt fails in a manner that may indicate that the
1135 *     connection is no longer valid.  If this field is present, then its value
1136 *     may be either a boolean to indicate whether to enable retry for all types
1137 *     of operations or no operations, or it may be an array of strings
1138 *     indicating the operation types ("add", "bind", "compare", "delete",
1139 *     "extended", "modify", "modify-dn", or "search") that should be retried
1140 *     in the event of a failure.  If this field is not present, then no
1141 *     automatic retry will be attempted.
1142 *   </LI>
1143 * </UL>
1144 * <BR>
1145 * The "connection-pool-options" field is optional, and if it is omitted from
1146 * the specification then the default values will be used for all options.
1147 */
1148@NotMutable()
1149@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
1150public final class LDAPConnectionDetailsJSONSpecification
1151{
1152  /**
1153   * The name of the top-level field that may be used to provide information to
1154   * use to authenticate connections to the server.
1155   */
1156  static final String FIELD_AUTHENTICATION_DETAILS = "authentication-details";
1157
1158
1159
1160  /**
1161   * The name of the top-level field that may be used to provide information
1162   * about the type of communication security that should be used.
1163   */
1164  static final String FIELD_COMMUNICATION_SECURITY = "communication-security";
1165
1166
1167
1168  /**
1169   * The name of the top-level field that may be used to provide information
1170   * about options that should be set when establishing connections.
1171   */
1172  static final String FIELD_CONNECTION_OPTIONS = "connection-options";
1173
1174
1175
1176  /**
1177   * The name of the top-level field that may be used to provide information
1178   * about options that should be set when creating a connection pool.
1179   */
1180  static final String FIELD_CONNECTION_POOL_OPTIONS =
1181       "connection-pool-options";
1182
1183
1184
1185  /**
1186   * The name of the top-level field that may be used to provide information
1187   * about the directory server(s) to which the connection should be
1188   * established.
1189   */
1190  static final String FIELD_SERVER_DETAILS = "server-details";
1191
1192
1193
1194  // The bind request that will be used to authenticate connections.
1195  private final BindRequest bindRequest;
1196
1197  // The processed connection pool options portion of the specification.
1198  private final ConnectionPoolOptions connectionPoolOptionsSpec;
1199
1200  // The processed security options portion of the specification.
1201  private final SecurityOptions securityOptionsSpec;
1202
1203  // The server set that will be used to create connections.
1204  private final ServerSet serverSet;
1205
1206
1207
1208  /**
1209   * Creates a new LDAP connection details object from the specification
1210   * contained in the provided JSON object.
1211   *
1212   * @param  connectionDetailsObject  The JSON object that contains information
1213   *                                  that may be used to create LDAP
1214   *                                  connections.
1215   *
1216   * @throws  LDAPException  If the provided JSON object does not contain a
1217   *                         valid connection details specification.
1218   */
1219  public LDAPConnectionDetailsJSONSpecification(
1220              final JSONObject connectionDetailsObject)
1221         throws LDAPException
1222  {
1223    validateTopLevelFields(connectionDetailsObject);
1224
1225    try
1226    {
1227      securityOptionsSpec = new SecurityOptions(connectionDetailsObject);
1228    }
1229    catch (final LDAPException le)
1230    {
1231      Debug.debugException(le);
1232      throw new LDAPException(le.getResultCode(),
1233           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1234                FIELD_COMMUNICATION_SECURITY, le.getMessage()),
1235           le);
1236    }
1237
1238    final ConnectionOptions connectionOptionsSpec;
1239    try
1240    {
1241      connectionOptionsSpec = new ConnectionOptions(connectionDetailsObject);
1242    }
1243    catch (final LDAPException le)
1244    {
1245      Debug.debugException(le);
1246      throw new LDAPException(le.getResultCode(),
1247           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1248                FIELD_CONNECTION_OPTIONS, le.getMessage()),
1249           le);
1250    }
1251
1252    try
1253    {
1254      final ServerDetails serverDetailsSpec =
1255           new ServerDetails(connectionDetailsObject, securityOptionsSpec,
1256                connectionOptionsSpec);
1257      serverSet = serverDetailsSpec.getServerSet();
1258    }
1259    catch (final LDAPException le)
1260    {
1261      Debug.debugException(le);
1262      throw new LDAPException(le.getResultCode(),
1263           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1264                FIELD_SERVER_DETAILS, le.getMessage()),
1265           le);
1266    }
1267
1268    try
1269    {
1270      final AuthenticationDetails authenticationDetailsSpec =
1271           new AuthenticationDetails(connectionDetailsObject);
1272      bindRequest = authenticationDetailsSpec.getBindRequest();
1273    }
1274    catch (final LDAPException le)
1275    {
1276      Debug.debugException(le);
1277      throw new LDAPException(le.getResultCode(),
1278           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1279                FIELD_AUTHENTICATION_DETAILS, le.getMessage()),
1280           le);
1281    }
1282
1283    try
1284    {
1285      connectionPoolOptionsSpec =
1286           new ConnectionPoolOptions(connectionDetailsObject);
1287    }
1288    catch (final LDAPException le)
1289    {
1290      Debug.debugException(le);
1291      throw new LDAPException(le.getResultCode(),
1292           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1293                FIELD_CONNECTION_POOL_OPTIONS, le.getMessage()),
1294           le);
1295    }
1296  }
1297
1298
1299
1300  /**
1301   * Creates a new LDAP connection details object from the specification
1302   * contained in the JSON object represented by the given string.
1303   *
1304   * @param  jsonString  The string representation of the JSON object that
1305   *                     contains information that may be used to create LDAP
1306   *                     connections.
1307   *
1308   * @return  The LDAP connection details object parsed from the provided
1309   *          JSON object string.
1310   *
1311   * @throws  JSONException  If the provided string cannot be parsed as a valid
1312   *                         JSON object.
1313   *
1314   * @throws  LDAPException  If the parsed JSON object does not contain a valid
1315   *                         connection details specification.
1316   */
1317  public static LDAPConnectionDetailsJSONSpecification fromString(
1318                     final String jsonString)
1319         throws JSONException, LDAPException
1320  {
1321    return new LDAPConnectionDetailsJSONSpecification(
1322         new JSONObject(jsonString));
1323  }
1324
1325
1326
1327  /**
1328   * Creates a new LDAP connection details object from the specification
1329   * contained in the JSON object read from the indicated file.
1330   *
1331   * @param  path  The path to a file containing a JSON object with information
1332   *               that may be used to create LDAP connections.
1333   *
1334   * @return  The LDAP connection details object parsed from the information in
1335   *          the specified file.
1336   *
1337   * @throws  IOException  If a problem is encountered while reading from the
1338   *                       specified file.
1339   *
1340   * @throws  JSONException  If the contents of the specified file cannot be
1341   *                         parsed as a valid JSON object.
1342   *
1343   * @throws  LDAPException  If the parsed JSON object does not contain a valid
1344   *                         connection details specification.
1345   */
1346  public static LDAPConnectionDetailsJSONSpecification fromFile(
1347                                                            final String path)
1348         throws IOException, JSONException, LDAPException
1349  {
1350    return fromFile(new File(path));
1351  }
1352
1353
1354
1355  /**
1356   * Creates a new LDAP connection details object from the specification
1357   * contained in the JSON object read from the indicated file.
1358   *
1359   * @param  file  The file containing a JSON object with information that may
1360   *               be used to create LDAP connections.
1361   *
1362   * @return  The LDAP connection details object parsed from the information in
1363   *          the specified file.
1364   *
1365   * @throws  IOException  If a problem is encountered while reading from the
1366   *                       specified file.
1367   *
1368   * @throws  JSONException  If the contents of the specified file cannot be
1369   *                         parsed as a valid JSON object.
1370   *
1371   * @throws  LDAPException  If the parsed JSON object does not contain a valid
1372   *                         connection details specification.
1373   */
1374  public static LDAPConnectionDetailsJSONSpecification fromFile(final File file)
1375         throws IOException, JSONException, LDAPException
1376  {
1377    return fromInputStream(new FileInputStream(file));
1378  }
1379
1380
1381
1382  /**
1383   * Creates a new LDAP connection details object from the specification
1384   * contained in the JSON object read from the provided input stream.  The
1385   * entire contents of the stream must be exactly one JSON object.  Because the
1386   * input stream will be fully read, it will always be closed by this method.
1387   *
1388   * @param  inputStream  The input stream from which to read a JSON object with
1389   *                      information that may be used to create LDAP
1390   *                      connections.  The entire contents of the stream must
1391   *                      be exactly one JSON object.  Because the input stream
1392   *                      will be fully read, it will always be closed by this
1393   *                      method.
1394   *
1395   * @return  The LDAP connection details object parsed from the information
1396   *          read from the provided input stream.
1397   *
1398   * @throws  IOException  If a problem is encountered while reading from the
1399   *                       provided input stream.
1400   *
1401   * @throws  JSONException  If the contents of the specified file cannot be
1402   *                         parsed as a valid JSON object.
1403   *
1404   * @throws  LDAPException  If the parsed JSON object does not contain a valid
1405   *                         connection details specification.
1406   */
1407  public static LDAPConnectionDetailsJSONSpecification fromInputStream(
1408                     final InputStream inputStream)
1409         throws IOException, JSONException, LDAPException
1410  {
1411    try
1412    {
1413      final ByteStringBuffer b = new ByteStringBuffer();
1414      final byte[] readBuffer = new byte[8192];
1415      while (true)
1416      {
1417        final int bytesRead = inputStream.read(readBuffer);
1418        if (bytesRead < 0)
1419        {
1420          break;
1421        }
1422        else
1423        {
1424          b.append(readBuffer, 0, bytesRead);
1425        }
1426      }
1427
1428      return new LDAPConnectionDetailsJSONSpecification(
1429           new JSONObject(b.toString()));
1430    }
1431    finally
1432    {
1433      inputStream.close();
1434    }
1435  }
1436
1437
1438
1439  /**
1440   * Retrieves the server set that may be used to create new connections based
1441   * on the JSON specification.
1442   *
1443   * @return  The server set that may be used to create new connections based on
1444   *          the JSON specification.
1445   */
1446  public ServerSet getServerSet()
1447  {
1448    return serverSet;
1449  }
1450
1451
1452
1453  /**
1454   * Retrieves the bind request that may be used to authenticate connections
1455   * created from the JSON specification.
1456   *
1457   * @return  The bind request that may be used to authenticate connections
1458   *          created from the JSON specification, or {@code null} if the
1459   *          connections should be unauthenticated.
1460   */
1461  public BindRequest getBindRequest()
1462  {
1463    return bindRequest;
1464  }
1465
1466
1467
1468  /**
1469   * Creates a new LDAP connection based on the JSON specification.  The
1470   * connection will be authenticated if appropriate.
1471   *
1472   * @return  The LDAP connection that was created.
1473   *
1474   * @throws  LDAPException  If a problem is encountered while trying to
1475   *                         establish or authenticate the connection.
1476   */
1477  public LDAPConnection createConnection()
1478         throws LDAPException
1479  {
1480    final LDAPConnection connection = createUnauthenticatedConnection();
1481
1482    if (bindRequest != null)
1483    {
1484      try
1485      {
1486        connection.bind(bindRequest);
1487      }
1488      catch (final LDAPException le)
1489      {
1490        Debug.debugException(le);
1491        connection.close();
1492        throw le;
1493      }
1494    }
1495
1496    return connection;
1497  }
1498
1499
1500
1501  /**
1502   * Creates a new LDAP connection based on the JSON specification.  No
1503   * authentication will be performed on the connection.
1504   *
1505   * @return  The LDAP connection that was created.
1506   *
1507   * @throws  LDAPException  If a problem is encountered while trying to
1508   *                         establish the connection.
1509   */
1510  public LDAPConnection createUnauthenticatedConnection()
1511         throws LDAPException
1512  {
1513    return serverSet.getConnection();
1514  }
1515
1516
1517
1518  /**
1519   * Creates a new LDAP connection pool based on the JSON specification.  The
1520   * pooled connections will be authenticated if appropriate.
1521   *
1522   * @param  initialConnections  The number of connections that should be
1523   *                             established at the time the pool is created.
1524   * @param  maximumConnections  The maximum number of connections that should
1525   *                             be available in the pool at any time.
1526   *
1527   * @return  The LDAP connection pool that was created.
1528   *
1529   * @throws  LDAPException  If a problem is encountered while attempting to
1530   *                         create the connection pool.
1531   */
1532  public LDAPConnectionPool createConnectionPool(final int initialConnections,
1533                                                 final int maximumConnections)
1534         throws LDAPException
1535  {
1536    final LDAPConnectionPool connectionPool = new LDAPConnectionPool(serverSet,
1537         bindRequest, initialConnections, maximumConnections,
1538         connectionPoolOptionsSpec.getInitialConnectThreads(),
1539         securityOptionsSpec.getPostConnectProcessor(), false,
1540         connectionPoolOptionsSpec.getHealthCheck());
1541
1542    connectionPoolOptionsSpec.applyConnectionPoolSettings(connectionPool);
1543    return connectionPool;
1544  }
1545
1546
1547
1548  /**
1549   * Creates a new LDAP connection pool based on the JSON specification.  No
1550   * authentication will be used for connections that are part of the pool.
1551   *
1552   * @param  initialConnections  The number of connections that should be
1553   *                             established at the time the pool is created.
1554   * @param  maximumConnections  The maximum number of connections that should
1555   *                             be available in the pool at any time.
1556   *
1557   * @return  The LDAP connection pool that was created.
1558   *
1559   * @throws  LDAPException  If a problem is encountered while attempting to
1560   *                         create the connection pool.
1561   */
1562  public LDAPConnectionPool createUnauthenticatedConnectionPool(
1563                                 final int initialConnections,
1564                                 final int maximumConnections)
1565       throws LDAPException
1566  {
1567    final LDAPConnectionPool connectionPool = new LDAPConnectionPool(serverSet,
1568         null, initialConnections, maximumConnections,
1569         connectionPoolOptionsSpec.getInitialConnectThreads(),
1570         securityOptionsSpec.getPostConnectProcessor(), false,
1571         connectionPoolOptionsSpec.getHealthCheck());
1572
1573    connectionPoolOptionsSpec.applyConnectionPoolSettings(connectionPool);
1574    return connectionPool;
1575  }
1576
1577
1578
1579  /**
1580   * Validates the top-level fields in the provided JSON object to ensure that
1581   * all required fields are present and no unrecognized fields are present.
1582   *
1583   * @param  o  The JSON object to validate.
1584   *
1585   * @throws  LDAPException  If there is a problem with the set of top-level
1586   *                         fields in the provided JSON object.
1587   */
1588  private static void validateTopLevelFields(final JSONObject o)
1589          throws LDAPException
1590  {
1591    boolean serverDetailsProvided = false;
1592    for (final String s : o.getFields().keySet())
1593    {
1594      if (s.equals(FIELD_SERVER_DETAILS))
1595      {
1596        // This is a required top-level field.
1597        serverDetailsProvided = true;
1598      }
1599      else if (s.equals(FIELD_CONNECTION_OPTIONS) ||
1600           s.equals(FIELD_COMMUNICATION_SECURITY) ||
1601           s.equals(FIELD_AUTHENTICATION_DETAILS) ||
1602           s.equals(FIELD_CONNECTION_POOL_OPTIONS))
1603      {
1604        // These are optional top-level fields.
1605      }
1606      else
1607      {
1608        // This is not a valid top-level field.
1609        throw new LDAPException(ResultCode.PARAM_ERROR,
1610             ERR_LDAP_SPEC_UNRECOGNIZED_TOP_LEVEL_FIELD.get(s));
1611      }
1612    }
1613
1614    if (! serverDetailsProvided)
1615    {
1616      throw new LDAPException(ResultCode.PARAM_ERROR,
1617           ERR_LDAP_SPEC_MISSING_SERVER_DETAILS.get(FIELD_SERVER_DETAILS));
1618    }
1619  }
1620
1621
1622
1623  /**
1624   * Validates that the set of fields contained in the JSON object that is the
1625   * value of the indicated field.
1626   *
1627   * @param  o  The JSON object to validate.
1628   * @param  f  The name of the field whose value is the provided JSON object.
1629   * @param  a  The names of the fields that are allowed to be present.
1630   *
1631   * @throws  LDAPException  If the provided JSON object contains any fields
1632   *                         that are not contained in the allowed set.
1633   */
1634  static void validateAllowedFields(final JSONObject o, final String f,
1635                                    final String... a)
1636         throws LDAPException
1637  {
1638    final HashSet<String> s = new HashSet<>(Arrays.asList(a));
1639    for (final String n : o.getFields().keySet())
1640    {
1641      if (! s.contains(n))
1642      {
1643        throw new LDAPException(ResultCode.PARAM_ERROR,
1644             ERR_LDAP_SPEC_UNRECOGNIZED_FIELD.get(n, f));
1645      }
1646    }
1647  }
1648
1649
1650
1651  /**
1652   * Retrieves the value of the specified JSON object field as a boolean.
1653   *
1654   * @param  o  The object from which to retrieve the boolean value.
1655   * @param  f  The name of the field to retrieve.
1656   * @param  d  The default value to return if the specified field does not
1657   *            exist.
1658   *
1659   * @return  The requested boolean value.
1660   *
1661   * @throws  LDAPException  If the specified field exists but is not a boolean.
1662   */
1663  static boolean getBoolean(final JSONObject o, final String f, final boolean d)
1664         throws LDAPException
1665  {
1666    final JSONValue v = o.getField(f);
1667    if (v == null)
1668    {
1669      return d;
1670    }
1671
1672    if (v instanceof JSONBoolean)
1673    {
1674      return ((JSONBoolean) v).booleanValue();
1675    }
1676    else
1677    {
1678      throw new LDAPException(ResultCode.PARAM_ERROR,
1679           ERR_LDAP_SPEC_VALUE_NOT_BOOLEAN.get(f));
1680    }
1681  }
1682
1683
1684
1685  /**
1686   * Retrieves the value of the specified JSON object field as an integer.
1687   *
1688   * @param  o  The object from which to retrieve the integer value.
1689   * @param  f  The name of the field to retrieve.
1690   * @param  d  The default value to return if the specified field does not
1691   *            exist.
1692   * @param  n  The minimum allowed value for the field, if any.
1693   * @param  x  The maximum allowed value for the field, if any.
1694   *
1695   * @return  The requested integer value.
1696   *
1697   * @throws  LDAPException  If the specified field exists but is not an
1698   *                         integer.
1699   */
1700  static Integer getInt(final JSONObject o, final String f, final Integer d,
1701                        final Integer n, final Integer x)
1702         throws LDAPException
1703  {
1704    final JSONValue v = o.getField(f);
1705    if (v == null)
1706    {
1707      return d;
1708    }
1709
1710    if (v instanceof JSONNumber)
1711    {
1712      try
1713      {
1714        final int i =((JSONNumber) v).getValue().intValueExact();
1715        if ((n != null) && (i < n))
1716        {
1717          throw new LDAPException(ResultCode.PARAM_ERROR,
1718               ERR_LDAP_SPEC_VALUE_BELOW_MIN.get(f, n));
1719        }
1720
1721        if ((x != null) && (i > x))
1722        {
1723          throw new LDAPException(ResultCode.PARAM_ERROR,
1724               ERR_LDAP_SPEC_VALUE_ABOVE_MAX.get(f, n));
1725        }
1726
1727        return i;
1728      }
1729      catch (final LDAPException le)
1730      {
1731        Debug.debugException(le);
1732        throw le;
1733      }
1734      catch (final Exception e)
1735      {
1736        Debug.debugException(e);
1737        throw new LDAPException(ResultCode.PARAM_ERROR,
1738             ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f), e);
1739      }
1740    }
1741    else
1742    {
1743      throw new LDAPException(ResultCode.PARAM_ERROR,
1744           ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f));
1745    }
1746  }
1747
1748
1749
1750  /**
1751   * Retrieves the value of the specified JSON object field as a long.
1752   *
1753   * @param  o  The object from which to retrieve the long value.
1754   * @param  f  The name of the field to retrieve.
1755   * @param  d  The default value to return if the specified field does not
1756   *            exist.
1757   * @param  n  The minimum allowed value for the field, if any.
1758   * @param  x  The maximum allowed value for the field, if any.
1759   *
1760   * @return  The requested long value.
1761   *
1762   * @throws  LDAPException  If the specified field exists but is not a long.
1763   */
1764  static Long getLong(final JSONObject o, final String f, final Long d,
1765                      final Long n, final Long x)
1766         throws LDAPException
1767  {
1768    final JSONValue v = o.getField(f);
1769    if (v == null)
1770    {
1771      return d;
1772    }
1773
1774    if (v instanceof JSONNumber)
1775    {
1776      try
1777      {
1778        final long l =((JSONNumber) v).getValue().longValueExact();
1779        if ((n != null) && (l < n))
1780        {
1781          throw new LDAPException(ResultCode.PARAM_ERROR,
1782               ERR_LDAP_SPEC_VALUE_BELOW_MIN.get(f, n));
1783        }
1784
1785        if ((x != null) && (l > x))
1786        {
1787          throw new LDAPException(ResultCode.PARAM_ERROR,
1788               ERR_LDAP_SPEC_VALUE_ABOVE_MAX.get(f, n));
1789        }
1790
1791        return l;
1792      }
1793      catch (final LDAPException le)
1794      {
1795        Debug.debugException(le);
1796        throw le;
1797      }
1798      catch (final Exception e)
1799      {
1800        Debug.debugException(e);
1801        throw new LDAPException(ResultCode.PARAM_ERROR,
1802             ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f), e);
1803      }
1804    }
1805    else
1806    {
1807      throw new LDAPException(ResultCode.PARAM_ERROR,
1808           ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f));
1809    }
1810  }
1811
1812
1813
1814  /**
1815   * Retrieves the value of the specified JSON object field as an object.
1816   *
1817   * @param  o  The object from which to retrieve the object value.
1818   * @param  f  The name of the field to retrieve.
1819   *
1820   * @return  The requested object value.
1821   *
1822   * @throws  LDAPException  If the specified field exists but is not an object.
1823   */
1824  static JSONObject getObject(final JSONObject o, final String f)
1825         throws LDAPException
1826  {
1827    final JSONValue v = o.getField(f);
1828    if (v == null)
1829    {
1830      return null;
1831    }
1832
1833    if (v instanceof JSONObject)
1834    {
1835      return (JSONObject) v;
1836    }
1837    else
1838    {
1839      throw new LDAPException(ResultCode.PARAM_ERROR,
1840           ERR_LDAP_SPEC_VALUE_NOT_OBJECT.get(f));
1841    }
1842  }
1843
1844
1845
1846  /**
1847   * Retrieves the value of the specified JSON object field as a string.
1848   *
1849   * @param  o  The object from which to retrieve the string value.
1850   * @param  f  The name of the field to retrieve.
1851   * @param  d  The default value to return if the specified field does not
1852   *            exist.
1853   *
1854   * @return  The requested string value.
1855   *
1856   * @throws  LDAPException  If the specified field exists but is not a string.
1857   */
1858  static String getString(final JSONObject o, final String f, final String d)
1859         throws LDAPException
1860  {
1861    final JSONValue v = o.getField(f);
1862    if (v == null)
1863    {
1864      return d;
1865    }
1866
1867    if (v instanceof JSONString)
1868    {
1869      return ((JSONString) v).stringValue();
1870    }
1871    else
1872    {
1873      throw new LDAPException(ResultCode.PARAM_ERROR,
1874           ERR_LDAP_SPEC_VALUE_NOT_STRING.get(f));
1875    }
1876  }
1877
1878
1879
1880  /**
1881   * Retrieves a string value read from the specified file.  The file must
1882   * contain exactly one line, and that line must not be empty.
1883   *
1884   * @param  path       The path to the file from which to read the string.
1885   * @param  fieldName  The name of the field from which the path was obtained.
1886   *
1887   * @return  The string read from the specified file.
1888   *
1889   * @throws  LDAPException  If a problem is encountered while reading from the
1890   *                         specified file, if the file does not contain
1891   *                         exactly one line, or if the line contained in the
1892   *                         file is empty.
1893   */
1894  static String getStringFromFile(final String path, final String fieldName)
1895         throws LDAPException
1896  {
1897    BufferedReader r = null;
1898    try
1899    {
1900      r = new BufferedReader(new FileReader(path));
1901
1902      final String line = r.readLine();
1903      if (line == null)
1904      {
1905        throw new LDAPException(ResultCode.PARAM_ERROR,
1906             ERR_LDAP_SPEC_READ_FILE_EMPTY.get(path, fieldName));
1907      }
1908
1909      if (r.readLine() != null)
1910      {
1911        throw new LDAPException(ResultCode.PARAM_ERROR,
1912             ERR_LDAP_SPEC_READ_FILE_MULTIPLE_LINES.get(path, fieldName));
1913      }
1914
1915      if (line.isEmpty())
1916      {
1917        throw new LDAPException(ResultCode.PARAM_ERROR,
1918             ERR_LDAP_SPEC_READ_FILE_EMPTY_LINE.get(path, fieldName));
1919      }
1920
1921      return line;
1922    }
1923    catch (final LDAPException le)
1924    {
1925      Debug.debugException(le);
1926      throw le;
1927    }
1928    catch (final Exception e)
1929    {
1930      Debug.debugException(e);
1931      throw new LDAPException(ResultCode.PARAM_ERROR,
1932           ERR_LDAP_SPEC_READ_FILE_ERROR.get(path, fieldName,
1933                StaticUtils.getExceptionMessage(e)),
1934           e);
1935    }
1936    finally
1937    {
1938      if (r != null)
1939      {
1940        try
1941        {
1942          r.close();
1943        }
1944        catch (final Exception e)
1945        {
1946          Debug.debugException(e);
1947        }
1948      }
1949    }
1950  }
1951
1952
1953
1954  /**
1955   * Verifies that none of the indicated fields exist in the provided JSON
1956   * object because they would conflict with the specified existing field.
1957   *
1958   * @param  o                  The JSON object to examine.
1959   * @param  existingField      The name of a field known to be present in the
1960   *                            JSON object that cannot coexist with the
1961   *                            indicated conflicting fields.
1962   * @param  conflictingFields  The names of the fields that cannot be used in
1963   *                            conjunction with the specified existing field.
1964   *
1965   * @throws  LDAPException  If the provided JSON object has one or more fields
1966   *                         that conflict with the specified existing field.
1967   */
1968  static void rejectConflictingFields(final JSONObject o,
1969                                      final String existingField,
1970                                      final String... conflictingFields)
1971         throws LDAPException
1972  {
1973    for (final String fieldName : conflictingFields)
1974    {
1975      if (o.getField(fieldName) != null)
1976      {
1977        throw new LDAPException(ResultCode.PARAM_ERROR,
1978             ERR_LDAP_SPEC_CONFLICTING_FIELD.get(fieldName, existingField));
1979      }
1980    }
1981  }
1982
1983
1984
1985  /**
1986   * Verifies that none of the indicated fields exist in the provided JSON
1987   * object because they can only be provided if the specified required field is
1988   * present.
1989   *
1990   * @param  o                The JSON object to examine.
1991   * @param  requiredField    The name of a field known to be missing from the
1992   *                          JSON object, but must be present to allow any of
1993   *                          the indicated dependent fields to be provided.
1994   * @param  dependentFields  The names of the fields that can only be present
1995   *                          if the specified required field is present.
1996   *
1997   * @throws  LDAPException  If the provided JSON object has one or more
1998   *                         unresolved dependencies.
1999   */
2000  static void rejectUnresolvedDependency(final JSONObject o,
2001                                         final String requiredField,
2002                                         final String... dependentFields)
2003         throws LDAPException
2004  {
2005    for (final String fieldName : dependentFields)
2006    {
2007      if (o.getField(fieldName) != null)
2008      {
2009        throw new LDAPException(ResultCode.PARAM_ERROR,
2010             ERR_LDAP_SPEC_MISSING_DEPENDENT_FIELD.get(fieldName,
2011                  requiredField));
2012      }
2013    }
2014  }
2015}