From 24841fa78a4602463372f5f5a678bf2e1ba0b4b6 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Thu, 15 Mar 2007 15:52:50 +0000
Subject: [PATCH] Fix for issue 528 (Windows Service Definition for Automatic Startup).

---
 opends/src/server/org/opends/server/core/DirectoryServer.java |  223 +++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 182 insertions(+), 41 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 7ee531b..bb0b5a8 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -127,6 +127,7 @@
 import org.opends.server.schema.TelephoneNumberEqualityMatchingRule;
 import org.opends.server.schema.TelephoneNumberSubstringMatchingRule;
 import org.opends.server.schema.TelephoneNumberSyntax;
+import org.opends.server.tools.ConfigureWindowsService;
 import org.opends.server.types.AcceptRejectWarn;
 import org.opends.server.types.AttributeType;
 import org.opends.server.types.AttributeUsage;
@@ -154,6 +155,7 @@
 import org.opends.server.types.Schema;
 import org.opends.server.types.WritabilityMode;
 import org.opends.server.util.MultiOutputStream;
+import org.opends.server.util.SetupUtils;
 import org.opends.server.util.TimeThread;
 import org.opends.server.util.Validator;
 import org.opends.server.util.args.ArgumentException;
@@ -205,6 +207,43 @@
   private static boolean serverLocked = false;
 
 
+  /**
+   * Return codes used when the hidden option --checkStartability is used.
+   * NOTE: when checkstartability is specified is recommended not to allocate
+   * a lot of memory for the JVM (Using -Xms and -Xmx options) as there might
+   * be calls to Runtime.exec.
+   */
+  /**
+   * Returned when the user specified the --checkStartability option with other
+   * options like printing the usage, dumping messages, displaying version, etc.
+   */
+  private static int NOTHING_TO_DO = 0;
+  /**
+   * Returned when the user specified the --checkStartability option with
+   * some incompatible arguments.
+   */
+  private static int CHECK_ERROR = 1;
+  /**
+   * The server is already started.
+   */
+  private static int SERVER_ALREADY_STARTED = 98;
+  /**
+   * The server must be started as detached process.
+   */
+  private static int START_AS_DETACH = 99;
+  /**
+   * The server must be started as a non-detached process.
+   */
+  private static int START_AS_NON_DETACH = 100;
+  /**
+   * The server must be started as a window service.
+   */
+  private static int START_AS_WINDOWS_SERVICE = 101;
+  /**
+   * The server must be started as detached and it is being called from the
+   * Windows Service.
+   */
+  private static int START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE = 102;
 
   // The policy to use regarding single structural objectclass enforcement.
   private AcceptRejectWarn singleStructuralClassPolicy;
@@ -2539,8 +2578,6 @@
     }
   }
 
-
-
   /**
    * Retrieves the time that the Directory Server was started, in milliseconds
    * since the epoch.
@@ -7662,6 +7699,7 @@
   {
     // Define the arguments that may be provided to the server.
     BooleanArgument checkStartability = null;
+    BooleanArgument windowsNetStart   = null;
     BooleanArgument displayUsage      = null;
     BooleanArgument dumpMessages      = null;
     BooleanArgument fullVersion       = null;
@@ -7705,6 +7743,12 @@
       checkStartability.setHidden(true);
       argParser.addArgument(checkStartability);
 
+      windowsNetStart = new BooleanArgument("windowsnetstart", null,
+                              "windowsNetStart",
+                              MSGID_DSCORE_DESCRIPTION_WINDOWS_NET_START);
+      windowsNetStart.setHidden(true);
+      argParser.addArgument(windowsNetStart);
+
 
       version = new BooleanArgument("version", 'v', "version",
                                     MSGID_DSCORE_DESCRIPTION_VERSION);
@@ -7782,14 +7826,15 @@
       //   something else like display the version number.  In that case, we
       //   don't need to write the PID file at all and can just execute the
       //   intended command.  If that command was successful, then we'll have an
-      //   exit code of 0.  Otherwise, it will have an exit code that is
-      //   something other than 0, 98, or 99 to indicate that a problem
-      // occurred.
+      //   exit code of NOTHING_TO_DO (0).  Otherwise, it will have an exit code
+      //   that is something other than NOTHING_TO_DO, SERVER_ALREADY_STARTED,
+      //   START_AS_DETACH, START_AS_NON_DETACH, START_AS_WINDOWS_SERVICE to
+      //   indicate that a problem occurred.
       if (argParser.usageDisplayed())
       {
         // We're just trying to display usage, and that's already been done so
         // exit with a code of zero.
-        System.exit(0);
+        System.exit(NOTHING_TO_DO);
       }
       else if (fullVersion.isPresent() || version.isPresent() ||
                systemInfo.isPresent() || dumpMessages.isPresent())
@@ -7808,44 +7853,11 @@
         String[] newArgs = new String[newArgList.size()];
         newArgList.toArray(newArgs);
         main(newArgs);
-        System.exit(0);
+        System.exit(NOTHING_TO_DO);
       }
       else
       {
-        // We're trying to start the server, so see if it's already running by
-        // trying to grab an exclusive lock on the server lock file.  If it
-        // succeeds, then the server isn't running and we can try to start.
-        // Otherwise, the server is running and this attempt should fail.
-        String lockFile = LockFileManager.getServerLockFileName();
-        try
-        {
-          StringBuilder failureReason = new StringBuilder();
-          if (LockFileManager.acquireExclusiveLock(lockFile, failureReason))
-          {
-            // The server isn't running, so it can be started.
-            LockFileManager.releaseLock(lockFile, failureReason);
-            System.exit(99);
-          }
-          else
-          {
-            // The server's already running.
-            int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
-            String message = getMessage(msgID, lockFile,
-                                        String.valueOf(failureReason));
-            System.err.println(message);
-            System.exit(98);
-          }
-        }
-        catch (Exception e)
-        {
-          // We'll treat this as if the server is running because we won't
-          // be able to start it anyway.
-          int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
-          String message = getMessage(msgID, lockFile,
-                                      stackTraceToSingleLineString(e));
-          System.err.println(message);
-          System.exit(98);
-        }
+        System.exit(checkStartability(argParser));
       }
     }
     else if (argParser.usageDisplayed())
@@ -8159,5 +8171,134 @@
     RDN rdn = RDN.create(cnType, new AttributeValue(cnType, monitorName));
     return monitorRootDN.concat(rdn);
   }
+
+  /**
+   * Returns the error code that we return when we are checking the startability
+   * of the server.
+   * If there are conflicting arguments (like asking to run the server in non
+   * detach mode when the server is configured to run as a window service) it
+   * returns CHECK_ERROR (1).
+   * @param argParser the ArgumentParser with the arguments already parsed.
+   * @return the error code that we return when we are checking the startability
+   * of the server.
+   */
+  private static int checkStartability(ArgumentParser argParser)
+  {
+    int returnValue;
+    boolean isServerRunning;
+
+    BooleanArgument noDetach =
+      (BooleanArgument)argParser.getArgumentForLongID("nodetach");
+    BooleanArgument windowsNetStart =
+      (BooleanArgument)argParser.getArgumentForLongID("windowsnetstart");
+
+    boolean noDetachPresent = noDetach.isPresent();
+    boolean windowsNetStartPresent = windowsNetStart.isPresent();
+
+    // We're trying to start the server, so see if it's already running by
+    // trying to grab an exclusive lock on the server lock file.  If it
+    // succeeds, then the server isn't running and we can try to start.
+    // Otherwise, the server is running and this attempt should fail.
+    String lockFile = LockFileManager.getServerLockFileName();
+    try
+    {
+      StringBuilder failureReason = new StringBuilder();
+      if (LockFileManager.acquireExclusiveLock(lockFile, failureReason))
+      {
+        // The server isn't running, so it can be started.
+        LockFileManager.releaseLock(lockFile, failureReason);
+        isServerRunning = false;
+      }
+      else
+      {
+        // The server's already running.
+        int msgID = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
+        String message = getMessage(msgID, lockFile,
+            String.valueOf(failureReason));
+        System.err.println(message);
+        isServerRunning = true;
+      }
+    }
+    catch (Exception e)
+    {
+      // We'll treat this as if the server is running because we won't
+      // be able to start it anyway.
+      int msgID = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
+      String message = getMessage(msgID, lockFile,
+          stackTraceToSingleLineString(e));
+      System.err.println(message);
+      isServerRunning = true;
+    }
+
+    if (isServerRunning)
+    {
+      returnValue = SERVER_ALREADY_STARTED;
+    }
+    else
+    {
+      boolean configuredAsService = isRunningAsWindowsService();
+
+      if (configuredAsService)
+      {
+        if (noDetachPresent)
+        {
+          // Conflicting arguments
+          returnValue = CHECK_ERROR;
+          int    msgID   = MSGID_DSCORE_ERROR_NODETACH_AND_WINDOW_SERVICE;
+          String message = getMessage(msgID, (Object[])null);
+
+          System.err.println(message);
+
+        }
+        else
+        {
+          if (windowsNetStartPresent)
+          {
+            // start-ds.bat is being called through net start, so return
+            // START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE so that the batch
+            // file actually starts the server.
+            returnValue = START_AS_DETACH_CALLED_FROM_WINDOWS_SERVICE;
+          }
+          else
+          {
+            returnValue = START_AS_WINDOWS_SERVICE;
+          }
+        }
+      }
+      else
+      {
+        if (noDetachPresent)
+        {
+          returnValue = START_AS_NON_DETACH;
+        }
+        else
+        {
+          returnValue = START_AS_DETACH;
+        }
+      }
+    }
+    return returnValue;
+  }
+
+  /**
+   * Returns true if this server is configured to run as a windows service.
+   * @return <CODE>true</CODE> if this server is configured to run as a windows
+   * service and <CODE>false</CODE> otherwise.
+   */
+  public static boolean isRunningAsWindowsService()
+  {
+    boolean isRunningAsWindowsService;
+    if (SetupUtils.isWindows())
+    {
+      isRunningAsWindowsService = ConfigureWindowsService.serviceState(null,
+      null) == ConfigureWindowsService.SERVICE_STATE_ENABLED;
+    }
+    else
+    {
+      isRunningAsWindowsService = false;
+    }
+    return isRunningAsWindowsService;
+  }
+
 }
 

--
Gitblit v1.10.0