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 2006-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2011-2015 ForgeRock AS 026 */ 027package org.opends.quicksetup.util; 028 029import static org.forgerock.util.Utils.*; 030import static org.opends.admin.ads.util.ConnectionUtils.*; 031import static org.opends.messages.QuickSetupMessages.*; 032import static org.opends.quicksetup.Installation.*; 033import static org.opends.server.util.DynamicConstants.*; 034 035import static com.forgerock.opendj.cli.Utils.*; 036import static com.forgerock.opendj.util.OperatingSystem.*; 037 038import java.io.BufferedOutputStream; 039import java.io.BufferedReader; 040import java.io.ByteArrayOutputStream; 041import java.io.File; 042import java.io.FileOutputStream; 043import java.io.FileReader; 044import java.io.FileWriter; 045import java.io.IOException; 046import java.io.InputStream; 047import java.io.InputStreamReader; 048import java.io.PrintStream; 049import java.io.PrintWriter; 050import java.io.RandomAccessFile; 051import java.net.InetAddress; 052import java.text.SimpleDateFormat; 053import java.util.ArrayList; 054import java.util.Collection; 055import java.util.HashMap; 056import java.util.Hashtable; 057import java.util.LinkedHashSet; 058import java.util.List; 059import java.util.Locale; 060import java.util.Map; 061import java.util.Set; 062import java.util.TimeZone; 063 064import javax.naming.AuthenticationException; 065import javax.naming.CommunicationException; 066import javax.naming.NamingEnumeration; 067import javax.naming.NamingException; 068import javax.naming.NamingSecurityException; 069import javax.naming.NoPermissionException; 070import javax.naming.directory.SearchControls; 071import javax.naming.directory.SearchResult; 072import javax.naming.ldap.InitialLdapContext; 073import javax.naming.ldap.LdapName; 074import javax.net.ssl.HostnameVerifier; 075import javax.net.ssl.TrustManager; 076 077import org.forgerock.i18n.LocalizableMessage; 078import org.forgerock.i18n.LocalizableMessageBuilder; 079import org.forgerock.i18n.slf4j.LocalizedLogger; 080import org.forgerock.opendj.config.ManagedObjectDefinition; 081import org.forgerock.opendj.server.config.client.BackendCfgClient; 082import org.forgerock.opendj.server.config.server.BackendCfg; 083import org.opends.admin.ads.ADSContext; 084import org.opends.admin.ads.ReplicaDescriptor; 085import org.opends.admin.ads.ServerDescriptor; 086import org.opends.admin.ads.SuffixDescriptor; 087import org.opends.admin.ads.TopologyCacheException; 088import org.opends.admin.ads.util.ConnectionUtils; 089import org.opends.quicksetup.Constants; 090import org.opends.quicksetup.Installation; 091import org.opends.quicksetup.SecurityOptions; 092import org.opends.quicksetup.UserData; 093import org.opends.quicksetup.installer.AuthenticationData; 094import org.opends.quicksetup.installer.DataReplicationOptions; 095import org.opends.quicksetup.installer.NewSuffixOptions; 096import org.opends.quicksetup.installer.SuffixesToReplicateOptions; 097import org.opends.quicksetup.ui.UIFactory; 098import org.opends.server.tools.BackendTypeHelper; 099import org.opends.server.util.SetupUtils; 100import org.opends.server.util.StaticUtils; 101 102import com.forgerock.opendj.cli.ArgumentConstants; 103import com.forgerock.opendj.cli.ClientException; 104 105/** 106 * This class provides some static convenience methods of different nature. 107 */ 108public class Utils 109{ 110 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 111 112 private Utils() {} 113 114 private static final int BUFFER_SIZE = 1024; 115 private static final int MAX_LINE_WIDTH = 80; 116 117 /** Chars that require special treatment when passing them to command-line. */ 118 private static final char[] CHARS_TO_ESCAPE = 119 { ' ', '\t', '\n', '|', ';', '<', '>', '(', ')', '$', '`', '\\', '"', '\'' }; 120 121 /** The class name that contains the control panel customizations for products. */ 122 private static final String CUSTOMIZATION_CLASS_NAME = "org.opends.server.util.ReleaseDefinition"; 123 124 /** The service name required by the JNLP downloader. */ 125 public static final String JNLP_SERVICE_NAME = "javax.jnlp.DownloadService"; 126 127 /** 128 * Returns <CODE>true</CODE> if the provided port is free and we can use it, 129 * <CODE>false</CODE> otherwise. 130 * 131 * @param port 132 * the port we are analyzing. 133 * @return <CODE>true</CODE> if the provided port is free and we can use it, 134 * <CODE>false</CODE> otherwise. 135 */ 136 public static boolean canUseAsPort(int port) 137 { 138 return SetupUtils.canUseAsPort(port); 139 } 140 141 /** 142 * Returns <CODE>true</CODE> if the provided port is a privileged port, 143 * <CODE>false</CODE> otherwise. 144 * 145 * @param port 146 * the port we are analyzing. 147 * @return <CODE>true</CODE> if the provided port is a privileged port, 148 * <CODE>false</CODE> otherwise. 149 */ 150 public static boolean isPrivilegedPort(int port) 151 { 152 return SetupUtils.isPrivilegedPort(port); 153 } 154 155 /** 156 * Tells whether the provided java installation supports a given option or 157 * not. 158 * 159 * @param javaHome 160 * the java installation path. 161 * @param option 162 * the java option that we want to check. 163 * @param installPath 164 * the install path of the server. 165 * @return <CODE>true</CODE> if the provided java installation supports a 166 * given option and <CODE>false</CODE> otherwise. 167 */ 168 public static boolean supportsOption(String option, String javaHome, String installPath) 169 { 170 boolean supported = false; 171 logger.info(LocalizableMessage.raw("Checking if options " + option + " are supported with java home: " + javaHome)); 172 try 173 { 174 List<String> args = new ArrayList<>(); 175 String script; 176 String libPath = Utils.getPath(installPath, Installation.LIBRARIES_PATH_RELATIVE); 177 if (isWindows()) 178 { 179 script = Utils.getScriptPath(Utils.getPath(libPath, Installation.SCRIPT_UTIL_FILE_WINDOWS)); 180 } 181 else 182 { 183 script = Utils.getScriptPath(Utils.getPath(libPath, Installation.SCRIPT_UTIL_FILE_UNIX)); 184 } 185 args.add(script); 186 ProcessBuilder pb = new ProcessBuilder(args); 187 Map<String, String> env = pb.environment(); 188 env.put(SetupUtils.OPENDJ_JAVA_HOME, javaHome); 189 env.put("OPENDJ_JAVA_ARGS", option); 190 env.put("SCRIPT_UTIL_CMD", "set-full-environment-and-test-java"); 191 env.remove("OPENDJ_JAVA_BIN"); 192 // In windows by default the scripts ask the user to click on enter when 193 // they fail. Set this environment variable to avoid it. 194 if (isWindows()) 195 { 196 env.put("DO_NOT_PAUSE", "true"); 197 } 198 final Process process = pb.start(); 199 logger.info(LocalizableMessage.raw("launching " + args + " with env: " + env)); 200 InputStream is = process.getInputStream(); 201 BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 202 String line; 203 boolean errorDetected = false; 204 while (null != (line = reader.readLine())) 205 { 206 logger.info(LocalizableMessage.raw("The output: " + line)); 207 if (line.contains("ERROR: The detected Java version")) 208 { 209 if (isWindows()) 210 { 211 // If we are running windows, the process get blocked waiting for 212 // user input. Just wait for a certain time to print the output 213 // in the logger and then kill the process. 214 Thread t = new Thread(new Runnable() 215 { 216 @Override 217 public void run() 218 { 219 try 220 { 221 Thread.sleep(3000); 222 // To see if the process is over, call the exitValue method. 223 // If it is not over, a IllegalThreadStateException. 224 process.exitValue(); 225 } 226 catch (Throwable t) 227 { 228 process.destroy(); 229 } 230 } 231 }); 232 t.start(); 233 } 234 errorDetected = true; 235 } 236 } 237 process.waitFor(); 238 int returnCode = process.exitValue(); 239 logger.info(LocalizableMessage.raw("returnCode: " + returnCode)); 240 supported = returnCode == 0 && !errorDetected; 241 logger.info(LocalizableMessage.raw("supported: " + supported)); 242 } 243 catch (Throwable t) 244 { 245 logger.warn(LocalizableMessage.raw("Error testing option " + option + " on " + javaHome, t)); 246 } 247 return supported; 248 } 249 250 /** 251 * Creates a new file attempting to create the parent directories if 252 * necessary. 253 * 254 * @param f 255 * File to create 256 * @return boolean indicating whether the file was created; false otherwise 257 * @throws IOException 258 * if something goes wrong 259 */ 260 public static boolean createFile(File f) throws IOException 261 { 262 boolean success = false; 263 if (f != null) 264 { 265 File parent = f.getParentFile(); 266 if (!parent.exists()) 267 { 268 parent.mkdirs(); 269 } 270 success = f.createNewFile(); 271 } 272 return success; 273 } 274 275 /** 276 * Returns the absolute path for the given parentPath and relativePath. 277 * 278 * @param parentPath 279 * the parent path. 280 * @param relativePath 281 * the relative path. 282 * @return the absolute path for the given parentPath and relativePath. 283 */ 284 public static String getPath(String parentPath, String relativePath) 285 { 286 return getPath(new File(new File(parentPath), relativePath)); 287 } 288 289 /** 290 * Returns the String that can be used to launch an script using Runtime.exec. 291 * This method is required because in Windows the script that contain a "=" in 292 * their path must be quoted. 293 * 294 * @param script 295 * the script name 296 * @return the absolute path for the given parentPath and relativePath. 297 */ 298 public static String getScriptPath(String script) 299 { 300 return SetupUtils.getScriptPath(script); 301 } 302 303 /** 304 * Returns the absolute path for the given file. It tries to get the canonical 305 * file path. If it fails it returns the string representation. 306 * 307 * @param f 308 * File to get the path 309 * @return the absolute path for the given file. 310 */ 311 public static String getPath(File f) 312 { 313 String path = null; 314 if (f != null) 315 { 316 try 317 { 318 /* 319 * Do a best effort to avoid having a relative representation (for 320 * instance to avoid having ../../../). 321 */ 322 f = f.getCanonicalFile(); 323 } 324 catch (IOException ioe) 325 { 326 /* 327 * This is a best effort to get the best possible representation of the 328 * file: reporting the error is not necessary. 329 */ 330 } 331 path = f.toString(); 332 } 333 return path; 334 } 335 336 /** 337 * Returns <CODE>true</CODE> if the first provided path is under the second 338 * path in the file system. 339 * 340 * @param descendant 341 * the descendant candidate path. 342 * @param path 343 * the path. 344 * @return <CODE>true</CODE> if the first provided path is under the second 345 * path in the file system; <code>false</code> otherwise or if either 346 * of the files are null 347 */ 348 public static boolean isDescendant(File descendant, File path) 349 { 350 boolean isDescendant = false; 351 if (descendant != null && path != null) 352 { 353 File parent = descendant.getParentFile(); 354 while (parent != null && !isDescendant) 355 { 356 isDescendant = path.equals(parent); 357 if (!isDescendant) 358 { 359 parent = parent.getParentFile(); 360 } 361 } 362 } 363 return isDescendant; 364 } 365 366 /** 367 * Returns <CODE>true</CODE> if the parent directory for the provided path 368 * exists and <CODE>false</CODE> otherwise. 369 * 370 * @param path 371 * the path that we are analyzing. 372 * @return <CODE>true</CODE> if the parent directory for the provided path 373 * exists and <CODE>false</CODE> otherwise. 374 */ 375 public static boolean parentDirectoryExists(String path) 376 { 377 boolean parentExists = false; 378 File f = new File(path); 379 File parentFile = f.getParentFile(); 380 if (parentFile != null) 381 { 382 parentExists = parentFile.isDirectory(); 383 } 384 return parentExists; 385 } 386 387 /** 388 * Returns <CODE>true</CODE> if the the provided path is a file and exists and 389 * <CODE>false</CODE> otherwise. 390 * 391 * @param path 392 * the path that we are analyzing. 393 * @return <CODE>true</CODE> if the the provided path is a file and exists and 394 * <CODE>false</CODE> otherwise. 395 */ 396 public static boolean fileExists(String path) 397 { 398 File f = new File(path); 399 return f.isFile(); 400 } 401 402 /** 403 * Returns <CODE>true</CODE> if the the provided path is a directory, exists 404 * and is not empty <CODE>false</CODE> otherwise. 405 * 406 * @param path 407 * the path that we are analyzing. 408 * @return <CODE>true</CODE> if the the provided path is a directory, exists 409 * and is not empty <CODE>false</CODE> otherwise. 410 */ 411 public static boolean directoryExistsAndIsNotEmpty(String path) 412 { 413 final File f = new File(path); 414 if (f.isDirectory()) 415 { 416 final String[] ch = f.list(); 417 return ch != null && ch.length > 0; 418 } 419 return false; 420 } 421 422 /** 423 * Returns <CODE>true</CODE> if the the provided string is a configuration DN 424 * and <CODE>false</CODE> otherwise. 425 * 426 * @param dn 427 * the String we are analyzing. 428 * @return <CODE>true</CODE> if the the provided string is a configuration DN 429 * and <CODE>false</CODE> otherwise. 430 */ 431 public static boolean isConfigurationDn(String dn) 432 { 433 boolean isConfigurationDn = false; 434 String[] configDns = { "cn=config", Constants.SCHEMA_DN }; 435 for (int i = 0; i < configDns.length && !isConfigurationDn; i++) 436 { 437 isConfigurationDn = areDnsEqual(dn, configDns[i]); 438 } 439 return isConfigurationDn; 440 } 441 442 /** 443 * Returns <CODE>true</CODE> if the the provided strings represent the same DN 444 * and <CODE>false</CODE> otherwise. 445 * 446 * @param dn1 447 * the first dn to compare. 448 * @param dn2 449 * the second dn to compare. 450 * @return <CODE>true</CODE> if the the provided strings represent the same DN 451 * and <CODE>false</CODE> otherwise. 452 */ 453 public static boolean areDnsEqual(String dn1, String dn2) 454 { 455 boolean areDnsEqual = false; 456 try 457 { 458 LdapName name1 = new LdapName(dn1); 459 LdapName name2 = new LdapName(dn2); 460 areDnsEqual = name1.equals(name2); 461 } 462 catch (Exception ex) 463 { 464 // do nothing 465 } 466 467 return areDnsEqual; 468 } 469 470 /** 471 * Creates the parent directory if it does not already exist. 472 * 473 * @param f 474 * File for which parentage will be insured 475 * @return boolean indicating whether or not the input <code>f</code> has a 476 * parent after this method is invoked. 477 */ 478 public static boolean insureParentsExist(File f) 479 { 480 final File parent = f.getParentFile(); 481 final boolean b = parent.exists(); 482 if (!b) 483 { 484 return parent.mkdirs(); 485 } 486 return b; 487 } 488 489 /** 490 * Creates the a directory in the provided path. 491 * 492 * @param path 493 * the path. 494 * @return <CODE>true</CODE> if the path was created or already existed (and 495 * was a directory) and <CODE>false</CODE> otherwise. 496 * @throws IOException 497 * if something goes wrong. 498 */ 499 public static boolean createDirectory(String path) throws IOException 500 { 501 return createDirectory(new File(path)); 502 } 503 504 /** 505 * Creates the a directory in the provided path. 506 * 507 * @param f 508 * the path. 509 * @return <CODE>true</CODE> if the path was created or already existed (and 510 * was a directory) and <CODE>false</CODE> otherwise. 511 * @throws IOException 512 * if something goes wrong. 513 */ 514 public static boolean createDirectory(File f) throws IOException 515 { 516 boolean directoryCreated; 517 if (!f.exists()) 518 { 519 directoryCreated = f.mkdirs(); 520 } 521 else 522 { 523 directoryCreated = f.isDirectory(); 524 } 525 return directoryCreated; 526 } 527 528 /** 529 * Creates a file on the specified path with the contents of the provided 530 * stream. 531 * 532 * @param path 533 * the path where the file will be created. 534 * @param is 535 * the InputStream with the contents of the file. 536 * @throws IOException 537 * if something goes wrong. 538 */ 539 public static void createFile(File path, InputStream is) throws IOException 540 { 541 FileOutputStream out; 542 BufferedOutputStream dest; 543 byte[] data = new byte[BUFFER_SIZE]; 544 int count; 545 546 out = new FileOutputStream(path); 547 548 dest = new BufferedOutputStream(out); 549 550 while ((count = is.read(data, 0, BUFFER_SIZE)) != -1) 551 { 552 dest.write(data, 0, count); 553 } 554 dest.flush(); 555 dest.close(); 556 } 557 558 /** 559 * Creates a file on the specified path with the contents of the provided 560 * String. The file is protected, so that 'others' have no access to it. 561 * 562 * @param path 563 * the path where the file will be created. 564 * @param content 565 * the String with the contents of the file. 566 * @throws IOException 567 * if something goes wrong. 568 * @throws InterruptedException 569 * if there is a problem changing the permissions of the file. 570 */ 571 public static void createProtectedFile(String path, String content) throws IOException, InterruptedException 572 { 573 FileWriter file = new FileWriter(path); 574 PrintWriter out = new PrintWriter(file); 575 576 out.println(content); 577 578 out.flush(); 579 out.close(); 580 581 if (!isWindows()) 582 { 583 setPermissionsUnix(path, "600"); 584 } 585 } 586 587 /** 588 * This is a helper method that gets a LocalizableMessage representation of 589 * the elements in the Collection of Messages. The LocalizableMessage will 590 * display the different elements separated by the separator String. 591 * 592 * @param col 593 * the collection containing the messages. 594 * @param separator 595 * the separator String to be used. 596 * @return the message representation for the collection; null if 597 * <code>col</code> is null 598 */ 599 public static LocalizableMessage getMessageFromCollection(Collection<LocalizableMessage> col, String separator) 600 { 601 if (col != null) 602 { 603 final LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 604 for (LocalizableMessage m : col) 605 { 606 mb.append(separator).append(m); 607 } 608 return mb.toMessage(); 609 } 610 return null; 611 } 612 613 /** 614 * Returns the default server location that will be proposed to the user in 615 * the installation. 616 * 617 * @return the default server location that will be proposed to the user in 618 * the installation. 619 */ 620 public static String getDefaultServerLocation() 621 { 622 String userDir = System.getProperty("user.home"); 623 String firstLocation = userDir + File.separator + SHORT_NAME.toLowerCase(Locale.ENGLISH); 624 String serverLocation = firstLocation; 625 int i = 1; 626 while (fileExists(serverLocation) || directoryExistsAndIsNotEmpty(serverLocation)) 627 { 628 serverLocation = firstLocation + "-" + i; 629 i++; 630 } 631 return serverLocation; 632 } 633 634 /** 635 * Returns <CODE>true</CODE> if there is more disk space in the provided path 636 * than what is specified with the bytes parameter. 637 * 638 * @param directoryPath 639 * the path. 640 * @param bytes 641 * the disk space. 642 * @return <CODE>true</CODE> if there is more disk space in the provided path 643 * than what is specified with the bytes parameter. 644 */ 645 public static synchronized boolean hasEnoughSpace(String directoryPath, long bytes) 646 { 647 // TODO This does not work with quotas etc. but at least it seems that 648 // we do not write all data on disk if it fails. 649 boolean hasEnoughSpace = false; 650 File file = null; 651 RandomAccessFile raf = null; 652 File directory = new File(directoryPath); 653 boolean deleteDirectory = false; 654 if (!directory.exists()) 655 { 656 deleteDirectory = directory.mkdir(); 657 } 658 659 try 660 { 661 file = File.createTempFile("temp" + System.nanoTime(), ".tmp", directory); 662 raf = new RandomAccessFile(file, "rw"); 663 raf.setLength(bytes); 664 hasEnoughSpace = true; 665 } 666 catch (IOException ex) 667 { /* do nothing */ 668 } 669 finally 670 { 671 StaticUtils.close(raf); 672 if (file != null) 673 { 674 file.delete(); 675 } 676 } 677 678 if (deleteDirectory) 679 { 680 directory.delete(); 681 } 682 683 return hasEnoughSpace; 684 } 685 686 /** 687 * Gets a localized representation of the provide TopologyCacheException. 688 * 689 * @param te 690 * the exception. 691 * @return a localized representation of the provide TopologyCacheException. 692 */ 693 public static LocalizableMessage getMessage(TopologyCacheException te) 694 { 695 LocalizableMessageBuilder buf = new LocalizableMessageBuilder(); 696 697 String ldapUrl = te.getLdapUrl(); 698 if (ldapUrl != null) 699 { 700 String hostName = ldapUrl.substring(ldapUrl.indexOf("://") + 3); 701 buf.append(INFO_SERVER_ERROR.get(hostName)); 702 buf.append(" "); 703 } 704 if (te.getType() == TopologyCacheException.Type.TIMEOUT) 705 { 706 buf.append(INFO_ERROR_CONNECTING_TIMEOUT.get()); 707 } 708 else if (te.getCause() instanceof NamingException) 709 { 710 buf.append(getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), te.getCause())); 711 } 712 else 713 { 714 logger.warn(LocalizableMessage.raw("Unexpected error: " + te, te)); 715 // This is unexpected. 716 if (te.getCause() != null) 717 { 718 buf.append(getThrowableMsg(INFO_BUG_MSG.get(), te.getCause())); 719 } 720 else 721 { 722 buf.append(getThrowableMsg(INFO_BUG_MSG.get(), te)); 723 } 724 } 725 return buf.toMessage(); 726 } 727 728 /** 729 * Sets the permissions of the provided paths with the provided permission 730 * String. 731 * 732 * @param paths 733 * the paths to set permissions on. 734 * @param permissions 735 * the UNIX-mode file system permission representation (for example 736 * "644" or "755") 737 * @return the return code of the chmod command. 738 * @throws IOException 739 * if something goes wrong. 740 * @throws InterruptedException 741 * if the Runtime.exec method is interrupted. 742 */ 743 public static int setPermissionsUnix(ArrayList<String> paths, String permissions) throws IOException, 744 InterruptedException 745 { 746 String[] args = new String[paths.size() + 2]; 747 args[0] = "chmod"; 748 args[1] = permissions; 749 for (int i = 2; i < args.length; i++) 750 { 751 args[i] = paths.get(i - 2); 752 } 753 Process p = Runtime.getRuntime().exec(args); 754 return p.waitFor(); 755 } 756 757 /** 758 * Sets the permissions of the provided paths with the provided permission 759 * String. 760 * 761 * @param path 762 * to set permissions on. 763 * @param permissions 764 * the UNIX-mode file system permission representation (for example 765 * "644" or "755") 766 * @return the return code of the chmod command. 767 * @throws IOException 768 * if something goes wrong. 769 * @throws InterruptedException 770 * if the Runtime.exec method is interrupted. 771 */ 772 public static int setPermissionsUnix(String path, String permissions) throws IOException, InterruptedException 773 { 774 String[] args = new String[3]; 775 args[0] = "chmod"; 776 args[1] = permissions; 777 args[2] = path; 778 Process p = Runtime.getRuntime().exec(args); 779 return p.waitFor(); 780 } 781 782 /** 783 * Indicates whether we are in a web start installation or not. 784 * 785 * @return <CODE>true</CODE> if we are in a web start installation and 786 * <CODE>false</CODE> if not. 787 */ 788 public static boolean isWebStart() 789 { 790 return SetupUtils.isWebStart(); 791 } 792 793 /** 794 * Returns <CODE>true</CODE> if this is executed from command line and 795 * <CODE>false</CODE> otherwise. 796 * 797 * @return <CODE>true</CODE> if this is executed from command line and 798 * <CODE>false</CODE> otherwise. 799 */ 800 public static boolean isCli() 801 { 802 return "true".equals(System.getProperty(Constants.CLI_JAVA_PROPERTY)); 803 } 804 805 /** 806 * Creates an LDAP+StartTLS connection and returns the corresponding 807 * LdapContext. This method first creates an LdapContext with anonymous bind. 808 * Then it requests a StartTlsRequest extended operation. The StartTlsResponse 809 * is setup with the specified hostname verifier. Negotiation is done using a 810 * TrustSocketFactory so that the specified TrustManager gets called during 811 * the SSL handshake. If trust manager is null, certificates are not checked 812 * during SSL handshake. 813 * 814 * @param ldapsURL 815 * the target *LDAPS* URL. 816 * @param dn 817 * passed as Context.SECURITY_PRINCIPAL if not null. 818 * @param pwd 819 * passed as Context.SECURITY_CREDENTIALS if not null. 820 * @param timeout 821 * passed as com.sun.jndi.ldap.connect.timeout if > 0. 822 * @param env 823 * null or additional environment properties. 824 * @param trustManager 825 * null or the trust manager to be invoked during SSL. negociation. 826 * @param verifier 827 * null or the hostname verifier to be setup in the StartTlsResponse. 828 * @return the established connection with the given parameters. 829 * @throws NamingException 830 * the exception thrown when instantiating InitialLdapContext. 831 * @see javax.naming.Context 832 * @see javax.naming.ldap.InitialLdapContext 833 * @see javax.naming.ldap.StartTlsRequest 834 * @see javax.naming.ldap.StartTlsResponse 835 * @see org.opends.admin.ads.util.TrustedSocketFactory 836 */ 837 838 public static InitialLdapContext createStartTLSContext(String ldapsURL, String dn, String pwd, int timeout, 839 Hashtable<String, String> env, TrustManager trustManager, HostnameVerifier verifier) throws NamingException 840 { 841 return ConnectionUtils.createStartTLSContext(ldapsURL, dn, pwd, timeout, env, trustManager, null, verifier); 842 } 843 844 /** 845 * Returns a message object for the given NamingException. The code assume 846 * that we are trying to connect to the local server. 847 * 848 * @param ne 849 * the NamingException. 850 * @return a message object for the given NamingException. 851 */ 852 public static LocalizableMessage getMessageForException(NamingException ne) 853 { 854 final String detailedException = ne.toString(true); 855 if (isCertificateException(ne)) 856 { 857 return INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE.get(detailedException); 858 } 859 else if (ne instanceof AuthenticationException) 860 { 861 return ERR_CANNOT_CONNECT_TO_LOCAL_AUTHENTICATION.get(detailedException); 862 } 863 else if (ne instanceof NoPermissionException) 864 { 865 return ERR_CANNOT_CONNECT_TO_LOCAL_PERMISSIONS.get(detailedException); 866 } 867 else if (ne instanceof NamingSecurityException) 868 { 869 return ERR_CANNOT_CONNECT_TO_LOCAL_PERMISSIONS.get(detailedException); 870 } 871 else if (ne instanceof CommunicationException) 872 { 873 return ERR_CANNOT_CONNECT_TO_LOCAL_COMMUNICATION.get(detailedException); 874 } 875 else 876 { 877 return ERR_CANNOT_CONNECT_TO_LOCAL_GENERIC.get(detailedException); 878 } 879 } 880 881 /** 882 * Returns the path of the installation of the directory server. Note that 883 * this method assumes that this code is being run locally. 884 * 885 * @return the path of the installation of the directory server. 886 */ 887 public static String getInstallPathFromClasspath() 888 { 889 String installPath = System.getProperty("org.opends.quicksetup.Root"); 890 if (installPath != null) 891 { 892 return installPath; 893 } 894 895 /* Get the install path from the Class Path */ 896 String sep = System.getProperty("path.separator"); 897 String[] classPaths = System.getProperty("java.class.path").split(sep); 898 String path = getInstallPath(classPaths); 899 if (path != null) 900 { 901 File f = new File(path).getAbsoluteFile(); 902 File librariesDir = f.getParentFile(); 903 904 /* 905 * Do a best effort to avoid having a relative representation (for 906 * instance to avoid having ../../../). 907 */ 908 try 909 { 910 installPath = librariesDir.getParentFile().getCanonicalPath(); 911 } 912 catch (IOException ioe) 913 { 914 // Best effort 915 installPath = librariesDir.getParent(); 916 } 917 } 918 return installPath; 919 } 920 921 private static String getInstallPath(final String[] classPaths) 922 { 923 for (String classPath : classPaths) 924 { 925 final String normPath = classPath.replace(File.separatorChar, '/'); 926 if (normPath.endsWith(OPENDJ_BOOTSTRAP_CLIENT_JAR_RELATIVE_PATH) 927 || normPath.endsWith(OPENDJ_BOOTSTRAP_JAR_RELATIVE_PATH)) 928 { 929 return classPath; 930 } 931 } 932 return null; 933 } 934 935 /** 936 * Returns the path of the installation of the directory server. Note that 937 * this method assumes that this code is being run locally. 938 * 939 * @param installPath 940 * The installation path 941 * @return the path of the installation of the directory server. 942 */ 943 public static String getInstancePathFromInstallPath(String installPath) 944 { 945 String instancePathFileName = Installation.INSTANCE_LOCATION_PATH; 946 File _svcScriptPathName = new File( 947 installPath + File.separator + Installation.LIBRARIES_PATH_RELATIVE + File.separator + "_svc-opendj.sh"); 948 949 // look for /etc/opt/opendj/instance.loc 950 File f = new File(instancePathFileName); 951 if (!_svcScriptPathName.exists() || !f.exists()) 952 { 953 // look for <installPath>/instance.loc 954 instancePathFileName = installPath + File.separator + Installation.INSTANCE_LOCATION_PATH_RELATIVE; 955 f = new File(instancePathFileName); 956 if (!f.exists()) 957 { 958 return installPath; 959 } 960 } 961 962 BufferedReader reader; 963 try 964 { 965 reader = new BufferedReader(new FileReader(instancePathFileName)); 966 } 967 catch (Exception e) 968 { 969 return installPath; 970 } 971 972 // Read the first line and close the file. 973 String line; 974 try 975 { 976 line = reader.readLine(); 977 File instanceLoc = new File(line.trim()); 978 if (instanceLoc.isAbsolute()) 979 { 980 return instanceLoc.getAbsolutePath(); 981 } 982 else 983 { 984 return new File(installPath + File.separator + instanceLoc.getPath()).getAbsolutePath(); 985 } 986 } 987 catch (Exception e) 988 { 989 return installPath; 990 } 991 finally 992 { 993 StaticUtils.close(reader); 994 } 995 } 996 997 /** 998 * Returns the max size in character of a line to be displayed in the command 999 * line. 1000 * 1001 * @return the max size in character of a line to be displayed in the command 1002 * line. 1003 */ 1004 public static int getCommandLineMaxLineWidth() 1005 { 1006 return MAX_LINE_WIDTH; 1007 } 1008 1009 /** 1010 * Puts Swing menus in the Mac OS menu bar, if using the Aqua look and feel, 1011 * and sets the application name that is displayed in the application menu and 1012 * in the dock. 1013 * 1014 * @param appName 1015 * application name to display in the menu bar and the dock. 1016 */ 1017 public static void setMacOSXMenuBar(LocalizableMessage appName) 1018 { 1019 System.setProperty("apple.laf.useScreenMenuBar", "true"); 1020 System.setProperty("com.apple.mrj.application.apple.menu.about.name", String.valueOf(appName)); 1021 } 1022 1023 /** 1024 * Returns the number of entries contained in the zip file. This is used to 1025 * update properly the progress bar ratio. 1026 * 1027 * @return the number of entries contained in the zip file. 1028 */ 1029 public static int getNumberZipEntries() 1030 { 1031 // TODO we should get this dynamically during build 1032 return 165; 1033 } 1034 1035 /** 1036 * Creates a string consisting of the string representation of the elements in 1037 * the <code>list</code> separated by <code>separator</code>. 1038 * 1039 * @param list 1040 * the list to print 1041 * @param separator 1042 * to use in separating elements 1043 * @param prefix 1044 * prepended to each individual element in the list before adding to 1045 * the returned string. 1046 * @param suffix 1047 * appended to each individual element in the list before adding to 1048 * the returned string. 1049 * @return String representing the list 1050 */ 1051 public static String listToString(List<?> list, String separator, String prefix, String suffix) 1052 { 1053 StringBuilder sb = new StringBuilder(); 1054 for (int i = 0; i < list.size(); i++) 1055 { 1056 if (prefix != null) 1057 { 1058 sb.append(prefix); 1059 } 1060 sb.append(list.get(i)); 1061 if (suffix != null) 1062 { 1063 sb.append(suffix); 1064 } 1065 if (i < list.size() - 1) 1066 { 1067 sb.append(separator); 1068 } 1069 } 1070 return sb.toString(); 1071 } 1072 1073 /** 1074 * Returns the file system permissions for a file. 1075 * 1076 * @param file 1077 * the file for which we want the file permissions. 1078 * @return the file system permissions for the file. 1079 */ 1080 public static String getFileSystemPermissions(File file) 1081 { 1082 String name = file.getName(); 1083 if (file.getParent().endsWith(File.separator + Installation.WINDOWS_BINARIES_PATH_RELATIVE) 1084 || file.getParent().endsWith(File.separator + Installation.UNIX_BINARIES_PATH_RELATIVE)) 1085 { 1086 return name.endsWith(".bat") ? "644" : "755"; 1087 } 1088 else if (name.endsWith(".sh") 1089 || name.endsWith(Installation.UNIX_SETUP_FILE_NAME) 1090 || name.endsWith(Installation.UNIX_UNINSTALL_FILE_NAME) 1091 || name.endsWith(Installation.UNIX_UPGRADE_FILE_NAME) 1092 || name.endsWith(Installation.MAC_JAVA_APP_STUB_NAME)) 1093 { 1094 return "755"; 1095 } 1096 else 1097 { 1098 return "644"; 1099 } 1100 } 1101 1102 /** 1103 * Inserts HTML break tags into <code>d</code> breaking it up so that ideally 1104 * no line is longer than <code>maxll</code> assuming no single word is longer 1105 * then <code>maxll</code>. If the string already contains HTML tags that 1106 * cause a line break (e.g break and closing list item tags) they are 1107 * respected by this method when calculating where to place new breaks to 1108 * control the maximum line length. 1109 * 1110 * @param cs 1111 * String to break 1112 * @param maxll 1113 * int maximum line length 1114 * @return String representing <code>d</code> with HTML break tags inserted 1115 */ 1116 public static String breakHtmlString(CharSequence cs, int maxll) 1117 { 1118 if (cs != null) 1119 { 1120 String d = cs.toString(); 1121 int len = d.length(); 1122 if (len <= 0) 1123 { 1124 return d; 1125 } 1126 if (len > maxll) 1127 { 1128 1129 // First see if there are any tags that would cause a 1130 // natural break in the line. If so start line break 1131 // point evaluation from that point. 1132 for (String tag : Constants.BREAKING_TAGS) 1133 { 1134 int p = d.lastIndexOf(tag, maxll); 1135 if (p > 0 && p < len) 1136 { 1137 return d.substring(0, p + tag.length()) + breakHtmlString(d.substring(p + tag.length()), maxll); 1138 } 1139 } 1140 1141 // Now look for spaces in which to insert a break. 1142 // First see if there are any spaces counting backward 1143 // from the max line length. If there aren't any, then 1144 // use the first space encountered after the max line 1145 // length. 1146 int p = d.lastIndexOf(' ', maxll); 1147 if (p <= 0) 1148 { 1149 p = d.indexOf(' ', maxll); 1150 } 1151 if (p > 0 && p < len) 1152 { 1153 return d.substring(0, p) + Constants.HTML_LINE_BREAK + breakHtmlString(d.substring(p + 1), maxll); 1154 } 1155 else 1156 { 1157 return d; 1158 } 1159 } 1160 else 1161 { 1162 return d; 1163 } 1164 } 1165 else 1166 { 1167 return null; 1168 } 1169 } 1170 1171 /** 1172 * Converts existing HTML break tags to native line separators. 1173 * 1174 * @param s 1175 * string to convert 1176 * @return converted string 1177 */ 1178 public static String convertHtmlBreakToLineSeparator(String s) 1179 { 1180 return s.replaceAll("<br>", Constants.LINE_SEPARATOR); 1181 } 1182 1183 /** 1184 * Strips any potential HTML markup from a given string. 1185 * 1186 * @param s 1187 * string to strip 1188 * @return resulting string 1189 */ 1190 public static String stripHtml(String s) 1191 { 1192 if (s != null) 1193 { 1194 1195 // This is not a comprehensive solution but addresses the few tags 1196 // that we have in Resources.properties at the moment. 1197 // Note that the following might strip out more than is intended for non-tags 1198 // like '<your name here>' or for funky tags like '<tag attr="1 > 0">'. 1199 // See test class for cases that might cause problems. 1200 return s.replaceAll("<.*?>", ""); 1201 } 1202 return null; 1203 } 1204 1205 /** 1206 * Tests a text string to see if it contains HTML. 1207 * 1208 * @param text 1209 * String to test 1210 * @return true if the string contains HTML 1211 */ 1212 public static boolean containsHtml(String text) 1213 { 1214 return text != null && text.indexOf('<') != -1 && text.indexOf('>') != -1; 1215 } 1216 1217 private static EmptyPrintStream emptyStream = new EmptyPrintStream(); 1218 1219 /** 1220 * Returns a printstream that does not write anything to standard output. 1221 * 1222 * @return a printstream that does not write anything to standard output. 1223 */ 1224 public static EmptyPrintStream getEmptyPrintStream() 1225 { 1226 if (emptyStream == null) 1227 { 1228 emptyStream = new EmptyPrintStream(); 1229 } 1230 return emptyStream; 1231 } 1232 1233 /** 1234 * Returns the current time of a server in milliseconds. 1235 * 1236 * @param ctx 1237 * the connection to the server. 1238 * @return the current time of a server in milliseconds. 1239 */ 1240 public static long getServerClock(InitialLdapContext ctx) 1241 { 1242 long time = -1; 1243 SearchControls ctls = new SearchControls(); 1244 ctls.setSearchScope(SearchControls.OBJECT_SCOPE); 1245 ctls.setReturningAttributes(new String[] { "currentTime" }); 1246 String filter = "(objectclass=*)"; 1247 1248 try 1249 { 1250 LdapName jndiName = new LdapName("cn=monitor"); 1251 NamingEnumeration<?> listeners = ctx.search(jndiName, filter, ctls); 1252 1253 try 1254 { 1255 while (listeners.hasMore()) 1256 { 1257 SearchResult sr = (SearchResult) listeners.next(); 1258 1259 String v = getFirstValue(sr, "currentTime"); 1260 1261 TimeZone utcTimeZone = TimeZone.getTimeZone("UTC"); 1262 1263 SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); 1264 formatter.setTimeZone(utcTimeZone); 1265 1266 time = formatter.parse(v).getTime(); 1267 } 1268 } 1269 finally 1270 { 1271 listeners.close(); 1272 } 1273 } 1274 catch (Throwable t) 1275 { 1276 logger.warn(LocalizableMessage.raw("Error retrieving server current time: " + t, t)); 1277 } 1278 return time; 1279 } 1280 1281 /** 1282 * Checks that the java version we are running is compatible with OpenDS. 1283 * 1284 * @throws IncompatibleVersionException 1285 * if the java version we are running is not compatible with OpenDS. 1286 */ 1287 public static void checkJavaVersion() throws IncompatibleVersionException 1288 { 1289 try 1290 { 1291 com.forgerock.opendj.cli.Utils.checkJavaVersion(); 1292 } 1293 catch (ClientException e) 1294 { 1295 throw new IncompatibleVersionException(e.getMessageObject(), e); 1296 } 1297 1298 if (Utils.isWebStart()) 1299 { 1300 // Check that the JNLP service exists. 1301 try 1302 { 1303 javax.jnlp.ServiceManager.lookup(JNLP_SERVICE_NAME); 1304 } 1305 catch (Throwable t) 1306 { 1307 throw new IncompatibleVersionException( 1308 INFO_DOWNLOADING_ERROR_NO_SERVICE_FOUND.get(JNLP_SERVICE_NAME, getSetupFilename()), t); 1309 } 1310 } 1311 } 1312 1313 /** 1314 * Basic method to know if the host is local or not. This is only used to know 1315 * if we can perform a port check or not. 1316 * 1317 * @param host 1318 * the host to analyze. 1319 * @return <CODE>true</CODE> if it is the local host and <CODE>false</CODE> 1320 * otherwise. 1321 */ 1322 public static boolean isLocalHost(String host) 1323 { 1324 if ("localhost".equalsIgnoreCase(host)) 1325 { 1326 return true; 1327 } 1328 1329 try 1330 { 1331 InetAddress localAddress = InetAddress.getLocalHost(); 1332 InetAddress[] addresses = InetAddress.getAllByName(host); 1333 for (InetAddress address : addresses) 1334 { 1335 if (localAddress.equals(address)) 1336 { 1337 return true; 1338 } 1339 } 1340 } 1341 catch (Throwable t) 1342 { 1343 logger.warn(LocalizableMessage.raw("Failing checking host names: " + t, t)); 1344 } 1345 return false; 1346 } 1347 1348 /** 1349 * Returns the HTML representation of a plain text string which is obtained 1350 * by converting some special characters (like '<') into its equivalent 1351 * escaped HTML representation. 1352 * 1353 * @param rawString the String from which we want to obtain the HTML 1354 * representation. 1355 * @return the HTML representation of the plain text string. 1356 */ 1357 private static String escapeHtml(String rawString) 1358 { 1359 StringBuilder buffer = new StringBuilder(); 1360 for (int i = 0; i < rawString.length(); i++) 1361 { 1362 char c = rawString.charAt(i); 1363 switch (c) 1364 { 1365 case '<': 1366 buffer.append("<"); 1367 break; 1368 1369 case '>': 1370 buffer.append(">"); 1371 break; 1372 1373 case '&': 1374 buffer.append("&"); 1375 break; 1376 1377 case '"': 1378 buffer.append("""); 1379 break; 1380 1381 default: 1382 buffer.append(c); 1383 break; 1384 } 1385 } 1386 1387 return buffer.toString(); 1388 } 1389 1390 /** 1391 * Returns the HTML representation for a given text. without adding any kind 1392 * of font or style elements. Just escapes the problematic characters 1393 * (like '<') and transform the break lines into '\n' characters. 1394 * 1395 * @param text the source text from which we want to get the HTML 1396 * representation 1397 * @return the HTML representation for the given text. 1398 */ 1399 public static String getHtml(String text) 1400 { 1401 StringBuilder buffer = new StringBuilder(); 1402 if (text != null) 1403 { 1404 text = text.replaceAll("\r\n", "\n"); 1405 String[] lines = text.split("[\n\r\u0085\u2028\u2029]"); 1406 for (int i = 0; i < lines.length; i++) 1407 { 1408 if (i != 0) 1409 { 1410 buffer.append(Constants.HTML_LINE_BREAK); 1411 } 1412 buffer.append(escapeHtml(lines[i])); 1413 } 1414 } 1415 return buffer.toString(); 1416 } 1417 1418 /** 1419 * Tries to find a customized object in the customization class. If the 1420 * customization class does not exist or it does not contain the field as the 1421 * specified type of the object, returns the default value. 1422 * 1423 * @param <T> 1424 * the type of the customized object. 1425 * @param fieldName 1426 * the name of the field representing an object in the customization 1427 * class. 1428 * @param defaultValue 1429 * the default value. 1430 * @param valueClass 1431 * the class of the parametrized value. 1432 * @return the customized object. 1433 */ 1434 public static <T> T getCustomizedObject(String fieldName, T defaultValue, Class<T> valueClass) 1435 { 1436 T value = defaultValue; 1437 if (!isWebStart()) 1438 { 1439 try 1440 { 1441 Class<?> c = Class.forName(Utils.CUSTOMIZATION_CLASS_NAME); 1442 Object obj = c.newInstance(); 1443 1444 value = valueClass.cast(c.getField(fieldName).get(obj)); 1445 } 1446 catch (Exception ex) 1447 { 1448 // do nothing 1449 } 1450 } 1451 return value; 1452 } 1453 1454 /** 1455 * Adds word break tags to the provided html string. 1456 * 1457 * @param htmlString 1458 * the string. 1459 * @param from 1460 * the first index to start the spacing from. 1461 * @param spacing 1462 * the minimal spacing between word breaks. 1463 * @return a string containing word breaks. 1464 */ 1465 public static String addWordBreaks(String htmlString, int from, int spacing) 1466 { 1467 StringBuilder sb = new StringBuilder(); 1468 boolean insideTag = false; 1469 int totalAddedChars = 0; 1470 int addedChars = 0; 1471 for (int i = 0; i < htmlString.length(); i++) 1472 { 1473 char c = htmlString.charAt(i); 1474 sb.append(c); 1475 if (c == '<') 1476 { 1477 insideTag = true; 1478 } 1479 else if (c == '>' && insideTag) 1480 { 1481 insideTag = false; 1482 } 1483 if (!insideTag && c != '>') 1484 { 1485 addedChars++; 1486 totalAddedChars++; 1487 } 1488 if (addedChars > spacing && totalAddedChars > from && !insideTag) 1489 { 1490 sb.append("<wbr>"); 1491 addedChars = 0; 1492 } 1493 } 1494 return sb.toString(); 1495 } 1496 1497 /** 1498 * Returns the localized string describing the DataOptions chosen by the user. 1499 * 1500 * @param userInstallData 1501 * the DataOptions of the user. 1502 * @return the localized string describing the DataOptions chosen by the user. 1503 */ 1504 public static String getDataDisplayString(final UserData userInstallData) 1505 { 1506 LocalizableMessage msg; 1507 1508 final DataReplicationOptions repl = userInstallData.getReplicationOptions(); 1509 final SuffixesToReplicateOptions suf = userInstallData.getSuffixesToReplicateOptions(); 1510 1511 boolean createSuffix = repl.getType() == DataReplicationOptions.Type.FIRST_IN_TOPOLOGY 1512 || repl.getType() == DataReplicationOptions.Type.STANDALONE 1513 || suf.getType() == SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY; 1514 1515 if (createSuffix) 1516 { 1517 LocalizableMessage arg2; 1518 NewSuffixOptions options = userInstallData.getNewSuffixOptions(); 1519 1520 switch (options.getType()) 1521 { 1522 case CREATE_BASE_ENTRY: 1523 arg2 = INFO_REVIEW_CREATE_BASE_ENTRY_LABEL.get(options.getBaseDns().getFirst()); 1524 break; 1525 1526 case LEAVE_DATABASE_EMPTY: 1527 arg2 = INFO_REVIEW_LEAVE_DATABASE_EMPTY_LABEL.get(); 1528 break; 1529 1530 case IMPORT_FROM_LDIF_FILE: 1531 arg2 = INFO_REVIEW_IMPORT_LDIF.get(options.getLDIFPaths().getFirst()); 1532 break; 1533 1534 case IMPORT_AUTOMATICALLY_GENERATED_DATA: 1535 arg2 = INFO_REVIEW_IMPORT_AUTOMATICALLY_GENERATED.get(options.getNumberEntries()); 1536 break; 1537 1538 default: 1539 throw new IllegalArgumentException("Unknown type: " + options.getType()); 1540 } 1541 1542 if (options.getBaseDns().isEmpty()) 1543 { 1544 msg = INFO_REVIEW_CREATE_NO_SUFFIX.get(); 1545 } 1546 else 1547 { 1548 final String backendType = userInstallData.getBackendType().getUserFriendlyName().toString(); 1549 if (options.getBaseDns().size() > 1) 1550 { 1551 msg = INFO_REVIEW_CREATE_SUFFIX.get( 1552 backendType, joinAsString(Constants.LINE_SEPARATOR, options.getBaseDns()), arg2); 1553 } 1554 else 1555 { 1556 msg = INFO_REVIEW_CREATE_SUFFIX.get(backendType, options.getBaseDns().getFirst(), arg2); 1557 } 1558 } 1559 } 1560 else 1561 { 1562 final StringBuilder buf = new StringBuilder(); 1563 for (final SuffixDescriptor suffix : suf.getSuffixes()) 1564 { 1565 if (buf.length() > 0) 1566 { 1567 buf.append(Constants.LINE_SEPARATOR); 1568 } 1569 buf.append(suffix.getDN()); 1570 } 1571 msg = INFO_REVIEW_REPLICATE_SUFFIX.get(buf); 1572 } 1573 1574 return msg.toString(); 1575 } 1576 1577 /** 1578 * Returns a localized String representation of the provided SecurityOptions 1579 * object. 1580 * 1581 * @param ops 1582 * the SecurityOptions object from which we want to obtain the String 1583 * representation. 1584 * @param html 1585 * whether the resulting String must be in HTML or not. 1586 * @return a localized String representation of the provided SecurityOptions 1587 * object. 1588 */ 1589 public static String getSecurityOptionsString(SecurityOptions ops, boolean html) 1590 { 1591 StringBuilder buf = new StringBuilder(); 1592 1593 if (ops.getCertificateType() == SecurityOptions.CertificateType.NO_CERTIFICATE) 1594 { 1595 buf.append(INFO_NO_SECURITY.get()); 1596 } 1597 else 1598 { 1599 if (ops.getEnableStartTLS()) 1600 { 1601 buf.append(INFO_ENABLE_STARTTLS.get()); 1602 } 1603 if (ops.getEnableSSL()) 1604 { 1605 if (buf.length() > 0) 1606 { 1607 if (html) 1608 { 1609 buf.append(Constants.HTML_LINE_BREAK); 1610 } 1611 else 1612 { 1613 buf.append("\n"); 1614 } 1615 } 1616 buf.append(INFO_ENABLE_SSL.get(ops.getSslPort())); 1617 } 1618 if (html) 1619 { 1620 buf.append(Constants.HTML_LINE_BREAK); 1621 } 1622 else 1623 { 1624 buf.append("\n"); 1625 } 1626 LocalizableMessage certMsg; 1627 switch (ops.getCertificateType()) 1628 { 1629 case SELF_SIGNED_CERTIFICATE: 1630 certMsg = INFO_SELF_SIGNED_CERTIFICATE.get(); 1631 break; 1632 1633 case JKS: 1634 certMsg = INFO_JKS_CERTIFICATE.get(); 1635 break; 1636 1637 case JCEKS: 1638 certMsg = INFO_JCEKS_CERTIFICATE.get(); 1639 break; 1640 1641 case PKCS11: 1642 certMsg = INFO_PKCS11_CERTIFICATE.get(); 1643 break; 1644 1645 case PKCS12: 1646 certMsg = INFO_PKCS12_CERTIFICATE.get(); 1647 break; 1648 1649 default: 1650 throw new IllegalStateException("Unknown certificate options type: " + ops.getCertificateType()); 1651 } 1652 buf.append(certMsg); 1653 } 1654 1655 if (html) 1656 { 1657 return "<html>" + UIFactory.applyFontToHtml(buf.toString(), UIFactory.SECONDARY_FIELD_VALID_FONT); 1658 } 1659 else 1660 { 1661 return buf.toString(); 1662 } 1663 } 1664 1665 /** 1666 * Returns a String representation of the provided command-line. 1667 * 1668 * @param cmd 1669 * the command-line arguments. 1670 * @param formatter 1671 * the formatted to be used to create the String representation. 1672 * @return a String representation of the provided command-line. 1673 */ 1674 public static String getFormattedEquivalentCommandLine(List<String> cmd, ProgressMessageFormatter formatter) 1675 { 1676 StringBuilder builder = new StringBuilder(); 1677 builder.append(formatter.getFormattedProgress(LocalizableMessage.raw(cmd.get(0)))); 1678 int initialIndex = 1; 1679 StringBuilder sbSeparator = new StringBuilder(); 1680 sbSeparator.append(formatter.getSpace()); 1681 if (!isWindows()) 1682 { 1683 sbSeparator.append("\\"); 1684 sbSeparator.append(formatter.getLineBreak()); 1685 for (int i = 0; i < 10; i++) 1686 { 1687 sbSeparator.append(formatter.getSpace()); 1688 } 1689 } 1690 1691 String lineSeparator = sbSeparator.toString(); 1692 for (int i = initialIndex; i < cmd.size(); i++) 1693 { 1694 String s = cmd.get(i); 1695 if (s.startsWith("-")) 1696 { 1697 builder.append(lineSeparator); 1698 builder.append(formatter.getFormattedProgress(LocalizableMessage.raw(s))); 1699 } 1700 else 1701 { 1702 builder.append(formatter.getSpace()); 1703 builder.append(formatter.getFormattedProgress(LocalizableMessage.raw(escapeCommandLineValue(s)))); 1704 } 1705 } 1706 return builder.toString(); 1707 } 1708 1709 /** 1710 * This method simply takes a value and tries to transform it (with escape or 1711 * '"') characters so that it can be used in a command line. 1712 * 1713 * @param value 1714 * the String to be treated. 1715 * @return the transformed value. 1716 */ 1717 public static String escapeCommandLineValue(String value) 1718 { 1719 StringBuilder b = new StringBuilder(); 1720 if (isUnix()) 1721 { 1722 for (int i = 0; i < value.length(); i++) 1723 { 1724 char c = value.charAt(i); 1725 boolean charToEscapeFound = false; 1726 for (int j = 0; j < CHARS_TO_ESCAPE.length && !charToEscapeFound; j++) 1727 { 1728 charToEscapeFound = c == CHARS_TO_ESCAPE[j]; 1729 } 1730 if (charToEscapeFound) 1731 { 1732 b.append('\\'); 1733 } 1734 b.append(c); 1735 } 1736 } 1737 else 1738 { 1739 b.append('"').append(value).append('"'); 1740 } 1741 1742 return b.toString(); 1743 } 1744 1745 /** 1746 * Returns the equivalent setup CLI command-line. Note that this command-line 1747 * does not cover all the replication part of the GUI install. Note also that 1748 * to avoid problems in the WebStart setup, all the Strings are hard-coded in 1749 * the implementation of this method. 1750 * 1751 * @param userData 1752 * the user data. 1753 * @return the equivalent setup command-line. 1754 */ 1755 public static List<String> getSetupEquivalentCommandLine(final UserData userData) 1756 { 1757 List<String> cmdLine = new ArrayList<>(); 1758 cmdLine.add(getInstallDir(userData) + getSetupFilename()); 1759 cmdLine.add("--cli"); 1760 1761 final ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendType = 1762 userData.getBackendType(); 1763 if (backendType != null) 1764 { 1765 cmdLine.add("--" + ArgumentConstants.OPTION_LONG_BACKEND_TYPE); 1766 cmdLine.add(BackendTypeHelper.filterSchemaBackendName(backendType.getName())); 1767 } 1768 1769 for (final String baseDN : getBaseDNs(userData)) 1770 { 1771 cmdLine.add("--baseDN"); 1772 cmdLine.add(baseDN); 1773 } 1774 1775 switch (userData.getNewSuffixOptions().getType()) 1776 { 1777 case CREATE_BASE_ENTRY: 1778 cmdLine.add("--addBaseEntry"); 1779 break; 1780 1781 case IMPORT_AUTOMATICALLY_GENERATED_DATA: 1782 cmdLine.add("--sampleData"); 1783 cmdLine.add(Integer.toString(userData.getNewSuffixOptions().getNumberEntries())); 1784 break; 1785 1786 case IMPORT_FROM_LDIF_FILE: 1787 for (final String ldifFile : userData.getNewSuffixOptions().getLDIFPaths()) 1788 { 1789 cmdLine.add("--ldifFile"); 1790 cmdLine.add(ldifFile); 1791 } 1792 1793 final String rejectFile = userData.getNewSuffixOptions().getRejectedFile(); 1794 if (rejectFile != null) 1795 { 1796 cmdLine.add("--rejectFile"); 1797 cmdLine.add(rejectFile); 1798 } 1799 1800 final String skipFile = userData.getNewSuffixOptions().getSkippedFile(); 1801 if (skipFile != null) 1802 { 1803 cmdLine.add("--skipFile"); 1804 cmdLine.add(skipFile); 1805 } 1806 break; 1807 1808 default: 1809 break; 1810 } 1811 1812 cmdLine.add("--ldapPort"); 1813 cmdLine.add(Integer.toString(userData.getServerPort())); 1814 1815 cmdLine.add("--adminConnectorPort"); 1816 cmdLine.add(Integer.toString(userData.getAdminConnectorPort())); 1817 1818 if (userData.getServerJMXPort() != -1) 1819 { 1820 cmdLine.add("--jmxPort"); 1821 cmdLine.add(Integer.toString(userData.getServerJMXPort())); 1822 } 1823 1824 cmdLine.add("--rootUserDN"); 1825 cmdLine.add(userData.getDirectoryManagerDn()); 1826 1827 cmdLine.add("--rootUserPassword"); 1828 cmdLine.add(OBFUSCATED_VALUE); 1829 1830 if (isWindows() && userData.getEnableWindowsService()) 1831 { 1832 cmdLine.add("--enableWindowsService"); 1833 } 1834 1835 if (userData.getReplicationOptions().getType() == DataReplicationOptions.Type.STANDALONE 1836 && !userData.getStartServer()) 1837 { 1838 cmdLine.add("--doNotStart"); 1839 } 1840 1841 if (userData.getSecurityOptions().getEnableStartTLS()) 1842 { 1843 cmdLine.add("--enableStartTLS"); 1844 } 1845 1846 if (userData.getSecurityOptions().getEnableSSL()) 1847 { 1848 cmdLine.add("--ldapsPort"); 1849 cmdLine.add(Integer.toString(userData.getSecurityOptions().getSslPort())); 1850 } 1851 1852 cmdLine.addAll(getSecurityOptionSetupEquivalentCmdLine(userData)); 1853 cmdLine.add("--no-prompt"); 1854 cmdLine.add("--noPropertiesFile"); 1855 1856 return cmdLine; 1857 } 1858 1859 private static String getSetupFilename() 1860 { 1861 return isWindows() ? Installation.WINDOWS_SETUP_FILE_NAME : Installation.UNIX_SETUP_FILE_NAME; 1862 } 1863 1864 private static List<String> getSecurityOptionSetupEquivalentCmdLine(final UserData userData) 1865 { 1866 final List<String> cmdLine = new ArrayList<>(); 1867 1868 switch (userData.getSecurityOptions().getCertificateType()) 1869 { 1870 case SELF_SIGNED_CERTIFICATE: 1871 cmdLine.add("--generateSelfSignedCertificate"); 1872 cmdLine.add("--hostName"); 1873 cmdLine.add(userData.getHostName()); 1874 break; 1875 1876 case JKS: 1877 cmdLine.add("--useJavaKeystore"); 1878 cmdLine.add(userData.getSecurityOptions().getKeystorePath()); 1879 if (userData.getSecurityOptions().getKeystorePassword() != null) 1880 { 1881 cmdLine.add("--keyStorePassword"); 1882 cmdLine.add(OBFUSCATED_VALUE); 1883 } 1884 1885 if (userData.getSecurityOptions().getAliasToUse() != null) 1886 { 1887 cmdLine.add("--certNickname"); 1888 cmdLine.add(userData.getSecurityOptions().getAliasToUse()); 1889 } 1890 break; 1891 1892 case JCEKS: 1893 cmdLine.add("--useJCEKS"); 1894 cmdLine.add(userData.getSecurityOptions().getKeystorePath()); 1895 1896 if (userData.getSecurityOptions().getKeystorePassword() != null) 1897 { 1898 cmdLine.add("--keyStorePassword"); 1899 cmdLine.add(OBFUSCATED_VALUE); 1900 } 1901 1902 if (userData.getSecurityOptions().getAliasToUse() != null) 1903 { 1904 cmdLine.add("--certNickname"); 1905 cmdLine.add(userData.getSecurityOptions().getAliasToUse()); 1906 } 1907 break; 1908 1909 case PKCS12: 1910 cmdLine.add("--usePkcs12keyStore"); 1911 cmdLine.add(userData.getSecurityOptions().getKeystorePath()); 1912 1913 if (userData.getSecurityOptions().getKeystorePassword() != null) 1914 { 1915 cmdLine.add("--keyStorePassword"); 1916 cmdLine.add(OBFUSCATED_VALUE); 1917 } 1918 1919 if (userData.getSecurityOptions().getAliasToUse() != null) 1920 { 1921 cmdLine.add("--certNickname"); 1922 cmdLine.add(userData.getSecurityOptions().getAliasToUse()); 1923 } 1924 break; 1925 1926 case PKCS11: 1927 cmdLine.add("--usePkcs11Keystore"); 1928 1929 if (userData.getSecurityOptions().getKeystorePassword() != null) 1930 { 1931 cmdLine.add("--keyStorePassword"); 1932 cmdLine.add(OBFUSCATED_VALUE); 1933 } 1934 1935 if (userData.getSecurityOptions().getAliasToUse() != null) 1936 { 1937 cmdLine.add("--certNickname"); 1938 cmdLine.add(userData.getSecurityOptions().getAliasToUse()); 1939 } 1940 break; 1941 1942 default: 1943 break; 1944 } 1945 1946 return cmdLine; 1947 } 1948 1949 /** 1950 * Returns the list of equivalent command-lines that must be executed to 1951 * enable or initialize replication as the setup does. 1952 * 1953 * @param subcommand 1954 * either {@code "enable"} or {@code "initialize"} 1955 * @param userData 1956 * the user data. 1957 * @return the list of equivalent command-lines that must be executed to 1958 * enable or initialize replication as the setup does. 1959 */ 1960 public static List<List<String>> getDsReplicationEquivalentCommandLines(String subcommand, UserData userData) 1961 { 1962 final List<List<String>> cmdLines = new ArrayList<>(); 1963 final Map<ServerDescriptor, Set<String>> hmServerBaseDNs = getServerDescriptorBaseDNMap(userData); 1964 for (ServerDescriptor server : hmServerBaseDNs.keySet()) 1965 { 1966 cmdLines.add(getDsReplicationEquivalentCommandLine(subcommand, userData, hmServerBaseDNs.get(server), server)); 1967 } 1968 return cmdLines; 1969 } 1970 1971 private static void addEnableCommandOptions(UserData userData, ServerDescriptor server, List<String> cmdLine) 1972 { 1973 DataReplicationOptions replOptions = userData.getReplicationOptions(); 1974 cmdLine.add("--host1"); 1975 cmdLine.add(server.getHostName()); 1976 cmdLine.add("--port1"); 1977 cmdLine.add(String.valueOf(server.getEnabledAdministrationPorts().get(0))); 1978 1979 AuthenticationData authData = userData.getReplicationOptions().getAuthenticationData(); 1980 if (!Utils.areDnsEqual(authData.getDn(), ADSContext.getAdministratorDN(userData.getGlobalAdministratorUID()))) 1981 { 1982 cmdLine.add("--bindDN1"); 1983 cmdLine.add(authData.getDn()); 1984 cmdLine.add("--bindPassword1"); 1985 cmdLine.add(OBFUSCATED_VALUE); 1986 } 1987 for (ServerDescriptor s : userData.getRemoteWithNoReplicationPort().keySet()) 1988 { 1989 if (s.getAdminConnectorURL().equals(server.getAdminConnectorURL())) 1990 { 1991 AuthenticationData remoteRepl = userData.getRemoteWithNoReplicationPort().get(server); 1992 int remoteReplicationPort = remoteRepl.getPort(); 1993 1994 cmdLine.add("--replicationPort1"); 1995 cmdLine.add(String.valueOf(remoteReplicationPort)); 1996 if (remoteRepl.useSecureConnection()) 1997 { 1998 cmdLine.add("--secureReplication1"); 1999 } 2000 } 2001 } 2002 cmdLine.add("--host2"); 2003 cmdLine.add(userData.getHostName()); 2004 cmdLine.add("--port2"); 2005 cmdLine.add(String.valueOf(userData.getAdminConnectorPort())); 2006 cmdLine.add("--bindDN2"); 2007 cmdLine.add(userData.getDirectoryManagerDn()); 2008 cmdLine.add("--bindPassword2"); 2009 cmdLine.add(OBFUSCATED_VALUE); 2010 if (replOptions.getReplicationPort() != -1) 2011 { 2012 cmdLine.add("--replicationPort2"); 2013 cmdLine.add(String.valueOf(replOptions.getReplicationPort())); 2014 if (replOptions.useSecureReplication()) 2015 { 2016 cmdLine.add("--secureReplication2"); 2017 } 2018 } 2019 } 2020 2021 /** 2022 * Returns the full path of the command-line for a given script name. 2023 * 2024 * @param userData 2025 * the user data. 2026 * @param scriptBasicName 2027 * the script basic name (with no extension). 2028 * @return the full path of the command-line for a given script name. 2029 */ 2030 private static String getCommandLinePath(UserData userData, String scriptBasicName) 2031 { 2032 String cmdLineName; 2033 if (isWindows()) 2034 { 2035 cmdLineName = 2036 getInstallDir(userData) + Installation.WINDOWS_BINARIES_PATH_RELATIVE + File.separatorChar + scriptBasicName 2037 + ".bat"; 2038 } 2039 else 2040 { 2041 cmdLineName = 2042 getInstallDir(userData) + Installation.UNIX_BINARIES_PATH_RELATIVE + File.separatorChar + scriptBasicName; 2043 } 2044 return cmdLineName; 2045 } 2046 2047 private static String installDir; 2048 2049 /** 2050 * Returns the installation directory. 2051 * 2052 * @return the installation directory. 2053 */ 2054 private static String getInstallDir(UserData userData) 2055 { 2056 if (isWebStart() || installDir == null) 2057 { 2058 File f; 2059 if (isWebStart()) 2060 { 2061 f = new File(userData.getServerLocation()); 2062 } 2063 else 2064 { 2065 f = org.opends.quicksetup.Installation.getLocal().getRootDirectory(); 2066 } 2067 try 2068 { 2069 installDir = f.getCanonicalPath(); 2070 } 2071 catch (Throwable t) 2072 { 2073 installDir = f.getAbsolutePath(); 2074 } 2075 if (installDir.lastIndexOf(File.separatorChar) != installDir.length() - 1) 2076 { 2077 installDir += File.separatorChar; 2078 } 2079 } 2080 2081 return installDir; 2082 } 2083 2084 private static List<String> getDsReplicationEquivalentCommandLine(String subcommand, UserData userData, 2085 Set<String> baseDNs, ServerDescriptor server) 2086 { 2087 List<String> cmdLine = new ArrayList<>(); 2088 String cmdName = getCommandLinePath(userData, "dsreplication"); 2089 cmdLine.add(cmdName); 2090 cmdLine.add(subcommand); 2091 2092 if ("enable".equals(subcommand)) 2093 { 2094 addEnableCommandOptions(userData, server, cmdLine); 2095 } 2096 else if ("initialize".equals(subcommand)) 2097 { 2098 addInitializeCommandOptions(userData, server, cmdLine); 2099 } 2100 else 2101 { 2102 throw new IllegalArgumentException("Code is not implemented for subcommand " + subcommand); 2103 } 2104 2105 addCommonOptions(userData, baseDNs, cmdLine); 2106 return cmdLine; 2107 } 2108 2109 private static void addInitializeCommandOptions(UserData userData, ServerDescriptor server, List<String> cmdLine) 2110 { 2111 cmdLine.add("--hostSource"); 2112 cmdLine.add(server.getHostName()); 2113 cmdLine.add("--portSource"); 2114 cmdLine.add(String.valueOf(server.getEnabledAdministrationPorts().get(0))); 2115 2116 cmdLine.add("--hostDestination"); 2117 cmdLine.add(userData.getHostName()); 2118 cmdLine.add("--portDestination"); 2119 cmdLine.add(String.valueOf(userData.getAdminConnectorPort())); 2120 } 2121 2122 private static void addCommonOptions(UserData userData, Set<String> baseDNs, List<String> cmdLine) 2123 { 2124 for (String baseDN : baseDNs) 2125 { 2126 cmdLine.add("--baseDN"); 2127 cmdLine.add(baseDN); 2128 } 2129 2130 cmdLine.add("--adminUID"); 2131 cmdLine.add(userData.getGlobalAdministratorUID()); 2132 cmdLine.add("--adminPassword"); 2133 cmdLine.add(OBFUSCATED_VALUE); 2134 2135 cmdLine.add("--trustAll"); 2136 cmdLine.add("--no-prompt"); 2137 cmdLine.add("--noPropertiesFile"); 2138 } 2139 2140 private static List<String> getBaseDNs(UserData userData) 2141 { 2142 List<String> baseDNs = new ArrayList<>(); 2143 2144 DataReplicationOptions repl = userData.getReplicationOptions(); 2145 SuffixesToReplicateOptions suf = userData.getSuffixesToReplicateOptions(); 2146 2147 boolean createSuffix = 2148 repl.getType() == DataReplicationOptions.Type.FIRST_IN_TOPOLOGY 2149 || repl.getType() == DataReplicationOptions.Type.STANDALONE 2150 || suf.getType() == SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY; 2151 2152 if (createSuffix) 2153 { 2154 NewSuffixOptions options = userData.getNewSuffixOptions(); 2155 baseDNs.addAll(options.getBaseDns()); 2156 } 2157 else 2158 { 2159 Set<SuffixDescriptor> suffixes = suf.getSuffixes(); 2160 for (SuffixDescriptor suffix : suffixes) 2161 { 2162 baseDNs.add(suffix.getDN()); 2163 } 2164 } 2165 return baseDNs; 2166 } 2167 2168 private static Map<ServerDescriptor, Set<String>> getServerDescriptorBaseDNMap(UserData userData) 2169 { 2170 Map<ServerDescriptor, Set<String>> hm = new HashMap<>(); 2171 2172 Set<SuffixDescriptor> suffixes = userData.getSuffixesToReplicateOptions().getSuffixes(); 2173 AuthenticationData authData = userData.getReplicationOptions().getAuthenticationData(); 2174 String ldapURL = 2175 ConnectionUtils.getLDAPUrl(authData.getHostName(), authData.getPort(), authData.useSecureConnection()); 2176 for (SuffixDescriptor suffix : suffixes) 2177 { 2178 boolean found = false; 2179 for (ReplicaDescriptor replica : suffix.getReplicas()) 2180 { 2181 if (ldapURL.equalsIgnoreCase(replica.getServer().getAdminConnectorURL())) 2182 { 2183 // This is the server we're configuring 2184 found = true; 2185 Set<String> baseDNs = hm.get(replica.getServer()); 2186 if (baseDNs == null) 2187 { 2188 baseDNs = new LinkedHashSet<>(); 2189 hm.put(replica.getServer(), baseDNs); 2190 } 2191 baseDNs.add(suffix.getDN()); 2192 break; 2193 } 2194 } 2195 if (!found) 2196 { 2197 for (ReplicaDescriptor replica : suffix.getReplicas()) 2198 { 2199 if (hm.keySet().contains(replica.getServer())) 2200 { 2201 hm.get(replica.getServer()).add(suffix.getDN()); 2202 found = true; 2203 break; 2204 } 2205 } 2206 } 2207 if (!found) 2208 { 2209 // We haven't found the server yet, just take the first one 2210 ReplicaDescriptor replica = suffix.getReplicas().iterator().next(); 2211 if (replica != null) 2212 { 2213 Set<String> baseDNs = new LinkedHashSet<>(); 2214 hm.put(replica.getServer(), baseDNs); 2215 baseDNs.add(suffix.getDN()); 2216 } 2217 } 2218 } 2219 return hm; 2220 } 2221 2222 /** 2223 * Returns the equivalent dsconfig command-line required to configure the 2224 * first replicated server in the topology. 2225 * 2226 * @param userData 2227 * the user data. 2228 * @return the equivalent dsconfig command-line required to configure the 2229 * first replicated server in the topology. 2230 */ 2231 public static List<List<String>> getDsConfigReplicationEnableEquivalentCommandLines(UserData userData) 2232 { 2233 final List<List<String>> cmdLines = new ArrayList<>(); 2234 final String cmdName = getCommandLinePath(userData, "dsconfig"); 2235 2236 List<String> connectionArgs = new ArrayList<>(); 2237 connectionArgs.add("--hostName"); 2238 connectionArgs.add(userData.getHostName()); 2239 connectionArgs.add("--port"); 2240 connectionArgs.add(String.valueOf(userData.getAdminConnectorPort())); 2241 connectionArgs.add("--bindDN"); 2242 connectionArgs.add(userData.getDirectoryManagerDn()); 2243 connectionArgs.add("--bindPassword"); 2244 connectionArgs.add(OBFUSCATED_VALUE); 2245 connectionArgs.add("--trustAll"); 2246 connectionArgs.add("--no-prompt"); 2247 connectionArgs.add("--noPropertiesFile"); 2248 2249 List<String> cmdReplicationServer = new ArrayList<>(); 2250 cmdReplicationServer.add(cmdName); 2251 cmdReplicationServer.add("create-replication-server"); 2252 cmdReplicationServer.add("--provider-name"); 2253 cmdReplicationServer.add("Multimaster Synchronization"); 2254 cmdReplicationServer.add("--set"); 2255 cmdReplicationServer.add("replication-port:" + userData.getReplicationOptions().getReplicationPort()); 2256 cmdReplicationServer.add("--set"); 2257 cmdReplicationServer.add("replication-server-id:1"); 2258 cmdReplicationServer.add("--type"); 2259 cmdReplicationServer.add("generic"); 2260 cmdReplicationServer.addAll(connectionArgs); 2261 2262 cmdLines.add(cmdReplicationServer); 2263 return cmdLines; 2264 } 2265} 2266 2267/** 2268 * This class is used to avoid displaying the error message related to display 2269 * problems that we might have when trying to display the SplashWindow. 2270 */ 2271class EmptyPrintStream extends PrintStream 2272{ 2273 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 2274 2275 /** Default constructor. */ 2276 public EmptyPrintStream() 2277 { 2278 super(new ByteArrayOutputStream(), true); 2279 } 2280 2281 @Override 2282 public void println(String msg) 2283 { 2284 logger.info(LocalizableMessage.raw("EmptyStream msg: " + msg)); 2285 } 2286}