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