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}