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 2008-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2015 ForgeRock AS.
016 */
017
018package org.opends.guitools.controlpanel.ui;
019
020import static org.opends.messages.AdminToolMessages.*;
021
022import java.awt.Component;
023import java.awt.GridBagConstraints;
024import java.awt.GridBagLayout;
025import java.io.File;
026import java.text.SimpleDateFormat;
027import java.util.ArrayList;
028import java.util.Collection;
029import java.util.Date;
030import java.util.HashSet;
031import java.util.LinkedHashSet;
032import java.util.Set;
033import java.util.TreeSet;
034
035import org.forgerock.i18n.LocalizableMessage;
036import org.forgerock.i18n.slf4j.LocalizedLogger;
037
038import javax.swing.ButtonGroup;
039import javax.swing.DefaultComboBoxModel;
040import javax.swing.JCheckBox;
041import javax.swing.JComboBox;
042import javax.swing.JComponent;
043import javax.swing.JLabel;
044import javax.swing.JPanel;
045import javax.swing.JRadioButton;
046import javax.swing.JTextField;
047import javax.swing.SwingUtilities;
048import javax.swing.event.ChangeEvent;
049import javax.swing.event.ChangeListener;
050
051import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
052import org.opends.guitools.controlpanel.datamodel.BackupDescriptor;
053import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
054import org.opends.guitools.controlpanel.datamodel.ScheduleType;
055import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
056import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
057import org.opends.guitools.controlpanel.task.Task;
058import org.opends.guitools.controlpanel.ui.components.ScheduleSummaryPanel;
059import org.opends.guitools.controlpanel.util.BackgroundTask;
060import org.opends.guitools.controlpanel.util.Utilities;
061import org.opends.server.tools.BackUpDB;
062import org.opends.server.types.BackupDirectory;
063import org.opends.server.types.BackupInfo;
064import org.opends.server.util.ServerConstants;
065
066/**
067 * The panel that appears when the user clicks on 'Backup...'.
068 *
069 */
070public class BackupPanel extends BackupListPanel
071{
072  private static final long serialVersionUID = -1626301350756394814L;
073  private JComboBox backends;
074  private JCheckBox allBackends;
075  private JTextField backupID;
076  private JTextField parentBackupID;
077  private JRadioButton fullBackup;
078  private JCheckBox incrementalParent;
079  private JRadioButton incrementalBackup;
080  private JCheckBox compressData;
081  private JCheckBox encryptData;
082  private JCheckBox generateMessageDigest;
083  private JCheckBox signMessageDigest;
084
085  private JLabel lBackend;
086  private JLabel lNoBackendsFound;
087  private JLabel lBackupID;
088  private JLabel lParentID;
089  private JLabel lBackupType;
090  private JLabel lBackupOptions;
091
092  private ChangeListener changeListener;
093
094  private boolean backupIDInitialized;
095
096  private ScheduleSummaryPanel schedulePanel;
097
098  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
099
100  /**
101   * Default constructor.
102   *
103   */
104  public BackupPanel()
105  {
106    super();
107    createLayout();
108  }
109
110  /** {@inheritDoc} */
111  public LocalizableMessage getTitle()
112  {
113    return INFO_CTRL_PANEL_BACKUP_TITLE.get();
114  }
115
116  /** {@inheritDoc} */
117  public Component getPreferredFocusComponent()
118  {
119    return backupID;
120  }
121
122  /** {@inheritDoc} */
123  protected void verifyBackupClicked()
124  {
125    // Nothing to do: the button is not visible.
126  }
127
128  /**
129   * Creates the layout of the panel (but the contents are not populated here).
130   *
131   */
132  private void createLayout()
133  {
134    GridBagConstraints gbc = new GridBagConstraints();
135    gbc.anchor = GridBagConstraints.WEST;
136    gbc.gridx = 0;
137    gbc.gridy = 0;
138    gbc.gridwidth = 3;
139    addErrorPane(gbc);
140
141    gbc.weightx = 0.0;
142    gbc.gridy ++;
143    gbc.gridwidth = 1;
144    gbc.fill = GridBagConstraints.NONE;
145    lBackend = Utilities.createPrimaryLabel(
146        INFO_CTRL_PANEL_BACKEND_LABEL.get());
147    add(lBackend, gbc);
148    gbc.insets.left = 10;
149    gbc.gridx = 1;
150    gbc.gridwidth = 2;
151    JPanel auxPanel = new JPanel(new GridBagLayout());
152    add(auxPanel, gbc);
153    auxPanel.setOpaque(false);
154    GridBagConstraints gbc2 = new GridBagConstraints();
155    backends = Utilities.createComboBox();
156    backends.setModel(new DefaultComboBoxModel(new String[]{}));
157    auxPanel.add(backends, gbc2);
158    lNoBackendsFound = Utilities.createDefaultLabel(
159        INFO_CTRL_PANEL_NO_BACKENDS_FOUND_LABEL.get());
160    add(lNoBackendsFound, gbc);
161    lNoBackendsFound.setVisible(false);
162    gbc2.insets.left = 10;
163    allBackends = Utilities.createCheckBox(
164        INFO_CTRL_PANEL_BACKUP_ALL_BACKENDS_LABEL.get());
165    auxPanel.add(allBackends, gbc2);
166
167    gbc.insets.top = 10;
168    gbc.gridx = 0;
169    gbc.gridy ++;
170    gbc.insets.left = 0;
171    gbc.gridwidth = 1;
172    lBackupType = Utilities.createPrimaryLabel(
173        INFO_CTRL_PANEL_BACKUP_TYPE_LABEL.get());
174    add(lBackupType, gbc);
175    gbc.insets.left = 10;
176    gbc.gridx = 1;
177    gbc.gridwidth = 2;
178    fullBackup = Utilities.createRadioButton(
179        INFO_CTRL_PANEL_FULL_BACKUP_LABEL.get());
180    add(fullBackup, gbc);
181
182    gbc.gridy ++;
183    gbc.insets.top = 5;
184    incrementalBackup = Utilities.createRadioButton(
185        INFO_CTRL_PANEL_INCREMENTAL_BACKUP_LABEL.get());
186    add(incrementalBackup, gbc);
187
188    gbc.gridy ++;
189    gbc.insets.left = 25;
190    incrementalParent = Utilities.createCheckBox(
191        INFO_CTRL_PANEL_INCREMENTAL_PARENT_LABEL.get());
192    add(incrementalParent, gbc);
193
194    ButtonGroup group = new ButtonGroup();
195    group.add(fullBackup);
196    group.add(incrementalBackup);
197    fullBackup.setSelected(true);
198
199    gbc.insets.top = 10;
200    gbc.gridx = 0;
201    gbc.gridy ++;
202    gbc.insets.left = 0;
203    gbc.gridwidth = 1;
204    lBackupID = Utilities.createPrimaryLabel(
205        INFO_CTRL_PANEL_BACKUP_ID_LABEL.get());
206    add(lBackupID, gbc);
207    backupID = Utilities.createMediumTextField();
208    gbc.weightx = 0.0;
209    gbc.gridx ++;
210    gbc.insets.left = 10;
211    gbc.fill = GridBagConstraints.NONE;
212    gbc.gridwidth = 2;
213    add(backupID, gbc);
214
215    gbc.insets.top = 10;
216    gbc.gridx = 0;
217    gbc.gridy ++;
218    super.createLayout(gbc);
219
220    verifyBackup.setVisible(false);
221    lAvailableBackups.setText(
222        INFO_CTRL_PANEL_AVAILABLE_PARENT_BACKUPS_LABEL.get().toString());
223    gbc.gridx = 0;
224    gbc.gridy ++;
225    gbc.insets.left = 0;
226    gbc.insets.top = 10;
227    gbc.gridwidth = 1;
228    gbc.anchor = GridBagConstraints.WEST;
229    lParentID = Utilities.createPrimaryLabel(
230        INFO_CTRL_PANEL_PARENT_BACKUP_ID_LABEL.get());
231    add(lParentID, gbc);
232    parentBackupID = Utilities.createMediumTextField();
233    gbc.weightx = 0.0;
234    gbc.gridx ++;
235    gbc.insets.left = 10;
236    gbc.fill = GridBagConstraints.NONE;
237    gbc.gridwidth = 2;
238    add(parentBackupID, gbc);
239
240    gbc.gridy ++;
241    gbc.gridx = 0;
242    gbc.gridwidth = 1;
243    gbc.insets.left = 0;
244    lBackupOptions = Utilities.createPrimaryLabel(
245        INFO_CTRL_PANEL_BACKUP_OPTIONS_LABEL.get());
246    add(lBackupOptions, gbc);
247
248    schedulePanel = new ScheduleSummaryPanel(
249        INFO_CTRL_PANEL_BACKUP_TASK_NAME.get().toString());
250    schedulePanel.setSchedule(ScheduleType.createLaunchNow());
251
252    gbc.insets.left = 10;
253    gbc.gridx = 1;
254    gbc.gridwidth = 2;
255    add(schedulePanel, gbc);
256
257    compressData = Utilities.createCheckBox(
258        INFO_CTRL_PANEL_COMPRESS_DATA_LABEL.get());
259    compressData.setSelected(false);
260
261    gbc.gridy ++;
262    gbc.insets.top = 5;
263    add(compressData, gbc);
264
265    encryptData = Utilities.createCheckBox(
266        INFO_CTRL_PANEL_ENCRYPT_DATA_LABEL.get());
267
268    gbc.gridy ++;
269    add(encryptData, gbc);
270    encryptData.setSelected(false);
271    generateMessageDigest = Utilities.createCheckBox(
272        INFO_CTRL_PANEL_GENERATE_MESSAGE_DIGEST_LABEL.get());
273
274    gbc.gridy ++;
275    add(generateMessageDigest, gbc);
276
277    signMessageDigest = Utilities.createCheckBox(
278        INFO_CTRL_PANEL_SIGN_MESSAGE_DIGEST_HASH_LABEL.get());
279    gbc.insets.left = 30;
280    gbc.gridy ++;
281    add(signMessageDigest, gbc);
282    generateMessageDigest.setSelected(false);
283
284    changeListener = new ChangeListener()
285    {
286      /** {@inheritDoc} */
287      public void stateChanged(ChangeEvent ev)
288      {
289        backends.setEnabled(!allBackends.isSelected());
290        signMessageDigest.setEnabled(generateMessageDigest.isSelected());
291        incrementalParent.setEnabled(incrementalBackup.isSelected());
292        boolean enable = isIncrementalWithParent();
293        refreshList.setEnabled(enable);
294        tableScroll.setEnabled(enable);
295        backupList.setEnabled(enable);
296        lAvailableBackups.setEnabled(enable);
297        lRefreshingList.setEnabled(enable);
298        lParentID.setEnabled(enable);
299        parentBackupID.setEnabled(enable);
300        verifyBackup.setEnabled(enable && getSelectedBackup() != null);
301      }
302    };
303    incrementalBackup.addChangeListener(changeListener);
304    incrementalParent.addChangeListener(changeListener);
305    generateMessageDigest.addChangeListener(changeListener);
306    allBackends.addChangeListener(changeListener);
307    changeListener.stateChanged(null);
308
309    addBottomGlue(gbc);
310  }
311
312  /**
313   * Check status of incremental backup radio/checkbox
314   *
315   * @return boolean true if both incremental and parent base ID
316   *                  are selected
317   */
318  private boolean isIncrementalWithParent()
319  {
320    return incrementalParent.isSelected() &&
321            incrementalBackup.isSelected();
322  }
323
324  /** {@inheritDoc} */
325  public void configurationChanged(ConfigurationChangeEvent ev)
326  {
327    final ServerDescriptor desc = ev.getNewDescriptor();
328    updateSimpleBackendComboBoxModel(backends, lNoBackendsFound, desc);
329    SwingUtilities.invokeLater(new Runnable()
330    {
331      /** {@inheritDoc} */
332      public void run()
333      {
334        allBackends.setVisible(backends.getModel().getSize() > 0);
335        lParentID.setVisible(!desc.isLocal());
336        parentBackupID.setVisible(!desc.isLocal());
337        if (desc.isLocal())
338        {
339          lPath.setText(INFO_CTRL_PANEL_BACKUP_PATH_LABEL.get().toString());
340        }
341        else
342        {
343          lPath.setText(
344              INFO_CTRL_PANEL_PARENT_BACKUP_PATH_LABEL.get().toString());
345        }
346      }
347    });
348    super.configurationChanged(ev);
349    updateErrorPaneAndOKButtonIfAuthRequired(desc,
350        isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_BACKUP.get() :
351      INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname()));
352  }
353
354  /** {@inheritDoc} */
355  public void okClicked()
356  {
357    setPrimaryValid(lBackend);
358    setPrimaryValid(lPath);
359    setPrimaryValid(lAvailableBackups);
360    setPrimaryValid(lParentID);
361    setPrimaryValid(lBackupOptions);
362    backupIDInitialized = false;
363
364    final LinkedHashSet<LocalizableMessage> errors = new LinkedHashSet<>();
365
366    if (!allBackends.isSelected())
367    {
368      String backendName = (String)backends.getSelectedItem();
369      if (backendName == null)
370      {
371        errors.add(ERR_CTRL_PANEL_NO_BACKENDS_SELECTED.get());
372        setPrimaryInvalid(lBackend);
373      }
374    }
375    else
376    {
377      if (backends.getModel().getSize() == 0)
378      {
379        errors.add(ERR_CTRL_PANEL_NO_BACKENDS_AVAILABLE.get());
380        setPrimaryInvalid(lBackend);
381      }
382    }
383
384    String parentPath = parentDirectory.getText();
385    if (parentPath == null || parentPath.trim().equals(""))
386    {
387      errors.add(ERR_CTRL_PANEL_NO_BACKUP_PATH_PROVIDED.get());
388      setPrimaryInvalid(lPath);
389    }
390    else if (isLocal())
391    {
392      File f = new File(parentPath);
393      if (f.isFile())
394      {
395        errors.add(ERR_CTRL_PANEL_BACKUP_PATH_IS_A_FILE.get(parentPath));
396        setPrimaryInvalid(lPath);
397      }
398      else if (!f.exists())
399      {
400        errors.add(ERR_CTRL_PANEL_BACKUP_PATH_DOES_NOT_EXIST.get(parentPath));
401        setPrimaryInvalid(lPath);
402      }
403    }
404    String dir = backupID.getText();
405    if (dir == null || dir.trim().equals(""))
406    {
407      errors.add(ERR_CTRL_PANEL_NO_BACKUP_ID_PROVIDED.get());
408      setPrimaryInvalid(lBackupID);
409    }
410
411    if (errors.isEmpty() && isLocal())
412    {
413      File f = new File(parentPath, dir);
414      if (f.isFile())
415      {
416        errors.add(ERR_CTRL_PANEL_BACKUP_PATH_EXISTS.get(
417            f.getAbsolutePath()));
418        setPrimaryInvalid(lPath);
419      }
420    }
421
422    if (isIncrementalWithParent())
423    {
424      if (isLocal())
425      {
426        boolean selected = backupList.isVisible() && getSelectedBackup() != null;
427        if (!selected)
428        {
429          errors.add(ERR_CTRL_PANEL_NO_PARENT_BACKUP_SELECTED.get());
430          setPrimaryInvalid(lAvailableBackups);
431        }
432      }
433      else
434      {
435        String parentID = parentBackupID.getText();
436        if (parentID == null || parentID.trim().equals(""))
437        {
438          errors.add(ERR_CTRL_PANEL_NO_PARENT_BACKUP_ID_PROVIDED.get());
439          setPrimaryInvalid(lParentID);
440        }
441      }
442    }
443
444    addScheduleErrors(getSchedule(), errors, lBackupOptions);
445
446    // Check that there is not a backup with the provided ID
447    final JComponent[] components =
448    {
449        backends, allBackends, fullBackup, incrementalBackup, parentDirectory,
450        browse, backupList, refreshList, compressData, encryptData,
451        generateMessageDigest, signMessageDigest, incrementalParent
452    };
453    setEnabledOK(false);
454    setEnabledCancel(false);
455    for (int i=0; i<components.length; i++)
456    {
457      components[i].setEnabled(false);
458    }
459    final String id = backupID.getText();
460    final String path = parentDirectory.getText();
461    BackgroundTask<Void> worker = new BackgroundTask<Void>()
462    {
463      /** {@inheritDoc} */
464      public Void processBackgroundTask() throws Throwable
465      {
466        // Open the backup directory and make sure it is valid.
467        LinkedHashSet<BackupInfo> backups = new LinkedHashSet<>();
468        try
469        {
470          BackupDirectory backupDir =
471            BackupDirectory.readBackupDirectoryDescriptor(path);
472          backups.addAll(backupDir.getBackups().values());
473        }
474        catch (Throwable t)
475        {
476          // Check the subdirectories
477          File f = new File(path);
478
479          if (f.isDirectory())
480          {
481            File[] children = f.listFiles();
482            for (int i=0; i<children.length; i++)
483            {
484              if (children[i].isDirectory())
485              {
486                try
487                {
488                  BackupDirectory backupDir =
489                    BackupDirectory.readBackupDirectoryDescriptor(
490                        children[i].getAbsolutePath());
491
492                  backups.addAll(backupDir.getBackups().values());
493                }
494                catch (Throwable t2)
495                {
496                  if (!children[i].getName().equals("tasks"))
497                  {
498                    logger.warn(LocalizableMessage.raw("Error searching backup: "+t2, t2));
499                  }
500                }
501              }
502            }
503          }
504        }
505        for (BackupInfo backup : backups)
506        {
507          if (backup.getBackupID().equalsIgnoreCase(id))
508          {
509            errors.add(ERR_CTRL_PANEL_BACKUP_ID_ALREADY_EXIST.get(id, path));
510            SwingUtilities.invokeLater(new Runnable()
511            {
512              /** {@inheritDoc} */
513              public void run()
514              {
515                setPrimaryInvalid(lBackupID);
516              }
517            });
518            break;
519          }
520        }
521        return null;
522      }
523      /** {@inheritDoc} */
524      public void backgroundTaskCompleted(Void returnValue,
525          Throwable t)
526      {
527        for (int i=0; i<components.length; i++)
528        {
529          components[i].setEnabled(true);
530        }
531        setEnabledOK(true);
532        setEnabledCancel(true);
533        changeListener.stateChanged(null);
534        if (errors.isEmpty())
535        {
536          ProgressDialog progressDialog = new ProgressDialog(
537              Utilities.createFrame(),
538              Utilities.getParentDialog(BackupPanel.this),
539              getTitle(), getInfo());
540          BackupTask newTask = new BackupTask(getInfo(), progressDialog);
541          for (Task task : getInfo().getTasks())
542          {
543            task.canLaunch(newTask, errors);
544          }
545          if (errors.isEmpty())
546          {
547            LocalizableMessage initMsg;
548            if (allBackends.isSelected())
549            {
550              initMsg = INFO_CTRL_PANEL_RUN_BACKUP_ALL_BACKENDS.get();
551            }
552            else
553            {
554              initMsg = INFO_CTRL_PANEL_RUN_BACKUP_SUMMARY.get(
555                  backends.getSelectedItem());
556            }
557            launchOperation(newTask,
558                initMsg,
559                INFO_CTRL_PANEL_RUN_BACKUP_SUCCESSFUL_SUMMARY.get(),
560                INFO_CTRL_PANEL_RUN_BACKUP_SUCCESSFUL_DETAILS.get(),
561                ERR_CTRL_PANEL_RUN_BACKUP_ERROR_SUMMARY.get(),
562                null,
563                ERR_CTRL_PANEL_RUN_BACKUP_ERROR_DETAILS,
564                progressDialog);
565            progressDialog.setVisible(true);
566            Utilities.getParentDialog(BackupPanel.this).setVisible(false);
567          }
568        }
569        if (!errors.isEmpty())
570        {
571          displayErrorDialog(errors);
572        }
573      }
574    };
575    if (errors.isEmpty())
576    {
577      worker.startBackgroundTask();
578    }
579    else
580    {
581      worker.backgroundTaskCompleted(null, null);
582    }
583  }
584
585  private ScheduleType getSchedule()
586  {
587    return schedulePanel.getSchedule();
588  }
589
590  /** {@inheritDoc} */
591  public void cancelClicked()
592  {
593    setPrimaryValid(lBackend);
594    setPrimaryValid(lPath);
595    setPrimaryValid(lAvailableBackups);
596    setPrimaryValid(lBackupOptions);
597
598    super.cancelClicked();
599  }
600
601  /** {@inheritDoc} */
602  public void toBeDisplayed(boolean visible)
603  {
604    super.toBeDisplayed(visible);
605    if (visible && !backupIDInitialized)
606    {
607      initializeBackupID();
608    }
609    if (!visible)
610    {
611      backupIDInitialized = false;
612    }
613  }
614
615  /**
616   * Initialize the backup ID field with a value.
617   *
618   */
619  private void initializeBackupID()
620  {
621    SimpleDateFormat dateFormat = new SimpleDateFormat(
622        ServerConstants.DATE_FORMAT_COMPACT_LOCAL_TIME);
623    final String id = dateFormat.format(new Date());
624    backupID.setText(id);
625  }
626
627  /**
628   * Class that launches the backup.
629   *
630   */
631  protected class BackupTask extends Task
632  {
633    private Set<String> backendSet;
634    private String dir;
635    /**
636     * The constructor of the task.
637     * @param info the control panel info.
638     * @param dlg the progress dialog that shows the progress of the task.
639     */
640    public BackupTask(ControlPanelInfo info, ProgressDialog dlg)
641    {
642      super(info, dlg);
643      backendSet = new HashSet<>();
644      if (!allBackends.isSelected())
645      {
646        backendSet.add((String)backends.getSelectedItem());
647      }
648      else
649      {
650        for (BackendDescriptor backend :
651          info.getServerDescriptor().getBackends())
652        {
653          if (!backend.isConfigBackend())
654          {
655            backendSet.add(backend.getBackendID());
656          }
657        }
658      }
659      if (isIncrementalWithParent())
660      {
661        if (isLocal())
662        {
663          BackupDescriptor backup = getSelectedBackup();
664          dir = backup.getPath().getAbsolutePath();
665        }
666        else
667        {
668          dir = parentDirectory.getText();
669        }
670      }
671      else
672      {
673        dir = parentDirectory.getText();
674      }
675    }
676
677    /** {@inheritDoc} */
678    public Type getType()
679    {
680      return Type.BACKUP;
681    }
682
683    /** {@inheritDoc} */
684    public LocalizableMessage getTaskDescription()
685    {
686      return INFO_CTRL_PANEL_BACKUP_TASK_DESCRIPTION.get(
687      Utilities.getStringFromCollection(backendSet, ", "), dir);
688    }
689
690    /** {@inheritDoc} */
691    public boolean canLaunch(Task taskToBeLaunched,
692        Collection<LocalizableMessage> incompatibilityReasons)
693    {
694      boolean canLaunch = true;
695      if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched))
696      {
697        // All the operations are incompatible if they apply to this backend.
698        Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends());
699        backends.retainAll(getBackends());
700        if (!backends.isEmpty())
701        {
702          incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched));
703          canLaunch = false;
704        }
705      }
706      return canLaunch;
707    }
708
709    /** {@inheritDoc} */
710    public void runTask()
711    {
712      state = State.RUNNING;
713      lastException = null;
714      try
715      {
716        ArrayList<String> arguments = getCommandLineArguments();
717
718        String[] args = new String[arguments.size()];
719
720        arguments.toArray(args);
721        if (isServerRunning())
722        {
723          returnCode = BackUpDB.mainBackUpDB(args, false, outPrintStream,
724              errorPrintStream);
725        }
726        else
727        {
728          returnCode = executeCommandLine(getCommandLinePath(), args);
729        }
730        if (returnCode != 0)
731        {
732          state = State.FINISHED_WITH_ERROR;
733        }
734        else
735        {
736          getInfo().backupCreated(
737              new BackupDescriptor(
738                  new File(parentDirectory.getText()),
739                  new Date(),
740                  fullBackup.isSelected() ? BackupDescriptor.Type.FULL :
741                    BackupDescriptor.Type.INCREMENTAL,
742                  backupID.getText()));
743          state = State.FINISHED_SUCCESSFULLY;
744        }
745      }
746      catch (Throwable t)
747      {
748        lastException = t;
749        state = State.FINISHED_WITH_ERROR;
750      }
751    }
752
753    /** {@inheritDoc} */
754    public Set<String> getBackends()
755    {
756      return backendSet;
757    }
758
759    /** {@inheritDoc} */
760    protected ArrayList<String> getCommandLineArguments()
761    {
762      ArrayList<String> args = new ArrayList<>();
763
764      args.add("--backupDirectory");
765      args.add(dir);
766
767      args.add("--backupID");
768      args.add(backupID.getText());
769
770      if (allBackends.isSelected())
771      {
772        args.add("--backUpAll");
773      }
774      else
775      {
776        args.add("--backendID");
777        args.add((String)backends.getSelectedItem());
778      }
779
780      if (incrementalBackup.isSelected())
781      {
782        args.add("--incremental");
783        if(incrementalParent.isSelected())
784        {
785          if (isLocal())
786          {
787            BackupDescriptor backup = getSelectedBackup();
788            args.add("--incrementalBaseID");
789            args.add(backup.getID());
790          }
791          else
792          {
793            args.add("--incrementalBaseID");
794            args.add(parentBackupID.getText());
795          }
796        }
797      }
798
799
800      if (compressData.isSelected())
801      {
802        args.add("--compress");
803      }
804
805      if (encryptData.isSelected())
806      {
807        args.add("--encrypt");
808      }
809
810      if (generateMessageDigest.isSelected())
811      {
812        args.add("--hash");
813        if (signMessageDigest.isSelected())
814        {
815          args.add("--signHash");
816        }
817      }
818
819      args.addAll(getConnectionCommandLineArguments());
820
821      args.addAll(getScheduleArgs(getSchedule()));
822
823      if (isServerRunning())
824      {
825        args.addAll(getConfigCommandLineArguments());
826      }
827
828      args.add(getNoPropertiesFileArgument());
829
830      return args;
831    }
832
833    /** {@inheritDoc} */
834    protected String getCommandLinePath()
835    {
836      return getCommandLinePath("backup");
837    }
838  }
839}