001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2011-2015 ForgeRock AS 026 */ 027package org.opends.quicksetup.installer.offline; 028 029import org.forgerock.i18n.LocalizableMessage; 030import static org.opends.messages.QuickSetupMessages.*; 031import static com.forgerock.opendj.util.OperatingSystem.isWindows; 032import static com.forgerock.opendj.cli.Utils.getThrowableMsg; 033 034import java.io.PrintStream; 035import java.io.File; 036import java.util.ArrayList; 037import java.util.HashMap; 038import java.util.List; 039import java.util.Map; 040 041import org.forgerock.i18n.slf4j.LocalizedLogger; 042import java.security.KeyStoreException; 043 044import org.opends.quicksetup.ApplicationException; 045import org.opends.quicksetup.LicenseFile; 046import org.opends.quicksetup.ReturnCode; 047import org.opends.quicksetup.ProgressStep; 048import org.opends.quicksetup.Installation; 049import org.opends.quicksetup.SecurityOptions; 050import org.opends.quicksetup.installer.Installer; 051import org.opends.quicksetup.installer.InstallProgressStep; 052import org.opends.quicksetup.util.Utils; 053import org.opends.quicksetup.util.ServerController; 054import org.opends.quicksetup.util.FileManager; 055import org.opends.server.util.CertificateManager; 056 057/** 058 * This is an implementation of the Installer class that is used to install 059 * the Directory Server from a zip file. The installer assumes that the zip 060 * file contents have been unzipped. 061 * 062 * It just takes a UserData object and based on that installs OpenDS. 063 * 064 * When there is an update during the installation it will notify the 065 * ProgressUpdateListener objects that have been added to it. The notification 066 * will send a ProgressUpdateEvent. 067 * 068 * This class is supposed to be fully independent of the graphical layout. 069 * 070 */ 071public class OfflineInstaller extends Installer 072{ 073 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 074 075 /** This map contains the ratio associated with each step. */ 076 private final Map<ProgressStep, Integer> hmRatio = new HashMap<>(); 077 /** This map contains the summary associated with each step. */ 078 private final Map<ProgressStep, LocalizableMessage> hmSummary = new HashMap<>(); 079 080 private ApplicationException runError; 081 082 /** 083 * Actually performs the install in this thread. The thread is blocked. 084 */ 085 @Override 086 public void run() 087 { 088 runError = null; 089 PrintStream origErr = System.err; 090 PrintStream origOut = System.out; 091 try 092 { 093 initMaps(); 094 095 System.setErr(getApplicationErrorStream()); 096 System.setOut(getApplicationOutputStream()); 097 098 checkAbort(); 099 100 setCurrentProgressStep(InstallProgressStep.CONFIGURING_SERVER); 101 102 notifyListenersOfLog(); 103 notifyListeners(getLineBreak()); 104 105 configureServer(); 106 107 checkAbort(); 108 109 // create license accepted file 110 LicenseFile.createFileLicenseApproved(getInstallationPath()); 111 112 checkAbort() ; 113 114 createData(); 115 116 checkAbort(); 117 118 if (isWindows() && getUserData().getEnableWindowsService()) 119 { 120 if (isVerbose()) 121 { 122 notifyListeners(getTaskSeparator()); 123 } 124 setCurrentProgressStep(InstallProgressStep.ENABLING_WINDOWS_SERVICE); 125 enableWindowsService(); 126 checkAbort(); 127 } 128 129 if (mustStart()) 130 { 131 if (isStartVerbose()) 132 { 133 notifyListeners(getTaskSeparator()); 134 } 135 setCurrentProgressStep(InstallProgressStep.STARTING_SERVER); 136 PointAdder pointAdder = new PointAdder(); 137 if (!isStartVerbose()) 138 { 139 notifyListeners(getFormattedProgress( 140 INFO_PROGRESS_STARTING_NON_VERBOSE.get())); 141 pointAdder.start(); 142 } 143 try 144 { 145 new ServerController(this).startServer(!isStartVerbose()); 146 } 147 finally 148 { 149 if (!isStartVerbose()) 150 { 151 pointAdder.stop(); 152 } 153 } 154 if (!isStartVerbose()) 155 { 156 notifyListeners(getFormattedDoneWithLineBreak()); 157 } 158 else 159 { 160 notifyListeners(getLineBreak()); 161 } 162 checkAbort(); 163 } 164 165 if (mustCreateAds()) 166 { 167 if (isVerbose()) 168 { 169 notifyListeners(getTaskSeparator()); 170 } 171 setCurrentProgressStep(InstallProgressStep.CONFIGURING_ADS); 172 updateADS(); 173 checkAbort(); 174 } 175 176 if (mustConfigureReplication()) 177 { 178 if (isVerbose()) 179 { 180 notifyListeners(getTaskSeparator()); 181 } 182 setCurrentProgressStep(InstallProgressStep.CONFIGURING_REPLICATION); 183 createReplicatedBackendsIfRequired(); 184 configureReplication(); 185 checkAbort(); 186 } 187 188 if (mustInitializeSuffixes()) 189 { 190 if (isVerbose()) 191 { 192 notifyListeners(getTaskSeparator()); 193 } 194 setCurrentProgressStep( 195 InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); 196 initializeSuffixes(); 197 checkAbort(); 198 } 199 200 if (mustStop()) 201 { 202 if (isVerbose()) 203 { 204 notifyListeners(getTaskSeparator()); 205 } 206 setCurrentProgressStep(InstallProgressStep.STOPPING_SERVER); 207 if (!isVerbose()) 208 { 209 notifyListeners(getFormattedWithPoints( 210 INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); 211 } 212 new ServerController(this).stopServer(!isVerbose()); 213 if (!isVerbose()) 214 { 215 notifyListeners(getFormattedDoneWithLineBreak()); 216 } 217 } 218 219 checkAbort(); 220 updateSummaryWithServerState(hmSummary, true); 221 setCurrentProgressStep(InstallProgressStep.FINISHED_SUCCESSFULLY); 222 notifyListeners(null); 223 224 } catch (ApplicationException ex) 225 { 226 logger.error(LocalizableMessage.raw("Caught exception: "+ex, ex)); 227 if (ReturnCode.CANCELED.equals(ex.getType())) { 228 uninstall(); 229 setCurrentProgressStep(InstallProgressStep.FINISHED_CANCELED); 230 notifyListeners(null); 231 } else { 232 // Stop the server if necessary 233 Installation installation = getInstallation(); 234 if (installation.getStatus().isServerRunning()) { 235 try { 236 if (!isVerbose()) 237 { 238 notifyListeners(getFormattedWithPoints( 239 INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); 240 } 241 new ServerController(installation).stopServer(!isVerbose()); 242 if (!isVerbose()) 243 { 244 notifyListeners(getFormattedDoneWithLineBreak()); 245 } 246 } catch (Throwable t) { 247 logger.info(LocalizableMessage.raw("error stopping server", t)); 248 } 249 } 250 notifyListeners(getLineBreak()); 251 updateSummaryWithServerState(hmSummary, true); 252 setCurrentProgressStep(InstallProgressStep.FINISHED_WITH_ERROR); 253 LocalizableMessage html = getFormattedError(ex, true); 254 notifyListeners(html); 255 logger.error(LocalizableMessage.raw("Error installing.", ex)); 256 notifyListeners(getLineBreak()); 257 notifyListenersOfLogAfterError(); 258 } 259 runError = ex; 260 } 261 catch (Throwable t) 262 { 263 // Stop the server if necessary 264 Installation installation = getInstallation(); 265 if (installation.getStatus().isServerRunning()) { 266 try { 267 if (!isVerbose()) 268 { 269 notifyListeners(getFormattedWithPoints( 270 INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); 271 } 272 new ServerController(installation).stopServer(!isVerbose()); 273 if (!isVerbose()) 274 { 275 notifyListeners(getFormattedDoneWithLineBreak()); 276 } 277 } catch (Throwable t2) { 278 logger.info(LocalizableMessage.raw("error stopping server", t2)); 279 } 280 } 281 notifyListeners(getLineBreak()); 282 updateSummaryWithServerState(hmSummary, true); 283 setCurrentProgressStep(InstallProgressStep.FINISHED_WITH_ERROR); 284 ApplicationException ex = new ApplicationException( 285 ReturnCode.BUG, 286 getThrowableMsg(INFO_BUG_MSG.get(), t), t); 287 LocalizableMessage msg = getFormattedError(ex, true); 288 notifyListeners(msg); 289 logger.error(LocalizableMessage.raw("Error installing.", t)); 290 notifyListeners(getLineBreak()); 291 notifyListenersOfLogAfterError(); 292 runError = ex; 293 } 294 finally 295 { 296 System.setErr(origErr); 297 System.setOut(origOut); 298 } 299 } 300 301 /** {@inheritDoc} */ 302 @Override 303 public Integer getRatio(ProgressStep status) 304 { 305 return hmRatio.get(status); 306 } 307 308 /** {@inheritDoc} */ 309 @Override 310 public LocalizableMessage getSummary(ProgressStep status) 311 { 312 return hmSummary.get(status); 313 } 314 315 /** 316 * Returns the exception from the run() method, if any. 317 * @return the ApplicationException raised during the run() method, if any. 318 * null otherwise. 319 */ 320 public ApplicationException getRunError() 321 { 322 return runError; 323 } 324 325 /** 326 * Called when the user elects to cancel this operation. 327 */ 328 protected void uninstall() { 329 330 notifyListeners(getTaskSeparator()); 331 if (!isVerbose()) 332 { 333 notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CANCELING.get())); 334 } 335 else 336 { 337 notifyListeners( 338 getFormattedProgressWithLineBreak(INFO_SUMMARY_CANCELING.get())); 339 } 340 Installation installation = getInstallation(); 341 FileManager fm = new FileManager(this); 342 343 // Stop the server if necessary 344 if (installation.getStatus().isServerRunning()) { 345 try { 346 if (!isVerbose()) 347 { 348 notifyListeners(getFormattedWithPoints( 349 INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); 350 } 351 new ServerController(installation).stopServer(!isVerbose()); 352 if (!isVerbose()) 353 { 354 notifyListeners(getFormattedDoneWithLineBreak()); 355 } 356 } catch (ApplicationException e) { 357 logger.info(LocalizableMessage.raw("error stopping server", e)); 358 } 359 } 360 361 uninstallServices(); 362 363 // Revert to the base configuration 364 try { 365 File newConfig = fm.copy(installation.getBaseConfigurationFile(), 366 installation.getConfigurationDirectory(), 367 /*overwrite=*/true); 368 fm.rename(newConfig, installation.getCurrentConfigurationFile()); 369 370 } catch (ApplicationException ae) { 371 logger.info(LocalizableMessage.raw("failed to restore base configuration", ae)); 372 } 373 374 // Cleanup SSL if necessary 375 SecurityOptions sec = getUserData().getSecurityOptions(); 376 if (sec.getEnableSSL() || sec.getEnableStartTLS()) { 377 if (SecurityOptions.CertificateType.SELF_SIGNED_CERTIFICATE.equals( 378 sec.getCertificateType())) { 379 CertificateManager cm = new CertificateManager( 380 getSelfSignedKeystorePath(), 381 CertificateManager.KEY_STORE_TYPE_JKS, 382 getSelfSignedCertificatePwd()); 383 try { 384 for (String alias : SELF_SIGNED_CERT_ALIASES) 385 { 386 if (cm.aliasInUse(alias)) 387 { 388 cm.removeCertificate(alias); 389 } 390 } 391 } catch (KeyStoreException e) { 392 logger.info(LocalizableMessage.raw("Error deleting self signed certification", e)); 393 } 394 } 395 396 File keystore = new File(installation.getConfigurationDirectory(), 397 "keystore"); 398 if (keystore.exists()) { 399 try { 400 fm.delete(keystore); 401 } catch (ApplicationException e) { 402 logger.info(LocalizableMessage.raw("Failed to delete keystore", e)); 403 } 404 } 405 406 File keystorePin = new File(installation.getConfigurationDirectory(), 407 "keystore.pin"); 408 if (keystorePin.exists()) { 409 try { 410 fm.delete(keystorePin); 411 } catch (ApplicationException e) { 412 logger.info(LocalizableMessage.raw("Failed to delete keystore.pin", e)); 413 } 414 } 415 416 File truststore = new File(installation.getConfigurationDirectory(), 417 "truststore"); 418 if (truststore.exists()) { 419 try { 420 fm.delete(truststore); 421 } catch (ApplicationException e) { 422 logger.info(LocalizableMessage.raw("Failed to delete truststore", e)); 423 } 424 } 425 } 426 427 // Remove the databases 428 try { 429 fm.deleteChildren(installation.getDatabasesDirectory()); 430 } catch (ApplicationException e) { 431 logger.info(LocalizableMessage.raw("Error deleting databases", e)); 432 } 433 434 if (!isVerbose()) 435 { 436 notifyListeners(getFormattedDoneWithLineBreak()); 437 } 438 439 } 440 441 /** 442 * Initialize the different map used in this class. 443 * 444 */ 445 protected void initMaps() 446 { 447 initSummaryMap(hmSummary, true); 448 449 /* 450 * hmTime contains the relative time that takes for each task to be 451 * accomplished. For instance if downloading takes twice the time of 452 * extracting, the value for downloading will be the double of the value for 453 * extracting. 454 */ 455 Map<ProgressStep, Integer> hmTime = new HashMap<>(); 456 hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5); 457 hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10); 458 hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20); 459 hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED, 20); 460 hmTime.put(InstallProgressStep.CONFIGURING_REPLICATION, 10); 461 hmTime.put(InstallProgressStep.ENABLING_WINDOWS_SERVICE, 5); 462 hmTime.put(InstallProgressStep.STARTING_SERVER, 10); 463 hmTime.put(InstallProgressStep.STOPPING_SERVER, 5); 464 hmTime.put(InstallProgressStep.CONFIGURING_ADS, 5); 465 hmTime.put(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES, 25); 466 467 int totalTime = 0; 468 List<InstallProgressStep> steps = new ArrayList<>(); 469 totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER); 470 steps.add(InstallProgressStep.CONFIGURING_SERVER); 471 if (createNotReplicatedSuffix()) 472 { 473 switch (getUserData().getNewSuffixOptions().getType()) 474 { 475 case CREATE_BASE_ENTRY: 476 steps.add(InstallProgressStep.CREATING_BASE_ENTRY); 477 totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY); 478 break; 479 case IMPORT_FROM_LDIF_FILE: 480 steps.add(InstallProgressStep.IMPORTING_LDIF); 481 totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF); 482 break; 483 case IMPORT_AUTOMATICALLY_GENERATED_DATA: 484 steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED); 485 totalTime += hmTime.get( 486 InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED); 487 break; 488 } 489 } 490 491 if (isWindows() && getUserData().getEnableWindowsService()) 492 { 493 totalTime += hmTime.get(InstallProgressStep.ENABLING_WINDOWS_SERVICE); 494 steps.add(InstallProgressStep.ENABLING_WINDOWS_SERVICE); 495 } 496 497 if (mustStart()) 498 { 499 totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER); 500 steps.add(InstallProgressStep.STARTING_SERVER); 501 } 502 503 if (mustCreateAds()) 504 { 505 totalTime += hmTime.get(InstallProgressStep.CONFIGURING_ADS); 506 steps.add(InstallProgressStep.CONFIGURING_ADS); 507 } 508 509 if (mustConfigureReplication()) 510 { 511 steps.add(InstallProgressStep.CONFIGURING_REPLICATION); 512 totalTime += hmTime.get(InstallProgressStep.CONFIGURING_REPLICATION); 513 } 514 515 if (mustInitializeSuffixes()) 516 { 517 totalTime += hmTime.get( 518 InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); 519 steps.add(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); 520 } 521 522 if (mustStop()) 523 { 524 totalTime += hmTime.get(InstallProgressStep.STOPPING_SERVER); 525 steps.add(InstallProgressStep.STOPPING_SERVER); 526 } 527 528 int cumulatedTime = 0; 529 for (InstallProgressStep s : steps) 530 { 531 Integer statusTime = hmTime.get(s); 532 hmRatio.put(s, (100 * cumulatedTime) / totalTime); 533 if (statusTime != null) 534 { 535 cumulatedTime += statusTime; 536 } 537 } 538 hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100); 539 hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100); 540 hmRatio.put(InstallProgressStep.FINISHED_CANCELED, 100); 541 } 542 543 /** {@inheritDoc} */ 544 @Override 545 public String getInstallationPath() 546 { 547 return Utils.getInstallPathFromClasspath(); 548 } 549 550 /** {@inheritDoc} */ 551 @Override 552 public String getInstancePath() 553 { 554 String installPath = Utils.getInstallPathFromClasspath(); 555 return Utils.getInstancePathFromInstallPath(installPath); 556 } 557 558}