Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2014-2017 UnboundID Corp.
* All Rights Reserved.
*/
/*
* Copyright (C) 2014-2017 UnboundID Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (GPLv2 only)
* or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
package com.unboundid.ldap.sdk;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
import javax.net.SocketFactory;
import com.unboundid.util.Debug;
import com.unboundid.util.NotMutable;
import com.unboundid.util.ObjectPair;
import com.unboundid.util.ThreadLocalRandom;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.Validator;
import static com.unboundid.ldap.sdk.LDAPMessages.*;
/**
* This class provides a server set implementation that handles the case in
* which a given host name may resolve to multiple IP addresses. Note that
* while a setup like this is typically referred to as "round-robin DNS", this
* server set implementation does not strictly require DNS (as names may be
* resolved through alternate mechanisms like a hosts file or an alternate name
* service), and it does not strictly require round-robin use of those addresses
* (as alternate ordering mechanisms, like randomized or failover, may be used).
*
*
Example
* The following example demonstrates the process for creating a round-robin DNS
* server set for the case in which the hostname "directory.example.com" may be
* associated with multiple IP addresses, and the LDAP SDK should attempt to use
* them in a round robin manner.
*
* // Define a number of variables that will be used by the server set.
* String hostname = "directory.example.com";
* int port = 389;
* AddressSelectionMode selectionMode =
* AddressSelectionMode.ROUND_ROBIN;
* long cacheTimeoutMillis = 3600000L; // 1 hour
* String providerURL = "dns:"; // Default DNS config.
* SocketFactory socketFactory = null; // Default socket factory.
* LDAPConnectionOptions connectionOptions = null; // Default options.
*
* // Create the server set using the settings defined above.
* RoundRobinDNSServerSet serverSet = new RoundRobinDNSServerSet(hostname,
* port, selectionMode, cacheTimeoutMillis, providerURL, socketFactory,
* connectionOptions);
*
* // Verify that we can establish a single connection using the server set.
* LDAPConnection connection = serverSet.getConnection();
* RootDSE rootDSEFromConnection = connection.getRootDSE();
* connection.close();
*
* // Verify that we can establish a connection pool using the server set.
* SimpleBindRequest bindRequest =
* new SimpleBindRequest("uid=pool.user,dc=example,dc=com", "password");
* LDAPConnectionPool pool =
* new LDAPConnectionPool(serverSet, bindRequest, 10);
* RootDSE rootDSEFromPool = pool.getRootDSE();
* pool.close();
*
*/
@NotMutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class RoundRobinDNSServerSet
extends ServerSet
{
/**
* The name of a system property that can be used to specify a comma-delimited
* list of IP addresses to use if resolution fails. This is intended
* primarily for testing purposes.
*/
static final String PROPERTY_DEFAULT_ADDRESSES =
RoundRobinDNSServerSet.class.getName() + ".defaultAddresses";
/**
* An enum that defines the modes that may be used to select the order in
* which addresses should be used in attempts to establish connections.
*/
public enum AddressSelectionMode
{
/**
* The address selection mode that will cause addresses to be consistently
* attempted in the order they are retrieved from the name service.
*/
FAILOVER,
/**
* The address selection mode that will cause the order of addresses to be
* randomized for each attempt.
*/
RANDOM,
/**
* The address selection mode that will cause connection attempts to be made
* in a round-robin order.
*/
ROUND_ROBIN,
}
// The address selection mode that should be used if the provided hostname
// resolves to multiple addresses.
private final AddressSelectionMode selectionMode;
// A counter that will be used to handle round-robin ordering.
private final AtomicLong roundRobinCounter;
// A reference to an object that combines the resolved addresses with a
// timestamp indicating when the value should no longer be trusted.
private final AtomicReference>
resolvedAddressesWithTimeout;
// The properties that will be used to initialize the JNDI context, if any.
private final Hashtable jndiProperties;
// The port number for the target server.
private final int port;
// The set of connection options to use for new connections.
private final LDAPConnectionOptions connectionOptions;
// The maximum length of time, in milliseconds, to cache resolved addresses.
private final long cacheTimeoutMillis;
// The socket factory to use to establish connections.
private final SocketFactory socketFactory;
// The hostname to be resolved.
private final String hostname;
// The provider URL to use to resolve names, if any.
private final String providerURL;
// The DNS record types that will be used to obtain the IP addresses for the
// specified hostname.
private final String[] dnsRecordTypes;
/**
* Creates a new round-robin DNS server set with the provided information.
*
* @param hostname The hostname to be resolved to one or more
* addresses. It must not be {@code null}.
* @param port The port to use to connect to the server. Note
* that even if the provided hostname resolves to
* multiple addresses, the same port must be used
* for all addresses.
* @param selectionMode The selection mode that should be used if the
* hostname resolves to multiple addresses. It
* must not be {@code null}.
* @param cacheTimeoutMillis The maximum length of time in milliseconds to
* cache addresses resolved from the provided
* hostname. Caching resolved addresses can
* result in better performance and can reduce the
* number of requests to the name service. A
* that is less than or equal to zero indicates
* that no caching should be used.
* @param providerURL The JNDI provider URL that should be used when
* communicating with the DNS server. If this is
* {@code null}, then the underlying system's
* name service mechanism will be used (which may
* make use of other services instead of or in
* addition to DNS). If this is non-{@code null},
* then only DNS will be used to perform the name
* resolution. A value of "dns:" indicates that
* the underlying system's DNS configuration
* should be used.
* @param socketFactory The socket factory to use to establish the
* connections. It may be {@code null} if the
* JVM-default socket factory should be used.
* @param connectionOptions The set of connection options that should be
* used for the connections. It may be
* {@code null} if a default set of connection
* options should be used.
*/
public RoundRobinDNSServerSet(final String hostname, final int port,
final AddressSelectionMode selectionMode,
final long cacheTimeoutMillis,
final String providerURL,
final SocketFactory socketFactory,
final LDAPConnectionOptions connectionOptions)
{
this(hostname, port, selectionMode, cacheTimeoutMillis, providerURL,
null, null, socketFactory, connectionOptions);
}
/**
* Creates a new round-robin DNS server set with the provided information.
*
* @param hostname The hostname to be resolved to one or more
* addresses. It must not be {@code null}.
* @param port The port to use to connect to the server. Note
* that even if the provided hostname resolves to
* multiple addresses, the same port must be used
* for all addresses.
* @param selectionMode The selection mode that should be used if the
* hostname resolves to multiple addresses. It
* must not be {@code null}.
* @param cacheTimeoutMillis The maximum length of time in milliseconds to
* cache addresses resolved from the provided
* hostname. Caching resolved addresses can
* result in better performance and can reduce the
* number of requests to the name service. A
* that is less than or equal to zero indicates
* that no caching should be used.
* @param providerURL The JNDI provider URL that should be used when
* communicating with the DNS server.If both
* {@code providerURL} and {@code jndiProperties}
* are {@code null}, then then JNDI will not be
* used to interact with DNS and the hostname
* resolution will be performed via the underlying
* system's name service mechanism (which may make
* use of other services instead of or in addition
* to DNS).. If this is non-{@code null}, then
* only DNS will be used to perform the name
* resolution. A value of "dns:" indicates that
* the underlying system's DNS configuration
* should be used.
* @param jndiProperties A set of JNDI-related properties that should be
* be used when initializing the context for
* interacting with the DNS server via JNDI. If
* both {@code providerURL} and
* {@code jndiProperties} are {@code null}, then
* then JNDI will not be used to interact with
* DNS and the hostname resolution will be
* performed via the underlying system's name
* service mechanism (which may make use of other
* services instead of or in addition to DNS). If
* {@code providerURL} is {@code null} and
* {@code jndiProperties} is non-{@code null},
* then the provided properties must specify the
* URL.
* @param dnsRecordTypes Specifies the types of DNS records that will be
* used to obtain the addresses for the specified
* hostname. This will only be used if at least
* one of {@code providerURL} and
* {@code jndiProperties} is non-{@code null}. If
* this is {@code null} or empty, then a default
* record type of "A" (indicating IPv4 addresses)
* will be used.
* @param socketFactory The socket factory to use to establish the
* connections. It may be {@code null} if the
* JVM-default socket factory should be used.
* @param connectionOptions The set of connection options that should be
* used for the connections. It may be
* {@code null} if a default set of connection
* options should be used.
*/
public RoundRobinDNSServerSet(final String hostname, final int port,
final AddressSelectionMode selectionMode,
final long cacheTimeoutMillis,
final String providerURL,
final Properties jndiProperties,
final String[] dnsRecordTypes,
final SocketFactory socketFactory,
final LDAPConnectionOptions connectionOptions)
{
Validator.ensureNotNull(hostname);
Validator.ensureTrue((port >= 1) && (port <= 65535));
Validator.ensureNotNull(selectionMode);
this.hostname = hostname;
this.port = port;
this.selectionMode = selectionMode;
this.providerURL = providerURL;
if (jndiProperties == null)
{
if (providerURL == null)
{
this.jndiProperties = null;
}
else
{
this.jndiProperties = new Hashtable(2);
this.jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.dns.DnsContextFactory");
this.jndiProperties.put(Context.PROVIDER_URL, providerURL);
}
}
else
{
this.jndiProperties =
new Hashtable(jndiProperties.size()+2);
for (final Map.Entry