001/*
002 * Copyright 2008-2017 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2017 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 * </UL>
070
071 */
072@NotMutable()
073@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
074public final class RestoreTask
075       extends Task
076{
077  /**
078   * The fully-qualified name of the Java class that is used for the restore
079   * task.
080   */
081  static final String RESTORE_TASK_CLASS =
082       "com.unboundid.directory.server.tasks.RestoreTask";
083
084
085
086  /**
087   * The name of the attribute used to specify the path to the backup directory
088   * containing the backup to restore.
089   */
090  private static final String ATTR_BACKUP_DIRECTORY =
091       "ds-backup-directory-path";
092
093
094
095  /**
096   * The name of the attribute used to specify the backup ID of the backup to
097   * restore.
098   */
099  private static final String ATTR_BACKUP_ID = "ds-backup-id";
100
101
102
103  /**
104   * The name of the attribute used to indicate whether to only verify the
105   * backup but not actually restore it.
106   */
107  private static final String ATTR_VERIFY_ONLY =
108       "ds-task-restore-verify-only";
109
110
111
112  /**
113   * The name of the object class used in restore task entries.
114   */
115  private static final String OC_RESTORE_TASK = "ds-task-restore";
116
117
118
119  /**
120   * The task property for the backup directory.
121   */
122  private static final TaskProperty PROPERTY_BACKUP_DIRECTORY =
123       new TaskProperty(ATTR_BACKUP_DIRECTORY,
124                        INFO_DISPLAY_NAME_BACKUP_DIRECTORY.get(),
125                        INFO_DESCRIPTION_BACKUP_DIRECTORY_RESTORE.get(),
126                        String.class, true, false, false);
127
128
129
130  /**
131   * The task property for the backup ID.
132   */
133  private static final TaskProperty PROPERTY_BACKUP_ID =
134       new TaskProperty(ATTR_BACKUP_ID, INFO_DISPLAY_NAME_BACKUP_ID.get(),
135                        INFO_DESCRIPTION_BACKUP_ID_RESTORE.get(), String.class,
136                        false, false, true);
137
138
139
140  /**
141   * The task property for the verify only flag.
142   */
143  private static final TaskProperty PROPERTY_VERIFY_ONLY =
144       new TaskProperty(ATTR_VERIFY_ONLY, INFO_DISPLAY_NAME_VERIFY_ONLY.get(),
145                        INFO_DESCRIPTION_VERIFY_ONLY.get(), Boolean.class,
146                        false, false, false);
147
148
149
150  /**
151   * The serial version UID for this serializable class.
152   */
153  private static final long serialVersionUID = -196339437379274643L;
154
155
156
157  // Indicates whether to only verify the backup without restoring it.
158  private final boolean verifyOnly;
159
160  // The path to the backup directory containing the backup to restore.
161  private final String backupDirectory;
162
163  // The backup ID of the backup to restore.
164  private final String backupID;
165
166
167
168  /**
169   * Creates a new uninitialized restore task instance which should only be used
170   * for obtaining general information about this task, including the task name,
171   * description, and supported properties.  Attempts to use a task created with
172   * this constructor for any other reason will likely fail.
173   */
174  public RestoreTask()
175  {
176    verifyOnly      = false;
177    backupDirectory = null;
178    backupID        = null;
179  }
180
181
182
183
184  /**
185   * Creates a new restore task with the provided information.
186   *
187   * @param  taskID           The task ID to use for this task.  If it is
188   *                          {@code null} then a UUID will be generated for use
189   *                          as the task ID.
190   * @param  backupDirectory  The path to the directory on the server containing
191   *                          the backup to restore.  It may be an absolute path
192   *                          or relative to the server root directory.  It must
193   *                          not be {@code null}.
194   * @param  backupID         The backup ID of the backup to restore.  If this
195   *                          is {@code null} then the most recent backup in the
196   *                          specified backup directory will be restored.
197   * @param  verifyOnly       Indicates whether to only verify the backup
198   *                          without restoring it.
199   */
200  public RestoreTask(final String taskID, final String backupDirectory,
201                     final String backupID, final boolean verifyOnly)
202  {
203    this(taskID, backupDirectory, backupID, verifyOnly, null, null, null, null,
204         null);
205  }
206
207
208
209  /**
210   * Creates a new restore task with the provided information.
211   *
212   * @param  taskID                  The task ID to use for this task.  If it is
213   *                                 {@code null} then a UUID will be generated
214   *                                 for use as the task ID.
215   * @param  backupDirectory         The path to the directory on the server
216   *                                 containing the backup to restore.  It may
217   *                                 be an absolute path or relative to the
218   *                                 server root directory.  It must not be
219   *                                 {@code null}.
220   * @param  backupID                The backup ID of the backup to restore.  If
221   *                                 this is {@code null} then the most recent
222   *                                 backup in the specified backup directory
223   *                                 will be restored.
224   * @param  verifyOnly              Indicates whether to only verify the backup
225   *                                 without restoring it.
226   * @param  scheduledStartTime      The time that this task should start
227   *                                 running.
228   * @param  dependencyIDs           The list of task IDs that will be required
229   *                                 to complete before this task will be
230   *                                 eligible to start.
231   * @param  failedDependencyAction  Indicates what action should be taken if
232   *                                 any of the dependencies for this task do
233   *                                 not complete successfully.
234   * @param  notifyOnCompletion      The list of e-mail addresses of individuals
235   *                                 that should be notified when this task
236   *                                 completes.
237   * @param  notifyOnError           The list of e-mail addresses of individuals
238   *                                 that should be notified if this task does
239   *                                 not complete successfully.
240   */
241  public RestoreTask(final String taskID, final String backupDirectory,
242                     final String backupID, final boolean verifyOnly,
243                     final Date scheduledStartTime,
244                     final List<String> dependencyIDs,
245                     final FailedDependencyAction failedDependencyAction,
246                     final List<String> notifyOnCompletion,
247                     final List<String> notifyOnError)
248  {
249    super(taskID, RESTORE_TASK_CLASS, scheduledStartTime,
250          dependencyIDs, failedDependencyAction, notifyOnCompletion,
251          notifyOnError);
252
253    ensureNotNull(backupDirectory);
254
255    this.backupDirectory = backupDirectory;
256    this.backupID        = backupID;
257    this.verifyOnly      = verifyOnly;
258  }
259
260
261
262  /**
263   * Creates a new restore task from the provided entry.
264   *
265   * @param  entry  The entry to use to create this restore task.
266   *
267   * @throws  TaskException  If the provided entry cannot be parsed as a restore
268   *                         task entry.
269   */
270  public RestoreTask(final Entry entry)
271         throws TaskException
272  {
273    super(entry);
274
275
276    // Get the backup directory.  It must be present.
277    backupDirectory = entry.getAttributeValue(ATTR_BACKUP_DIRECTORY);
278    if (backupDirectory == null)
279    {
280      throw new TaskException(ERR_RESTORE_NO_BACKUP_DIRECTORY.get(
281                                   getTaskEntryDN()));
282    }
283
284
285    // Get the backup ID.  It may be absent.
286    backupID = entry.getAttributeValue(ATTR_BACKUP_ID);
287
288
289    // Get the verifyOnly flag.  It may be absent.
290    verifyOnly = parseBooleanValue(entry, ATTR_VERIFY_ONLY, false);
291  }
292
293
294
295  /**
296   * Creates a new restore task from the provided set of task properties.
297   *
298   * @param  properties  The set of task properties and their corresponding
299   *                     values to use for the task.  It must not be
300   *                     {@code null}.
301   *
302   * @throws  TaskException  If the provided set of properties cannot be used to
303   *                         create a valid restore task.
304   */
305  public RestoreTask(final Map<TaskProperty,List<Object>> properties)
306         throws TaskException
307  {
308    super(RESTORE_TASK_CLASS, properties);
309
310    boolean v = false;
311    String  b = null;
312    String  i = null;
313
314    for (final Map.Entry<TaskProperty,List<Object>> entry :
315         properties.entrySet())
316    {
317      final TaskProperty p = entry.getKey();
318      final String attrName = p.getAttributeName();
319      final List<Object> values = entry.getValue();
320
321      if (attrName.equalsIgnoreCase(ATTR_BACKUP_DIRECTORY))
322      {
323        b = parseString(p, values, b);
324      }
325      else if (attrName.equalsIgnoreCase(ATTR_BACKUP_ID))
326      {
327        i = parseString(p, values, i);
328      }
329      else if (attrName.equalsIgnoreCase(ATTR_VERIFY_ONLY))
330      {
331        v = parseBoolean(p, values, v);
332      }
333    }
334
335    if (b == null)
336    {
337      throw new TaskException(ERR_RESTORE_NO_BACKUP_DIRECTORY.get(
338                                   getTaskEntryDN()));
339    }
340
341    backupDirectory = b;
342    backupID        = i;
343    verifyOnly      = v;
344  }
345
346
347
348  /**
349   * {@inheritDoc}
350   */
351  @Override()
352  public String getTaskName()
353  {
354    return INFO_TASK_NAME_RESTORE.get();
355  }
356
357
358
359  /**
360   * {@inheritDoc}
361   */
362  @Override()
363  public String getTaskDescription()
364  {
365    return INFO_TASK_DESCRIPTION_RESTORE.get();
366  }
367
368
369
370  /**
371   * Retrieves the path to the backup directory which contains the backup to
372   * restore.  It may be either an absolute path or one that is relative to the
373   * server root.
374   *
375   * @return  The path to the backup directory which contains the backup to
376   *          restore.
377   */
378  public String getBackupDirectory()
379  {
380    return backupDirectory;
381  }
382
383
384
385  /**
386   * Retrieves the backup ID of the backup to restore.
387   *
388   * @return  The backup ID of the backup to restore, or {@code null} if the
389   *          most recent backup in the backup directory should be restored.
390   */
391  public String getBackupID()
392  {
393    return backupID;
394  }
395
396
397
398  /**
399   * Indicates whether the backup should only be verified without actually being
400   * restored.
401   *
402   * @return  {@code true} if the backup should be verified but not restored, or
403   *          {@code false} if it should be restored.
404   */
405  public boolean verifyOnly()
406  {
407    return verifyOnly;
408  }
409
410
411
412  /**
413   * {@inheritDoc}
414   */
415  @Override()
416  protected List<String> getAdditionalObjectClasses()
417  {
418    return Arrays.asList(OC_RESTORE_TASK);
419  }
420
421
422
423  /**
424   * {@inheritDoc}
425   */
426  @Override()
427  protected List<Attribute> getAdditionalAttributes()
428  {
429    final ArrayList<Attribute> attrs = new ArrayList<Attribute>(3);
430
431    attrs.add(new Attribute(ATTR_BACKUP_DIRECTORY, backupDirectory));
432    attrs.add(new Attribute(ATTR_VERIFY_ONLY, String.valueOf(verifyOnly)));
433
434    if (backupID != null)
435    {
436      attrs.add(new Attribute(ATTR_BACKUP_ID, backupID));
437    }
438
439    return attrs;
440  }
441
442
443
444  /**
445   * {@inheritDoc}
446   */
447  @Override()
448  public List<TaskProperty> getTaskSpecificProperties()
449  {
450    final List<TaskProperty> propList = Arrays.asList(
451         PROPERTY_BACKUP_DIRECTORY,
452         PROPERTY_BACKUP_ID,
453         PROPERTY_VERIFY_ONLY);
454
455    return Collections.unmodifiableList(propList);
456  }
457
458
459
460  /**
461   * {@inheritDoc}
462   */
463  @Override()
464  public Map<TaskProperty,List<Object>> getTaskPropertyValues()
465  {
466    final LinkedHashMap<TaskProperty,List<Object>> props =
467         new LinkedHashMap<TaskProperty,List<Object>>();
468
469    props.put(PROPERTY_BACKUP_DIRECTORY,
470         Collections.<Object>unmodifiableList(Arrays.asList(backupDirectory)));
471
472    if (backupID == null)
473    {
474      props.put(PROPERTY_BACKUP_ID, Collections.emptyList());
475    }
476    else
477    {
478      props.put(PROPERTY_BACKUP_ID,
479                Collections.<Object>unmodifiableList(Arrays.asList(backupID)));
480    }
481
482    props.put(PROPERTY_VERIFY_ONLY,
483              Collections.<Object>unmodifiableList(Arrays.asList(verifyOnly)));
484
485    props.putAll(super.getTaskPropertyValues());
486    return Collections.unmodifiableMap(props);
487  }
488}