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}