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