From 2273c26793fe6e3abfd90a400823e8e46b3303bb Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Mon, 15 Dec 2008 16:07:29 +0000
Subject: [PATCH] - [Issue 274]  Recurring Tasks

---
 opends/src/server/org/opends/server/backends/task/TaskBackend.java |  140 ++++++++++++++++++++++++++++++----------------
 1 files changed, 90 insertions(+), 50 deletions(-)

diff --git a/opends/src/server/org/opends/server/backends/task/TaskBackend.java b/opends/src/server/org/opends/server/backends/task/TaskBackend.java
index b158520..6029483 100644
--- a/opends/src/server/org/opends/server/backends/task/TaskBackend.java
+++ b/opends/src/server/org/opends/server/backends/task/TaskBackend.java
@@ -617,7 +617,11 @@
       TaskState state = t.getTaskState();
       if (TaskState.isPending(state))
       {
-        taskScheduler.removePendingTask(t.getTaskID());
+        if (t.isRecurring()) {
+          taskScheduler.removeRecurringTaskIteration(t.getTaskID());
+        } else {
+          taskScheduler.removePendingTask(t.getTaskID());
+        }
       }
       else if (TaskState.isDone(t.getTaskState()))
       {
@@ -641,9 +645,6 @@
         throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message);
       }
 
-
-      // Try to remove the recurring task.  This will fail if there are any
-      // associated iterations pending or running.
       taskScheduler.removeRecurringTask(rt.getRecurringTaskID());
     }
     else
@@ -707,13 +708,12 @@
           throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message);
         }
 
-
         // Look at the state of the task.  We will allow anything to be altered
         // for a pending task.  For a running task, we will only allow the state
         // to be altered in order to cancel it.  We will not allow any
         // modifications for completed tasks.
         TaskState state = t.getTaskState();
-        if (TaskState.isPending(state))
+        if (TaskState.isPending(state) && !t.isRecurring())
         {
           Task newTask = taskScheduler.entryToScheduledTask(newEntry,
               modifyOperation);
@@ -727,50 +727,7 @@
           // This will only be allowed using the replace modification type on
           // the ds-task-state attribute if the value starts with "cancel" or
           // "stop".  In that case, we'll cancel the task.
-          boolean acceptable = true;
-          for (Modification m : modifyOperation.getModifications())
-          {
-            if (m.isInternal())
-            {
-              continue;
-            }
-
-            if (m.getModificationType() != ModificationType.REPLACE)
-            {
-              acceptable = false;
-              break;
-            }
-
-            Attribute a = m.getAttribute();
-            AttributeType at = a.getAttributeType();
-            if (! at.hasName(ATTR_TASK_STATE))
-            {
-              acceptable = false;
-              break;
-            }
-
-            Iterator<AttributeValue> iterator = a.iterator();
-            if (! iterator.hasNext())
-            {
-              acceptable = false;
-              break;
-            }
-
-            AttributeValue v = iterator.next();
-            String valueString = toLowerCase(v.getStringValue());
-            if (! (valueString.startsWith("cancel") ||
-                   valueString.startsWith("stop")))
-            {
-              acceptable = false;
-              break;
-            }
-
-            if (iterator.hasNext())
-            {
-              acceptable = false;
-              break;
-            }
-          }
+          boolean acceptable = isReplaceEntryAcceptable(modifyOperation);
 
           if (acceptable)
           {
@@ -786,6 +743,37 @@
                                          message);
           }
         }
+        else if (TaskState.isPending(state) && t.isRecurring())
+        {
+          // Pending recurring task iterations can only be canceled.
+          boolean acceptable = isReplaceEntryAcceptable(modifyOperation);
+
+          if (acceptable)
+          {
+            Task newTask = taskScheduler.entryToScheduledTask(newEntry,
+              modifyOperation);
+            if (newTask.getTaskState() ==
+              TaskState.CANCELED_BEFORE_STARTING)
+            {
+              taskScheduler.removePendingTask(t.getTaskID());
+              taskScheduler.scheduleTask(newTask, true);
+            }
+            else if (newTask.getTaskState() ==
+              TaskState.STOPPED_BY_ADMINISTRATOR)
+            {
+              Message message = INFO_TASKBE_RUNNING_TASK_CANCELLED.get();
+              t.interruptTask(TaskState.STOPPED_BY_ADMINISTRATOR, message);
+            }
+              return;
+          }
+          else
+          {
+            Message message =
+              ERR_TASKBE_MODIFY_RECURRING.get(String.valueOf(entryDN));
+            throw new DirectoryException(
+              ResultCode.UNWILLING_TO_PERFORM, message);
+          }
+        }
         else
         {
           Message message =
@@ -820,6 +808,58 @@
 
 
   /**
+   * Helper to determine if requested modifications are acceptable.
+   * @param modifyOperation associated with requested modifications.
+   * @return <CODE>true</CODE> if requested modifications are
+   *         acceptable, <CODE>false</CODE> otherwise.
+   */
+  private boolean isReplaceEntryAcceptable(ModifyOperation modifyOperation)
+  {
+    boolean acceptable = true;
+
+    for (Modification m : modifyOperation.getModifications()) {
+      if (m.isInternal()) {
+        continue;
+      }
+
+      if (m.getModificationType() != ModificationType.REPLACE) {
+        acceptable = false;
+        break;
+      }
+
+      Attribute a = m.getAttribute();
+      AttributeType at = a.getAttributeType();
+      if (!at.hasName(ATTR_TASK_STATE)) {
+        acceptable = false;
+        break;
+      }
+
+      Iterator<AttributeValue> iterator = a.iterator();
+      if (!iterator.hasNext()) {
+        acceptable = false;
+        break;
+      }
+
+      AttributeValue v = iterator.next();
+      String valueString = toLowerCase(v.getStringValue());
+      if (!(valueString.startsWith("cancel") ||
+        valueString.startsWith("stop"))) {
+        acceptable = false;
+        break;
+      }
+
+      if (iterator.hasNext()) {
+        acceptable = false;
+        break;
+      }
+    }
+
+    return acceptable;
+  }
+
+
+
+  /**
    * {@inheritDoc}
    */
   @Override()

--
Gitblit v1.10.0