/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2006-2010 Sun Microsystems, Inc. * Portions Copyright 2011-2015 ForgeRock AS */ package org.opends.quicksetup.installer.offline; import org.forgerock.i18n.LocalizableMessage; import static org.opends.messages.QuickSetupMessages.*; import static com.forgerock.opendj.util.OperatingSystem.isWindows; import static com.forgerock.opendj.cli.Utils.getThrowableMsg; import java.io.PrintStream; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.forgerock.i18n.slf4j.LocalizedLogger; import java.security.KeyStoreException; import org.opends.quicksetup.ApplicationException; import org.opends.quicksetup.LicenseFile; import org.opends.quicksetup.ReturnCode; import org.opends.quicksetup.ProgressStep; import org.opends.quicksetup.Installation; import org.opends.quicksetup.SecurityOptions; import org.opends.quicksetup.installer.Installer; import org.opends.quicksetup.installer.InstallProgressStep; import org.opends.quicksetup.util.Utils; import org.opends.quicksetup.util.ServerController; import org.opends.quicksetup.util.FileManager; import org.opends.server.util.CertificateManager; /** * This is an implementation of the Installer class that is used to install * the Directory Server from a zip file. The installer assumes that the zip * file contents have been unzipped. * * It just takes a UserData object and based on that installs OpenDS. * * When there is an update during the installation it will notify the * ProgressUpdateListener objects that have been added to it. The notification * will send a ProgressUpdateEvent. * * This class is supposed to be fully independent of the graphical layout. * */ public class OfflineInstaller extends Installer { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** This map contains the ratio associated with each step. */ private final Map<ProgressStep, Integer> hmRatio = new HashMap<>(); /** This map contains the summary associated with each step. */ private final Map<ProgressStep, LocalizableMessage> hmSummary = new HashMap<>(); private ApplicationException runError; /** * Actually performs the install in this thread. The thread is blocked. */ @Override public void run() { runError = null; PrintStream origErr = System.err; PrintStream origOut = System.out; try { initMaps(); System.setErr(getApplicationErrorStream()); System.setOut(getApplicationOutputStream()); checkAbort(); setCurrentProgressStep(InstallProgressStep.CONFIGURING_SERVER); notifyListenersOfLog(); notifyListeners(getLineBreak()); configureServer(); checkAbort(); // create license accepted file LicenseFile.createFileLicenseApproved(getInstallationPath()); checkAbort() ; createData(); checkAbort(); if (isWindows() && getUserData().getEnableWindowsService()) { if (isVerbose()) { notifyListeners(getTaskSeparator()); } setCurrentProgressStep(InstallProgressStep.ENABLING_WINDOWS_SERVICE); enableWindowsService(); checkAbort(); } if (mustStart()) { if (isStartVerbose()) { notifyListeners(getTaskSeparator()); } setCurrentProgressStep(InstallProgressStep.STARTING_SERVER); PointAdder pointAdder = new PointAdder(); if (!isStartVerbose()) { notifyListeners(getFormattedProgress( INFO_PROGRESS_STARTING_NON_VERBOSE.get())); pointAdder.start(); } try { new ServerController(this).startServer(!isStartVerbose()); } finally { if (!isStartVerbose()) { pointAdder.stop(); } } if (!isStartVerbose()) { notifyListeners(getFormattedDoneWithLineBreak()); } else { notifyListeners(getLineBreak()); } checkAbort(); } if (mustCreateAds()) { if (isVerbose()) { notifyListeners(getTaskSeparator()); } setCurrentProgressStep(InstallProgressStep.CONFIGURING_ADS); updateADS(); checkAbort(); } if (mustConfigureReplication()) { if (isVerbose()) { notifyListeners(getTaskSeparator()); } setCurrentProgressStep(InstallProgressStep.CONFIGURING_REPLICATION); createReplicatedBackendsIfRequired(); configureReplication(); checkAbort(); } if (mustInitializeSuffixes()) { if (isVerbose()) { notifyListeners(getTaskSeparator()); } setCurrentProgressStep( InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); initializeSuffixes(); checkAbort(); } if (mustStop()) { if (isVerbose()) { notifyListeners(getTaskSeparator()); } setCurrentProgressStep(InstallProgressStep.STOPPING_SERVER); if (!isVerbose()) { notifyListeners(getFormattedWithPoints( INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); } new ServerController(this).stopServer(!isVerbose()); if (!isVerbose()) { notifyListeners(getFormattedDoneWithLineBreak()); } } checkAbort(); updateSummaryWithServerState(hmSummary, true); setCurrentProgressStep(InstallProgressStep.FINISHED_SUCCESSFULLY); notifyListeners(null); } catch (ApplicationException ex) { logger.error(LocalizableMessage.raw("Caught exception: "+ex, ex)); if (ReturnCode.CANCELED.equals(ex.getType())) { uninstall(); setCurrentProgressStep(InstallProgressStep.FINISHED_CANCELED); notifyListeners(null); } else { // Stop the server if necessary Installation installation = getInstallation(); if (installation.getStatus().isServerRunning()) { try { if (!isVerbose()) { notifyListeners(getFormattedWithPoints( INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); } new ServerController(installation).stopServer(!isVerbose()); if (!isVerbose()) { notifyListeners(getFormattedDoneWithLineBreak()); } } catch (Throwable t) { logger.info(LocalizableMessage.raw("error stopping server", t)); } } notifyListeners(getLineBreak()); updateSummaryWithServerState(hmSummary, true); setCurrentProgressStep(InstallProgressStep.FINISHED_WITH_ERROR); LocalizableMessage html = getFormattedError(ex, true); notifyListeners(html); logger.error(LocalizableMessage.raw("Error installing.", ex)); notifyListeners(getLineBreak()); notifyListenersOfLogAfterError(); } runError = ex; } catch (Throwable t) { // Stop the server if necessary Installation installation = getInstallation(); if (installation.getStatus().isServerRunning()) { try { if (!isVerbose()) { notifyListeners(getFormattedWithPoints( INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); } new ServerController(installation).stopServer(!isVerbose()); if (!isVerbose()) { notifyListeners(getFormattedDoneWithLineBreak()); } } catch (Throwable t2) { logger.info(LocalizableMessage.raw("error stopping server", t2)); } } notifyListeners(getLineBreak()); updateSummaryWithServerState(hmSummary, true); setCurrentProgressStep(InstallProgressStep.FINISHED_WITH_ERROR); ApplicationException ex = new ApplicationException( ReturnCode.BUG, getThrowableMsg(INFO_BUG_MSG.get(), t), t); LocalizableMessage msg = getFormattedError(ex, true); notifyListeners(msg); logger.error(LocalizableMessage.raw("Error installing.", t)); notifyListeners(getLineBreak()); notifyListenersOfLogAfterError(); runError = ex; } finally { System.setErr(origErr); System.setOut(origOut); } } /** {@inheritDoc} */ @Override public Integer getRatio(ProgressStep status) { return hmRatio.get(status); } /** {@inheritDoc} */ @Override public LocalizableMessage getSummary(ProgressStep status) { return hmSummary.get(status); } /** * Returns the exception from the run() method, if any. * @return the ApplicationException raised during the run() method, if any. * null otherwise. */ public ApplicationException getRunError() { return runError; } /** * Called when the user elects to cancel this operation. */ protected void uninstall() { notifyListeners(getTaskSeparator()); if (!isVerbose()) { notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CANCELING.get())); } else { notifyListeners( getFormattedProgressWithLineBreak(INFO_SUMMARY_CANCELING.get())); } Installation installation = getInstallation(); FileManager fm = new FileManager(this); // Stop the server if necessary if (installation.getStatus().isServerRunning()) { try { if (!isVerbose()) { notifyListeners(getFormattedWithPoints( INFO_PROGRESS_STOPPING_NON_VERBOSE.get())); } new ServerController(installation).stopServer(!isVerbose()); if (!isVerbose()) { notifyListeners(getFormattedDoneWithLineBreak()); } } catch (ApplicationException e) { logger.info(LocalizableMessage.raw("error stopping server", e)); } } uninstallServices(); // Revert to the base configuration try { File newConfig = fm.copy(installation.getBaseConfigurationFile(), installation.getConfigurationDirectory(), /*overwrite=*/true); fm.rename(newConfig, installation.getCurrentConfigurationFile()); } catch (ApplicationException ae) { logger.info(LocalizableMessage.raw("failed to restore base configuration", ae)); } // Cleanup SSL if necessary SecurityOptions sec = getUserData().getSecurityOptions(); if (sec.getEnableSSL() || sec.getEnableStartTLS()) { if (SecurityOptions.CertificateType.SELF_SIGNED_CERTIFICATE.equals( sec.getCertificateType())) { CertificateManager cm = new CertificateManager( getSelfSignedKeystorePath(), CertificateManager.KEY_STORE_TYPE_JKS, getSelfSignedCertificatePwd()); try { for (String alias : SELF_SIGNED_CERT_ALIASES) { if (cm.aliasInUse(alias)) { cm.removeCertificate(alias); } } } catch (KeyStoreException e) { logger.info(LocalizableMessage.raw("Error deleting self signed certification", e)); } } File keystore = new File(installation.getConfigurationDirectory(), "keystore"); if (keystore.exists()) { try { fm.delete(keystore); } catch (ApplicationException e) { logger.info(LocalizableMessage.raw("Failed to delete keystore", e)); } } File keystorePin = new File(installation.getConfigurationDirectory(), "keystore.pin"); if (keystorePin.exists()) { try { fm.delete(keystorePin); } catch (ApplicationException e) { logger.info(LocalizableMessage.raw("Failed to delete keystore.pin", e)); } } File truststore = new File(installation.getConfigurationDirectory(), "truststore"); if (truststore.exists()) { try { fm.delete(truststore); } catch (ApplicationException e) { logger.info(LocalizableMessage.raw("Failed to delete truststore", e)); } } } // Remove the databases try { fm.deleteChildren(installation.getDatabasesDirectory()); } catch (ApplicationException e) { logger.info(LocalizableMessage.raw("Error deleting databases", e)); } if (!isVerbose()) { notifyListeners(getFormattedDoneWithLineBreak()); } } /** * Initialize the different map used in this class. * */ protected void initMaps() { initSummaryMap(hmSummary, true); /* * hmTime contains the relative time that takes for each task to be * accomplished. For instance if downloading takes twice the time of * extracting, the value for downloading will be the double of the value for * extracting. */ Map<ProgressStep, Integer> hmTime = new HashMap<>(); hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5); hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10); hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20); hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED, 20); hmTime.put(InstallProgressStep.CONFIGURING_REPLICATION, 10); hmTime.put(InstallProgressStep.ENABLING_WINDOWS_SERVICE, 5); hmTime.put(InstallProgressStep.STARTING_SERVER, 10); hmTime.put(InstallProgressStep.STOPPING_SERVER, 5); hmTime.put(InstallProgressStep.CONFIGURING_ADS, 5); hmTime.put(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES, 25); int totalTime = 0; List<InstallProgressStep> steps = new ArrayList<>(); totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER); steps.add(InstallProgressStep.CONFIGURING_SERVER); if (createNotReplicatedSuffix()) { switch (getUserData().getNewSuffixOptions().getType()) { case CREATE_BASE_ENTRY: steps.add(InstallProgressStep.CREATING_BASE_ENTRY); totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY); break; case IMPORT_FROM_LDIF_FILE: steps.add(InstallProgressStep.IMPORTING_LDIF); totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF); break; case IMPORT_AUTOMATICALLY_GENERATED_DATA: steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED); totalTime += hmTime.get( InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED); break; } } if (isWindows() && getUserData().getEnableWindowsService()) { totalTime += hmTime.get(InstallProgressStep.ENABLING_WINDOWS_SERVICE); steps.add(InstallProgressStep.ENABLING_WINDOWS_SERVICE); } if (mustStart()) { totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER); steps.add(InstallProgressStep.STARTING_SERVER); } if (mustCreateAds()) { totalTime += hmTime.get(InstallProgressStep.CONFIGURING_ADS); steps.add(InstallProgressStep.CONFIGURING_ADS); } if (mustConfigureReplication()) { steps.add(InstallProgressStep.CONFIGURING_REPLICATION); totalTime += hmTime.get(InstallProgressStep.CONFIGURING_REPLICATION); } if (mustInitializeSuffixes()) { totalTime += hmTime.get( InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); steps.add(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES); } if (mustStop()) { totalTime += hmTime.get(InstallProgressStep.STOPPING_SERVER); steps.add(InstallProgressStep.STOPPING_SERVER); } int cumulatedTime = 0; for (InstallProgressStep s : steps) { Integer statusTime = hmTime.get(s); hmRatio.put(s, (100 * cumulatedTime) / totalTime); if (statusTime != null) { cumulatedTime += statusTime; } } hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100); hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100); hmRatio.put(InstallProgressStep.FINISHED_CANCELED, 100); } /** {@inheritDoc} */ @Override public String getInstallationPath() { return Utils.getInstallPathFromClasspath(); } /** {@inheritDoc} */ @Override public String getInstancePath() { String installPath = Utils.getInstallPathFromClasspath(); return Utils.getInstancePathFromInstallPath(installPath); } }