001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2009-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2011-2015 ForgeRock AS 026 */ 027 028package org.forgerock.opendj.ldap; 029 030import static org.forgerock.opendj.ldap.RequestHandlerFactoryAdapter.adaptRequestHandler; 031 032import java.net.InetAddress; 033import java.net.InetSocketAddress; 034import java.util.Collection; 035import java.util.concurrent.ScheduledExecutorService; 036import java.util.concurrent.TimeUnit; 037 038import org.forgerock.util.Options; 039import org.forgerock.util.Reject; 040import org.forgerock.util.promise.Promise; 041 042/** 043 * This class contains methods for creating and manipulating connection 044 * factories and connections. 045 */ 046public final class Connections { 047 /** 048 * Creates a new connection pool which creates new connections as needed 049 * using the provided connection factory, but will reuse previously 050 * allocated connections when they are available. 051 * <p> 052 * Connections which have not been used for sixty seconds are closed and 053 * removed from the pool. Thus, a pool that remains idle for long enough 054 * will not contain any cached connections. 055 * <p> 056 * Connections obtained from the connection pool are guaranteed to be valid 057 * immediately before being returned to the calling application. More 058 * specifically, connections which have remained idle in the connection pool 059 * for a long time and which have been remotely closed due to a time out 060 * will never be returned. However, once a pooled connection has been 061 * obtained it is the responsibility of the calling application to handle 062 * subsequent connection failures, these being signaled via a 063 * {@link ConnectionException}. 064 * 065 * @param factory 066 * The connection factory to use for creating new connections. 067 * @return The new connection pool. 068 * @throws NullPointerException 069 * If {@code factory} was {@code null}. 070 */ 071 public static ConnectionPool newCachedConnectionPool(final ConnectionFactory factory) { 072 return new CachedConnectionPool(factory, 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, null); 073 } 074 075 /** 076 * Creates a new connection pool which creates new connections as needed 077 * using the provided connection factory, but will reuse previously 078 * allocated connections when they are available. 079 * <p> 080 * Attempts to use more than {@code maximumPoolSize} connections at once 081 * will block until a connection is released back to the pool. In other 082 * words, this pool will prevent applications from using more than 083 * {@code maximumPoolSize} connections at the same time. 084 * <p> 085 * Connections which have not been used for the provided {@code idleTimeout} 086 * period are closed and removed from the pool, until there are only 087 * {@code corePoolSize} connections remaining. 088 * <p> 089 * Connections obtained from the connection pool are guaranteed to be valid 090 * immediately before being returned to the calling application. More 091 * specifically, connections which have remained idle in the connection pool 092 * for a long time and which have been remotely closed due to a time out 093 * will never be returned. However, once a pooled connection has been 094 * obtained it is the responsibility of the calling application to handle 095 * subsequent connection failures, these being signaled via a 096 * {@link ConnectionException}. 097 * 098 * @param factory 099 * The connection factory to use for creating new connections. 100 * @param corePoolSize 101 * The minimum number of connections to keep in the pool, even if 102 * they are idle. 103 * @param maximumPoolSize 104 * The maximum number of connections to allow in the pool. 105 * @param idleTimeout 106 * The time out period, after which unused non-core connections 107 * will be closed. 108 * @param unit 109 * The time unit for the {@code keepAliveTime} argument. 110 * @return The new connection pool. 111 * @throws IllegalArgumentException 112 * If {@code corePoolSize}, {@code maximumPoolSize} are less 113 * than or equal to zero, or if {@code idleTimeout} is negative, 114 * or if {@code corePoolSize} is greater than 115 * {@code maximumPoolSize}, or if {@code idleTimeout} is 116 * non-zero and {@code unit} is {@code null}. 117 * @throws NullPointerException 118 * If {@code factory} was {@code null}. 119 */ 120 public static ConnectionPool newCachedConnectionPool(final ConnectionFactory factory, 121 final int corePoolSize, final int maximumPoolSize, final long idleTimeout, 122 final TimeUnit unit) { 123 return new CachedConnectionPool(factory, corePoolSize, maximumPoolSize, idleTimeout, unit, 124 null); 125 } 126 127 /** 128 * Creates a new connection pool which creates new connections as needed 129 * using the provided connection factory, but will reuse previously 130 * allocated connections when they are available. 131 * <p> 132 * Attempts to use more than {@code maximumPoolSize} connections at once 133 * will block until a connection is released back to the pool. In other 134 * words, this pool will prevent applications from using more than 135 * {@code maximumPoolSize} connections at the same time. 136 * <p> 137 * Connections which have not been used for the provided {@code idleTimeout} 138 * period are closed and removed from the pool, until there are only 139 * {@code corePoolSize} connections remaining. 140 * <p> 141 * Connections obtained from the connection pool are guaranteed to be valid 142 * immediately before being returned to the calling application. More 143 * specifically, connections which have remained idle in the connection pool 144 * for a long time and which have been remotely closed due to a time out 145 * will never be returned. However, once a pooled connection has been 146 * obtained it is the responsibility of the calling application to handle 147 * subsequent connection failures, these being signaled via a 148 * {@link ConnectionException}. 149 * 150 * @param factory 151 * The connection factory to use for creating new connections. 152 * @param corePoolSize 153 * The minimum number of connections to keep in the pool, even if 154 * they are idle. 155 * @param maximumPoolSize 156 * The maximum number of connections to allow in the pool. 157 * @param idleTimeout 158 * The time out period, after which unused non-core connections 159 * will be closed. 160 * @param unit 161 * The time unit for the {@code keepAliveTime} argument. 162 * @param scheduler 163 * The scheduler which should be used for periodically checking 164 * for idle connections, or {@code null} if the default scheduler 165 * should be used. 166 * @return The new connection pool. 167 * @throws IllegalArgumentException 168 * If {@code corePoolSize}, {@code maximumPoolSize} are less 169 * than or equal to zero, or if {@code idleTimeout} is negative, 170 * or if {@code corePoolSize} is greater than 171 * {@code maximumPoolSize}, or if {@code idleTimeout} is 172 * non-zero and {@code unit} is {@code null}. 173 * @throws NullPointerException 174 * If {@code factory} was {@code null}. 175 */ 176 public static ConnectionPool newCachedConnectionPool(final ConnectionFactory factory, 177 final int corePoolSize, final int maximumPoolSize, final long idleTimeout, 178 final TimeUnit unit, final ScheduledExecutorService scheduler) { 179 return new CachedConnectionPool(factory, corePoolSize, maximumPoolSize, idleTimeout, unit, 180 scheduler); 181 } 182 183 /** 184 * Creates a new connection pool which will maintain {@code poolSize} 185 * connections created using the provided connection factory. 186 * <p> 187 * Attempts to use more than {@code poolSize} connections at once will block 188 * until a connection is released back to the pool. In other words, this 189 * pool will prevent applications from using more than {@code poolSize} 190 * connections at the same time. 191 * <p> 192 * Connections obtained from the connection pool are guaranteed to be valid 193 * immediately before being returned to the calling application. More 194 * specifically, connections which have remained idle in the connection pool 195 * for a long time and which have been remotely closed due to a time out 196 * will never be returned. However, once a pooled connection has been 197 * obtained it is the responsibility of the calling application to handle 198 * subsequent connection failures, these being signaled via a 199 * {@link ConnectionException}. 200 * 201 * @param factory 202 * The connection factory to use for creating new connections. 203 * @param poolSize 204 * The maximum size of the connection pool. 205 * @return The new connection pool. 206 * @throws IllegalArgumentException 207 * If {@code poolSize} is negative. 208 * @throws NullPointerException 209 * If {@code factory} was {@code null}. 210 */ 211 public static ConnectionPool newFixedConnectionPool(final ConnectionFactory factory, 212 final int poolSize) { 213 return new CachedConnectionPool(factory, poolSize, poolSize, 0L, null, null); 214 } 215 216 /** 217 * Creates a new internal client connection which will route requests to the 218 * provided {@code RequestHandler}. 219 * <p> 220 * When processing requests, {@code RequestHandler} implementations are 221 * passed a {@code RequestContext} having a pseudo {@code requestID} which 222 * is incremented for each successive internal request on a per client 223 * connection basis. The request ID may be useful for logging purposes. 224 * <p> 225 * An internal connection does not require {@code RequestHandler} 226 * implementations to return a result when processing requests. However, it 227 * is recommended that implementations do always return results even for 228 * abandoned requests. This is because application client threads may block 229 * indefinitely waiting for results. 230 * 231 * @param requestHandler 232 * The request handler which will be used for all client 233 * connections. 234 * @return The new internal connection. 235 * @throws NullPointerException 236 * If {@code requestHandler} was {@code null}. 237 */ 238 public static Connection newInternalConnection( 239 final RequestHandler<RequestContext> requestHandler) { 240 Reject.ifNull(requestHandler); 241 return newInternalConnection(adaptRequestHandler(requestHandler)); 242 } 243 244 /** 245 * Creates a new internal client connection which will route requests to the 246 * provided {@code ServerConnection}. 247 * <p> 248 * When processing requests, {@code ServerConnection} implementations are 249 * passed an integer as the first parameter. This integer represents a 250 * pseudo {@code requestID} which is incremented for each successive 251 * internal request on a per client connection basis. The request ID may be 252 * useful for logging purposes. 253 * <p> 254 * An internal connection does not require {@code ServerConnection} 255 * implementations to return a result when processing requests. However, it 256 * is recommended that implementations do always return results even for 257 * abandoned requests. This is because application client threads may block 258 * indefinitely waiting for results. 259 * 260 * @param serverConnection 261 * The server connection. 262 * @return The new internal connection. 263 * @throws NullPointerException 264 * If {@code serverConnection} was {@code null}. 265 */ 266 public static Connection newInternalConnection(final ServerConnection<Integer> serverConnection) { 267 Reject.ifNull(serverConnection); 268 return new InternalConnection(serverConnection); 269 } 270 271 /** 272 * Creates a new connection factory which binds internal client connections 273 * to the provided {@link RequestHandler}s. 274 * <p> 275 * When processing requests, {@code RequestHandler} implementations are 276 * passed an integer as the first parameter. This integer represents a 277 * pseudo {@code requestID} which is incremented for each successive 278 * internal request on a per client connection basis. The request ID may be 279 * useful for logging purposes. 280 * <p> 281 * An internal connection factory does not require {@code RequestHandler} 282 * implementations to return a result when processing requests. However, it 283 * is recommended that implementations do always return results even for 284 * abandoned requests. This is because application client threads may block 285 * indefinitely waiting for results. 286 * 287 * @param requestHandler 288 * The request handler which will be used for all client 289 * connections. 290 * @return The new internal connection factory. 291 * @throws NullPointerException 292 * If {@code requestHandler} was {@code null}. 293 */ 294 public static ConnectionFactory newInternalConnectionFactory( 295 final RequestHandler<RequestContext> requestHandler) { 296 Reject.ifNull(requestHandler); 297 return new InternalConnectionFactory<>( 298 Connections.<Void> newServerConnectionFactory(requestHandler), null); 299 } 300 301 /** 302 * Creates a new connection factory which binds internal client connections 303 * to {@link RequestHandler}s created using the provided 304 * {@link RequestHandlerFactory}. 305 * <p> 306 * When processing requests, {@code RequestHandler} implementations are 307 * passed an integer as the first parameter. This integer represents a 308 * pseudo {@code requestID} which is incremented for each successive 309 * internal request on a per client connection basis. The request ID may be 310 * useful for logging purposes. 311 * <p> 312 * An internal connection factory does not require {@code RequestHandler} 313 * implementations to return a result when processing requests. However, it 314 * is recommended that implementations do always return results even for 315 * abandoned requests. This is because application client threads may block 316 * indefinitely waiting for results. 317 * 318 * @param <C> 319 * The type of client context. 320 * @param factory 321 * The request handler factory to use for creating connections. 322 * @param clientContext 323 * The client context. 324 * @return The new internal connection factory. 325 * @throws NullPointerException 326 * If {@code factory} was {@code null}. 327 */ 328 public static <C> ConnectionFactory newInternalConnectionFactory( 329 final RequestHandlerFactory<C, RequestContext> factory, final C clientContext) { 330 Reject.ifNull(factory); 331 return new InternalConnectionFactory<>(newServerConnectionFactory(factory), clientContext); 332 } 333 334 /** 335 * Creates a new connection factory which binds internal client connections 336 * to {@link ServerConnection}s created using the provided 337 * {@link ServerConnectionFactory}. 338 * <p> 339 * When processing requests, {@code ServerConnection} implementations are 340 * passed an integer as the first parameter. This integer represents a 341 * pseudo {@code requestID} which is incremented for each successive 342 * internal request on a per client connection basis. The request ID may be 343 * useful for logging purposes. 344 * <p> 345 * An internal connection factory does not require {@code ServerConnection} 346 * implementations to return a result when processing requests. However, it 347 * is recommended that implementations do always return results even for 348 * abandoned requests. This is because application client threads may block 349 * indefinitely waiting for results. 350 * 351 * @param <C> 352 * The type of client context. 353 * @param factory 354 * The server connection factory to use for creating connections. 355 * @param clientContext 356 * The client context. 357 * @return The new internal connection factory. 358 * @throws NullPointerException 359 * If {@code factory} was {@code null}. 360 */ 361 public static <C> ConnectionFactory newInternalConnectionFactory( 362 final ServerConnectionFactory<C, Integer> factory, final C clientContext) { 363 Reject.ifNull(factory); 364 return new InternalConnectionFactory<>(factory, clientContext); 365 } 366 367 /** 368 * Creates a new "round-robin" load-balance which will load-balance connections across the provided set of 369 * connection factories. A round robin load balancing algorithm distributes connection requests across a list of 370 * connection factories one at a time. When the end of the list is reached, the algorithm starts again from the 371 * beginning. 372 * <p/> 373 * This algorithm is typically used for load-balancing <i>within</i> data centers, where load must be distributed 374 * equally across multiple data sources. This algorithm contrasts with the {@link FailoverLoadBalancingAlgorithm} 375 * which is used for load-balancing <i>between</i> data centers. 376 * <p/> 377 * If a problem occurs that temporarily prevents connections from being obtained for one of the connection 378 * factories, then this algorithm automatically "fails over" to the next operational connection factory in the list. 379 * If none of the connection factories are operational then a {@code ConnectionException} is returned to the 380 * client. 381 * <p/> 382 * The implementation periodically attempts to connect to failed connection factories in order to determine if they 383 * have become available again. 384 * 385 * @param factories 386 * The connection factories. 387 * @param options 388 * This configuration options for the load-balancer. See {@link LoadBalancingAlgorithm} for common options. 389 * @return The new round-robin load balancer. 390 * @see #newFailoverLoadBalancer(Collection, Options) 391 * @see LoadBalancingAlgorithm 392 */ 393 public static ConnectionFactory newRoundRobinLoadBalancer( 394 final Collection<? extends ConnectionFactory> factories, final Options options) { 395 return new LoadBalancer(new RoundRobinLoadBalancingAlgorithm(factories, options)); 396 } 397 398 /** 399 * Creates a new "fail-over" load-balance which will load-balance connections across the provided set of connection 400 * factories. A fail-over load balancing algorithm provides fault tolerance across multiple underlying connection 401 * factories. 402 * <p/> 403 * This algorithm is typically used for load-balancing <i>between</i> data centers, where there is preference to 404 * always forward connection requests to the <i>closest available</i> data center. This algorithm contrasts with the 405 * {@link RoundRobinLoadBalancingAlgorithm} which is used for load-balancing <i>within</i> a data center. 406 * <p/> 407 * This algorithm selects connection factories based on the order in which they were provided during construction. 408 * More specifically, an attempt to obtain a connection factory will always return the <i>first operational</i> 409 * connection factory in the list. Applications should, therefore, organize the connection factories such that the 410 * <i>preferred</i> (usually the closest) connection factories appear before those which are less preferred. 411 * <p/> 412 * If a problem occurs that temporarily prevents connections from being obtained for one of the connection 413 * factories, then this algorithm automatically "fails over" to the next operational connection factory in the list. 414 * If none of the connection factories are operational then a {@code ConnectionException} is returned to the 415 * client. 416 * <p/> 417 * The implementation periodically attempts to connect to failed connection factories in order to determine if they 418 * have become available again. 419 * 420 * @param factories 421 * The connection factories. 422 * @param options 423 * This configuration options for the load-balancer. See {@link LoadBalancingAlgorithm} for common options. 424 * @return The new fail-over load balancer. 425 * @see #newRoundRobinLoadBalancer(Collection, Options) 426 * @see LoadBalancingAlgorithm 427 */ 428 public static ConnectionFactory newFailoverLoadBalancer( 429 final Collection<? extends ConnectionFactory> factories, final Options options) { 430 return new LoadBalancer(new FailoverLoadBalancingAlgorithm(factories, options)); 431 } 432 433 /** 434 * Creates a new load balancer which will obtain connections using the provided load balancing algorithm. 435 * 436 * @param algorithm 437 * The load balancing algorithm which will be used to obtain the next 438 * @return The new load balancer. 439 * @throws NullPointerException 440 * If {@code algorithm} was {@code null}. 441 */ 442 public static ConnectionFactory newLoadBalancer(final LoadBalancingAlgorithm algorithm) { 443 return new LoadBalancer(algorithm); 444 } 445 446 /** 447 * Creates a new connection factory which forwards connection requests to 448 * the provided factory, but whose {@code toString} method will always 449 * return {@code name}. 450 * <p> 451 * This method may be useful for debugging purposes in order to more easily 452 * identity connection factories. 453 * 454 * @param factory 455 * The connection factory to be named. 456 * @param name 457 * The name of the connection factory. 458 * @return The named connection factory. 459 * @throws NullPointerException 460 * If {@code factory} or {@code name} was {@code null}. 461 */ 462 public static ConnectionFactory newNamedConnectionFactory(final ConnectionFactory factory, 463 final String name) { 464 Reject.ifNull(factory, name); 465 466 return new ConnectionFactory() { 467 468 @Override 469 public void close() { 470 factory.close(); 471 } 472 473 @Override 474 public Connection getConnection() throws LdapException { 475 return factory.getConnection(); 476 } 477 478 @Override 479 public Promise<Connection, LdapException> getConnectionAsync() { 480 return factory.getConnectionAsync(); 481 } 482 483 @Override 484 public String toString() { 485 return name; 486 } 487 488 }; 489 } 490 491 /** 492 * Creates a new server connection factory using the provided 493 * {@link RequestHandler}. The returned factory will manage connection and 494 * request life-cycle, including request cancellation. 495 * <p> 496 * When processing requests, {@link RequestHandler} implementations are 497 * passed a {@link RequestContext} as the first parameter which may be used 498 * for detecting whether or not the request should be aborted due to 499 * cancellation requests or other events, such as connection failure. 500 * <p> 501 * The returned factory maintains state information which includes a table 502 * of active requests. Therefore, {@code RequestHandler} implementations are 503 * required to always return results in order to avoid potential memory 504 * leaks. 505 * 506 * @param <C> 507 * The type of client context. 508 * @param requestHandler 509 * The request handler which will be used for all client 510 * connections. 511 * @return The new server connection factory. 512 * @throws NullPointerException 513 * If {@code requestHandler} was {@code null}. 514 */ 515 public static <C> ServerConnectionFactory<C, Integer> newServerConnectionFactory( 516 final RequestHandler<RequestContext> requestHandler) { 517 Reject.ifNull(requestHandler); 518 return new RequestHandlerFactoryAdapter<>(new RequestHandlerFactory<C, RequestContext>() { 519 @Override 520 public RequestHandler<RequestContext> handleAccept(final C clientContext) { 521 return requestHandler; 522 } 523 }); 524 } 525 526 /** 527 * Creates a new server connection factory using the provided 528 * {@link RequestHandlerFactory}. The returned factory will manage 529 * connection and request life-cycle, including request cancellation. 530 * <p> 531 * When processing requests, {@link RequestHandler} implementations are 532 * passed a {@link RequestContext} as the first parameter which may be used 533 * for detecting whether or not the request should be aborted due to 534 * cancellation requests or other events, such as connection failure. 535 * <p> 536 * The returned factory maintains state information which includes a table 537 * of active requests. Therefore, {@code RequestHandler} implementations are 538 * required to always return results in order to avoid potential memory 539 * leaks. 540 * 541 * @param <C> 542 * The type of client context. 543 * @param factory 544 * The request handler factory to use for associating request 545 * handlers with client connections. 546 * @return The new server connection factory. 547 * @throws NullPointerException 548 * If {@code factory} was {@code null}. 549 */ 550 public static <C> ServerConnectionFactory<C, Integer> newServerConnectionFactory( 551 final RequestHandlerFactory<C, RequestContext> factory) { 552 Reject.ifNull(factory); 553 return new RequestHandlerFactoryAdapter<>(factory); 554 } 555 556 /** 557 * Returns an uncloseable view of the provided connection. Attempts to call 558 * {@link Connection#close()} or 559 * {@link Connection#close(org.forgerock.opendj.ldap.requests.UnbindRequest, String)} 560 * will be ignored. 561 * 562 * @param connection 563 * The connection whose {@code close} methods are to be disabled. 564 * @return An uncloseable view of the provided connection. 565 */ 566 public static Connection uncloseable(Connection connection) { 567 return new AbstractConnectionWrapper<Connection>(connection) { 568 @Override 569 public void close() { 570 // Do nothing. 571 } 572 573 @Override 574 public void close(org.forgerock.opendj.ldap.requests.UnbindRequest request, 575 String reason) { 576 // Do nothing. 577 } 578 }; 579 } 580 581 /** 582 * Returns an uncloseable view of the provided connection factory. Attempts 583 * to call {@link ConnectionFactory#close()} will be ignored. 584 * 585 * @param factory 586 * The connection factory whose {@code close} method is to be 587 * disabled. 588 * @return An uncloseable view of the provided connection factory. 589 */ 590 public static ConnectionFactory uncloseable(final ConnectionFactory factory) { 591 return new ConnectionFactory() { 592 593 @Override 594 public Promise<Connection, LdapException> getConnectionAsync() { 595 return factory.getConnectionAsync(); 596 } 597 598 @Override 599 public Connection getConnection() throws LdapException { 600 return factory.getConnection(); 601 } 602 603 @Override 604 public void close() { 605 // Do nothing. 606 } 607 }; 608 } 609 610 /** 611 * Returns the host name associated with the provided 612 * {@code InetSocketAddress}, without performing a DNS lookup. This method 613 * attempts to provide functionality which is compatible with 614 * {@code InetSocketAddress.getHostString()} in JDK7. It can be removed once 615 * we drop support for JDK6. 616 * 617 * @param socketAddress 618 * The socket address which is expected to be an instance of 619 * {@code InetSocketAddress}. 620 * @return The host name associated with the provided {@code SocketAddress}, 621 * or {@code null} if it is unknown. 622 */ 623 public static String getHostString(final InetSocketAddress socketAddress) { 624 /* 625 * See OPENDJ-1270 for more information about slow DNS queries. 626 * 627 * We must avoid calling getHostName() in the case where it is likely to 628 * perform a blocking DNS query. Ideally we would call getHostString(), 629 * but the method was only added in JDK7. 630 */ 631 if (socketAddress.isUnresolved()) { 632 /* 633 * Usually socket addresses are resolved on creation. If the address 634 * is unresolved then there must be a user provided hostname instead 635 * and getHostName will not perform a reverse lookup. 636 */ 637 return socketAddress.getHostName(); 638 } else { 639 /* 640 * Simulate getHostString() by parsing the toString() 641 * representation. This assumes that the toString() representation 642 * is stable, which I assume it is because it is documented. 643 */ 644 final InetAddress address = socketAddress.getAddress(); 645 final String hostSlashIp = address.toString(); 646 final int slashPos = hostSlashIp.indexOf('/'); 647 if (slashPos == 0) { 648 return hostSlashIp.substring(1); 649 } else { 650 return hostSlashIp.substring(0, slashPos); 651 } 652 } 653 } 654 655 /** Prevent instantiation. */ 656 private Connections() { 657 // Do nothing. 658 } 659}