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 cm.removeCertificate(SELF_SIGNED_CERT_ALIAS); 385 } catch (KeyStoreException e) { 386 logger.info(LocalizableMessage.raw("Error deleting self signed certification", e)); 387 } 388 } 389 390 File keystore = new File(installation.getConfigurationDirectory(), 391 "keystore"); 392 if (keystore.exists()) { 393 try { 394 fm.delete(keystore); 395 } catch (ApplicationException e) { 396 logger.info(LocalizableMessage.raw("Failed to delete keystore", e)); 397 } 398 } 399 400 File keystorePin = new File(installation.getConfigurationDirectory(), 401 "keystore.pin"); 402 if (keystorePin.exists()) { 403 try { 404 fm.delete(keystorePin); 405 } catch (ApplicationException e) { 406 logger.info(LocalizableMessage.raw("Failed to delete keystore.pin", e)); 407 } 408 } 409 410 File truststore = new File(installation.getConfigurationDirectory(), 411 "truststore"); 412 if (truststore.exists()) { 413 try { 414 fm.delete(truststore); 415 } catch (ApplicationException e) { 416 logger.info(LocalizableMessage.raw("Failed to delete truststore", e)); 417 } 418 } 419 } 420 421 // Remove the databases 422 try { 423 fm.deleteChildren(installation.getDatabasesDirectory()); 424 } catch (ApplicationException e) { 425 logger.info(LocalizableMessage.raw("Error deleting databases", e)); 426 } 427 428 if (!isVerbose()) 429 { 430 notifyListeners(getFormattedDoneWithLineBreak()); 431 } 432 433 } 434 435 /** 436 * Initialize the different map used in this class. 437 * 438 */ 439 protected void initMaps() 440 { 441 initSummaryMap(hmSummary, true); 442 443 /* 444 * hmTime contains the relative time that takes for each task to be 445 * accomplished. For instance if downloading takes twice the time of 446 * extracting, the value for downloading will be the double of the value for 447 * extracting. 448 */ 449 Map<ProgressStep, Integer> hmTime = new HashMap<>(); 450 hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5); 451 hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10); 452 hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20); 453 hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED, 20); 454 hmTime.put(InstallProgressStep.CONFIGURING_REPLICATION, 10); 455 hmTime.put(InstallProgressStep.ENABLING_WINDOWS_SERVICE, 5); 456 hmTime.put(InstallProgressStep.STARTING_SERVER, 10); 457 hmTime.put(InstallProgressStep.STOPPING_SERVER, 5); 458 hmTime.put(InstallProgressStep.CONFIGURING_ADS, 5); 459 hmTime.put(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES, 25); 460 461 int totalTime = 0; 462 List<InstallProgressStep> steps = new ArrayList<>(); 463 totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER); 464 steps.add(InstallProgressStep.CONFIGURING_SERVER); 465 if (createNotReplicatedSuffix()) 466 { 467 switch (getUserData().getNewSuffixOptions().getType()) 468 { 469 case CREATE_BASE_ENTRY: 470 steps.add(InstallProgressStep.CREATING_BASE_ENTRY); 471 totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY); 472 break; 473 case IMPORT_FROM_LDIF_FILE: 474 steps.add(InstallProgressStep.IMPORTING_LDIF); 475 totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF); 476 break; 477 case IMPORT_AUTOMATICALLY_GENERATED_DATA: 478 steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED); 479 totalTime += hmTime.get( 480 InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED); 481 break; 482 } 483 } 484 485 if (isWindows() && getUserData().getEnableWindowsService()) 486 { 487 totalTime += hmTime.get(InstallProgressStep.ENABLING_WINDOWS_SERVICE); 488 steps.add(InstallProgressStep.ENABLING_WINDOWS_SERVICE); 489 } 490 491 if (mustStart()) 492 { 493 totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER); 494 steps.add(InstallProgressStep.STARTING_SERVER); 495 } 496 497 if (mustCreateAds()) 498 { 499 totalTime += hmTime.get(InstallProgressStep.CONFIGURING_ADS); 500 steps.add(InstallProgressStep.CONFIGURING_ADS); 501 } 502 503 if (mustConfigureReplication()) 504 { 505 steps.add(InstallProgressStep.CONFIGURING_REPLICATION); 506 totalTime += hmTime.get(InstallProgressStep.CONFIGURING_REPLICATION); 507 } 508 509 if (mustInitializeSuffixes()) 510 { 511 totalTime += hmTime.get( 512 InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); 513 steps.add(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); 514 } 515 516 if (mustStop()) 517 { 518 totalTime += hmTime.get(InstallProgressStep.STOPPING_SERVER); 519 steps.add(InstallProgressStep.STOPPING_SERVER); 520 } 521 522 int cumulatedTime = 0; 523 for (InstallProgressStep s : steps) 524 { 525 Integer statusTime = hmTime.get(s); 526 hmRatio.put(s, (100 * cumulatedTime) / totalTime); 527 if (statusTime != null) 528 { 529 cumulatedTime += statusTime; 530 } 531 } 532 hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100); 533 hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100); 534 hmRatio.put(InstallProgressStep.FINISHED_CANCELED, 100); 535 } 536 537 /** {@inheritDoc} */ 538 @Override 539 public String getInstallationPath() 540 { 541 return Utils.getInstallPathFromClasspath(); 542 } 543 544 /** {@inheritDoc} */ 545 @Override 546 public String getInstancePath() 547 { 548 String installPath = Utils.getInstallPathFromClasspath(); 549 return Utils.getInstancePathFromInstallPath(installPath); 550 } 551 552}