001/*
002 * Copyright 2015-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2017 UnboundID Corp.
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-exception-health-checks" -- Indicates whether the connection pool
1079 *     should invoke health check processing on connections just after an
1080 *     exception is caught that might indicate that the connection is no longer
1081 *     valid.  Note that this only applies to exceptions caught during
1082 *     operations processed directly against the connection pool and not to
1083 *     exceptions caught on a connection checked out of the pool.  If this field
1084 *     is present, then its value must be a boolean.  If it is not present, then
1085 *     a default of {@code true} will be assumed.
1086 *   </LI>
1087 *   <LI>
1088 *     "invoke-release-health-checks" -- Indicates whether the connection pool
1089 *     should invoke health check processing on connections just before they are
1090 *     released back to the pool to ensure that they are valid.  If this field
1091 *     is present, then its value must be a boolean.  If it is not present, then
1092 *     a default of {@code false} will be assumed.
1093 *   </LI>
1094 *   <LI>
1095 *     "maximum-connection-age-millis" -- Specifies the maximum length of time
1096 *     (in milliseconds) that a connection should be allowed to remain
1097 *     established before it is eligible to be closed and replaced with a
1098 *     newly-created connection.  If present, then the value must be a positive
1099 *     integer to specify the maximum age, or zero to indicate that no maximum
1100 *     age should be applied.  If it is not present, then a default value of
1101 *     zero will be used.
1102 *   </LI>
1103 *   <LI>
1104 *     "maximum-defunct-replacement-connection-age-millis" -- Specifies the
1105 *     maximum connection age (in milliseconds) that should be used for
1106 *     connections created to replace a defunct connection.  If present, then
1107 *     the value must be a positive integer to specify the maximum age, or zero
1108 *     to indicate that no maximum age should be applied.  If it is not present,
1109 *     then the value of the "maximum-connection-age-millis" field will be used
1110 *     for connections created as replacements for defunct connections.
1111 *   </LI>
1112 *   <LI>
1113 *     "maximum-wait-time-millis" -- Specifies the maximum length of time (in
1114 *     milliseconds) that the pool should wait for a connection to be released
1115 *     if one is needed but none are immediately available.  If present, then
1116 *     this value must be a positive integer to specify the length of time to
1117 *     wait, or zero to indicate that it should not wait at all.  If it is not
1118 *     provided, then a default value of zero will be used.
1119 *   </LI>
1120 *   <LI>
1121 *     "retry-failed-operations-due-to-invalid-connections" -- Indicates whether
1122 *     the pool should automatically attempt to retry operations attempted
1123 *     directly against the pool (but not for connections checked out of the
1124 *     pool) if the initial attempt fails in a manner that may indicate that the
1125 *     connection is no longer valid.  If this field is present, then its value
1126 *     may be either a boolean to indicate whether to enable retry for all types
1127 *     of operations or no operations, or it may be an array of strings
1128 *     indicating the operation types ("add", "bind", "compare", "delete",
1129 *     "extended", "modify", "modify-dn", or "search") that should be retried
1130 *     in the event of a failure.  If this field is not present, then no
1131 *     automatic retry will be attempted.
1132 *   </LI>
1133 * </UL>
1134 * <BR>
1135 * The "connection-pool-options" field is optional, and if it is omitted from
1136 * the specification then the default values will be used for all options.
1137 */
1138@NotMutable()
1139@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
1140public final class LDAPConnectionDetailsJSONSpecification
1141{
1142  /**
1143   * The name of the top-level field that may be used to provide information to
1144   * use to authenticate connections to the server.
1145   */
1146  static final String FIELD_AUTHENTICATION_DETAILS = "authentication-details";
1147
1148
1149
1150  /**
1151   * The name of the top-level field that may be used to provide information
1152   * about the type of communication security that should be used.
1153   */
1154  static final String FIELD_COMMUNICATION_SECURITY = "communication-security";
1155
1156
1157
1158  /**
1159   * The name of the top-level field that may be used to provide information
1160   * about options that should be set when establishing connections.
1161   */
1162  static final String FIELD_CONNECTION_OPTIONS = "connection-options";
1163
1164
1165
1166  /**
1167   * The name of the top-level field that may be used to provide information
1168   * about options that should be set when creating a connection pool.
1169   */
1170  static final String FIELD_CONNECTION_POOL_OPTIONS =
1171       "connection-pool-options";
1172
1173
1174
1175  /**
1176   * The name of the top-level field that may be used to provide information
1177   * about the directory server(s) to which the connection should be
1178   * established.
1179   */
1180  static final String FIELD_SERVER_DETAILS = "server-details";
1181
1182
1183
1184  // The bind request that will be used to authenticate connections.
1185  private final BindRequest bindRequest;
1186
1187  // The processed connection pool options portion of the specification.
1188  private final ConnectionPoolOptions connectionPoolOptionsSpec;
1189
1190  // The processed security options portion of the specification.
1191  private final SecurityOptions securityOptionsSpec;
1192
1193  // The server set that will be used to create connections.
1194  private final ServerSet serverSet;
1195
1196
1197
1198  /**
1199   * Creates a new LDAP connection details object from the specification
1200   * contained in the provided JSON object.
1201   *
1202   * @param  connectionDetailsObject  The JSON object that contains information
1203   *                                  that may be used to create LDAP
1204   *                                  connections.
1205   *
1206   * @throws  LDAPException  If the provided JSON object does not contain a
1207   *                         valid connection details specification.
1208   */
1209  public LDAPConnectionDetailsJSONSpecification(
1210              final JSONObject connectionDetailsObject)
1211         throws LDAPException
1212  {
1213    validateTopLevelFields(connectionDetailsObject);
1214
1215    try
1216    {
1217      securityOptionsSpec = new SecurityOptions(connectionDetailsObject);
1218    }
1219    catch (final LDAPException le)
1220    {
1221      Debug.debugException(le);
1222      throw new LDAPException(le.getResultCode(),
1223           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1224                FIELD_COMMUNICATION_SECURITY, le.getMessage()),
1225           le);
1226    }
1227
1228    final ConnectionOptions connectionOptionsSpec;
1229    try
1230    {
1231      connectionOptionsSpec = new ConnectionOptions(connectionDetailsObject);
1232    }
1233    catch (final LDAPException le)
1234    {
1235      Debug.debugException(le);
1236      throw new LDAPException(le.getResultCode(),
1237           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1238                FIELD_CONNECTION_OPTIONS, le.getMessage()),
1239           le);
1240    }
1241
1242    try
1243    {
1244      final ServerDetails serverDetailsSpec =
1245           new ServerDetails(connectionDetailsObject, securityOptionsSpec,
1246                connectionOptionsSpec);
1247      serverSet = serverDetailsSpec.getServerSet();
1248    }
1249    catch (final LDAPException le)
1250    {
1251      Debug.debugException(le);
1252      throw new LDAPException(le.getResultCode(),
1253           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1254                FIELD_SERVER_DETAILS, le.getMessage()),
1255           le);
1256    }
1257
1258    try
1259    {
1260      final AuthenticationDetails authenticationDetailsSpec =
1261           new AuthenticationDetails(connectionDetailsObject);
1262      bindRequest = authenticationDetailsSpec.getBindRequest();
1263    }
1264    catch (final LDAPException le)
1265    {
1266      Debug.debugException(le);
1267      throw new LDAPException(le.getResultCode(),
1268           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1269                FIELD_AUTHENTICATION_DETAILS, le.getMessage()),
1270           le);
1271    }
1272
1273    try
1274    {
1275      connectionPoolOptionsSpec =
1276           new ConnectionPoolOptions(connectionDetailsObject);
1277    }
1278    catch (final LDAPException le)
1279    {
1280      Debug.debugException(le);
1281      throw new LDAPException(le.getResultCode(),
1282           ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get(
1283                FIELD_CONNECTION_POOL_OPTIONS, le.getMessage()),
1284           le);
1285    }
1286  }
1287
1288
1289
1290  /**
1291   * Creates a new LDAP connection details object from the specification
1292   * contained in the JSON object represented by the given string.
1293   *
1294   * @param  jsonString  The string representation of the JSON object that
1295   *                     contains information that may be used to create LDAP
1296   *                     connections.
1297   *
1298   * @return  The LDAP connection details object parsed from the provided
1299   *          JSON object string.
1300   *
1301   * @throws  JSONException  If the provided string cannot be parsed as a valid
1302   *                         JSON object.
1303   *
1304   * @throws  LDAPException  If the parsed JSON object does not contain a valid
1305   *                         connection details specification.
1306   */
1307  public static LDAPConnectionDetailsJSONSpecification fromString(
1308                     final String jsonString)
1309         throws JSONException, LDAPException
1310  {
1311    return new LDAPConnectionDetailsJSONSpecification(
1312         new JSONObject(jsonString));
1313  }
1314
1315
1316
1317  /**
1318   * Creates a new LDAP connection details object from the specification
1319   * contained in the JSON object read from the indicated file.
1320   *
1321   * @param  path  The path to a file containing a JSON object with information
1322   *               that may be used to create LDAP connections.
1323   *
1324   * @return  The LDAP connection details object parsed from the information in
1325   *          the specified file.
1326   *
1327   * @throws  IOException  If a problem is encountered while reading from the
1328   *                       specified file.
1329   *
1330   * @throws  JSONException  If the contents of the specified file cannot be
1331   *                         parsed as a valid JSON object.
1332   *
1333   * @throws  LDAPException  If the parsed JSON object does not contain a valid
1334   *                         connection details specification.
1335   */
1336  public static LDAPConnectionDetailsJSONSpecification fromFile(
1337                                                            final String path)
1338         throws IOException, JSONException, LDAPException
1339  {
1340    return fromFile(new File(path));
1341  }
1342
1343
1344
1345  /**
1346   * Creates a new LDAP connection details object from the specification
1347   * contained in the JSON object read from the indicated file.
1348   *
1349   * @param  file  The file containing a JSON object with information that may
1350   *               be used to create LDAP connections.
1351   *
1352   * @return  The LDAP connection details object parsed from the information in
1353   *          the specified file.
1354   *
1355   * @throws  IOException  If a problem is encountered while reading from the
1356   *                       specified file.
1357   *
1358   * @throws  JSONException  If the contents of the specified file cannot be
1359   *                         parsed as a valid JSON object.
1360   *
1361   * @throws  LDAPException  If the parsed JSON object does not contain a valid
1362   *                         connection details specification.
1363   */
1364  public static LDAPConnectionDetailsJSONSpecification fromFile(final File file)
1365         throws IOException, JSONException, LDAPException
1366  {
1367    return fromInputStream(new FileInputStream(file));
1368  }
1369
1370
1371
1372  /**
1373   * Creates a new LDAP connection details object from the specification
1374   * contained in the JSON object read from the provided input stream.  The
1375   * entire contents of the stream must be exactly one JSON object.  Because the
1376   * input stream will be fully read, it will always be closed by this method.
1377   *
1378   * @param  inputStream  The input stream from which to read a JSON object with
1379   *                      information that may be used to create LDAP
1380   *                      connections.  The entire contents of the stream must
1381   *                      be exactly one JSON object.  Because the input stream
1382   *                      will be fully read, it will always be closed by this
1383   *                      method.
1384   *
1385   * @return  The LDAP connection details object parsed from the information
1386   *          read from the provided input stream.
1387   *
1388   * @throws  IOException  If a problem is encountered while reading from the
1389   *                       provided input stream.
1390   *
1391   * @throws  JSONException  If the contents of the specified file cannot be
1392   *                         parsed as a valid JSON object.
1393   *
1394   * @throws  LDAPException  If the parsed JSON object does not contain a valid
1395   *                         connection details specification.
1396   */
1397  public static LDAPConnectionDetailsJSONSpecification fromInputStream(
1398                     final InputStream inputStream)
1399         throws IOException, JSONException, LDAPException
1400  {
1401    try
1402    {
1403      final ByteStringBuffer b = new ByteStringBuffer();
1404      final byte[] readBuffer = new byte[8192];
1405      while (true)
1406      {
1407        final int bytesRead = inputStream.read(readBuffer);
1408        if (bytesRead < 0)
1409        {
1410          break;
1411        }
1412        else
1413        {
1414          b.append(readBuffer, 0, bytesRead);
1415        }
1416      }
1417
1418      return new LDAPConnectionDetailsJSONSpecification(
1419           new JSONObject(b.toString()));
1420    }
1421    finally
1422    {
1423      inputStream.close();
1424    }
1425  }
1426
1427
1428
1429  /**
1430   * Retrieves the server set that may be used to create new connections based
1431   * on the JSON specification.
1432   *
1433   * @return  The server set that may be used to create new connections based on
1434   *          the JSON specification.
1435   */
1436  public ServerSet getServerSet()
1437  {
1438    return serverSet;
1439  }
1440
1441
1442
1443  /**
1444   * Retrieves the bind request that may be used to authenticate connections
1445   * created from the JSON specification.
1446   *
1447   * @return  The bind request that may be used to authenticate connections
1448   *          created from the JSON specification, or {@code null} if the
1449   *          connections should be unauthenticated.
1450   */
1451  public BindRequest getBindRequest()
1452  {
1453    return bindRequest;
1454  }
1455
1456
1457
1458  /**
1459   * Creates a new LDAP connection based on the JSON specification.  The
1460   * connection will be authenticated if appropriate.
1461   *
1462   * @return  The LDAP connection that was created.
1463   *
1464   * @throws  LDAPException  If a problem is encountered while trying to
1465   *                         establish or authenticate the connection.
1466   */
1467  public LDAPConnection createConnection()
1468         throws LDAPException
1469  {
1470    final LDAPConnection connection = createUnauthenticatedConnection();
1471
1472    if (bindRequest != null)
1473    {
1474      try
1475      {
1476        connection.bind(bindRequest);
1477      }
1478      catch (final LDAPException le)
1479      {
1480        Debug.debugException(le);
1481        connection.close();
1482        throw le;
1483      }
1484    }
1485
1486    return connection;
1487  }
1488
1489
1490
1491  /**
1492   * Creates a new LDAP connection based on the JSON specification.  No
1493   * authentication will be performed on the connection.
1494   *
1495   * @return  The LDAP connection that was created.
1496   *
1497   * @throws  LDAPException  If a problem is encountered while trying to
1498   *                         establish the connection.
1499   */
1500  public LDAPConnection createUnauthenticatedConnection()
1501         throws LDAPException
1502  {
1503    return serverSet.getConnection();
1504  }
1505
1506
1507
1508  /**
1509   * Creates a new LDAP connection pool based on the JSON specification.  The
1510   * pooled connections will be authenticated if appropriate.
1511   *
1512   * @param  initialConnections  The number of connections that should be
1513   *                             established at the time the pool is created.
1514   * @param  maximumConnections  The maximum number of connections that should
1515   *                             be available in the pool at any time.
1516   *
1517   * @return  The LDAP connection pool that was created.
1518   *
1519   * @throws  LDAPException  If a problem is encountered while attempting to
1520   *                         create the connection pool.
1521   */
1522  public LDAPConnectionPool createConnectionPool(final int initialConnections,
1523                                                 final int maximumConnections)
1524         throws LDAPException
1525  {
1526    final LDAPConnectionPool connectionPool = new LDAPConnectionPool(serverSet,
1527         bindRequest, initialConnections, maximumConnections,
1528         connectionPoolOptionsSpec.getInitialConnectThreads(),
1529         securityOptionsSpec.getPostConnectProcessor(), false,
1530         connectionPoolOptionsSpec.getHealthCheck());
1531
1532    connectionPoolOptionsSpec.applyConnectionPoolSettings(connectionPool);
1533    return connectionPool;
1534  }
1535
1536
1537
1538  /**
1539   * Creates a new LDAP connection pool based on the JSON specification.  No
1540   * authentication will be used for connections that are part of the pool.
1541   *
1542   * @param  initialConnections  The number of connections that should be
1543   *                             established at the time the pool is created.
1544   * @param  maximumConnections  The maximum number of connections that should
1545   *                             be available in the pool at any time.
1546   *
1547   * @return  The LDAP connection pool that was created.
1548   *
1549   * @throws  LDAPException  If a problem is encountered while attempting to
1550   *                         create the connection pool.
1551   */
1552  public LDAPConnectionPool createUnauthenticatedConnectionPool(
1553                                 final int initialConnections,
1554                                 final int maximumConnections)
1555       throws LDAPException
1556  {
1557    final LDAPConnectionPool connectionPool = new LDAPConnectionPool(serverSet,
1558         null, initialConnections, maximumConnections,
1559         connectionPoolOptionsSpec.getInitialConnectThreads(),
1560         securityOptionsSpec.getPostConnectProcessor(), false,
1561         connectionPoolOptionsSpec.getHealthCheck());
1562
1563    connectionPoolOptionsSpec.applyConnectionPoolSettings(connectionPool);
1564    return connectionPool;
1565  }
1566
1567
1568
1569  /**
1570   * Validates the top-level fields in the provided JSON object to ensure that
1571   * all required fields are present and no unrecognized fields are present.
1572   *
1573   * @param  o  The JSON object to validate.
1574   *
1575   * @throws  LDAPException  If there is a problem with the set of top-level
1576   *                         fields in the provided JSON object.
1577   */
1578  private static void validateTopLevelFields(final JSONObject o)
1579          throws LDAPException
1580  {
1581    boolean serverDetailsProvided = false;
1582    for (final String s : o.getFields().keySet())
1583    {
1584      if (s.equals(FIELD_SERVER_DETAILS))
1585      {
1586        // This is a required top-level field.
1587        serverDetailsProvided = true;
1588      }
1589      else if (s.equals(FIELD_CONNECTION_OPTIONS) ||
1590           s.equals(FIELD_COMMUNICATION_SECURITY) ||
1591           s.equals(FIELD_AUTHENTICATION_DETAILS) ||
1592           s.equals(FIELD_CONNECTION_POOL_OPTIONS))
1593      {
1594        // These are optional top-level fields.
1595      }
1596      else
1597      {
1598        // This is not a valid top-level field.
1599        throw new LDAPException(ResultCode.PARAM_ERROR,
1600             ERR_LDAP_SPEC_UNRECOGNIZED_TOP_LEVEL_FIELD.get(s));
1601      }
1602    }
1603
1604    if (! serverDetailsProvided)
1605    {
1606      throw new LDAPException(ResultCode.PARAM_ERROR,
1607           ERR_LDAP_SPEC_MISSING_SERVER_DETAILS.get(FIELD_SERVER_DETAILS));
1608    }
1609  }
1610
1611
1612
1613  /**
1614   * Validates that the set of fields contained in the JSON object that is the
1615   * value of the indicated field.
1616   *
1617   * @param  o  The JSON object to validate.
1618   * @param  f  The name of the field whose value is the provided JSON object.
1619   * @param  a  The names of the fields that are allowed to be present.
1620   *
1621   * @throws  LDAPException  If the provided JSON object contains any fields
1622   *                         that are not contained in the allowed set.
1623   */
1624  static void validateAllowedFields(final JSONObject o, final String f,
1625                                    final String... a)
1626         throws LDAPException
1627  {
1628    final HashSet<String> s = new HashSet<String>(Arrays.asList(a));
1629    for (final String n : o.getFields().keySet())
1630    {
1631      if (! s.contains(n))
1632      {
1633        throw new LDAPException(ResultCode.PARAM_ERROR,
1634             ERR_LDAP_SPEC_UNRECOGNIZED_FIELD.get(n, f));
1635      }
1636    }
1637  }
1638
1639
1640
1641  /**
1642   * Retrieves the value of the specified JSON object field as a boolean.
1643   *
1644   * @param  o  The object from which to retrieve the boolean value.
1645   * @param  f  The name of the field to retrieve.
1646   * @param  d  The default value to return if the specified field does not
1647   *            exist.
1648   *
1649   * @return  The requested boolean value.
1650   *
1651   * @throws  LDAPException  If the specified field exists but is not a boolean.
1652   */
1653  static boolean getBoolean(final JSONObject o, final String f, final boolean d)
1654         throws LDAPException
1655  {
1656    final JSONValue v = o.getField(f);
1657    if (v == null)
1658    {
1659      return d;
1660    }
1661
1662    if (v instanceof JSONBoolean)
1663    {
1664      return ((JSONBoolean) v).booleanValue();
1665    }
1666    else
1667    {
1668      throw new LDAPException(ResultCode.PARAM_ERROR,
1669           ERR_LDAP_SPEC_VALUE_NOT_BOOLEAN.get(f));
1670    }
1671  }
1672
1673
1674
1675  /**
1676   * Retrieves the value of the specified JSON object field as an integer.
1677   *
1678   * @param  o  The object from which to retrieve the integer value.
1679   * @param  f  The name of the field to retrieve.
1680   * @param  d  The default value to return if the specified field does not
1681   *            exist.
1682   * @param  n  The minimum allowed value for the field, if any.
1683   * @param  x  The maximum allowed value for the field, if any.
1684   *
1685   * @return  The requested integer value.
1686   *
1687   * @throws  LDAPException  If the specified field exists but is not an
1688   *                         integer.
1689   */
1690  static Integer getInt(final JSONObject o, final String f, final Integer d,
1691                        final Integer n, final Integer x)
1692         throws LDAPException
1693  {
1694    final JSONValue v = o.getField(f);
1695    if (v == null)
1696    {
1697      return d;
1698    }
1699
1700    if (v instanceof JSONNumber)
1701    {
1702      try
1703      {
1704        final int i =((JSONNumber) v).getValue().intValueExact();
1705        if ((n != null) && (i < n))
1706        {
1707          throw new LDAPException(ResultCode.PARAM_ERROR,
1708               ERR_LDAP_SPEC_VALUE_BELOW_MIN.get(f, n));
1709        }
1710
1711        if ((x != null) && (i > x))
1712        {
1713          throw new LDAPException(ResultCode.PARAM_ERROR,
1714               ERR_LDAP_SPEC_VALUE_ABOVE_MAX.get(f, n));
1715        }
1716
1717        return i;
1718      }
1719      catch (final LDAPException le)
1720      {
1721        Debug.debugException(le);
1722        throw le;
1723      }
1724      catch (final Exception e)
1725      {
1726        Debug.debugException(e);
1727        throw new LDAPException(ResultCode.PARAM_ERROR,
1728             ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f), e);
1729      }
1730    }
1731    else
1732    {
1733      throw new LDAPException(ResultCode.PARAM_ERROR,
1734           ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f));
1735    }
1736  }
1737
1738
1739
1740  /**
1741   * Retrieves the value of the specified JSON object field as a long.
1742   *
1743   * @param  o  The object from which to retrieve the long value.
1744   * @param  f  The name of the field to retrieve.
1745   * @param  d  The default value to return if the specified field does not
1746   *            exist.
1747   * @param  n  The minimum allowed value for the field, if any.
1748   * @param  x  The maximum allowed value for the field, if any.
1749   *
1750   * @return  The requested long value.
1751   *
1752   * @throws  LDAPException  If the specified field exists but is not a long.
1753   */
1754  static Long getLong(final JSONObject o, final String f, final Long d,
1755                      final Long n, final Long x)
1756         throws LDAPException
1757  {
1758    final JSONValue v = o.getField(f);
1759    if (v == null)
1760    {
1761      return d;
1762    }
1763
1764    if (v instanceof JSONNumber)
1765    {
1766      try
1767      {
1768        final long l =((JSONNumber) v).getValue().longValueExact();
1769        if ((n != null) && (l < n))
1770        {
1771          throw new LDAPException(ResultCode.PARAM_ERROR,
1772               ERR_LDAP_SPEC_VALUE_BELOW_MIN.get(f, n));
1773        }
1774
1775        if ((x != null) && (l > x))
1776        {
1777          throw new LDAPException(ResultCode.PARAM_ERROR,
1778               ERR_LDAP_SPEC_VALUE_ABOVE_MAX.get(f, n));
1779        }
1780
1781        return l;
1782      }
1783      catch (final LDAPException le)
1784      {
1785        Debug.debugException(le);
1786        throw le;
1787      }
1788      catch (final Exception e)
1789      {
1790        Debug.debugException(e);
1791        throw new LDAPException(ResultCode.PARAM_ERROR,
1792             ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f), e);
1793      }
1794    }
1795    else
1796    {
1797      throw new LDAPException(ResultCode.PARAM_ERROR,
1798           ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f));
1799    }
1800  }
1801
1802
1803
1804  /**
1805   * Retrieves the value of the specified JSON object field as an object.
1806   *
1807   * @param  o  The object from which to retrieve the object value.
1808   * @param  f  The name of the field to retrieve.
1809   *
1810   * @return  The requested object value.
1811   *
1812   * @throws  LDAPException  If the specified field exists but is not an object.
1813   */
1814  static JSONObject getObject(final JSONObject o, final String f)
1815         throws LDAPException
1816  {
1817    final JSONValue v = o.getField(f);
1818    if (v == null)
1819    {
1820      return null;
1821    }
1822
1823    if (v instanceof JSONObject)
1824    {
1825      return (JSONObject) v;
1826    }
1827    else
1828    {
1829      throw new LDAPException(ResultCode.PARAM_ERROR,
1830           ERR_LDAP_SPEC_VALUE_NOT_OBJECT.get(f));
1831    }
1832  }
1833
1834
1835
1836  /**
1837   * Retrieves the value of the specified JSON object field as a string.
1838   *
1839   * @param  o  The object from which to retrieve the string value.
1840   * @param  f  The name of the field to retrieve.
1841   * @param  d  The default value to return if the specified field does not
1842   *            exist.
1843   *
1844   * @return  The requested string value.
1845   *
1846   * @throws  LDAPException  If the specified field exists but is not a string.
1847   */
1848  static String getString(final JSONObject o, final String f, final String d)
1849         throws LDAPException
1850  {
1851    final JSONValue v = o.getField(f);
1852    if (v == null)
1853    {
1854      return d;
1855    }
1856
1857    if (v instanceof JSONString)
1858    {
1859      return ((JSONString) v).stringValue();
1860    }
1861    else
1862    {
1863      throw new LDAPException(ResultCode.PARAM_ERROR,
1864           ERR_LDAP_SPEC_VALUE_NOT_STRING.get(f));
1865    }
1866  }
1867
1868
1869
1870  /**
1871   * Retrieves a string value read from the specified file.  The file must
1872   * contain exactly one line, and that line must not be empty.
1873   *
1874   * @param  path       The path to the file from which to read the string.
1875   * @param  fieldName  The name of the field from which the path was obtained.
1876   *
1877   * @return  The string read from the specified file.
1878   *
1879   * @throws  LDAPException  If a problem is encountered while reading from the
1880   *                         specified file, if the file does not contain
1881   *                         exactly one line, or if the line contained in the
1882   *                         file is empty.
1883   */
1884  static String getStringFromFile(final String path, final String fieldName)
1885         throws LDAPException
1886  {
1887    BufferedReader r = null;
1888    try
1889    {
1890      r = new BufferedReader(new FileReader(path));
1891
1892      final String line = r.readLine();
1893      if (line == null)
1894      {
1895        throw new LDAPException(ResultCode.PARAM_ERROR,
1896             ERR_LDAP_SPEC_READ_FILE_EMPTY.get(path, fieldName));
1897      }
1898
1899      if (r.readLine() != null)
1900      {
1901        throw new LDAPException(ResultCode.PARAM_ERROR,
1902             ERR_LDAP_SPEC_READ_FILE_MULTIPLE_LINES.get(path, fieldName));
1903      }
1904
1905      if (line.length() == 0)
1906      {
1907        throw new LDAPException(ResultCode.PARAM_ERROR,
1908             ERR_LDAP_SPEC_READ_FILE_EMPTY_LINE.get(path, fieldName));
1909      }
1910
1911      return line;
1912    }
1913    catch (final LDAPException le)
1914    {
1915      Debug.debugException(le);
1916      throw le;
1917    }
1918    catch (final Exception e)
1919    {
1920      Debug.debugException(e);
1921      throw new LDAPException(ResultCode.PARAM_ERROR,
1922           ERR_LDAP_SPEC_READ_FILE_ERROR.get(path, fieldName,
1923                StaticUtils.getExceptionMessage(e)),
1924           e);
1925    }
1926    finally
1927    {
1928      if (r != null)
1929      {
1930        try
1931        {
1932          r.close();
1933        }
1934        catch (final Exception e)
1935        {
1936          Debug.debugException(e);
1937        }
1938      }
1939    }
1940  }
1941
1942
1943
1944  /**
1945   * Verifies that none of the indicated fields exist in the provided JSON
1946   * object because they would conflict with the specified existing field.
1947   *
1948   * @param  o                  The JSON object to examine.
1949   * @param  existingField      The name of a field known to be present in the
1950   *                            JSON object that cannot coexist with the
1951   *                            indicated conflicting fields.
1952   * @param  conflictingFields  The names of the fields that cannot be used in
1953   *                            conjunction with the specified existing field.
1954   *
1955   * @throws  LDAPException  If the provided JSON object has one or more fields
1956   *                         that conflict with the specified existing field.
1957   */
1958  static void rejectConflictingFields(final JSONObject o,
1959                                      final String existingField,
1960                                      final String... conflictingFields)
1961         throws LDAPException
1962  {
1963    for (final String fieldName : conflictingFields)
1964    {
1965      if (o.getField(fieldName) != null)
1966      {
1967        throw new LDAPException(ResultCode.PARAM_ERROR,
1968             ERR_LDAP_SPEC_CONFLICTING_FIELD.get(fieldName, existingField));
1969      }
1970    }
1971  }
1972
1973
1974
1975  /**
1976   * Verifies that none of the indicated fields exist in the provided JSON
1977   * object because they can only be provided if the specified required field is
1978   * present.
1979   *
1980   * @param  o                The JSON object to examine.
1981   * @param  requiredField    The name of a field known to be missing from the
1982   *                          JSON object, but must be present to allow any of
1983   *                          the indicated dependent fields to be provided.
1984   * @param  dependentFields  The names of the fields that can only be present
1985   *                          if the specified required field is present.
1986   *
1987   * @throws  LDAPException  If the provided JSON object has one or more
1988   *                         unresolved dependencies.
1989   */
1990  static void rejectUnresolvedDependency(final JSONObject o,
1991                                         final String requiredField,
1992                                         final String... dependentFields)
1993         throws LDAPException
1994  {
1995    for (final String fieldName : dependentFields)
1996    {
1997      if (o.getField(fieldName) != null)
1998      {
1999        throw new LDAPException(ResultCode.PARAM_ERROR,
2000             ERR_LDAP_SPEC_MISSING_DEPENDENT_FIELD.get(fieldName,
2001                  requiredField));
2002      }
2003    }
2004  }
2005}