mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
23.17.2013 78813fcdf53fa83bd4ea4ab55fec7bd8de9f4476
OPENDJ-1134 (CR-2338) Introduce a class in replication for encapsulating host+port combinations

Augmented HostPort class to support the use cases mentioned in OPENDJ-1134.
Moved host splitting and port range validation to HostPort class.


HostPort.java:
Added valueOf() to parses a "host:port" URL + Added extractPort(), normalizePort(), normalizedHost(), removeExtraChars().
Moved isLocalAddress() code here from StaticUtils.
Added normalizedHost field, toNormalizedString() and toString(String) + modified hashCode() and equals() to ensure stability of the results returned by hashCode() and equals().
Added allAddresses() to hide HostPort(int).
Moved isEquivalentTo() code here from ReplicationBroker.isSameReplicationServerUrl().

HostPortTest.java:
Added.

StaticUtils.java:
Moved isLocalAddress() and related code to the HostPort class.

ReplicationBroker.java:
Moved some isSameReplicationServerUrl() to HostPort as isEquivalentTo().

*.java:
Used the new HostPort ctor everywhere.
It simplified the code in many places and also helped remove duplicated code.

ComputeBestServerTest.java:
Added ports to serverURLs to ensure tests still pass.

*Test.java:
Removed the test anti-pattern try/catch/fail.
1 files added
15 files modified
1337 ■■■■ changed files
opends/src/server/org/opends/server/core/CoreConfigManager.java 87 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java 38 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java 28 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationServer.java 42 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/service/ReplicationBroker.java 96 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/HostPort.java 383 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/LDAPURL.java 66 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/StaticUtils.java 83 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ComputeBestServerTest.java 6 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/FractionalReplicationTest.java 6 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/GroupIdHandshakeTest.java 86 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ReplicationServerFailoverTest.java 105 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java 100 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/AssuredReplicationServerTest.java 87 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/types/HostPortTest.java 122 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/CoreConfigManager.java
@@ -23,35 +23,26 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011-2012 ForgeRock AS.
 *      Portions copyright 2011-2013 ForgeRock AS.
 */
package org.opends.server.core;
import java.util.*;
import org.opends.messages.Message;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ServerManagementContext;
import org.opends.server.admin.std.meta.GlobalCfgDefn;
import org.opends.server.admin.std.meta.GlobalCfgDefn.WorkflowConfigurationMode;
import org.opends.server.admin.std.server.GlobalCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.admin.server.ServerManagementContext;
import org.opends.server.api.AuthenticationPolicy;
import org.opends.server.config.ConfigException;
import org.opends.server.types.*;
import static org.opends.messages.ConfigMessages.*;
import static org.opends.server.util.ServerConstants.*;
/**
 * This class defines a utility that will be used to manage the set of core
 * configuration attributes defined in the Directory Server.  These
@@ -104,31 +95,18 @@
    {
      for (String server : smtpServers)
      {
        int colonPos = server.indexOf(':');
        if ((colonPos == 0) || (colonPos == (server.length()-1)))
        {
          Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
          throw new ConfigException(message);
        }
        else if (colonPos > 0)
        {
          try
          {
            int port = Integer.parseInt(server.substring(colonPos+1));
            if ((port < 1) || (port > 65535))
            {
              Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
              throw new ConfigException(message);
          // validate provided string
          HostPort.valueOf(server);
            }
          }
          catch (Exception e)
        catch (RuntimeException e)
          {
            Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
            throw new ConfigException(message, e);
          }
        }
      }
    }
    // Apply the configuration to the server.
@@ -222,33 +200,31 @@
    DirectoryServer.setLookthroughLimit(globalConfig.getLookthroughLimit());
    ArrayList<Properties> mailServerProperties = new ArrayList<Properties>();
    List<Properties> mailServerProperties = new ArrayList<Properties>();
    Set<String> smtpServers = globalConfig.getSMTPServer();
    if ((smtpServers != null) && (! smtpServers.isEmpty()))
    {
      for (String smtpServer : smtpServers)
      {
        int colonPos = smtpServer.indexOf(':');
        if (colonPos > 0)
        final Properties properties = new Properties();
        try
        {
          String smtpHost = smtpServer.substring(0, colonPos);
          String smtpPort = smtpServer.substring(colonPos+1);
          final HostPort hp = HostPort.valueOf(smtpServer);
          Properties properties = new Properties();
          properties.setProperty(SMTP_PROPERTY_HOST, smtpHost);
          properties.setProperty(SMTP_PROPERTY_PORT, smtpPort);
          properties.setProperty(SMTP_PROPERTY_HOST, hp.getHost());
          properties.setProperty(SMTP_PROPERTY_PORT,
              String.valueOf(hp.getPort()));
          properties.setProperty(SMTP_PROPERTY_CONNECTION_TIMEOUT,
                    SMTP_DEFAULT_TIMEOUT_VALUE);
          properties.setProperty(SMTP_PROPERTY_IO_TIMEOUT,
                  SMTP_DEFAULT_TIMEOUT_VALUE);
          mailServerProperties.add(properties);
        }
        else
        catch (RuntimeException e)
        {
          Properties properties = new Properties();
          // no valid port provided
          properties.setProperty(SMTP_PROPERTY_HOST, smtpServer);
          mailServerProperties.add(properties);
        }
        mailServerProperties.add(properties);
      }
    }
    DirectoryServer.setMailServerPropertySets(mailServerProperties);
@@ -379,6 +355,7 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isConfigurationChangeAcceptable(GlobalCfg configuration,
                      List<Message> unacceptableReasons)
  {
@@ -389,33 +366,18 @@
    {
      for (String server : smtpServers)
      {
        int colonPos = server.indexOf(':');
        if ((colonPos == 0) || (colonPos == (server.length()-1)))
        {
          Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
          unacceptableReasons.add(message);
          configAcceptable = false;
        }
        else if (colonPos > 0)
        {
          try
          {
            int port = Integer.parseInt(server.substring(colonPos+1));
            if ((port < 1) || (port > 65535))
          // validate provided string
          HostPort.valueOf(server);
        }
        catch (RuntimeException e)
            {
              Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
              unacceptableReasons.add(message);
              configAcceptable = false;
            }
          }
          catch (Exception e)
          {
            Message message = ERR_CONFIG_CORE_INVALID_SMTP_SERVER.get(server);
            unacceptableReasons.add(message);
            configAcceptable = false;
          }
        }
      }
    }
    // Ensure that the default password policy always points to a password
@@ -440,11 +402,12 @@
  /**
   * {@inheritDoc}
   */
  @Override
  public ConfigChangeResult applyConfigurationChange(GlobalCfg configuration)
  {
    ResultCode         resultCode          = ResultCode.SUCCESS;
    boolean            adminActionRequired = false;
    ArrayList<Message> messages            = new ArrayList<Message>();
    List<Message>      messages            = new ArrayList<Message>();
    applyGlobalConfiguration(configuration);
opends/src/server/org/opends/server/extensions/LDAPPassThroughAuthenticationPolicyFactory.java
@@ -26,15 +26,6 @@
 */
package org.opends.server.extensions;
import static org.opends.messages.ExtensionMessages.*;
import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
import static org.opends.server.util.StaticUtils.getExceptionMessage;
import static org.opends.server.util.StaticUtils.getFileForPath;
import java.io.*;
import java.net.*;
import java.util.*;
@@ -68,7 +59,11 @@
import org.opends.server.types.*;
import org.opends.server.util.TimeThread;
import static org.opends.messages.ExtensionMessages.*;
import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * LDAP pass through authentication policy implementation.
@@ -2266,10 +2261,8 @@
    private ConnectionFactory newLDAPConnectionFactory(final String hostPort)
    {
      // Validation already performed by admin framework.
      final int colonIndex = hostPort.lastIndexOf(":");
      final String hostname = hostPort.substring(0, colonIndex);
      final int port = Integer.parseInt(hostPort.substring(colonIndex + 1));
      return provider.getLDAPConnectionFactory(hostname, port, cfg);
      final HostPort hp = HostPort.valueOf(hostPort);
      return provider.getLDAPConnectionFactory(hp.getHost(), hp.getPort(), cfg);
    }
  }
@@ -2331,15 +2324,13 @@
      return scheduler;
    }
    @Override
    public String getCurrentTime()
    {
      return TimeThread.getGMTTime();
    }
    @Override
    public long getCurrentTimeMS()
    {
      return TimeThread.getTime();
@@ -2484,9 +2475,13 @@
      final LDAPPassThroughAuthenticationPolicyCfg configuration,
      final List<Message> unacceptableReasons, final String hostPort)
  {
    final int colonIndex = hostPort.lastIndexOf(":");
    final int port = Integer.parseInt(hostPort.substring(colonIndex + 1));
    if (port < 1 || port > 65535)
    try
    {
      // validate provided string
      HostPort.valueOf(hostPort);
      return true;
    }
    catch (RuntimeException e)
    {
      if (unacceptableReasons != null)
      {
@@ -2496,7 +2491,6 @@
      }
      return false;
    }
    return true;
  }
opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
@@ -27,18 +27,9 @@
 */
package org.opends.server.protocols.jmx;
import static org.opends.messages.ProtocolMessages.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.util.StaticUtils.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.opends.messages.Message;
import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -50,14 +41,13 @@
import org.opends.server.api.ServerShutdownListener;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.HostPort;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
import org.opends.server.types.*;
import org.opends.server.util.StaticUtils;
import static org.opends.messages.ProtocolMessages.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.types.HostPort.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a connection handler that will be used for
@@ -71,8 +61,6 @@
    ServerShutdownListener, AlertGenerator,
    ConfigurationChangeListener<JMXConnectionHandlerCfg> {
  private static final String WILDCARD_ADDRESS = "0.0.0.0";
  /**
   * Key that may be placed into a JMX connection environment map to
   * provide a custom <code>javax.net.ssl.TrustManager</code> array
@@ -159,7 +147,7 @@
      }
      listeners.clear();
      listeners.add(new HostPort(config.getListenPort()));
      listeners.add(HostPort.allAddresses(config.getListenPort()));
      rmiConnector.finalizeConnectionHandler(portChanged);
      try
@@ -365,7 +353,7 @@
    }
    listeners.clear();
    listeners.add(new HostPort(WILDCARD_ADDRESS, config.getListenPort()));
    listeners.add(HostPort.allAddresses(config.getListenPort()));
    connectionHandlerName = "JMX Connection Handler " + config.getListenPort();
    // Create a system property to store the JMX port the server is
opends/src/server/org/opends/server/replication/server/ReplicationServer.java
@@ -440,9 +440,6 @@
   */
  private void connect(String remoteServerURL, DN baseDN)
  {
    int separator = remoteServerURL.lastIndexOf(':');
    String port = remoteServerURL.substring(separator + 1);
    String hostname = remoteServerURL.substring(0, separator);
    boolean sslEncryption =replSessionSecurity.isSslEncryption(remoteServerURL);
    if (debugEnabled())
@@ -453,11 +450,12 @@
    Session session = null;
    try
    {
      InetSocketAddress ServerAddr = new InetSocketAddress(
          InetAddress.getByName(hostname), Integer.parseInt(port));
      final HostPort hp = HostPort.valueOf(remoteServerURL);
      final InetSocketAddress serverAddr = new InetSocketAddress(
          InetAddress.getByName(hp.getHost()), hp.getPort());
      socket.setTcpNoDelay(true);
      int timeoutMS = MultimasterReplication.getConnectionTimeoutMS();
      socket.connect(ServerAddr, timeoutMS);
      socket.connect(serverAddr, timeoutMS);
      session = replSessionSecurity.createClientSession(socket, timeoutMS);
      ReplicationServerHandler rsHandler = new ReplicationServerHandler(
@@ -1001,11 +999,8 @@
       * No need validate the string format because the admin framework has
       * already done it.
       */
      final int index = rsUrl.lastIndexOf(":");
      final String hostname = rsUrl.substring(0, index);
      final int port = Integer.parseInt(rsUrl.substring(index + 1));
      if (port == replicationPort && isLocalAddress(hostname))
      final HostPort hp = HostPort.valueOf(rsUrl);
      if (hp.getPort() == replicationPort && hp.isLocalAddress())
      {
        serverURL = rsUrl;
        return;
@@ -1352,9 +1347,10 @@
        try
        {
          // translate the server name into IP address and keep the port number
          String[] host = rsUrl.split(":");
          serversToDisconnect.add(
              InetAddress.getByName(host[0]).getHostAddress() + ":" + host[1]);
          final HostPort hp = HostPort.valueOf(rsUrl);
          final String hostAddress =
              InetAddress.getByName(hp.getHost()).getHostAddress();
          serversToDisconnect.add(hostAddress + ":" + hp.getPort());
        }
        catch (IOException e)
        {
@@ -1423,11 +1419,7 @@
   */
  public static void onlyForTestsAddlocalReplicationServer(String server)
  {
    int separator = server.lastIndexOf(':');
    if (separator == -1)
      return ;
    int port = Integer.parseInt(server.substring(separator + 1));
    localPorts.add(port);
    localPorts.add(HostPort.valueOf(server).getPort());
  }
  /**
@@ -1762,23 +1754,21 @@
   */
  private String normalizeServerURL(final String url)
  {
    final int separator = url.lastIndexOf(':');
    final String portString = url.substring(separator + 1);
    final String hostname = url.substring(0, separator);
    final HostPort hp = HostPort.valueOf(url);
    try
    {
      InetAddress inetAddress = InetAddress.getByName(hostname);
      if (isLocalAddress(inetAddress))
      InetAddress inetAddress = InetAddress.getByName(hp.getHost());
      if (HostPort.isLocalAddress(inetAddress))
      {
        inetAddress = getLocalAddress();
      }
      return inetAddress.getHostAddress() + ":" + portString;
      return inetAddress.getHostAddress() + ":" + hp.getPort();
    }
    catch (UnknownHostException e)
    {
      // This should not happen, but if it does then just default to the
      // original URL.
      Message message = ERR_COULD_NOT_SOLVE_HOSTNAME.get(hostname);
      Message message = ERR_COULD_NOT_SOLVE_HOSTNAME.get(hp.getHost());
      logError(message);
      return url;
    }
opends/src/server/org/opends/server/replication/server/ReplicationServerHandler.java
@@ -82,7 +82,7 @@
      generationId = inReplServerStartMsg.getGenerationId();
      serverId = inReplServerStartMsg.getServerId();
      serverURL = inReplServerStartMsg.getServerURL();
      final String port = serverURL.substring(serverURL.lastIndexOf(':') + 1);
      final int port = HostPort.valueOf(serverURL).getPort();
      serverAddressURL = session.getRemoteAddress() + ":" + port;
      DN baseDN = DN.decode(inReplServerStartMsg.getBaseDn());
      setBaseDNAndDomain(baseDN, false);
opends/src/server/org/opends/server/replication/service/ReplicationBroker.java
@@ -47,6 +47,7 @@
import org.opends.server.replication.protocol.*;
import org.opends.server.types.DN;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.HostPort;
import org.opends.server.util.ServerConstants;
import static org.opends.messages.ReplicationMessages.*;
@@ -376,81 +377,17 @@
  private static boolean isSameReplicationServerUrl(String rs1Url,
      String rs2Url)
  {
    // Get and compare ports of RS1 and RS2
    int separator1 = rs1Url.lastIndexOf(':');
    if (separator1 < 0)
    {
      // Not a RS url: should not happen
      return false;
    }
    int rs1Port = Integer.parseInt(rs1Url.substring(separator1 + 1));
    int separator2 = rs2Url.lastIndexOf(':');
    if (separator2 < 0)
    {
      // Not a RS url: should not happen
      return false;
    }
    int rs2Port = Integer.parseInt(rs2Url.substring(separator2 + 1));
    if (rs1Port != rs2Port)
    {
      return false;
    }
    // Get and compare addresses of RS1 and RS2
    final String rs1 = rs1Url.substring(0, separator1);
    final InetAddress[] rs1Addresses;
    try
    {
      // Normalize local address to null.
      rs1Addresses = isLocalAddress(rs1) ? null : InetAddress.getAllByName(rs1);
      final HostPort hp1 = HostPort.valueOf(rs1Url);
      final HostPort hp2 = HostPort.valueOf(rs2Url);
      return hp1.isEquivalentTo(hp2);
    }
    catch (UnknownHostException ex)
    catch (RuntimeException ex)
    {
      // Unknown RS: should not happen
      // Not a RS url or not a valid port number: should not happen
      return false;
    }
    final String rs2 = rs2Url.substring(0, separator2);
    final InetAddress[] rs2Addresses;
    try
    {
      // Normalize local address to null.
      rs2Addresses = isLocalAddress(rs2) ? null : InetAddress.getAllByName(rs2);
    }
    catch (UnknownHostException ex)
    {
      // Unknown RS: should not happen
      return false;
    }
    // Now compare addresses, if at least one match, this is the same server.
    if (rs1Addresses == null && rs2Addresses == null)
    {
      // Both local addresses.
      return true;
    }
    else if (rs1Addresses == null || rs2Addresses == null)
    {
      // One local address and one non-local.
      return false;
    }
    else
    {
      // Both non-local addresses: check for overlap.
      for (InetAddress inetAddress1 : rs1Addresses)
      {
        for (InetAddress inetAddress2 : rs2Addresses)
        {
          if (inetAddress2.equals(inetAddress1))
          {
            return true;
          }
        }
      }
    }
    return false;
  }
  /**
@@ -1205,10 +1142,6 @@
  private ReplicationServerInfo performPhaseOneHandshake(
      String server, boolean keepConnection, boolean isECL)
  {
    int separator = server.lastIndexOf(':');
    String port = server.substring(separator + 1);
    String hostname = server.substring(0, separator);
    final String baseDn = this.baseDN.toNormalizedString();
    Session localSession = null;
@@ -1219,9 +1152,9 @@
    try
    {
      // Open a socket connection to the next candidate.
      int intPort = Integer.parseInt(port);
      final HostPort hp = HostPort.valueOf(server);
      InetSocketAddress serverAddr = new InetSocketAddress(
          InetAddress.getByName(hostname), intPort);
          InetAddress.getByName(hp.getHost()), hp.getPort());
      socket = new Socket();
      socket.setReceiveBufferSize(1000000);
      socket.setTcpNoDelay(true);
@@ -1783,15 +1716,11 @@
    for (Integer rsId : bestServers.keySet())
    {
      ReplicationServerInfo replicationServerInfo = bestServers.get(rsId);
      String server = replicationServerInfo.getServerURL();
      int separator = server.lastIndexOf(':');
      if (separator > 0)
      final HostPort hp =
          HostPort.valueOf(replicationServerInfo.getServerURL());
      if (hp.isLocalAddress())
      {
        String hostname = server.substring(0, separator);
        if (isLocalAddress(hostname))
        {
          int port = Integer.parseInt(server.substring(separator + 1));
          if (isLocalReplicationServerPort(port))
        if (isLocalReplicationServerPort(hp.getPort()))
          {
            // An RS in the same VM will always have priority.
            if (!filterServersInSameVM)
@@ -1812,7 +1741,6 @@
          }
        }
      }
    }
    return result;
  }
opends/src/server/org/opends/server/types/HostPort.java
@@ -23,9 +23,18 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.types;
import java.net.*;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.loggers.debug.DebugLogger.*;
/**
 * This class defines a data structure that combines an address and
@@ -39,24 +48,146 @@
     mayInvoke=true)
public final class HostPort
{
  // The host for this object.
  /** The tracer object for the debug logger. */
  private static final DebugTracer TRACER = getTracer();
  /**
   * The wildcard address allows to instruct a server to
   * "listen to all addresses".
   *
   * @see InetSocketAddress#InetSocketAddress(int) InetSocketAddress javadoc
   */
  public static final String WILDCARD_ADDRESS = "0.0.0.0";
  /** The supplied host for this object. */
  private final String host;
  // The port for this object;
  /**
   * The normalized host for this object.
   * <p>
   * Normalization consists of converting local addresses to "localhost".
   */
  private final String normalizedHost;
  /** The port for this object. */
  private final int port;
  // Time-stamp acts as memory barrier for networkInterfaces.
  private static final long CACHED_LOCAL_ADDRESSES_TIMEOUT_MS = 30 * 1000;
  private static volatile long localAddressesTimeStamp = 0;
  private static Set<InetAddress> localAddresses = new HashSet<InetAddress>();
  /**
   * Creates a new {@code HostPort} object with the specified port
   * number but no host.
   * Returns {@code true} if the provided IPv4 or IPv6 address or host name
   * represents the address of one of the interfaces on the current host
   * machine.
   *
   * @param  port  The port number for this {@code HostPort} object.
   * @param addressString
   *          The IPv4 or IPv6 address or host name.
   * @return {@code true} if the provided IPv4 or IPv6 address or host name
   *         represents the address of one of the interfaces on the current host
   *         machine.
   */
  public HostPort(int port)
  public static boolean isLocalAddress(String addressString)
  {
    try
    {
      return isLocalAddress(InetAddress.getByName(addressString));
    }
    catch (UnknownHostException e)
    {
      return false;
    }
  }
  /**
   * Returns {@code true} if the provided {@code InetAddress} represents the
   * address of one of the interfaces on the current host machine.
   *
   * @param address
   *          The network address.
   * @return {@code true} if the provided {@code InetAddress} represents the
   *         address of one of the interfaces on the current host machine.
   */
  public static boolean isLocalAddress(InetAddress address)
  {
    return address.isLoopbackAddress() || getLocalAddresses().contains(address);
  }
  /**
   * Returns a Set of all the local addresses as detected by the Java
   * environment from the operating system configuration.
   * <p>
   * The local addresses are temporarily cached to balance the cost of this
   * expensive computation vs. refreshing the data that can be changed while the
   * system is running.
   *
   * @return a Set containing all the local addresses
   */
  private static Set<InetAddress> getLocalAddresses()
  {
    final long currentTimeStamp = System.currentTimeMillis();
    if (localAddressesTimeStamp
        < (currentTimeStamp - CACHED_LOCAL_ADDRESSES_TIMEOUT_MS))
    {
      // Refresh the cache.
      try
      {
        final Enumeration<NetworkInterface> i =
            NetworkInterface.getNetworkInterfaces();
        final Set<InetAddress> newLocalAddresses = new HashSet<InetAddress>();
        while (i.hasMoreElements())
        {
          NetworkInterface n = i.nextElement();
          Enumeration<InetAddress> j = n.getInetAddresses();
          while (j.hasMoreElements())
          {
            newLocalAddresses.add(j.nextElement());
          }
        }
        localAddresses = newLocalAddresses;
      }
      catch (SocketException e)
      {
        // Ignore and keep the old set.
        TRACER.debugCaught(DebugLogLevel.WARNING, e);
      }
      localAddressesTimeStamp = currentTimeStamp; // Publishes.
    }
    return localAddresses;
  }
  /**
   * Returns a a new HostPort for all addresses, also known as a wildcard
   * address.
   *
   * @param port
   *          The port number for the new {@code HostPort} object.
   * @return a newly constructed HostPort object
   */
  public static HostPort allAddresses(int port)
  {
    return new HostPort(port);
  }
  /**
   * Creates a new {@code HostPort} object with the specified port number but no
   * host.
   *
   * @param port
   *          The port number for this {@code HostPort} object.
   */
  private HostPort(int port)
  {
    this.host = null;
    this.port = port;
    this.normalizedHost = null;
    this.port = normalizePort(port);
  }
@@ -71,13 +202,103 @@
   */
  public HostPort(String host, int port)
  {
    this.host = host;
    this.port = port;
    this.host = removeExtraChars(host);
    this.normalizedHost = normalizedHost(this.host);
    this.port = normalizePort(port);
  }
  /**
   * Creates a new {@code HostPort} object by parsing the supplied
   * "hostName:port" String URL. This method also accepts IPV6 style
   * "[hostAddress]:port" String URLs.
   *
   * @param hostPort
   *          a String representing the URL made of a host and a port.
   * @return a new {@link HostPort} built from the supplied string.
   * @throws NumberFormatException
   *           If the "port" in the supplied string cannot be converted to an
   *           int
   * @throws IllegalArgumentException
   *           if no port could be found in the supplied string, or if the port
   *           is not a valid port number
   */
  public static HostPort valueOf(String hostPort) throws NumberFormatException,
      IllegalArgumentException
  {
    final int sepIndex = hostPort.lastIndexOf(':');
    if (sepIndex == -1)
    {
      throw new IllegalArgumentException(
          "Invalid host/port string: no network port was provided in '"
              + hostPort + "'");
    }
    if (sepIndex == 0)
    {
      throw new IllegalArgumentException(
          "Invalid host/port string: no host name was provided in '" + hostPort
              + "'");
    }
    String host = sepIndex != -1 ? hostPort.substring(0, sepIndex) : hostPort;
    int port = Integer.parseInt(hostPort.substring(sepIndex + 1).trim());
    return new HostPort(host, port);
  }
  /**
   * Removes extra characters from the host name: leading and trailing white
   * spaces, and surrounding square brackets for IPv6 addresses.
   *
   * @param host
   *          the host name to clean
   * @return the cleaned up host name
   */
  private String removeExtraChars(String host)
  {
    host = host.trim();
    final int startsWith = host.indexOf("[");
    if (startsWith == -1)
    {
      return host;
    }
    return host.substring(1, host.length() - 1);
  }
  /**
   * Returns a normalized String representation of the supplied host.
   *
   * @param host
   *          the host address to normalize
   * @return a normalized String representation of the supplied host.
   * @see #normalizedHost what host normalization covers
   */
  private String normalizedHost(String host)
  {
    if (isLocalAddress(host))
    {
      return "localhost";
    }
    return host;
  }
  /**
   * Ensures the supplied port number is valid.
   *
   * @param port
   *          the port number to validate
   * @return the port number if valid
   */
  private int normalizePort(int port)
  {
    if (1 <= port && port <= 65535)
    {
      return port;
    }
    throw new IllegalArgumentException("Invalid network port provided: " + port
        + " is not included in the [1, 65535] range.");
  }
  /**
   * Retrieves the host for this {@code HostPort} object.
   *
   * @return  The host for this {@code HostPort} object, or
@@ -93,56 +314,150 @@
  /**
   * Retrieves the port number for this {@code HostPort} object.
   *
   * @return  The port number for this {@code HostPort} object.
   * @return The valid port number in the [1, 65535] range for this
   *         {@code HostPort} object.
   */
  public int getPort()
  {
    return port;
  }
  /**
   * Whether the current object represents a local address.
   *
   * @return true if this represents a local address, false otherwise.
   */
  public boolean isLocalAddress()
  {
    return isLocalAddress(getHost());
  }
  /**
   * Retrieves a string representation of this {@code HostPort}
   * object.  It will be the host element (or nothing if no host was
   * given) followed by a colon and the port number.
   * Returns a string representation of this {@code HostPort} object. It will be
   * the host element (or nothing if no host was given) followed by a colon and
   * the port number.
   *
   * @return  A string representation of this {@code HostPort} object.
   */
  @Override
  public String toString()
  {
    if (host ==  null)
    return toString(host);
  }
  /**
   * Returns a normalized string representation of this {@code HostPort} object.
   *
   * @return A string representation of this {@code HostPort} object.
   * @see #normalizedHost what host normalization covers
   */
  private String toNormalizedString()
    {
    return toString(normalizedHost);
  }
  /**
   * Inner computation for #toString() and {@link #toNormalizedString()}.
   *
   * @param hostName
   *          the hostName to use for this computation
   * @return the String representation fo4r this object
   */
  private String toString(String hostName)
  {
    if (hostName != null)
    {
      if (hostName.contains(":"))
      {
        return "[" + hostName + "]:" + port;
      }
      return hostName + ":" + port;
    }
      return ":" + port;
    }
    else
  /**
   * Checks whether the supplied HostPort is an equivalent to the current
   * HostPort.
   *
   * @param other
   *          the HostPort to compare to "this"
   * @return true if the HostPorts are equivalent, false otherwise. False is
   *         also return if calling {@link InetAddress#getAllByName(String)}
   *         throws an UnknownHostException.
   */
  public boolean isEquivalentTo(final HostPort other)
    {
      return host + ":" + port;
    try
    {
      // Get and compare ports of RS1 and RS2
      if (getPort() != other.getPort())
      {
        return false;
      }
      // Get and compare addresses of RS1 and RS2
      // Normalize local addresses to null for fast comparison.
      final InetAddress[] thisAddresses =
          isLocalAddress() ? null : InetAddress.getAllByName(getHost());
      final InetAddress[] otherAddresses =
          other.isLocalAddress() ? null : InetAddress.getAllByName(other
              .getHost());
      // Now compare addresses, if at least one match, this is the same server.
      if (thisAddresses == null && otherAddresses == null)
      {
        // Both local addresses.
        return true;
      }
      else if (thisAddresses == null || otherAddresses == null)
      {
        // One local address and one non-local.
        return false;
      }
      // Both non-local addresses: check for overlap.
      for (InetAddress thisAddress : thisAddresses)
      {
        for (InetAddress otherAddress : otherAddresses)
        {
          if (thisAddress.equals(otherAddress))
          {
            return true;
          }
        }
      }
      return false;
    }
    catch (UnknownHostException ex)
    {
      // Unknown RS: should not happen
      return false;
    }
  }
  /**
   * Returns {@code true} if the provided Object is a HostPort object
   * with the same host name and port than this HostPort object.
   * @param obj the reference object with which to compare.
   * @return  {@code true} if this object is the same as the obj
   * argument; {@code false} otherwise.
   * Returns {@code true} if the provided Object is a HostPort object with the
   * same host name and port than this HostPort object.
   *
   * @param obj
   *          the reference object with which to compare.
   * @return {@code true} if this object is the same as the obj argument;
   *         {@code false} otherwise.
   */
  @Override
  public boolean equals(Object obj)
  {
    boolean equals = false;
    if (obj != null)
    {
    if (obj == null)
      return false;
      if (obj == this)
      return true;
    if (obj instanceof HostPort)
      {
        equals = true;
      final HostPort other = (HostPort) obj;
      return toNormalizedString().equals(other.toNormalizedString());
      }
      else if (obj instanceof HostPort)
      {
        equals = toString().equals(obj.toString());
      }
    }
    return equals;
    return false;
  }
  /**
@@ -150,9 +465,11 @@
   *
   * @return  A hash code for this HostPort object.
   */
  @Override
  public int hashCode()
  {
    return toString().hashCode();
    return toNormalizedString().hashCode();
  }
}
opends/src/server/org/opends/server/types/LDAPURL.java
@@ -23,27 +23,23 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 *      Portions copyright 2012-2013 ForgeRock AS.
 */
package org.opends.server.types;
import org.opends.messages.Message;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.StringTokenizer;
import org.opends.messages.Message;
import org.opends.server.core.DirectoryServer;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.messages.UtilityMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.types.ResultCode.*;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a data structure that represents the components
 * of an LDAP URL, including the scheme, host, port, base DN,
@@ -343,19 +339,17 @@
    {
      Message message =
          ERR_LDAPURL_NO_COLON_SLASH_SLASH.get(String.valueOf(url));
      throw new DirectoryException(
                     ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
      throw new DirectoryException(INVALID_ATTRIBUTE_SYNTAX, message);
    }
    else if (schemeEndPos == 0)
    {
      Message message =
          ERR_LDAPURL_NO_SCHEME.get(String.valueOf(url));
      throw new DirectoryException(
                     ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
      Message message = ERR_LDAPURL_NO_SCHEME.get(String.valueOf(url));
      throw new DirectoryException(INVALID_ATTRIBUTE_SYNTAX, message);
    }
    else
    {
      scheme = urlDecode(url.substring(0, schemeEndPos));
      // FIXME also need to check that the scheme is actually ldap/ldaps!!
    }
@@ -382,61 +376,46 @@
      {
        break;
      }
      else
      {
        pos++;
      }
    }
    if (pos > startPos)
    {
      String hostPort = url.substring(startPos, pos);
      int colonPos = hostPort.indexOf(':');
      int colonPos = hostPort.lastIndexOf(':');
      if (colonPos < 0)
      {
        host = urlDecode(hostPort);
      }
      else if (colonPos == 0)
      {
        Message message =
            ERR_LDAPURL_NO_HOST.get(String.valueOf(url));
        throw new DirectoryException(
                       ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
        Message message = ERR_LDAPURL_NO_HOST.get(String.valueOf(url));
        throw new DirectoryException(INVALID_ATTRIBUTE_SYNTAX, message);
      }
      else if (colonPos == (hostPort.length() - 1))
      {
        Message message =
            ERR_LDAPURL_NO_PORT.get(String.valueOf(url));
        throw new DirectoryException(
                       ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
        Message message = ERR_LDAPURL_NO_PORT.get(String.valueOf(url));
        throw new DirectoryException(INVALID_ATTRIBUTE_SYNTAX, message);
      }
      else
      {
        host = urlDecode(hostPort.substring(0, colonPos));
        try
        {
          port = Integer.parseInt(hostPort.substring(colonPos+1));
          final HostPort hp = HostPort.valueOf(hostPort);
          host = urlDecode(hp.getHost());
          port = hp.getPort();
        }
        catch (Exception e)
        catch (NumberFormatException e)
        {
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
          }
          Message message = ERR_LDAPURL_CANNOT_DECODE_PORT.get(
              String.valueOf(url), hostPort.substring(colonPos+1));
          throw new DirectoryException(
                        ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
          throw new DirectoryException(INVALID_ATTRIBUTE_SYNTAX, message);
        }
        if ((port <= 0) || (port > 65535))
        catch (IllegalArgumentException e)
        {
          Message message =
              ERR_LDAPURL_INVALID_PORT.get(String.valueOf(url), port);
          throw new DirectoryException(
                        ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
          throw new DirectoryException(INVALID_ATTRIBUTE_SYNTAX, message);
        }
      }
    }
@@ -1309,6 +1288,7 @@
   * @return  <CODE>true</CODE> if the object is equal to this LDAP
   *          URL, or <CODE>false</CODE> if not.
   */
  @Override
  public boolean equals(Object o)
  {
    if (o == null)
@@ -1481,6 +1461,7 @@
   *
   * @return  The hash code for this LDAP URL.
   */
  @Override
  public int hashCode()
  {
    int hashCode = 0;
@@ -1550,6 +1531,7 @@
   *
   * @return  A string representation of this LDAP URL.
   */
  @Override
  public String toString()
  {
    StringBuilder buffer = new StringBuilder();
opends/src/server/org/opends/server/util/StaticUtils.java
@@ -29,7 +29,10 @@
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
@@ -4507,84 +4510,6 @@
  }
  /**
   * Returns {@code true} if the provided IPv4 or IPv6 address or host name
   * represents the address of one of the interfaces on the current host
   * machine.
   *
   * @param addressString
   *          The IPv4 or IPv6 address or host name.
   * @return {@code true} if the provided IPv4 or IPv6 address or host name
   *         represents the address of one of the interfaces on the current host
   *         machine.
   */
  public static boolean isLocalAddress(String addressString)
  {
    try
    {
      return isLocalAddress(InetAddress.getByName(addressString));
    }
    catch (UnknownHostException e)
    {
      return false;
    }
  }
  /**
   * Returns {@code true} if the provided {@code InetAddress} represents the
   * address of one of the interfaces on the current host machine.
   *
   * @param address
   *          The network address.
   * @return {@code true} if the provided {@code InetAddress} represents the
   *         address of one of the interfaces on the current host machine.
   */
  public static boolean isLocalAddress(InetAddress address)
  {
    return address.isLoopbackAddress() || getLocalAddresses().contains(address);
  }
  // Time-stamp acts as memory barrier for networkInterfaces.
  private static final long CACHED_LOCAL_ADDRESSES_TIMEOUT_MS = 30 * 1000;
  private static volatile long localAddressesTimeStamp = 0;
  private static Set<InetAddress> localAddresses = new HashSet<InetAddress>();
  private static Set<InetAddress> getLocalAddresses()
  {
    final long currentTimeStamp = System.currentTimeMillis();
    if (localAddressesTimeStamp
        < (currentTimeStamp - CACHED_LOCAL_ADDRESSES_TIMEOUT_MS))
    {
      // Refresh the cache.
      try
      {
        final Enumeration<NetworkInterface> i = NetworkInterface
            .getNetworkInterfaces();
        final Set<InetAddress> newLocalAddresses = new HashSet<InetAddress>();
        while (i.hasMoreElements())
        {
          NetworkInterface n = i.nextElement();
          Enumeration<InetAddress> j = n.getInetAddresses();
          while (j.hasMoreElements())
          {
            newLocalAddresses.add(j.nextElement());
          }
        }
        localAddresses = newLocalAddresses;
      }
      catch (SocketException e)
      {
        // Ignore and keep the old set.
        TRACER.debugCaught(DebugLogLevel.WARNING, e);
      }
      localAddressesTimeStamp = currentTimeStamp; // Publishes.
    }
    return localAddresses;
  }
  /**
   * Closes the provided {@link Closeable}'s ignoring any errors which
   * occurred.
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ComputeBestServerTest.java
@@ -70,9 +70,9 @@
  private static final int myId3 = 3;
  // definitions for server names
  private static final String WINNER = "winner";
  private static final String LOOSER1 = "looser1";
  private static final String LOOSER2 = "looser2";
  private static final String WINNER = "winner:389";
  private static final String LOOSER1 = "looser1:389";
  private static final String LOOSER2 = "looser2:389";
  private void debugInfo(String s)
  {
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/FractionalReplicationTest.java
@@ -390,11 +390,7 @@
    assertTrue(replicationDomain.isConnected());
    // Check connected server port
    String serverStr = replicationDomain.getReplicationServer();
    int index = serverStr.lastIndexOf(':');
    assertTrue(index > -1, "Unable to find port number in: " + serverStr);
    String rdPortStr = serverStr.substring(index + 1);
    int rdPort = Integer.valueOf(rdPortStr);
    assertEquals(rdPort, replServerPort);
    assertEquals(HostPort.valueOf(serverStr).getPort(), replServerPort);
  }
  private void initTest() throws Exception
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/GroupIdHandshakeTest.java
@@ -27,12 +27,6 @@
 */
package org.opends.server.replication.plugin;
import static org.opends.server.TestCaseUtils.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.StaticUtils.*;
import static org.testng.Assert.*;
import java.io.File;
import java.io.IOException;
import java.util.SortedSet;
@@ -48,10 +42,15 @@
import org.opends.server.replication.server.ReplServerFakeConfiguration;
import org.opends.server.replication.server.ReplicationServer;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.HostPort;
import org.opends.server.util.StaticUtils;
import org.testng.annotations.Test;
import static org.opends.server.TestCaseUtils.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.testng.Assert.*;
/**
 * Some real connections from clients that should end up with a server with
 * the right groupId if available.
@@ -97,7 +96,7 @@
    findFreePorts();
  }
  private void endTest()
  private void endTest() throws Exception
  {
    if (rd1 != null)
    {
@@ -111,14 +110,8 @@
      rd2 = null;
    }
    try
    {
      // Clear any reference to a domain in synchro plugin
      MultimasterReplication.deleteDomain(DN.decode(TEST_ROOT_DN_STRING));
    } catch (DirectoryException ex)
    {
      fail("Error deleting reference to domain: " + TEST_ROOT_DN_STRING);
    }
    rs1 = clear(rs1);
    rs2 = clear(rs2);
@@ -147,6 +140,7 @@
   * before failing.
   */
  private void checkConnection(int secTimeout, int dsId, int rsId, String msg)
      throws Exception
  {
    int rsPort = -1;
@@ -190,17 +184,7 @@
      if (connected)
      {
        String serverStr = rd.getReplicationServer();
        int index = serverStr.lastIndexOf(':');
        if ((index == -1) || (index >= serverStr.length()))
          fail("Enable to find port number in: " + serverStr);
        String rdPortStr = serverStr.substring(index + 1);
        try
        {
          rdPort = (new Integer(rdPortStr)).intValue();
        } catch (Exception e)
        {
          fail("Enable to get an int from: " + rdPortStr);
        }
        rdPort = HostPort.valueOf(serverStr).getPort();
        if (rdPort == rsPort)
          rightPort = true;
      }
@@ -214,13 +198,7 @@
      }
      // Sleep 1 second
      try
      {
        Thread.sleep(1000);
      } catch (InterruptedException ex)
      {
        fail("Error sleeping " + stackTraceToSingleLineString(ex));
      }
      nSec++;
      if (nSec > secTimeout)
@@ -274,12 +252,10 @@
  /**
   * Creates a new ReplicationServer.
   */
  private ReplicationServer createReplicationServer(int serverId,
    int groupId, String testCase)
  private ReplicationServer createReplicationServer(int serverId, int groupId,
      String testCase) throws Exception
  {
    SortedSet<String> replServers = new TreeSet<String>();
    try
    {
      int port = -1;
      if (serverId == RS1_ID)
      {
@@ -288,28 +264,33 @@
        {
          // 2 servers used for this test case.
          replServers.add("localhost:" + rs2Port);
        } else if (testCase.equals("testRSWithManyGroupIds"))
      }
      else if (testCase.equals("testRSWithManyGroupIds"))
        {
          // 3 servers used for this test case.
          replServers.add("localhost:" + rs2Port);
          replServers.add("localhost:" + rs3Port);
        } else
      }
      else
          fail("Unknown test case: " + testCase);
      } else if (serverId == RS2_ID)
    }
    else if (serverId == RS2_ID)
      {
        port = rs2Port;
        if (testCase.equals("testRSWithSameGroupIds"))
        {
          // 2 servers used for this test case.
          replServers.add("localhost:" + rs1Port);
        } else if (testCase.equals("testRSWithManyGroupIds"))
      }
      else if (testCase.equals("testRSWithManyGroupIds"))
        {
          // 3 servers used for this test case.
          replServers.add("localhost:" + rs1Port);
          replServers.add("localhost:" + rs3Port);
        } else
          fail("Unknown test case: " + testCase);
      } else if (serverId == RS3_ID)
    }
    else if (serverId == RS3_ID)
      {
        port = rs3Port;
        if (testCase.equals("testRSWithManyGroupIds"))
@@ -317,9 +298,11 @@
          // 3 servers used for this test case.
          replServers.add("localhost:" + rs2Port);
          replServers.add("localhost:" + rs3Port);
        } else
      }
      else
          fail("Invalid test case: " + testCase);
      } else
    }
    else
      {
        fail("Unknown replication server id.");
      }
@@ -328,23 +311,14 @@
      ReplServerFakeConfiguration conf =
        new ReplServerFakeConfiguration(port, dir, 0, serverId, 0, 100,
        replServers, groupId, 1000, 5000);
      ReplicationServer replicationServer = new ReplicationServer(conf);
      return replicationServer;
    } catch (Exception e)
    {
      fail("createReplicationServer " + stackTraceToSingleLineString(e));
    }
    return null;
    return new ReplicationServer(conf);
  }
  /**
   * Creates a new ReplicationDomain.
   */
  private LDAPReplicationDomain createReplicationDomain(int serverId,
    int groupId, String testCase)
  {
    try
      int groupId, String testCase) throws Exception
    {
      SortedSet<String> replServers = createRSListForTestCase(testCase);
      DN baseDn = DN.decode(TEST_ROOT_DN_STRING);
@@ -354,12 +328,6 @@
        MultimasterReplication.createNewDomain(domainConf);
      replicationDomain.start();
      return replicationDomain;
    } catch (Exception e)
    {
      fail("createReplicationDomain " + stackTraceToSingleLineString(e));
    }
    return null;
  }
  /**
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ReplicationServerFailoverTest.java
@@ -27,12 +27,6 @@
 */
package org.opends.server.replication.plugin;
import static org.opends.server.TestCaseUtils.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.StaticUtils.*;
import static org.testng.Assert.*;
import java.io.File;
import java.io.IOException;
import java.util.SortedSet;
@@ -42,16 +36,22 @@
import org.opends.messages.Message;
import org.opends.messages.Severity;
import org.opends.server.TestCaseUtils;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.server.ReplServerFakeConfiguration;
import org.opends.server.replication.server.ReplicationServer;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.HostPort;
import org.opends.server.util.StaticUtils;
import org.testng.annotations.Test;
import static org.opends.server.TestCaseUtils.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.testng.Assert.*;
/**
 * Test if the replication domain is able to switch of replication server
 * if there is some replication server failure.
@@ -93,7 +93,7 @@
    findFreePorts();
  }
  private void endTest()
  private void endTest() throws Exception
  {
    if (rd1 != null)
    {
@@ -107,14 +107,8 @@
      rd2 = null;
    }
    try
    {
      // Clear any reference to a domain in synchro plugin
      MultimasterReplication.deleteDomain(DN.decode(TEST_ROOT_DN_STRING));
    } catch (DirectoryException ex)
    {
      fail("Error deleting reference to domain: " + TEST_ROOT_DN_STRING);
    }
    rs1 = clear(rs1);
    rs2 = clear(rs2);
@@ -166,7 +160,7 @@
      rd1 = createReplicationDomain(baseDn, DS1_ID);
      // Wait a bit so that connections are performed
      sleep(2000);
      Thread.sleep(2000);
      // DS1 connected to RS1 ?
      // Check which replication server is connected to this LDAP server
@@ -237,7 +231,7 @@
      rd2 = createReplicationDomain(baseDn, DS2_ID);
      // Wait a bit so that connections are performed
      sleep(3000);
      Thread.sleep(3000);
      // Simulate RS1 failure
      rs1.remove();
@@ -282,26 +276,14 @@
    }
  }
  private void sleep(long time)
  {
    try
    {
      Thread.sleep(time);
    } catch (InterruptedException ex)
    {
      fail("Error sleeping " + stackTraceToSingleLineString(ex));
    }
  }
  /**
   * Check connection of the provided replication domain to the provided
   * replication server. Waits for connection to be ok up to secTimeout seconds
   * before failing.
   */
  private void checkConnection(int secTimeout, int dsId, int rsId, String msg)
      throws Exception
  {
    int rsPort = -1;
    LDAPReplicationDomain rd = null;
    switch (dsId)
    {
@@ -315,6 +297,7 @@
        fail("Unknown replication domain server id.");
    }
    int rsPort = -1;
    switch (rsId)
    {
      case RS1_ID:
@@ -339,17 +322,7 @@
      if (connected)
      {
        String serverStr = rd.getReplicationServer();
        int index = serverStr.lastIndexOf(':');
        if ((index == -1) || (index >= serverStr.length()))
          fail("Enable to find port number in: " + serverStr);
        String rdPortStr = serverStr.substring(index + 1);
        try
        {
          rdPort = (new Integer(rdPortStr)).intValue();
        } catch (Exception e)
        {
          fail("Enable to get an int from: " + rdPortStr);
        }
        rdPort = HostPort.valueOf(serverStr).getPort();
        if (rdPort == rsPort)
          rightPort = true;
      }
@@ -363,13 +336,7 @@
      }
      // Sleep 1 second
      try
      {
        Thread.sleep(1000);
      } catch (InterruptedException ex)
      {
        fail("Error sleeping " + stackTraceToSingleLineString(ex));
      }
      nSec++;
      if (nSec > secTimeout)
@@ -396,22 +363,22 @@
  /**
   * Creates a new ReplicationServer.
   */
  private ReplicationServer createReplicationServer(int serverId,
    String suffix)
  private ReplicationServer createReplicationServer(int serverId, String suffix)
      throws ConfigException
  {
    SortedSet<String> replServers = new TreeSet<String>();
    try
    {
      int port = -1;
      if (serverId == RS1_ID)
      {
        port = rs1Port;
        replServers.add("localhost:" + rs2Port);
      } else if (serverId == RS2_ID)
    }
    else if (serverId == RS2_ID)
      {
        port = rs2Port;
        replServers.add("localhost:" + rs1Port);
      } else
    }
    else
      {
        fail("Unknown replication server id.");
      }
@@ -420,59 +387,37 @@
      ReplServerFakeConfiguration conf =
        new ReplServerFakeConfiguration(port, dir, 0, serverId, 0, 100,
        replServers);
      ReplicationServer replicationServer = new ReplicationServer(conf);
      return replicationServer;
    } catch (Exception e)
    {
      fail("createReplicationServer " + stackTraceToSingleLineString(e));
    }
    return null;
    return new ReplicationServer(conf);
  }
  /**
   * Creates a new ReplicationDomain.
   */
  private LDAPReplicationDomain createReplicationDomain(DN baseDn, int serverId)
      throws Exception
  {
    SortedSet<String> replServers = new TreeSet<String>();
    try
    {
      // Create a domain with two replication servers
      replServers.add("localhost:" + rs1Port);
      replServers.add("localhost:" + rs2Port);
      DomainFakeCfg domainConf =
        new DomainFakeCfg(baseDn, serverId, replServers);
    DomainFakeCfg domainConf = new DomainFakeCfg(baseDn, serverId, replServers);
      //domainConf.setHeartbeatInterval(500);
      LDAPReplicationDomain replicationDomain =
        MultimasterReplication.createNewDomain(domainConf);
      replicationDomain.start();
      return replicationDomain;
    } catch (Exception e)
    {
      fail("createReplicationDomain " + stackTraceToSingleLineString(e));
    }
    return null;
  }
  private int findReplServerConnected(LDAPReplicationDomain rd)
  {
    int rsPort = -1;
    // First check that the Replication domain is connected
    if (!rd.isConnected())
      return rsPort;
      return -1;
    String serverStr = rd.getReplicationServer();
    int index = serverStr.lastIndexOf(':');
    if ((index == -1) || (index >= serverStr.length()))
      fail("Enable to find port number in: " + serverStr);
    rsPort = (new Integer(serverStr.substring(index + 1)));
      return rsPort;
    return HostPort.valueOf(serverStr).getPort();
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/TopologyViewTest.java
@@ -27,12 +27,6 @@
 */
package org.opends.server.replication.plugin;
import static org.opends.server.TestCaseUtils.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.StaticUtils.*;
import static org.testng.Assert.*;
import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -43,6 +37,7 @@
import org.opends.messages.Severity;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.std.meta.ReplicationDomainCfgDefn.AssuredType;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.ReplicationTestCase;
@@ -54,10 +49,15 @@
import org.opends.server.replication.server.ReplServerFakeConfiguration;
import org.opends.server.replication.server.ReplicationServer;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.HostPort;
import org.opends.server.util.StaticUtils;
import org.testng.annotations.Test;
import static org.opends.server.TestCaseUtils.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.testng.Assert.*;
/**
 * Some tests to know if at any time the view DSs and RSs have of the current
 * topology is accurate, even after some connections, disconnections and
@@ -173,7 +173,7 @@
    findFreePorts();
  }
  private void endTest()
  private void endTest() throws Exception
  {
    if (rd1 != null)
    {
@@ -211,14 +211,8 @@
      rd6 = null;
    }
    try
    {
      // Clear any reference to a domain in synchro plugin
      MultimasterReplication.deleteDomain(DN.decode(TEST_ROOT_DN_STRING));
    } catch (DirectoryException ex)
    {
      fail("Error deleting reference to domain: " + TEST_ROOT_DN_STRING);
    }
    if (rs1 != null)
    {
@@ -251,23 +245,13 @@
    rs3Port = -1;
  }
  private void sleep(long time)
  {
    try
    {
      Thread.sleep(time);
    } catch (InterruptedException ex)
    {
      fail("Error sleeping " + stackTraceToSingleLineString(ex));
    }
  }
  /**
   * Check connection of the provided replication domain to the provided
   * replication server. Waits for connection to be ok up to secTimeout seconds
   * before failing.
   */
  private void checkConnection(int secTimeout, int dsId, int rsId)
      throws Exception
  {
    int rsPort = -1;
    LDAPReplicationDomain rd = null;
@@ -322,17 +306,7 @@
      if (connected)
      {
        String serverStr = rd.getReplicationServer();
        int index = serverStr.lastIndexOf(':');
        if ((index == -1) || (index >= serverStr.length()))
          fail("Enable to find port number in: " + serverStr);
        String rdPortStr = serverStr.substring(index + 1);
        try
        {
          rdPort = (new Integer(rdPortStr)).intValue();
        } catch (Exception e)
        {
          fail("Enable to get an int from: " + rdPortStr);
        }
        rdPort = HostPort.valueOf(serverStr).getPort();
        if (rdPort == rsPort)
          rightPort = true;
      }
@@ -346,13 +320,7 @@
      }
      // Sleep 1 second
      try
      {
        Thread.sleep(1000);
      } catch (InterruptedException ex)
      {
        fail("Error sleeping " + stackTraceToSingleLineString(ex));
      }
      nSec++;
      if (nSec > secTimeout)
@@ -406,8 +374,7 @@
   * Creates a new ReplicationServer.
   */
  private ReplicationServer createReplicationServer(int rsId, String testCase)
  {
    try
      throws ConfigException
    {
      SortedSet<String> replServers = createRSListExceptOne(rsId);
@@ -435,14 +402,7 @@
      ReplServerFakeConfiguration conf =
        new ReplServerFakeConfiguration(rsPort, dir, 0, rsId, 0, 100,
        replServers, groupId, 1000, 5000);
      ReplicationServer replicationServer = new ReplicationServer(conf);
      return replicationServer;
    } catch (Exception e)
    {
      fail("createReplicationServer " + stackTraceToSingleLineString(e));
    }
    return null;
    return new ReplicationServer(conf);
  }
  /**
@@ -450,8 +410,7 @@
   * know RSs according to DS id
   */
  private LDAPReplicationDomain createReplicationDomain(int dsId)
  {
    try
      throws Exception
    {
      SortedSet<String> replServers = new TreeSet<String>();
      int groupId = -1;
@@ -530,12 +489,6 @@
      replicationDomain.start();
      return replicationDomain;
    } catch (Exception e)
    {
      fail("createReplicationDomain " + stackTraceToSingleLineString(e));
    }
    return null;
  }
  // Definitions of steps for the test case
@@ -631,7 +584,7 @@
       */
      debugInfo("*** STEP 2 ***");
      rd2 = createReplicationDomain(DS2_ID);
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      theoricalTopoView = createTheoreticalTopoViewForStep(STEP_2);
@@ -642,7 +595,7 @@
       */
      debugInfo("*** STEP 3 ***");
      rs2 = createReplicationServer(RS2_ID, testCase);
      sleep(1000); // Let time to topo msgs being propagated through the network
      Thread.sleep(1000); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      theoricalTopoView = createTheoreticalTopoViewForStep(STEP_3);
@@ -653,7 +606,7 @@
       */
      debugInfo("*** STEP 4 ***");
      rd3 = createReplicationDomain(DS3_ID);
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -665,7 +618,7 @@
       */
      debugInfo("*** STEP 5 ***");
      rd4 = createReplicationDomain(DS4_ID);
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -679,7 +632,7 @@
       */
      debugInfo("*** STEP 6 ***");
      rd5 = createReplicationDomain(DS5_ID);
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -695,7 +648,7 @@
       */
      debugInfo("*** STEP 7 ***");
      rs3 = createReplicationServer(RS3_ID, testCase);
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -712,7 +665,7 @@
       */
      debugInfo("*** STEP 8 ***");
      rd6 = createReplicationDomain(DS6_ID);
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -729,7 +682,7 @@
       */
      debugInfo("*** STEP 9 ***");
      rd6.disable();
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -747,7 +700,7 @@
       */
      debugInfo("*** STEP 10 ***");
      rd6.enable();
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -765,7 +718,7 @@
       */
      debugInfo("*** STEP 11 ***");
      rs3.remove();
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -783,7 +736,7 @@
       */
      debugInfo("*** STEP 12 ***");
      rs3 = createReplicationServer(RS3_ID, testCase);
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS3_ID, RS2_ID);
@@ -802,7 +755,7 @@
       */
      debugInfo("*** STEP 13 ***");
      rs2.remove();
      sleep(500); // Let time to topo msgs being propagated through the network
      Thread.sleep(500); // Let time to topo msgs being propagated through the network
      checkConnection(30, DS1_ID, RS1_ID);
      checkConnection(30, DS2_ID, RS1_ID);
      checkConnection(30, DS5_ID, RS3_ID);
@@ -1062,8 +1015,9 @@
   * this method is called.
   */
  private void checkTopoView(int[] dsIdList, TopoView theoricalTopoView)
      throws Exception
  {
   sleep(500);
   Thread.sleep(500);
   for(int currentDsId : dsIdList)
   {
     LDAPReplicationDomain rd = null;
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/AssuredReplicationServerTest.java
@@ -27,11 +27,6 @@
 */
package org.opends.server.replication.server;
import static org.opends.server.TestCaseUtils.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.testng.Assert.*;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
@@ -56,11 +51,17 @@
import org.opends.server.replication.service.ReplicationDomain;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.HostPort;
import org.opends.server.util.StaticUtils;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.opends.server.TestCaseUtils.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.testng.Assert.*;
/**
 * Test Server part of the assured feature in both safe data and
 * safe read modes.
@@ -471,12 +472,9 @@
      // Test connection
      assertTrue(fakeReplicationDomain.isConnected());
      // Check connected server port
      String serverStr = fakeReplicationDomain.getReplicationServer();
      int index = serverStr.lastIndexOf(':');
      assertFalse(index == -1, "Enable to find port number in: " + serverStr);
      String rdPortStr = serverStr.substring(index + 1);
      int rdPort = Integer.parseInt(rdPortStr);// fail the test if not an int
      assertEquals(rdPort, rsPort);
    HostPort rd =
        HostPort.valueOf(fakeReplicationDomain.getReplicationServer());
      assertEquals(rd.getPort(), rsPort);
      return fakeReplicationDomain;
  }
@@ -999,7 +997,7 @@
                  AckMsg ackMsg = new AckMsg(updateMsg.getCSN());
                  ackMsg.setHasWrongStatus(true);
                  List<Integer> failedServers = new ArrayList<Integer>();
                  failedServers.add((serverId + 10));
                  failedServers.add(serverId + 10);
                  ackMsg.setFailedServers(failedServers);
                  session.publish(ackMsg);
                  ackReplied = true;
@@ -1012,7 +1010,7 @@
                  AckMsg ackMsg = new AckMsg(updateMsg.getCSN());
                  ackMsg.setHasReplayError(true);
                  List<Integer> failedServers = new ArrayList<Integer>();
                  failedServers.add((serverId + 10));
                  failedServers.add(serverId + 10);
                  ackMsg.setFailedServers(failedServers);
                  session.publish(ackMsg);
                  ackReplied = true;
@@ -1120,20 +1118,6 @@
  }
  /**
   * Sleep a while
   */
  private void sleep(long time)
  {
    try
    {
      Thread.sleep(time);
    } catch (InterruptedException ex)
    {
      fail("Error sleeping " + ex);
    }
  }
  /**
   * See testSafeDataLevelOne comment.
   * This is a facility to run the testSafeDataLevelOne in precommit in simplest
   * case, so that precommit run test something and is not long.
@@ -1275,7 +1259,7 @@
      long sendUpdateTime = System.currentTimeMillis() - startTime;
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      if (mainDsGid == DEFAULT_GID)
      {
        // Check monitoring values (check that ack has been correctly received)
@@ -1294,7 +1278,7 @@
      }
      // Sanity check
      sleep(500);           // Let time to update to reach other servers
      Thread.sleep(500);           // Let time to update to reach other servers
      assertEquals(fakeRd1.getReceivedUpdates(), 0);
      assertTrue(fakeRd1.receivedUpdatesOk());
      if (otherFakeDS)
@@ -1637,7 +1621,7 @@
      long sendUpdateTime = System.currentTimeMillis() - startTime;
      // Check
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked and let time the update to reach other servers
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked and let time the update to reach other servers
      checkTimeAndMonitoringSafeData(1, acknowledgedUpdates, timeoutUpdates, serverErrors, sendUpdateTime, nWishedServers, eligibleServers, expectedServers);
      checkWhatHasBeenReceivedSafeData(1, otherFakeDS, otherFakeDsGenId, fakeRs1GenId, fakeRs2GenId, fakeRs3GenId, expectedServers);
@@ -1668,7 +1652,7 @@
      sendUpdateTime = System.currentTimeMillis() - startTime;
      // Check
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked and let time the update to reach other servers
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked and let time the update to reach other servers
      checkTimeAndMonitoringSafeData(2, acknowledgedUpdates, timeoutUpdates, serverErrors, sendUpdateTime, nWishedServers, eligibleServers, expectedServers);
      checkWhatHasBeenReceivedSafeData(2, otherFakeDS, otherFakeDsGenId, fakeRs1GenId, fakeRs2GenId, -1L, expectedServers);
@@ -1699,7 +1683,7 @@
      sendUpdateTime = System.currentTimeMillis() - startTime;
      // Check
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked and let time the update to reach other servers
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked and let time the update to reach other servers
      checkTimeAndMonitoringSafeData(3, acknowledgedUpdates, timeoutUpdates, serverErrors, sendUpdateTime, nWishedServers, eligibleServers, expectedServers);
      checkWhatHasBeenReceivedSafeData(3, otherFakeDS, otherFakeDsGenId, fakeRs1GenId, -1L, -1L, expectedServers);
@@ -1730,7 +1714,7 @@
      sendUpdateTime = System.currentTimeMillis() - startTime;
      // Check
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked and let time the update to reach other servers
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked and let time the update to reach other servers
      checkTimeAndMonitoringSafeData(4, acknowledgedUpdates, timeoutUpdates, serverErrors, sendUpdateTime, nWishedServers, eligibleServers, expectedServers);
      checkWhatHasBeenReceivedSafeData(4, otherFakeDS, otherFakeDsGenId, -1L, -1L, -1L, expectedServers);
    } finally
@@ -1937,7 +1921,8 @@
   * Wait until number of fake DSs and fake RSs are available in the topo view of the passed
   * fake DS or throw an assertion if timeout waiting.
   */
  private void waitForStableTopo(FakeReplicationDomain fakeRd, int expectedDs, int expectedRs)
  private void waitForStableTopo(FakeReplicationDomain fakeRd, int expectedDs,
      int expectedRs) throws Exception
  {
    List<DSInfo> dsInfo = null;
    List<RSInfo> rsInfo = null;
@@ -1952,7 +1937,7 @@
        debugInfo("waitForStableTopo: expected topo obtained after " + nSec + " second(s).");
        return;
      }
      sleep(100);
      Thread.sleep(100);
      nSec = (System.currentTimeMillis() - startTime) / 1000;
    }
    while (nSec < 30);
@@ -2223,7 +2208,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSdSentUpdates(), 1);
      assertEquals(fakeRd1.getAssuredSdAcknowledgedUpdates(), 1);
      assertEquals(fakeRd1.getAssuredSdTimeoutUpdates(), 0);
@@ -2281,7 +2266,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSrSentUpdates(), 1);
      assertEquals(fakeRd1.getAssuredSrAcknowledgedUpdates(), 1);
      assertEquals(fakeRd1.getAssuredSrNotAcknowledgedUpdates(), 0);
@@ -2323,7 +2308,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSrSentUpdates(), 2);
      assertEquals(fakeRd1.getAssuredSrAcknowledgedUpdates(), 2);
      assertEquals(fakeRd1.getAssuredSrNotAcknowledgedUpdates(), 0);
@@ -2376,7 +2361,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSrSentUpdates(), 3);
      assertEquals(fakeRd1.getAssuredSrAcknowledgedUpdates(), 3);
      assertEquals(fakeRd1.getAssuredSrNotAcknowledgedUpdates(), 0);
@@ -2431,7 +2416,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSrSentUpdates(), 4);
      assertEquals(fakeRd1.getAssuredSrAcknowledgedUpdates(), 4);
      assertEquals(fakeRd1.getAssuredSrNotAcknowledgedUpdates(), 0);
@@ -2472,7 +2457,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSrSentUpdates(), 5);
      assertEquals(fakeRd1.getAssuredSrAcknowledgedUpdates(), 5);
      assertEquals(fakeRd1.getAssuredSrNotAcknowledgedUpdates(), 0);
@@ -2726,7 +2711,7 @@
      }
      // Sleep a while as counters are updated just after sending thread is unblocked
      sleep(500);
      Thread.sleep(500);
      // Check monitoring values in DS 1
      //
@@ -3054,7 +3039,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(1000); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(1000); // Sleep a while as counters are updated just after sending thread is unblocked
      checkDSSentAndAcked(fakeRd1, 1);
@@ -3126,7 +3111,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME, "Exceeded max send time: " + sendUpdateTime);
      // Check monitoring values (check that ack has been correctly received)
      sleep(1000); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(1000); // Sleep a while as counters are updated just after sending thread is unblocked
      checkDSSentAndAcked(fakeRd1, 2);
@@ -3302,7 +3287,7 @@
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      checkDSSentAndAcked(fakeRd1, 1);
@@ -3430,7 +3415,7 @@
        assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      // Check monitoring values (check that ack has been correctly received)
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      if (fakeDsIsEligible)
      {
@@ -3602,12 +3587,12 @@
        }
        else
        {
          sleep(1000);
          Thread.sleep(1000);
        }
      }
      assertFalse(error, "DS2 not in degraded status");
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSrSentUpdates(), 4);
      assertEquals(fakeRd1.getAssuredSrAcknowledgedUpdates(), 0);
      assertEquals(fakeRd1.getAssuredSrNotAcknowledgedUpdates(), 4);
@@ -3651,7 +3636,7 @@
      // RS should ack quickly as DS2 degraded and not eligible for assured
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSrSentUpdates(), 5);
      assertEquals(fakeRd1.getAssuredSrAcknowledgedUpdates(), 1);
      assertEquals(fakeRd1.getAssuredSrNotAcknowledgedUpdates(), 4);
@@ -3709,7 +3694,7 @@
        }
        else
        {
          sleep(1000);
          Thread.sleep(1000);
        }
      }
      assertFalse(error, "DS2 not back to normal status");
@@ -3758,7 +3743,7 @@
      // RS should ack quickly as DS2 degraded and not eligible for assured
      assertTrue(sendUpdateTime < MAX_SEND_UPDATE_TIME);
      sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      Thread.sleep(500); // Sleep a while as counters are updated just after sending thread is unblocked
      assertEquals(fakeRd1.getAssuredSrSentUpdates(), 6);
      assertEquals(fakeRd1.getAssuredSrAcknowledgedUpdates(), 2);
      assertEquals(fakeRd1.getAssuredSrNotAcknowledgedUpdates(), 4);
opends/tests/unit-tests-testng/src/server/org/opends/server/types/HostPortTest.java
New file
@@ -0,0 +1,122 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Copyright 2013 ForgeRock AS
 */
package org.opends.server.types;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.*;
@Test(groups = { "precommit", "types" })
@SuppressWarnings("javadoc")
public class HostPortTest extends TypesTestCase
{
  public void valueOfIPv4NoSpaces()
  {
    final String serverURL = "home:1";
    final HostPort hp = HostPort.valueOf(serverURL);
    assertThat(hp.getHost()).isEqualTo("home");
    assertThat(hp.getPort()).isEqualTo(1);
    assertThat(hp.toString()).isEqualTo(serverURL);
  }
  public void valueOfIPv4Spaces()
  {
    final String serverURL = "home:1";
    final HostPort hp = HostPort.valueOf("  " + serverURL + "  ");
    assertThat(hp.getHost()).isEqualTo("home");
    assertThat(hp.getPort()).isEqualTo(1);
    assertThat(hp.toString()).isEqualTo(serverURL);
  }
  public void valueOfEqualsHashCodeIPv4()
  {
    final HostPort hp1 = HostPort.valueOf("home:1");
    final HostPort hp2 = HostPort.valueOf(" home:1 ");
    assertThat(hp1).isEqualTo(hp2);
    assertThat(hp1.hashCode()).isEqualTo(hp2.hashCode());
  }
  public void valueOfIPv6Brackets()
  {
    final String hostName = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
    final String serverURL = "[" + hostName + "]:389";
    final HostPort hp = HostPort.valueOf(serverURL);
    assertThat(hp.getHost()).isEqualTo(hostName);
    assertThat(hp.getPort()).isEqualTo(389);
    assertThat(hp.toString()).isEqualTo(serverURL);
  }
  public void valueOfIPv6NoBrackets()
  {
    final String hostName = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
    final HostPort hp = HostPort.valueOf(hostName + ":389");
    assertThat(hp.getHost()).isEqualTo(hostName);
    assertThat(hp.getPort()).isEqualTo(389);
    assertThat(hp.toString()).isEqualTo("[" + hostName + "]:389");
  }
  public void valueOfEqualsHashCodeIPv6()
  {
    final String hostName = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
    final HostPort hp1 = HostPort.valueOf("[" + hostName + "]:389");
    final HostPort hp2 = HostPort.valueOf(" " + hostName + " : 389 ");
    assertThat(hp1).isEqualTo(hp2);
    assertThat(hp1.hashCode()).isEqualTo(hp2.hashCode());
  }
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void valueOfNoPort()
  {
    HostPort.valueOf("host");
  }
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void valueOfNoHost()
  {
    HostPort.valueOf(":389");
  }
  @Test(expectedExceptions = NumberFormatException.class)
  public void valueOfPortNotANumber()
  {
    HostPort.valueOf("host:port");
  }
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void valueOfPortNumberTooSmall()
  {
    HostPort.valueOf("host:-1");
  }
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void valueOfPortNumberTooBig()
  {
    HostPort.valueOf("host:99999999");
  }
}