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 2006-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2011-2016 ForgeRock AS. 016 */ 017package org.opends.quicksetup.installer; 018 019import static com.forgerock.opendj.cli.ArgumentConstants.*; 020import static com.forgerock.opendj.cli.Utils.*; 021import static com.forgerock.opendj.util.OperatingSystem.*; 022 023import static org.forgerock.util.Utils.*; 024import static org.opends.admin.ads.ServerDescriptor.*; 025import static org.opends.admin.ads.ServerDescriptor.ServerProperty.*; 026import static org.opends.admin.ads.util.ConnectionUtils.*; 027import static org.opends.admin.ads.util.PreferredConnection.Type.*; 028import static org.opends.messages.QuickSetupMessages.*; 029import static org.opends.quicksetup.Step.*; 030import static org.opends.quicksetup.installer.DataReplicationOptions.Type.*; 031import static org.opends.quicksetup.installer.InstallProgressStep.*; 032import static org.opends.quicksetup.util.Utils.*; 033 034import java.awt.event.WindowEvent; 035import java.io.BufferedWriter; 036import java.io.File; 037import java.io.FileWriter; 038import java.io.IOException; 039import java.io.PrintStream; 040import java.net.URI; 041import java.security.KeyStoreException; 042import java.util.ArrayList; 043import java.util.Collection; 044import java.util.Collections; 045import java.util.HashMap; 046import java.util.HashSet; 047import java.util.LinkedHashSet; 048import java.util.LinkedList; 049import java.util.List; 050import java.util.Map; 051import java.util.Set; 052 053import javax.naming.NameAlreadyBoundException; 054import javax.naming.NameNotFoundException; 055import javax.naming.NamingEnumeration; 056import javax.naming.NamingException; 057import javax.naming.NamingSecurityException; 058import javax.naming.directory.Attribute; 059import javax.naming.directory.BasicAttribute; 060import javax.naming.directory.BasicAttributes; 061import javax.naming.directory.DirContext; 062import javax.naming.directory.SearchControls; 063import javax.naming.directory.SearchResult; 064import javax.naming.ldap.InitialLdapContext; 065import javax.naming.ldap.Rdn; 066import javax.swing.JPanel; 067 068import org.forgerock.i18n.LocalizableMessage; 069import org.forgerock.i18n.LocalizableMessageBuilder; 070import org.forgerock.i18n.LocalizableMessageDescriptor.Arg0; 071import org.forgerock.i18n.slf4j.LocalizedLogger; 072import org.forgerock.opendj.config.ManagedObjectDefinition; 073import org.forgerock.opendj.server.config.client.BackendCfgClient; 074import org.forgerock.opendj.server.config.server.BackendCfg; 075import org.opends.admin.ads.ADSContext; 076import org.opends.admin.ads.ADSContextException; 077import org.opends.admin.ads.ReplicaDescriptor; 078import org.opends.admin.ads.ServerDescriptor; 079import org.opends.admin.ads.SuffixDescriptor; 080import org.opends.admin.ads.TopologyCache; 081import org.opends.admin.ads.TopologyCacheException; 082import org.opends.admin.ads.TopologyCacheFilter; 083import org.opends.admin.ads.util.ApplicationTrustManager; 084import org.opends.admin.ads.util.ConnectionWrapper; 085import org.opends.admin.ads.util.PreferredConnection; 086import org.opends.quicksetup.ApplicationException; 087import org.opends.quicksetup.ButtonName; 088import org.opends.quicksetup.Constants; 089import org.opends.quicksetup.Installation; 090import org.opends.quicksetup.JavaArguments; 091import org.opends.quicksetup.LicenseFile; 092import org.opends.quicksetup.ProgressStep; 093import org.opends.quicksetup.ReturnCode; 094import org.opends.quicksetup.SecurityOptions; 095import org.opends.quicksetup.Step; 096import org.opends.quicksetup.UserData; 097import org.opends.quicksetup.UserDataCertificateException; 098import org.opends.quicksetup.UserDataConfirmationException; 099import org.opends.quicksetup.UserDataException; 100import org.opends.quicksetup.WizardStep; 101import org.opends.quicksetup.event.ButtonActionListener; 102import org.opends.quicksetup.event.ButtonEvent; 103import org.opends.quicksetup.installer.ui.DataOptionsPanel; 104import org.opends.quicksetup.installer.ui.DataReplicationPanel; 105import org.opends.quicksetup.installer.ui.GlobalAdministratorPanel; 106import org.opends.quicksetup.installer.ui.InstallLicensePanel; 107import org.opends.quicksetup.installer.ui.InstallReviewPanel; 108import org.opends.quicksetup.installer.ui.InstallWelcomePanel; 109import org.opends.quicksetup.installer.ui.RemoteReplicationPortsPanel; 110import org.opends.quicksetup.installer.ui.RuntimeOptionsPanel; 111import org.opends.quicksetup.installer.ui.ServerSettingsPanel; 112import org.opends.quicksetup.installer.ui.SuffixesToReplicatePanel; 113import org.opends.quicksetup.ui.FieldName; 114import org.opends.quicksetup.ui.FinishedPanel; 115import org.opends.quicksetup.ui.GuiApplication; 116import org.opends.quicksetup.ui.ProgressPanel; 117import org.opends.quicksetup.ui.QuickSetup; 118import org.opends.quicksetup.ui.QuickSetupDialog; 119import org.opends.quicksetup.ui.QuickSetupErrorPanel; 120import org.opends.quicksetup.ui.QuickSetupStepPanel; 121import org.opends.quicksetup.ui.UIFactory; 122import org.opends.quicksetup.util.FileManager; 123import org.opends.quicksetup.util.IncompatibleVersionException; 124import org.opends.quicksetup.util.ServerController; 125import org.opends.quicksetup.util.Utils; 126import org.opends.server.tools.BackendTypeHelper; 127import org.opends.server.tools.BackendTypeHelper.BackendTypeUIAdapter; 128import org.opends.server.types.HostPort; 129import org.opends.server.util.CertificateManager; 130import org.opends.server.util.CollectionUtils; 131import org.opends.server.util.DynamicConstants; 132import org.opends.server.util.Platform.KeyType; 133import org.opends.server.util.SetupUtils; 134import org.opends.server.util.StaticUtils; 135 136import com.forgerock.opendj.util.OperatingSystem; 137 138/** 139 * This is an abstract class that is in charge of actually performing the 140 * installation. 141 * 142 * It just takes a UserData object and based on that installs OpenDJ. 143 * 144 * When there is an update during the installation it will notify the 145 * ProgressUpdateListener objects that have been added to it. The 146 * notification will send a ProgressUpdateEvent. 147 * 148 * This class is supposed to be fully independent of the graphical layout. 149 * 150 * Note that we can use freely the class org.opends.server.util.SetupUtils as 151 * it is included in quicksetup.jar. 152 */ 153public class Installer extends GuiApplication 154{ 155 /** The minimum integer value that can be used for a port. */ 156 public static final int MIN_PORT_VALUE = 1; 157 /** The maximum integer value that can be used for a port. */ 158 public static final int MAX_PORT_VALUE = 65535; 159 160 /** The name of the backend created on setup. */ 161 public static final String ROOT_BACKEND_NAME = "userRoot"; 162 163 /** Constants used to do checks. */ 164 private static final int MIN_DIRECTORY_MANAGER_PWD = 1; 165 166 private static final int MIN_NUMBER_ENTRIES = 1; 167 private static final int MAX_NUMBER_ENTRIES = 10000000; 168 169 /** 170 * If the user decides to import more than this number of entries, the import 171 * process of automatically generated data will be verbose. 172 */ 173 private static final int THRESHOLD_AUTOMATIC_DATA_VERBOSE = 20000; 174 175 /** 176 * If the user decides to import a number of entries higher than this 177 * threshold, the start process will be verbose. 178 */ 179 private static final int THRESHOLD_VERBOSE_START = 100000; 180 181 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 182 183 private TopologyCache lastLoadedCache; 184 185 /** Indicates that we've detected that there is something installed. */ 186 private boolean forceToDisplaySetup; 187 188 /** When true indicates that the user has canceled this operation. */ 189 private boolean canceled; 190 private boolean javaVersionCheckFailed; 191 192 /** Map containing information about what has been configured remotely. */ 193 private final Map<ServerDescriptor, ConfiguredReplication> hmConfiguredRemoteReplication = new HashMap<>(); 194 195 /** Set of progress steps that have been completed. */ 196 private final Set<InstallProgressStep> completedProgress = new HashSet<>(); 197 private final List<WizardStep> listSteps = new ArrayList<>(); 198 private final Set<WizardStep> SUBSTEPS = CollectionUtils.<WizardStep> newHashSet( 199 Step.CREATE_GLOBAL_ADMINISTRATOR, 200 Step.SUFFIXES_OPTIONS, 201 Step.NEW_SUFFIX_OPTIONS, 202 Step.REMOTE_REPLICATION_PORTS); 203 204 private final Map<WizardStep, WizardStep> hmPreviousSteps = new HashMap<>(); 205 206 private char[] selfSignedCertPw; 207 208 private boolean registeredNewServerOnRemote; 209 private boolean createdAdministrator; 210 private boolean createdRemoteAds; 211 private String lastImportProgress; 212 213 /** Aliases of self-signed certificates. */ 214 private static final String[] SELF_SIGNED_CERT_ALIASES = { 215 SecurityOptions.SELF_SIGNED_CERT_ALIAS, 216 SecurityOptions.SELF_SIGNED_EC_CERT_ALIAS 217 }; 218 219 /** 220 * The threshold in minutes used to know whether we must display a warning 221 * informing that there is a server clock difference between two servers whose 222 * contents are being replicated. 223 */ 224 public static final int THRESHOLD_CLOCK_DIFFERENCE_WARNING = 5; 225 226 /** This map contains the ratio associated with each step. */ 227 private final Map<ProgressStep, Integer> hmRatio = new HashMap<>(); 228 /** This map contains the summary associated with each step. */ 229 private final Map<ProgressStep, LocalizableMessage> hmSummary = new HashMap<>(); 230 231 private ApplicationException applicationException; 232 233 /** Actually performs the install in this thread. The thread is blocked. */ 234 @Override 235 public void run() 236 { 237 applicationException = null; 238 PrintStream origErr = System.err; 239 PrintStream origOut = System.out; 240 try 241 { 242 initMaps(); 243 System.setErr(getApplicationErrorStream()); 244 System.setOut(getApplicationOutputStream()); 245 checkAbort(); 246 247 setCurrentProgressStep(InstallProgressStep.CONFIGURING_SERVER); 248 configureServer(); 249 checkAbort(); 250 251 LicenseFile.createFileLicenseApproved(getInstallationPath()); 252 checkAbort(); 253 254 createData(); 255 checkAbort(); 256 257 if (isWindows() && getUserData().getEnableWindowsService()) 258 { 259 showStepStarted(InstallProgressStep.ENABLING_WINDOWS_SERVICE); 260 enableWindowsService(); 261 checkAbort(); 262 } 263 264 if (mustStart()) 265 { 266 startServer(); 267 } 268 269 if (mustCreateAds()) 270 { 271 showStepStarted(InstallProgressStep.CONFIGURING_ADS); 272 updateADS(); 273 checkAbort(); 274 } 275 276 if (mustConfigureReplication()) 277 { 278 showStepStarted(InstallProgressStep.CONFIGURING_REPLICATION); 279 createReplicatedBackendsIfRequired(); 280 configureReplication(); 281 checkAbort(); 282 } 283 284 if (mustInitializeSuffixes()) 285 { 286 showStepStarted(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); 287 initializeSuffixes(); 288 checkAbort(); 289 } 290 291 if (mustStop()) 292 { 293 showStepStarted(InstallProgressStep.STOPPING_SERVER); 294 stopServer(new ServerController(this)); 295 } 296 297 checkAbort(); 298 updateSummaryWithServerState(hmSummary, true); 299 setCurrentProgressStep(InstallProgressStep.FINISHED_SUCCESSFULLY); 300 notifyListeners(null); 301 tempLogFile.deleteLogFileAfterSuccess(); 302 } 303 catch (final ApplicationException ex) 304 { 305 logger.error(LocalizableMessage.raw("Caught exception: "+ex, ex)); 306 if (ReturnCode.CANCELED.equals(ex.getType())) { 307 uninstall(); 308 setCurrentProgressStep(InstallProgressStep.FINISHED_CANCELED); 309 notifyListeners(null); 310 } else { 311 handleInstallationError(ex); 312 } 313 applicationException = ex; 314 } 315 catch (final Throwable t) 316 { 317 final ApplicationException ex = 318 new ApplicationException(ReturnCode.BUG, getThrowableMsg(INFO_BUG_MSG.get(), t), t); 319 handleInstallationError(ex); 320 applicationException = ex; 321 } 322 finally 323 { 324 System.setErr(origErr); 325 System.setOut(origOut); 326 } 327 } 328 329 private void showStepStarted(final InstallProgressStep step) 330 { 331 if (isVerbose()) 332 { 333 notifyListeners(getTaskSeparator()); 334 } 335 setCurrentProgressStep(step); 336 } 337 338 private void startServer() throws ApplicationException 339 { 340 final boolean verbose = isStartVerbose(); 341 if (verbose) 342 { 343 notifyListeners(getTaskSeparator()); 344 } 345 setCurrentProgressStep(InstallProgressStep.STARTING_SERVER); 346 final PointAdder pointAdder = new PointAdder(); 347 if (!verbose) 348 { 349 notifyListeners(getFormattedProgress(INFO_PROGRESS_STARTING_NON_VERBOSE.get())); 350 pointAdder.start(); 351 } 352 try 353 { 354 new ServerController(this).startServer(!verbose); 355 } 356 finally 357 { 358 if (!verbose) 359 { 360 pointAdder.stop(); 361 } 362 } 363 notifyListeners(verbose ? getLineBreak() : getFormattedDoneWithLineBreak()); 364 checkAbort(); 365 } 366 367 private void handleInstallationError(final ApplicationException exception) 368 { 369 stopServerIfNeeded(); 370 notifyListeners(getLineBreak()); 371 updateSummaryWithServerState(hmSummary, true); 372 setCurrentProgressStep(InstallProgressStep.FINISHED_WITH_ERROR); 373 notifyListeners(getFormattedError(exception, true)); 374 logger.error(LocalizableMessage.raw("Error installing.", exception)); 375 notifyListeners(getLineBreak()); 376 notifyListenersOfExistingLogFile(); 377 } 378 379 private void stopServerIfNeeded() 380 { 381 final Installation installation = getInstallation(); 382 if (installation.getStatus().isServerRunning()) 383 { 384 try 385 { 386 stopServer(new ServerController(installation)); 387 } 388 catch (final ApplicationException t) 389 { 390 logger.info(LocalizableMessage.raw("error stopping server", t)); 391 } 392 } 393 } 394 395 private void stopServer(final ServerController serverController) throws ApplicationException 396 { 397 if (isVerbose()) 398 { 399 serverController.stopServer(false); 400 } 401 else 402 { 403 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); 404 serverController.stopServer(true); 405 notifyListeners(getFormattedDoneWithLineBreak()); 406 } 407 } 408 409 @Override 410 public Integer getRatio(ProgressStep status) 411 { 412 return hmRatio.get(status); 413 } 414 415 @Override 416 public LocalizableMessage getSummary(ProgressStep status) 417 { 418 return hmSummary.get(status); 419 } 420 421 /** 422 * Returns the exception from the run() method, if any. 423 * @return the ApplicationException raised during the run() method, if any. 424 * null otherwise. 425 */ 426 public ApplicationException getApplicationException() 427 { 428 return applicationException; 429 } 430 431 private void uninstall() { 432 notifyListeners(getTaskSeparator()); 433 if (!isVerbose()) 434 { 435 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CANCELING.get())); 436 } 437 else 438 { 439 notifyListeners( 440 getFormattedProgressWithLineBreak(INFO_SUMMARY_CANCELING.get())); 441 } 442 Installation installation = getInstallation(); 443 FileManager fm = new FileManager(this); 444 445 stopServerIfNeeded(); 446 uninstallServices(); 447 revertToBaseConfiguration(installation, fm); 448 cleanupSSLIfNeeded(installation, fm); 449 450 // Remove the databases 451 try { 452 fm.deleteChildren(installation.getDatabasesDirectory()); 453 } catch (ApplicationException e) { 454 logger.info(LocalizableMessage.raw("Error deleting databases", e)); 455 } 456 457 if (!isVerbose()) 458 { 459 notifyListeners(getFormattedDoneWithLineBreak()); 460 } 461 } 462 463 private void revertToBaseConfiguration(final Installation installation, final FileManager fm) 464 { 465 try 466 { 467 File newConfig = fm.copy(installation.getBaseConfigurationFile(), 468 installation.getConfigurationDirectory(), true); 469 fm.rename(newConfig, installation.getCurrentConfigurationFile()); 470 } 471 catch (ApplicationException ae) 472 { 473 logger.info(LocalizableMessage.raw("failed to restore base configuration", ae)); 474 } 475 } 476 477 private void cleanupSSLIfNeeded(final Installation installation, final FileManager fm) 478 { 479 final SecurityOptions sec = getUserData().getSecurityOptions(); 480 if (sec.getEnableSSL() || sec.getEnableStartTLS()) 481 { 482 if (SecurityOptions.CertificateType.SELF_SIGNED_CERTIFICATE.equals(sec.getCertificateType())) 483 { 484 final CertificateManager cm = new CertificateManager( 485 getSelfSignedKeystorePath(), CertificateManager.KEY_STORE_TYPE_JKS, getSelfSignedCertificatePwd()); 486 try 487 { 488 for (final String alias : SELF_SIGNED_CERT_ALIASES) 489 { 490 if (cm.aliasInUse(alias)) 491 { 492 cm.removeCertificate(alias); 493 } 494 } 495 } 496 catch (KeyStoreException e) 497 { 498 logger.info(LocalizableMessage.raw("Error deleting self signed certification", e)); 499 } 500 } 501 502 final File configDir = installation.getConfigurationDirectory(); 503 removeFileIfExists(fm, configDir, "keystore"); 504 removeFileIfExists(fm, configDir, "keystore.pin"); 505 removeFileIfExists(fm, configDir, "truststore"); 506 } 507 } 508 509 private void removeFileIfExists(final FileManager fileManager, final File configDir, final String fileName) 510 { 511 final File file = new File(configDir, fileName); 512 if (file.exists()) 513 { 514 try 515 { 516 fileManager.delete(file); 517 } 518 catch (ApplicationException e) 519 { 520 logger.info(LocalizableMessage.raw("Failed to delete " + fileName, e)); 521 } 522 } 523 } 524 525 private void initMaps() 526 { 527 initSummaryMap(hmSummary, true); 528 529 final List<InstallProgressStep> steps = new ArrayList<>(); 530 steps.add(InstallProgressStep.CONFIGURING_SERVER); 531 if (createNotReplicatedSuffix()) 532 { 533 switch (getUserData().getNewSuffixOptions().getType()) 534 { 535 case CREATE_BASE_ENTRY: 536 steps.add(InstallProgressStep.CREATING_BASE_ENTRY); 537 break; 538 case IMPORT_FROM_LDIF_FILE: 539 steps.add(InstallProgressStep.IMPORTING_LDIF); 540 break; 541 case IMPORT_AUTOMATICALLY_GENERATED_DATA: 542 steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED); 543 break; 544 } 545 } 546 547 if (isWindows() && getUserData().getEnableWindowsService()) 548 { 549 steps.add(InstallProgressStep.ENABLING_WINDOWS_SERVICE); 550 } 551 552 if (mustStart()) 553 { 554 steps.add(InstallProgressStep.STARTING_SERVER); 555 } 556 557 if (mustCreateAds()) 558 { 559 steps.add(InstallProgressStep.CONFIGURING_ADS); 560 } 561 562 if (mustConfigureReplication()) 563 { 564 steps.add(InstallProgressStep.CONFIGURING_REPLICATION); 565 } 566 567 if (mustInitializeSuffixes()) 568 { 569 steps.add(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); 570 } 571 572 if (mustStop()) 573 { 574 steps.add(InstallProgressStep.STOPPING_SERVER); 575 } 576 577 int totalTime = 0; 578 for (final InstallProgressStep step : steps) { 579 totalTime += step.getRelativeDuration(); 580 } 581 582 int cumulatedTime = 0; 583 for (InstallProgressStep s : steps) 584 { 585 Integer statusTime = s.getRelativeDuration(); 586 hmRatio.put(s, (100 * cumulatedTime) / totalTime); 587 cumulatedTime += statusTime; 588 } 589 hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100); 590 hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100); 591 hmRatio.put(InstallProgressStep.FINISHED_CANCELED, 100); 592 } 593 594 @Override 595 public String getInstallationPath() 596 { 597 return Utils.getInstallPathFromClasspath(); 598 } 599 600 @Override 601 public String getInstancePath() 602 { 603 String installPath = Utils.getInstallPathFromClasspath(); 604 return Utils.getInstancePathFromInstallPath(installPath); 605 } 606 607 private void notifyListenersOfExistingLogFile() 608 { 609 if (tempLogFile.isEnabled()) 610 { 611 final String tempLogFilePath = tempLogFile.getPath(); 612 notifyListeners(getFormattedProgress(INFO_GENERAL_PROVIDE_LOG_IN_ERROR.get(tempLogFilePath))); 613 notifyListeners(getLineBreak()); 614 } 615 } 616 617 /** Creates a default instance. */ 618 public Installer() 619 { 620 addStepsInOrder(listSteps, LicenseFile.exists()); 621 } 622 623 @Override 624 public boolean isCancellable() 625 { 626 return true; 627 } 628 629 @Override 630 public UserData createUserData() 631 { 632 UserData ud = new UserData(); 633 ud.setServerLocation(getDefaultServerLocation()); 634 initializeUserDataWithUserArguments(ud, getUserArguments()); 635 return ud; 636 } 637 638 private void initializeUserDataWithUserArguments(UserData ud, String[] userArguments) 639 { 640 for (int i = 0; i < userArguments.length; i++) 641 { 642 if ("--connectTimeout".equalsIgnoreCase(userArguments[i])) 643 { 644 if (i < userArguments.length - 1) 645 { 646 String sTimeout = userArguments[i + 1]; 647 try 648 { 649 ud.setConnectTimeout(Integer.valueOf(sTimeout)); 650 } 651 catch (Throwable t) 652 { 653 logger.warn(LocalizableMessage.raw("Error getting connect timeout: " + t, t)); 654 } 655 } 656 break; 657 } 658 } 659 } 660 661 @Override 662 public void forceToDisplay() 663 { 664 forceToDisplaySetup = true; 665 } 666 667 @Override 668 public boolean canGoBack(WizardStep step) 669 { 670 return step != WELCOME && step != PROGRESS && step != FINISHED; 671 } 672 673 @Override 674 public boolean canGoForward(WizardStep step) 675 { 676 return step != REVIEW && step != PROGRESS && step != FINISHED; 677 } 678 679 @Override 680 public boolean canFinish(WizardStep step) 681 { 682 return step == REVIEW; 683 } 684 685 @Override 686 public boolean isSubStep(WizardStep step) 687 { 688 return SUBSTEPS.contains(step); 689 } 690 691 @Override 692 public boolean isVisible(WizardStep step, UserData userData) 693 { 694 if (step == CREATE_GLOBAL_ADMINISTRATOR) 695 { 696 return userData.mustCreateAdministrator(); 697 } 698 else if (step == NEW_SUFFIX_OPTIONS) 699 { 700 SuffixesToReplicateOptions suf = userData.getSuffixesToReplicateOptions(); 701 return suf != null && suf.getType() != SuffixesToReplicateOptions.Type.REPLICATE_WITH_EXISTING_SUFFIXES; 702 } 703 else if (step == SUFFIXES_OPTIONS) 704 { 705 DataReplicationOptions repl = userData.getReplicationOptions(); 706 return repl != null && repl.getType() != DataReplicationOptions.Type.STANDALONE 707 && repl.getType() != DataReplicationOptions.Type.FIRST_IN_TOPOLOGY; 708 } 709 else if (step == REMOTE_REPLICATION_PORTS) 710 { 711 return isVisible(SUFFIXES_OPTIONS, userData) 712 && !userData.getRemoteWithNoReplicationPort().isEmpty() 713 && userData.getSuffixesToReplicateOptions().getType() == 714 SuffixesToReplicateOptions.Type.REPLICATE_WITH_EXISTING_SUFFIXES; 715 } 716 return true; 717 } 718 719 @Override 720 public boolean isVisible(WizardStep step, QuickSetup qs) 721 { 722 return isVisible(step, getUserData()); 723 } 724 725 @Override 726 public boolean finishClicked(final WizardStep cStep, final QuickSetup qs) 727 { 728 if (cStep != Step.REVIEW) 729 { 730 throw new IllegalStateException("Cannot click on finish when we are not in the Review window"); 731 } 732 733 updateUserDataForReviewPanel(qs); 734 qs.launch(); 735 qs.setCurrentStep(Step.PROGRESS); 736 // Installer responsible for updating the user data and launching 737 return false; 738 } 739 740 @Override 741 public void nextClicked(WizardStep cStep, QuickSetup qs) 742 { 743 if (cStep == PROGRESS) 744 { 745 throw new IllegalStateException("Cannot click on next from progress step"); 746 } 747 else if (cStep == REVIEW) 748 { 749 throw new IllegalStateException("Cannot click on next from review step"); 750 } 751 else if (cStep == FINISHED) 752 { 753 throw new IllegalStateException("Cannot click on next from finished step"); 754 } 755 } 756 757 @Override 758 public void closeClicked(WizardStep cStep, QuickSetup qs) 759 { 760 if (cStep == PROGRESS) 761 { 762 if (isFinished() 763 || qs.displayConfirmation(INFO_CONFIRM_CLOSE_INSTALL_MSG.get(), INFO_CONFIRM_CLOSE_INSTALL_TITLE.get())) 764 { 765 qs.quit(); 766 } 767 } 768 else if (cStep == FINISHED) 769 { 770 qs.quit(); 771 } 772 else 773 { 774 throw new IllegalStateException("Close only can be clicked on PROGRESS step"); 775 } 776 } 777 778 @Override 779 public boolean isFinished() 780 { 781 return getCurrentProgressStep() == InstallProgressStep.FINISHED_SUCCESSFULLY 782 || getCurrentProgressStep() == InstallProgressStep.FINISHED_CANCELED 783 || getCurrentProgressStep() == InstallProgressStep.FINISHED_WITH_ERROR; 784 } 785 786 @Override 787 public void cancel() 788 { 789 setCurrentProgressStep(InstallProgressStep.WAITING_TO_CANCEL); 790 notifyListeners(null); 791 this.canceled = true; 792 } 793 794 @Override 795 public void quitClicked(WizardStep cStep, QuickSetup qs) 796 { 797 if (cStep == FINISHED) 798 { 799 qs.quit(); 800 } 801 else if (cStep == PROGRESS) 802 { 803 throw new IllegalStateException("Cannot click on quit from progress step"); 804 } 805 else if (installStatus.isInstalled()) 806 { 807 qs.quit(); 808 } 809 else if (javaVersionCheckFailed) 810 { 811 qs.quit(); 812 } 813 else if (qs.displayConfirmation(INFO_CONFIRM_QUIT_INSTALL_MSG.get(), INFO_CONFIRM_QUIT_INSTALL_TITLE.get())) 814 { 815 qs.quit(); 816 } 817 } 818 819 @Override 820 public ButtonName getInitialFocusButtonName() 821 { 822 if (!installStatus.isInstalled() || forceToDisplaySetup) 823 { 824 return ButtonName.NEXT; 825 } 826 else if (installStatus.canOverwriteCurrentInstall()) 827 { 828 return ButtonName.CONTINUE_INSTALL; 829 } 830 else 831 { 832 return ButtonName.QUIT; 833 } 834 } 835 836 @Override 837 public JPanel createFramePanel(QuickSetupDialog dlg) 838 { 839 JPanel p; 840 javaVersionCheckFailed = true; 841 try 842 { 843 Utils.checkJavaVersion(); 844 javaVersionCheckFailed = false; 845 if (installStatus.isInstalled() && !forceToDisplaySetup) 846 { 847 p = dlg.getInstalledPanel(); 848 } 849 else 850 { 851 p = super.createFramePanel(dlg); 852 } 853 } 854 catch (IncompatibleVersionException ijv) 855 { 856 LocalizableMessageBuilder sb = new LocalizableMessageBuilder(); 857 sb.append(Utils.breakHtmlString(Utils.getHtml(ijv.getMessageObject().toString()), 858 Constants.MAX_CHARS_PER_LINE_IN_DIALOG)); 859 QuickSetupErrorPanel errPanel = new QuickSetupErrorPanel(this, sb.toMessage()); 860 final QuickSetupDialog fDlg = dlg; 861 errPanel.addButtonActionListener(new ButtonActionListener() 862 { 863 @Override 864 public void buttonActionPerformed(ButtonEvent ev) 865 { 866 // assumes that we are called in the event thread. 867 // Simulate a close button event 868 fDlg.notifyButtonEvent(ButtonName.QUIT); 869 } 870 }); 871 p = errPanel; 872 } 873 return p; 874 } 875 876 @Override 877 public Set<? extends WizardStep> getWizardSteps() 878 { 879 return Collections.unmodifiableSet(new HashSet<WizardStep>(listSteps)); 880 } 881 882 @Override 883 public QuickSetupStepPanel createWizardStepPanel(WizardStep step) 884 { 885 if (step instanceof Step) 886 { 887 switch ((Step) step) 888 { 889 case WELCOME: 890 return new InstallWelcomePanel(this); 891 case LICENSE: 892 return new InstallLicensePanel(this); 893 case SERVER_SETTINGS: 894 return new ServerSettingsPanel(this); 895 case REPLICATION_OPTIONS: 896 return new DataReplicationPanel(this); 897 case CREATE_GLOBAL_ADMINISTRATOR: 898 return new GlobalAdministratorPanel(this); 899 case SUFFIXES_OPTIONS: 900 return new SuffixesToReplicatePanel(this); 901 case REMOTE_REPLICATION_PORTS: 902 return new RemoteReplicationPortsPanel(this); 903 case NEW_SUFFIX_OPTIONS: 904 return new DataOptionsPanel(this); 905 case RUNTIME_OPTIONS: 906 return new RuntimeOptionsPanel(this); 907 case REVIEW: 908 return new InstallReviewPanel(this); 909 case PROGRESS: 910 return new ProgressPanel(this); 911 case FINISHED: 912 return new FinishedPanel(this); 913 } 914 } 915 return null; 916 } 917 918 @Override 919 public void windowClosing(QuickSetupDialog dlg, WindowEvent evt) 920 { 921 if (installStatus.isInstalled() && forceToDisplaySetup) 922 { 923 // Simulate a close button event 924 dlg.notifyButtonEvent(ButtonName.QUIT); 925 } 926 else if (dlg.getDisplayedStep() == Step.PROGRESS) 927 { 928 // Simulate a close button event 929 dlg.notifyButtonEvent(ButtonName.CLOSE); 930 } 931 else 932 { 933 // Simulate a quit button event 934 dlg.notifyButtonEvent(ButtonName.QUIT); 935 } 936 } 937 938 @Override 939 public LocalizableMessage getCloseButtonToolTip() 940 { 941 return INFO_CLOSE_BUTTON_INSTALL_TOOLTIP.get(); 942 } 943 944 @Override 945 public LocalizableMessage getQuitButtonToolTip() 946 { 947 return INFO_QUIT_BUTTON_INSTALL_TOOLTIP.get(); 948 } 949 950 @Override 951 public LocalizableMessage getFinishButtonToolTip() 952 { 953 return INFO_FINISH_BUTTON_INSTALL_TOOLTIP.get(); 954 } 955 956 @Override 957 public int getExtraDialogHeight() 958 { 959 return UIFactory.EXTRA_DIALOG_HEIGHT; 960 } 961 962 @Override 963 public void previousClicked(WizardStep cStep, QuickSetup qs) 964 { 965 if (cStep == WELCOME) 966 { 967 throw new IllegalStateException("Cannot click on previous from progress step"); 968 } 969 else if (cStep == PROGRESS) 970 { 971 throw new IllegalStateException("Cannot click on previous from progress step"); 972 } 973 else if (cStep == FINISHED) 974 { 975 throw new IllegalStateException("Cannot click on previous from finished step"); 976 } 977 } 978 979 @Override 980 public LocalizableMessage getFrameTitle() 981 { 982 return Utils.getCustomizedObject("INFO_FRAME_INSTALL_TITLE", INFO_FRAME_INSTALL_TITLE 983 .get(DynamicConstants.PRODUCT_NAME), LocalizableMessage.class); 984 } 985 986 /** Indicates the current progress step. */ 987 private InstallProgressStep currentProgressStep = InstallProgressStep.NOT_STARTED; 988 989 @Override 990 public void setWizardDialogState(QuickSetupDialog dlg, UserData userData, WizardStep step) 991 { 992 if (!installStatus.isInstalled() || forceToDisplaySetup) 993 { 994 // Set the default button for the frame 995 if (step == REVIEW) 996 { 997 dlg.setFocusOnButton(ButtonName.FINISH); 998 dlg.setDefaultButton(ButtonName.FINISH); 999 } 1000 else if (step == WELCOME) 1001 { 1002 dlg.setDefaultButton(ButtonName.NEXT); 1003 dlg.setFocusOnButton(ButtonName.NEXT); 1004 } 1005 else if (step == PROGRESS || step == FINISHED) 1006 { 1007 dlg.setDefaultButton(ButtonName.CLOSE); 1008 dlg.setFocusOnButton(ButtonName.CLOSE); 1009 } 1010 else 1011 { 1012 dlg.setDefaultButton(ButtonName.NEXT); 1013 } 1014 } 1015 } 1016 1017 @Override 1018 public ProgressStep getCurrentProgressStep() 1019 { 1020 return currentProgressStep; 1021 } 1022 1023 @Override 1024 public WizardStep getFirstWizardStep() 1025 { 1026 return WELCOME; 1027 } 1028 1029 @Override 1030 public WizardStep getNextWizardStep(WizardStep step) 1031 { 1032 WizardStep next = getNextWizardStep0(step); 1033 if (next != null) 1034 { 1035 hmPreviousSteps.put(next, step); 1036 } 1037 return next; 1038 } 1039 1040 private WizardStep getNextWizardStep0(WizardStep step) 1041 { 1042 if (step == Step.REPLICATION_OPTIONS) 1043 { 1044 if (getUserData().mustCreateAdministrator()) 1045 { 1046 return Step.CREATE_GLOBAL_ADMINISTRATOR; 1047 } 1048 1049 switch (getUserData().getReplicationOptions().getType()) 1050 { 1051 case FIRST_IN_TOPOLOGY: 1052 case STANDALONE: 1053 return Step.NEW_SUFFIX_OPTIONS; 1054 default: 1055 return Step.SUFFIXES_OPTIONS; 1056 } 1057 } 1058 else if (step == Step.SUFFIXES_OPTIONS) 1059 { 1060 switch (getUserData().getSuffixesToReplicateOptions().getType()) 1061 { 1062 case REPLICATE_WITH_EXISTING_SUFFIXES: 1063 if (!getUserData().getRemoteWithNoReplicationPort().isEmpty()) 1064 { 1065 return Step.REMOTE_REPLICATION_PORTS; 1066 } 1067 return Step.RUNTIME_OPTIONS; 1068 default: 1069 return Step.NEW_SUFFIX_OPTIONS; 1070 } 1071 } 1072 else if (step == Step.REMOTE_REPLICATION_PORTS) 1073 { 1074 return Step.RUNTIME_OPTIONS; 1075 } 1076 else 1077 { 1078 int i = listSteps.indexOf(step); 1079 if (i != -1 && i + 1 < listSteps.size()) 1080 { 1081 return listSteps.get(i + 1); 1082 } 1083 } 1084 return null; 1085 } 1086 1087 @Override 1088 public LinkedHashSet<WizardStep> getOrderedSteps() 1089 { 1090 LinkedHashSet<WizardStep> orderedSteps = new LinkedHashSet<>(); 1091 addStepsInOrder(orderedSteps, listSteps.contains(LICENSE)); 1092 return orderedSteps; 1093 } 1094 1095 private void addStepsInOrder(Collection<WizardStep> steps, boolean licenseExists) 1096 { 1097 steps.add(WELCOME); 1098 if (licenseExists) 1099 { 1100 steps.add(LICENSE); 1101 } 1102 steps.add(SERVER_SETTINGS); 1103 steps.add(REPLICATION_OPTIONS); 1104 steps.add(CREATE_GLOBAL_ADMINISTRATOR); 1105 steps.add(SUFFIXES_OPTIONS); 1106 steps.add(REMOTE_REPLICATION_PORTS); 1107 steps.add(NEW_SUFFIX_OPTIONS); 1108 steps.add(RUNTIME_OPTIONS); 1109 steps.add(REVIEW); 1110 steps.add(PROGRESS); 1111 steps.add(FINISHED); 1112 } 1113 1114 @Override 1115 public WizardStep getPreviousWizardStep(WizardStep step) 1116 { 1117 // Try with the steps calculated in method getNextWizardStep. 1118 WizardStep prev = hmPreviousSteps.get(step); 1119 1120 if (prev == null) 1121 { 1122 int i = listSteps.indexOf(step); 1123 if (i != -1 && i > 0) 1124 { 1125 prev = listSteps.get(i - 1); 1126 } 1127 } 1128 return prev; 1129 } 1130 1131 @Override 1132 public WizardStep getFinishedStep() 1133 { 1134 return Step.FINISHED; 1135 } 1136 1137 /** 1138 * Uninstalls installed services. This is to be used when the user has elected 1139 * to cancel an installation. 1140 */ 1141 private void uninstallServices() 1142 { 1143 if (completedProgress.contains(InstallProgressStep.ENABLING_WINDOWS_SERVICE)) 1144 { 1145 try 1146 { 1147 new InstallerHelper().disableWindowsService(); 1148 } 1149 catch (ApplicationException ae) 1150 { 1151 logger.info(LocalizableMessage.raw("Error disabling Windows service", ae)); 1152 } 1153 } 1154 1155 unconfigureRemote(); 1156 } 1157 1158 /** 1159 * Creates the template files based in the contents of the UserData object. 1160 * These templates files are used to generate automatically data. To generate 1161 * the template file the code will basically take into account the value of 1162 * the base dn and the number of entries to be generated. 1163 * 1164 * @return a list of file objects pointing to the create template files. 1165 * @throws ApplicationException 1166 * if an error occurs. 1167 */ 1168 private File createTemplateFile() throws ApplicationException 1169 { 1170 try 1171 { 1172 Set<String> baseDNs = new LinkedHashSet<>(getUserData().getNewSuffixOptions().getBaseDns()); 1173 int nEntries = getUserData().getNewSuffixOptions().getNumberEntries(); 1174 return SetupUtils.createTemplateFile(baseDNs, nEntries); 1175 } 1176 catch (IOException ioe) 1177 { 1178 LocalizableMessage failedMsg = getThrowableMsg(INFO_ERROR_CREATING_TEMP_FILE.get(), ioe); 1179 throw new ApplicationException(ReturnCode.FILE_SYSTEM_ACCESS_ERROR, failedMsg, ioe); 1180 } 1181 } 1182 1183 /** 1184 * This methods configures the server based on the contents of the UserData 1185 * object provided in the constructor. 1186 * 1187 * @throws ApplicationException 1188 * if something goes wrong. 1189 */ 1190 private void configureServer() throws ApplicationException 1191 { 1192 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CONFIGURING.get())); 1193 copyTemplateInstance(); 1194 writeOpenDSJavaHome(); 1195 writeHostName(); 1196 checkAbort(); 1197 1198 List<String> argList = CollectionUtils.newArrayList( 1199 "-c", getConfigurationFile(), 1200 "-h", getUserData().getHostName(), 1201 "-p", String.valueOf(getUserData().getServerPort()), 1202 "--adminConnectorPort", String.valueOf(getUserData().getAdminConnectorPort())); 1203 1204 final SecurityOptions sec = getUserData().getSecurityOptions(); 1205 // TODO: even if the user does not configure SSL maybe we should choose 1206 // a secure port that is not being used and that we can actually use. 1207 if (sec.getEnableSSL()) 1208 { 1209 argList.add("-P"); 1210 argList.add(String.valueOf(sec.getSslPort())); 1211 } 1212 1213 if (sec.getEnableStartTLS()) 1214 { 1215 argList.add("-q"); 1216 } 1217 1218 addCertificateArguments(sec, argList); 1219 // For the moment do not enable JMX 1220 if (getUserData().getServerJMXPort() > 0) 1221 { 1222 argList.add("-x"); 1223 argList.add(String.valueOf(getUserData().getServerJMXPort())); 1224 } 1225 1226 argList.add("-D"); 1227 argList.add(getUserData().getDirectoryManagerDn()); 1228 1229 argList.add("-w"); 1230 argList.add(getUserData().getDirectoryManagerPwd()); 1231 1232 final ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendType = 1233 getUserData().getBackendType(); 1234 if (backendType != null) 1235 { 1236 argList.add("--" + OPTION_LONG_BACKEND_TYPE); 1237 argList.add(BackendTypeHelper.filterSchemaBackendName(backendType.getName())); 1238 } 1239 1240 if (createNotReplicatedSuffix()) 1241 { 1242 for (String baseDn : getUserData().getNewSuffixOptions().getBaseDns()) 1243 { 1244 argList.add("-b"); 1245 argList.add(baseDn); 1246 } 1247 } 1248 1249 argList.add("-R"); 1250 argList.add(getInstallation().getRootDirectory().getAbsolutePath()); 1251 1252 final String[] args = new String[argList.size()]; 1253 argList.toArray(args); 1254 StringBuilder cmd = new StringBuilder(); 1255 boolean nextPassword = false; 1256 for (String s : argList) 1257 { 1258 if (cmd.length() > 0) 1259 { 1260 cmd.append(" "); 1261 } 1262 if (nextPassword) 1263 { 1264 cmd.append("{rootUserPassword}"); 1265 } 1266 else 1267 { 1268 cmd.append(s); 1269 } 1270 nextPassword = "-w".equals(s); 1271 } 1272 logger.info(LocalizableMessage.raw("configure DS cmd: " + cmd)); 1273 final InstallerHelper helper = new InstallerHelper(); 1274 setNotifyListeners(false); 1275 InvokeThread thread = new InvokeThread() 1276 { 1277 @Override 1278 public void run() 1279 { 1280 try 1281 { 1282 if (helper.invokeConfigureServer(args) != 0) 1283 { 1284 ae = new ApplicationException(ReturnCode.CONFIGURATION_ERROR, INFO_ERROR_CONFIGURING.get(), null); 1285 } 1286 else if (getUserData().getNewSuffixOptions().getBaseDns().isEmpty()) 1287 { 1288 helper.deleteBackend(ROOT_BACKEND_NAME); 1289 } 1290 } 1291 catch (ApplicationException aex) 1292 { 1293 ae = aex; 1294 } 1295 catch (Throwable t) 1296 { 1297 ae = new ApplicationException( 1298 ReturnCode.CONFIGURATION_ERROR, getThrowableMsg(INFO_ERROR_CONFIGURING.get(), t), t); 1299 } 1300 finally 1301 { 1302 setNotifyListeners(true); 1303 } 1304 isOver = true; 1305 } 1306 1307 @Override 1308 public void abort() 1309 { 1310 // TODO: implement the abort 1311 } 1312 }; 1313 invokeLongOperation(thread); 1314 notifyListeners(getFormattedDoneWithLineBreak()); 1315 checkAbort(); 1316 configureCertificate(sec); 1317 } 1318 1319 private void configureCertificate(SecurityOptions sec) throws ApplicationException 1320 { 1321 try 1322 { 1323 SecurityOptions.CertificateType certType = sec.getCertificateType(); 1324 if (certType != SecurityOptions.CertificateType.NO_CERTIFICATE) 1325 { 1326 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_UPDATING_CERTIFICATES.get())); 1327 } 1328 1329 switch (certType) 1330 { 1331 case NO_CERTIFICATE: 1332 // Nothing to do 1333 break; 1334 case SELF_SIGNED_CERTIFICATE: 1335 String pwd = getSelfSignedCertificatePwd(); 1336 final CertificateManager certManager = 1337 new CertificateManager(getSelfSignedKeystorePath(), CertificateManager.KEY_STORE_TYPE_JKS, pwd); 1338 for (String alias : sec.getAliasesToUse()) 1339 { 1340 final KeyType keyType = KeyType.getTypeOrDefault(alias); 1341 certManager.generateSelfSignedCertificate(keyType, alias, getSelfSignedCertificateSubjectDN(keyType), 1342 getSelfSignedCertificateValidity()); 1343 SetupUtils.exportCertificate(certManager, alias, getTemporaryCertificatePath()); 1344 configureTrustStore(CertificateManager.KEY_STORE_TYPE_JKS, alias, pwd); 1345 } 1346 break; 1347 1348 case JKS: 1349 configureKeyAndTrustStore(sec.getKeystorePath(), CertificateManager.KEY_STORE_TYPE_JKS, 1350 CertificateManager.KEY_STORE_TYPE_JKS, sec); 1351 break; 1352 1353 case JCEKS: 1354 configureKeyAndTrustStore(sec.getKeystorePath(), CertificateManager.KEY_STORE_TYPE_JCEKS, 1355 CertificateManager.KEY_STORE_TYPE_JCEKS, sec); 1356 break; 1357 1358 case PKCS12: 1359 configureKeyAndTrustStore(sec.getKeystorePath(), CertificateManager.KEY_STORE_TYPE_PKCS12, 1360 CertificateManager.KEY_STORE_TYPE_JKS, sec); 1361 break; 1362 1363 case PKCS11: 1364 configureKeyAndTrustStore(CertificateManager.KEY_STORE_PATH_PKCS11, CertificateManager.KEY_STORE_TYPE_PKCS11, 1365 CertificateManager.KEY_STORE_TYPE_JKS, sec); 1366 break; 1367 1368 default: 1369 throw new IllegalStateException("Unknown certificate type: " + certType); 1370 } 1371 1372 if (certType != SecurityOptions.CertificateType.NO_CERTIFICATE) 1373 { 1374 notifyListeners(getFormattedDoneWithLineBreak()); 1375 } 1376 } 1377 catch (Throwable t) 1378 { 1379 logger.error(LocalizableMessage.raw("Error configuring certificate: " + t, t)); 1380 throw new ApplicationException( 1381 ReturnCode.CONFIGURATION_ERROR, getThrowableMsg(INFO_ERROR_CONFIGURING_CERTIFICATE.get(), t), t); 1382 } 1383 } 1384 1385 private void configureKeyAndTrustStore(final String keyStorePath, final String keyStoreType, 1386 final String trustStoreType, final SecurityOptions sec) throws Exception 1387 { 1388 final String keystorePassword = sec.getKeystorePassword(); 1389 CertificateManager certManager = new CertificateManager(keyStorePath, keyStoreType, keystorePassword); 1390 for (String keyStoreAlias : sec.getAliasesToUse()) 1391 { 1392 SetupUtils.exportCertificate(certManager, keyStoreAlias, getTemporaryCertificatePath()); 1393 configureTrustStore(trustStoreType, keyStoreAlias, keystorePassword); 1394 } 1395 } 1396 1397 private void configureTrustStore(final String type, final String keyStoreAlias, final String password) 1398 throws Exception 1399 { 1400 final String alias = keyStoreAlias != null ? keyStoreAlias : SELF_SIGNED_CERT_ALIASES[0]; 1401 final CertificateManager trustMgr = new CertificateManager(getTrustManagerPath(), type, password); 1402 trustMgr.addCertificate(alias, new File(getTemporaryCertificatePath())); 1403 1404 createProtectedFile(getKeystorePinPath(), password); 1405 final File f = new File(getTemporaryCertificatePath()); 1406 f.delete(); 1407 } 1408 1409 private void addCertificateArguments(SecurityOptions sec, List<String> argList) 1410 { 1411 final Collection<String> aliasInKeyStore = sec.getAliasesToUse(); 1412 1413 switch (sec.getCertificateType()) 1414 { 1415 case SELF_SIGNED_CERTIFICATE: 1416 argList.add("-k"); 1417 argList.add("cn=JKS,cn=Key Manager Providers,cn=config"); 1418 argList.add("-t"); 1419 argList.add("cn=JKS,cn=Trust Manager Providers,cn=config"); 1420 break; 1421 case JKS: 1422 addCertificateArguments(argList, sec, aliasInKeyStore, "cn=JKS,cn=Key Manager Providers,cn=config", 1423 "cn=JKS,cn=Trust Manager Providers,cn=config"); 1424 break; 1425 case JCEKS: 1426 addCertificateArguments(argList, sec, aliasInKeyStore, "cn=JCEKS,cn=Key Manager Providers,cn=config", 1427 "cn=JCEKS,cn=Trust Manager Providers,cn=config"); 1428 break; 1429 case PKCS12: 1430 addCertificateArguments(argList, sec, aliasInKeyStore, "cn=PKCS12,cn=Key Manager Providers,cn=config", 1431 "cn=JKS,cn=Trust Manager Providers,cn=config"); 1432 break; 1433 case PKCS11: 1434 addCertificateArguments(argList, null, aliasInKeyStore, "cn=PKCS11,cn=Key Manager Providers,cn=config", 1435 "cn=JKS,cn=Trust Manager Providers,cn=config"); 1436 break; 1437 case NO_CERTIFICATE: 1438 // Nothing to do. 1439 break; 1440 default: 1441 throw new IllegalStateException("Unknown certificate type: " + sec.getCertificateType()); 1442 } 1443 } 1444 1445 private static void addCertificateArguments(List<String> argList, SecurityOptions sec, 1446 Collection<String> aliasesInKeyStore, String keyStoreDN, String trustStoreDN) 1447 { 1448 argList.add("-k"); 1449 argList.add(keyStoreDN); 1450 argList.add("-t"); 1451 argList.add(trustStoreDN); 1452 if (sec != null) 1453 { 1454 argList.add("-m"); 1455 argList.add(sec.getKeystorePath()); 1456 } 1457 for(String alias : aliasesInKeyStore) 1458 { 1459 argList.add("-a"); 1460 argList.add(alias); 1461 } 1462 } 1463 1464 /** 1465 * This methods creates the base entry for the suffix based on the contents of 1466 * the UserData object provided in the constructor. 1467 * 1468 * @throws ApplicationException 1469 * if something goes wrong. 1470 */ 1471 private void createBaseEntry() throws ApplicationException 1472 { 1473 LinkedList<String> baseDns = getUserData().getNewSuffixOptions().getBaseDns(); 1474 if (baseDns.size() == 1) 1475 { 1476 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CREATING_BASE_ENTRY.get(baseDns.getFirst()))); 1477 } 1478 else 1479 { 1480 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CREATING_BASE_ENTRIES.get())); 1481 } 1482 1483 final InstallerHelper helper = new InstallerHelper(); 1484 1485 LinkedList<File> ldifFiles = new LinkedList<>(); 1486 1487 for (String baseDn : baseDns) 1488 { 1489 ldifFiles.add(helper.createBaseEntryTempFile(baseDn)); 1490 } 1491 checkAbort(); 1492 1493 List<String> argList = new ArrayList<>(); 1494 argList.add("-n"); 1495 argList.add(ROOT_BACKEND_NAME); 1496 for (File f : ldifFiles) 1497 { 1498 argList.add("-l"); 1499 argList.add(f.getAbsolutePath()); 1500 } 1501 argList.add("-F"); 1502 argList.add("-Q"); 1503 argList.add("--noPropertiesFile"); 1504 1505 final String[] args = new String[argList.size()]; 1506 argList.toArray(args); 1507 1508 setNotifyListeners(false); 1509 1510 InvokeThread thread = new InvokeThread() 1511 { 1512 @Override 1513 public void run() 1514 { 1515 try 1516 { 1517 int result = helper.invokeImportLDIF(Installer.this, args); 1518 1519 if (result != 0) 1520 { 1521 ae = new ApplicationException(ReturnCode.IMPORT_ERROR, INFO_ERROR_CREATING_BASE_ENTRY.get(), null); 1522 } 1523 } 1524 catch (Throwable t) 1525 { 1526 ae = 1527 new ApplicationException(ReturnCode.IMPORT_ERROR, 1528 getThrowableMsg(INFO_ERROR_CREATING_BASE_ENTRY.get(), t), t); 1529 } 1530 finally 1531 { 1532 setNotifyListeners(true); 1533 } 1534 isOver = true; 1535 } 1536 1537 @Override 1538 public void abort() 1539 { 1540 // TODO: implement the abort 1541 } 1542 }; 1543 invokeLongOperation(thread); 1544 notifyListeners(getFormattedDoneWithLineBreak()); 1545 } 1546 1547 /** 1548 * This methods imports the contents of an LDIF file based on the contents of 1549 * the UserData object provided in the constructor. 1550 * 1551 * @throws ApplicationException 1552 * if something goes wrong. 1553 */ 1554 private void importLDIF() throws ApplicationException 1555 { 1556 LinkedList<String> ldifPaths = getUserData().getNewSuffixOptions().getLDIFPaths(); 1557 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 1558 if (ldifPaths.size() > 1) 1559 { 1560 if (isVerbose()) 1561 { 1562 mb.append(getFormattedProgress(INFO_PROGRESS_IMPORTING_LDIFS.get(joinAsString(", ", ldifPaths)))); 1563 mb.append(getLineBreak()); 1564 } 1565 else 1566 { 1567 mb.append(getFormattedProgress(INFO_PROGRESS_IMPORTING_LDIFS_NON_VERBOSE.get(joinAsString(", ", ldifPaths)))); 1568 } 1569 } 1570 else if (isVerbose()) 1571 { 1572 mb.append(getFormattedProgress(INFO_PROGRESS_IMPORTING_LDIF.get(ldifPaths.getFirst()))); 1573 mb.append(getLineBreak()); 1574 } 1575 else 1576 { 1577 mb.append(getFormattedProgress(INFO_PROGRESS_IMPORTING_LDIF_NON_VERBOSE.get(ldifPaths.getFirst()))); 1578 } 1579 notifyListeners(mb.toMessage()); 1580 1581 final PointAdder pointAdder = new PointAdder(); 1582 1583 if (!isVerbose()) 1584 { 1585 setNotifyListeners(false); 1586 pointAdder.start(); 1587 } 1588 1589 List<String> argList = new ArrayList<>(); 1590 argList.add("-n"); 1591 argList.add(ROOT_BACKEND_NAME); 1592 for (String ldifPath : ldifPaths) 1593 { 1594 argList.add("-l"); 1595 argList.add(ldifPath); 1596 } 1597 argList.add("-F"); 1598 String rejectedFile = getUserData().getNewSuffixOptions().getRejectedFile(); 1599 if (rejectedFile != null) 1600 { 1601 argList.add("-R"); 1602 argList.add(rejectedFile); 1603 } 1604 String skippedFile = getUserData().getNewSuffixOptions().getSkippedFile(); 1605 if (skippedFile != null) 1606 { 1607 argList.add("--skipFile"); 1608 argList.add(skippedFile); 1609 } 1610 1611 argList.add("--noPropertiesFile"); 1612 1613 final String[] args = new String[argList.size()]; 1614 argList.toArray(args); 1615 1616 InvokeThread thread = new InvokeThread() 1617 { 1618 @Override 1619 public void run() 1620 { 1621 try 1622 { 1623 InstallerHelper helper = new InstallerHelper(); 1624 int result = helper.invokeImportLDIF(Installer.this, args); 1625 1626 if (result != 0) 1627 { 1628 ae = new ApplicationException(ReturnCode.IMPORT_ERROR, INFO_ERROR_IMPORTING_LDIF.get(), null); 1629 } 1630 } 1631 catch (Throwable t) 1632 { 1633 ae = new ApplicationException( 1634 ReturnCode.IMPORT_ERROR, getThrowableMsg(INFO_ERROR_IMPORTING_LDIF.get(), t), t); 1635 } 1636 finally 1637 { 1638 if (!isVerbose()) 1639 { 1640 setNotifyListeners(true); 1641 pointAdder.stop(); 1642 } 1643 } 1644 isOver = true; 1645 } 1646 1647 @Override 1648 public void abort() 1649 { 1650 // TODO: implement the abort 1651 } 1652 }; 1653 try 1654 { 1655 invokeLongOperation(thread); 1656 } 1657 catch (ApplicationException ae) 1658 { 1659 if (!isVerbose() && lastImportProgress != null) 1660 { 1661 notifyListeners(getFormattedProgress(LocalizableMessage.raw(lastImportProgress))); 1662 notifyListeners(getLineBreak()); 1663 } 1664 throw ae; 1665 } 1666 if (!isVerbose()) 1667 { 1668 if (lastImportProgress == null) 1669 { 1670 notifyListeners(getFormattedDoneWithLineBreak()); 1671 } 1672 else 1673 { 1674 notifyListeners(getFormattedProgress(LocalizableMessage.raw(lastImportProgress))); 1675 notifyListeners(getLineBreak()); 1676 } 1677 } 1678 } 1679 1680 /** 1681 * This methods imports automatically generated data based on the contents of 1682 * the UserData object provided in the constructor. 1683 * 1684 * @throws ApplicationException 1685 * if something goes wrong. 1686 */ 1687 private void importAutomaticallyGenerated() throws ApplicationException 1688 { 1689 File templatePath = createTemplateFile(); 1690 int nEntries = getUserData().getNewSuffixOptions().getNumberEntries(); 1691 LocalizableMessageBuilder mb = new LocalizableMessageBuilder(); 1692 if (isVerbose() || nEntries > THRESHOLD_AUTOMATIC_DATA_VERBOSE) 1693 { 1694 mb.append(getFormattedProgress(INFO_PROGRESS_IMPORT_AUTOMATICALLY_GENERATED.get(nEntries))); 1695 mb.append(getLineBreak()); 1696 } 1697 else 1698 { 1699 mb.append(getFormattedProgress(INFO_PROGRESS_IMPORT_AUTOMATICALLY_GENERATED_NON_VERBOSE.get(nEntries))); 1700 } 1701 notifyListeners(mb.toMessage()); 1702 1703 final PointAdder pointAdder = new PointAdder(); 1704 if (!isVerbose()) 1705 { 1706 pointAdder.start(); 1707 } 1708 1709 if (!isVerbose()) 1710 { 1711 setNotifyListeners(false); 1712 } 1713 final List<String> argList = new ArrayList<>(); 1714 argList.add("-n"); 1715 argList.add(ROOT_BACKEND_NAME); 1716 argList.add("-A"); 1717 argList.add(templatePath.getAbsolutePath()); 1718 argList.add("-s"); // seed 1719 argList.add("0"); 1720 argList.add("-F"); 1721 argList.add("--noPropertiesFile"); 1722 1723 final String[] args = new String[argList.size()]; 1724 argList.toArray(args); 1725 1726 InvokeThread thread = new InvokeThread() 1727 { 1728 @Override 1729 public void run() 1730 { 1731 try 1732 { 1733 InstallerHelper helper = new InstallerHelper(); 1734 int result = helper.invokeImportLDIF(Installer.this, args); 1735 1736 if (result != 0) 1737 { 1738 ae = new ApplicationException( 1739 ReturnCode.IMPORT_ERROR, INFO_ERROR_IMPORT_LDIF_TOOL_RETURN_CODE.get(result), null); 1740 } 1741 } 1742 catch (Throwable t) 1743 { 1744 ae = new ApplicationException(ReturnCode.IMPORT_ERROR, getThrowableMsg( 1745 INFO_ERROR_IMPORT_AUTOMATICALLY_GENERATED.get(joinAsString(" ", argList), 1746 t.getLocalizedMessage()), t), t); 1747 } 1748 finally 1749 { 1750 if (!isVerbose()) 1751 { 1752 setNotifyListeners(true); 1753 if (ae != null) 1754 { 1755 pointAdder.stop(); 1756 } 1757 } 1758 } 1759 isOver = true; 1760 } 1761 1762 @Override 1763 public void abort() 1764 { 1765 // TODO: implement the abort 1766 } 1767 }; 1768 invokeLongOperation(thread); 1769 if (!isVerbose()) 1770 { 1771 pointAdder.stop(); 1772 notifyListeners(getFormattedDoneWithLineBreak()); 1773 } 1774 } 1775 1776 /** 1777 * This method undoes the modifications made in other servers in terms of 1778 * replication. This method assumes that we are aborting the Installer and 1779 * that is why it does not call checkAbort. 1780 */ 1781 private void unconfigureRemote() 1782 { 1783 if (registeredNewServerOnRemote || createdAdministrator || createdRemoteAds) 1784 { 1785 // Try to connect 1786 DataReplicationOptions repl = getUserData().getReplicationOptions(); 1787 AuthenticationData auth = repl.getAuthenticationData(); 1788 if (isVerbose()) 1789 { 1790 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_UNCONFIGURING_ADS_ON_REMOTE.get(auth.getHostPort()))); 1791 } 1792 try (ConnectionWrapper connectionWrapper = createConnection(auth)) 1793 { 1794 ADSContext adsContext = new ADSContext(connectionWrapper); 1795 if (createdRemoteAds) 1796 { 1797 adsContext.removeAdminData(true); 1798 } 1799 else 1800 { 1801 if (registeredNewServerOnRemote) 1802 { 1803 try 1804 { 1805 adsContext.unregisterServer(getNewServerAdsProperties(getUserData())); 1806 } 1807 catch (ADSContextException ace) 1808 { 1809 if (ace.getError() != ADSContextException.ErrorType.NOT_YET_REGISTERED) 1810 { 1811 throw ace; 1812 } 1813 // Else, nothing to do: this may occur if the new server has been 1814 // unregistered on another server and the modification has been 1815 // already propagated by replication. 1816 } 1817 } 1818 if (createdAdministrator) 1819 { 1820 adsContext.deleteAdministrator(getAdministratorProperties(getUserData())); 1821 } 1822 } 1823 if (isVerbose()) 1824 { 1825 notifyListeners(getFormattedDoneWithLineBreak()); 1826 } 1827 } 1828 catch (Throwable t) 1829 { 1830 notifyListeners(getFormattedError(t, true)); 1831 } 1832 } 1833 InstallerHelper helper = new InstallerHelper(); 1834 for (ServerDescriptor server : hmConfiguredRemoteReplication.keySet()) 1835 { 1836 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_UNCONFIGURING_REPLICATION_REMOTE.get(getHostPort(server)))); 1837 try (ConnectionWrapper connectionWrapper = getRemoteConnection(server)) 1838 { 1839 helper.unconfigureReplication(connectionWrapper, hmConfiguredRemoteReplication.get(server)); 1840 } 1841 catch (ApplicationException ae) 1842 { 1843 notifyListeners(getFormattedError(ae, true)); 1844 } 1845 notifyListeners(getFormattedDoneWithLineBreak()); 1846 } 1847 } 1848 1849 /** 1850 * This method configures the backends and suffixes that must be replicated. 1851 * The setup uses the same backend names as in the remote servers. If userRoot 1852 * is not one of the backends defined in the remote servers, it deletes it 1853 * from the configuration. NOTE: this method assumes that the server is 1854 * running. 1855 * 1856 * @throws ApplicationException 1857 * if something goes wrong. 1858 */ 1859 private void createReplicatedBackendsIfRequired() throws ApplicationException 1860 { 1861 if (FIRST_IN_TOPOLOGY == getUserData().getReplicationOptions().getType()) 1862 { 1863 return; 1864 } 1865 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CREATING_REPLICATED_BACKENDS.get())); 1866 1867 // The keys are the backend IDs and the values the list of base DNs. 1868 final Map<String, Set<String>> hmBackendSuffix = new HashMap<>(); 1869 final SuffixesToReplicateOptions suffixData = getUserData().getSuffixesToReplicateOptions(); 1870 populateBackendsToCreate(hmBackendSuffix, suffixData.getSuffixes()); 1871 createReplicatedBackends(hmBackendSuffix, suffixData.getSuffixBackendTypes()); 1872 notifyListeners(getFormattedDoneWithLineBreak()); 1873 checkAbort(); 1874 } 1875 1876 /** 1877 * The criteria to choose the name of the backend is to try to have the 1878 * configuration of the other server. The algorithm consists on putting the 1879 * remote servers in a list and pick the backend as they appear on the list. 1880 */ 1881 private void populateBackendsToCreate(Map<String, Set<String>> hmBackendSuffix, Set<SuffixDescriptor> suffixes) 1882 { 1883 Set<ServerDescriptor> serverList = getServerListFromSuffixes(suffixes); 1884 for (SuffixDescriptor suffix : suffixes) 1885 { 1886 final ReplicaDescriptor replica = retrieveReplicaForSuffix(serverList, suffix); 1887 if (replica != null) 1888 { 1889 final String backendNameKey = getOrAddBackend(hmBackendSuffix, replica.getBackendName()); 1890 hmBackendSuffix.get(backendNameKey).add(suffix.getDN()); 1891 } 1892 } 1893 } 1894 1895 private Set<ServerDescriptor> getServerListFromSuffixes(Set<SuffixDescriptor> suffixes) 1896 { 1897 Set<ServerDescriptor> serverList = new LinkedHashSet<>(); 1898 for (SuffixDescriptor suffix : suffixes) 1899 { 1900 for (ReplicaDescriptor replica : suffix.getReplicas()) 1901 { 1902 serverList.add(replica.getServer()); 1903 } 1904 } 1905 return serverList; 1906 } 1907 1908 private ReplicaDescriptor retrieveReplicaForSuffix(Set<ServerDescriptor> serverList, SuffixDescriptor suffix) 1909 { 1910 for (ServerDescriptor server : serverList) 1911 { 1912 for (ReplicaDescriptor replica : suffix.getReplicas()) 1913 { 1914 if (replica.getServer() == server) 1915 { 1916 return replica; 1917 } 1918 } 1919 } 1920 return null; 1921 } 1922 1923 private String getOrAddBackend(Map<String, Set<String>> hmBackendSuffix, String backendName) 1924 { 1925 for (String storedBackend : hmBackendSuffix.keySet()) 1926 { 1927 if (storedBackend.equalsIgnoreCase(backendName)) 1928 { 1929 return storedBackend; 1930 } 1931 } 1932 hmBackendSuffix.put(backendName, new HashSet<String>()); 1933 return backendName; 1934 } 1935 1936 private void createReplicatedBackends(final Map<String, Set<String>> hmBackendSuffix, 1937 final Map<String, BackendTypeUIAdapter> backendTypes) throws ApplicationException 1938 { 1939 try (ConnectionWrapper connection = createLocalConnection()) 1940 { 1941 final InstallerHelper helper = new InstallerHelper(); 1942 for (String backendName : hmBackendSuffix.keySet()) 1943 { 1944 helper.createBackend(connection, backendName, hmBackendSuffix.get(backendName), 1945 backendTypes.get(backendName).getBackend()); 1946 } 1947 } 1948 catch (NamingException ne) 1949 { 1950 LocalizableMessage failedMsg = getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), ne); 1951 throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, failedMsg, ne); 1952 } 1953 } 1954 1955 /** 1956 * This method creates the replication configuration for the suffixes on the 1957 * the local server (and eventually in the remote servers) to synchronize 1958 * things. NOTE: this method assumes that the server is running. 1959 * 1960 * @throws ApplicationException 1961 * if something goes wrong. 1962 */ 1963 private void configureReplication() throws ApplicationException 1964 { 1965 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CONFIGURING_REPLICATION.get())); 1966 1967 InstallerHelper helper = new InstallerHelper(); 1968 Set<Integer> knownServerIds = new HashSet<>(); 1969 Set<Integer> knownReplicationServerIds = new HashSet<>(); 1970 if (lastLoadedCache != null) 1971 { 1972 for (SuffixDescriptor suffix : lastLoadedCache.getSuffixes()) 1973 { 1974 for (ReplicaDescriptor replica : suffix.getReplicas()) 1975 { 1976 knownServerIds.add(replica.getReplicationId()); 1977 } 1978 } 1979 for (ServerDescriptor server : lastLoadedCache.getServers()) 1980 { 1981 Object v = server.getServerProperties().get(REPLICATION_SERVER_ID); 1982 if (v != null) 1983 { 1984 knownReplicationServerIds.add((Integer) v); 1985 } 1986 } 1987 } 1988 else 1989 { 1990 /* There is no ADS anywhere. Just use the SuffixDescriptors we found */ 1991 for (SuffixDescriptor suffix : getUserData().getSuffixesToReplicateOptions().getAvailableSuffixes()) 1992 { 1993 for (ReplicaDescriptor replica : suffix.getReplicas()) 1994 { 1995 knownServerIds.add(replica.getReplicationId()); 1996 Object v = replica.getServer().getServerProperties().get(REPLICATION_SERVER_ID); 1997 if (v != null) 1998 { 1999 knownReplicationServerIds.add((Integer) v); 2000 } 2001 } 2002 } 2003 } 2004 2005 /* 2006 * For each suffix specified by the user, create a map from the suffix DN to 2007 * the set of replication servers. The initial instance in a topology is a 2008 * degenerate case. Also, collect a set of all observed replication servers 2009 * as the set of ADS suffix replicas (all instances hosting the replication 2010 * server also replicate ADS). 2011 */ 2012 Map<String, Set<String>> replicationServers = new HashMap<>(); 2013 Set<String> adsServers = new HashSet<>(); 2014 2015 if (getUserData().getReplicationOptions().getType() == DataReplicationOptions.Type.FIRST_IN_TOPOLOGY) 2016 { 2017 List<String> baseDns = getUserData().getNewSuffixOptions().getBaseDns(); 2018 Set<String> h = new HashSet<>(); 2019 h.add(getLocalReplicationServer()); 2020 adsServers.add(getLocalReplicationServer()); 2021 for (String dn : baseDns) 2022 { 2023 replicationServers.put(dn, h); 2024 } 2025 } 2026 else 2027 { 2028 Set<SuffixDescriptor> suffixes = getUserData().getSuffixesToReplicateOptions().getSuffixes(); 2029 for (SuffixDescriptor suffix : suffixes) 2030 { 2031 Set<String> h = new HashSet<>(suffix.getReplicationServers()); 2032 adsServers.addAll(suffix.getReplicationServers()); 2033 h.add(getLocalReplicationServer()); 2034 adsServers.add(getLocalReplicationServer()); 2035 for (ReplicaDescriptor replica : suffix.getReplicas()) 2036 { 2037 ServerDescriptor server = replica.getServer(); 2038 AuthenticationData repPort = getUserData().getRemoteWithNoReplicationPort().get(server); 2039 if (repPort != null) 2040 { 2041 String serverDisplay = server.getHostName() + ":" + repPort.getPort(); 2042 h.add(serverDisplay); 2043 adsServers.add(serverDisplay); 2044 } 2045 } 2046 replicationServers.put(suffix.getDN(), h); 2047 } 2048 } 2049 replicationServers.put(ADSContext.getAdministrationSuffixDN(), adsServers); 2050 replicationServers.put(Constants.SCHEMA_DN, new HashSet<String>(adsServers)); 2051 2052 long localTime = -1; 2053 long localTimeMeasureTime = -1; 2054 HostPort localServerDisplay = null; 2055 try (ConnectionWrapper conn = createLocalConnection()) 2056 { 2057 helper.configureReplication(conn, replicationServers, 2058 getUserData().getReplicationOptions().getReplicationPort(), 2059 getUserData().getReplicationOptions().useSecureReplication(), 2060 knownReplicationServerIds, 2061 knownServerIds); 2062 localTimeMeasureTime = System.currentTimeMillis(); 2063 localTime = Utils.getServerClock(conn.getLdapContext()); 2064 localServerDisplay = conn.getHostPort(); 2065 } 2066 catch (NamingException ne) 2067 { 2068 LocalizableMessage failedMsg = getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), ne); 2069 throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, failedMsg, ne); 2070 } 2071 notifyListeners(getFormattedDoneWithLineBreak()); 2072 checkAbort(); 2073 2074 if (getUserData().getReplicationOptions().getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY) 2075 { 2076 Map<ServerDescriptor, Set<ReplicaDescriptor>> hm = new HashMap<>(); 2077 for (SuffixDescriptor suffix : getUserData().getSuffixesToReplicateOptions().getSuffixes()) 2078 { 2079 for (ReplicaDescriptor replica : suffix.getReplicas()) 2080 { 2081 Set<ReplicaDescriptor> replicas = hm.get(replica.getServer()); 2082 if (replicas == null) 2083 { 2084 replicas = new HashSet<>(); 2085 hm.put(replica.getServer(), replicas); 2086 } 2087 replicas.add(replica); 2088 } 2089 } 2090 for (ServerDescriptor server : hm.keySet()) 2091 { 2092 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CONFIGURING_REPLICATION_REMOTE.get(getHostPort(server)))); 2093 Integer v = (Integer) server.getServerProperties().get(REPLICATION_SERVER_PORT); 2094 int replicationPort; 2095 boolean enableSecureReplication; 2096 if (v != null) 2097 { 2098 replicationPort = v; 2099 enableSecureReplication = false; 2100 } 2101 else 2102 { 2103 AuthenticationData authData = getUserData().getRemoteWithNoReplicationPort().get(server); 2104 if (authData != null) 2105 { 2106 replicationPort = authData.getPort(); 2107 enableSecureReplication = authData.useSecureConnection(); 2108 } 2109 else 2110 { 2111 replicationPort = Constants.DEFAULT_REPLICATION_PORT; 2112 enableSecureReplication = false; 2113 logger.warn(LocalizableMessage.raw("Could not find replication port for: " + getHostPort(server))); 2114 } 2115 } 2116 Set<String> dns = new HashSet<>(); 2117 for (ReplicaDescriptor replica : hm.get(server)) 2118 { 2119 dns.add(replica.getSuffix().getDN()); 2120 } 2121 dns.add(ADSContext.getAdministrationSuffixDN()); 2122 dns.add(Constants.SCHEMA_DN); 2123 Map<String, Set<String>> remoteReplicationServers = new HashMap<>(); 2124 for (String dn : dns) 2125 { 2126 Set<String> repServer = replicationServers.get(dn); 2127 if (repServer == null) 2128 { 2129 // Do the comparison manually 2130 for (String dn1 : replicationServers.keySet()) 2131 { 2132 if (Utils.areDnsEqual(dn, dn1)) 2133 { 2134 repServer = replicationServers.get(dn1); 2135 dn = dn1; 2136 break; 2137 } 2138 } 2139 } 2140 if (repServer != null) 2141 { 2142 remoteReplicationServers.put(dn, repServer); 2143 } 2144 else 2145 { 2146 logger.warn(LocalizableMessage.raw("Could not find replication server for: " + dn)); 2147 } 2148 } 2149 2150 try (ConnectionWrapper conn = getRemoteConnection(server)) 2151 { 2152 ConfiguredReplication repl = helper.configureReplication( 2153 conn, remoteReplicationServers, replicationPort, enableSecureReplication, 2154 knownReplicationServerIds, knownServerIds); 2155 long remoteTimeMeasureTime = System.currentTimeMillis(); 2156 long remoteTime = Utils.getServerClock(conn.getLdapContext()); 2157 if (localTime != -1 2158 && remoteTime != -1 2159 && Math.abs(localTime - remoteTime - localTimeMeasureTime + remoteTimeMeasureTime) > 2160 THRESHOLD_CLOCK_DIFFERENCE_WARNING * 60 * 1000) 2161 { 2162 notifyListeners(getFormattedWarning(INFO_WARNING_SERVERS_CLOCK_DIFFERENCE.get( 2163 localServerDisplay, conn.getHostPort(), THRESHOLD_CLOCK_DIFFERENCE_WARNING))); 2164 } 2165 2166 hmConfiguredRemoteReplication.put(server, repl); 2167 } 2168 2169 notifyListeners(getFormattedDoneWithLineBreak()); 2170 checkAbort(); 2171 } 2172 } 2173 } 2174 2175 /** 2176 * This methods enables this server as a Windows service. 2177 * 2178 * @throws ApplicationException 2179 * if something goes wrong. 2180 */ 2181 private void enableWindowsService() throws ApplicationException 2182 { 2183 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_ENABLING_WINDOWS_SERVICE.get())); 2184 InstallerHelper helper = new InstallerHelper(); 2185 helper.enableWindowsService(); 2186 notifyListeners(getLineBreak()); 2187 } 2188 2189 /** 2190 * Updates the contents of the provided map with the localized summary 2191 * strings. 2192 * 2193 * @param hmSummary 2194 * the Map to be updated. 2195 * @param isCli 2196 * a boolean to indicate if the install is using CLI or GUI 2197 */ 2198 private void initSummaryMap(Map<ProgressStep, LocalizableMessage> hmSummary, boolean isCli) 2199 { 2200 put(hmSummary, NOT_STARTED, INFO_SUMMARY_INSTALL_NOT_STARTED); 2201 put(hmSummary, CONFIGURING_SERVER, INFO_SUMMARY_CONFIGURING); 2202 put(hmSummary, CREATING_BASE_ENTRY, INFO_SUMMARY_CREATING_BASE_ENTRY); 2203 put(hmSummary, IMPORTING_LDIF, INFO_SUMMARY_IMPORTING_LDIF); 2204 put(hmSummary, IMPORTING_AUTOMATICALLY_GENERATED, INFO_SUMMARY_IMPORTING_AUTOMATICALLY_GENERATED); 2205 put(hmSummary, CONFIGURING_REPLICATION, INFO_SUMMARY_CONFIGURING_REPLICATION); 2206 put(hmSummary, STARTING_SERVER, INFO_SUMMARY_STARTING); 2207 put(hmSummary, STOPPING_SERVER, INFO_SUMMARY_STOPPING); 2208 put(hmSummary, CONFIGURING_ADS, INFO_SUMMARY_CONFIGURING_ADS); 2209 put(hmSummary, INITIALIZE_REPLICATED_SUFFIXES, INFO_SUMMARY_INITIALIZE_REPLICATED_SUFFIXES); 2210 put(hmSummary, ENABLING_WINDOWS_SERVICE, INFO_SUMMARY_ENABLING_WINDOWS_SERVICE); 2211 put(hmSummary, WAITING_TO_CANCEL, INFO_SUMMARY_WAITING_TO_CANCEL); 2212 put(hmSummary, CANCELING, INFO_SUMMARY_CANCELING); 2213 2214 Installation installation = getInstallation(); 2215 String cmd = Utils.addWordBreaks(getPath(installation.getControlPanelCommandFile()), 60, 5); 2216 if (!isCli) 2217 { 2218 cmd = UIFactory.applyFontToHtml(cmd, UIFactory.INSTRUCTIONS_MONOSPACE_FONT); 2219 } 2220 String formattedPath = 2221 Utils.addWordBreaks(formatter.getFormattedText(LocalizableMessage.raw(getPath(new File(getInstancePath())))) 2222 .toString(), 60, 5); 2223 LocalizableMessage successMessage = 2224 Utils.getCustomizedObject("INFO_SUMMARY_INSTALL_FINISHED_SUCCESSFULLY", 2225 INFO_SUMMARY_INSTALL_FINISHED_SUCCESSFULLY.get(DynamicConstants.PRODUCT_NAME, 2226 DynamicConstants.PRODUCT_NAME, formattedPath, INFO_GENERAL_SERVER_STOPPED.get(), 2227 DynamicConstants.DOC_QUICK_REFERENCE_GUIDE, DynamicConstants.PRODUCT_NAME, cmd), 2228 LocalizableMessage.class); 2229 hmSummary.put(FINISHED_SUCCESSFULLY, getFormattedSuccess(successMessage)); 2230 hmSummary.put(FINISHED_CANCELED, getFormattedSuccess(INFO_SUMMARY_INSTALL_FINISHED_CANCELED.get())); 2231 hmSummary.put(FINISHED_WITH_ERROR, 2232 getFormattedError(INFO_SUMMARY_INSTALL_FINISHED_WITH_ERROR.get(INFO_GENERAL_SERVER_STOPPED.get(), cmd))); 2233 } 2234 2235 private void put(Map<ProgressStep, LocalizableMessage> hmSummary, InstallProgressStep step, Arg0 msg) 2236 { 2237 hmSummary.put(step, getFormattedSummary(msg.get())); 2238 } 2239 2240 /** 2241 * Updates the messages in the summary with the state of the server. 2242 * 2243 * @param hmSummary 2244 * the Map containing the messages. 2245 * @param isCli 2246 * a boolean to indicate if the install is using CLI or GUI 2247 */ 2248 private void updateSummaryWithServerState(Map<ProgressStep, LocalizableMessage> hmSummary, Boolean isCli) 2249 { 2250 Installation installation = getInstallation(); 2251 String cmd = getPath(installation.getControlPanelCommandFile()); 2252 if (!isCli) 2253 { 2254 cmd = Utils.addWordBreaks(UIFactory.applyFontToHtml(cmd, UIFactory.INSTRUCTIONS_MONOSPACE_FONT), 60, 5); 2255 } 2256 LocalizableMessage status; 2257 if (installation.getStatus().isServerRunning()) 2258 { 2259 status = INFO_GENERAL_SERVER_STARTED.get(); 2260 } 2261 else 2262 { 2263 status = INFO_GENERAL_SERVER_STOPPED.get(); 2264 } 2265 String formattedPath = 2266 Utils.addWordBreaks(formatter.getFormattedText(LocalizableMessage.raw(getPath(new File(getInstancePath())))) 2267 .toString(), 60, 5); 2268 LocalizableMessage successMessage = 2269 Utils.getCustomizedObject("INFO_SUMMARY_INSTALL_FINISHED_SUCCESSFULLY", 2270 INFO_SUMMARY_INSTALL_FINISHED_SUCCESSFULLY.get(DynamicConstants.PRODUCT_NAME, 2271 DynamicConstants.PRODUCT_NAME, formattedPath, status, DynamicConstants.DOC_QUICK_REFERENCE_GUIDE, 2272 DynamicConstants.PRODUCT_NAME, cmd), LocalizableMessage.class); 2273 hmSummary.put(InstallProgressStep.FINISHED_SUCCESSFULLY, getFormattedSuccess(successMessage)); 2274 hmSummary.put(InstallProgressStep.FINISHED_WITH_ERROR, getFormattedError(INFO_SUMMARY_INSTALL_FINISHED_WITH_ERROR 2275 .get(status, cmd))); 2276 } 2277 2278 /** 2279 * Checks the value of <code>canceled</code> field and throws an 2280 * ApplicationException if true. This indicates that the user has canceled 2281 * this operation and the process of aborting should begin as soon as 2282 * possible. 2283 * 2284 * @throws ApplicationException 2285 * thrown if <code>canceled</code> 2286 */ 2287 @Override 2288 public void checkAbort() throws ApplicationException 2289 { 2290 if (canceled) 2291 { 2292 setCurrentProgressStep(InstallProgressStep.CANCELING); 2293 notifyListeners(null); 2294 throw new ApplicationException(ReturnCode.CANCELED, INFO_INSTALL_CANCELED.get(), null); 2295 } 2296 } 2297 2298 /** 2299 * Writes the host name to a file that will be used by the server to generate 2300 * a self-signed certificate. 2301 */ 2302 private void writeHostName() 2303 { 2304 try (BufferedWriter writer = new BufferedWriter(new FileWriter(getHostNameFile(), false))) 2305 { 2306 writer.append(getUserData().getHostName()); 2307 } 2308 catch (IOException ioe) 2309 { 2310 logger.warn(LocalizableMessage.raw("Error writing host name file: " + ioe, ioe)); 2311 } 2312 } 2313 2314 /** 2315 * Returns the file path where the host name is to be written. 2316 * 2317 * @return the file path where the host name is to be written. 2318 */ 2319 private String getHostNameFile() 2320 { 2321 return Utils.getPath(getInstallation().getRootDirectory().getAbsolutePath(), SetupUtils.HOST_NAME_FILE); 2322 } 2323 2324 /** 2325 * Writes the java home that we are using for the setup in a file. This way we 2326 * can use this java home even if the user has not set OPENDJ_JAVA_HOME when 2327 * running the different scripts. 2328 */ 2329 private void writeOpenDSJavaHome() 2330 { 2331 try 2332 { 2333 // This isn't likely to happen, and it's not a serious problem even if 2334 // it does. 2335 InstallerHelper helper = new InstallerHelper(); 2336 helper.writeSetOpenDSJavaHome(getUserData(), getInstallationPath()); 2337 } 2338 catch (Exception e) 2339 { 2340 logger.warn(LocalizableMessage.raw("Error writing OpenDJ Java Home file: " + e, e)); 2341 } 2342 } 2343 2344 /** 2345 * These methods validate the data provided by the user in the panels and 2346 * update the userData object according to that content. 2347 * 2348 * @param cStep 2349 * the current step of the wizard 2350 * @param qs 2351 * QuickStart controller 2352 * @throws UserDataException 2353 * if the data provided by the user is not valid. 2354 */ 2355 @Override 2356 public void updateUserData(WizardStep cStep, QuickSetup qs) throws UserDataException 2357 { 2358 if (cStep == SERVER_SETTINGS) 2359 { 2360 updateUserDataForServerSettingsPanel(qs); 2361 } 2362 else if (cStep == REPLICATION_OPTIONS) 2363 { 2364 updateUserDataForReplicationOptionsPanel(qs); 2365 } 2366 else if (cStep == CREATE_GLOBAL_ADMINISTRATOR) 2367 { 2368 updateUserDataForCreateAdministratorPanel(qs); 2369 } 2370 else if (cStep == SUFFIXES_OPTIONS) 2371 { 2372 updateUserDataForSuffixesOptionsPanel(qs); 2373 } 2374 else if (cStep == REMOTE_REPLICATION_PORTS) 2375 { 2376 updateUserDataForRemoteReplicationPorts(qs); 2377 } 2378 else if (cStep == NEW_SUFFIX_OPTIONS) 2379 { 2380 updateUserDataForNewSuffixOptionsPanel(qs); 2381 } 2382 else if (cStep == RUNTIME_OPTIONS) 2383 { 2384 updateUserDataForRuntimeOptionsPanel(qs); 2385 } 2386 else if (cStep == REVIEW) 2387 { 2388 updateUserDataForReviewPanel(qs); 2389 } 2390 } 2391 2392 /** 2393 * Sets the current progress step of the installation process. 2394 * 2395 * @param currentProgressStep 2396 * the current progress step of the installation process. 2397 */ 2398 private void setCurrentProgressStep(InstallProgressStep currentProgressStep) 2399 { 2400 if (currentProgressStep != null) 2401 { 2402 this.completedProgress.add(currentProgressStep); 2403 } 2404 this.currentProgressStep = currentProgressStep; 2405 } 2406 2407 /** 2408 * This methods updates the data on the server based on the contents of the 2409 * UserData object provided in the constructor. 2410 * 2411 * @throws ApplicationException 2412 * if something goes wrong. 2413 */ 2414 private void createData() throws ApplicationException 2415 { 2416 if (createNotReplicatedSuffix() 2417 && NewSuffixOptions.Type.LEAVE_DATABASE_EMPTY != getUserData().getNewSuffixOptions().getType()) 2418 { 2419 currentProgressStep = getUserData().getNewSuffixOptions().getInstallProgressStep(); 2420 if (isVerbose()) 2421 { 2422 notifyListeners(getTaskSeparator()); 2423 } 2424 2425 switch (getUserData().getNewSuffixOptions().getType()) 2426 { 2427 case CREATE_BASE_ENTRY: 2428 createBaseEntry(); 2429 break; 2430 case IMPORT_FROM_LDIF_FILE: 2431 importLDIF(); 2432 break; 2433 case IMPORT_AUTOMATICALLY_GENERATED_DATA: 2434 importAutomaticallyGenerated(); 2435 break; 2436 default: 2437 break; 2438 } 2439 } 2440 } 2441 2442 /** 2443 * This method initialize the contents of the synchronized servers with the 2444 * contents of the first server we find. 2445 * 2446 * @throws ApplicationException 2447 * if something goes wrong. 2448 */ 2449 private void initializeSuffixes() throws ApplicationException 2450 { 2451 ConnectionWrapper conn = null; 2452 try 2453 { 2454 conn = createLocalConnection(); 2455 } 2456 catch (Throwable t) 2457 { 2458 LocalizableMessage failedMsg = getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), t); 2459 StaticUtils.close(conn); 2460 throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, failedMsg, t); 2461 } 2462 2463 Set<SuffixDescriptor> suffixes = getUserData().getSuffixesToReplicateOptions().getSuffixes(); 2464 2465 /* Initialize local ADS and schema contents using any replica. */ 2466 { 2467 ServerDescriptor server = suffixes.iterator().next().getReplicas().iterator().next().getServer(); 2468 try (ConnectionWrapper remoteConn = getRemoteConnection(server)) 2469 { 2470 TopologyCacheFilter filter = new TopologyCacheFilter(); 2471 filter.setSearchMonitoringInformation(false); 2472 filter.addBaseDNToSearch(ADSContext.getAdministrationSuffixDN()); 2473 filter.addBaseDNToSearch(Constants.SCHEMA_DN); 2474 ServerDescriptor s = createStandalone(remoteConn.getLdapContext(), filter); 2475 for (ReplicaDescriptor replica : s.getReplicas()) 2476 { 2477 String dn = replica.getSuffix().getDN(); 2478 if (areDnsEqual(dn, ADSContext.getAdministrationSuffixDN())) 2479 { 2480 suffixes.add(replica.getSuffix()); 2481 } 2482 else if (areDnsEqual(dn, Constants.SCHEMA_DN)) 2483 { 2484 suffixes.add(replica.getSuffix()); 2485 } 2486 } 2487 } 2488 catch (NamingException ne) 2489 { 2490 LocalizableMessage msg; 2491 if (isCertificateException(ne)) 2492 { 2493 msg = INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(getHostPort(server), ne.toString(true)); 2494 } 2495 else 2496 { 2497 msg = INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(getHostPort(server), ne.toString(true)); 2498 } 2499 throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg, ne); 2500 } 2501 } 2502 2503 for (SuffixDescriptor suffix : suffixes) 2504 { 2505 String dn = suffix.getDN(); 2506 2507 ReplicaDescriptor replica = suffix.getReplicas().iterator().next(); 2508 ServerDescriptor server = replica.getServer(); 2509 HostPort hostPort = getHostPort(server); 2510 2511 boolean isADS = areDnsEqual(dn, ADSContext.getAdministrationSuffixDN()); 2512 boolean isSchema = areDnsEqual(dn, Constants.SCHEMA_DN); 2513 if (isADS) 2514 { 2515 if (isVerbose()) 2516 { 2517 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_INITIALIZING_ADS.get())); 2518 } 2519 } 2520 else if (isSchema) 2521 { 2522 if (isVerbose()) 2523 { 2524 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_INITIALIZING_SCHEMA.get())); 2525 } 2526 } 2527 else 2528 { 2529 notifyListeners(getFormattedProgress(INFO_PROGRESS_INITIALIZING_SUFFIX.get(dn, hostPort))); 2530 notifyListeners(getLineBreak()); 2531 } 2532 try 2533 { 2534 int replicationId = replica.getReplicationId(); 2535 if (replicationId == -1) 2536 { 2537 // This occurs if the remote server had not replication configured. 2538 try (ConnectionWrapper remoteConn = getRemoteConnection(server)) 2539 { 2540 TopologyCacheFilter filter = new TopologyCacheFilter(); 2541 filter.setSearchMonitoringInformation(false); 2542 filter.addBaseDNToSearch(dn); 2543 ServerDescriptor s = createStandalone(remoteConn.getLdapContext(), filter); 2544 for (ReplicaDescriptor r : s.getReplicas()) 2545 { 2546 if (areDnsEqual(r.getSuffix().getDN(), dn)) 2547 { 2548 replicationId = r.getReplicationId(); 2549 } 2550 } 2551 } 2552 catch (NamingException ne) 2553 { 2554 LocalizableMessage msg; 2555 if (isCertificateException(ne)) 2556 { 2557 msg = INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(getHostPort(server), ne.toString(true)); 2558 } 2559 else 2560 { 2561 msg = INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(getHostPort(server), ne.toString(true)); 2562 } 2563 throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg, ne); 2564 } 2565 } 2566 if (replicationId == -1) 2567 { 2568 throw new ApplicationException(ReturnCode.APPLICATION_ERROR, ERR_COULD_NOT_FIND_REPLICATIONID.get(dn), null); 2569 } 2570 StaticUtils.sleep(3000); 2571 int nTries = 5; 2572 boolean initDone = false; 2573 while (!initDone) 2574 { 2575 try 2576 { 2577 logger.info(LocalizableMessage.raw("Calling initializeSuffix with base DN: " + dn)); 2578 logger.info(LocalizableMessage.raw("Try number: " + (6 - nTries))); 2579 logger.info(LocalizableMessage.raw("replicationId of source replica: " + replicationId)); 2580 initializeSuffix(conn.getLdapContext(), replicationId, dn, !isADS && !isSchema, hostPort); 2581 initDone = true; 2582 } 2583 catch (PeerNotFoundException pnfe) 2584 { 2585 logger.info(LocalizableMessage.raw("Peer could not be found")); 2586 if (nTries == 1) 2587 { 2588 throw new ApplicationException(ReturnCode.APPLICATION_ERROR, pnfe.getMessageObject(), null); 2589 } 2590 StaticUtils.sleep((5 - nTries) * 3000); 2591 } 2592 nTries--; 2593 } 2594 } 2595 catch (ApplicationException ae) 2596 { 2597 StaticUtils.close(conn); 2598 throw ae; 2599 } 2600 if ((isADS || isSchema) && isVerbose()) 2601 { 2602 notifyListeners(getFormattedDone()); 2603 notifyListeners(getLineBreak()); 2604 } 2605 checkAbort(); 2606 } 2607 } 2608 2609 /** 2610 * This method updates the ADS contents (and creates the according suffixes). 2611 * If the user specified an existing topology, the new instance is registered 2612 * with that ADS (the ADS might need to be created), and the local ADS will be 2613 * populated when the local server is added to the remote server's ADS 2614 * replication domain in a subsequent step. Otherwise, an ADS is created on 2615 * the new instance and the server is registered with the new ADS. NOTE: this 2616 * method assumes that the local server and any remote server are running. 2617 * 2618 * @throws ApplicationException 2619 * if something goes wrong. 2620 */ 2621 private void updateADS() throws ApplicationException 2622 { 2623 DataReplicationOptions repl = getUserData().getReplicationOptions(); 2624 boolean isRemoteServer = repl.getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY; 2625 AuthenticationData auth = isRemoteServer ? repl.getAuthenticationData() : null; 2626 ConnectionWrapper remoteConn = null; // Bound to remote ADS host (if any). 2627 ConnectionWrapper localConn = null; // Bound to local server. 2628 ADSContext adsContext = null; // Bound to ADS host (via one of above). 2629 2630 /* 2631 * Outer try-catch-finally to convert occurrences of NamingException and 2632 * ADSContextException to ApplicationException and clean up JNDI contexts. 2633 */ 2634 try 2635 { 2636 if (isRemoteServer) 2637 { 2638 remoteConn = createConnection(auth); 2639 adsContext = new ADSContext(remoteConn); // adsContext owns remoteCtx 2640 2641 /* 2642 * Check the remote server for ADS. If it does not exist, create the 2643 * initial ADS there and register the server with itself. 2644 */ 2645 if (!adsContext.hasAdminData()) 2646 { 2647 if (isVerbose()) 2648 { 2649 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CREATING_ADS_ON_REMOTE.get(auth.getHostPort()))); 2650 } 2651 2652 adsContext.createAdminData(null); 2653 TopologyCacheFilter filter = new TopologyCacheFilter(); 2654 filter.setSearchMonitoringInformation(false); 2655 filter.setSearchBaseDNInformation(false); 2656 ServerDescriptor server = createStandalone(remoteConn.getLdapContext(), filter); 2657 server.updateAdsPropertiesWithServerProperties(); 2658 adsContext.registerServer(server.getAdsProperties()); 2659 createdRemoteAds = true; 2660 if (isVerbose()) 2661 { 2662 notifyListeners(getFormattedDoneWithLineBreak()); 2663 } 2664 checkAbort(); 2665 } 2666 } 2667 2668 /* Act on local server depending on if using remote or local ADS */ 2669 if (isVerbose()) 2670 { 2671 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CREATING_ADS.get())); 2672 } 2673 localConn = createLocalConnection(); 2674 if (!isRemoteServer) 2675 { 2676 /* Configure local server to have an ADS */ 2677 adsContext = new ADSContext(localConn); // adsContext owns localCtx 2678 adsContext.createAdminData(null); 2679 } 2680 /* Register new server in ADS. */ 2681 TopologyCacheFilter filter = new TopologyCacheFilter(); 2682 filter.setSearchMonitoringInformation(false); 2683 filter.setSearchBaseDNInformation(false); 2684 ServerDescriptor server = createStandalone(localConn.getLdapContext(), filter); 2685 server.updateAdsPropertiesWithServerProperties(); 2686 if (0 == adsContext.registerOrUpdateServer(server.getAdsProperties())) 2687 { 2688 if (isRemoteServer) 2689 { 2690 registeredNewServerOnRemote = true; 2691 } 2692 } 2693 else 2694 { 2695 logger.warn(LocalizableMessage.raw("Server was already registered. Updating " + "server registration.")); 2696 } 2697 if (isRemoteServer) 2698 { 2699 seedAdsTrustStore(localConn.getLdapContext(), adsContext.getTrustedCertificates()); 2700 } 2701 if (isVerbose()) 2702 { 2703 notifyListeners(getFormattedDoneWithLineBreak()); 2704 } 2705 checkAbort(); 2706 2707 /* Add global administrator if the user specified one. */ 2708 if (getUserData().mustCreateAdministrator()) 2709 { 2710 try 2711 { 2712 if (isVerbose()) 2713 { 2714 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CREATING_ADMINISTRATOR.get())); 2715 } 2716 adsContext.createAdministrator(getAdministratorProperties(getUserData())); 2717 if (isRemoteServer && !createdRemoteAds) 2718 { 2719 createdAdministrator = true; 2720 } 2721 if (isVerbose()) 2722 { 2723 notifyListeners(getFormattedDoneWithLineBreak()); 2724 } 2725 checkAbort(); 2726 } 2727 catch (ADSContextException ade) 2728 { 2729 if (ade.getError() == ADSContextException.ErrorType.ALREADY_REGISTERED) 2730 { 2731 notifyListeners(getFormattedWarning(INFO_ADMINISTRATOR_ALREADY_REGISTERED.get())); 2732 adsContext.unregisterServer(server.getAdsProperties()); 2733 adsContext.registerServer(server.getAdsProperties()); 2734 } 2735 else 2736 { 2737 throw ade; 2738 } 2739 } 2740 } 2741 } 2742 catch (NamingException ne) 2743 { 2744 LocalizableMessage msg; 2745 if (isRemoteServer) 2746 { 2747 msg = getMessageForException(ne, auth.getHostPort().toString()); 2748 } 2749 else 2750 { 2751 msg = Utils.getMessageForException(ne); 2752 } 2753 throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg, ne); 2754 } 2755 catch (ADSContextException ace) 2756 { 2757 throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, (isRemoteServer ? INFO_REMOTE_ADS_EXCEPTION.get( 2758 auth.getHostPort(), ace.getMessageObject()) : INFO_ADS_EXCEPTION.get(ace)), ace); 2759 } 2760 finally 2761 { 2762 StaticUtils.close(remoteConn, localConn); 2763 } 2764 } 2765 2766 private ConnectionWrapper createConnection(AuthenticationData auth) throws NamingException 2767 { 2768 String ldapUrl = auth.getLdapUrl(); 2769 String dn = auth.getDn(); 2770 String pwd = auth.getPwd(); 2771 2772 if (auth.useSecureConnection()) 2773 { 2774 ApplicationTrustManager trustManager = getTrustManager(); 2775 trustManager.setHost(auth.getHostPort().getHost()); 2776 return new ConnectionWrapper(ldapUrl, LDAPS, dn, pwd, getConnectTimeout(), getTrustManager()); 2777 } 2778 else 2779 { 2780 return new ConnectionWrapper(ldapUrl, LDAP, dn, pwd, getConnectTimeout(), getTrustManager()); 2781 } 2782 } 2783 2784 /** 2785 * Tells whether we must create a suffix that we are not going to replicate 2786 * with other servers or not. 2787 * 2788 * @return {@code true} if we must create a new suffix and {@code false} otherwise. 2789 */ 2790 private boolean createNotReplicatedSuffix() 2791 { 2792 DataReplicationOptions repl = getUserData().getReplicationOptions(); 2793 2794 SuffixesToReplicateOptions suf = getUserData().getSuffixesToReplicateOptions(); 2795 2796 return repl.getType() == DataReplicationOptions.Type.FIRST_IN_TOPOLOGY 2797 || repl.getType() == DataReplicationOptions.Type.STANDALONE 2798 || suf.getType() == SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY; 2799 } 2800 2801 /** 2802 * Returns whether we must configure replication. 2803 * 2804 * @return {@code true} if we must configure replication and {@code false} otherwise. 2805 */ 2806 private boolean mustConfigureReplication() 2807 { 2808 return getUserData().getReplicationOptions().getType() != DataReplicationOptions.Type.STANDALONE; 2809 } 2810 2811 /** 2812 * Returns whether we must create the ADS. 2813 * 2814 * @return {@code true} if we must create the ADS and {@code false} otherwise. 2815 */ 2816 private boolean mustCreateAds() 2817 { 2818 return getUserData().getReplicationOptions().getType() != DataReplicationOptions.Type.STANDALONE; 2819 } 2820 2821 /** 2822 * Returns whether we must start the server. 2823 * 2824 * @return {@code true} if we must start the server and {@code false} otherwise. 2825 */ 2826 private boolean mustStart() 2827 { 2828 return getUserData().getStartServer() || mustCreateAds(); 2829 } 2830 2831 /** 2832 * Returns whether the start server must be launched in verbose mode. 2833 * <p> 2834 * The verbose flag is not enough because in the case where many entries have been imported, 2835 * the startup phase can take long. 2836 * 2837 * @return {@code true} if the start server must be launched in verbose mode and {@code false} otherwise. 2838 */ 2839 private boolean isStartVerbose() 2840 { 2841 if (isVerbose()) 2842 { 2843 return true; 2844 } 2845 boolean manyEntriesToImport = false; 2846 NewSuffixOptions.Type type = getUserData().getNewSuffixOptions().getType(); 2847 if (type == NewSuffixOptions.Type.IMPORT_FROM_LDIF_FILE) 2848 { 2849 long mbTotalSize = 0; 2850 LinkedList<String> ldifPaths = getUserData().getNewSuffixOptions().getLDIFPaths(); 2851 for (String ldifPath : ldifPaths) 2852 { 2853 File f = new File(ldifPath); 2854 mbTotalSize += f.length(); 2855 } 2856 // Assume entries of 1kb 2857 if (mbTotalSize > THRESHOLD_VERBOSE_START * 1024) 2858 { 2859 manyEntriesToImport = true; 2860 } 2861 } 2862 else if (type == NewSuffixOptions.Type.IMPORT_AUTOMATICALLY_GENERATED_DATA) 2863 { 2864 int nEntries = getUserData().getNewSuffixOptions().getNumberEntries(); 2865 if (nEntries > THRESHOLD_VERBOSE_START) 2866 { 2867 manyEntriesToImport = true; 2868 } 2869 } 2870 return manyEntriesToImport; 2871 } 2872 2873 /** 2874 * Returns whether we must stop the server. 2875 * <p> 2876 * The server might be stopped if the user asked not to start it at the end 2877 * of the installation and it was started temporarily to update its configuration. 2878 * 2879 * @return {@code true} if we must stop the server and {@code false} otherwise. 2880 */ 2881 private boolean mustStop() 2882 { 2883 return !getUserData().getStartServer() && mustCreateAds(); 2884 } 2885 2886 /** 2887 * Returns whether we must initialize suffixes. 2888 * 2889 * @return {@code true} if we must initialize suffixes and {@code false} otherwise. 2890 */ 2891 private boolean mustInitializeSuffixes() 2892 { 2893 return getUserData().getReplicationOptions().getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY; 2894 } 2895 2896 /** 2897 * Returns the list of preferred URLs to connect to remote servers. In fact it 2898 * returns only the URL to the remote server specified by the user in the 2899 * replication options panel. The method returns a list for convenience with 2900 * other interfaces. 2901 * <p> 2902 * NOTE: this method assumes that the UserData object has 2903 * already been updated with the host and port of the remote server. 2904 * 2905 * @return the list of preferred URLs to connect to remote servers. 2906 */ 2907 private Set<PreferredConnection> getPreferredConnections() 2908 { 2909 Set<PreferredConnection> cnx = new LinkedHashSet<>(); 2910 DataReplicationOptions repl = getUserData().getReplicationOptions(); 2911 if (repl.getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY) 2912 { 2913 AuthenticationData auth = repl.getAuthenticationData(); 2914 if (auth != null) 2915 { 2916 PreferredConnection.Type type; 2917 if (auth.useSecureConnection()) 2918 { 2919 type = PreferredConnection.Type.LDAPS; 2920 } 2921 else 2922 { 2923 type = PreferredConnection.Type.LDAP; 2924 } 2925 cnx.add(new PreferredConnection(auth.getLdapUrl(), type)); 2926 } 2927 } 2928 return cnx; 2929 } 2930 2931 private Map<ADSContext.ServerProperty, Object> getNewServerAdsProperties(UserData userData) 2932 { 2933 Map<ADSContext.ServerProperty, Object> serverProperties = new HashMap<>(); 2934 serverProperties.put(ADSContext.ServerProperty.HOST_NAME, userData.getHostName()); 2935 serverProperties.put(ADSContext.ServerProperty.LDAP_PORT, String.valueOf(userData.getServerPort())); 2936 serverProperties.put(ADSContext.ServerProperty.LDAP_ENABLED, "true"); 2937 2938 // TODO: even if the user does not configure SSL maybe we should choose 2939 // a secure port that is not being used and that we can actually use. 2940 SecurityOptions sec = userData.getSecurityOptions(); 2941 if (sec.getEnableSSL()) 2942 { 2943 serverProperties.put(ADSContext.ServerProperty.LDAPS_PORT, String.valueOf(sec.getSslPort())); 2944 serverProperties.put(ADSContext.ServerProperty.LDAPS_ENABLED, "true"); 2945 } 2946 else 2947 { 2948 serverProperties.put(ADSContext.ServerProperty.LDAPS_PORT, "636"); 2949 serverProperties.put(ADSContext.ServerProperty.LDAPS_ENABLED, "false"); 2950 } 2951 2952 if (sec.getEnableStartTLS()) 2953 { 2954 serverProperties.put(ADSContext.ServerProperty.STARTTLS_ENABLED, "true"); 2955 } 2956 else 2957 { 2958 serverProperties.put(ADSContext.ServerProperty.STARTTLS_ENABLED, "false"); 2959 } 2960 2961 serverProperties.put(ADSContext.ServerProperty.JMX_PORT, "1689"); 2962 serverProperties.put(ADSContext.ServerProperty.JMX_ENABLED, "false"); 2963 2964 serverProperties.put(ADSContext.ServerProperty.INSTANCE_PATH, getInstallPathFromClasspath()); 2965 2966 String serverID = serverProperties.get(ADSContext.ServerProperty.HOST_NAME) + ":" + userData.getServerPort(); 2967 2968 /* TODO: do we want to ask this specifically to the user? */ 2969 serverProperties.put(ADSContext.ServerProperty.ID, serverID); 2970 serverProperties.put(ADSContext.ServerProperty.HOST_OS, OperatingSystem.getOperatingSystem().toString()); 2971 2972 return serverProperties; 2973 } 2974 2975 private Map<ADSContext.AdministratorProperty, Object> getAdministratorProperties(UserData userData) 2976 { 2977 Map<ADSContext.AdministratorProperty, Object> adminProperties = new HashMap<>(); 2978 adminProperties.put(ADSContext.AdministratorProperty.UID, userData.getGlobalAdministratorUID()); 2979 adminProperties.put(ADSContext.AdministratorProperty.PASSWORD, userData.getGlobalAdministratorPassword()); 2980 adminProperties.put(ADSContext.AdministratorProperty.DESCRIPTION, 2981 INFO_GLOBAL_ADMINISTRATOR_DESCRIPTION.get().toString()); 2982 return adminProperties; 2983 } 2984 2985 /** 2986 * Validate the data provided by the user in the server settings panel and 2987 * update the userData object according to that content. 2988 * 2989 * @throws UserDataException 2990 * if the data provided by the user is not valid. 2991 */ 2992 private void updateUserDataForServerSettingsPanel(QuickSetup qs) throws UserDataException 2993 { 2994 List<LocalizableMessage> errorMsgs = new ArrayList<>(); 2995 2996 // Check the host is not empty. 2997 // TODO: check that the host name is valid... 2998 String hostName = qs.getFieldStringValue(FieldName.HOST_NAME); 2999 if (hostName == null || hostName.trim().length() == 0) 3000 { 3001 errorMsgs.add(INFO_EMPTY_HOST_NAME.get()); 3002 qs.displayFieldInvalid(FieldName.HOST_NAME, true); 3003 } 3004 else 3005 { 3006 qs.displayFieldInvalid(FieldName.HOST_NAME, false); 3007 getUserData().setHostName(hostName); 3008 } 3009 3010 // Check the port 3011 String sPort = qs.getFieldStringValue(FieldName.SERVER_PORT); 3012 int port = -1; 3013 try 3014 { 3015 port = Integer.parseInt(sPort); 3016 if (port < MIN_PORT_VALUE || port > MAX_PORT_VALUE) 3017 { 3018 errorMsgs.add(INFO_INVALID_PORT_VALUE_RANGE.get(MIN_PORT_VALUE, MAX_PORT_VALUE)); 3019 qs.displayFieldInvalid(FieldName.SERVER_PORT, true); 3020 } 3021 else if (!canUseAsPort(port)) 3022 { 3023 errorMsgs.add(getCannotBindErrorMessage(port)); 3024 qs.displayFieldInvalid(FieldName.SERVER_PORT, true); 3025 } 3026 else 3027 { 3028 getUserData().setServerPort(port); 3029 qs.displayFieldInvalid(FieldName.SERVER_PORT, false); 3030 } 3031 } 3032 catch (NumberFormatException nfe) 3033 { 3034 errorMsgs.add(INFO_INVALID_PORT_VALUE_RANGE.get(MIN_PORT_VALUE, MAX_PORT_VALUE)); 3035 qs.displayFieldInvalid(FieldName.SERVER_PORT, true); 3036 } 3037 3038 // Check the admin connector port 3039 sPort = qs.getFieldStringValue(FieldName.ADMIN_CONNECTOR_PORT); 3040 int adminConnectorPort = -1; 3041 try 3042 { 3043 adminConnectorPort = Integer.parseInt(sPort); 3044 if (adminConnectorPort < MIN_PORT_VALUE || adminConnectorPort > MAX_PORT_VALUE) 3045 { 3046 errorMsgs.add(INFO_INVALID_PORT_VALUE_RANGE.get(MIN_PORT_VALUE, MAX_PORT_VALUE)); 3047 qs.displayFieldInvalid(FieldName.ADMIN_CONNECTOR_PORT, true); 3048 } 3049 else if (!canUseAsPort(adminConnectorPort)) 3050 { 3051 errorMsgs.add(getCannotBindErrorMessage(adminConnectorPort)); 3052 qs.displayFieldInvalid(FieldName.ADMIN_CONNECTOR_PORT, true); 3053 } 3054 else if (adminConnectorPort == port) 3055 { 3056 errorMsgs.add(INFO_ADMIN_CONNECTOR_VALUE_SEVERAL_TIMES.get()); 3057 qs.displayFieldInvalid(FieldName.SERVER_PORT, true); 3058 qs.displayFieldInvalid(FieldName.ADMIN_CONNECTOR_PORT, true); 3059 } 3060 else 3061 { 3062 getUserData().setAdminConnectorPort(adminConnectorPort); 3063 qs.displayFieldInvalid(FieldName.ADMIN_CONNECTOR_PORT, false); 3064 } 3065 } 3066 catch (NumberFormatException nfe) 3067 { 3068 errorMsgs.add(INFO_INVALID_PORT_VALUE_RANGE.get(MIN_PORT_VALUE, MAX_PORT_VALUE)); 3069 qs.displayFieldInvalid(FieldName.ADMIN_CONNECTOR_PORT, true); 3070 } 3071 3072 // Check the secure port 3073 SecurityOptions sec = (SecurityOptions) qs.getFieldValue(FieldName.SECURITY_OPTIONS); 3074 int securePort = sec.getSslPort(); 3075 if (sec.getEnableSSL()) 3076 { 3077 if (securePort < MIN_PORT_VALUE || securePort > MAX_PORT_VALUE) 3078 { 3079 errorMsgs.add(INFO_INVALID_SECURE_PORT_VALUE_RANGE.get(MIN_PORT_VALUE, MAX_PORT_VALUE)); 3080 qs.displayFieldInvalid(FieldName.SECURITY_OPTIONS, true); 3081 } 3082 else if (!canUseAsPort(securePort)) 3083 { 3084 errorMsgs.add(getCannotBindErrorMessage(securePort)); 3085 qs.displayFieldInvalid(FieldName.SECURITY_OPTIONS, true); 3086 } 3087 else if (port == securePort) 3088 { 3089 errorMsgs.add(INFO_EQUAL_PORTS.get()); 3090 qs.displayFieldInvalid(FieldName.SECURITY_OPTIONS, true); 3091 qs.displayFieldInvalid(FieldName.SERVER_PORT, true); 3092 } 3093 else if (adminConnectorPort == securePort) 3094 { 3095 errorMsgs.add(INFO_ADMIN_CONNECTOR_VALUE_SEVERAL_TIMES.get()); 3096 qs.displayFieldInvalid(FieldName.SECURITY_OPTIONS, true); 3097 qs.displayFieldInvalid(FieldName.ADMIN_CONNECTOR_PORT, true); 3098 } 3099 else 3100 { 3101 getUserData().setSecurityOptions(sec); 3102 qs.displayFieldInvalid(FieldName.SECURITY_OPTIONS, false); 3103 } 3104 } 3105 else 3106 { 3107 getUserData().setSecurityOptions(sec); 3108 qs.displayFieldInvalid(FieldName.SECURITY_OPTIONS, false); 3109 } 3110 3111 // Check the Directory Manager DN 3112 String dmDn = qs.getFieldStringValue(FieldName.DIRECTORY_MANAGER_DN); 3113 3114 if (dmDn == null || dmDn.trim().length() == 0) 3115 { 3116 errorMsgs.add(INFO_EMPTY_DIRECTORY_MANAGER_DN.get()); 3117 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true); 3118 } 3119 else if (!isDN(dmDn)) 3120 { 3121 errorMsgs.add(INFO_NOT_A_DIRECTORY_MANAGER_DN.get()); 3122 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true); 3123 } 3124 else if (isConfigurationDn(dmDn)) 3125 { 3126 errorMsgs.add(INFO_DIRECTORY_MANAGER_DN_IS_CONFIG_DN.get()); 3127 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true); 3128 } 3129 else 3130 { 3131 getUserData().setDirectoryManagerDn(dmDn); 3132 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, false); 3133 } 3134 3135 // Check the provided passwords 3136 String pwd1 = qs.getFieldStringValue(FieldName.DIRECTORY_MANAGER_PWD); 3137 String pwd2 = qs.getFieldStringValue(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM); 3138 if (pwd1 == null) 3139 { 3140 pwd1 = ""; 3141 } 3142 3143 boolean pwdValid = true; 3144 if (!pwd1.equals(pwd2)) 3145 { 3146 errorMsgs.add(INFO_NOT_EQUAL_PWD.get()); 3147 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, true); 3148 pwdValid = false; 3149 } 3150 if (pwd1.length() < MIN_DIRECTORY_MANAGER_PWD) 3151 { 3152 errorMsgs.add(INFO_PWD_TOO_SHORT.get(MIN_DIRECTORY_MANAGER_PWD)); 3153 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD, true); 3154 if (pwd2 == null || pwd2.length() < MIN_DIRECTORY_MANAGER_PWD) 3155 { 3156 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, true); 3157 } 3158 pwdValid = false; 3159 } 3160 3161 if (pwdValid) 3162 { 3163 getUserData().setDirectoryManagerPwd(pwd1); 3164 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD, false); 3165 qs.displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, false); 3166 } 3167 3168 // For the moment do not enable JMX 3169 int defaultJMXPort = UserData.getDefaultJMXPort(new int[] { port, securePort }); 3170 if (defaultJMXPort != -1) 3171 { 3172 //getUserData().setServerJMXPort(defaultJMXPort); 3173 getUserData().setServerJMXPort(-1); 3174 } 3175 3176 if (!errorMsgs.isEmpty()) 3177 { 3178 throw new UserDataException(Step.SERVER_SETTINGS, getMessageFromCollection(errorMsgs, "\n")); 3179 } 3180 } 3181 3182 private LocalizableMessage getCannotBindErrorMessage(int port) 3183 { 3184 if (isPrivilegedPort(port)) 3185 { 3186 return INFO_CANNOT_BIND_PRIVILEDGED_PORT.get(port); 3187 } 3188 return INFO_CANNOT_BIND_PORT.get(port); 3189 } 3190 3191 /** 3192 * Validate the data provided by the user in the data options panel and update 3193 * the userData object according to that content. 3194 * 3195 * @throws UserDataException 3196 * if the data provided by the user is not valid. 3197 */ 3198 private void updateUserDataForReplicationOptionsPanel(QuickSetup qs) throws UserDataException 3199 { 3200 boolean hasGlobalAdministrators = false; 3201 int replicationPort = -1; 3202 boolean secureReplication = false; 3203 Integer port = null; 3204 List<LocalizableMessage> errorMsgs = new ArrayList<>(); 3205 3206 DataReplicationOptions.Type type = (DataReplicationOptions.Type) qs.getFieldValue(FieldName.REPLICATION_OPTIONS); 3207 String host = qs.getFieldStringValue(FieldName.REMOTE_SERVER_HOST); 3208 String dn = qs.getFieldStringValue(FieldName.REMOTE_SERVER_DN); 3209 String pwd = qs.getFieldStringValue(FieldName.REMOTE_SERVER_PWD); 3210 3211 if (type != DataReplicationOptions.Type.STANDALONE) 3212 { 3213 // Check replication port 3214 replicationPort = checkReplicationPort(qs, errorMsgs); 3215 secureReplication = (Boolean) qs.getFieldValue(FieldName.REPLICATION_SECURE); 3216 } 3217 3218 UserDataConfirmationException confirmEx = null; 3219 switch (type) 3220 { 3221 case IN_EXISTING_TOPOLOGY: 3222 { 3223 String sPort = qs.getFieldStringValue(FieldName.REMOTE_SERVER_PORT); 3224 checkRemoteHostPortDnAndPwd(host, sPort, dn, pwd, qs, errorMsgs); 3225 3226 if (errorMsgs.isEmpty()) 3227 { 3228 port = Integer.parseInt(sPort); 3229 // Try to connect 3230 boolean[] globalAdmin = { hasGlobalAdministrators }; 3231 String[] effectiveDn = { dn }; 3232 try 3233 { 3234 updateUserDataWithADS(host, port, dn, pwd, qs, errorMsgs, globalAdmin, effectiveDn); 3235 } 3236 catch (UserDataConfirmationException e) 3237 { 3238 confirmEx = e; 3239 } 3240 hasGlobalAdministrators = globalAdmin[0]; 3241 dn = effectiveDn[0]; 3242 } 3243 break; 3244 } 3245 case STANDALONE: 3246 { 3247 getUserData().setSuffixesToReplicateOptions( 3248 new SuffixesToReplicateOptions(SuffixesToReplicateOptions.Type.NO_SUFFIX_TO_REPLICATE, 3249 new HashSet<SuffixDescriptor>(), new HashSet<SuffixDescriptor>())); 3250 break; 3251 } 3252 case FIRST_IN_TOPOLOGY: 3253 { 3254 getUserData().setSuffixesToReplicateOptions( 3255 new SuffixesToReplicateOptions(SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY, 3256 new HashSet<SuffixDescriptor>(), new HashSet<SuffixDescriptor>())); 3257 break; 3258 } 3259 default: 3260 throw new IllegalStateException("Do not know what to do with type: " + type); 3261 } 3262 3263 if (errorMsgs.isEmpty()) 3264 { 3265 AuthenticationData auth = new AuthenticationData(); 3266 auth.setHostPort(new HostPort("".equals(host) ? null : host, port != null ? port : 0)); 3267 auth.setDn(dn); 3268 auth.setPwd(pwd); 3269 auth.setUseSecureConnection(true); 3270 3271 getUserData().setReplicationOptions(createDataReplicationOptions(replicationPort, secureReplication, type, auth)); 3272 getUserData().createAdministrator( 3273 !hasGlobalAdministrators && type == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY); 3274 } 3275 if (!errorMsgs.isEmpty()) 3276 { 3277 throw new UserDataException(Step.REPLICATION_OPTIONS, getMessageFromCollection(errorMsgs, "\n")); 3278 } 3279 if (confirmEx != null) 3280 { 3281 throw confirmEx; 3282 } 3283 } 3284 3285 private DataReplicationOptions createDataReplicationOptions(int replicationPort, boolean secureReplication, 3286 DataReplicationOptions.Type type, AuthenticationData auth) 3287 { 3288 switch (type) 3289 { 3290 case IN_EXISTING_TOPOLOGY: 3291 return DataReplicationOptions.createInExistingTopology(auth, replicationPort, secureReplication); 3292 case STANDALONE: 3293 return DataReplicationOptions.createStandalone(); 3294 case FIRST_IN_TOPOLOGY: 3295 return DataReplicationOptions.createFirstInTopology(replicationPort, secureReplication); 3296 default: 3297 throw new IllegalStateException("Do not know what to do with type: " + type); 3298 } 3299 } 3300 3301 private int checkReplicationPort(QuickSetup qs, List<LocalizableMessage> errorMsgs) 3302 { 3303 int replicationPort = -1; 3304 String sPort = qs.getFieldStringValue(FieldName.REPLICATION_PORT); 3305 try 3306 { 3307 replicationPort = Integer.parseInt(sPort); 3308 if (replicationPort < MIN_PORT_VALUE || replicationPort > MAX_PORT_VALUE) 3309 { 3310 errorMsgs.add(INFO_INVALID_REPLICATION_PORT_VALUE_RANGE.get(MIN_PORT_VALUE, MAX_PORT_VALUE)); 3311 qs.displayFieldInvalid(FieldName.SERVER_PORT, true); 3312 } 3313 else if (!canUseAsPort(replicationPort)) 3314 { 3315 errorMsgs.add(getCannotBindErrorMessage(replicationPort)); 3316 qs.displayFieldInvalid(FieldName.REPLICATION_PORT, true); 3317 } 3318 else 3319 { 3320 /* Check that we did not chose this port for another protocol */ 3321 SecurityOptions sec = getUserData().getSecurityOptions(); 3322 if (replicationPort == getUserData().getServerPort() || replicationPort == getUserData().getServerJMXPort() 3323 || (replicationPort == sec.getSslPort() && sec.getEnableSSL())) 3324 { 3325 errorMsgs.add(INFO_REPLICATION_PORT_ALREADY_CHOSEN_FOR_OTHER_PROTOCOL.get()); 3326 qs.displayFieldInvalid(FieldName.REPLICATION_PORT, true); 3327 } 3328 else 3329 { 3330 qs.displayFieldInvalid(FieldName.REPLICATION_PORT, false); 3331 } 3332 } 3333 } 3334 catch (NumberFormatException nfe) 3335 { 3336 errorMsgs.add(INFO_INVALID_REPLICATION_PORT_VALUE_RANGE.get(MIN_PORT_VALUE, MAX_PORT_VALUE)); 3337 qs.displayFieldInvalid(FieldName.REPLICATION_PORT, true); 3338 } 3339 return replicationPort; 3340 } 3341 3342 private void checkRemoteHostPortDnAndPwd(String host, String sPort, String dn, String pwd, QuickSetup qs, 3343 List<LocalizableMessage> errorMsgs) 3344 { 3345 // Check host 3346 if (host == null || host.length() == 0) 3347 { 3348 errorMsgs.add(INFO_EMPTY_REMOTE_HOST.get()); 3349 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, true); 3350 } 3351 else 3352 { 3353 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, false); 3354 } 3355 3356 // Check port 3357 try 3358 { 3359 Integer.parseInt(sPort); 3360 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, false); 3361 } 3362 catch (Throwable t) 3363 { 3364 errorMsgs.add(INFO_INVALID_REMOTE_PORT.get()); 3365 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, true); 3366 } 3367 3368 // Check dn 3369 if (dn == null || dn.length() == 0) 3370 { 3371 errorMsgs.add(INFO_EMPTY_REMOTE_DN.get()); 3372 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true); 3373 } 3374 else 3375 { 3376 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, false); 3377 } 3378 3379 // Check password 3380 if (pwd == null || pwd.length() == 0) 3381 { 3382 errorMsgs.add(INFO_EMPTY_REMOTE_PWD.get()); 3383 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true); 3384 } 3385 else 3386 { 3387 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, false); 3388 } 3389 } 3390 3391 private void updateUserDataWithADS(String host, int port, String dn, String pwd, QuickSetup qs, 3392 List<LocalizableMessage> errorMsgs, boolean[] hasGlobalAdministrators, String[] effectiveDn) 3393 throws UserDataException 3394 { 3395 host = getHostNameForLdapUrl(host); 3396 HostPort hostPort = new HostPort(host, port); 3397 3398 ApplicationTrustManager trustManager = getTrustManager(); 3399 trustManager.setHost(host); 3400 trustManager.resetLastRefusedItems(); 3401 try (ConnectionWrapper conn = newConnectionWrapper(dn, pwd, effectiveDn, hostPort, trustManager)) 3402 { 3403 ADSContext adsContext = new ADSContext(conn); 3404 if (adsContext.hasAdminData()) 3405 { 3406 /* Check if there are already global administrators */ 3407 Set<?> administrators = adsContext.readAdministratorRegistry(); 3408 hasGlobalAdministrators[0] = !administrators.isEmpty(); 3409 Set<TopologyCacheException> exceptions = updateUserDataWithSuffixesInADS(adsContext, trustManager); 3410 Set<LocalizableMessage> exceptionMsgs = new LinkedHashSet<>(); 3411 /* Check the exceptions and see if we throw them or not. */ 3412 for (TopologyCacheException e : exceptions) 3413 { 3414 switch (e.getType()) 3415 { 3416 case NOT_GLOBAL_ADMINISTRATOR: 3417 LocalizableMessage errorMsg = INFO_NOT_GLOBAL_ADMINISTRATOR_PROVIDED.get(); 3418 throw new UserDataException(Step.REPLICATION_OPTIONS, errorMsg); 3419 case GENERIC_CREATING_CONNECTION: 3420 if (isCertificateException(e.getCause())) 3421 { 3422 UserDataCertificateException.Type excType; 3423 ApplicationTrustManager.Cause cause = null; 3424 if (e.getTrustManager() != null) 3425 { 3426 cause = e.getTrustManager().getLastRefusedCause(); 3427 } 3428 logger.info(LocalizableMessage.raw("Certificate exception cause: " + cause)); 3429 if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED) 3430 { 3431 excType = UserDataCertificateException.Type.NOT_TRUSTED; 3432 } 3433 else if (cause == ApplicationTrustManager.Cause.HOST_NAME_MISMATCH) 3434 { 3435 excType = UserDataCertificateException.Type.HOST_NAME_MISMATCH; 3436 } 3437 else 3438 { 3439 excType = null; 3440 } 3441 if (excType != null) 3442 { 3443 String h; 3444 int p; 3445 try 3446 { 3447 URI uri = new URI(e.getLdapUrl()); 3448 h = uri.getHost(); 3449 p = uri.getPort(); 3450 } 3451 catch (Throwable t) 3452 { 3453 logger.warn(LocalizableMessage.raw("Error parsing ldap url of TopologyCacheException.", t)); 3454 h = INFO_NOT_AVAILABLE_LABEL.get().toString(); 3455 p = -1; 3456 } 3457 throw new UserDataCertificateException(Step.REPLICATION_OPTIONS, INFO_CERTIFICATE_EXCEPTION.get(h, p), 3458 e.getCause(), h, p, e.getTrustManager().getLastRefusedChain(), e.getTrustManager() 3459 .getLastRefusedAuthType(), excType); 3460 } 3461 } 3462 break; 3463 default: 3464 break; 3465 } 3466 exceptionMsgs.add(getMessage(e)); 3467 } 3468 if (!exceptionMsgs.isEmpty()) 3469 { 3470 LocalizableMessage confirmationMsg = 3471 INFO_ERROR_READING_REGISTERED_SERVERS_CONFIRM.get(getMessageFromCollection(exceptionMsgs, "\n")); 3472 throw new UserDataConfirmationException(Step.REPLICATION_OPTIONS, confirmationMsg); 3473 } 3474 } 3475 else 3476 { 3477 updateUserDataWithSuffixesInServer(conn.getLdapContext()); 3478 } 3479 } 3480 catch (UserDataException ude) 3481 { 3482 throw ude; 3483 } 3484 catch (Throwable t) 3485 { 3486 logger.info(LocalizableMessage.raw("Error connecting to remote server.", t)); 3487 if (isCertificateException(t)) 3488 { 3489 UserDataCertificateException.Type excType; 3490 ApplicationTrustManager.Cause cause = trustManager.getLastRefusedCause(); 3491 logger.info(LocalizableMessage.raw("Certificate exception cause: " + cause)); 3492 if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED) 3493 { 3494 excType = UserDataCertificateException.Type.NOT_TRUSTED; 3495 } 3496 else if (cause == ApplicationTrustManager.Cause.HOST_NAME_MISMATCH) 3497 { 3498 excType = UserDataCertificateException.Type.HOST_NAME_MISMATCH; 3499 } 3500 else 3501 { 3502 excType = null; 3503 } 3504 3505 if (excType != null) 3506 { 3507 throw new UserDataCertificateException(Step.REPLICATION_OPTIONS, INFO_CERTIFICATE_EXCEPTION.get(host, port), 3508 t, host, port, trustManager.getLastRefusedChain(), trustManager.getLastRefusedAuthType(), excType); 3509 } 3510 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, true); 3511 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, true); 3512 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true); 3513 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true); 3514 errorMsgs.add(INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(host + ":" + port, t)); 3515 } 3516 else if (t instanceof NamingException) 3517 { 3518 errorMsgs.add(getMessageForException((NamingException) t, host + ":" + port)); 3519 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true); 3520 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true); 3521 if (!(t instanceof NamingSecurityException)) 3522 { 3523 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, true); 3524 qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, true); 3525 } 3526 } 3527 else if (t instanceof ADSContextException) 3528 { 3529 errorMsgs.add(INFO_REMOTE_ADS_EXCEPTION.get(host + ":" + port, t)); 3530 } 3531 else 3532 { 3533 throw new UserDataException(Step.REPLICATION_OPTIONS, getThrowableMsg(INFO_BUG_MSG.get(), t)); 3534 } 3535 } 3536 } 3537 3538 private ConnectionWrapper newConnectionWrapper(String dn, String pwd, String[] effectiveDn, HostPort hostPort, 3539 ApplicationTrustManager trustManager) throws Throwable 3540 { 3541 try 3542 { 3543 effectiveDn[0] = dn; 3544 return new ConnectionWrapper(hostPort, LDAPS, dn, pwd, getConnectTimeout(), trustManager); 3545 } 3546 catch (Throwable t) 3547 { 3548 if (isCertificateException(t)) 3549 { 3550 throw t; 3551 } 3552 // Try using a global administrator 3553 dn = ADSContext.getAdministratorDN(dn); 3554 effectiveDn[0] = dn; 3555 return new ConnectionWrapper(hostPort, LDAPS, dn, pwd, getConnectTimeout(), trustManager); 3556 } 3557 } 3558 3559 /** 3560 * Validate the data provided by the user in the create global administrator 3561 * panel and update the UserInstallData object according to that content. 3562 * 3563 * @throws UserDataException 3564 * if the data provided by the user is not valid. 3565 */ 3566 private void updateUserDataForCreateAdministratorPanel(QuickSetup qs) throws UserDataException 3567 { 3568 List<LocalizableMessage> errorMsgs = new ArrayList<>(); 3569 3570 // Check the Global Administrator UID 3571 String uid = qs.getFieldStringValue(FieldName.GLOBAL_ADMINISTRATOR_UID); 3572 3573 if (uid == null || uid.trim().length() == 0) 3574 { 3575 errorMsgs.add(INFO_EMPTY_ADMINISTRATOR_UID.get()); 3576 qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_UID, true); 3577 } 3578 else 3579 { 3580 getUserData().setGlobalAdministratorUID(uid); 3581 qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_UID, false); 3582 } 3583 3584 // Check the provided passwords 3585 String pwd1 = qs.getFieldStringValue(FieldName.GLOBAL_ADMINISTRATOR_PWD); 3586 String pwd2 = qs.getFieldStringValue(FieldName.GLOBAL_ADMINISTRATOR_PWD_CONFIRM); 3587 if (pwd1 == null) 3588 { 3589 pwd1 = ""; 3590 } 3591 3592 boolean pwdValid = true; 3593 if (!pwd1.equals(pwd2)) 3594 { 3595 errorMsgs.add(INFO_NOT_EQUAL_PWD.get()); 3596 qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_PWD_CONFIRM, true); 3597 pwdValid = false; 3598 } 3599 if (pwd1.length() < MIN_DIRECTORY_MANAGER_PWD) 3600 { 3601 errorMsgs.add(INFO_PWD_TOO_SHORT.get(MIN_DIRECTORY_MANAGER_PWD)); 3602 qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_PWD, true); 3603 if (pwd2 == null || pwd2.length() < MIN_DIRECTORY_MANAGER_PWD) 3604 { 3605 qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_PWD_CONFIRM, true); 3606 } 3607 pwdValid = false; 3608 } 3609 3610 if (pwdValid) 3611 { 3612 getUserData().setGlobalAdministratorPassword(pwd1); 3613 qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_PWD, false); 3614 qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_PWD_CONFIRM, false); 3615 } 3616 3617 if (!errorMsgs.isEmpty()) 3618 { 3619 throw new UserDataException(Step.CREATE_GLOBAL_ADMINISTRATOR, getMessageFromCollection(errorMsgs, "\n")); 3620 } 3621 } 3622 3623 /** 3624 * Validate the data provided by the user in the replicate suffixes options 3625 * panel and update the UserInstallData object according to that content. 3626 * 3627 * @throws UserDataException 3628 * if the data provided by the user is not valid. 3629 */ 3630 @SuppressWarnings("unchecked") 3631 private void updateUserDataForSuffixesOptionsPanel(QuickSetup qs) throws UserDataException 3632 { 3633 List<LocalizableMessage> errorMsgs = new ArrayList<>(); 3634 if (qs.getFieldValue(FieldName.SUFFIXES_TO_REPLICATE_OPTIONS) == 3635 SuffixesToReplicateOptions.Type.REPLICATE_WITH_EXISTING_SUFFIXES) 3636 { 3637 Set<?> s = (Set<?>) qs.getFieldValue(FieldName.SUFFIXES_TO_REPLICATE); 3638 if (s.isEmpty()) 3639 { 3640 errorMsgs.add(INFO_NO_SUFFIXES_CHOSEN_TO_REPLICATE.get()); 3641 qs.displayFieldInvalid(FieldName.SUFFIXES_TO_REPLICATE, true); 3642 } 3643 else 3644 { 3645 Set<SuffixDescriptor> chosen = new HashSet<>(); 3646 for (Object o : s) 3647 { 3648 chosen.add((SuffixDescriptor) o); 3649 } 3650 qs.displayFieldInvalid(FieldName.SUFFIXES_TO_REPLICATE, false); 3651 Set<SuffixDescriptor> available = getUserData().getSuffixesToReplicateOptions().getAvailableSuffixes(); 3652 Map<String, BackendTypeUIAdapter> suffixesBackendTypes = 3653 (Map<String, BackendTypeUIAdapter>) qs.getFieldValue(FieldName.SUFFIXES_TO_REPLICATE_BACKEND_TYPE); 3654 SuffixesToReplicateOptions options = new SuffixesToReplicateOptions( 3655 SuffixesToReplicateOptions.Type.REPLICATE_WITH_EXISTING_SUFFIXES, available, chosen, suffixesBackendTypes); 3656 getUserData().setSuffixesToReplicateOptions(options); 3657 } 3658 getUserData().setRemoteWithNoReplicationPort(getRemoteWithNoReplicationPort(getUserData())); 3659 } 3660 else 3661 { 3662 Set<SuffixDescriptor> available = getUserData().getSuffixesToReplicateOptions().getAvailableSuffixes(); 3663 Set<SuffixDescriptor> chosen = getUserData().getSuffixesToReplicateOptions().getSuffixes(); 3664 SuffixesToReplicateOptions options = 3665 new SuffixesToReplicateOptions(SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY, available, chosen); 3666 getUserData().setSuffixesToReplicateOptions(options); 3667 } 3668 3669 if (!errorMsgs.isEmpty()) 3670 { 3671 throw new UserDataException(Step.SUFFIXES_OPTIONS, getMessageFromCollection(errorMsgs, "\n")); 3672 } 3673 } 3674 3675 /** 3676 * Validate the data provided by the user in the remote server replication 3677 * port panel and update the userData object according to that content. 3678 * 3679 * @throws UserDataException 3680 * if the data provided by the user is not valid. 3681 */ 3682 private void updateUserDataForRemoteReplicationPorts(QuickSetup qs) throws UserDataException 3683 { 3684 List<LocalizableMessage> errorMsgs = new ArrayList<>(); 3685 Map<ServerDescriptor, AuthenticationData> servers = getUserData().getRemoteWithNoReplicationPort(); 3686 Map<?, ?> hm = (Map<?, ?>) qs.getFieldValue(FieldName.REMOTE_REPLICATION_PORT); 3687 Map<?, ?> hmSecure = (Map<?, ?>) qs.getFieldValue(FieldName.REMOTE_REPLICATION_SECURE); 3688 for (ServerDescriptor server : servers.keySet()) 3689 { 3690 String hostName = server.getHostName(); 3691 boolean secureReplication = (Boolean) hmSecure.get(server.getId()); 3692 String sPort = (String) hm.get(server.getId()); 3693 try 3694 { 3695 int replicationPort = Integer.parseInt(sPort); 3696 if (replicationPort < MIN_PORT_VALUE || replicationPort > MAX_PORT_VALUE) 3697 { 3698 errorMsgs.add(INFO_INVALID_REMOTE_REPLICATION_PORT_VALUE_RANGE.get(getHostPort(server), MIN_PORT_VALUE, 3699 MAX_PORT_VALUE)); 3700 } 3701 if (hostName.equalsIgnoreCase(getUserData().getHostName())) 3702 { 3703 int securePort = -1; 3704 if (getUserData().getSecurityOptions().getEnableSSL()) 3705 { 3706 securePort = getUserData().getSecurityOptions().getSslPort(); 3707 } 3708 if (replicationPort == getUserData().getServerPort() || replicationPort == getUserData().getServerJMXPort() 3709 || replicationPort == getUserData().getReplicationOptions().getReplicationPort() 3710 || replicationPort == securePort) 3711 { 3712 errorMsgs.add(INFO_REMOTE_REPLICATION_PORT_ALREADY_CHOSEN_FOR_OTHER_PROTOCOL.get(getHostPort(server))); 3713 } 3714 } 3715 AuthenticationData authData = new AuthenticationData(); 3716 authData.setPort(replicationPort); 3717 authData.setUseSecureConnection(secureReplication); 3718 servers.put(server, authData); 3719 } 3720 catch (NumberFormatException nfe) 3721 { 3722 errorMsgs.add(INFO_INVALID_REMOTE_REPLICATION_PORT_VALUE_RANGE.get(hostName, MIN_PORT_VALUE, MAX_PORT_VALUE)); 3723 } 3724 } 3725 3726 if (!errorMsgs.isEmpty()) 3727 { 3728 qs.displayFieldInvalid(FieldName.REMOTE_REPLICATION_PORT, true); 3729 throw new UserDataException(Step.REMOTE_REPLICATION_PORTS, getMessageFromCollection(errorMsgs, "\n")); 3730 } 3731 else 3732 { 3733 qs.displayFieldInvalid(FieldName.REMOTE_REPLICATION_PORT, false); 3734 getUserData().setRemoteWithNoReplicationPort(servers); 3735 } 3736 } 3737 3738 /** 3739 * Validate the data provided by the user in the new suffix data options panel 3740 * and update the UserInstallData object according to that content. 3741 * 3742 * @throws UserDataException 3743 * if the data provided by the user is not valid. 3744 */ 3745 @SuppressWarnings("unchecked") 3746 private void updateUserDataForNewSuffixOptionsPanel(final QuickSetup ui) throws UserDataException 3747 { 3748 final List<LocalizableMessage> errorMsgs = new ArrayList<>(); 3749 // Singleton list with the provided baseDN (if exists and valid) 3750 List<String> baseDn = new LinkedList<>(); 3751 boolean validBaseDn = checkProvidedBaseDn(ui, baseDn, errorMsgs); 3752 final NewSuffixOptions dataOptions = checkImportData(ui, baseDn, validBaseDn, errorMsgs); 3753 3754 if (dataOptions != null) 3755 { 3756 getUserData().setBackendType((ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>) 3757 ui.getFieldValue(FieldName.BACKEND_TYPE)); 3758 getUserData().setNewSuffixOptions(dataOptions); 3759 } 3760 3761 if (!errorMsgs.isEmpty()) 3762 { 3763 throw new UserDataException(Step.NEW_SUFFIX_OPTIONS, 3764 getMessageFromCollection(errorMsgs, Constants.LINE_SEPARATOR)); 3765 } 3766 } 3767 3768 private NewSuffixOptions checkImportData(final QuickSetup ui, final List<String> baseDn, final boolean validBaseDn, 3769 final List<LocalizableMessage> errorMsgs) 3770 { 3771 if (baseDn.isEmpty()) 3772 { 3773 return NewSuffixOptions.createEmpty(baseDn); 3774 } 3775 3776 final NewSuffixOptions.Type type = (NewSuffixOptions.Type) ui.getFieldValue(FieldName.DATA_OPTIONS); 3777 switch (type) 3778 { 3779 case IMPORT_FROM_LDIF_FILE: 3780 return checkImportLDIFFile(ui, baseDn, validBaseDn, errorMsgs); 3781 3782 case IMPORT_AUTOMATICALLY_GENERATED_DATA: 3783 return checkImportGeneratedData(ui, baseDn, validBaseDn, errorMsgs); 3784 3785 default: 3786 if (validBaseDn) 3787 { 3788 return type == NewSuffixOptions.Type.CREATE_BASE_ENTRY ? NewSuffixOptions.createBaseEntry(baseDn) 3789 : NewSuffixOptions.createEmpty(baseDn); 3790 } 3791 } 3792 3793 return null; 3794 } 3795 3796 private NewSuffixOptions checkImportGeneratedData(final QuickSetup ui, final List<String> baseDn, 3797 final boolean validBaseDn, final List<LocalizableMessage> errorMsgs) 3798 { 3799 boolean fieldIsValid = true; 3800 final List<LocalizableMessage> localErrorMsgs = new LinkedList<>(); 3801 final String nEntries = ui.getFieldStringValue(FieldName.NUMBER_ENTRIES); 3802 if (nEntries == null || "".equals(nEntries.trim())) 3803 { 3804 localErrorMsgs.add(INFO_NO_NUMBER_ENTRIES.get()); 3805 fieldIsValid = false; 3806 } 3807 else 3808 { 3809 boolean nEntriesValid = false; 3810 try 3811 { 3812 int n = Integer.parseInt(nEntries); 3813 nEntriesValid = n >= MIN_NUMBER_ENTRIES && n <= MAX_NUMBER_ENTRIES; 3814 } 3815 catch (NumberFormatException nfe) 3816 { 3817 /* do nothing */ 3818 } 3819 3820 if (!nEntriesValid) 3821 { 3822 localErrorMsgs.add(INFO_INVALID_NUMBER_ENTRIES_RANGE.get(MIN_NUMBER_ENTRIES, MAX_NUMBER_ENTRIES)); 3823 fieldIsValid = false; 3824 } 3825 } 3826 3827 ui.displayFieldInvalid(FieldName.NUMBER_ENTRIES, !fieldIsValid); 3828 if (validBaseDn && localErrorMsgs.isEmpty()) 3829 { 3830 return NewSuffixOptions.createAutomaticallyGenerated(baseDn, Integer.parseInt(nEntries)); 3831 } 3832 errorMsgs.addAll(localErrorMsgs); 3833 3834 return null; 3835 } 3836 3837 private NewSuffixOptions checkImportLDIFFile(final QuickSetup ui, final List<String> baseDn, 3838 final boolean validBaseDn, final List<LocalizableMessage> errorMsgs) 3839 { 3840 final boolean fieldIsValid = false; 3841 final String ldifPath = ui.getFieldStringValue(FieldName.LDIF_PATH); 3842 if (ldifPath == null || ldifPath.trim().isEmpty()) 3843 { 3844 errorMsgs.add(INFO_NO_LDIF_PATH.get()); 3845 } 3846 else if (!fileExists(ldifPath)) 3847 { 3848 errorMsgs.add(INFO_LDIF_FILE_DOES_NOT_EXIST.get()); 3849 } 3850 else if (validBaseDn) 3851 { 3852 return NewSuffixOptions.createImportFromLDIF(baseDn, Collections.singletonList(ldifPath), null, null); 3853 } 3854 ui.displayFieldInvalid(FieldName.LDIF_PATH, !fieldIsValid); 3855 3856 return null; 3857 } 3858 3859 private boolean checkProvidedBaseDn(final QuickSetup ui, final List<String> baseDn, 3860 final List<LocalizableMessage> errorMsgs) 3861 { 3862 boolean validBaseDn = true; 3863 String dn = ui.getFieldStringValue(FieldName.DIRECTORY_BASE_DN); 3864 if (dn == null || dn.trim().length() == 0) 3865 { 3866 // Do nothing, the user does not want to provide a base DN. 3867 dn = ""; 3868 } 3869 else if (!isDN(dn)) 3870 { 3871 validBaseDn = false; 3872 errorMsgs.add(INFO_NOT_A_BASE_DN.get()); 3873 } 3874 else if (isConfigurationDn(dn)) 3875 { 3876 validBaseDn = false; 3877 errorMsgs.add(INFO_BASE_DN_IS_CONFIGURATION_DN.get()); 3878 } 3879 else 3880 { 3881 baseDn.add(dn); 3882 } 3883 ui.displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, !validBaseDn); 3884 3885 return validBaseDn; 3886 } 3887 3888 /** Update the userData object according to the content of the runtime options panel. */ 3889 private void updateUserDataForRuntimeOptionsPanel(QuickSetup qs) 3890 { 3891 getUserData().setJavaArguments(UserData.SERVER_SCRIPT_NAME, 3892 (JavaArguments) qs.getFieldValue(FieldName.SERVER_JAVA_ARGUMENTS)); 3893 getUserData().setJavaArguments(UserData.IMPORT_SCRIPT_NAME, 3894 (JavaArguments) qs.getFieldValue(FieldName.IMPORT_JAVA_ARGUMENTS)); 3895 } 3896 3897 /** Update the userData object according to the content of the review panel. */ 3898 private void updateUserDataForReviewPanel(QuickSetup qs) 3899 { 3900 Boolean b = (Boolean) qs.getFieldValue(FieldName.SERVER_START_INSTALLER); 3901 getUserData().setStartServer(b); 3902 b = (Boolean) qs.getFieldValue(FieldName.ENABLE_WINDOWS_SERVICE); 3903 getUserData().setEnableWindowsService(b); 3904 } 3905 3906 /** Update the UserInstallData with the contents we discover in the ADS. */ 3907 private Set<TopologyCacheException> updateUserDataWithSuffixesInADS(ADSContext adsContext, 3908 ApplicationTrustManager trustManager) throws TopologyCacheException 3909 { 3910 Set<TopologyCacheException> exceptions = new HashSet<>(); 3911 SuffixesToReplicateOptions suf = getUserData().getSuffixesToReplicateOptions(); 3912 SuffixesToReplicateOptions.Type type; 3913 3914 if (suf == null || suf.getType() == SuffixesToReplicateOptions.Type.NO_SUFFIX_TO_REPLICATE) 3915 { 3916 type = SuffixesToReplicateOptions.Type.NO_SUFFIX_TO_REPLICATE; 3917 } 3918 else 3919 { 3920 type = SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY; 3921 } 3922 lastLoadedCache = new TopologyCache(adsContext, trustManager, getConnectTimeout()); 3923 // We cannot use getPreferredConnections since the user data has not been updated yet. 3924 lastLoadedCache.setPreferredConnections(PreferredConnection.getPreferredConnections(adsContext.getConnection())); 3925 lastLoadedCache.reloadTopology(); 3926 Set<SuffixDescriptor> suffixes = lastLoadedCache.getSuffixes(); 3927 Set<SuffixDescriptor> moreSuffixes = null; 3928 if (suf != null) 3929 { 3930 moreSuffixes = suf.getSuffixes(); 3931 } 3932 getUserData().setSuffixesToReplicateOptions(new SuffixesToReplicateOptions(type, suffixes, moreSuffixes)); 3933 3934 /* 3935 * Analyze if we had any exception while loading servers. For the moment 3936 * only throw the exception found if the user did not provide the 3937 * Administrator DN and this caused a problem authenticating in one server 3938 * or if there is a certificate problem. 3939 */ 3940 Set<ServerDescriptor> servers = lastLoadedCache.getServers(); 3941 for (ServerDescriptor server : servers) 3942 { 3943 TopologyCacheException e = server.getLastException(); 3944 if (e != null) 3945 { 3946 exceptions.add(e); 3947 } 3948 } 3949 return exceptions; 3950 } 3951 3952 /** 3953 * Update the UserInstallData object with the contents of the server to which 3954 * we are connected with the provided InitialLdapContext. 3955 */ 3956 private void updateUserDataWithSuffixesInServer(InitialLdapContext ctx) throws NamingException 3957 { 3958 SuffixesToReplicateOptions suf = getUserData().getSuffixesToReplicateOptions(); 3959 SuffixesToReplicateOptions.Type type; 3960 Set<SuffixDescriptor> suffixes = new HashSet<>(); 3961 if (suf != null) 3962 { 3963 type = suf.getType(); 3964 } 3965 else 3966 { 3967 type = SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY; 3968 } 3969 3970 ServerDescriptor s = createStandalone(ctx, new TopologyCacheFilter()); 3971 Set<ReplicaDescriptor> replicas = s.getReplicas(); 3972 for (ReplicaDescriptor replica : replicas) 3973 { 3974 suffixes.add(replica.getSuffix()); 3975 } 3976 Set<SuffixDescriptor> moreSuffixes = null; 3977 if (suf != null) 3978 { 3979 moreSuffixes = suf.getSuffixes(); 3980 } 3981 getUserData().setSuffixesToReplicateOptions(new SuffixesToReplicateOptions(type, suffixes, moreSuffixes)); 3982 } 3983 3984 /** 3985 * Returns the keystore path to be used for generating a self-signed 3986 * certificate. 3987 * 3988 * @return the keystore path to be used for generating a self-signed 3989 * certificate. 3990 */ 3991 private String getSelfSignedKeystorePath() 3992 { 3993 return getPath2("keystore"); 3994 } 3995 3996 /** 3997 * Returns the trustmanager path to be used for generating a self-signed 3998 * certificate. 3999 * 4000 * @return the trustmanager path to be used for generating a self-signed 4001 * certificate. 4002 */ 4003 private String getTrustManagerPath() 4004 { 4005 return getPath2("truststore"); 4006 } 4007 4008 /** 4009 * Returns the path of the self-signed that we export to be able to create a 4010 * truststore. 4011 * 4012 * @return the path of the self-signed that is exported. 4013 */ 4014 private String getTemporaryCertificatePath() 4015 { 4016 return getPath2("server-cert.txt"); 4017 } 4018 4019 /** 4020 * Returns the path to be used to store the password of the keystore. 4021 * 4022 * @return the path to be used to store the password of the keystore. 4023 */ 4024 private String getKeystorePinPath() 4025 { 4026 return getPath2("keystore.pin"); 4027 } 4028 4029 private String getPath2(String relativePath) 4030 { 4031 String parentFile = getPath(getInstancePath(), Installation.CONFIG_PATH_RELATIVE); 4032 return getPath(parentFile, relativePath); 4033 } 4034 4035 /** 4036 * Returns the validity period to be used to generate the self-signed 4037 * certificate. 4038 * 4039 * @return the validity period to be used to generate the self-signed 4040 * certificate. 4041 */ 4042 private int getSelfSignedCertificateValidity() 4043 { 4044 return 20 * 365; 4045 } 4046 4047 /** 4048 * Returns the Subject DN to be used to generate the self-signed certificate. 4049 * 4050 * @return the Subject DN to be used to generate the self-signed certificate. 4051 */ 4052 private String getSelfSignedCertificateSubjectDN(KeyType keyType) 4053 { 4054 return "cn=" + Rdn.escapeValue(getUserData().getHostName()) + ",O=OpenDJ " + keyType + " Self-Signed Certificate"; 4055 } 4056 4057 /** 4058 * Returns the self-signed certificate password used for this session. This 4059 * method calls <code>createSelfSignedCertificatePwd()</code> the first time 4060 * this method is called. 4061 * 4062 * @return the self-signed certificate password used for this session. 4063 */ 4064 private String getSelfSignedCertificatePwd() 4065 { 4066 if (selfSignedCertPw == null) 4067 { 4068 selfSignedCertPw = SetupUtils.createSelfSignedCertificatePwd(); 4069 } 4070 return new String(selfSignedCertPw); 4071 } 4072 4073 private Map<ServerDescriptor, AuthenticationData> getRemoteWithNoReplicationPort(UserData userData) 4074 { 4075 Map<ServerDescriptor, AuthenticationData> servers = new HashMap<>(); 4076 Set<SuffixDescriptor> suffixes = userData.getSuffixesToReplicateOptions().getSuffixes(); 4077 for (SuffixDescriptor suffix : suffixes) 4078 { 4079 for (ReplicaDescriptor replica : suffix.getReplicas()) 4080 { 4081 ServerDescriptor server = replica.getServer(); 4082 Object v = server.getServerProperties().get(IS_REPLICATION_SERVER); 4083 if (!Boolean.TRUE.equals(v)) 4084 { 4085 AuthenticationData authData = new AuthenticationData(); 4086 authData.setPort(Constants.DEFAULT_REPLICATION_PORT); 4087 authData.setUseSecureConnection(false); 4088 servers.put(server, authData); 4089 } 4090 } 4091 } 4092 return servers; 4093 } 4094 4095 private ConnectionWrapper createLocalConnection() throws NamingException 4096 { 4097 UserData uData = getUserData(); 4098 HostPort hostPort = new HostPort(uData.getHostName(), uData.getAdminConnectorPort()); 4099 String dn = uData.getDirectoryManagerDn(); 4100 String pwd = uData.getDirectoryManagerPwd(); 4101 return new ConnectionWrapper(hostPort, LDAPS, dn, pwd, getConnectTimeout(), null); 4102 } 4103 4104 /** 4105 * Gets a connection based on the information that appears on the 4106 * provided ServerDescriptor. 4107 * 4108 * @param server 4109 * the object describing the server. 4110 * @return the InitialLdapContext to the remote server. 4111 * @throws ApplicationException 4112 * if something goes wrong. 4113 */ 4114 private ConnectionWrapper getRemoteConnection(ServerDescriptor server) throws ApplicationException 4115 { 4116 Map<ADSContext.ServerProperty, Object> adsProperties; 4117 AuthenticationData auth = getUserData().getReplicationOptions().getAuthenticationData(); 4118 if (!server.isRegistered()) 4119 { 4120 /* 4121 * Create adsProperties to be able to use the class ServerLoader to get 4122 * the connection. Just update the connection parameters with what the 4123 * user chose in the Topology Options panel (i.e. even if SSL is enabled 4124 * on the remote server, use standard LDAP to connect to the server if the 4125 * user specified the LDAP port: this avoids having an issue with the 4126 * certificate if it has not been accepted previously by the user). 4127 */ 4128 adsProperties = new HashMap<>(); 4129 adsProperties.put(ADSContext.ServerProperty.HOST_NAME, server.getHostName()); 4130 if (auth.useSecureConnection()) 4131 { 4132 adsProperties.put(ADSContext.ServerProperty.LDAPS_PORT, String.valueOf(auth.getPort())); 4133 adsProperties.put(ADSContext.ServerProperty.LDAPS_ENABLED, "true"); 4134 } 4135 else 4136 { 4137 adsProperties.put(ADSContext.ServerProperty.LDAP_PORT, String.valueOf(auth.getPort())); 4138 adsProperties.put(ADSContext.ServerProperty.LDAP_ENABLED, "true"); 4139 } 4140 server.setAdsProperties(adsProperties); 4141 } 4142 return getRemoteConnection(server, auth.getDn(), auth.getPwd(), getConnectTimeout(), getPreferredConnections()); 4143 } 4144 4145 /** 4146 * Initializes a suffix with the contents of a replica that has a given 4147 * replication id. 4148 * 4149 * @param ctx 4150 * the connection to the server whose suffix we want to initialize. 4151 * @param replicaId 4152 * the replication ID of the replica we want to use to initialize the 4153 * contents of the suffix. 4154 * @param suffixDn 4155 * the dn of the suffix. 4156 * @param displayProgress 4157 * whether we want to display progress or not. 4158 * @param sourceServerDisplay 4159 * the string to be used to represent the server that contains the 4160 * data that will be used to initialize the suffix. 4161 * @throws ApplicationException 4162 * if an unexpected error occurs. 4163 * @throws PeerNotFoundException 4164 * if the replication mechanism cannot find a peer. 4165 */ 4166 public void initializeSuffix(InitialLdapContext ctx, int replicaId, String suffixDn, boolean displayProgress, 4167 HostPort sourceServerDisplay) throws ApplicationException, PeerNotFoundException 4168 { 4169 boolean taskCreated = false; 4170 int i = 1; 4171 boolean isOver = false; 4172 String dn = null; 4173 BasicAttributes attrs = new BasicAttributes(); 4174 Attribute oc = new BasicAttribute("objectclass"); 4175 oc.add("top"); 4176 oc.add("ds-task"); 4177 oc.add("ds-task-initialize-from-remote-replica"); 4178 attrs.put(oc); 4179 attrs.put("ds-task-class-name", "org.opends.server.tasks.InitializeTask"); 4180 attrs.put("ds-task-initialize-domain-dn", suffixDn); 4181 attrs.put("ds-task-initialize-replica-server-id", String.valueOf(replicaId)); 4182 while (!taskCreated) 4183 { 4184 checkAbort(); 4185 String id = "quicksetup-initialize" + i; 4186 dn = "ds-task-id=" + id + ",cn=Scheduled Tasks,cn=Tasks"; 4187 attrs.put("ds-task-id", id); 4188 try 4189 { 4190 DirContext dirCtx = ctx.createSubcontext(dn, attrs); 4191 taskCreated = true; 4192 logger.info(LocalizableMessage.raw("created task entry: " + attrs)); 4193 dirCtx.close(); 4194 } 4195 catch (NameAlreadyBoundException x) 4196 { 4197 logger.warn(LocalizableMessage.raw("A task with dn: " + dn + " already existed.")); 4198 } 4199 catch (NamingException ne) 4200 { 4201 logger.error(LocalizableMessage.raw("Error creating task " + attrs, ne)); 4202 throw new ApplicationException(ReturnCode.APPLICATION_ERROR, getThrowableMsg( 4203 INFO_ERROR_LAUNCHING_INITIALIZATION.get(sourceServerDisplay), ne), ne); 4204 } 4205 i++; 4206 } 4207 // Wait until it is over 4208 SearchControls searchControls = new SearchControls(); 4209 searchControls.setSearchScope(SearchControls.OBJECT_SCOPE); 4210 String filter = "objectclass=*"; 4211 searchControls.setReturningAttributes(new String[] { "ds-task-unprocessed-entry-count", 4212 "ds-task-processed-entry-count", "ds-task-log-message", "ds-task-state" }); 4213 LocalizableMessage lastDisplayedMsg = null; 4214 String lastLogMsg = null; 4215 long lastTimeMsgDisplayed = -1; 4216 long lastTimeMsgLogged = -1; 4217 long totalEntries = 0; 4218 while (!isOver) 4219 { 4220 if (canceled) 4221 { 4222 // TODO: we should try to cleanly abort the initialize. As we have 4223 // aborted the install, the server will be stopped and the remote 4224 // server will receive a connect error. 4225 checkAbort(); 4226 } 4227 StaticUtils.sleep(500); 4228 if (canceled) 4229 { 4230 // TODO: we should try to cleanly abort the initialize. As we have 4231 // aborted the install, the server will be stopped and the remote 4232 // server will receive a connect error. 4233 checkAbort(); 4234 } 4235 try 4236 { 4237 NamingEnumeration<SearchResult> res = ctx.search(dn, filter, searchControls); 4238 SearchResult sr = null; 4239 try 4240 { 4241 while (res.hasMore()) 4242 { 4243 sr = res.next(); 4244 } 4245 } 4246 finally 4247 { 4248 res.close(); 4249 } 4250 // Get the number of entries that have been handled and 4251 // a percentage... 4252 LocalizableMessage msg; 4253 String sProcessed = getFirstValue(sr, "ds-task-processed-entry-count"); 4254 String sUnprocessed = getFirstValue(sr, "ds-task-unprocessed-entry-count"); 4255 long processed = -1; 4256 long unprocessed = -1; 4257 if (sProcessed != null) 4258 { 4259 processed = Integer.parseInt(sProcessed); 4260 } 4261 if (sUnprocessed != null) 4262 { 4263 unprocessed = Integer.parseInt(sUnprocessed); 4264 } 4265 totalEntries = Math.max(totalEntries, processed + unprocessed); 4266 4267 if (processed != -1 && unprocessed != -1) 4268 { 4269 if (processed + unprocessed > 0) 4270 { 4271 long perc = (100 * processed) / (processed + unprocessed); 4272 msg = INFO_INITIALIZE_PROGRESS_WITH_PERCENTAGE.get(sProcessed, perc); 4273 } 4274 else 4275 { 4276 //msg = INFO_NO_ENTRIES_TO_INITIALIZE.get(); 4277 msg = null; 4278 } 4279 } 4280 else if (processed != -1) 4281 { 4282 msg = INFO_INITIALIZE_PROGRESS_WITH_PROCESSED.get(sProcessed); 4283 } 4284 else if (unprocessed != -1) 4285 { 4286 msg = INFO_INITIALIZE_PROGRESS_WITH_UNPROCESSED.get(sUnprocessed); 4287 } 4288 else 4289 { 4290 msg = lastDisplayedMsg; 4291 } 4292 4293 if (msg != null) 4294 { 4295 long currentTime = System.currentTimeMillis(); 4296 /* Refresh period: to avoid having too many lines in the log */ 4297 long minRefreshPeriod; 4298 if (totalEntries < 100) 4299 { 4300 minRefreshPeriod = 0; 4301 } 4302 else if (totalEntries < 1000) 4303 { 4304 minRefreshPeriod = 1000; 4305 } 4306 else if (totalEntries < 10000) 4307 { 4308 minRefreshPeriod = 5000; 4309 } 4310 else 4311 { 4312 minRefreshPeriod = 10000; 4313 } 4314 if (currentTime - minRefreshPeriod > lastTimeMsgLogged) 4315 { 4316 lastTimeMsgLogged = currentTime; 4317 logger.info(LocalizableMessage.raw("Progress msg: " + msg)); 4318 } 4319 if (displayProgress && currentTime - minRefreshPeriod > lastTimeMsgDisplayed && !msg.equals(lastDisplayedMsg)) 4320 { 4321 notifyListeners(getFormattedProgress(msg)); 4322 lastDisplayedMsg = msg; 4323 notifyListeners(getLineBreak()); 4324 lastTimeMsgDisplayed = currentTime; 4325 } 4326 } 4327 4328 String logMsg = getFirstValue(sr, "ds-task-log-message"); 4329 if (logMsg != null && !logMsg.equals(lastLogMsg)) 4330 { 4331 logger.info(LocalizableMessage.raw(logMsg)); 4332 lastLogMsg = logMsg; 4333 } 4334 InstallerHelper helper = new InstallerHelper(); 4335 String state = getFirstValue(sr, "ds-task-state"); 4336 4337 if (helper.isDone(state) || helper.isStoppedByError(state)) 4338 { 4339 isOver = true; 4340 LocalizableMessage errorMsg; 4341 logger.info(LocalizableMessage.raw("Last task entry: " + sr)); 4342 if (displayProgress && msg != null && !msg.equals(lastDisplayedMsg)) 4343 { 4344 notifyListeners(getFormattedProgress(msg)); 4345 lastDisplayedMsg = msg; 4346 notifyListeners(getLineBreak()); 4347 } 4348 4349 if (lastLogMsg != null) 4350 { 4351 errorMsg = 4352 INFO_ERROR_DURING_INITIALIZATION_LOG.get(sourceServerDisplay, lastLogMsg, state, sourceServerDisplay); 4353 } 4354 else 4355 { 4356 errorMsg = INFO_ERROR_DURING_INITIALIZATION_NO_LOG.get(sourceServerDisplay, state, sourceServerDisplay); 4357 } 4358 4359 logger.warn(LocalizableMessage.raw("Processed errorMsg: " + errorMsg)); 4360 if (helper.isCompletedWithErrors(state)) 4361 { 4362 if (displayProgress) 4363 { 4364 notifyListeners(getFormattedWarning(errorMsg)); 4365 } 4366 } 4367 else if (!helper.isSuccessful(state) || helper.isStoppedByError(state)) 4368 { 4369 ApplicationException ae = new ApplicationException(ReturnCode.APPLICATION_ERROR, errorMsg, null); 4370 if (lastLogMsg == null || helper.isPeersNotFoundError(lastLogMsg)) 4371 { 4372 logger.warn(LocalizableMessage.raw("Throwing peer not found error. " + "Last Log Msg: " + lastLogMsg)); 4373 // Assume that this is a peer not found error. 4374 throw new PeerNotFoundException(errorMsg); 4375 } 4376 else 4377 { 4378 logger.error(LocalizableMessage.raw("Throwing ApplicationException.")); 4379 throw ae; 4380 } 4381 } 4382 else if (displayProgress) 4383 { 4384 logger.info(LocalizableMessage.raw("Initialization completed successfully.")); 4385 notifyListeners(getFormattedProgress(INFO_SUFFIX_INITIALIZED_SUCCESSFULLY.get())); 4386 notifyListeners(getLineBreak()); 4387 } 4388 } 4389 } 4390 catch (NameNotFoundException x) 4391 { 4392 isOver = true; 4393 logger.info(LocalizableMessage.raw("Initialization entry not found.")); 4394 if (displayProgress) 4395 { 4396 notifyListeners(getFormattedProgress(INFO_SUFFIX_INITIALIZED_SUCCESSFULLY.get())); 4397 notifyListeners(getLineBreak()); 4398 } 4399 } 4400 catch (NamingException ne) 4401 { 4402 throw new ApplicationException(ReturnCode.APPLICATION_ERROR, getThrowableMsg(INFO_ERROR_POOLING_INITIALIZATION 4403 .get(sourceServerDisplay), ne), ne); 4404 } 4405 } 4406 resetGenerationId(ctx, suffixDn, sourceServerDisplay); 4407 } 4408 4409 /** 4410 * Returns the configuration file path to be used when invoking the 4411 * command-lines. 4412 * 4413 * @return the configuration file path to be used when invoking the 4414 * command-lines. 4415 */ 4416 private String getConfigurationFile() 4417 { 4418 return getPath(getInstallation().getCurrentConfigurationFile()); 4419 } 4420 4421 private String getLocalReplicationServer() 4422 { 4423 return getUserData().getHostName() + ":" + getUserData().getReplicationOptions().getReplicationPort(); 4424 } 4425 4426 private void resetGenerationId(InitialLdapContext ctx, String suffixDn, HostPort sourceServerDisplay) 4427 throws ApplicationException 4428 { 4429 boolean taskCreated = false; 4430 int i = 1; 4431 boolean isOver = false; 4432 String dn = null; 4433 BasicAttributes attrs = new BasicAttributes(); 4434 Attribute oc = new BasicAttribute("objectclass"); 4435 oc.add("top"); 4436 oc.add("ds-task"); 4437 oc.add("ds-task-reset-generation-id"); 4438 attrs.put(oc); 4439 attrs.put("ds-task-class-name", "org.opends.server.tasks.SetGenerationIdTask"); 4440 attrs.put("ds-task-reset-generation-id-domain-base-dn", suffixDn); 4441 while (!taskCreated) 4442 { 4443 checkAbort(); 4444 String id = "quicksetup-reset-generation-id-" + i; 4445 dn = "ds-task-id=" + id + ",cn=Scheduled Tasks,cn=Tasks"; 4446 attrs.put("ds-task-id", id); 4447 try 4448 { 4449 DirContext dirCtx = ctx.createSubcontext(dn, attrs); 4450 taskCreated = true; 4451 logger.info(LocalizableMessage.raw("created task entry: " + attrs)); 4452 dirCtx.close(); 4453 } 4454 catch (NameAlreadyBoundException x) 4455 { 4456 } 4457 catch (NamingException ne) 4458 { 4459 logger.error(LocalizableMessage.raw("Error creating task " + attrs, ne)); 4460 throw new ApplicationException(ReturnCode.APPLICATION_ERROR, getThrowableMsg( 4461 INFO_ERROR_LAUNCHING_INITIALIZATION.get(sourceServerDisplay), ne), ne); 4462 } 4463 i++; 4464 } 4465 // Wait until it is over 4466 SearchControls searchControls = new SearchControls(); 4467 searchControls.setSearchScope(SearchControls.OBJECT_SCOPE); 4468 String filter = "objectclass=*"; 4469 searchControls.setReturningAttributes(new String[] { "ds-task-log-message", "ds-task-state" }); 4470 String lastLogMsg = null; 4471 while (!isOver) 4472 { 4473 StaticUtils.sleep(500); 4474 try 4475 { 4476 NamingEnumeration<SearchResult> res = ctx.search(dn, filter, searchControls); 4477 SearchResult sr = null; 4478 try 4479 { 4480 while (res.hasMore()) 4481 { 4482 sr = res.next(); 4483 } 4484 } 4485 finally 4486 { 4487 res.close(); 4488 } 4489 String logMsg = getFirstValue(sr, "ds-task-log-message"); 4490 if (logMsg != null && !logMsg.equals(lastLogMsg)) 4491 { 4492 logger.info(LocalizableMessage.raw(logMsg)); 4493 lastLogMsg = logMsg; 4494 } 4495 InstallerHelper helper = new InstallerHelper(); 4496 String state = getFirstValue(sr, "ds-task-state"); 4497 4498 if (helper.isDone(state) || helper.isStoppedByError(state)) 4499 { 4500 isOver = true; 4501 LocalizableMessage errorMsg = lastLogMsg != null ? 4502 INFO_ERROR_DURING_INITIALIZATION_LOG.get(sourceServerDisplay, lastLogMsg, state, sourceServerDisplay) 4503 : INFO_ERROR_DURING_INITIALIZATION_NO_LOG.get(sourceServerDisplay, state, sourceServerDisplay); 4504 4505 if (helper.isCompletedWithErrors(state)) 4506 { 4507 logger.warn(LocalizableMessage.raw("Completed with error: " + errorMsg)); 4508 notifyListeners(getFormattedWarning(errorMsg)); 4509 } 4510 else if (!helper.isSuccessful(state) || helper.isStoppedByError(state)) 4511 { 4512 logger.warn(LocalizableMessage.raw("Error: " + errorMsg)); 4513 throw new ApplicationException(ReturnCode.APPLICATION_ERROR, errorMsg, null); 4514 } 4515 } 4516 } 4517 catch (NameNotFoundException x) 4518 { 4519 isOver = true; 4520 } 4521 catch (NamingException ne) 4522 { 4523 throw new ApplicationException(ReturnCode.APPLICATION_ERROR, 4524 getThrowableMsg(INFO_ERROR_POOLING_INITIALIZATION.get(sourceServerDisplay), ne), ne); 4525 } 4526 } 4527 } 4528 4529 /** 4530 * Invokes a long operation in a separate thread and checks whether the user 4531 * canceled the operation or not. 4532 * 4533 * @param thread 4534 * the Thread that must be launched. 4535 * @throws ApplicationException 4536 * if there was an error executing the task or if the user canceled 4537 * the installer. 4538 */ 4539 private void invokeLongOperation(InvokeThread thread) throws ApplicationException 4540 { 4541 try 4542 { 4543 thread.start(); 4544 while (!thread.isOver() && thread.isAlive()) 4545 { 4546 if (canceled) 4547 { 4548 // Try to abort the thread 4549 try 4550 { 4551 thread.abort(); 4552 } 4553 catch (Throwable t) 4554 { 4555 logger.warn(LocalizableMessage.raw("Error cancelling thread: " + t, t)); 4556 } 4557 } 4558 else if (thread.getException() != null) 4559 { 4560 throw thread.getException(); 4561 } 4562 else 4563 { 4564 StaticUtils.sleep(100); 4565 } 4566 } 4567 if (thread.getException() != null) 4568 { 4569 throw thread.getException(); 4570 } 4571 if (canceled) 4572 { 4573 checkAbort(); 4574 } 4575 } 4576 catch (ApplicationException e) 4577 { 4578 logger.error(LocalizableMessage.raw("Error: " + e, e)); 4579 throw e; 4580 } 4581 catch (Throwable t) 4582 { 4583 logger.error(LocalizableMessage.raw("Error: " + t, t)); 4584 throw new ApplicationException(ReturnCode.BUG, getThrowableMsg(INFO_BUG_MSG.get(), t), t); 4585 } 4586 } 4587 4588 /** 4589 * Returns the host port representation of the server to be used in progress 4590 * and error messages. It takes into account the fact the host and port 4591 * provided by the user in the replication options panel. NOTE: the code 4592 * assumes that the user data with the contents of the replication options has 4593 * already been updated. 4594 * 4595 * @param server 4596 * the ServerDescriptor. 4597 * @return the host port string representation of the provided server. 4598 */ 4599 private HostPort getHostPort(ServerDescriptor server) 4600 { 4601 HostPort hostPort = null; 4602 4603 for (PreferredConnection connection : getPreferredConnections()) 4604 { 4605 String url = connection.getLDAPURL(); 4606 if (url.equals(server.getLDAPURL())) 4607 { 4608 hostPort = server.getHostPort(false); 4609 } 4610 else if (url.equals(server.getLDAPsURL())) 4611 { 4612 hostPort = server.getHostPort(true); 4613 } 4614 } 4615 if (hostPort == null) 4616 { 4617 hostPort = server.getHostPort(true); 4618 } 4619 return hostPort; 4620 } 4621 4622 @Override 4623 protected void applicationPrintStreamReceived(String message) 4624 { 4625 InstallerHelper helper = new InstallerHelper(); 4626 String parsedMessage = helper.getImportProgressMessage(message); 4627 if (parsedMessage != null) 4628 { 4629 lastImportProgress = parsedMessage; 4630 } 4631 } 4632 4633 /** 4634 * Returns the timeout to be used to connect in milliseconds. 4635 * 4636 * @return the timeout to be used to connect in milliseconds. Returns 4637 * {@code 0} if there is no timeout. 4638 */ 4639 private int getConnectTimeout() 4640 { 4641 return getUserData().getConnectTimeout(); 4642 } 4643 4644 /** 4645 * Copies the template instance files into the instance directory. 4646 * 4647 * @throws ApplicationException 4648 * If an IO error occurred. 4649 */ 4650 private void copyTemplateInstance() throws ApplicationException 4651 { 4652 FileManager fileManager = new FileManager(); 4653 fileManager.synchronize(getInstallation().getTemplateDirectory(), getInstallation().getInstanceDirectory()); 4654 } 4655} 4656 4657/** Class used to be able to cancel long operations. */ 4658abstract class InvokeThread extends Thread 4659{ 4660 protected boolean isOver; 4661 protected ApplicationException ae; 4662 4663 /** 4664 * Returns whether the thread is over. 4665 * 4666 * @return {@code true} if the thread is over and {@code false} otherwise. 4667 */ 4668 public boolean isOver() 4669 { 4670 return isOver; 4671 } 4672 4673 /** 4674 * Returns the exception that was encountered running the thread. 4675 * 4676 * @return the exception that was encountered running the thread. 4677 */ 4678 public ApplicationException getException() 4679 { 4680 return ae; 4681 } 4682 4683 @Override 4684 public abstract void run(); 4685 4686 /** Abort this thread. */ 4687 public abstract void abort(); 4688}