/* * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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. */ package org.opends.guitools.controlpanel.ui; import static org.opends.messages.AdminToolMessages.*; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.ButtonGroup; import javax.swing.DefaultComboBoxModel; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; 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.ScheduleType; import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; import org.opends.guitools.controlpanel.task.Task; import org.opends.guitools.controlpanel.ui.components.ScheduleSummaryPanel; import org.opends.guitools.controlpanel.util.BackgroundTask; import org.opends.guitools.controlpanel.util.Utilities; import org.opends.messages.Message; import org.opends.server.tools.BackUpDB; import org.opends.server.types.BackupDirectory; import org.opends.server.types.BackupInfo; import org.opends.server.util.ServerConstants; /** * The panel that appears when the user clicks on 'Backup...'. * */ public class BackupPanel extends BackupListPanel { private static final long serialVersionUID = -1626301350756394814L; private JComboBox backends; private JCheckBox allBackends; private JTextField backupID; private JTextField parentBackupID; private JRadioButton fullBackup; private JRadioButton incrementalBackup; private JCheckBox compressData; private JCheckBox encryptData; private JCheckBox generateMessageDigest; private JCheckBox signMessageDigest; private JLabel lBackend; private JLabel lNoBackendsFound; private JLabel lBackupID; private JLabel lParentID; private JLabel lBackupType; private JLabel lBackupOptions; private ChangeListener changeListener; private boolean backupIDInitialized = false; private ScheduleSummaryPanel schedulePanel; private static final Logger LOG = Logger.getLogger(BackupPanel.class.getName()); /** * Default constructor. * */ public BackupPanel() { super(); createLayout(); } /** * {@inheritDoc} */ public Message getTitle() { return INFO_CTRL_PANEL_BACKUP_TITLE.get(); } /** * {@inheritDoc} */ public Component getPreferredFocusComponent() { return backupID; } /** * {@inheritDoc} */ protected void verifyBackupClicked() { // Nothing to do: the button is not visible. } /** * Creates the layout of the panel (but the contents are not populated here). * */ private void createLayout() { GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 3; addErrorPane(gbc); gbc.weightx = 0.0; gbc.gridy ++; gbc.gridwidth = 1; gbc.fill = GridBagConstraints.NONE; lBackend = Utilities.createPrimaryLabel( INFO_CTRL_PANEL_BACKEND_LABEL.get()); add(lBackend, gbc); gbc.insets.left = 10; gbc.gridx = 1; gbc.gridwidth = 2; JPanel auxPanel = new JPanel(new GridBagLayout()); add(auxPanel, gbc); auxPanel.setOpaque(false); GridBagConstraints gbc2 = new GridBagConstraints(); backends = Utilities.createComboBox(); backends.setModel(new DefaultComboBoxModel(new String[]{})); auxPanel.add(backends, gbc2); lNoBackendsFound = Utilities.createDefaultLabel( INFO_CTRL_PANEL_NO_BACKENDS_FOUND_LABEL.get()); add(lNoBackendsFound, gbc); lNoBackendsFound.setVisible(false); gbc2.insets.left = 10; allBackends = Utilities.createCheckBox( INFO_CTRL_PANEL_BACKUP_ALL_BACKENDS_LABEL.get()); auxPanel.add(allBackends, gbc2); gbc.insets.top = 10; gbc.gridx = 0; gbc.gridy ++; gbc.insets.left = 0; gbc.gridwidth = 1; lBackupType = Utilities.createPrimaryLabel( INFO_CTRL_PANEL_BACKUP_TYPE_LABEL.get()); add(lBackupType, gbc); gbc.insets.left = 10; gbc.gridx = 1; gbc.gridwidth = 2; fullBackup = Utilities.createRadioButton( INFO_CTRL_PANEL_FULL_BACKUP_LABEL.get()); add(fullBackup, gbc); gbc.gridy ++; gbc.insets.top = 5; incrementalBackup = Utilities.createRadioButton( INFO_CTRL_PANEL_INCREMENTAL_BACKUP_LABEL.get()); add(incrementalBackup, gbc); ButtonGroup group = new ButtonGroup(); group.add(fullBackup); group.add(incrementalBackup); fullBackup.setSelected(true); 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 ++; gbc.insets.left = 10; gbc.fill = GridBagConstraints.NONE; gbc.gridwidth = 2; add(backupID, gbc); gbc.insets.top = 10; gbc.gridx = 0; gbc.gridy ++; super.createLayout(gbc); verifyBackup.setVisible(false); lAvailableBackups.setText( INFO_CTRL_PANEL_AVAILABLE_PARENT_BACKUPS_LABEL.get().toString()); gbc.gridx = 0; gbc.gridy ++; gbc.insets.left = 0; gbc.insets.top = 10; gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.WEST; lParentID = Utilities.createPrimaryLabel( INFO_CTRL_PANEL_PARENT_BACKUP_ID_LABEL.get()); add(lParentID, gbc); parentBackupID = Utilities.createMediumTextField(); gbc.weightx = 0.0; gbc.gridx ++; gbc.insets.left = 10; gbc.fill = GridBagConstraints.NONE; gbc.gridwidth = 2; add(parentBackupID, gbc); gbc.gridy ++; gbc.gridx = 0; gbc.gridwidth = 1; gbc.insets.left = 0; lBackupOptions = Utilities.createPrimaryLabel( INFO_CTRL_PANEL_BACKUP_OPTIONS_LABEL.get()); add(lBackupOptions, gbc); schedulePanel = new ScheduleSummaryPanel( INFO_CTRL_PANEL_BACKUP_TASK_NAME.get().toString()); schedulePanel.setSchedule(ScheduleType.createLaunchNow()); gbc.insets.left = 10; gbc.gridx = 1; gbc.gridwidth = 2; add(schedulePanel, gbc); compressData = Utilities.createCheckBox( INFO_CTRL_PANEL_COMPRESS_DATA_LABEL.get()); compressData.setSelected(false); gbc.gridy ++; gbc.insets.top = 5; add(compressData, gbc); encryptData = Utilities.createCheckBox( INFO_CTRL_PANEL_ENCRYPT_DATA_LABEL.get()); gbc.gridy ++; add(encryptData, gbc); encryptData.setSelected(false); generateMessageDigest = Utilities.createCheckBox( INFO_CTRL_PANEL_GENERATE_MESSAGE_DIGEST_LABEL.get()); gbc.gridy ++; add(generateMessageDigest, gbc); signMessageDigest = Utilities.createCheckBox( INFO_CTRL_PANEL_SIGN_MESSAGE_DIGEST_HASH_LABEL.get()); gbc.insets.left = 30; gbc.gridy ++; add(signMessageDigest, gbc); generateMessageDigest.setSelected(false); changeListener = new ChangeListener() { /** * {@inheritDoc} */ public void stateChanged(ChangeEvent ev) { backends.setEnabled(!allBackends.isSelected()); signMessageDigest.setEnabled(generateMessageDigest.isSelected()); boolean enable = incrementalBackup.isSelected(); refreshList.setEnabled(enable); tableScroll.setEnabled(enable); backupList.setEnabled(enable); lAvailableBackups.setEnabled(enable); lRefreshingList.setEnabled(enable); lParentID.setEnabled(enable); parentBackupID.setEnabled(enable); verifyBackup.setEnabled(enable && getSelectedBackup() != null); } }; incrementalBackup.addChangeListener(changeListener); generateMessageDigest.addChangeListener(changeListener); allBackends.addChangeListener(changeListener); changeListener.stateChanged(null); addBottomGlue(gbc); } /** * {@inheritDoc} */ public void configurationChanged(ConfigurationChangeEvent ev) { final ServerDescriptor desc = ev.getNewDescriptor(); updateSimpleBackendComboBoxModel(backends, lNoBackendsFound, desc); SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { allBackends.setVisible(backends.getModel().getSize() > 0); lParentID.setVisible(!desc.isLocal()); parentBackupID.setVisible(!desc.isLocal()); if (desc.isLocal()) { lPath.setText(INFO_CTRL_PANEL_BACKUP_PATH_LABEL.get().toString()); } else { lPath.setText( INFO_CTRL_PANEL_PARENT_BACKUP_PATH_LABEL.get().toString()); } } }); super.configurationChanged(ev); updateErrorPaneAndOKButtonIfAuthRequired(desc, isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_BACKUP.get() : INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname())); } /** * {@inheritDoc} */ public void okClicked() { setPrimaryValid(lBackend); setPrimaryValid(lPath); setPrimaryValid(lAvailableBackups); setPrimaryValid(lParentID); setPrimaryValid(lBackupOptions); backupIDInitialized = false; final LinkedHashSet<Message> errors = new LinkedHashSet<Message>(); if (!allBackends.isSelected()) { String backendName = (String)backends.getSelectedItem(); if (backendName == null) { errors.add(ERR_CTRL_PANEL_NO_BACKENDS_SELECTED.get()); setPrimaryInvalid(lBackend); } } else { if (backends.getModel().getSize() == 0) { errors.add(ERR_CTRL_PANEL_NO_BACKENDS_AVAILABLE.get()); setPrimaryInvalid(lBackend); } } String parentPath = parentDirectory.getText(); if ((parentPath == null) || (parentPath.trim().equals(""))) { errors.add(ERR_CTRL_PANEL_NO_BACKUP_PATH_PROVIDED.get()); setPrimaryInvalid(lPath); } else if (isLocal()) { File f = new File(parentPath); if (f.isFile()) { errors.add(ERR_CTRL_PANEL_BACKUP_PATH_IS_A_FILE.get(parentPath)); setPrimaryInvalid(lPath); } else if (!f.exists()) { errors.add(ERR_CTRL_PANEL_BACKUP_PATH_DOES_NOT_EXIST.get(parentPath)); setPrimaryInvalid(lPath); } } String dir = backupID.getText(); if ((dir == null) || (dir.trim().equals(""))) { errors.add(ERR_CTRL_PANEL_NO_BACKUP_ID_PROVIDED.get()); setPrimaryInvalid(lBackupID); } if (errors.isEmpty() && isLocal()) { File f = new File(parentPath, dir); if (f.isFile()) { errors.add(ERR_CTRL_PANEL_BACKUP_PATH_EXISTS.get( f.getAbsolutePath())); setPrimaryInvalid(lPath); } } if (incrementalBackup.isSelected()) { if (isLocal()) { boolean selected = backupList.isVisible() && (getSelectedBackup() != null); if (!selected) { errors.add(ERR_CTRL_PANEL_NO_PARENT_BACKUP_SELECTED.get()); setPrimaryInvalid(lAvailableBackups); } } else { String parentID = parentBackupID.getText(); if ((parentID == null) || (parentID.trim().equals(""))) { errors.add(ERR_CTRL_PANEL_NO_PARENT_BACKUP_ID_PROVIDED.get()); setPrimaryInvalid(lParentID); } } } addScheduleErrors(getSchedule(), errors, lBackupOptions); // Check that there is not a backup with the provided ID final JComponent[] components = { backends, allBackends, fullBackup, incrementalBackup, parentDirectory, browse, backupList, refreshList, compressData, encryptData, generateMessageDigest, signMessageDigest }; setEnabledOK(false); setEnabledCancel(false); for (int i=0; i<components.length; i++) { components[i].setEnabled(false); } final String id = backupID.getText(); final String path = parentDirectory.getText(); BackgroundTask<Void> worker = new BackgroundTask<Void>() { /** * {@inheritDoc} */ public Void processBackgroundTask() throws Throwable { // Open the backup directory and make sure it is valid. LinkedHashSet<BackupInfo> backups = new LinkedHashSet<BackupInfo>(); try { BackupDirectory backupDir = BackupDirectory.readBackupDirectoryDescriptor(path); backups.addAll(backupDir.getBackups().values()); } catch (Throwable t) { // Check the subdirectories File f = new File(path); if (f.isDirectory()) { File[] children = f.listFiles(); for (int i=0; i<children.length; i++) { if (children[i].isDirectory()) { try { BackupDirectory backupDir = BackupDirectory.readBackupDirectoryDescriptor( children[i].getAbsolutePath()); backups.addAll(backupDir.getBackups().values()); } catch (Throwable t2) { if (!children[i].getName().equals("tasks")) { LOG.log(Level.WARNING, "Error searching backup: "+t2, t2); } } } } } } for (BackupInfo backup : backups) { if (backup.getBackupID().equalsIgnoreCase(id)) { errors.add(ERR_CTRL_PANEL_BACKUP_ID_ALREADY_EXIST.get(id, path)); SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { setPrimaryInvalid(lBackupID); } }); break; } } return null; } /** * {@inheritDoc} */ public void backgroundTaskCompleted(Void returnValue, Throwable t) { for (int i=0; i<components.length; i++) { components[i].setEnabled(true); } setEnabledOK(true); setEnabledCancel(true); changeListener.stateChanged(null); if (errors.isEmpty()) { ProgressDialog progressDialog = new ProgressDialog( Utilities.createFrame(), Utilities.getParentDialog(BackupPanel.this), getTitle(), getInfo()); BackupTask newTask = new BackupTask(getInfo(), progressDialog); for (Task task : getInfo().getTasks()) { task.canLaunch(newTask, errors); } if (errors.isEmpty()) { Message initMsg; if (allBackends.isSelected()) { initMsg = INFO_CTRL_PANEL_RUN_BACKUP_ALL_BACKENDS.get(); } else { initMsg = INFO_CTRL_PANEL_RUN_BACKUP_SUMMARY.get( backends.getSelectedItem().toString()); } launchOperation(newTask, initMsg, INFO_CTRL_PANEL_RUN_BACKUP_SUCCESSFUL_SUMMARY.get(), INFO_CTRL_PANEL_RUN_BACKUP_SUCCESSFUL_DETAILS.get(), ERR_CTRL_PANEL_RUN_BACKUP_ERROR_SUMMARY.get(), null, ERR_CTRL_PANEL_RUN_BACKUP_ERROR_DETAILS, progressDialog); progressDialog.setVisible(true); Utilities.getParentDialog(BackupPanel.this).setVisible(false); } } if (errors.size() > 0) { displayErrorDialog(errors); } } }; if (errors.isEmpty()) { worker.startBackgroundTask(); } else { worker.backgroundTaskCompleted(null, null); } } private ScheduleType getSchedule() { return schedulePanel.getSchedule(); } /** * {@inheritDoc} */ public void cancelClicked() { setPrimaryValid(lBackend); setPrimaryValid(lPath); setPrimaryValid(lAvailableBackups); setPrimaryValid(lBackupOptions); super.cancelClicked(); } /** * {@inheritDoc} */ public void toBeDisplayed(boolean visible) { super.toBeDisplayed(visible); if (visible && !backupIDInitialized) { initializeBackupID(); } if (!visible) { backupIDInitialized = false; } } /** * Initialize the backup ID field with a value. * */ private void initializeBackupID() { SimpleDateFormat dateFormat = new SimpleDateFormat( ServerConstants.DATE_FORMAT_COMPACT_LOCAL_TIME); final String id = dateFormat.format(new Date()); backupID.setText(id); } /** * Class that launches the backup. * */ protected class BackupTask extends Task { private Set<String> backendSet; private String dir; /** * The constructor of the task. * @param info the control panel info. * @param dlg the progress dialog that shows the progress of the task. */ public BackupTask(ControlPanelInfo info, ProgressDialog dlg) { super(info, dlg); backendSet = new HashSet<String>(); if (!allBackends.isSelected()) { backendSet.add((String)backends.getSelectedItem()); } else { for (BackendDescriptor backend : info.getServerDescriptor().getBackends()) { if (!backend.isConfigBackend()) { backendSet.add(backend.getBackendID()); } } } if (incrementalBackup.isSelected()) { if (isLocal()) { BackupDescriptor backup = getSelectedBackup(); dir = backup.getPath().getAbsolutePath(); } else { dir = parentDirectory.getText(); } } else { dir = parentDirectory.getText(); } } /** * {@inheritDoc} */ public Type getType() { return Type.BACKUP; } /** * {@inheritDoc} */ public Message getTaskDescription() { return INFO_CTRL_PANEL_BACKUP_TASK_DESCRIPTION.get( Utilities.getStringFromCollection(backendSet, ", "), dir); } /** * {@inheritDoc} */ public boolean canLaunch(Task taskToBeLaunched, Collection<Message> 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<String>(taskToBeLaunched.getBackends()); backends.retainAll(getBackends()); if (backends.size() > 0) { 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 = BackUpDB.mainBackUpDB(args, false, outPrintStream, errorPrintStream); } else { returnCode = executeCommandLine(getCommandLinePath(), args); } if (returnCode != 0) { state = State.FINISHED_WITH_ERROR; } else { getInfo().backupCreated( new BackupDescriptor( new File(parentDirectory.getText()), new Date(), fullBackup.isSelected() ? BackupDescriptor.Type.FULL : BackupDescriptor.Type.INCREMENTAL, backupID.getText())); state = State.FINISHED_SUCCESSFULLY; } } catch (Throwable t) { lastException = t; state = State.FINISHED_WITH_ERROR; } } /** * {@inheritDoc} */ public Set<String> getBackends() { return backendSet; } /** * {@inheritDoc} */ protected ArrayList<String> getCommandLineArguments() { ArrayList<String> args = new ArrayList<String>(); args.add("--backupDirectory"); args.add(dir); args.add("--backupID"); args.add(backupID.getText()); if (allBackends.isSelected()) { args.add("--backUpAll"); } else { args.add("--backendID"); args.add((String)backends.getSelectedItem()); } if (incrementalBackup.isSelected()) { args.add("--incremental"); if (isLocal()) { BackupDescriptor backup = getSelectedBackup(); args.add("--incrementalBaseID"); args.add(backup.getID()); } else { args.add("--incrementalBaseID"); args.add(parentBackupID.getText()); } } if (compressData.isSelected()) { args.add("--compress"); } if (encryptData.isSelected()) { args.add("--encrypt"); } if (generateMessageDigest.isSelected()) { args.add("--hash"); if (signMessageDigest.isSelected()) { args.add("--signHash"); } } args.addAll(getConnectionCommandLineArguments()); args.addAll(getScheduleArgs(getSchedule())); if (isServerRunning()) { args.addAll(getConfigCommandLineArguments()); } args.add(getNoPropertiesFileArgument()); return args; } /** * {@inheritDoc} */ protected String getCommandLinePath() { return getCommandLinePath("backup"); } }; }