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