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 invoke
052     * third-party code created using the UnboundID Server SDK.  The properties that
053     * are available for use with this type of task include:
054     * <UL>
055     *   <LI>The fully-qualified name of the Java class providing the logic for the
056     *       third-party task.  This must be provided.</LI>
057     *   <LI>A list of the arguments to use for the task.</LI>
058     * </UL>
059     */
060    @NotMutable()
061    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
062    public final class ThirdPartyTask
063           extends Task
064    {
065      /**
066       * The fully-qualified name of the Java class that is used for the core
067       * third-party task.
068       */
069      static final String THIRD_PARTY_TASK_CLASS =
070           "com.unboundid.directory.sdk.extensions.ThirdPartyTask";
071    
072    
073    
074      /**
075       * The name of the attribute used to specify the fully-qualified name of the
076       * Java class providing the task logic.
077       */
078      private static final String ATTR_THIRD_PARTY_TASK_CLASS =
079           "ds-third-party-task-java-class";
080    
081    
082    
083      /**
084       * The name of the attribute used to provide arguments for the task.
085       */
086      private static final String ATTR_THIRD_PARTY_TASK_ARGUMENT =
087           "ds-third-party-task-argument";
088    
089    
090    
091      /**
092       * The name of the object class used in third-party task entries.
093       */
094      private static final String OC_THIRD_PARTY_TASK =
095           "ds-third-party-task";
096    
097    
098    
099      /**
100       * The task property that will be used for the task class.
101       */
102      static final TaskProperty PROPERTY_TASK_CLASS =
103         new TaskProperty(ATTR_THIRD_PARTY_TASK_CLASS,
104              INFO_DISPLAY_NAME_THIRD_PARTY_TASK_CLASS.get(),
105              INFO_DESCRIPTION_THIRD_PARTY_TASK_CLASS.get(), String.class, true,
106              false, false);
107    
108    
109    
110      /**
111       * The task property that will be used for the task arguments.
112       */
113      static final TaskProperty PROPERTY_TASK_ARG =
114         new TaskProperty(ATTR_THIRD_PARTY_TASK_ARGUMENT,
115              INFO_DISPLAY_NAME_THIRD_PARTY_TASK_ARG.get(),
116              INFO_DESCRIPTION_THIRD_PARTY_TASK_ARG.get(), String.class, false,
117              true, false);
118    
119    
120    
121      /**
122       * The serial version UID for this serializable class.
123       */
124      private static final long serialVersionUID = 8448474409066265724L;
125    
126    
127    
128      // A list of the arguments for the task.
129      private final List<String> taskArguments;
130    
131      // The name of the java class providing the logic for the third-party task.
132      private final String taskClassName;
133    
134    
135    
136      /**
137       * Creates a new uninitialized third-party task instance which should only
138       * be used for obtaining general information about this task, including the
139       * task name, description, and supported properties.  Attempts to use a task
140       * created with this constructor for any other reason will likely fail.
141       */
142      public ThirdPartyTask()
143      {
144        taskArguments = null;
145        taskClassName = null;
146      }
147    
148    
149    
150    
151      /**
152       * Creates a new third-party task with the provided information.
153       *
154       * @param  taskID         The task ID to use for this task.  If it is
155       *                        {@code null} then a UUID will be generated for use
156       *                        as the task ID.
157       * @param  taskClassName  The fully-qualified name of the Java class providing
158       *                        the logic for the task.  It must not be
159       *                        {@code null}.
160       * @param  taskArguments  A list of the arguments for the task, in the form
161       *                        name=value.  It may be {@code null} or empty if
162       *                        there should not be any arguments.
163       */
164      public ThirdPartyTask(final String taskID, final String taskClassName,
165                            final List<String> taskArguments)
166      {
167        this(taskID, taskClassName, taskArguments, null, null, null, null, null);
168      }
169    
170    
171    
172      /**
173       * Creates a new third-party task with the provided information.
174       *
175       * @param  taskID                  The task ID to use for this task.  If it is
176       *                                 {@code null} then a UUID will be generated
177       *                                 for use as the task ID.
178       * @param  taskClassName           The fully-qualified name of the Java class
179       *                                 providing the logic for the task.  It must
180       *                                 not be {@code null}.
181       * @param  taskArguments           A list of the arguments for the task, in
182       *                                 the form name=value.  It may be
183       *                                 {@code null} or empty if there should not
184       *                                 be any arguments.
185       * @param  scheduledStartTime      The time that this task should start
186       *                                 running.
187       * @param  dependencyIDs           The list of task IDs that will be required
188       *                                 to complete before this task will be
189       *                                 eligible to start.
190       * @param  failedDependencyAction  Indicates what action should be taken if
191       *                                 any of the dependencies for this task do
192       *                                 not complete successfully.
193       * @param  notifyOnCompletion      The list of e-mail addresses of individuals
194       *                                 that should be notified when this task
195       *                                 completes.
196       * @param  notifyOnError           The list of e-mail addresses of individuals
197       *                                 that should be notified if this task does
198       *                                 not complete successfully.
199       */
200      public ThirdPartyTask(final String taskID, final String taskClassName,
201                            final List<String> taskArguments,
202                            final Date scheduledStartTime,
203                            final List<String> dependencyIDs,
204                            final FailedDependencyAction failedDependencyAction,
205                            final List<String> notifyOnCompletion,
206                            final List<String> notifyOnError)
207      {
208        super(taskID, THIRD_PARTY_TASK_CLASS, scheduledStartTime,
209              dependencyIDs, failedDependencyAction, notifyOnCompletion,
210              notifyOnError);
211    
212        ensureNotNull(taskClassName);
213    
214        this.taskClassName = taskClassName;
215    
216        if (taskArguments == null)
217        {
218          this.taskArguments = Collections.emptyList();
219        }
220        else
221        {
222          this.taskArguments = Collections.unmodifiableList(taskArguments);
223        }
224      }
225    
226    
227    
228      /**
229       * Creates a new third-party task from the provided entry.
230       *
231       * @param  entry  The entry to use to create this third-party task.
232       *
233       * @throws  TaskException  If the provided entry cannot be parsed as a
234       *                         third-party task entry.
235       */
236      public ThirdPartyTask(final Entry entry)
237             throws TaskException
238      {
239        super(entry);
240    
241    
242        // Get the task class name.  It must be present.
243        taskClassName = entry.getAttributeValue(ATTR_THIRD_PARTY_TASK_CLASS);
244        if (taskClassName == null)
245        {
246          throw new TaskException(ERR_THIRD_PARTY_TASK_NO_CLASS.get(
247               getTaskEntryDN()));
248        }
249    
250    
251        // Get the task arguments.  It may be absent.
252        final String[] args =
253             entry.getAttributeValues(ATTR_THIRD_PARTY_TASK_ARGUMENT);
254        if ((args == null) || (args.length == 0))
255        {
256          taskArguments = Collections.emptyList();
257        }
258        else
259        {
260          taskArguments = Collections.unmodifiableList(Arrays.asList(args));
261        }
262      }
263    
264    
265    
266      /**
267       * Creates a new third-party task from the provided set of task properties.
268       *
269       * @param  properties  The set of task properties and their corresponding
270       *                     values to use for the task.  It must not be
271       *                     {@code null}.
272       *
273       * @throws  TaskException  If the provided set of properties cannot be used to
274       *                         create a valid third-party task.
275       */
276      public ThirdPartyTask(final Map<TaskProperty,List<Object>> properties)
277             throws TaskException
278      {
279        super(THIRD_PARTY_TASK_CLASS, properties);
280    
281        String   className = null;
282        String[] args      = null;
283        for (final Map.Entry<TaskProperty,List<Object>> entry :
284             properties.entrySet())
285        {
286          final TaskProperty p = entry.getKey();
287          final String attrName = p.getAttributeName();
288          final List<Object> values = entry.getValue();
289    
290          if (attrName.equalsIgnoreCase(ATTR_THIRD_PARTY_TASK_CLASS))
291          {
292            className = parseString(p, values, null);
293          }
294          else if (attrName.equalsIgnoreCase(ATTR_THIRD_PARTY_TASK_ARGUMENT))
295          {
296            args = parseStrings(p, values, null);
297          }
298        }
299    
300        if (className == null)
301        {
302          throw new TaskException(ERR_THIRD_PARTY_TASK_NO_CLASS.get(
303               getTaskEntryDN()));
304        }
305    
306        taskClassName = className;
307    
308        if (args == null)
309        {
310          taskArguments = Collections.emptyList();
311        }
312        else
313        {
314          taskArguments = Collections.unmodifiableList(Arrays.asList(args));
315        }
316      }
317    
318    
319    
320      /**
321       * {@inheritDoc}
322       */
323      @Override()
324      public String getTaskName()
325      {
326        return INFO_TASK_NAME_THIRD_PARTY_TASK.get();
327      }
328    
329    
330    
331      /**
332       * {@inheritDoc}
333       */
334      @Override()
335      public String getTaskDescription()
336      {
337        return INFO_TASK_DESCRIPTION_THIRD_PARTY_TASK.get();
338      }
339    
340    
341    
342      /**
343       * Retrieves the fully-qualified name of the Java class providing the logic
344       * for the third-party task.
345       *
346       * @return  The fully-qualified name of the Java class providing the logic
347       *          for the third-party task.
348       */
349      public String getThirdPartyTaskClassName()
350      {
351        return taskClassName;
352      }
353    
354    
355    
356      /**
357       * Retrieves a list of the arguments to provide to the third-party task.
358       *
359       * @return  A list of the arguments to provide to the third-party task, or
360       *          an empty list if there are no arguments.
361       */
362      public List<String> getThirdPartyTaskArguments()
363      {
364        return taskArguments;
365      }
366    
367    
368    
369      /**
370       * {@inheritDoc}
371       */
372      @Override()
373      protected List<String> getAdditionalObjectClasses()
374      {
375        return Arrays.asList(OC_THIRD_PARTY_TASK);
376      }
377    
378    
379    
380      /**
381       * {@inheritDoc}
382       */
383      @Override()
384      protected List<Attribute> getAdditionalAttributes()
385      {
386        final ArrayList<Attribute> attrList = new ArrayList<Attribute>(2);
387        attrList.add(new Attribute(ATTR_THIRD_PARTY_TASK_CLASS, taskClassName));
388    
389        if (! taskArguments.isEmpty())
390        {
391          attrList.add(new Attribute(ATTR_THIRD_PARTY_TASK_ARGUMENT,
392               taskArguments));
393        }
394    
395        return attrList;
396      }
397    
398    
399    
400      /**
401       * {@inheritDoc}
402       */
403      @Override()
404      public List<TaskProperty> getTaskSpecificProperties()
405      {
406        return Collections.unmodifiableList(Arrays.asList(
407             PROPERTY_TASK_CLASS,
408             PROPERTY_TASK_ARG));
409      }
410    
411    
412    
413      /**
414       * {@inheritDoc}
415       */
416      @Override()
417      public Map<TaskProperty,List<Object>> getTaskPropertyValues()
418      {
419        final LinkedHashMap<TaskProperty,List<Object>> props =
420             new LinkedHashMap<TaskProperty,List<Object>>(2);
421    
422        props.put(PROPERTY_TASK_CLASS,
423             Collections.<Object>unmodifiableList(Arrays.asList(taskClassName)));
424    
425        props.put(PROPERTY_TASK_ARG,
426             Collections.<Object>unmodifiableList(taskArguments));
427    
428        props.putAll(super.getTaskPropertyValues());
429        return Collections.unmodifiableMap(props);
430      }
431    }