001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008-2010 Sun Microsystems, Inc.
015 * Portions Copyright 2011-2016 ForgeRock AS.
016 */
017package org.opends.server.tools;
018
019import static com.forgerock.opendj.cli.Utils.*;
020import static com.forgerock.opendj.util.OperatingSystem.*;
021import static com.forgerock.opendj.cli.CommonArguments.*;
022
023import static org.opends.messages.ToolMessages.*;
024
025import java.io.BufferedReader;
026import java.io.File;
027import java.io.IOException;
028import java.io.InputStreamReader;
029import java.io.OutputStream;
030import java.io.PrintStream;
031
032import org.forgerock.i18n.LocalizableMessage;
033import org.opends.guitools.controlpanel.util.Utilities;
034import org.opends.quicksetup.util.Utils;
035import org.opends.server.core.DirectoryServer;
036import org.opends.server.loggers.JDKLogging;
037import org.opends.server.types.NullOutputStream;
038import org.opends.server.util.DynamicConstants;
039import org.opends.server.util.SetupUtils;
040
041import com.forgerock.opendj.cli.ArgumentException;
042import com.forgerock.opendj.cli.ArgumentParser;
043import com.forgerock.opendj.cli.BooleanArgument;
044import com.forgerock.opendj.cli.StringArgument;
045
046/**
047  * This class is used to configure the Windows service for this instance on
048  * this machine.
049  * This tool allows to enable and disable OpenDJ to run as a Windows service
050  * and allows to know if OpenDJ is running as a Windows service or not.
051  *
052  * Some comments about Vista:
053  * In Vista, when we launch the subcommands that require administrator
054  * privileges (enable, disable and cleanup) we cannot use the administrator
055  * launcher binary directly from Java (see
056  * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6410605) so we use
057  * winlauncher.exe.
058  * When we launch subcommands that required administrator privileges
059  * we must launch a binary containing the manifest that specifies that we
060  * require administrator privileges (requireAdministrator value): if UAC is
061  * enabled, the user will be asked for confirmation.
062  * To minimize the number of confirmation that the user must provide when
063  * launching the state subcommand we will use a binary whose manifest does
064  * not contain the requireAdministrator value.
065  *
066  * See the files under src/build-tools/windows for more details.
067  */
068public class ConfigureWindowsService
069{
070  /** The fully-qualified name of this class. */
071  private static final String CLASS_NAME = "org.opends.server.tools.ConfigureWindowsService";
072
073  private static final String DEBUG_OPTION = "--debug";
074  /** Option to be used when calling the launchers. */
075  public static final String LAUNCHER_OPTION = "run";
076
077  private static final int SUCCESS = 0;
078  private static final int ERROR = 1;
079
080  /** Return codes for the method enableService. */
081  /** The service was successfully enabled. */
082  public static final int SERVICE_ENABLE_SUCCESS = 0;
083  /** The service was already enabled. */
084  public static final int SERVICE_ALREADY_ENABLED = 1;
085  /** The service name was already in use. */
086  public static final int SERVICE_NAME_ALREADY_IN_USE = 2;
087  /** An error occurred enabling the service. */
088  public static final int SERVICE_ENABLE_ERROR = 3;
089
090  /** Return codes for the method disableService. */
091  /** The service was successfully disabled. */
092  public static final int SERVICE_DISABLE_SUCCESS = 0;
093  /** The service was already disabled. */
094  public static final int SERVICE_ALREADY_DISABLED = 1;
095  /** The service is marked for deletion. */
096  public static final int SERVICE_MARKED_FOR_DELETION = 2;
097  /** An error occurred disabling the service. */
098  public static final int SERVICE_DISABLE_ERROR = 3;
099
100  /** Return codes for the method serviceState. */
101  /** The service is enabled. */
102  public static final int SERVICE_STATE_ENABLED = 0;
103  /** The service is disabled. */
104  public static final int SERVICE_STATE_DISABLED = 1;
105  /** An error occurred checking the service state. */
106  public static final int SERVICE_STATE_ERROR = 2;
107
108  /** Return codes for the method cleanupService. */
109  /** The service cleanup worked. */
110  public static final int SERVICE_CLEANUP_SUCCESS = 0;
111  /** The service could not be found. */
112  public static final int SERVICE_NOT_FOUND = 1;
113  /** An error occurred cleaning up the service. */
114  public static final int SERVICE_CLEANUP_ERROR = 2;
115  /** The service is marked for deletion. */
116  public static final int SERVICE_CLEANUP_MARKED_FOR_DELETION = 3;
117
118  /**
119   * Configures the Windows service for this instance on this machine. This tool
120   * allows to enable and disable OpenDJ to run as a Windows service and allows
121   * to know if OpenDJ is running as a Windows service or not.
122   *
123   * @param args
124   *          The command-line arguments provided to this program.
125   */
126  public static void main(String[] args)
127  {
128    int result = configureWindowsService(args, System.out, System.err);
129
130    System.exit(filterExitCode(result));
131  }
132
133  /**
134   * Configures the Windows service for this instance on this machine. This tool
135   * allows to enable and disable OpenDJ to run as a Windows service and allows
136   * to know if OpenDJ is running as a Windows service or not.
137   *
138   * @param args
139   *          The command-line arguments provided to this program.
140   * @param outStream
141   *          the stream used to write the standard output.
142   * @param errStream
143   *          the stream used to write the error output.
144   * @return the integer code describing if the operation could be completed or
145   *         not.
146   */
147  public static int configureWindowsService(String[] args, OutputStream outStream, OutputStream errStream)
148  {
149    PrintStream out = NullOutputStream.wrapOrNullStream(outStream);
150    PrintStream err = NullOutputStream.wrapOrNullStream(errStream);
151    JDKLogging.disableLogging();
152
153    //  Define all the arguments that may be used with this program.
154    LocalizableMessage toolDescription = INFO_CONFIGURE_WINDOWS_SERVICE_TOOL_DESCRIPTION.get();
155    ArgumentParser argParser = new ArgumentParser(CLASS_NAME, toolDescription, false);
156    argParser.setShortToolDescription(REF_SHORT_DESC_WINDOWS_SERVICE.get());
157    BooleanArgument enableService = null;
158    BooleanArgument disableService = null;
159    BooleanArgument serviceState = null;
160    StringArgument cleanupService = null;
161    BooleanArgument showUsage = null;
162
163    try
164    {
165      enableService =
166              BooleanArgument.builder("enableService")
167                      .shortIdentifier('e')
168                      .description(INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_ENABLE.get())
169                      .buildAndAddToParser(argParser);
170      disableService =
171              BooleanArgument.builder("disableService")
172                      .shortIdentifier('d')
173                      .description(INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_DISABLE.get())
174                      .buildAndAddToParser(argParser);
175      serviceState =
176              BooleanArgument.builder("serviceState")
177                      .shortIdentifier('s')
178                      .description(INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_STATE.get())
179                      .buildAndAddToParser(argParser);
180      cleanupService =
181              StringArgument.builder("cleanupService")
182                      .shortIdentifier('c')
183                      .description(INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_CLEANUP.get())
184                      .valuePlaceholder(INFO_SERVICE_NAME_PLACEHOLDER.get())
185                      .buildAndAddToParser(argParser);
186
187      showUsage = showUsageArgument();
188      argParser.addArgument(showUsage);
189      argParser.setUsageArgument(showUsage, out);
190    }
191    catch (ArgumentException ae)
192    {
193      printWrappedText(err, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()));
194      return ERROR;
195    }
196
197    try
198    {
199      argParser.parseArguments(args);
200    }
201    catch (ArgumentException ae)
202    {
203      argParser.displayMessageAndUsageReference(err, ERR_ERROR_PARSING_ARGS.get(ae.getMessage()));
204      return ERROR;
205    }
206
207    // If we should just display usage or version information,
208    // then it is already done
209    if (!argParser.usageOrVersionDisplayed())
210    {
211      /* Check that the user only asked for one argument */
212      int nArgs = 0;
213      if (enableService.isPresent())
214      {
215        nArgs++;
216      }
217      if (disableService.isPresent())
218      {
219        nArgs++;
220      }
221      if (serviceState.isPresent())
222      {
223        nArgs++;
224      }
225      if (cleanupService.isPresent())
226      {
227        nArgs++;
228      }
229      if (nArgs != 1)
230      {
231        argParser.displayMessageAndUsageReference(err, nArgs == 0 ? ERR_CONFIGURE_WINDOWS_SERVICE_TOO_FEW_ARGS.get()
232                                                                  : ERR_CONFIGURE_WINDOWS_SERVICE_TOO_MANY_ARGS.get());
233        return ERROR;
234      }
235    }
236
237    if (argParser.usageOrVersionDisplayed())
238    {
239      return SUCCESS;
240    }
241
242    if (enableService.isPresent())
243    {
244      return enableService(out, err);
245    }
246    else if (disableService.isPresent())
247    {
248      return disableService(out, err);
249    }
250    else if (serviceState.isPresent())
251    {
252      return serviceState(out, err);
253    }
254
255    return cleanupService(cleanupService.getValue(), out, err);
256  }
257
258  /**
259   * Returns the service name associated with OpenDJ or null if no service name
260   * could be found.
261   *
262   * @return the service name associated with OpenDJ or null if no service name
263   *         could be found.
264   */
265  static String getServiceName()
266  {
267    String serverRoot = getServerRoot();
268    String[] cmd = { getBinaryFullPath(), "state", serverRoot };
269    try
270    {
271      String serviceName = null;
272      Process p = Runtime.getRuntime().exec(cmd);
273      BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
274      boolean processDone = false;
275      String s;
276      while (!processDone)
277      {
278        try
279        {
280          p.exitValue();
281          processDone = true;
282        }
283        catch (Throwable t)
284        {
285        }
286        while ((s = stdout.readLine()) != null)
287        {
288          serviceName = s;
289          if (serviceName.trim().length() == 0)
290          {
291            serviceName = null;
292          }
293        }
294      }
295      return serviceName;
296    }
297    catch (Throwable t)
298    {
299      return null;
300    }
301  }
302
303  /**
304   * Enables OpenDJ to run as a windows service.
305   *
306   * @param out
307   *          the stream used to write the standard output.
308   * @param err
309   *          the stream used to write the error output.
310   * @return <CODE>SERVICE_ENABLE_SUCCESS</CODE>,
311   *         <CODE>SERVICE_ENABLE_ERROR</CODE>,
312   *         <CODE>SERVICE_NAME_ALREADY_IN_USE</CODE> or
313   *         <CODE>SERVICE_ALREADY_ENABLED</CODE> depending on whether the
314   *         service could be enabled or not.
315   */
316  public static int enableService(PrintStream out, PrintStream err)
317  {
318    LocalizableMessage serviceName = Utils.getCustomizedObject(
319        "INFO_WINDOWS_SERVICE_NAME",
320        INFO_WINDOWS_SERVICE_NAME.get(DynamicConstants.PRODUCT_NAME),
321        LocalizableMessage.class);
322    LocalizableMessage serviceDescription = Utils.getCustomizedObject(
323        "INFO_WINDOWS_SERVICE_DESCRIPTION",
324        INFO_WINDOWS_SERVICE_DESCRIPTION.get(getServerRoot()), LocalizableMessage.class);
325    return enableService(out, err, serviceName.toString(), serviceDescription.toString());
326  }
327
328  /**
329   * Enables OpenDJ to run as a windows service.
330   *
331   * @param out
332   *          the stream used to write the standard output.
333   * @param err
334   *          the stream used to write the error output.
335   * @param serviceName
336   *          the name of the service as it will appear in the registry.
337   * @param serviceDescription
338   *          the description of the service as it will appear in the registry.
339   * @return <CODE>SERVICE_ENABLE_SUCCESS</CODE>,
340   *         <CODE>SERVICE_ENABLE_ERROR</CODE>,
341   *         <CODE>SERVICE_NAME_ALREADY_IN_USE</CODE> or
342   *         <CODE>SERVICE_ALREADY_ENABLED</CODE> depending on whether the
343   *         service could be enabled or not.
344   */
345  public static int enableService(PrintStream out, PrintStream err, String serviceName, String serviceDescription)
346  {
347    String serverRoot = getServerRoot();
348    String[] cmd;
349
350    if (hasUAC())
351    {
352      cmd = new String[] {
353          getLauncherBinaryFullPath(),
354          LAUNCHER_OPTION,
355          getLauncherAdministratorBinaryFullPath(),
356          LAUNCHER_OPTION,
357          getBinaryFullPath(),
358          "create",
359          serverRoot,
360          serviceName,
361          serviceDescription,
362          DEBUG_OPTION
363      };
364    }
365    else
366    {
367      cmd = new String[] {
368          getBinaryFullPath(),
369          "create",
370          serverRoot,
371          serviceName,
372          serviceDescription,
373          DEBUG_OPTION
374      };
375    }
376
377    try
378    {
379      boolean isServerRunning = Utilities.isServerRunning(new File(serverRoot));
380
381      int resultCode = Runtime.getRuntime().exec(cmd).waitFor();
382      switch (resultCode)
383      {
384      case 0:
385        if (isServerRunning)
386        {
387          // We have to launch the windows service.  The service code already
388          // handles this case (the service binary is executed when the server
389          // already runs).
390          final int returnValue = StartWindowsService.startWindowsService(out, err);
391          if (returnValue == 0)
392          {
393            printWrappedText(out, INFO_WINDOWS_SERVICE_SUCCESSULLY_ENABLED.get());
394            return SERVICE_ENABLE_SUCCESS;
395          }
396          else
397          {
398            printWrappedText(err, ERR_WINDOWS_SERVICE_ENABLING_ERROR_STARTING_SERVER.get(SERVICE_ENABLE_ERROR));
399            return SERVICE_ENABLE_ERROR;
400          }
401        }
402        else
403        {
404          printWrappedText(out, INFO_WINDOWS_SERVICE_SUCCESSULLY_ENABLED.get());
405          return SERVICE_ENABLE_SUCCESS;
406        }
407      case 1:
408        printWrappedText(out, INFO_WINDOWS_SERVICE_ALREADY_ENABLED.get());
409        return SERVICE_ALREADY_ENABLED;
410      case 2:
411        printWrappedText(err, ERR_WINDOWS_SERVICE_NAME_ALREADY_IN_USE.get());
412        return SERVICE_NAME_ALREADY_IN_USE;
413      case 3:
414        printWrappedText(err, ERR_WINDOWS_SERVICE_ENABLE_ERROR.get());
415        return SERVICE_ENABLE_ERROR;
416      default:
417        printWrappedText(err, ERR_WINDOWS_SERVICE_ENABLE_ERROR.get());
418        return SERVICE_ENABLE_ERROR;
419      }
420    }
421    catch (Throwable t)
422    {
423      err.println("Unexpected throwable: "+t);
424      t.printStackTrace();
425      printWrappedText(err, ERR_WINDOWS_SERVICE_ENABLE_ERROR.get());
426      return SERVICE_ENABLE_ERROR;
427    }
428  }
429
430  /**
431   * Disables OpenDJ to run as a windows service.
432   *
433   * @param out
434   *          the stream used to write the standard output.
435   * @param err
436   *          the stream used to write the error output.
437   * @return <CODE>SERVICE_DISABLE_SUCCESS</CODE>,
438   *         <CODE>SERVICE_DISABLE_ERROR</CODE>,
439   *         <CODE>SERVICE_MARKED_FOR_DELETION</CODE> or
440   *         <CODE>SERVICE_ALREADY_DISABLED</CODE> depending on whether the
441   *         service could be disabled or not.
442   */
443  public static int disableService(PrintStream out, PrintStream err)
444  {
445    String serverRoot = getServerRoot();
446    String[] cmd;
447    if (hasUAC())
448    {
449      cmd = new String[] {
450          getLauncherBinaryFullPath(),
451          LAUNCHER_OPTION,
452          getLauncherAdministratorBinaryFullPath(),
453          LAUNCHER_OPTION,
454          getBinaryFullPath(),
455          "remove",
456          serverRoot,
457          DEBUG_OPTION
458      };
459    }
460    else
461    {
462      cmd = new String[] {
463        getBinaryFullPath(),
464        "remove",
465        serverRoot,
466        DEBUG_OPTION
467        };
468    }
469    try
470    {
471      int resultCode = Runtime.getRuntime().exec(cmd).waitFor();
472      switch (resultCode)
473      {
474      case 0:
475        printWrappedText(out, INFO_WINDOWS_SERVICE_SUCCESSULLY_DISABLED.get());
476        return SERVICE_DISABLE_SUCCESS;
477      case 1:
478        printWrappedText(out, INFO_WINDOWS_SERVICE_ALREADY_DISABLED.get());
479        return SERVICE_ALREADY_DISABLED;
480      case 2:
481        printWrappedText(out, WARN_WINDOWS_SERVICE_MARKED_FOR_DELETION.get());
482        return SERVICE_MARKED_FOR_DELETION;
483      case 3:
484        printWrappedText(err, ERR_WINDOWS_SERVICE_DISABLE_ERROR.get());
485        return SERVICE_DISABLE_ERROR;
486      default:
487        printWrappedText(err, ERR_WINDOWS_SERVICE_DISABLE_ERROR.get());
488        return SERVICE_DISABLE_ERROR;
489      }
490    }
491    catch (Throwable t)
492    {
493      t.printStackTrace();
494      printWrappedText(err, ERR_WINDOWS_SERVICE_DISABLE_ERROR.get());
495      return SERVICE_DISABLE_ERROR;
496    }
497  }
498
499  /**
500   * Cleans up a service for a given service name.
501   *
502   * @param serviceName
503   *          the service name to be cleaned up.
504   * @param out
505   *          the stream used to write the standard output.
506   * @param err
507   *          the stream used to write the error output.
508   * @return <CODE>SERVICE_CLEANUP_SUCCESS</CODE>,
509   *         <CODE>SERVICE_NOT_FOUND</CODE>,
510   *         <CODE>SERVICE_MARKED_FOR_DELETION</CODE> or
511   *         <CODE>SERVICE_CLEANUP_ERROR</CODE> depending on whether the service
512   *         could be found or not.
513   */
514  public static int cleanupService(String serviceName, PrintStream out,
515      PrintStream err)
516  {
517    String[] cmd;
518    if (hasUAC())
519    {
520      cmd = new String[] {
521          getLauncherBinaryFullPath(),
522          LAUNCHER_OPTION,
523          getLauncherAdministratorBinaryFullPath(),
524          LAUNCHER_OPTION,
525          getBinaryFullPath(),
526          "cleanup",
527          serviceName,
528          DEBUG_OPTION
529      };
530    }
531    else
532    {
533      cmd = new String[] {
534          getBinaryFullPath(),
535          "cleanup",
536          serviceName,
537          DEBUG_OPTION
538      };
539    }
540    try
541    {
542      int resultCode = Runtime.getRuntime().exec(cmd).waitFor();
543      switch (resultCode)
544      {
545      case 0:
546        printWrappedText(out, INFO_WINDOWS_SERVICE_CLEANUP_SUCCESS.get(serviceName));
547        return SERVICE_CLEANUP_SUCCESS;
548      case 1:
549        printWrappedText(err, ERR_WINDOWS_SERVICE_CLEANUP_NOT_FOUND.get(serviceName));
550        return SERVICE_NOT_FOUND;
551      case 2:
552        printWrappedText(out, WARN_WINDOWS_SERVICE_CLEANUP_MARKED_FOR_DELETION.get(serviceName));
553        return SERVICE_CLEANUP_MARKED_FOR_DELETION;
554      case 3:
555        printWrappedText(err, ERR_WINDOWS_SERVICE_CLEANUP_ERROR.get(serviceName));
556        return SERVICE_CLEANUP_ERROR;
557      default:
558        printWrappedText(err, ERR_WINDOWS_SERVICE_CLEANUP_ERROR.get(serviceName));
559        return SERVICE_CLEANUP_ERROR;
560      }
561    }
562    catch (Throwable t)
563    {
564      err.println(ERR_WINDOWS_SERVICE_CLEANUP_ERROR.get(serviceName));
565      printWrappedText(err, "Exception:" + t);
566      return SERVICE_CLEANUP_ERROR;
567    }
568  }
569
570  /**
571   * Checks if OpenDJ is enabled as a windows service.
572   *
573   * @return <CODE>SERVICE_STATE_ENABLED</CODE>,
574   *         <CODE>SERVICE_STATE_DISABLED</CODE> or
575   *         <CODE>SERVICE_STATE_ERROR</CODE> depending on the state of the
576   *         service.
577   */
578  public static int serviceState()
579  {
580    return serviceState(NullOutputStream.printStream(), NullOutputStream.printStream());
581  }
582
583  /**
584   * Checks if OpenDJ is enabled as a windows service and if it is write the
585   * serviceName in the output stream (if it is not null).
586   *
587   * @param out
588   *          the stream used to write the standard output.
589   * @param err
590   *          the stream used to write the error output.
591   * @return <CODE>SERVICE_STATE_ENABLED</CODE>,
592   *         <CODE>SERVICE_STATE_DISABLED</CODE> or
593   *         <CODE>SERVICE_STATE_ERROR</CODE> depending on the state of the
594   *         service.
595   */
596  public static int serviceState(PrintStream out, PrintStream err)
597  {
598    String serviceName = null;
599
600    String serverRoot = getServerRoot();
601    String[] cmd = new String[] {
602        getBinaryFullPath(),
603        "state",
604        serverRoot,
605        DEBUG_OPTION
606    };
607
608    try
609    {
610      int resultCode = -1;
611      Process process = new ProcessBuilder(cmd).start();
612      BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
613
614      boolean processDone = false;
615      String s;
616      while (!processDone)
617      {
618        try
619        {
620          resultCode = process.exitValue();
621          processDone = true;
622        }
623        catch (Throwable t)
624        {
625        }
626        while ((s = stdout.readLine()) != null)
627        {
628          if (s.trim().length() != 0)
629          {
630            serviceName = s;
631          }
632        }
633      }
634      switch (resultCode)
635      {
636      case 0:
637        printWrappedText(out, INFO_WINDOWS_SERVICE_ENABLED.get(serviceName));
638        return SERVICE_STATE_ENABLED;
639      case 1:
640        printWrappedText(out, INFO_WINDOWS_SERVICE_DISABLED.get());
641        return SERVICE_STATE_DISABLED;
642      case 2:
643        printWrappedText(err, ERR_WINDOWS_SERVICE_STATE_ERROR.get());
644        return SERVICE_STATE_ERROR;
645      default:
646        printWrappedText(err, ERR_WINDOWS_SERVICE_STATE_ERROR.get());
647        return SERVICE_STATE_ERROR;
648      }
649    }
650    catch (Throwable t)
651    {
652      printWrappedText(err, ERR_WINDOWS_SERVICE_STATE_ERROR.get());
653      printWrappedText(err, t.toString());
654      return SERVICE_STATE_ERROR;
655    }
656  }
657
658  /**
659   * Returns the Directory Server installation path in a user friendly
660   * representation.
661   *
662   * @return the Directory Server installation path in a user friendly
663   *         representation.
664   */
665  private static String getServerRoot()
666  {
667    String serverRoot = DirectoryServer.getServerRoot();
668    File f = new File(serverRoot);
669    try
670    {
671      /*
672       * Do a best effort to avoid having a relative representation (for
673       * instance to avoid having ../../../).
674       */
675      f = f.getCanonicalFile();
676    }
677    catch (IOException ioe)
678    {
679      /* This is a best effort to get the best possible representation of the
680       * file: reporting the error is not necessary.
681       */
682    }
683    serverRoot = f.toString();
684    if (serverRoot.endsWith(File.separator))
685    {
686      serverRoot = serverRoot.substring(0, serverRoot.length() - 1);
687    }
688    return serverRoot;
689  }
690
691  /**
692   * Returns the full path of the executable used by this class to perform
693   * operations related to the service. This binaries file has the asInvoker
694   * value in its manifest.
695   *
696   * @return the full path of the executable used by this class to perform
697   *         operations related to the service.
698   */
699  private static String getBinaryFullPath()
700  {
701    return SetupUtils.getScriptPath(getServerRoot() + "\\lib\\opendj_service.exe");
702  }
703
704  /**
705   * Returns the full path of the executable that has a manifest requiring
706   * administrator privileges used by this class to perform operations related
707   * to the service.
708   *
709   * @return the full path of the executable that has a manifest requiring
710   *         administrator privileges used by this class to perform operations
711   *         related to the service.
712   */
713  public static String getLauncherAdministratorBinaryFullPath()
714  {
715    return getServerRoot() + "\\lib\\launcher_administrator.exe";
716  }
717
718  /**
719   * Returns the full path of the executable that has a manifest requiring
720   * administrator privileges used by this class to perform operations related
721   * to the service.
722   *
723   * @return the full path of the executable that has a manifest requiring
724   *         administrator privileges used by this class to perform operations
725   *         related to the service.
726   */
727  public static String getLauncherBinaryFullPath()
728  {
729    return getServerRoot() + "\\lib\\winlauncher.exe";
730  }
731}