From a22acf0c877f931dcce85305b6a5232c805e407b Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Thu, 03 May 2007 07:41:18 +0000
Subject: [PATCH] Fix for issues 1231 and 1234 ('start-ds logs are incomplete when we provide an invalid LDAP port' and 'Server should not start when no connection handler can be enabled').

---
 opends/src/server/org/opends/server/core/DirectoryServer.java  |   87 +++++++++++++++++++--
 opends/src/server/org/opends/server/types/HostPort.java        |   32 ++++++++
 opends/src/server/org/opends/server/util/SetupUtils.java       |   19 ++++
 opends/src/server/org/opends/server/messages/CoreMessages.java |   52 ++++++++++++
 4 files changed, 175 insertions(+), 15 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 3985252..336d878 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -1106,14 +1106,9 @@
       }
 
 
-      // At this point, we should be ready to go.  Start all the connection
-      // handlers.
       if (startConnectionHandlers)
       {
-        for (ConnectionHandler c : connectionHandlers)
-        {
-          c.start();
-        }
+        startConnectionHandlers();
       }
 
 
@@ -6991,7 +6986,81 @@
     }
   }
 
+  /**
+   * Starts the connection handlers defined in the Directory Server
+   * Configuration.
+   *
+   * @throws  ConfigException If there are more than one connection handlers
+   *                          using the same host port or no connection handler
+   *                          are enabled or we could not bind to any of the
+   *                          listeners.
+   */
+  private void startConnectionHandlers() throws ConfigException
+  {
+    LinkedHashSet<HostPort> usedListeners = new LinkedHashSet<HostPort>();
+    LinkedHashSet<String> errorMessages = new LinkedHashSet<String>();
+    // Check that the port specified in the connection handlers is
+    // available.
+    for (ConnectionHandler<?> c : connectionHandlers)
+    {
+      for (HostPort listener : c.getListeners())
+      {
+        if (usedListeners.contains(listener))
+        {
+          // The port was already specified: this is a configuration error,
+          // log a message.
+          int msgID = MSGID_HOST_PORT_ALREADY_SPECIFIED;
+          String message = getMessage(msgID, c.getConnectionHandlerName(),
+              listener.toString());
+          logError(ErrorLogCategory.CONNECTION_HANDLING,
+              ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+          errorMessages.add(message);
 
+        }
+        else if (!SetupUtils.canUseAsPort(
+            listener.getHost(), listener.getPort()))
+        {
+          // Cannot use the specified HostPort: log a message and throw an
+          // InitializationException.
+          int msgID = MSGID_HOST_PORT_CANNOT_BE_USED;
+          String message = getMessage(msgID, listener.toString(),
+              c.getConnectionHandlerName());
+          logError(ErrorLogCategory.CONNECTION_HANDLING,
+              ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+          errorMessages.add(message);
+        }
+        else
+        {
+          usedListeners.add(listener);
+        }
+      }
+    }
+
+    if (errorMessages.size() > 0)
+    {
+      throw new ConfigException(MSGID_ERROR_STARTING_CONNECTION_HANDLERS,
+          getMessage(MSGID_ERROR_STARTING_CONNECTION_HANDLERS));
+    }
+
+
+    // If there are no connection handlers log a message.
+    if (connectionHandlers.isEmpty())
+    {
+      int msgID = MSGID_NOT_AVAILABLE_CONNECTION_HANDLERS;
+      String message = getMessage(msgID);
+      logError(ErrorLogCategory.CONNECTION_HANDLING,
+          ErrorLogSeverity.SEVERE_ERROR, message, msgID);
+      throw new ConfigException(MSGID_ERROR_STARTING_CONNECTION_HANDLERS,
+          getMessage(MSGID_ERROR_STARTING_CONNECTION_HANDLERS));
+    }
+
+    // At this point, we should be ready to go.  Start all the connection
+    // handlers.
+    for (ConnectionHandler c : connectionHandlers)
+    {
+      c.start();
+    }
+  }
 
   /**
    * Retrieves a reference to the Directory Server work queue.
@@ -8871,15 +8940,13 @@
 
       int    msgID   = MSGID_DSCORE_CANNOT_START;
       String message = getMessage(msgID, ie.getMessage());
-      System.err.println(message);
-      System.exit(1);
+      shutDown(directoryServer.getClass().getName(), message);
     }
     catch (Exception e)
     {
       int    msgID   = MSGID_DSCORE_CANNOT_START;
       String message = getMessage(msgID, stackTraceToSingleLineString(e));
-      System.err.println(message);
-      System.exit(1);
+      shutDown(directoryServer.getClass().getName(), message);
     }
   }
 
diff --git a/opends/src/server/org/opends/server/messages/CoreMessages.java b/opends/src/server/org/opends/server/messages/CoreMessages.java
index 1f3f357..eaec91d 100644
--- a/opends/src/server/org/opends/server/messages/CoreMessages.java
+++ b/opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6089,8 +6089,6 @@
   public static final int MSGID_SORTORDER_DECODE_NO_KEYS =
        CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 607;
 
-
-
   /**
    * The message ID for the string representation of the result code that will
    * be used for search operations containing the VLV request control that do
@@ -6132,6 +6130,40 @@
 
 
   /**
+   * The message ID for the message that will be used if a connection handler
+   * has a host port already in use by another connection handler.  This takes
+   * two parameters: the connection handler name and the host port that
+   * is trying to be used twice.
+   */
+  public static final int MSGID_HOST_PORT_ALREADY_SPECIFIED =
+    CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_ERROR | 612;
+
+
+  /**
+   * The message ID for the message that will be used if a connection handler
+   * has a host port that we could not use.  This takes two parameters: the host
+   * port and the connection handler name.
+   */
+  public static final int MSGID_HOST_PORT_CANNOT_BE_USED =
+    CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_ERROR | 613;
+
+  /**
+   * The message ID for the message that will be used if no connection handler
+   * was enabled and we are not in the mode where we start
+   * the server with no connection handlers.  This does not take any arguments.
+   */
+  public static final int MSGID_NOT_AVAILABLE_CONNECTION_HANDLERS =
+    CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_ERROR | 614;
+
+
+  /**
+   * The message ID for the message that will be used if no connection handler
+   * could be properly started and we are not in the mode where we start
+   * the server with no connection handlers.  This does not take any arguments.
+   */
+  public static final int MSGID_ERROR_STARTING_CONNECTION_HANDLERS =
+    CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_ERROR | 615;
+  /**
    * Associates a set of generic messages with the message IDs defined
    * in this class.
    */
@@ -8336,6 +8368,22 @@
     registerMessage(MSGID_SORTORDER_DECODE_NO_KEYS,
                     "The provided sort order string \"%s\" is invalid " +
                     "because it does not contain any sort keys");
+
+    registerMessage(MSGID_HOST_PORT_ALREADY_SPECIFIED,
+                    "The connection handler %s is trying to use the listener " +
+                    "%s which is already in use by another connection handler");
+
+    registerMessage(MSGID_HOST_PORT_CANNOT_BE_USED,
+                    "The server cannot use the listener %s of connection " +
+                    "handler %s because it is already being used by another " +
+                    "process or because it does not have the rights to use it");
+
+    registerMessage(MSGID_NOT_AVAILABLE_CONNECTION_HANDLERS,
+                    "No enabled connection handler available");
+
+    registerMessage(MSGID_ERROR_STARTING_CONNECTION_HANDLERS,
+                    "Could not start connection handlers");
+
   }
 }
 
diff --git a/opends/src/server/org/opends/server/types/HostPort.java b/opends/src/server/org/opends/server/types/HostPort.java
index ef5af84..7f650b8 100644
--- a/opends/src/server/org/opends/server/types/HostPort.java
+++ b/opends/src/server/org/opends/server/types/HostPort.java
@@ -117,5 +117,37 @@
       return host + ":" + port;
     }
   }
+
+  /**
+   * 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.
+   */
+  public boolean equals(Object obj)
+  {
+    boolean equals = false;
+    if (obj != null)
+    {
+      if (obj == this)
+      {
+        equals = true;
+      }
+      else if (obj instanceof HostPort)
+      {
+        equals = toString().equals(obj.toString());
+      }
+    }
+    return equals;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int hashCode()
+  {
+    return toString().hashCode();
+  }
 }
 
diff --git a/opends/src/server/org/opends/server/util/SetupUtils.java b/opends/src/server/org/opends/server/util/SetupUtils.java
index 45b6e79..1157329 100644
--- a/opends/src/server/org/opends/server/util/SetupUtils.java
+++ b/opends/src/server/org/opends/server/util/SetupUtils.java
@@ -246,17 +246,18 @@
   /**
    * Returns {@code true} if the provided port is free and we can use it,
    * {@code false} otherwise.
+   * @param hostname the host name we are analyzing.
    * @param port the port we are analyzing.
    * @return {@code true} if the provided port is free and we can use it,
    * {@code false} otherwise.
    */
-  public static boolean canUseAsPort(int port)
+  public static boolean canUseAsPort(String hostname, int port)
   {
     boolean canUseAsPort = false;
     ServerSocket serverSocket = null;
     try
     {
-      InetSocketAddress socketAddress = new InetSocketAddress(port);
+      InetSocketAddress socketAddress = new InetSocketAddress(hostname, port);
       serverSocket = new ServerSocket();
       if (!isWindows())
       {
@@ -273,7 +274,7 @@
        */
       try
       {
-        new Socket("localhost", port);
+        new Socket(hostname, port);
         canUseAsPort = false;
 
       } catch (IOException ioe)
@@ -300,6 +301,18 @@
   }
 
   /**
+   * Returns {@code true} if the provided port is free and we can use it,
+   * {@code false} otherwise.
+   * @param port the port we are analyzing.
+   * @return {@code true} if the provided port is free and we can use it,
+   * {@code false} otherwise.
+   */
+  public static boolean canUseAsPort(int port)
+  {
+    return canUseAsPort("localhost", port);
+  }
+
+  /**
    * Returns {@code true} if the provided port is a priviledged port,
    * {@code false} otherwise.
    * @param port the port we are analyzing.

--
Gitblit v1.10.0