From 16781afd94b0ad1014b8394f524ffcc5bd89255b Mon Sep 17 00:00:00 2001
From: jarnou <jarnou@localhost>
Date: Tue, 17 Jul 2007 13:35:12 +0000
Subject: [PATCH] This fix is the refactoring of the extended operation (issue 1189).

---
 opends/src/server/org/opends/server/core/DirectoryServer.java                                               |    4 
 opends/src/server/org/opends/server/core/ExtendedOperation.java                                             |  697 +--------------------------
 opends/src/server/org/opends/server/core/ExtendedOperationBasis.java                                        |  737 +++++++++++++++++++++++++++++
 opends/src/server/org/opends/server/core/PluginConfigManager.java                                           |   12 
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java |    1 
 opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java                        |    7 
 opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java                                  |    6 
 opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java                                |    8 
 8 files changed, 783 insertions(+), 689 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 5ba5159..6b7c19c 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -7164,7 +7164,7 @@
           }
 
         case EXTENDED:
-         ExtendedOperation extOp = (ExtendedOperation) operation;
+         ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation;
          String   requestOID = extOp.getRequestOID();
          if (!((requestOID != null) &&
                  requestOID.equals(OID_START_TLS_REQUEST)))
@@ -7211,7 +7211,7 @@
         case EXTENDED:
           // We will only allow the password modify and StartTLS extended
           // operations.
-          ExtendedOperation extOp = (ExtendedOperation) operation;
+          ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation;
           String            requestOID = extOp.getRequestOID();
           if ((requestOID == null) ||
               ((! requestOID.equals(OID_PASSWORD_MODIFY_REQUEST)) &&
diff --git a/opends/src/server/org/opends/server/core/ExtendedOperation.java b/opends/src/server/org/opends/server/core/ExtendedOperation.java
index a683fc1..c588942 100644
--- a/opends/src/server/org/opends/server/core/ExtendedOperation.java
+++ b/opends/src/server/org/opends/server/core/ExtendedOperation.java
@@ -26,137 +26,26 @@
  */
 package org.opends.server.core;
 
-
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.opends.server.api.ClientConnection;
-import org.opends.server.api.ExtendedOperationHandler;
-import org.opends.server.api.plugin.PostOperationPluginResult;
-import org.opends.server.api.plugin.PreOperationPluginResult;
-import org.opends.server.api.plugin.PreParsePluginResult;
 import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.types.AbstractOperation;
-import org.opends.server.types.CancelRequest;
-import org.opends.server.types.CancelResult;
-import org.opends.server.types.Control;
-import org.opends.server.types.DisconnectReason;
-import org.opends.server.types.DN;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.operation.PostOperationExtendedOperation;
-import org.opends.server.types.operation.PostResponseExtendedOperation;
-import org.opends.server.types.operation.PreOperationExtendedOperation;
-import org.opends.server.types.operation.PreParseExtendedOperation;
-
-import static org.opends.server.core.CoreConstants.*;
-import static org.opends.server.loggers.AccessLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-
-import org.opends.server.loggers.debug.DebugLogger;
-import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.messages.CoreMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.ServerConstants.*;
+import org.opends.server.types.Operation;
 
 
 
 /**
- * This class defines an extended operation, which can perform virtually any
+ * This interface defines an extended operation, which can perform virtually any
  * kind of task.
  */
-public class ExtendedOperation
-       extends AbstractOperation
-       implements PreParseExtendedOperation, PreOperationExtendedOperation,
-                  PostOperationExtendedOperation, PostResponseExtendedOperation
+public interface ExtendedOperation
+       extends Operation
 {
   /**
-   * The tracer object for the debug logger.
-   */
-  private static final DebugTracer TRACER = DebugLogger.getTracer();
-
-  // The value for the request associated with this extended operation.
-  private ASN1OctetString requestValue;
-
-  // The value for the response associated with this extended operation.
-  private ASN1OctetString responseValue;
-
-  // Indicates whether a response has yet been sent for this operation.
-  private boolean responseSent;
-
-  // The cancel request that has been issued for this extended operation.
-  private CancelRequest cancelRequest;
-
-  // The set of response controls for this extended operation.
-  private List<Control> responseControls;
-
-  // The OID for the request associated with this extended operation.
-  private String requestOID;
-
-  // The OID for the response associated with this extended operation.
-  private String responseOID;
-
-
-
-  /**
-   * Creates a new extended operation with the provided information.
+   * Retrieves the OID for the request associated with this extended
+   * operation.
    *
-   * @param  clientConnection  The client connection with which this operation
-   *                           is associated.
-   * @param  operationID       The operation ID for this operation.
-   * @param  messageID         The message ID of the request with which this
-   *                           operation is associated.
-   * @param  requestControls   The set of controls included in the request.
-   * @param  requestOID        The OID for the request associated with this
-   *                           extended operation.
-   * @param  requestValue      The value for the request associated with this
-   *                           extended operation.
+   * @return  The OID for the request associated with this extended
+   *          operation.
    */
-  public ExtendedOperation(ClientConnection clientConnection, long operationID,
-                           int messageID, List<Control> requestControls,
-                           String requestOID, ASN1OctetString requestValue)
-  {
-    super(clientConnection, operationID, messageID, requestControls);
-
-
-    this.requestOID   = requestOID;
-    this.requestValue = requestValue;
-
-    responseOID      = null;
-    responseValue    = null;
-    responseControls = new ArrayList<Control>();
-    cancelRequest    = null;
-    responseSent     = false;
-  }
-
-
-
-  /**
-   * Retrieves the OID for the request associated with this extended operation.
-   *
-   * @return  The OID for the request associated with this extended operation.
-   */
-  public final String getRequestOID()
-  {
-    return requestOID;
-  }
-
-
-
-  /**
-   * Specifies the OID for the request associated with this extended operation.
-   * This should only be called by pre-parse plugins.
-   *
-   * @param  requestOID  The OID for the request associated with this extended
-   *                     operation.
-   */
-  public final void setRequestOID(String requestOID)
-  {
-    this.requestOID = requestOID;
-  }
+  public String getRequestOID();
 
 
 
@@ -164,498 +53,48 @@
    * Retrieves the value for the request associated with this extended
    * operation.
    *
-   * @return  The value for the request associated with this extended operation.
+   * @return  The value for the request associated with this extended
+   *          operation.
    */
-  public final ASN1OctetString getRequestValue()
-  {
-    return requestValue;
-  }
+  public ASN1OctetString getRequestValue();
 
 
 
   /**
-   * Specifies the value for the request associated with this extended
-   * operation.  This should only be called by pre-parse plugins.
-   *
-   * @param  requestValue  The value for the request associated with this
-   *                       extended operation.
-   */
-  public final void setRequestValue(ASN1OctetString requestValue)
-  {
-    this.requestValue = requestValue;
-  }
-
-
-
-  /**
-   * Retrieves the OID to include in the response to the client.  This should
-   * not be called by pre-parse or pre-operation plugins.
+   * Retrieves the OID to include in the response to the client.
    *
    * @return  The OID to include in the response to the client.
    */
-  public final String getResponseOID()
-  {
-    return responseOID;
-  }
+  public String getResponseOID();
 
 
 
   /**
-   * Specifies the OID to include in the response to the client.  This should
-   * not be called by post-response plugins.
+   * Specifies the OID to include in the response to the client.
    *
-   * @param  responseOID  The OID to include in the response to the client.
+   * @param  responseOID  The OID to include in the response to the
+   *                      client.
    */
-  public final void setResponseOID(String responseOID)
-  {
-    this.responseOID = responseOID;
-  }
+  public void setResponseOID(String responseOID);
 
 
 
   /**
-   * Retrieves the value to include in the response to the client.  This should
-   * not be called by pre-parse or pre-operation plugins.
+   * Retrieves the value to include in the response to the client.
    *
    * @return  The value to include in the response to the client.
    */
-  public final ASN1OctetString getResponseValue()
-  {
-    return responseValue;
-  }
+  public ASN1OctetString getResponseValue();
 
 
 
   /**
-   * Specifies the value to include in the response to the client.  This should
-   * not be called by post-response plugins.
+   * Specifies the value to include in the response to the client.
    *
-   * @param  responseValue  The value to include in the response to the client.
+   * @param  responseValue  The value to include in the response to
+   *                        the client.
    */
-  public final void setResponseValue(ASN1OctetString responseValue)
-  {
-    this.responseValue = responseValue;
-  }
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final OperationType getOperationType()
-  {
-    // Note that no debugging will be done in this method because it is a likely
-    // candidate for being called by the logging subsystem.
-
-    return OperationType.EXTENDED;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final void disconnectClient(DisconnectReason disconnectReason,
-                                     boolean sendNotification, String message,
-                                     int messageID)
-  {
-    // Before calling clientConnection.disconnect, we need to mark this
-    // operation as cancelled so that the attempt to cancel it later won't cause
-    // an unnecessary delay.
-    setCancelResult(CancelResult.CANCELED);
-
-    clientConnection.disconnect(disconnectReason, sendNotification, message,
-                                messageID);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final String[][] getRequestLogElements()
-  {
-    // Note that no debugging will be done in this method because it is a likely
-    // candidate for being called by the logging subsystem.
-
-    return new String[][]
-    {
-      new String[] { LOG_ELEMENT_EXTENDED_REQUEST_OID, requestOID }
-    };
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final String[][] getResponseLogElements()
-  {
-    // Note that no debugging will be done in this method because it is a likely
-    // candidate for being called by the logging subsystem.
-
-    String resultCode = String.valueOf(getResultCode().getIntValue());
-
-    String errorMessage;
-    StringBuilder errorMessageBuffer = getErrorMessage();
-    if (errorMessageBuffer == null)
-    {
-      errorMessage = null;
-    }
-    else
-    {
-      errorMessage = errorMessageBuffer.toString();
-    }
-
-    String matchedDNStr;
-    DN matchedDN = getMatchedDN();
-    if (matchedDN == null)
-    {
-      matchedDNStr = null;
-    }
-    else
-    {
-      matchedDNStr = matchedDN.toString();
-    }
-
-    String referrals;
-    List<String> referralURLs = getReferralURLs();
-    if ((referralURLs == null) || referralURLs.isEmpty())
-    {
-      referrals = null;
-    }
-    else
-    {
-      StringBuilder buffer = new StringBuilder();
-      Iterator<String> iterator = referralURLs.iterator();
-      buffer.append(iterator.next());
-
-      while (iterator.hasNext())
-      {
-        buffer.append(", ");
-        buffer.append(iterator.next());
-      }
-
-      referrals = buffer.toString();
-    }
-
-    String processingTime =
-         String.valueOf(getProcessingTime());
-
-    return new String[][]
-    {
-      new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
-      new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
-      new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
-      new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
-      new String[] { LOG_ELEMENT_EXTENDED_RESPONSE_OID, responseOID },
-      new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
-    };
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final List<Control> getResponseControls()
-  {
-    return responseControls;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final void addResponseControl(Control control)
-  {
-    responseControls.add(control);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final void removeResponseControl(Control control)
-  {
-    responseControls.remove(control);
-  }
-
-
-
-  /**
-   * Performs the work of actually processing this operation.  This
-   * should include all processing for the operation, including
-   * invoking plugins, logging messages, performing access control,
-   * managing synchronization, and any other work that might need to
-   * be done in the course of processing.
-   */
-  public final void run()
-  {
-    setResultCode(ResultCode.UNDEFINED);
-
-
-    // Get the plugin config manager that will be used for invoking plugins.
-    PluginConfigManager pluginConfigManager =
-         DirectoryServer.getPluginConfigManager();
-    boolean skipPostOperation = false;
-
-
-    // Start the processing timer.
-    setProcessingStartTime();
-
-
-    // Check for and handle a request to cancel this operation.
-    if (cancelRequest != null)
-    {
-      if (! (requestOID.equals(OID_CANCEL_REQUEST) ||
-             requestOID.equals(OID_START_TLS_REQUEST)))
-      {
-        indicateCancelled(cancelRequest);
-        setProcessingStopTime();
-        return;
-      }
-    }
-
-
-    // Create a labeled block of code that we can break out of if a problem is
-    // detected.
-extendedProcessing:
-    {
-      // Invoke the pre-parse extended plugins.
-      PreParsePluginResult preParseResult =
-           pluginConfigManager.invokePreParseExtendedPlugins(this);
-      if (preParseResult.connectionTerminated())
-      {
-        // There's no point in continuing with anything.  Log the request and
-        // result and return.
-        setResultCode(ResultCode.CANCELED);
-
-        int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
-        appendErrorMessage(getMessage(msgID));
-
-        setProcessingStopTime();
-
-        logExtendedRequest(this);
-        logExtendedResponse(this);
-        pluginConfigManager.invokePostResponseExtendedPlugins(this);
-        return;
-      }
-      else if (preParseResult.sendResponseImmediately())
-      {
-        skipPostOperation = true;
-        logExtendedRequest(this);
-        break extendedProcessing;
-      }
-      else if (preParseResult.skipCoreProcessing())
-      {
-        skipPostOperation = false;
-        break extendedProcessing;
-      }
-
-
-      // Log the extended request message.
-      logExtendedRequest(this);
-
-
-      // Check for and handle a request to cancel this operation.
-      if (cancelRequest != null)
-      {
-        if (! (requestOID.equals(OID_CANCEL_REQUEST) ||
-               requestOID.equals(OID_START_TLS_REQUEST)))
-        {
-          indicateCancelled(cancelRequest);
-          setProcessingStopTime();
-          pluginConfigManager.invokePostResponseExtendedPlugins(this);
-          return;
-        }
-      }
-
-
-      // Get the extended operation handler for the request OID.  If there is
-      // none, then fail.
-      ExtendedOperationHandler handler =
-           DirectoryServer.getExtendedOperationHandler(requestOID);
-      if (handler == null)
-      {
-        setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
-        appendErrorMessage(getMessage(MSGID_EXTENDED_NO_HANDLER,
-                                      String.valueOf(requestOID)));
-        break extendedProcessing;
-      }
-
-
-      // Look at the controls included in the request and ensure that all
-      // critical controls are supported by the handler.
-      List<Control> requestControls = getRequestControls();
-      if ((requestControls != null) && (! requestControls.isEmpty()))
-      {
-        for (Control c : requestControls)
-        {
-          if (! c.isCritical())
-          {
-            // The control isn't critical, so we don't care if it's supported
-            // or not.
-          }
-          else if (! handler.supportsControl(c.getOID()))
-          {
-            setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
-
-            int msgID = MSGID_EXTENDED_UNSUPPORTED_CRITICAL_CONTROL;
-            appendErrorMessage(getMessage(msgID, String.valueOf(requestOID),
-                                          c.getOID()));
-
-            break extendedProcessing;
-          }
-        }
-      }
-
-
-      // Check to see if the client has permission to perform the
-      // extended operation.
-
-      // FIXME: for now assume that this will check all permission
-      // pertinent to the operation. This includes proxy authorization
-      // and any other controls specified.
-      if (AccessControlConfigManager.getInstance()
-          .getAccessControlHandler().isAllowed(this) == false) {
-        setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
-        int msgID = MSGID_EXTENDED_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
-        appendErrorMessage(getMessage(msgID, String.valueOf(requestOID)));
-
-        skipPostOperation = true;
-        break extendedProcessing;
-      }
-
-      // Invoke the pre-operation extended plugins.
-      PreOperationPluginResult preOpResult =
-           pluginConfigManager.invokePreOperationExtendedPlugins(this);
-      if (preOpResult.connectionTerminated())
-      {
-        // There's no point in continuing with anything.  Log the result
-        // and return.
-        setResultCode(ResultCode.CANCELED);
-
-        int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
-        appendErrorMessage(getMessage(msgID));
-
-        setProcessingStopTime();
-
-        logExtendedResponse(this);
-        pluginConfigManager.invokePostResponseExtendedPlugins(this);
-        return;
-      }
-      else if (preOpResult.sendResponseImmediately())
-      {
-        skipPostOperation = true;
-        break extendedProcessing;
-      }
-      else if (preOpResult.skipCoreProcessing())
-      {
-        skipPostOperation = false;
-        break extendedProcessing;
-      }
-
-
-      // Check for and handle a request to cancel this operation.
-      if (cancelRequest != null)
-      {
-        if (! (requestOID.equals(OID_CANCEL_REQUEST) ||
-               requestOID.equals(OID_START_TLS_REQUEST)))
-        {
-          indicateCancelled(cancelRequest);
-          setProcessingStopTime();
-          pluginConfigManager.invokePostResponseExtendedPlugins(this);
-          return;
-        }
-      }
-
-
-      // Actually perform the processing for this operation.
-      handler.processExtendedOperation(this);
-    }
-
-
-    // Indicate that it is now too late to attempt to cancel the operation.
-    setCancelResult(CancelResult.TOO_LATE);
-
-
-    // Invoke the post-operation extended plugins.
-    if (! skipPostOperation)
-    {
-      PostOperationPluginResult postOpResult =
-           pluginConfigManager.invokePostOperationExtendedPlugins(this);
-      if (postOpResult.connectionTerminated())
-      {
-        // There's no point in continuing with anything.  Log the result and
-        // return.
-        setResultCode(ResultCode.CANCELED);
-
-        int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
-        appendErrorMessage(getMessage(msgID));
-
-        setProcessingStopTime();
-
-        logExtendedResponse(this);
-        pluginConfigManager.invokePostResponseExtendedPlugins(this);
-        return;
-      }
-    }
-
-
-    // Stop the processing timer.
-    setProcessingStopTime();
-
-
-    // Send the response to the client, if it has not already been sent.
-    if (! responseSent)
-    {
-      responseSent = true;
-      clientConnection.sendResponse(this);
-    }
-
-
-    // Log the extended response.
-    logExtendedResponse(this);
-
-
-
-    // Invoke the post-response extended plugins.
-    pluginConfigManager.invokePostResponseExtendedPlugins(this);
-  }
-
-
-
-  /**
-   * Sends an extended response to the client if none has already been sent.
-   * Note that extended operation handlers are strongly discouraged from using
-   * this method when it is not necessary because its use will prevent the
-   * response from being sent after post-operation plugin processing, which may
-   * impact the result that should be included.  Nevertheless, it may be needed
-   * in some special cases in which the response must be sent before the
-   * extended operation handler completes its processing (e.g., the StartTLS
-   * operation in which the response must be sent in the clear before actually
-   * enabling TLS protection).
-   */
-  public final void sendExtendedResponse()
-  {
-    if (! responseSent)
-    {
-      responseSent = true;
-      clientConnection.sendResponse(this);
-    }
-  }
-
-
+  public void setResponseValue(ASN1OctetString responseValue);
 
   /**
    * Indicates that the response for this extended operation has been sent from
@@ -663,92 +102,6 @@
    * extended operation for the case in which it needs to send a response in the
    * clear after TLS negotiation has already started on the connection.
    */
-  public final void setResponseSent()
-  {
-    this.responseSent = true;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final CancelResult cancel(CancelRequest cancelRequest)
-  {
-    this.cancelRequest = cancelRequest;
-
-    CancelResult cancelResult = getCancelResult();
-    long stopWaitingTime = System.currentTimeMillis() + 5000;
-    while ((cancelResult == null) &&
-           (System.currentTimeMillis() < stopWaitingTime))
-    {
-      try
-      {
-        Thread.sleep(50);
-      }
-      catch (Exception e)
-      {
-        if (debugEnabled())
-        {
-          TRACER.debugCaught(DebugLogLevel.ERROR, e);
-        }
-      }
-
-      cancelResult = getCancelResult();
-    }
-
-    if (cancelResult == null)
-    {
-      // This can happen in some rare cases (e.g., if a client disconnects and
-      // there is still a lot of data to send to that client), and in this case
-      // we'll prevent the cancel thread from blocking for a long period of
-      // time.
-      cancelResult = CancelResult.CANNOT_CANCEL;
-    }
-
-    return cancelResult;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final CancelRequest getCancelRequest()
-  {
-    return cancelRequest;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public boolean setCancelRequest(CancelRequest cancelRequest)
-  {
-    this.cancelRequest = cancelRequest;
-    return true;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override()
-  public final void toString(StringBuilder buffer)
-  {
-    buffer.append("ExtendedOperation(connID=");
-    buffer.append(clientConnection.getConnectionID());
-    buffer.append(", opID=");
-    buffer.append(operationID);
-    buffer.append(", oid=");
-    buffer.append(requestOID);
-    buffer.append(")");
-  }
-
+  public void setResponseSent();
 }
 
diff --git a/opends/src/server/org/opends/server/core/ExtendedOperationBasis.java b/opends/src/server/org/opends/server/core/ExtendedOperationBasis.java
new file mode 100644
index 0000000..3b5b432
--- /dev/null
+++ b/opends/src/server/org/opends/server/core/ExtendedOperationBasis.java
@@ -0,0 +1,737 @@
+/*
+ * 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-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.ExtendedOperationHandler;
+import org.opends.server.api.plugin.PostOperationPluginResult;
+import org.opends.server.api.plugin.PreOperationPluginResult;
+import org.opends.server.api.plugin.PreParsePluginResult;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.DN;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.operation.PostOperationExtendedOperation;
+import org.opends.server.types.operation.PostResponseExtendedOperation;
+import org.opends.server.types.operation.PreOperationExtendedOperation;
+import org.opends.server.types.operation.PreParseExtendedOperation;
+
+import static org.opends.server.core.CoreConstants.*;
+import static org.opends.server.loggers.AccessLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.DebugLogLevel;
+import static org.opends.server.messages.CoreMessages.*;
+import static org.opends.server.messages.MessageHandler.*;
+import static org.opends.server.util.ServerConstants.*;
+
+
+
+/**
+ * This class defines an extended operation, which can perform virtually any
+ * kind of task.
+ */
+public class ExtendedOperationBasis
+       extends AbstractOperation
+       implements ExtendedOperation,
+                  PreParseExtendedOperation,
+                  PreOperationExtendedOperation,
+                  PostOperationExtendedOperation,
+                  PostResponseExtendedOperation
+{
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = DebugLogger.getTracer();
+
+  // The value for the request associated with this extended operation.
+  private ASN1OctetString requestValue;
+
+  // The value for the response associated with this extended operation.
+  private ASN1OctetString responseValue;
+
+  // Indicates whether a response has yet been sent for this operation.
+  private boolean responseSent;
+
+  // The cancel request that has been issued for this extended operation.
+  private CancelRequest cancelRequest;
+
+  // The set of response controls for this extended operation.
+  private List<Control> responseControls;
+
+  // The OID for the request associated with this extended operation.
+  private String requestOID;
+
+  // The OID for the response associated with this extended operation.
+  private String responseOID;
+
+
+
+  /**
+   * Creates a new extended operation with the provided information.
+   *
+   * @param  clientConnection  The client connection with which this operation
+   *                           is associated.
+   * @param  operationID       The operation ID for this operation.
+   * @param  messageID         The message ID of the request with which this
+   *                           operation is associated.
+   * @param  requestControls   The set of controls included in the request.
+   * @param  requestOID        The OID for the request associated with this
+   *                           extended operation.
+   * @param  requestValue      The value for the request associated with this
+   *                           extended operation.
+   */
+  public ExtendedOperationBasis(ClientConnection clientConnection,
+                           long operationID,
+                           int messageID, List<Control> requestControls,
+                           String requestOID, ASN1OctetString requestValue)
+  {
+    super(clientConnection, operationID, messageID, requestControls);
+
+
+    this.requestOID   = requestOID;
+    this.requestValue = requestValue;
+
+    responseOID      = null;
+    responseValue    = null;
+    responseControls = new ArrayList<Control>();
+    cancelRequest    = null;
+    responseSent     = false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final String getRequestOID()
+  {
+    return requestOID;
+  }
+
+
+
+  /**
+   * Specifies the OID for the request associated with this extended operation.
+   * This should only be called by pre-parse plugins.
+   *
+   * @param  requestOID  The OID for the request associated with this extended
+   *                     operation.
+   */
+  public final void setRequestOID(String requestOID)
+  {
+    this.requestOID = requestOID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final ASN1OctetString getRequestValue()
+  {
+    return requestValue;
+  }
+
+
+
+  /**
+   * Specifies the value for the request associated with this extended
+   * operation.  This should only be called by pre-parse plugins.
+   *
+   * @param  requestValue  The value for the request associated with this
+   *                       extended operation.
+   */
+  public final void setRequestValue(ASN1OctetString requestValue)
+  {
+    this.requestValue = requestValue;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final String getResponseOID()
+  {
+    return responseOID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final void setResponseOID(String responseOID)
+  {
+    this.responseOID = responseOID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final ASN1OctetString getResponseValue()
+  {
+    return responseValue;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final void setResponseValue(ASN1OctetString responseValue)
+  {
+    this.responseValue = responseValue;
+  }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final OperationType getOperationType()
+  {
+    // Note that no debugging will be done in this method because it is a likely
+    // candidate for being called by the logging subsystem.
+
+    return OperationType.EXTENDED;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final void disconnectClient(DisconnectReason disconnectReason,
+                                     boolean sendNotification, String message,
+                                     int messageID)
+  {
+    // Before calling clientConnection.disconnect, we need to mark this
+    // operation as cancelled so that the attempt to cancel it later won't cause
+    // an unnecessary delay.
+    setCancelResult(CancelResult.CANCELED);
+
+    clientConnection.disconnect(disconnectReason, sendNotification, message,
+                                messageID);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final String[][] getRequestLogElements()
+  {
+    // Note that no debugging will be done in this method because it is a likely
+    // candidate for being called by the logging subsystem.
+
+    return new String[][]
+    {
+      new String[] { LOG_ELEMENT_EXTENDED_REQUEST_OID, requestOID }
+    };
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final String[][] getResponseLogElements()
+  {
+    // Note that no debugging will be done in this method because it is a likely
+    // candidate for being called by the logging subsystem.
+
+    String resultCode = String.valueOf(getResultCode().getIntValue());
+
+    String errorMessage;
+    StringBuilder errorMessageBuffer = getErrorMessage();
+    if (errorMessageBuffer == null)
+    {
+      errorMessage = null;
+    }
+    else
+    {
+      errorMessage = errorMessageBuffer.toString();
+    }
+
+    String matchedDNStr;
+    DN matchedDN = getMatchedDN();
+    if (matchedDN == null)
+    {
+      matchedDNStr = null;
+    }
+    else
+    {
+      matchedDNStr = matchedDN.toString();
+    }
+
+    String referrals;
+    List<String> referralURLs = getReferralURLs();
+    if ((referralURLs == null) || referralURLs.isEmpty())
+    {
+      referrals = null;
+    }
+    else
+    {
+      StringBuilder buffer = new StringBuilder();
+      Iterator<String> iterator = referralURLs.iterator();
+      buffer.append(iterator.next());
+
+      while (iterator.hasNext())
+      {
+        buffer.append(", ");
+        buffer.append(iterator.next());
+      }
+
+      referrals = buffer.toString();
+    }
+
+    String processingTime =
+         String.valueOf(getProcessingTime());
+
+    return new String[][]
+    {
+      new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
+      new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
+      new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
+      new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
+      new String[] { LOG_ELEMENT_EXTENDED_RESPONSE_OID, responseOID },
+      new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
+    };
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final List<Control> getResponseControls()
+  {
+    return responseControls;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final void addResponseControl(Control control)
+  {
+    responseControls.add(control);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final void removeResponseControl(Control control)
+  {
+    responseControls.remove(control);
+  }
+
+
+
+  /**
+   * Performs the work of actually processing this operation.  This
+   * should include all processing for the operation, including
+   * invoking plugins, logging messages, performing access control,
+   * managing synchronization, and any other work that might need to
+   * be done in the course of processing.
+   */
+  public final void run()
+  {
+    setResultCode(ResultCode.UNDEFINED);
+
+
+    // Get the plugin config manager that will be used for invoking plugins.
+    PluginConfigManager pluginConfigManager =
+         DirectoryServer.getPluginConfigManager();
+    boolean skipPostOperation = false;
+
+
+    // Start the processing timer.
+    setProcessingStartTime();
+
+
+    // Check for and handle a request to cancel this operation.
+    if (cancelRequest != null)
+    {
+      if (! (requestOID.equals(OID_CANCEL_REQUEST) ||
+             requestOID.equals(OID_START_TLS_REQUEST)))
+      {
+        indicateCancelled(cancelRequest);
+        setProcessingStopTime();
+        return;
+      }
+    }
+
+
+    // Create a labeled block of code that we can break out of if a problem is
+    // detected.
+extendedProcessing:
+    {
+      // Invoke the pre-parse extended plugins.
+      PreParsePluginResult preParseResult =
+           pluginConfigManager.invokePreParseExtendedPlugins(this);
+      if (preParseResult.connectionTerminated())
+      {
+        // There's no point in continuing with anything.  Log the request and
+        // result and return.
+        setResultCode(ResultCode.CANCELED);
+
+        int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
+        appendErrorMessage(getMessage(msgID));
+
+        setProcessingStopTime();
+
+        logExtendedRequest(this);
+        logExtendedResponse(this);
+        pluginConfigManager.invokePostResponseExtendedPlugins(this);
+        return;
+      }
+      else if (preParseResult.sendResponseImmediately())
+      {
+        skipPostOperation = true;
+        logExtendedRequest(this);
+        break extendedProcessing;
+      }
+      else if (preParseResult.skipCoreProcessing())
+      {
+        skipPostOperation = false;
+        break extendedProcessing;
+      }
+
+
+      // Log the extended request message.
+      logExtendedRequest(this);
+
+
+      // Check for and handle a request to cancel this operation.
+      if (cancelRequest != null)
+      {
+        if (! (requestOID.equals(OID_CANCEL_REQUEST) ||
+               requestOID.equals(OID_START_TLS_REQUEST)))
+        {
+          indicateCancelled(cancelRequest);
+          setProcessingStopTime();
+          pluginConfigManager.invokePostResponseExtendedPlugins(this);
+          return;
+        }
+      }
+
+
+      // Get the extended operation handler for the request OID.  If there is
+      // none, then fail.
+      ExtendedOperationHandler handler =
+           DirectoryServer.getExtendedOperationHandler(requestOID);
+      if (handler == null)
+      {
+        setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
+        appendErrorMessage(getMessage(MSGID_EXTENDED_NO_HANDLER,
+                                      String.valueOf(requestOID)));
+        break extendedProcessing;
+      }
+
+
+      // Look at the controls included in the request and ensure that all
+      // critical controls are supported by the handler.
+      List<Control> requestControls = getRequestControls();
+      if ((requestControls != null) && (! requestControls.isEmpty()))
+      {
+        for (Control c : requestControls)
+        {
+          if (! c.isCritical())
+          {
+            // The control isn't critical, so we don't care if it's supported
+            // or not.
+          }
+          else if (! handler.supportsControl(c.getOID()))
+          {
+            setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
+
+            int msgID = MSGID_EXTENDED_UNSUPPORTED_CRITICAL_CONTROL;
+            appendErrorMessage(getMessage(msgID, String.valueOf(requestOID),
+                                          c.getOID()));
+
+            break extendedProcessing;
+          }
+        }
+      }
+
+
+      // Check to see if the client has permission to perform the
+      // extended operation.
+
+      // FIXME: for now assume that this will check all permission
+      // pertinent to the operation. This includes proxy authorization
+      // and any other controls specified.
+      if (AccessControlConfigManager.getInstance()
+          .getAccessControlHandler().isAllowed(this) == false) {
+        setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+
+        int msgID = MSGID_EXTENDED_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
+        appendErrorMessage(getMessage(msgID, String.valueOf(requestOID)));
+
+        skipPostOperation = true;
+        break extendedProcessing;
+      }
+
+      // Invoke the pre-operation extended plugins.
+      PreOperationPluginResult preOpResult =
+           pluginConfigManager.invokePreOperationExtendedPlugins(this);
+      if (preOpResult.connectionTerminated())
+      {
+        // There's no point in continuing with anything.  Log the result
+        // and return.
+        setResultCode(ResultCode.CANCELED);
+
+        int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
+        appendErrorMessage(getMessage(msgID));
+
+        setProcessingStopTime();
+
+        logExtendedResponse(this);
+        pluginConfigManager.invokePostResponseExtendedPlugins(this);
+        return;
+      }
+      else if (preOpResult.sendResponseImmediately())
+      {
+        skipPostOperation = true;
+        break extendedProcessing;
+      }
+      else if (preOpResult.skipCoreProcessing())
+      {
+        skipPostOperation = false;
+        break extendedProcessing;
+      }
+
+
+      // Check for and handle a request to cancel this operation.
+      if (cancelRequest != null)
+      {
+        if (! (requestOID.equals(OID_CANCEL_REQUEST) ||
+               requestOID.equals(OID_START_TLS_REQUEST)))
+        {
+          indicateCancelled(cancelRequest);
+          setProcessingStopTime();
+          pluginConfigManager.invokePostResponseExtendedPlugins(this);
+          return;
+        }
+      }
+
+
+      // Actually perform the processing for this operation.
+      handler.processExtendedOperation(this);
+    }
+
+
+    // Indicate that it is now too late to attempt to cancel the operation.
+    setCancelResult(CancelResult.TOO_LATE);
+
+
+    // Invoke the post-operation extended plugins.
+    if (! skipPostOperation)
+    {
+      PostOperationPluginResult postOpResult =
+           pluginConfigManager.invokePostOperationExtendedPlugins(this);
+      if (postOpResult.connectionTerminated())
+      {
+        // There's no point in continuing with anything.  Log the result and
+        // return.
+        setResultCode(ResultCode.CANCELED);
+
+        int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
+        appendErrorMessage(getMessage(msgID));
+
+        setProcessingStopTime();
+
+        logExtendedResponse(this);
+        pluginConfigManager.invokePostResponseExtendedPlugins(this);
+        return;
+      }
+    }
+
+
+    // Stop the processing timer.
+    setProcessingStopTime();
+
+
+    // Send the response to the client, if it has not already been sent.
+    if (! responseSent)
+    {
+      responseSent = true;
+      clientConnection.sendResponse(this);
+    }
+
+
+    // Log the extended response.
+    logExtendedResponse(this);
+
+
+
+    // Invoke the post-response extended plugins.
+    pluginConfigManager.invokePostResponseExtendedPlugins(this);
+  }
+
+
+
+  /**
+   * Sends an extended response to the client if none has already been sent.
+   * Note that extended operation handlers are strongly discouraged from using
+   * this method when it is not necessary because its use will prevent the
+   * response from being sent after post-operation plugin processing, which may
+   * impact the result that should be included.  Nevertheless, it may be needed
+   * in some special cases in which the response must be sent before the
+   * extended operation handler completes its processing (e.g., the StartTLS
+   * operation in which the response must be sent in the clear before actually
+   * enabling TLS protection).
+   */
+  public final void sendExtendedResponse()
+  {
+    if (! responseSent)
+    {
+      responseSent = true;
+      clientConnection.sendResponse(this);
+    }
+  }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final void setResponseSent()
+  {
+    this.responseSent = true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final CancelResult cancel(CancelRequest cancelRequest)
+  {
+    this.cancelRequest = cancelRequest;
+
+    CancelResult cancelResult = getCancelResult();
+    long stopWaitingTime = System.currentTimeMillis() + 5000;
+    while ((cancelResult == null) &&
+           (System.currentTimeMillis() < stopWaitingTime))
+    {
+      try
+      {
+        Thread.sleep(50);
+      }
+      catch (Exception e)
+      {
+        if (debugEnabled())
+        {
+          TRACER.debugCaught(DebugLogLevel.ERROR, e);
+        }
+      }
+
+      cancelResult = getCancelResult();
+    }
+
+    if (cancelResult == null)
+    {
+      // This can happen in some rare cases (e.g., if a client disconnects and
+      // there is still a lot of data to send to that client), and in this case
+      // we'll prevent the cancel thread from blocking for a long period of
+      // time.
+      cancelResult = CancelResult.CANNOT_CANCEL;
+    }
+
+    return cancelResult;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final CancelRequest getCancelRequest()
+  {
+    return cancelRequest;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean setCancelRequest(CancelRequest cancelRequest)
+  {
+    this.cancelRequest = cancelRequest;
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public final void toString(StringBuilder buffer)
+  {
+    buffer.append("ExtendedOperation(connID=");
+    buffer.append(clientConnection.getConnectionID());
+    buffer.append(", opID=");
+    buffer.append(operationID);
+    buffer.append(", oid=");
+    buffer.append(requestOID);
+    buffer.append(")");
+  }
+
+}
+
diff --git a/opends/src/server/org/opends/server/core/PluginConfigManager.java b/opends/src/server/org/opends/server/core/PluginConfigManager.java
index 6022046..6cfeec1 100644
--- a/opends/src/server/org/opends/server/core/PluginConfigManager.java
+++ b/opends/src/server/org/opends/server/core/PluginConfigManager.java
@@ -84,6 +84,7 @@
 import org.opends.server.types.operation.PostOperationBindOperation;
 import org.opends.server.types.operation.PostOperationCompareOperation;
 import org.opends.server.types.operation.PostOperationDeleteOperation;
+import org.opends.server.types.operation.PostOperationExtendedOperation;
 import org.opends.server.types.operation.PostOperationModifyDNOperation;
 import org.opends.server.types.operation.PostOperationModifyOperation;
 import org.opends.server.types.operation.PostOperationSearchOperation;
@@ -91,6 +92,7 @@
 import org.opends.server.types.operation.PostResponseBindOperation;
 import org.opends.server.types.operation.PostResponseCompareOperation;
 import org.opends.server.types.operation.PostResponseDeleteOperation;
+import org.opends.server.types.operation.PostResponseExtendedOperation;
 import org.opends.server.types.operation.PostResponseModifyDNOperation;
 import org.opends.server.types.operation.PostResponseModifyOperation;
 import org.opends.server.types.operation.PostResponseSearchOperation;
@@ -98,6 +100,7 @@
 import org.opends.server.types.operation.PreOperationBindOperation;
 import org.opends.server.types.operation.PreOperationCompareOperation;
 import org.opends.server.types.operation.PreOperationDeleteOperation;
+import org.opends.server.types.operation.PreOperationExtendedOperation;
 import org.opends.server.types.operation.PreOperationModifyDNOperation;
 import org.opends.server.types.operation.PreOperationModifyOperation;
 import org.opends.server.types.operation.PreOperationSearchOperation;
@@ -105,6 +108,7 @@
 import org.opends.server.types.operation.PreParseBindOperation;
 import org.opends.server.types.operation.PreParseCompareOperation;
 import org.opends.server.types.operation.PreParseDeleteOperation;
+import org.opends.server.types.operation.PreParseExtendedOperation;
 import org.opends.server.types.operation.PreParseModifyOperation;
 import org.opends.server.types.operation.PreParseSearchOperation;
 import org.opends.server.workflowelement.localbackend.*;
@@ -2142,7 +2146,7 @@
    * @return  The result of processing the pre-parse extended plugins.
    */
   public PreParsePluginResult invokePreParseExtendedPlugins(
-                                   ExtendedOperation extendedOperation)
+                                   PreParseExtendedOperation extendedOperation)
   {
     PreParsePluginResult result = null;
 
@@ -2876,7 +2880,7 @@
    * @return  The result of processing the pre-operation extended plugins.
    */
   public PreOperationPluginResult invokePreOperationExtendedPlugins(
-                                       ExtendedOperation extendedOperation)
+                               PreOperationExtendedOperation extendedOperation)
   {
     PreOperationPluginResult result = null;
 
@@ -3610,7 +3614,7 @@
    * @return  The result of processing the post-operation extended plugins.
    */
   public PostOperationPluginResult invokePostOperationExtendedPlugins(
-                                        ExtendedOperation extendedOperation)
+                             PostOperationExtendedOperation extendedOperation)
   {
     PostOperationPluginResult result = null;
 
@@ -4316,7 +4320,7 @@
    * @return  The result of processing the post-response extended plugins.
    */
   public PostResponsePluginResult invokePostResponseExtendedPlugins(
-                                       ExtendedOperation extendedOperation)
+                              PostResponseExtendedOperation extendedOperation)
   {
     PostResponsePluginResult result = null;
 
diff --git a/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java b/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
index ea0b076..4984b4b 100644
--- a/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -1076,11 +1076,12 @@
    *          and contains information about the result of the
    *          processing.
    */
-  public ExtendedOperation processExtendedOperation(String requestOID,
+  public ExtendedOperation processExtendedOperation(
+                                String requestOID,
                                 ASN1OctetString requestValue)
   {
-    ExtendedOperation extendedOperation =
-         new ExtendedOperation(this, nextOperationID(),
+    ExtendedOperationBasis extendedOperation =
+         new ExtendedOperationBasis(this, nextOperationID(),
                                nextMessageID(),
                                new ArrayList<Control>(0), requestOID,
                                requestValue);
diff --git a/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java b/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
index 23eaf49..530a0b0 100644
--- a/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -652,11 +652,11 @@
    * @return  A reference to the extended operation that was processed and
    *          contains information about the result of the processing.
    */
-  public ExtendedOperation processExtendedOperation(String requestOID,
+  public ExtendedOperationBasis processExtendedOperation(String requestOID,
                                 ASN1OctetString requestValue)
   {
-    ExtendedOperation extendedOperation =
-         new ExtendedOperation(this, nextOperationID(), nextMessageID(),
+    ExtendedOperationBasis extendedOperation =
+         new ExtendedOperationBasis(this, nextOperationID(), nextMessageID(),
                                new ArrayList<Control>(0), requestOID,
                                requestValue);
 
diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
index 1330c29..6226046 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -59,7 +59,7 @@
 import org.opends.server.core.CompareOperationBasis;
 import org.opends.server.core.DeleteOperationBasis;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ExtendedOperation;
+import org.opends.server.core.ExtendedOperationBasis;
 import org.opends.server.core.ModifyDNOperationBasis;
 import org.opends.server.core.ModifyOperationBasis;
 import org.opends.server.core.PersistentSearch;
@@ -661,7 +661,7 @@
           return null;
         }
 
-        ExtendedOperation extOp = (ExtendedOperation) operation;
+        ExtendedOperationBasis extOp = (ExtendedOperationBasis) operation;
         protocolOp = new ExtendedResponseProtocolOp(resultCode.getIntValue(),
                               errorMessage.toString(), matchedDN, referralURLs,
                               extOp.getResponseOID(), extOp.getResponseValue());
@@ -2195,8 +2195,8 @@
 
     ExtendedRequestProtocolOp protocolOp =
          message.getExtendedRequestProtocolOp();
-    ExtendedOperation extendedOp =
-         new ExtendedOperation(this, nextOperationID.getAndIncrement(),
+    ExtendedOperationBasis extendedOp =
+         new ExtendedOperationBasis(this, nextOperationID.getAndIncrement(),
                                message.getMessageID(), controls,
                                protocolOp.getOID(), protocolOp.getValue());
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java
index fb50041..a3ca950 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/WhoAmIExtendedOperationTestCase.java
@@ -47,7 +47,6 @@
 import org.opends.server.protocols.ldap.UnbindRequestProtocolOp;
 import org.opends.server.tools.LDAPAuthenticationHandler;
 import org.opends.server.types.AuthenticationInfo;
-import org.opends.server.types.Control;
 import org.opends.server.types.Entry;
 import org.opends.server.types.ResultCode;
 

--
Gitblit v1.10.0