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.concurrent.ScheduledExecutorService;
035import java.util.concurrent.TimeUnit;
036
037import org.forgerock.opendj.ldap.requests.BindRequest;
038import org.forgerock.opendj.ldap.requests.SearchRequest;
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 authenticated connection factory which will obtain
049     * connections using the provided connection factory and immediately perform
050     * the provided Bind request.
051     * <p>
052     * The connections returned by an authenticated connection factory support
053     * all operations with the exception of Bind requests. Attempts to perform a
054     * Bind will result in an {@code UnsupportedOperationException}.
055     * <p>
056     * If the Bind request fails for some reason (e.g. invalid credentials),
057     * then the connection attempt will fail and an {@link LdapException}
058     * will be thrown.
059     *
060     * @param factory
061     *            The connection factory to use for connecting to the Directory
062     *            Server.
063     * @param request
064     *            The Bind request to use for authentication.
065     * @return The new connection pool.
066     * @throws NullPointerException
067     *             If {@code factory} or {@code request} was {@code null}.
068     */
069    public static ConnectionFactory newAuthenticatedConnectionFactory(
070            final ConnectionFactory factory, final BindRequest request) {
071        Reject.ifNull(factory, request);
072
073        return new AuthenticatedConnectionFactory(factory, request);
074    }
075
076    /**
077     * Creates a new connection pool which creates new connections as needed
078     * using the provided connection factory, but will reuse previously
079     * allocated connections when they are available.
080     * <p>
081     * Connections which have not been used for sixty seconds are closed and
082     * removed from the pool. Thus, a pool that remains idle for long enough
083     * will not contain any cached connections.
084     * <p>
085     * Connections obtained from the connection pool are guaranteed to be valid
086     * immediately before being returned to the calling application. More
087     * specifically, connections which have remained idle in the connection pool
088     * for a long time and which have been remotely closed due to a time out
089     * will never be returned. However, once a pooled connection has been
090     * obtained it is the responsibility of the calling application to handle
091     * subsequent connection failures, these being signaled via a
092     * {@link ConnectionException}.
093     *
094     * @param factory
095     *            The connection factory to use for creating new connections.
096     * @return The new connection pool.
097     * @throws NullPointerException
098     *             If {@code factory} was {@code null}.
099     */
100    public static ConnectionPool newCachedConnectionPool(final ConnectionFactory factory) {
101        return new CachedConnectionPool(factory, 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, null);
102    }
103
104    /**
105     * Creates a new connection pool which creates new connections as needed
106     * using the provided connection factory, but will reuse previously
107     * allocated connections when they are available.
108     * <p>
109     * Attempts to use more than {@code maximumPoolSize} connections at once
110     * will block until a connection is released back to the pool. In other
111     * words, this pool will prevent applications from using more than
112     * {@code maximumPoolSize} connections at the same time.
113     * <p>
114     * Connections which have not been used for the provided {@code idleTimeout}
115     * period are closed and removed from the pool, until there are only
116     * {@code corePoolSize} connections remaining.
117     * <p>
118     * Connections obtained from the connection pool are guaranteed to be valid
119     * immediately before being returned to the calling application. More
120     * specifically, connections which have remained idle in the connection pool
121     * for a long time and which have been remotely closed due to a time out
122     * will never be returned. However, once a pooled connection has been
123     * obtained it is the responsibility of the calling application to handle
124     * subsequent connection failures, these being signaled via a
125     * {@link ConnectionException}.
126     *
127     * @param factory
128     *            The connection factory to use for creating new connections.
129     * @param corePoolSize
130     *            The minimum number of connections to keep in the pool, even if
131     *            they are idle.
132     * @param maximumPoolSize
133     *            The maximum number of connections to allow in the pool.
134     * @param idleTimeout
135     *            The time out period, after which unused non-core connections
136     *            will be closed.
137     * @param unit
138     *            The time unit for the {@code keepAliveTime} argument.
139     * @return The new connection pool.
140     * @throws IllegalArgumentException
141     *             If {@code corePoolSize}, {@code maximumPoolSize} are less
142     *             than or equal to zero, or if {@code idleTimeout} is negative,
143     *             or if {@code corePoolSize} is greater than
144     *             {@code maximumPoolSize}, or if {@code idleTimeout} is
145     *             non-zero and {@code unit} is {@code null}.
146     * @throws NullPointerException
147     *             If {@code factory} was {@code null}.
148     */
149    public static ConnectionPool newCachedConnectionPool(final ConnectionFactory factory,
150            final int corePoolSize, final int maximumPoolSize, final long idleTimeout,
151            final TimeUnit unit) {
152        return new CachedConnectionPool(factory, corePoolSize, maximumPoolSize, idleTimeout, unit,
153                null);
154    }
155
156    /**
157     * Creates a new connection pool which creates new connections as needed
158     * using the provided connection factory, but will reuse previously
159     * allocated connections when they are available.
160     * <p>
161     * Attempts to use more than {@code maximumPoolSize} connections at once
162     * will block until a connection is released back to the pool. In other
163     * words, this pool will prevent applications from using more than
164     * {@code maximumPoolSize} connections at the same time.
165     * <p>
166     * Connections which have not been used for the provided {@code idleTimeout}
167     * period are closed and removed from the pool, until there are only
168     * {@code corePoolSize} connections remaining.
169     * <p>
170     * Connections obtained from the connection pool are guaranteed to be valid
171     * immediately before being returned to the calling application. More
172     * specifically, connections which have remained idle in the connection pool
173     * for a long time and which have been remotely closed due to a time out
174     * will never be returned. However, once a pooled connection has been
175     * obtained it is the responsibility of the calling application to handle
176     * subsequent connection failures, these being signaled via a
177     * {@link ConnectionException}.
178     *
179     * @param factory
180     *            The connection factory to use for creating new connections.
181     * @param corePoolSize
182     *            The minimum number of connections to keep in the pool, even if
183     *            they are idle.
184     * @param maximumPoolSize
185     *            The maximum number of connections to allow in the pool.
186     * @param idleTimeout
187     *            The time out period, after which unused non-core connections
188     *            will be closed.
189     * @param unit
190     *            The time unit for the {@code keepAliveTime} argument.
191     * @param scheduler
192     *            The scheduler which should be used for periodically checking
193     *            for idle connections, or {@code null} if the default scheduler
194     *            should be used.
195     * @return The new connection pool.
196     * @throws IllegalArgumentException
197     *             If {@code corePoolSize}, {@code maximumPoolSize} are less
198     *             than or equal to zero, or if {@code idleTimeout} is negative,
199     *             or if {@code corePoolSize} is greater than
200     *             {@code maximumPoolSize}, or if {@code idleTimeout} is
201     *             non-zero and {@code unit} is {@code null}.
202     * @throws NullPointerException
203     *             If {@code factory} was {@code null}.
204     */
205    public static ConnectionPool newCachedConnectionPool(final ConnectionFactory factory,
206            final int corePoolSize, final int maximumPoolSize, final long idleTimeout,
207            final TimeUnit unit, final ScheduledExecutorService scheduler) {
208        return new CachedConnectionPool(factory, corePoolSize, maximumPoolSize, idleTimeout, unit,
209                scheduler);
210    }
211
212    /**
213     * Creates a new connection pool which will maintain {@code poolSize}
214     * connections created using the provided connection factory.
215     * <p>
216     * Attempts to use more than {@code poolSize} connections at once will block
217     * until a connection is released back to the pool. In other words, this
218     * pool will prevent applications from using more than {@code poolSize}
219     * connections at the same time.
220     * <p>
221     * Connections obtained from the connection pool are guaranteed to be valid
222     * immediately before being returned to the calling application. More
223     * specifically, connections which have remained idle in the connection pool
224     * for a long time and which have been remotely closed due to a time out
225     * will never be returned. However, once a pooled connection has been
226     * obtained it is the responsibility of the calling application to handle
227     * subsequent connection failures, these being signaled via a
228     * {@link ConnectionException}.
229     *
230     * @param factory
231     *            The connection factory to use for creating new connections.
232     * @param poolSize
233     *            The maximum size of the connection pool.
234     * @return The new connection pool.
235     * @throws IllegalArgumentException
236     *             If {@code poolSize} is negative.
237     * @throws NullPointerException
238     *             If {@code factory} was {@code null}.
239     */
240    public static ConnectionPool newFixedConnectionPool(final ConnectionFactory factory,
241            final int poolSize) {
242        return new CachedConnectionPool(factory, poolSize, poolSize, 0L, null, null);
243    }
244
245    /**
246     * Creates a new heart-beat connection factory which will create connections
247     * using the provided connection factory and periodically ping any created
248     * connections in order to detect that they are still alive every 10 seconds
249     * using the default scheduler. Connections will be marked as having failed
250     * if a heart-beat takes longer than 3 seconds.
251     *
252     * @param factory
253     *            The connection factory to use for creating connections.
254     * @return The new heart-beat connection factory.
255     * @throws NullPointerException
256     *             If {@code factory} was {@code null}.
257     */
258    public static ConnectionFactory newHeartBeatConnectionFactory(final ConnectionFactory factory) {
259        return new HeartBeatConnectionFactory(factory, 10, 3, TimeUnit.SECONDS, null, null);
260    }
261
262    /**
263     * Creates a new heart-beat connection factory which will create connections
264     * using the provided connection factory and periodically ping any created
265     * connections in order to detect that they are still alive using the
266     * specified frequency and the default scheduler.
267     *
268     * @param factory
269     *            The connection factory to use for creating connections.
270     * @param interval
271     *            The interval between keepalive pings.
272     * @param timeout
273     *            The heart-beat timeout after which a connection will be marked
274     *            as failed.
275     * @param unit
276     *            The time unit for the interval between keepalive pings.
277     * @return The new heart-beat connection factory.
278     * @throws IllegalArgumentException
279     *             If {@code interval} was negative.
280     * @throws NullPointerException
281     *             If {@code factory} or {@code unit} was {@code null}.
282     */
283    public static ConnectionFactory newHeartBeatConnectionFactory(final ConnectionFactory factory,
284            final long interval, final long timeout, final TimeUnit unit) {
285        return new HeartBeatConnectionFactory(factory, interval, timeout, unit, null, null);
286    }
287
288    /**
289     * Creates a new heart-beat connection factory which will create connections
290     * using the provided connection factory and periodically ping any created
291     * connections using the specified search request in order to detect that
292     * they are still alive.
293     *
294     * @param factory
295     *            The connection factory to use for creating connections.
296     * @param interval
297     *            The interval between keepalive pings.
298     * @param timeout
299     *            The heart-beat timeout after which a connection will be marked
300     *            as failed.
301     * @param unit
302     *            The time unit for the interval between keepalive pings.
303     * @param heartBeat
304     *            The search request to use for keepalive pings.
305     * @return The new heart-beat connection factory.
306     * @throws IllegalArgumentException
307     *             If {@code interval} was negative.
308     * @throws NullPointerException
309     *             If {@code factory}, {@code unit}, or {@code heartBeat} was
310     *             {@code null}.
311     */
312    public static ConnectionFactory newHeartBeatConnectionFactory(final ConnectionFactory factory,
313            final long interval, final long timeout, final TimeUnit unit,
314            final SearchRequest heartBeat) {
315        return new HeartBeatConnectionFactory(factory, interval, timeout, unit, heartBeat, null);
316    }
317
318    /**
319     * Creates a new heart-beat connection factory which will create connections
320     * using the provided connection factory and periodically ping any created
321     * connections using the specified search request in order to detect that
322     * they are still alive.
323     *
324     * @param factory
325     *            The connection factory to use for creating connections.
326     * @param interval
327     *            The interval between keepalive pings.
328     * @param timeout
329     *            The heart-beat timeout after which a connection will be marked
330     *            as failed.
331     * @param unit
332     *            The time unit for the interval between keepalive pings.
333     * @param heartBeat
334     *            The search request to use for keepalive pings.
335     * @param scheduler
336     *            The scheduler which should for periodically sending keepalive
337     *            pings.
338     * @return The new heart-beat connection factory.
339     * @throws IllegalArgumentException
340     *             If {@code interval} was negative.
341     * @throws NullPointerException
342     *             If {@code factory}, {@code unit}, or {@code heartBeat} was
343     *             {@code null}.
344     */
345    public static ConnectionFactory newHeartBeatConnectionFactory(final ConnectionFactory factory,
346            final long interval, final long timeout, final TimeUnit unit,
347            final SearchRequest heartBeat, final ScheduledExecutorService scheduler) {
348        return new HeartBeatConnectionFactory(factory, interval, timeout, unit, heartBeat,
349                scheduler);
350    }
351
352    /**
353     * Creates a new internal client connection which will route requests to the
354     * provided {@code RequestHandler}.
355     * <p>
356     * When processing requests, {@code RequestHandler} implementations are
357     * passed a {@code RequestContext} having a pseudo {@code requestID} which
358     * is incremented for each successive internal request on a per client
359     * connection basis. The request ID may be useful for logging purposes.
360     * <p>
361     * An internal connection does not require {@code RequestHandler}
362     * implementations to return a result when processing requests. However, it
363     * is recommended that implementations do always return results even for
364     * abandoned requests. This is because application client threads may block
365     * indefinitely waiting for results.
366     *
367     * @param requestHandler
368     *            The request handler which will be used for all client
369     *            connections.
370     * @return The new internal connection.
371     * @throws NullPointerException
372     *             If {@code requestHandler} was {@code null}.
373     */
374    public static Connection newInternalConnection(
375            final RequestHandler<RequestContext> requestHandler) {
376        Reject.ifNull(requestHandler);
377        return newInternalConnection(adaptRequestHandler(requestHandler));
378    }
379
380    /**
381     * Creates a new internal client connection which will route requests to the
382     * provided {@code ServerConnection}.
383     * <p>
384     * When processing requests, {@code ServerConnection} implementations are
385     * passed an integer as the first parameter. This integer represents a
386     * pseudo {@code requestID} which is incremented for each successive
387     * internal request on a per client connection basis. The request ID may be
388     * useful for logging purposes.
389     * <p>
390     * An internal connection does not require {@code ServerConnection}
391     * implementations to return a result when processing requests. However, it
392     * is recommended that implementations do always return results even for
393     * abandoned requests. This is because application client threads may block
394     * indefinitely waiting for results.
395     *
396     * @param serverConnection
397     *            The server connection.
398     * @return The new internal connection.
399     * @throws NullPointerException
400     *             If {@code serverConnection} was {@code null}.
401     */
402    public static Connection newInternalConnection(final ServerConnection<Integer> serverConnection) {
403        Reject.ifNull(serverConnection);
404        return new InternalConnection(serverConnection);
405    }
406
407    /**
408     * Creates a new connection factory which binds internal client connections
409     * to the provided {@link RequestHandler}s.
410     * <p>
411     * When processing requests, {@code RequestHandler} implementations are
412     * passed an integer as the first parameter. This integer represents a
413     * pseudo {@code requestID} which is incremented for each successive
414     * internal request on a per client connection basis. The request ID may be
415     * useful for logging purposes.
416     * <p>
417     * An internal connection factory does not require {@code RequestHandler}
418     * implementations to return a result when processing requests. However, it
419     * is recommended that implementations do always return results even for
420     * abandoned requests. This is because application client threads may block
421     * indefinitely waiting for results.
422     *
423     * @param requestHandler
424     *            The request handler which will be used for all client
425     *            connections.
426     * @return The new internal connection factory.
427     * @throws NullPointerException
428     *             If {@code requestHandler} was {@code null}.
429     */
430    public static ConnectionFactory newInternalConnectionFactory(
431            final RequestHandler<RequestContext> requestHandler) {
432        Reject.ifNull(requestHandler);
433        return new InternalConnectionFactory<>(
434            Connections.<Void> newServerConnectionFactory(requestHandler), null);
435    }
436
437    /**
438     * Creates a new connection factory which binds internal client connections
439     * to {@link RequestHandler}s created using the provided
440     * {@link RequestHandlerFactory}.
441     * <p>
442     * When processing requests, {@code RequestHandler} implementations are
443     * passed an integer as the first parameter. This integer represents a
444     * pseudo {@code requestID} which is incremented for each successive
445     * internal request on a per client connection basis. The request ID may be
446     * useful for logging purposes.
447     * <p>
448     * An internal connection factory does not require {@code RequestHandler}
449     * implementations to return a result when processing requests. However, it
450     * is recommended that implementations do always return results even for
451     * abandoned requests. This is because application client threads may block
452     * indefinitely waiting for results.
453     *
454     * @param <C>
455     *            The type of client context.
456     * @param factory
457     *            The request handler factory to use for creating connections.
458     * @param clientContext
459     *            The client context.
460     * @return The new internal connection factory.
461     * @throws NullPointerException
462     *             If {@code factory} was {@code null}.
463     */
464    public static <C> ConnectionFactory newInternalConnectionFactory(
465            final RequestHandlerFactory<C, RequestContext> factory, final C clientContext) {
466        Reject.ifNull(factory);
467        return new InternalConnectionFactory<>(newServerConnectionFactory(factory), clientContext);
468    }
469
470    /**
471     * Creates a new connection factory which binds internal client connections
472     * to {@link ServerConnection}s created using the provided
473     * {@link ServerConnectionFactory}.
474     * <p>
475     * When processing requests, {@code ServerConnection} implementations are
476     * passed an integer as the first parameter. This integer represents a
477     * pseudo {@code requestID} which is incremented for each successive
478     * internal request on a per client connection basis. The request ID may be
479     * useful for logging purposes.
480     * <p>
481     * An internal connection factory does not require {@code ServerConnection}
482     * implementations to return a result when processing requests. However, it
483     * is recommended that implementations do always return results even for
484     * abandoned requests. This is because application client threads may block
485     * indefinitely waiting for results.
486     *
487     * @param <C>
488     *            The type of client context.
489     * @param factory
490     *            The server connection factory to use for creating connections.
491     * @param clientContext
492     *            The client context.
493     * @return The new internal connection factory.
494     * @throws NullPointerException
495     *             If {@code factory} was {@code null}.
496     */
497    public static <C> ConnectionFactory newInternalConnectionFactory(
498            final ServerConnectionFactory<C, Integer> factory, final C clientContext) {
499        Reject.ifNull(factory);
500        return new InternalConnectionFactory<>(factory, clientContext);
501    }
502
503    /**
504     * Creates a new load balancer which will obtain connections using the
505     * provided load balancing algorithm.
506     *
507     * @param algorithm
508     *            The load balancing algorithm which will be used to obtain the
509     *            next
510     * @return The new load balancer.
511     * @throws NullPointerException
512     *             If {@code algorithm} was {@code null}.
513     */
514    public static ConnectionFactory newLoadBalancer(final LoadBalancingAlgorithm algorithm) {
515        return new LoadBalancer(algorithm);
516    }
517
518    /**
519     * Creates a new connection factory which forwards connection requests to
520     * the provided factory, but whose {@code toString} method will always
521     * return {@code name}.
522     * <p>
523     * This method may be useful for debugging purposes in order to more easily
524     * identity connection factories.
525     *
526     * @param factory
527     *            The connection factory to be named.
528     * @param name
529     *            The name of the connection factory.
530     * @return The named connection factory.
531     * @throws NullPointerException
532     *             If {@code factory} or {@code name} was {@code null}.
533     */
534    public static ConnectionFactory newNamedConnectionFactory(final ConnectionFactory factory,
535            final String name) {
536        Reject.ifNull(factory, name);
537
538        return new ConnectionFactory() {
539
540            @Override
541            public void close() {
542                factory.close();
543            }
544
545            @Override
546            public Connection getConnection() throws LdapException {
547                return factory.getConnection();
548            }
549
550            @Override
551            public Promise<Connection, LdapException> getConnectionAsync() {
552                return factory.getConnectionAsync();
553            }
554
555            @Override
556            public String toString() {
557                return name;
558            }
559
560        };
561    }
562
563    /**
564     * Creates a new server connection factory using the provided
565     * {@link RequestHandler}. The returned factory will manage connection and
566     * request life-cycle, including request cancellation.
567     * <p>
568     * When processing requests, {@link RequestHandler} implementations are
569     * passed a {@link RequestContext} as the first parameter which may be used
570     * for detecting whether or not the request should be aborted due to
571     * cancellation requests or other events, such as connection failure.
572     * <p>
573     * The returned factory maintains state information which includes a table
574     * of active requests. Therefore, {@code RequestHandler} implementations are
575     * required to always return results in order to avoid potential memory
576     * leaks.
577     *
578     * @param <C>
579     *            The type of client context.
580     * @param requestHandler
581     *            The request handler which will be used for all client
582     *            connections.
583     * @return The new server connection factory.
584     * @throws NullPointerException
585     *             If {@code requestHandler} was {@code null}.
586     */
587    public static <C> ServerConnectionFactory<C, Integer> newServerConnectionFactory(
588            final RequestHandler<RequestContext> requestHandler) {
589        Reject.ifNull(requestHandler);
590        return new RequestHandlerFactoryAdapter<>(new RequestHandlerFactory<C, RequestContext>() {
591            @Override
592            public RequestHandler<RequestContext> handleAccept(final C clientContext) {
593                return requestHandler;
594            }
595        });
596    }
597
598    /**
599     * Creates a new server connection factory using the provided
600     * {@link RequestHandlerFactory}. The returned factory will manage
601     * connection and request life-cycle, including request cancellation.
602     * <p>
603     * When processing requests, {@link RequestHandler} implementations are
604     * passed a {@link RequestContext} as the first parameter which may be used
605     * for detecting whether or not the request should be aborted due to
606     * cancellation requests or other events, such as connection failure.
607     * <p>
608     * The returned factory maintains state information which includes a table
609     * of active requests. Therefore, {@code RequestHandler} implementations are
610     * required to always return results in order to avoid potential memory
611     * leaks.
612     *
613     * @param <C>
614     *            The type of client context.
615     * @param factory
616     *            The request handler factory to use for associating request
617     *            handlers with client connections.
618     * @return The new server connection factory.
619     * @throws NullPointerException
620     *             If {@code factory} was {@code null}.
621     */
622    public static <C> ServerConnectionFactory<C, Integer> newServerConnectionFactory(
623            final RequestHandlerFactory<C, RequestContext> factory) {
624        Reject.ifNull(factory);
625        return new RequestHandlerFactoryAdapter<>(factory);
626    }
627
628    /**
629     * Returns an uncloseable view of the provided connection. Attempts to call
630     * {@link Connection#close()} or
631     * {@link Connection#close(org.forgerock.opendj.ldap.requests.UnbindRequest, String)}
632     * will be ignored.
633     *
634     * @param connection
635     *            The connection whose {@code close} methods are to be disabled.
636     * @return An uncloseable view of the provided connection.
637     */
638    public static Connection uncloseable(Connection connection) {
639        return new AbstractConnectionWrapper<Connection>(connection) {
640            @Override
641            public void close() {
642                // Do nothing.
643            }
644
645            @Override
646            public void close(org.forgerock.opendj.ldap.requests.UnbindRequest request,
647                    String reason) {
648                // Do nothing.
649            };
650        };
651    }
652
653    /**
654     * Returns an uncloseable view of the provided connection factory. Attempts
655     * to call {@link ConnectionFactory#close()} will be ignored.
656     *
657     * @param factory
658     *            The connection factory whose {@code close} method is to be
659     *            disabled.
660     * @return An uncloseable view of the provided connection factory.
661     */
662    public static ConnectionFactory uncloseable(final ConnectionFactory factory) {
663        return new ConnectionFactory() {
664
665            @Override
666            public Promise<Connection, LdapException> getConnectionAsync() {
667                return factory.getConnectionAsync();
668            }
669
670            @Override
671            public Connection getConnection() throws LdapException {
672                return factory.getConnection();
673            }
674
675            @Override
676            public void close() {
677                // Do nothing.
678            }
679        };
680    }
681
682    /**
683     * Returns the host name associated with the provided
684     * {@code InetSocketAddress}, without performing a DNS lookup. This method
685     * attempts to provide functionality which is compatible with
686     * {@code InetSocketAddress.getHostString()} in JDK7. It can be removed once
687     * we drop support for JDK6.
688     *
689     * @param socketAddress
690     *            The socket address which is expected to be an instance of
691     *            {@code InetSocketAddress}.
692     * @return The host name associated with the provided {@code SocketAddress},
693     *         or {@code null} if it is unknown.
694     */
695    public static String getHostString(final InetSocketAddress socketAddress) {
696        /*
697         * See OPENDJ-1270 for more information about slow DNS queries.
698         *
699         * We must avoid calling getHostName() in the case where it is likely to
700         * perform a blocking DNS query. Ideally we would call getHostString(),
701         * but the method was only added in JDK7.
702         */
703        if (socketAddress.isUnresolved()) {
704            /*
705             * Usually socket addresses are resolved on creation. If the address
706             * is unresolved then there must be a user provided hostname instead
707             * and getHostName will not perform a reverse lookup.
708             */
709            return socketAddress.getHostName();
710        } else {
711            /*
712             * Simulate getHostString() by parsing the toString()
713             * representation. This assumes that the toString() representation
714             * is stable, which I assume it is because it is documented.
715             */
716            final InetAddress address = socketAddress.getAddress();
717            final String hostSlashIp = address.toString();
718            final int slashPos = hostSlashIp.indexOf('/');
719            if (slashPos == 0) {
720                return hostSlashIp.substring(1);
721            } else {
722                return hostSlashIp.substring(0, slashPos);
723            }
724        }
725    }
726
727    /** Prevent instantiation. */
728    private Connections() {
729        // Do nothing.
730    }
731}