From 8e5d07e690c02c684b88faced089a98879b5eb30 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Sat, 23 Sep 2006 23:24:28 +0000
Subject: [PATCH] Add a simple plugin that can be used to introduce a delay in pre-operation processing.  The delay will only be introduced for operations that contain a special control which also indicates the length of time to sleep before returning.  This can be useful in testing cancel and abandon operations.

---
 opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/DelayPreOpPlugin.java |  348 +++++++++++++++++++++++++++++++++++++++++++++++++
 opends/tests/unit-tests-testng/resource/config-changes.ldif                               |   16 ++
 2 files changed, 364 insertions(+), 0 deletions(-)

diff --git a/opends/tests/unit-tests-testng/resource/config-changes.ldif b/opends/tests/unit-tests-testng/resource/config-changes.ldif
index 2982515..3b6c11b 100644
--- a/opends/tests/unit-tests-testng/resource/config-changes.ldif
+++ b/opends/tests/unit-tests-testng/resource/config-changes.ldif
@@ -100,3 +100,19 @@
 ds-cfg-require-secure-password-changes: false
 ds-cfg-skip-validation-for-administrators: false
 
+dn: cn=Delay PreOperation Plugin,cn=Plugins,cn=config
+changetype: add
+objectClass: top
+objectClass: ds-cfg-plugin
+cn: Delay PreOperation Plugin
+ds-cfg-plugin-class: org.opends.server.plugins.DelayPreOpPlugin
+ds-cfg-plugin-enabled: true
+ds-cfg-plugin-type: preOperationAdd
+ds-cfg-plugin-type: preOperationBind
+ds-cfg-plugin-type: preOperationCompare
+ds-cfg-plugin-type: preOperationDelete
+ds-cfg-plugin-type: preOperationExtended
+ds-cfg-plugin-type: preOperationModify
+ds-cfg-plugin-type: preOperationModifyDN
+ds-cfg-plugin-type: preOperationSearch
+
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/DelayPreOpPlugin.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/DelayPreOpPlugin.java
new file mode 100644
index 0000000..4801e4d
--- /dev/null
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/DelayPreOpPlugin.java
@@ -0,0 +1,348 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.server.plugins;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.opends.server.api.plugin.DirectoryServerPlugin;
+import org.opends.server.api.plugin.PluginType;
+import org.opends.server.api.plugin.PreOperationPluginResult;
+import org.opends.server.config.ConfigEntry;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.BindOperation;
+import org.opends.server.core.CompareOperation;
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ExtendedOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.Operation;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.protocols.asn1.ASN1Long;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.ldap.LDAPControl;
+import org.opends.server.types.Control;
+import org.opends.server.types.ResultCode;
+
+
+
+/**
+ * This class defines a very simple pre-operation plugin that sleeps for up to
+ * five seconds for add, compare, delete, extended, modify, modify DN, and
+ * search operations (and therefore not for abandon, bind, and unbind
+ * operations, since those operations cannot be cancelled).  While it is
+ * sleeping, it also checks for a request to cancel the associated operation and
+ * will respond to it accordingly.
+ */
+public class DelayPreOpPlugin
+       extends DirectoryServerPlugin
+{
+  /**
+   * The OID for the delay request control, which is used to flag operations
+   * that should be delayed.
+   */
+  public static final String OID_DELAY_REQUEST = "1.3.6.1.4.1.26027.1.999.1";
+
+
+
+  /**
+   * Creates a new instance of this Directory Server plugin.  Every
+   * plugin must implement a default constructor (it is the only one
+   * that will be used to create plugins defined in the
+   * configuration), and every plugin constructor must call
+   * <CODE>super()</CODE> as its first element.
+   */
+  public DelayPreOpPlugin()
+  {
+    super();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public void initializePlugin(DirectoryServer directoryServer,
+                               Set<PluginType> pluginTypes,
+                               ConfigEntry configEntry)
+         throws ConfigException
+  {
+    // This plugin may only be used as a pre-operation plugin.
+    for (PluginType t : pluginTypes)
+    {
+      switch (t)
+      {
+        case PRE_OPERATION_ADD:
+        case PRE_OPERATION_BIND:
+        case PRE_OPERATION_COMPARE:
+        case PRE_OPERATION_DELETE:
+        case PRE_OPERATION_EXTENDED:
+        case PRE_OPERATION_MODIFY:
+        case PRE_OPERATION_MODIFY_DN:
+        case PRE_OPERATION_SEARCH:
+          // This is fine.
+          break;
+        default:
+          throw new ConfigException(-1, "Invalid plugin type " + t +
+                                    " for delay pre-op plugin.");
+      }
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public PreOperationPluginResult doPreOperation(AddOperation addOperation)
+  {
+    return doPreOperationInternal(addOperation);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public PreOperationPluginResult doPreOperation(BindOperation bindOperation)
+  {
+    return doPreOperationInternal(bindOperation);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public PreOperationPluginResult doPreOperation(CompareOperation
+                                                      compareOperation)
+  {
+    return doPreOperationInternal(compareOperation);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public PreOperationPluginResult doPreOperation(DeleteOperation
+                                                      deleteOperation)
+  {
+    return doPreOperationInternal(deleteOperation);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public PreOperationPluginResult doPreOperation(ExtendedOperation
+                                                      extendedOperation)
+  {
+    return doPreOperationInternal(extendedOperation);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public PreOperationPluginResult doPreOperation(ModifyOperation
+                                                      modifyOperation)
+  {
+    return doPreOperationInternal(modifyOperation);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public PreOperationPluginResult doPreOperation(ModifyDNOperation
+                                                      modifyDNOperation)
+  {
+    return doPreOperationInternal(modifyDNOperation);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public PreOperationPluginResult doPreOperation(SearchOperation
+                                                      searchOperation)
+  {
+    return doPreOperationInternal(searchOperation);
+  }
+
+
+
+  /**
+   * Looks for a delay request control in the operation, and if one is found
+   * then sleep in 10 millisecond increments up to the length of time specified
+   * in the control value.  If the operation receives a cancel request during
+   * this time, then the control will stop sleeping immediately.
+   *
+   * @param  operation  The operation to be processed.
+   *
+   * @return  The result of the plugin processing.
+   */
+  private PreOperationPluginResult doPreOperationInternal(Operation operation)
+  {
+    long delayDuration = 0L;
+    List<Control> requestControls = operation.getRequestControls();
+    if (requestControls != null)
+    {
+      for (Control c : requestControls)
+      {
+        if (c.getOID().equals(OID_DELAY_REQUEST))
+        {
+          try
+          {
+            delayDuration =
+                 ASN1Long.decodeAsLong(c.getValue().value()).longValue();
+          }
+          catch (Exception e)
+          {
+            operation.setResultCode(ResultCode.PROTOCOL_ERROR);
+            operation.appendErrorMessage("Unable to decode the delay request " +
+                                         "control:  " + e);
+            return new PreOperationPluginResult(false, false, true);
+          }
+        }
+      }
+    }
+
+    if (delayDuration <= 0)
+    {
+      return new PreOperationPluginResult();
+    }
+
+    long stopSleepTime = System.currentTimeMillis() + delayDuration;
+    while (System.currentTimeMillis() < stopSleepTime)
+    {
+      if (operation.getCancelRequest() != null)
+      {
+        break;
+      }
+
+      try
+      {
+        Thread.sleep(10);
+      } catch (Exception e) {}
+    }
+
+    return new PreOperationPluginResult(false, false, false);
+  }
+
+
+
+  /**
+   * Creates a delay request control with the specified delay.
+   *
+   * @param  delay  The length of time in milliseconds to sleep.
+   *
+   * @return  The appropriate delay request control.
+   */
+  public static Control createDelayControl(long delay)
+  {
+    return new Control(OID_DELAY_REQUEST, false,
+                       new ASN1OctetString(new ASN1Long(delay).encode()));
+  }
+
+
+
+  /**
+   * Retrieves a list containing a delay request control with the specified
+   * delay.
+   *
+   * @param  delay  The length of time in milliseconds to sleep.
+   *
+   * @return  A list containing the appropriate delay request control.
+   */
+  public static List<Control> createDelayControlList(long delay)
+  {
+    ArrayList<Control> controlList = new ArrayList<Control>(1);
+
+    ASN1OctetString controlValue =
+         new ASN1OctetString(new ASN1Long(delay).encode());
+    controlList.add(new Control(OID_DELAY_REQUEST, false, controlValue));
+
+    return controlList;
+  }
+
+
+
+  /**
+   * Creates a delay request LDAP control with the specified delay.
+   *
+   * @param  delay  The length of time in milliseconds to sleep.
+   *
+   * @return  The appropriate delay request LDAP control.
+   */
+  public static LDAPControl createDelayLDAPControl(long delay)
+  {
+    return new LDAPControl(OID_DELAY_REQUEST, false,
+                           new ASN1OctetString(new ASN1Long(delay).encode()));
+  }
+
+
+
+  /**
+   * Retrieves a list containing a delay request LDAP control with the specified
+   * delay.
+   *
+   * @param  delay  The length of time in milliseconds to sleep.
+   *
+   * @return  A list containing the appropriate delay request LDAP control.
+   */
+  public static ArrayList<LDAPControl> createDelayLDAPControlList(long delay)
+  {
+    ArrayList<LDAPControl> controlList = new ArrayList<LDAPControl>(1);
+
+    ASN1OctetString controlValue =
+         new ASN1OctetString(new ASN1Long(delay).encode());
+    controlList.add(new LDAPControl(OID_DELAY_REQUEST, false, controlValue));
+
+    return controlList;
+  }
+}
+

--
Gitblit v1.10.0