mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
24.24.2006 8e5d07e690c02c684b88faced089a98879b5eb30
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.
1 files added
1 files modified
364 ■■■■■ changed files
opends/tests/unit-tests-testng/resource/config-changes.ldif 16 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/DelayPreOpPlugin.java 348 ●●●●● patch | view | raw | blame | history
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
opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/DelayPreOpPlugin.java
New file
@@ -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;
  }
}