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.CommonArguments.*; 020import static com.forgerock.opendj.cli.Utils.*; 021import static com.forgerock.opendj.util.OperatingSystem.*; 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 private static final int SERVICE_NAME_ALREADY_IN_USE = 2; 087 /** An error occurred enabling the service. */ 088 private 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 private 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 private static final int SERVICE_STATE_DISABLED = 1; 105 /** An error occurred checking the service state. */ 106 private static final int SERVICE_STATE_ERROR = 2; 107 108 /** Return codes for the method cleanupService. */ 109 /** The service cleanup worked. */ 110 private static final int SERVICE_CLEANUP_SUCCESS = 0; 111 /** The service could not be found. */ 112 private static final int SERVICE_NOT_FOUND = 1; 113 /** An error occurred cleaning up the service. */ 114 private static final int SERVICE_CLEANUP_ERROR = 2; 115 /** The service is marked for deletion. */ 116 private 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 private 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 private 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 private static int cleanupService(String serviceName, PrintStream out, PrintStream err) 515 { 516 String[] cmd; 517 if (hasUAC()) 518 { 519 cmd = new String[] { 520 getLauncherBinaryFullPath(), 521 LAUNCHER_OPTION, 522 getLauncherAdministratorBinaryFullPath(), 523 LAUNCHER_OPTION, 524 getBinaryFullPath(), 525 "cleanup", 526 serviceName, 527 DEBUG_OPTION 528 }; 529 } 530 else 531 { 532 cmd = new String[] { 533 getBinaryFullPath(), 534 "cleanup", 535 serviceName, 536 DEBUG_OPTION 537 }; 538 } 539 try 540 { 541 int resultCode = Runtime.getRuntime().exec(cmd).waitFor(); 542 switch (resultCode) 543 { 544 case 0: 545 printWrappedText(out, INFO_WINDOWS_SERVICE_CLEANUP_SUCCESS.get(serviceName)); 546 return SERVICE_CLEANUP_SUCCESS; 547 case 1: 548 printWrappedText(err, ERR_WINDOWS_SERVICE_CLEANUP_NOT_FOUND.get(serviceName)); 549 return SERVICE_NOT_FOUND; 550 case 2: 551 printWrappedText(out, WARN_WINDOWS_SERVICE_CLEANUP_MARKED_FOR_DELETION.get(serviceName)); 552 return SERVICE_CLEANUP_MARKED_FOR_DELETION; 553 case 3: 554 printWrappedText(err, ERR_WINDOWS_SERVICE_CLEANUP_ERROR.get(serviceName)); 555 return SERVICE_CLEANUP_ERROR; 556 default: 557 printWrappedText(err, ERR_WINDOWS_SERVICE_CLEANUP_ERROR.get(serviceName)); 558 return SERVICE_CLEANUP_ERROR; 559 } 560 } 561 catch (Throwable t) 562 { 563 err.println(ERR_WINDOWS_SERVICE_CLEANUP_ERROR.get(serviceName)); 564 printWrappedText(err, "Exception:" + t); 565 return SERVICE_CLEANUP_ERROR; 566 } 567 } 568 569 /** 570 * Checks if OpenDJ is enabled as a windows service. 571 * 572 * @return <CODE>SERVICE_STATE_ENABLED</CODE>, 573 * <CODE>SERVICE_STATE_DISABLED</CODE> or 574 * <CODE>SERVICE_STATE_ERROR</CODE> depending on the state of the 575 * service. 576 */ 577 public static int serviceState() 578 { 579 return serviceState(NullOutputStream.printStream(), NullOutputStream.printStream()); 580 } 581 582 /** 583 * Checks if OpenDJ is enabled as a windows service and if it is write the 584 * serviceName in the output stream (if it is not null). 585 * 586 * @param out 587 * the stream used to write the standard output. 588 * @param err 589 * the stream used to write the error output. 590 * @return <CODE>SERVICE_STATE_ENABLED</CODE>, 591 * <CODE>SERVICE_STATE_DISABLED</CODE> or 592 * <CODE>SERVICE_STATE_ERROR</CODE> depending on the state of the 593 * service. 594 */ 595 private static int serviceState(PrintStream out, PrintStream err) 596 { 597 String serviceName = null; 598 599 String serverRoot = getServerRoot(); 600 String[] cmd = new String[] { 601 getBinaryFullPath(), 602 "state", 603 serverRoot, 604 DEBUG_OPTION 605 }; 606 607 try 608 { 609 int resultCode = -1; 610 Process process = new ProcessBuilder(cmd).start(); 611 BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream())); 612 613 boolean processDone = false; 614 String s; 615 while (!processDone) 616 { 617 try 618 { 619 resultCode = process.exitValue(); 620 processDone = true; 621 } 622 catch (Throwable t) 623 { 624 } 625 while ((s = stdout.readLine()) != null) 626 { 627 if (s.trim().length() != 0) 628 { 629 serviceName = s; 630 } 631 } 632 } 633 switch (resultCode) 634 { 635 case 0: 636 printWrappedText(out, INFO_WINDOWS_SERVICE_ENABLED.get(serviceName)); 637 return SERVICE_STATE_ENABLED; 638 case 1: 639 printWrappedText(out, INFO_WINDOWS_SERVICE_DISABLED.get()); 640 return SERVICE_STATE_DISABLED; 641 case 2: 642 printWrappedText(err, ERR_WINDOWS_SERVICE_STATE_ERROR.get()); 643 return SERVICE_STATE_ERROR; 644 default: 645 printWrappedText(err, ERR_WINDOWS_SERVICE_STATE_ERROR.get()); 646 return SERVICE_STATE_ERROR; 647 } 648 } 649 catch (Throwable t) 650 { 651 printWrappedText(err, ERR_WINDOWS_SERVICE_STATE_ERROR.get()); 652 printWrappedText(err, t.toString()); 653 return SERVICE_STATE_ERROR; 654 } 655 } 656 657 /** 658 * Returns the Directory Server installation path in a user friendly 659 * representation. 660 * 661 * @return the Directory Server installation path in a user friendly 662 * representation. 663 */ 664 private static String getServerRoot() 665 { 666 String serverRoot = DirectoryServer.getServerRoot(); 667 File f = new File(serverRoot); 668 try 669 { 670 /* 671 * Do a best effort to avoid having a relative representation (for 672 * instance to avoid having ../../../). 673 */ 674 f = f.getCanonicalFile(); 675 } 676 catch (IOException ioe) 677 { 678 /* This is a best effort to get the best possible representation of the 679 * file: reporting the error is not necessary. 680 */ 681 } 682 serverRoot = f.toString(); 683 if (serverRoot.endsWith(File.separator)) 684 { 685 serverRoot = serverRoot.substring(0, serverRoot.length() - 1); 686 } 687 return serverRoot; 688 } 689 690 /** 691 * Returns the full path of the executable used by this class to perform 692 * operations related to the service. This binaries file has the asInvoker 693 * value in its manifest. 694 * 695 * @return the full path of the executable used by this class to perform 696 * operations related to the service. 697 */ 698 private static String getBinaryFullPath() 699 { 700 return SetupUtils.getScriptPath(getServerRoot() + "\\lib\\opendj_service.exe"); 701 } 702 703 /** 704 * Returns the full path of the executable that has a manifest requiring 705 * administrator privileges used by this class to perform operations related 706 * to the service. 707 * 708 * @return the full path of the executable that has a manifest requiring 709 * administrator privileges used by this class to perform operations 710 * related to the service. 711 */ 712 public static String getLauncherAdministratorBinaryFullPath() 713 { 714 return getServerRoot() + "\\lib\\launcher_administrator.exe"; 715 } 716 717 /** 718 * Returns the full path of the executable that has a manifest requiring 719 * administrator privileges used by this class to perform operations related 720 * to the service. 721 * 722 * @return the full path of the executable that has a manifest requiring 723 * administrator privileges used by this class to perform operations 724 * related to the service. 725 */ 726 public static String getLauncherBinaryFullPath() 727 { 728 return getServerRoot() + "\\lib\\winlauncher.exe"; 729 } 730}