001/*
002 * Copyright 2008-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk.unboundidds.tasks;
022
023
024
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.Collections;
028import java.util.Date;
029import java.util.LinkedHashMap;
030import java.util.List;
031import java.util.Map;
032
033import com.unboundid.ldap.sdk.Attribute;
034import com.unboundid.ldap.sdk.Entry;
035import com.unboundid.util.NotMutable;
036import com.unboundid.util.ThreadSafety;
037import com.unboundid.util.ThreadSafetyLevel;
038
039import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*;
040import static com.unboundid.util.Validator.*;
041
042
043
044/**
045 * This class defines a Directory Server task that can be used to restore a
046 * backup.
047 * <BR>
048 * <BLOCKQUOTE>
049 *   <B>NOTE:</B>  This class, and other classes within the
050 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
051 *   supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661
052 *   server products.  These classes provide support for proprietary
053 *   functionality or for external specifications that are not considered stable
054 *   or mature enough to be guaranteed to work in an interoperable way with
055 *   other types of LDAP servers.
056 * </BLOCKQUOTE>
057 * <BR>
058 * The properties that are available for use with this type of task include:
059 * <UL>
060 *   <LI>The path to the backup directory in which the backup resides.  This
061 *       must be provided when scheduling a new task of this type.</LI>
062 *   <LI>The backup ID of the backup to be restored.  If this is not provided
063 *       when scheduling an instance of this task, then the most recent backup
064 *       in the backup directory will be selected.</LI>
065 *   <LI>A flag that indicates whether to attempt to restore the backup or
066 *       only to verify it to determine whether it appears to be valid (e.g.,
067 *       validate the digest and/or signature, make sure that the backend
068 *       considers it valid, etc.).</LI>
069 *   <LI>The path to a file containing a passphrase to use to generate the
070 *       encryption key.</LI>
071 * </UL>
072
073 */
074@NotMutable()
075@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
076public final class RestoreTask
077       extends Task
078{
079  /**
080   * The fully-qualified name of the Java class that is used for the restore
081   * task.
082   */
083  static final String RESTORE_TASK_CLASS =
084       "com.unboundid.directory.server.tasks.RestoreTask";
085
086
087
088  /**
089   * The name of the attribute used to specify the path to the backup directory
090   * containing the backup to restore.
091   */
092  private static final String ATTR_BACKUP_DIRECTORY =
093       "ds-backup-directory-path";
094
095
096
097  /**
098   * The name of the attribute used to specify the backup ID of the backup to
099   * restore.
100   */
101  private static final String ATTR_BACKUP_ID = "ds-backup-id";
102
103
104
105  /**
106   * The name of the attribute used to specify the path to a file that contains
107   * the passphrase to use to generate the encryption key.
108   */
109  private static final String ATTR_ENCRYPTION_PASSPHRASE_FILE =
110       "ds-task-restore-encryption-passphrase-file";
111
112
113
114  /**
115   * The name of the attribute used to indicate whether to only verify the
116   * backup but not actually restore it.
117   */
118  private static final String ATTR_VERIFY_ONLY =
119       "ds-task-restore-verify-only";
120
121
122
123  /**
124   * The name of the object class used in restore task entries.
125   */
126  private static final String OC_RESTORE_TASK = "ds-task-restore";
127
128
129
130  /**
131   * The task property for the backup directory.
132   */
133  private static final TaskProperty PROPERTY_BACKUP_DIRECTORY =
134       new TaskProperty(ATTR_BACKUP_DIRECTORY,
135                        INFO_DISPLAY_NAME_BACKUP_DIRECTORY.get(),
136                        INFO_DESCRIPTION_BACKUP_DIRECTORY_RESTORE.get(),
137                        String.class, true, false, false);
138
139
140
141  /**
142   * The task property for the backup ID.
143   */
144  private static final TaskProperty PROPERTY_BACKUP_ID =
145       new TaskProperty(ATTR_BACKUP_ID, INFO_DISPLAY_NAME_BACKUP_ID.get(),
146                        INFO_DESCRIPTION_BACKUP_ID_RESTORE.get(), String.class,
147                        false, false, true);
148
149
150
151  /**
152   * The task property that will be used for the encryption passphrase file.
153   */
154  private static final TaskProperty PROPERTY_ENCRYPTION_PASSPHRASE_FILE =
155       new TaskProperty(ATTR_ENCRYPTION_PASSPHRASE_FILE,
156            INFO_DISPLAY_NAME_ENCRYPTION_PASSPHRASE_FILE.get(),
157            INFO_DESCRIPTION_ENCRYPTION_PASSPHRASE_FILE.get(),
158            String.class, false, false, true);
159
160
161
162  /**
163   * The task property for the verify only flag.
164   */
165  private static final TaskProperty PROPERTY_VERIFY_ONLY =
166       new TaskProperty(ATTR_VERIFY_ONLY, INFO_DISPLAY_NAME_VERIFY_ONLY.get(),
167                        INFO_DESCRIPTION_VERIFY_ONLY.get(), Boolean.class,
168                        false, false, false);
169
170
171
172  /**
173   * The serial version UID for this serializable class.
174   */
175  private static final long serialVersionUID = -8441221098187125379L;
176
177
178
179  // Indicates whether to only verify the backup without restoring it.
180  private final boolean verifyOnly;
181
182  // The path to the backup directory containing the backup to restore.
183  private final String backupDirectory;
184
185  // The path to a file containing the passphrase to use to generate the
186  // encryption key.
187  private final String encryptionPassphraseFile;
188
189  // The backup ID of the backup to restore.
190  private final String backupID;
191
192
193
194  /**
195   * Creates a new uninitialized restore task instance which should only be used
196   * for obtaining general information about this task, including the task name,
197   * description, and supported properties.  Attempts to use a task created with
198   * this constructor for any other reason will likely fail.
199   */
200  public RestoreTask()
201  {
202    verifyOnly = false;
203    backupDirectory = null;
204    backupID = null;
205    encryptionPassphraseFile = null;
206  }
207
208
209
210
211  /**
212   * Creates a new restore task with the provided information.
213   *
214   * @param  taskID           The task ID to use for this task.  If it is
215   *                          {@code null} then a UUID will be generated for use
216   *                          as the task ID.
217   * @param  backupDirectory  The path to the directory on the server containing
218   *                          the backup to restore.  It may be an absolute path
219   *                          or relative to the server root directory.  It must
220   *                          not be {@code null}.
221   * @param  backupID         The backup ID of the backup to restore.  If this
222   *                          is {@code null} then the most recent backup in the
223   *                          specified backup directory will be restored.
224   * @param  verifyOnly       Indicates whether to only verify the backup
225   *                          without restoring it.
226   */
227  public RestoreTask(final String taskID, final String backupDirectory,
228                     final String backupID, final boolean verifyOnly)
229  {
230    this(taskID, backupDirectory, backupID, verifyOnly, null, null, null, null,
231         null);
232  }
233
234
235
236  /**
237   * Creates a new restore task with the provided information.
238   *
239   * @param  taskID                  The task ID to use for this task.  If it is
240   *                                 {@code null} then a UUID will be generated
241   *                                 for use as the task ID.
242   * @param  backupDirectory         The path to the directory on the server
243   *                                 containing the backup to restore.  It may
244   *                                 be an absolute path or relative to the
245   *                                 server root directory.  It must not be
246   *                                 {@code null}.
247   * @param  backupID                The backup ID of the backup to restore.  If
248   *                                 this is {@code null} then the most recent
249   *                                 backup in the specified backup directory
250   *                                 will be restored.
251   * @param  verifyOnly              Indicates whether to only verify the backup
252   *                                 without restoring it.
253   * @param  scheduledStartTime      The time that this task should start
254   *                                 running.
255   * @param  dependencyIDs           The list of task IDs that will be required
256   *                                 to complete before this task will be
257   *                                 eligible to start.
258   * @param  failedDependencyAction  Indicates what action should be taken if
259   *                                 any of the dependencies for this task do
260   *                                 not complete successfully.
261   * @param  notifyOnCompletion      The list of e-mail addresses of individuals
262   *                                 that should be notified when this task
263   *                                 completes.
264   * @param  notifyOnError           The list of e-mail addresses of individuals
265   *                                 that should be notified if this task does
266   *                                 not complete successfully.
267   */
268  public RestoreTask(final String taskID, final String backupDirectory,
269                     final String backupID, final boolean verifyOnly,
270                     final Date scheduledStartTime,
271                     final List<String> dependencyIDs,
272                     final FailedDependencyAction failedDependencyAction,
273                     final List<String> notifyOnCompletion,
274                     final List<String> notifyOnError)
275  {
276    this(taskID, backupDirectory, backupID, verifyOnly, null,
277         scheduledStartTime, dependencyIDs, failedDependencyAction,
278         notifyOnCompletion, notifyOnError);
279  }
280
281
282
283  /**
284   * Creates a new restore task with the provided information.
285   *
286   * @param  taskID                    The task ID to use for this task.  If it
287   *                                   is {@code null} then a UUID will be
288   *                                   generated for use as the task ID.
289   * @param  backupDirectory           The path to the directory on the server
290   *                                   containing the backup to restore.  It may
291   *                                   be an absolute path or relative to the
292   *                                   server root directory.  It must not be
293   *                                   {@code null}.
294   * @param  backupID                  The backup ID of the backup to restore.
295   *                                   If this is {@code null} then the most
296   *                                   recent backup in the specified backup
297   *                                   directory will be restored.
298   * @param  verifyOnly                Indicates whether to only verify the
299   *                                   backup without restoring it.
300   * @param  encryptionPassphraseFile  The path to a file containing the
301   *                                   passphrase to use to generate the
302   *                                   encryption key.  It amy be {@code null}
303   *                                   if the backup is not to be encrypted, or
304   *                                   if the key should be obtained in some
305   *                                   other way.
306   * @param  scheduledStartTime        The time that this task should start
307   *                                   running.
308   * @param  dependencyIDs             The list of task IDs that will be
309   *                                   required to complete before this task
310   *                                   will be eligible to start.
311   * @param  failedDependencyAction    Indicates what action should be taken if
312   *                                   any of the dependencies for this task do
313   *                                   not complete successfully.
314   * @param  notifyOnCompletion        The list of e-mail addresses of
315   *                                   individuals that should be notified when
316   *                                   this task completes.
317   * @param  notifyOnError             The list of e-mail addresses of
318   *                                   individuals that should be notified if
319   *                                   this task does not complete successfully.
320   */
321  public RestoreTask(final String taskID, final String backupDirectory,
322                     final String backupID, final boolean verifyOnly,
323                     final String encryptionPassphraseFile,
324                     final Date scheduledStartTime,
325                     final List<String> dependencyIDs,
326                     final FailedDependencyAction failedDependencyAction,
327                     final List<String> notifyOnCompletion,
328                     final List<String> notifyOnError)
329  {
330    super(taskID, RESTORE_TASK_CLASS, scheduledStartTime,
331          dependencyIDs, failedDependencyAction, notifyOnCompletion,
332          notifyOnError);
333
334    ensureNotNull(backupDirectory);
335
336    this.backupDirectory = backupDirectory;
337    this.backupID = backupID;
338    this.verifyOnly = verifyOnly;
339    this.encryptionPassphraseFile = encryptionPassphraseFile;
340  }
341
342
343
344  /**
345   * Creates a new restore task from the provided entry.
346   *
347   * @param  entry  The entry to use to create this restore task.
348   *
349   * @throws  TaskException  If the provided entry cannot be parsed as a restore
350   *                         task entry.
351   */
352  public RestoreTask(final Entry entry)
353         throws TaskException
354  {
355    super(entry);
356
357
358    // Get the backup directory.  It must be present.
359    backupDirectory = entry.getAttributeValue(ATTR_BACKUP_DIRECTORY);
360    if (backupDirectory == null)
361    {
362      throw new TaskException(ERR_RESTORE_NO_BACKUP_DIRECTORY.get(
363                                   getTaskEntryDN()));
364    }
365
366
367    // Get the backup ID.  It may be absent.
368    backupID = entry.getAttributeValue(ATTR_BACKUP_ID);
369
370
371    // Get the verifyOnly flag.  It may be absent.
372    verifyOnly = parseBooleanValue(entry, ATTR_VERIFY_ONLY, false);
373
374
375    // Get the path to the encryption passphrase file.  It may be absent.
376    encryptionPassphraseFile =
377         entry.getAttributeValue(ATTR_ENCRYPTION_PASSPHRASE_FILE);
378  }
379
380
381
382  /**
383   * Creates a new restore task from the provided set of task properties.
384   *
385   * @param  properties  The set of task properties and their corresponding
386   *                     values to use for the task.  It must not be
387   *                     {@code null}.
388   *
389   * @throws  TaskException  If the provided set of properties cannot be used to
390   *                         create a valid restore task.
391   */
392  public RestoreTask(final Map<TaskProperty,List<Object>> properties)
393         throws TaskException
394  {
395    super(RESTORE_TASK_CLASS, properties);
396
397    boolean v = false;
398    String  b = null;
399    String  f = null;
400    String  i = null;
401
402    for (final Map.Entry<TaskProperty,List<Object>> entry :
403         properties.entrySet())
404    {
405      final TaskProperty p = entry.getKey();
406      final String attrName = p.getAttributeName();
407      final List<Object> values = entry.getValue();
408
409      if (attrName.equalsIgnoreCase(ATTR_BACKUP_DIRECTORY))
410      {
411        b = parseString(p, values, b);
412      }
413      else if (attrName.equalsIgnoreCase(ATTR_BACKUP_ID))
414      {
415        i = parseString(p, values, i);
416      }
417      else if (attrName.equalsIgnoreCase(ATTR_VERIFY_ONLY))
418      {
419        v = parseBoolean(p, values, v);
420      }
421      else if (attrName.equalsIgnoreCase(ATTR_ENCRYPTION_PASSPHRASE_FILE))
422      {
423        f = parseString(p, values, f);
424      }
425    }
426
427    if (b == null)
428    {
429      throw new TaskException(ERR_RESTORE_NO_BACKUP_DIRECTORY.get(
430                                   getTaskEntryDN()));
431    }
432
433    backupDirectory = b;
434    backupID = i;
435    verifyOnly = v;
436    encryptionPassphraseFile = f;
437  }
438
439
440
441  /**
442   * {@inheritDoc}
443   */
444  @Override()
445  public String getTaskName()
446  {
447    return INFO_TASK_NAME_RESTORE.get();
448  }
449
450
451
452  /**
453   * {@inheritDoc}
454   */
455  @Override()
456  public String getTaskDescription()
457  {
458    return INFO_TASK_DESCRIPTION_RESTORE.get();
459  }
460
461
462
463  /**
464   * Retrieves the path to the backup directory which contains the backup to
465   * restore.  It may be either an absolute path or one that is relative to the
466   * server root.
467   *
468   * @return  The path to the backup directory which contains the backup to
469   *          restore.
470   */
471  public String getBackupDirectory()
472  {
473    return backupDirectory;
474  }
475
476
477
478  /**
479   * Retrieves the backup ID of the backup to restore.
480   *
481   * @return  The backup ID of the backup to restore, or {@code null} if the
482   *          most recent backup in the backup directory should be restored.
483   */
484  public String getBackupID()
485  {
486    return backupID;
487  }
488
489
490
491  /**
492   * Indicates whether the backup should only be verified without actually being
493   * restored.
494   *
495   * @return  {@code true} if the backup should be verified but not restored, or
496   *          {@code false} if it should be restored.
497   */
498  public boolean verifyOnly()
499  {
500    return verifyOnly;
501  }
502
503
504
505  /**
506   * Retrieves the path to a file that contains the passphrase to use to
507   * generate the encryption key.
508   *
509   * @return  The path to a file that contains the passphrase to use to
510   *          generate the encryption key, or {@code null} if the backup is
511   *          not encrypted or if the encryption key should be obtained through
512   *          some other means.
513   */
514  public String getEncryptionPassphraseFile()
515  {
516    return encryptionPassphraseFile;
517  }
518
519
520
521  /**
522   * {@inheritDoc}
523   */
524  @Override()
525  protected List<String> getAdditionalObjectClasses()
526  {
527    return Arrays.asList(OC_RESTORE_TASK);
528  }
529
530
531
532  /**
533   * {@inheritDoc}
534   */
535  @Override()
536  protected List<Attribute> getAdditionalAttributes()
537  {
538    final ArrayList<Attribute> attrs = new ArrayList<Attribute>(10);
539
540    attrs.add(new Attribute(ATTR_BACKUP_DIRECTORY, backupDirectory));
541    attrs.add(new Attribute(ATTR_VERIFY_ONLY, String.valueOf(verifyOnly)));
542
543    if (backupID != null)
544    {
545      attrs.add(new Attribute(ATTR_BACKUP_ID, backupID));
546    }
547
548    if (encryptionPassphraseFile != null)
549    {
550      attrs.add(new Attribute(ATTR_ENCRYPTION_PASSPHRASE_FILE,
551           encryptionPassphraseFile));
552    }
553
554    return attrs;
555  }
556
557
558
559  /**
560   * {@inheritDoc}
561   */
562  @Override()
563  public List<TaskProperty> getTaskSpecificProperties()
564  {
565    final List<TaskProperty> propList = Arrays.asList(
566         PROPERTY_BACKUP_DIRECTORY,
567         PROPERTY_BACKUP_ID,
568         PROPERTY_VERIFY_ONLY,
569         PROPERTY_ENCRYPTION_PASSPHRASE_FILE);
570
571    return Collections.unmodifiableList(propList);
572  }
573
574
575
576  /**
577   * {@inheritDoc}
578   */
579  @Override()
580  public Map<TaskProperty,List<Object>> getTaskPropertyValues()
581  {
582    final LinkedHashMap<TaskProperty,List<Object>> props =
583         new LinkedHashMap<TaskProperty,List<Object>>();
584
585    props.put(PROPERTY_BACKUP_DIRECTORY,
586         Collections.<Object>unmodifiableList(Arrays.asList(backupDirectory)));
587
588    if (backupID == null)
589    {
590      props.put(PROPERTY_BACKUP_ID, Collections.emptyList());
591    }
592    else
593    {
594      props.put(PROPERTY_BACKUP_ID,
595                Collections.<Object>unmodifiableList(Arrays.asList(backupID)));
596    }
597
598    props.put(PROPERTY_VERIFY_ONLY,
599              Collections.<Object>unmodifiableList(Arrays.asList(verifyOnly)));
600
601    if (encryptionPassphraseFile == null)
602    {
603      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE, Collections.emptyList());
604    }
605    else
606    {
607      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
608         Collections.<Object>unmodifiableList(Arrays.asList(
609              encryptionPassphraseFile)));
610    }
611
612    props.putAll(super.getTaskPropertyValues());
613    return Collections.unmodifiableMap(props);
614  }
615}