/* * 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 2008-2009 Sun Microsystems, Inc. * Portions Copyright 2014-2015 ForgeRock AS */ package org.opends.guitools.controlpanel.ui; import static org.opends.messages.AdminToolMessages.*; import java.awt.GridBagConstraints; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; import org.opends.guitools.controlpanel.datamodel.BackupDescriptor; import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; import org.opends.guitools.controlpanel.event.BackupCreatedEvent; import org.opends.guitools.controlpanel.event.BackupCreatedListener; import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; import org.opends.guitools.controlpanel.task.Task; import org.opends.guitools.controlpanel.util.Utilities; import org.forgerock.i18n.LocalizableMessage; import org.opends.server.tools.RestoreDB; /** * The panel that appears when the user wants to restore from a backup. * */ public class RestorePanel extends BackupListPanel implements BackupCreatedListener { private static final long serialVersionUID = -205585323128518051L; private ListSelectionListener listener; private JLabel lBackupID; private JTextField backupID; /** * Constructor of the panel. * */ public RestorePanel() { super(); createLayout(); } /** {@inheritDoc} */ public LocalizableMessage getTitle() { return INFO_CTRL_PANEL_RESTORE_PANEL_TITLE.get(); } /** {@inheritDoc} */ public void backupCreated(BackupCreatedEvent ev) { boolean refreshList = false; File f = new File(parentDirectory.getText()); File fBackup = ev.getBackupDescriptor().getPath(); if (fBackup.equals(f)) { refreshList = true; } else { f = f.getParentFile(); if (f != null) { refreshList = fBackup.equals(f); } } if (refreshList && isVisible()) { // If not visible the list will be refreshed next time the dialog is // opened. SwingUtilities.invokeLater(new Runnable() { public void run() { refreshList(); } }); } } /** {@inheritDoc} */ public void setInfo(ControlPanelInfo info) { super.setInfo(info); info.addBackupCreatedListener(this); } /** {@inheritDoc} */ public void toBeDisplayed(boolean visible) { if (visible) { listener.valueChanged(null); } } /** {@inheritDoc} */ public void configurationChanged(ConfigurationChangeEvent ev) { final ServerDescriptor desc = ev.getNewDescriptor(); SwingUtilities.invokeLater(new Runnable() { /** {@inheritDoc} */ public void run() { lBackupID.setVisible(!desc.isLocal()); backupID.setVisible(!desc.isLocal()); } }); super.configurationChanged(ev); updateErrorPaneAndOKButtonIfAuthRequired(desc, isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_RESTORE.get() : INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname())); } /** {@inheritDoc} */ protected void verifyBackupClicked() { LinkedHashSet<LocalizableMessage> errors = new LinkedHashSet<>(); // Launch the task in another progress dialog. ProgressDialog dlg = new ProgressDialog( Utilities.createFrame(), Utilities.getParentDialog(this), INFO_CTRL_PANEL_VERIFY_BACKUP_TITLE.get(), getInfo()); RestoreTask newTask = new RestoreTask(getInfo(), dlg, true); for (Task task : getInfo().getTasks()) { task.canLaunch(newTask, errors); } if (errors.isEmpty()) { BackupDescriptor backup = getSelectedBackup(); launchOperation(newTask, INFO_CTRL_PANEL_VERIFYING_BACKUP_SUMMARY.get(backup.getID()), INFO_CTRL_PANEL_VERIFYING_BACKUP_SUCCESSFUL_SUMMARY.get(), INFO_CTRL_PANEL_VERIFYING_BACKUP_SUCCESSFUL_DETAILS.get(), ERR_CTRL_PANEL_VERIFYING_BACKUP_ERROR_SUMMARY.get(), null, ERR_CTRL_PANEL_VERIFYING_BACKUP_ERROR_DETAILS, dlg); dlg.setVisible(true); } else { displayErrorDialog(errors); } } /** * Creates the layout of the panel (but the contents are not populated here). */ private void createLayout() { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 3; addErrorPane(gbc); super.createLayout(gbc); gbc.insets.top = 10; gbc.gridx = 0; gbc.gridy ++; gbc.insets.left = 0; gbc.gridwidth = 1; lBackupID = Utilities.createPrimaryLabel( INFO_CTRL_PANEL_BACKUP_ID_LABEL.get()); add(lBackupID, gbc); backupID = Utilities.createMediumTextField(); gbc.weightx = 0.0; gbc.gridx = 1; gbc.insets.left = 10; gbc.insets.right = 40; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.WEST; gbc.gridwidth = 2; add(backupID, gbc); listener = new ListSelectionListener() { public void valueChanged(ListSelectionEvent ev) { BackupDescriptor backup = getSelectedBackup(); setEnabledOK(backup != null && !errorPane.isVisible()); } }; backupList.getSelectionModel().addListSelectionListener(listener); addBottomGlue(gbc); } /** {@inheritDoc} */ protected void checkOKButtonEnable() { listener.valueChanged(null); } /** {@inheritDoc} */ public void okClicked() { setPrimaryValid(lPath); setPrimaryValid(lAvailableBackups); setPrimaryValid(lBackupID); final LinkedHashSet<LocalizableMessage> errors = new LinkedHashSet<>(); BackupDescriptor backup = getSelectedBackup(); if (isLocal()) { boolean selected = backupList.isVisible() && backup != null; if (!selected) { if (backupList.getRowCount() == 0) { setPrimaryInvalid(lPath); errors.add(ERR_CTRL_PANEL_NO_PARENT_BACKUP_TO_VERIFY.get()); } else { errors.add(ERR_CTRL_PANEL_REQUIRED_BACKUP_TO_VERIFY.get()); } setPrimaryInvalid(lAvailableBackups); } } else { String parentPath = parentDirectory.getText(); if (parentPath == null || parentPath.trim().equals("")) { errors.add(ERR_CTRL_PANEL_NO_BACKUP_PATH_PROVIDED.get()); setPrimaryInvalid(lPath); } String id = backupID.getText(); if (id == null || id.trim().equals("")) { errors.add(ERR_CTRL_PANEL_NO_BACKUP_ID_PROVIDED.get()); setPrimaryInvalid(lBackupID); } } if (errors.isEmpty()) { ProgressDialog progressDialog = new ProgressDialog( Utilities.createFrame(), Utilities.getParentDialog(this), getTitle(), getInfo()); RestoreTask newTask = new RestoreTask(getInfo(), progressDialog, false); for (Task task : getInfo().getTasks()) { task.canLaunch(newTask, errors); } // Ask for confirmation boolean confirmed = true; if (errors.isEmpty()) { confirmed = displayConfirmationDialog( INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), INFO_CTRL_PANEL_CONFIRM_RESTORE_DETAILS.get()); } if (errors.isEmpty() && confirmed) { launchOperation(newTask, INFO_CTRL_PANEL_RESTORING_SUMMARY.get(backup.getID()), INFO_CTRL_PANEL_RESTORING_SUCCESSFUL_SUMMARY.get(), INFO_CTRL_PANEL_RESTORING_SUCCESSFUL_DETAILS.get(), ERR_CTRL_PANEL_RESTORING_ERROR_SUMMARY.get(), null, ERR_CTRL_PANEL_RESTORING_ERROR_DETAILS, progressDialog); progressDialog.setVisible(true); Utilities.getParentDialog(this).setVisible(false); } } if (!errors.isEmpty()) { displayErrorDialog(errors); } } /** {@inheritDoc} */ public void cancelClicked() { setPrimaryValid(lPath); setPrimaryValid(lAvailableBackups); super.cancelClicked(); } /** The task in charge of restoring or verifying the backup. */ protected class RestoreTask extends Task { private Set<String> backendSet; private String dir; private String backupID; private boolean verify; /** * The constructor of the task. * @param info the control panel info. * @param dlg the progress dialog that shows the progress of the task. * @param verify whether this is an actual restore or a verify of the * backup. */ public RestoreTask(ControlPanelInfo info, ProgressDialog dlg, boolean verify) { super(info, dlg); this.verify = verify; if (isLocal()) { BackupDescriptor backup = getSelectedBackup(); dir = backup.getPath().getAbsolutePath(); backupID = backup.getID(); } else { dir = parentDirectory.getText(); backupID = RestorePanel.this.backupID.getText(); } backendSet = new HashSet<>(); for (BackendDescriptor backend : info.getServerDescriptor().getBackends()) { if (!backend.isConfigBackend()) { backendSet.add(backend.getBackendID()); } } } /** {@inheritDoc} */ public Type getType() { return Type.RESTORE; } /** {@inheritDoc} */ public LocalizableMessage getTaskDescription() { if (verify) { return INFO_CTRL_PANEL_VERIFY_TASK_DESCRIPTION.get(backupID, dir); } else { return INFO_CTRL_PANEL_RESTORE_TASK_DESCRIPTION.get(backupID, dir); } } /** {@inheritDoc} */ public boolean canLaunch(Task taskToBeLaunched, Collection<LocalizableMessage> incompatibilityReasons) { boolean canLaunch = true; if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched)) { // All the operations are incompatible if they apply to this backend. Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends()); backends.retainAll(getBackends()); if (!backends.isEmpty()) { incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched)); canLaunch = false; } } return canLaunch; } /** {@inheritDoc} */ public void runTask() { state = State.RUNNING; lastException = null; try { ArrayList<String> arguments = getCommandLineArguments(); String[] args = new String[arguments.size()]; arguments.toArray(args); if (isServerRunning()) { returnCode = RestoreDB.mainRestoreDB(args, false, outPrintStream, errorPrintStream); } else { returnCode = executeCommandLine(getCommandLinePath(), args); } if (returnCode != 0) { state = State.FINISHED_WITH_ERROR; } else { if (!verify) { for (String backend : getBackends()) { getInfo().unregisterModifiedIndexesInBackend(backend); } } state = State.FINISHED_SUCCESSFULLY; } } catch (Throwable t) { lastException = t; state = State.FINISHED_WITH_ERROR; } HashSet<BackendDescriptor> backends = new HashSet<>(); for (BackendDescriptor backend : getInfo().getServerDescriptor().getBackends()) { for (String backendID : getBackends()) { if (backendID.equalsIgnoreCase(backend.getBackendID())) { backends.add(backend); break; } } } if (!backends.isEmpty()) { getInfo().backendPopulated(backends); } } /** {@inheritDoc} */ public Set<String> getBackends() { return backendSet; } /** {@inheritDoc} */ protected ArrayList<String> getCommandLineArguments() { ArrayList<String> args = new ArrayList<>(); args.add("--backupDirectory"); args.add(dir); args.add("--backupID"); args.add(backupID); if (verify) { args.add("--dry-run"); } args.addAll(getConnectionCommandLineArguments()); if (isServerRunning()) { args.addAll(getConfigCommandLineArguments()); } args.add(getNoPropertiesFileArgument()); return args; } /** {@inheritDoc} */ protected String getCommandLinePath() { return getCommandLinePath("restore"); } } }