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}