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