From 61319d28a0a0129e3a81f4f9ca770d1b63e06233 Mon Sep 17 00:00:00 2001
From: jdemendi <jdemendi@localhost>
Date: Mon, 16 Jul 2007 08:02:35 +0000
Subject: [PATCH] This fix is the refactoring of the compare operation (issue #1886).
---
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java | 582 ++++++++++
opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxPrivilegeTestCase.java | 10
opends/src/server/org/opends/server/core/CompareOperationBasis.java | 720 ++++++++++++
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java | 86 +
opends/src/server/org/opends/server/api/AccessControlHandler.java | 4
opends/src/server/org/opends/server/core/PluginConfigManager.java | 12
opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java | 2
opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java | 4
opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java | 2
opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java | 9
opends/src/server/org/opends/server/core/CompareOperation.java | 1134 -------------------
opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java | 4
opends/src/server/org/opends/server/core/OperationWrapper.java | 511 +++++++++
opends/src/server/org/opends/server/core/CompareOperationWrapper.java | 158 ++
opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java | 8
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java | 6
opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java | 94 +
17 files changed, 2,168 insertions(+), 1,178 deletions(-)
diff --git a/opends/src/server/org/opends/server/api/AccessControlHandler.java b/opends/src/server/org/opends/server/api/AccessControlHandler.java
index ef0b4ad..99d8a58 100644
--- a/opends/src/server/org/opends/server/api/AccessControlHandler.java
+++ b/opends/src/server/org/opends/server/api/AccessControlHandler.java
@@ -161,8 +161,8 @@
* @return {@code true} if the operation should be allowed by the
* access control configuration, or {@code false} if not.
*/
- public abstract boolean isAllowed(CompareOperation
- compareOperation);
+ public abstract boolean isAllowed(LocalBackendCompareOperation
+ compareOperation);
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
index d1907c5..56125c6 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -880,7 +880,7 @@
* @param operation The compare operation to check access on.
* @return True if access is allowed.
*/
- public boolean isAllowed(CompareOperation operation) {
+ public boolean isAllowed(LocalBackendCompareOperation operation) {
AciLDAPOperationContainer operationContainer =
new AciLDAPOperationContainer(operation, ACI_COMPARE);
String baseName;
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
index 2f791e4..aea44cb 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
+++ b/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
@@ -58,7 +58,9 @@
* @param operation The compare operation to evaluate.
* @param rights The rights of a compare operation.
*/
- public AciLDAPOperationContainer(CompareOperation operation, int rights) {
+ public AciLDAPOperationContainer(LocalBackendCompareOperation operation,
+ int rights)
+ {
super(operation, rights, operation.getEntryToCompare());
}
diff --git a/opends/src/server/org/opends/server/core/CompareOperation.java b/opends/src/server/org/opends/server/core/CompareOperation.java
index 1a3af75..6a302e5 100644
--- a/opends/src/server/org/opends/server/core/CompareOperation.java
+++ b/opends/src/server/org/opends/server/core/CompareOperation.java
@@ -26,188 +26,27 @@
*/
package org.opends.server.core;
-
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.locks.Lock;
-
-import org.opends.server.api.Backend;
-import org.opends.server.api.ClientConnection;
-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.controls.LDAPAssertionRequestControl;
-import org.opends.server.controls.ProxiedAuthV1Control;
-import org.opends.server.controls.ProxiedAuthV2Control;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.types.AbstractOperation;
-import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
import org.opends.server.types.ByteString;
-import org.opends.server.types.CancelRequest;
-import org.opends.server.types.CancelResult;
-import org.opends.server.types.Control;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
-import org.opends.server.types.LDAPException;
-import org.opends.server.types.LockManager;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.Privilege;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
-import org.opends.server.types.operation.PostOperationCompareOperation;
-import org.opends.server.types.operation.PostResponseCompareOperation;
-import org.opends.server.types.operation.PreOperationCompareOperation;
-import org.opends.server.types.operation.PreParseCompareOperation;
-
-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 static org.opends.server.util.StaticUtils.*;
-
+import org.opends.server.types.Operation;
/**
- * This class defines an operation that may be used to determine whether a
+ * This interface defines an operation that may be used to determine whether a
* specified entry in the Directory Server contains a given attribute-value
* pair.
*/
-public class CompareOperation
- extends AbstractOperation
- implements PreParseCompareOperation, PreOperationCompareOperation,
- PostOperationCompareOperation, PostResponseCompareOperation
+public interface CompareOperation extends Operation
{
/**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = DebugLogger.getTracer();
-
- // The attribute type for this compare operation.
- private AttributeType attributeType;
-
- // The assertion value for the compare operation.
- private ByteString assertionValue;
-
- // The raw, unprocessed entry DN as included in the client request.
- private ByteString rawEntryDN;
-
- // The cancel request that has been issued for this compare operation.
- private CancelRequest cancelRequest;
-
- // The DN of the entry for the compare operation.
- private DN entryDN;
-
- // The proxied authorization target DN for this operation.
- private DN proxiedAuthorizationDN;
-
- // The entry to be compared.
- private Entry entry;
-
- // The set of response controls for this compare operation.
- private List<Control> responseControls;
-
- // The attribute type for the compare operation.
- private String rawAttributeType;
-
-
-
- /**
- * Creates a new compare 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 rawEntryDN The raw, unprocessed entry DN as provided in the
- * client request. This may or may not be a valid
- * DN as no validation will have been performed yet.
- * @param rawAttributeType The raw attribute type for the compare operation.
- * @param assertionValue The assertion value for the compare operation.
- */
- public CompareOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- ByteString rawEntryDN, String rawAttributeType,
- ByteString assertionValue)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.rawEntryDN = rawEntryDN;
- this.rawAttributeType = rawAttributeType;
- this.assertionValue = assertionValue;
-
- responseControls = new ArrayList<Control>();
- entry = null;
- entryDN = null;
- attributeType = null;
- cancelRequest = null;
- proxiedAuthorizationDN = null;
- }
-
-
-
- /**
- * Creates a new compare 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 entryDN The entry DN for this compare operation.
- * @param attributeType The attribute type for this compare operation.
- * @param assertionValue The assertion value for the compare operation.
- */
- public CompareOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- DN entryDN, AttributeType attributeType,
- ByteString assertionValue)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.entryDN = entryDN;
- this.attributeType = attributeType;
- this.assertionValue = assertionValue;
-
- responseControls = new ArrayList<Control>();
- rawEntryDN = new ASN1OctetString(entryDN.toString());
- rawAttributeType = attributeType.getNameOrOID();
- cancelRequest = null;
- entry = null;
- proxiedAuthorizationDN = null;
- }
-
-
-
- /**
* Retrieves the raw, unprocessed entry DN as included in the client request.
* The DN that is returned may or may not be a valid DN, since no validation
* will have been performed upon it.
*
* @return The raw, unprocessed entry DN as included in the client request.
*/
- public final ByteString getRawEntryDN()
- {
- return rawEntryDN;
- }
-
+ public ByteString getRawEntryDN();
/**
@@ -217,13 +56,7 @@
* @param rawEntryDN The raw, unprocessed entry DN as included in the client
* request.
*/
- public final void setRawEntryDN(ByteString rawEntryDN)
- {
- this.rawEntryDN = rawEntryDN;
-
- entryDN = null;
- }
-
+ public void setRawEntryDN(ByteString rawEntryDN);
/**
@@ -234,11 +67,7 @@
* @return The DN of the entry to compare, or <CODE>null</CODE> if the raw
* entry DN has not yet been processed.
*/
- public final DN getEntryDN()
- {
- return entryDN;
- }
-
+ public DN getEntryDN();
/**
@@ -246,11 +75,7 @@
*
* @return The raw attribute type for this compare operation.
*/
- public final String getRawAttributeType()
- {
- return rawAttributeType;
- }
-
+ public String getRawAttributeType();
/**
@@ -260,13 +85,7 @@
* @param rawAttributeType The raw attribute type for this compare
* operation.
*/
- public final void setRawAttributeType(String rawAttributeType)
- {
- this.rawAttributeType = rawAttributeType;
-
- attributeType = null;
- }
-
+ public void setRawAttributeType(String rawAttributeType);
/**
@@ -276,23 +95,23 @@
*
* @return The attribute type for this compare operation.
*/
- public final AttributeType getAttributeType()
- {
- return attributeType;
- }
+ public AttributeType getAttributeType();
+ /**
+ * Specifies the attribute type for this compare operation.
+ *
+ * @param attributeType The attribute type for this compare operation.
+ */
+ public void setAttributeType(AttributeType attributeType);
+
/**
* Retrieves the assertion value for this compare operation.
*
* @return The assertion value for this compare operation.
*/
- public final ByteString getAssertionValue()
- {
- return assertionValue;
- }
-
+ public ByteString getAssertionValue();
/**
@@ -301,926 +120,23 @@
*
* @param assertionValue The assertion value for this compare operation.
*/
- public final void setAssertionValue(ByteString assertionValue)
- {
- this.assertionValue = assertionValue;
- }
-
+ public void setAssertionValue(ByteString assertionValue);
/**
- * Retrieves the entry to target with the compare operation. This should not
- * be called by pre-parse plugins.
+ * Retrieves the proxied authorization target DN for this compare operation.
*
- * @return The entry to target with the compare operation, or
- * <CODE>null</CODE> if the entry is not yet available.
+ * @return The proxied authorization target DN for this compare operation
*/
- public final Entry getEntryToCompare()
- {
- return entry;
- }
-
- /**
- * {@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.COMPARE;
- }
-
+ public DN getProxiedAuthorizationDN();
/**
- * {@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_ENTRY_DN, String.valueOf(rawEntryDN) },
- new String[] { LOG_ELEMENT_COMPARE_ATTR, rawAttributeType }
- };
- }
-
-
-
- /**
- * {@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_PROCESSING_TIME, processingTime }
- };
- }
-
-
-
- /**
- * Retrieves the proxied authorization DN for this operation if proxied
- * authorization has been requested.
+ * Specifies the proxied authorization target DN for this compare operation.
*
- * @return The proxied authorization DN for this operation if proxied
- * authorization has been requested, or {@code null} if proxied
- * authorization has not been requested.
+ * @param proxiedAuthorizationDN The proxied authorization target DN for
+ * this compare operation
*/
- public DN getProxiedAuthorizationDN()
- {
- return proxiedAuthorizationDN;
- }
-
-
-
- /**
- * {@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)
- {
- indicateCancelled(cancelRequest);
- setProcessingStopTime();
- return;
- }
-
-
- // Create a labeled block of code that we can break out of if a problem is
- // detected.
-compareProcessing:
- {
- // Invoke the pre-parse compare plugins.
- PreParsePluginResult preParseResult =
- pluginConfigManager.invokePreParseComparePlugins(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();
-
- logCompareRequest(this);
- logCompareResponse(this);
- pluginConfigManager.invokePostResponseComparePlugins(this);
- return;
- }
- else if (preParseResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- logCompareRequest(this);
- break compareProcessing;
- }
- else if (preParseResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break compareProcessing;
- }
-
-
- // Log the compare request message.
- logCompareRequest(this);
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- setProcessingStopTime();
- logCompareResponse(this);
- pluginConfigManager.invokePostResponseComparePlugins(this);
- return;
- }
-
-
- // Process the entry DN to convert it from the raw form to the form
- // required for the rest of the compare processing.
- try
- {
- if (entryDN == null)
- {
- entryDN = DN.decode(rawEntryDN);
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- skipPostOperation = true;
-
- break compareProcessing;
- }
-
-
- // If the target entry is in the server configuration, then make sure the
- // requester has the CONFIG_READ privilege.
- if (DirectoryServer.getConfigHandler().handlesEntry(entryDN) &&
- (! clientConnection.hasPrivilege(Privilege.CONFIG_READ, this)))
- {
- int msgID = MSGID_COMPARE_CONFIG_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
- skipPostOperation = true;
-
- break compareProcessing;
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- setProcessingStopTime();
- logCompareResponse(this);
- pluginConfigManager.invokePostResponseComparePlugins(this);
- return;
- }
-
-
- // Grab a read lock on the entry.
- Lock readLock = null;
- for (int i=0; i < 3; i++)
- {
- readLock = LockManager.lockRead(entryDN);
- if (readLock != null)
- {
- break;
- }
- }
-
- if (readLock == null)
- {
- int msgID = MSGID_COMPARE_CANNOT_LOCK_ENTRY;
- String message = getMessage(msgID, String.valueOf(entryDN));
-
- setResultCode(DirectoryServer.getServerErrorResultCode());
- appendErrorMessage(message);
- skipPostOperation = true;
- break compareProcessing;
- }
-
- try
- {
- // Get the entry. If it does not exist, then fail.
- try
- {
- entry = DirectoryServer.getEntry(entryDN);
-
- if (entry == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_COMPARE_NO_SUCH_ENTRY,
- String.valueOf(entryDN)));
-
- // See if one of the entry's ancestors exists.
- DN parentDN = entryDN.getParentDNInSuffix();
- while (parentDN != null)
- {
- try
- {
- if (DirectoryServer.entryExists(parentDN))
- {
- setMatchedDN(parentDN);
- break;
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- break;
- }
-
- parentDN = parentDN.getParentDNInSuffix();
- }
-
- break compareProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- break compareProcessing;
- }
-
- // Check to see if there are any controls in the request. If so, then
- // see if there is any special processing required.
- List<Control> requestControls = getRequestControls();
- if ((requestControls != null) && (! requestControls.isEmpty()))
- {
- for (int i=0; i < requestControls.size(); i++)
- {
- Control c = requestControls.get(i);
- String oid = c.getOID();
-
- if (oid.equals(OID_LDAP_ASSERTION))
- {
- LDAPAssertionRequestControl assertControl;
- if (c instanceof LDAPAssertionRequestControl)
- {
- assertControl = (LDAPAssertionRequestControl) c;
- }
- else
- {
- try
- {
- assertControl = LDAPAssertionRequestControl.decodeControl(c);
- requestControls.set(i, assertControl);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break compareProcessing;
- }
- }
-
- try
- {
- // FIXME -- We need to determine whether the current user has
- // permission to make this determination.
- SearchFilter filter = assertControl.getSearchFilter();
- if (! filter.matchesEntry(entry))
- {
- setResultCode(ResultCode.ASSERTION_FAILED);
-
- appendErrorMessage(getMessage(MSGID_COMPARE_ASSERTION_FAILED,
- String.valueOf(entryDN)));
-
- break compareProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(ResultCode.PROTOCOL_ERROR);
-
- int msgID = MSGID_COMPARE_CANNOT_PROCESS_ASSERTION_FILTER;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- de.getErrorMessage()));
-
- break compareProcessing;
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V1))
- {
- // The requester must have the PROXIED_AUTH privilige in order to
- // be able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break compareProcessing;
- }
-
-
- ProxiedAuthV1Control proxyControl;
- if (c instanceof ProxiedAuthV1Control)
- {
- proxyControl = (ProxiedAuthV1Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV1Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break compareProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break compareProcessing;
- }
-
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break compareProcessing;
- }
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V2))
- {
- // The requester must have the PROXIED_AUTH privilige in order to
- // be able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break compareProcessing;
- }
-
-
- ProxiedAuthV2Control proxyControl;
- if (c instanceof ProxiedAuthV2Control)
- {
- proxyControl = (ProxiedAuthV2Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV2Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break compareProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break compareProcessing;
- }
-
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break compareProcessing;
- }
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
-
- // NYI -- Add support for additional controls.
- else if (c.isCritical())
- {
- Backend backend = DirectoryServer.getBackend(entryDN);
- if ((backend == null) || (! backend.supportsControl(oid)))
- {
- setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
-
- int msgID = MSGID_COMPARE_UNSUPPORTED_CRITICAL_CONTROL;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- oid));
-
- break compareProcessing;
- }
- }
- }
- }
-
-
- // Check to see if the client has permission to perform the
- // compare.
-
- // FIXME: for now assume that this will check all permission
- // pertinent to the operation. This includes proxy authorization
- // and any other controls specified.
-
- // FIXME: earlier checks to see if the entry already exists may
- // have already exposed sensitive information to the client.
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isAllowed(this) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break compareProcessing;
- }
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- setProcessingStopTime();
- logCompareResponse(this);
- pluginConfigManager.invokePostResponseComparePlugins(this);
- return;
- }
-
-
- // Invoke the pre-operation compare plugins.
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationComparePlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the request and
- // result and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- setProcessingStopTime();
- logCompareResponse(this);
- pluginConfigManager.invokePostResponseComparePlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break compareProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break compareProcessing;
- }
-
-
- // Get the base attribute type and set of options.
- String baseName;
- HashSet<String> options;
- int semicolonPos = rawAttributeType.indexOf(';');
- if (semicolonPos > 0)
- {
- baseName = toLowerCase(rawAttributeType.substring(0, semicolonPos));
-
- options = new HashSet<String>();
- int nextPos = rawAttributeType.indexOf(';', semicolonPos+1);
- while (nextPos > 0)
- {
- options.add(rawAttributeType.substring(semicolonPos+1, nextPos));
- semicolonPos = nextPos;
- nextPos = rawAttributeType.indexOf(';', semicolonPos+1);
- }
-
- options.add(rawAttributeType.substring(semicolonPos+1));
- }
- else
- {
- baseName = toLowerCase(rawAttributeType);
- options = null;
- }
-
-
- // Actually perform the compare operation.
- List<Attribute> attrList = null;
- if (attributeType == null)
- {
- attributeType = DirectoryServer.getAttributeType(baseName);
- }
- if (attributeType == null)
- {
- attrList = entry.getAttribute(baseName, options);
- attributeType = DirectoryServer.getDefaultAttributeType(baseName);
- }
- else
- {
- attrList = entry.getAttribute(attributeType, options);
- }
-
- if ((attrList == null) || attrList.isEmpty())
- {
- setResultCode(ResultCode.NO_SUCH_ATTRIBUTE);
- if (options == null)
- {
- appendErrorMessage(getMessage(MSGID_COMPARE_OP_NO_SUCH_ATTR,
- String.valueOf(entryDN), baseName));
- }
- else
- {
- appendErrorMessage(getMessage(
- MSGID_COMPARE_OP_NO_SUCH_ATTR_WITH_OPTIONS,
- String.valueOf(entryDN), baseName));
- }
- }
- else
- {
- AttributeValue value = new AttributeValue(attributeType,
- assertionValue);
-
- boolean matchFound = false;
- for (Attribute a : attrList)
- {
- if (a.hasValue(value))
- {
- matchFound = true;
- break;
- }
- }
-
- if (matchFound)
- {
- setResultCode(ResultCode.COMPARE_TRUE);
- }
- else
- {
- setResultCode(ResultCode.COMPARE_FALSE);
- }
- }
- }
- finally
- {
- LockManager.unlock(entryDN, readLock);
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- setProcessingStopTime();
- logCompareResponse(this);
- pluginConfigManager.invokePostResponseComparePlugins(this);
- return;
- }
-
-
- // Invoke the post-operation compare plugins.
- if (! skipPostOperation)
- {
- PostOperationPluginResult postOperationResult =
- pluginConfigManager.invokePostOperationComparePlugins(this);
- if (postOperationResult.connectionTerminated())
- {
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- setProcessingStopTime();
- logCompareResponse(this);
- pluginConfigManager.invokePostResponseComparePlugins(this);
- return;
- }
- }
-
-
- // Indicate that it is now too late to attempt to cancel the operation.
- setCancelResult(CancelResult.TOO_LATE);
-
-
- // Stop the processing timer.
- setProcessingStopTime();
-
-
- // Send the compare response to the client.
- clientConnection.sendResponse(this);
-
-
- // Log the compare response message.
- logCompareResponse(this);
-
-
- // Invoke the post-response compare plugins.
- pluginConfigManager.invokePostResponseComparePlugins(this);
- }
-
-
-
- /**
- * {@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("CompareOperation(connID=");
- buffer.append(clientConnection.getConnectionID());
- buffer.append(", opID=");
- buffer.append(operationID);
- buffer.append(", dn=");
- buffer.append(rawEntryDN);
- buffer.append(", attr=");
- buffer.append(rawAttributeType);
- buffer.append(")");
- }
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN);
}
-
diff --git a/opends/src/server/org/opends/server/core/CompareOperationBasis.java b/opends/src/server/org/opends/server/core/CompareOperationBasis.java
new file mode 100644
index 0000000..e4f74f8
--- /dev/null
+++ b/opends/src/server/org/opends/server/core/CompareOperationBasis.java
@@ -0,0 +1,720 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+import static org.opends.server.core.CoreConstants.*;
+import static org.opends.server.loggers.AccessLogger.logCompareRequest;
+import static org.opends.server.loggers.AccessLogger.logCompareResponse;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.messages.CoreMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.plugin.PreParsePluginResult;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.operation.PostResponseCompareOperation;
+import org.opends.server.types.operation.PreParseCompareOperation;
+import org.opends.server.workflowelement.localbackend.
+ LocalBackendCompareOperation;
+
+
+/**
+ * This class defines an operation that may be used to determine whether a
+ * specified entry in the Directory Server contains a given attribute-value
+ * pair.
+ */
+public class CompareOperationBasis
+ extends AbstractOperation
+ implements PreParseCompareOperation, CompareOperation,
+ Runnable, PostResponseCompareOperation
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
+
+ // The attribute type for this compare operation.
+ private AttributeType attributeType;
+
+ // The assertion value for the compare operation.
+ private ByteString assertionValue;
+
+ // The raw, unprocessed entry DN as included in the client request.
+ private ByteString rawEntryDN;
+
+ // The cancel request that has been issued for this compare operation.
+ private CancelRequest cancelRequest;
+
+ // The DN of the entry for the compare operation.
+ private DN entryDN;
+
+ // The proxied authorization target DN for this operation.
+ private DN proxiedAuthorizationDN;
+
+ // The set of response controls for this compare operation.
+ private List<Control> responseControls;
+
+ // The attribute type for the compare operation.
+ private String rawAttributeType;
+
+
+
+ /**
+ * Creates a new compare 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 rawEntryDN The raw, unprocessed entry DN as provided in the
+ * client request. This may or may not be a valid
+ * DN as no validation will have been performed yet.
+ * @param rawAttributeType The raw attribute type for the compare operation.
+ * @param assertionValue The assertion value for the compare operation.
+ */
+ public CompareOperationBasis(
+ ClientConnection clientConnection, long operationID,
+ int messageID, List<Control> requestControls,
+ ByteString rawEntryDN, String rawAttributeType,
+ ByteString assertionValue)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.rawEntryDN = rawEntryDN;
+ this.rawAttributeType = rawAttributeType;
+ this.assertionValue = assertionValue;
+
+ responseControls = new ArrayList<Control>();
+ entryDN = null;
+ attributeType = null;
+ cancelRequest = null;
+ proxiedAuthorizationDN = null;
+ }
+
+
+
+ /**
+ * Creates a new compare 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 entryDN The entry DN for this compare operation.
+ * @param attributeType The attribute type for this compare operation.
+ * @param assertionValue The assertion value for the compare operation.
+ */
+ public CompareOperationBasis(
+ ClientConnection clientConnection, long operationID,
+ int messageID, List<Control> requestControls,
+ DN entryDN, AttributeType attributeType,
+ ByteString assertionValue)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.entryDN = entryDN;
+ this.attributeType = attributeType;
+ this.assertionValue = assertionValue;
+
+ responseControls = new ArrayList<Control>();
+ rawEntryDN = new ASN1OctetString(entryDN.toString());
+ rawAttributeType = attributeType.getNameOrOID();
+ cancelRequest = null;
+ proxiedAuthorizationDN = null;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ByteString getRawEntryDN()
+ {
+ return rawEntryDN;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawEntryDN(ByteString rawEntryDN)
+ {
+ this.rawEntryDN = rawEntryDN;
+
+ entryDN = null;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getEntryDN()
+ {
+ return entryDN;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String getRawAttributeType()
+ {
+ return rawAttributeType;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawAttributeType(String rawAttributeType)
+ {
+ this.rawAttributeType = rawAttributeType;
+
+ attributeType = null;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final AttributeType getAttributeType()
+ {
+ return attributeType;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttributeType(AttributeType attributeType)
+ {
+ this.attributeType = attributeType;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ByteString getAssertionValue()
+ {
+ return assertionValue;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setAssertionValue(ByteString assertionValue)
+ {
+ this.assertionValue = assertionValue;
+ }
+
+
+
+ /**
+ * {@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.COMPARE;
+ }
+
+
+
+ /**
+ * {@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_ENTRY_DN, String.valueOf(rawEntryDN) },
+ new String[] { LOG_ELEMENT_COMPARE_ATTR, rawAttributeType }
+ };
+ }
+
+
+
+ /**
+ * {@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_PROCESSING_TIME, processingTime }
+ };
+ }
+
+
+
+ /**
+ * Retrieves the proxied authorization DN for this operation if proxied
+ * authorization has been requested.
+ *
+ * @return The proxied authorization DN for this operation if proxied
+ * authorization has been requested, or {@code null} if proxied
+ * authorization has not been requested.
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return proxiedAuthorizationDN;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+ {
+ this.proxiedAuthorizationDN = proxiedAuthorizationDN;
+ }
+
+
+
+ /**
+ * {@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);
+
+ // Start the processing timer.
+ setProcessingStartTime();
+
+ // Check for and handle a request to cancel this operation.
+ if (cancelRequest != null)
+ {
+ indicateCancelled(cancelRequest);
+ setProcessingStopTime();
+ return;
+ }
+
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+
+ // Create a labeled block of code that we can break out of if a problem is
+ // detected.
+ boolean workflowExecuted = false;
+compareProcessing:
+ {
+ // Invoke the pre-parse compare plugins.
+ PreParsePluginResult preParseResult =
+ pluginConfigManager.invokePreParseComparePlugins(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();
+
+ logCompareRequest(this);
+ logCompareResponse(this);
+ pluginConfigManager.invokePostResponseComparePlugins(this);
+ return;
+ }
+ else if (preParseResult.sendResponseImmediately())
+ {
+ logCompareRequest(this);
+ break compareProcessing;
+ }
+ else if (preParseResult.skipCoreProcessing())
+ {
+ break compareProcessing;
+ }
+
+
+ // Log the compare request message.
+ logCompareRequest(this);
+
+
+ // Check for and handle a request to cancel this operation.
+ if (cancelRequest != null)
+ {
+ indicateCancelled(cancelRequest);
+ setProcessingStopTime();
+ logCompareResponse(this);
+ pluginConfigManager.invokePostResponseComparePlugins(this);
+ return;
+ }
+
+
+ // Process the entry DN to convert it from the raw form to the form
+ // required for the rest of the compare processing.
+ try
+ {
+ if (entryDN == null)
+ {
+ entryDN = DN.decode(rawEntryDN);
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResultCode(de.getResultCode());
+ appendErrorMessage(de.getErrorMessage());
+
+ break compareProcessing;
+ }
+
+
+ // Retrieve the network group registered with the client connection
+ // and get a workflow to process the operation.
+ NetworkGroup ng = getClientConnection().getNetworkGroup();
+ Workflow workflow = ng.getWorkflowCandidate(entryDN);
+ if (workflow == null)
+ {
+ // We have found no workflow for the requested base DN, just return
+ // a no such entry result code and stop the processing.
+ updateOperationErrMsgAndResCode();
+ break compareProcessing;
+ }
+ workflow.execute(this);
+ workflowExecuted = true;
+ }
+
+ // Check for and handle a request to cancel this operation.
+ if (cancelRequest != null)
+ {
+ indicateCancelled(cancelRequest);
+ setProcessingStopTime();
+ logCompareResponse(this);
+ pluginConfigManager.invokePostResponseComparePlugins(this);
+ return;
+ }
+
+ // Indicate that it is now too late to attempt to cancel the operation.
+ setCancelResult(CancelResult.TOO_LATE);
+
+ // Stop the processing timer.
+ setProcessingStopTime();
+
+ // Send the compare response to the client unless the operation result
+ // code is CANCELED
+ if (getResultCode() != ResultCode.CANCELED)
+ {
+ clientConnection.sendResponse(this);
+ }
+
+ // Log the compare response message.
+ logCompareResponse(this);
+
+ // Invoke the post-response compare plugins.
+ if (workflowExecuted)
+ {
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+ if (localOperations != null)
+ {
+ for (Object localOp : localOperations)
+ {
+ LocalBackendCompareOperation localOperation =
+ (LocalBackendCompareOperation)localOp;
+ pluginConfigManager.invokePostResponseComparePlugins(localOperation);
+ }
+ }
+ }
+ else
+ {
+ pluginConfigManager.invokePostResponseComparePlugins(this);
+ }
+ }
+
+
+ /**
+ * Updates the error message and the result code of the operation.
+ *
+ * This method is called because no workflow was found to process
+ * the operation.
+ */
+ private void updateOperationErrMsgAndResCode()
+ {
+ setResultCode(ResultCode.NO_SUCH_OBJECT);
+ appendErrorMessage(
+ getMessage(MSGID_COMPARE_NO_SUCH_ENTRY, String.valueOf(getEntryDN())));
+ }
+
+
+ /**
+ * {@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("CompareOperation(connID=");
+ buffer.append(clientConnection.getConnectionID());
+ buffer.append(", opID=");
+ buffer.append(operationID);
+ buffer.append(", dn=");
+ buffer.append(rawEntryDN);
+ buffer.append(", attr=");
+ buffer.append(rawAttributeType);
+ buffer.append(")");
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * This method always returns null.
+ */
+ public Entry getEntryToCompare()
+ {
+ return null;
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/core/CompareOperationWrapper.java b/opends/src/server/org/opends/server/core/CompareOperationWrapper.java
new file mode 100644
index 0000000..c19ba40
--- /dev/null
+++ b/opends/src/server/org/opends/server/core/CompareOperationWrapper.java
@@ -0,0 +1,158 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.DN;
+
+
+/**
+ * This abstract class wraps/decorates a given compare operation.
+ * This class will be extended by sub-classes to enhance the
+ * functionnality of the CompareOperationBasis.
+ */
+public abstract class CompareOperationWrapper
+ extends OperationWrapper
+ implements CompareOperation
+{
+ // The wrapped operation
+ private CompareOperation compare;
+
+
+ /**
+ * Creates a new compare operation based on the provided compare operation.
+ *
+ * @param compare The compare operation to wrap
+ */
+ public CompareOperationWrapper(CompareOperation compare)
+ {
+ super(compare);
+ this.compare = compare;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString getRawEntryDN()
+ {
+ return compare.getRawEntryDN();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawEntryDN(ByteString rawEntryDN)
+ {
+ compare.setRawEntryDN(rawEntryDN);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getEntryDN()
+ {
+ return compare.getEntryDN();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getRawAttributeType()
+ {
+ return compare.getRawAttributeType();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawAttributeType(String rawAttributeType)
+ {
+ compare.setRawAttributeType(rawAttributeType);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public AttributeType getAttributeType()
+ {
+ return compare.getAttributeType();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttributeType(AttributeType attributeType)
+ {
+ compare.setAttributeType(attributeType);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString getAssertionValue()
+ {
+ return compare.getAssertionValue();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAssertionValue(ByteString assertionValue)
+ {
+ compare.setAssertionValue(assertionValue);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return compare.getProxiedAuthorizationDN();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+ {
+ compare.setProxiedAuthorizationDN(proxiedAuthorizationDN);
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java b/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
index 2a4a8ed..50e2393 100644
--- a/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
+++ b/opends/src/server/org/opends/server/core/DefaultAccessControlHandler.java
@@ -116,7 +116,7 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(CompareOperation compareOperation)
+ public boolean isAllowed(LocalBackendCompareOperation compareOperation)
{
return true;
}
diff --git a/opends/src/server/org/opends/server/core/OperationWrapper.java b/opends/src/server/org/opends/server/core/OperationWrapper.java
new file mode 100644
index 0000000..af9b4bf
--- /dev/null
+++ b/opends/src/server/org/opends/server/core/OperationWrapper.java
@@ -0,0 +1,511 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.ResultCode;
+
+
+/**
+ * This abstract class is a generic operation wrapper intended to be
+ * subclassed by a specific operation wrapper.
+ */
+public class OperationWrapper implements Operation
+{
+ // The wrapped operation.
+ private Operation operation;
+
+
+ /**
+ * Creates a new generic operation wrapper.
+ *
+ * @param operation the generic operation to wrap
+ */
+ public OperationWrapper(Operation operation)
+ {
+ this.operation = operation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addRequestControl(Control control)
+ {
+ operation.addRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addResponseControl(Control control)
+ {
+ operation.addResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendAdditionalLogMessage(String message)
+ {
+ operation.appendAdditionalLogMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendErrorMessage(String message)
+ {
+ operation.appendErrorMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult cancel(CancelRequest cancelRequest)
+ {
+ return operation.cancel(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void disconnectClient(
+ DisconnectReason disconnectReason,
+ boolean sendNotification,
+ String message,
+ int messageID)
+ {
+ operation.disconnectClient(
+ disconnectReason, sendNotification, message, messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean dontSynchronize()
+ {
+ return operation.dontSynchronize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getAdditionalLogMessage()
+ {
+ return operation.getAdditionalLogMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getAttachment(String name)
+ {
+ return operation.getAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<String, Object> getAttachments()
+ {
+ return operation.getAttachments();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getAuthorizationDN()
+ {
+ return operation.getAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry getAuthorizationEntry()
+ {
+ return operation.getAuthorizationEntry();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelRequest getCancelRequest()
+ {
+ return operation.getCancelRequest();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult getCancelResult()
+ {
+ return operation.getCancelResult();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClientConnection getClientConnection()
+ {
+ return operation.getClientConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getCommonLogElements()
+ {
+ return operation.getCommonLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getConnectionID()
+ {
+ return operation.getConnectionID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getErrorMessage()
+ {
+ return operation.getErrorMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getMatchedDN()
+ {
+ return operation.getMatchedDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMessageID()
+ {
+ return operation.getMessageID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getOperationID()
+ {
+ return operation.getOperationID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public OperationType getOperationType()
+ {
+ return operation.getOperationType();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStartTime()
+ {
+ return operation.getProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStopTime()
+ {
+ return operation.getProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingTime()
+ {
+ return operation.getProcessingTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<String> getReferralURLs()
+ {
+ return operation.getReferralURLs();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getRequestControls()
+ {
+ return operation.getRequestControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getRequestLogElements()
+ {
+ return operation.getRequestLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getResponseControls()
+ {
+ return operation.getResponseControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getResponseLogElements()
+ {
+ return operation.getResponseLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultCode getResultCode()
+ {
+ return operation.getResultCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void indicateCancelled(CancelRequest cancelRequest)
+ {
+ operation.indicateCancelled(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isInternalOperation()
+ {
+ return operation.isInternalOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSynchronizationOperation()
+ {
+ return operation.isSynchronizationOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void operationCompleted()
+ {
+ operation.operationCompleted();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object removeAttachment(String name)
+ {
+ return operation.removeAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeRequestControl(Control control)
+ {
+ operation.removeRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeResponseControl(Control control)
+ {
+ operation.removeResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAdditionalLogMessage(StringBuilder additionalLogMessage)
+ {
+ operation.setAdditionalLogMessage(additionalLogMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object setAttachment(String name, Object value)
+ {
+ return operation.setAttachment(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttachments(Map<String, Object> attachments)
+ {
+ operation.setAttachments(attachments);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAuthorizationEntry(Entry authorizationEntry)
+ {
+ operation.setAuthorizationEntry(authorizationEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ return operation.setCancelRequest(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCancelResult(CancelResult cancelResult)
+ {
+ operation.setCancelResult(cancelResult);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDontSynchronize(boolean dontSynchronize)
+ {
+ operation.setDontSynchronize(dontSynchronize);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setErrorMessage(StringBuilder errorMessage)
+ {
+ operation.setErrorMessage(errorMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInternalOperation(boolean isInternalOperation)
+ {
+ operation.setInternalOperation(isInternalOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMatchedDN(DN matchedDN)
+ {
+ operation.setMatchedDN(matchedDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStartTime()
+ {
+ operation.setProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStopTime()
+ {
+ operation.setProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setReferralURLs(List<String> referralURLs)
+ {
+ operation.setReferralURLs(referralURLs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResponseData(DirectoryException directoryException)
+ {
+ operation.setResponseData(directoryException);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResultCode(ResultCode resultCode)
+ {
+ operation.setResultCode(resultCode);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSynchronizationOperation(boolean isSynchronizationOperation)
+ {
+ operation.setSynchronizationOperation(isSynchronizationOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void toString(StringBuilder buffer)
+ {
+ operation.toString(buffer);
+ }
+
+}
+
diff --git a/opends/src/server/org/opends/server/core/PluginConfigManager.java b/opends/src/server/org/opends/server/core/PluginConfigManager.java
index 12b2140..cde00ad 100644
--- a/opends/src/server/org/opends/server/core/PluginConfigManager.java
+++ b/opends/src/server/org/opends/server/core/PluginConfigManager.java
@@ -82,21 +82,25 @@
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.operation.PostOperationAddOperation;
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.PostOperationModifyOperation;
import org.opends.server.types.operation.PostOperationSearchOperation;
import org.opends.server.types.operation.PostResponseAddOperation;
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.PostResponseModifyOperation;
import org.opends.server.types.operation.PostResponseSearchOperation;
import org.opends.server.types.operation.PreOperationAddOperation;
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.PreOperationModifyOperation;
import org.opends.server.types.operation.PreOperationSearchOperation;
import org.opends.server.types.operation.PreParseAddOperation;
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.PreParseModifyOperation;
import org.opends.server.types.operation.PreParseSearchOperation;
@@ -1971,7 +1975,7 @@
* @return The result of processing the pre-parse compare plugins.
*/
public PreParsePluginResult invokePreParseComparePlugins(
- CompareOperation compareOperation)
+ PreParseCompareOperation compareOperation)
{
PreParsePluginResult result = null;
@@ -2705,7 +2709,7 @@
* @return The result of processing the pre-operation compare plugins.
*/
public PreOperationPluginResult invokePreOperationComparePlugins(
- CompareOperation compareOperation)
+ PreOperationCompareOperation compareOperation)
{
PreOperationPluginResult result = null;
@@ -3439,7 +3443,7 @@
* @return The result of processing the post-operation compare plugins.
*/
public PostOperationPluginResult invokePostOperationComparePlugins(
- CompareOperation compareOperation)
+ PostOperationCompareOperation compareOperation)
{
PostOperationPluginResult result = null;
@@ -4161,7 +4165,7 @@
* @return The result of processing the post-response compare plugins.
*/
public PostResponsePluginResult invokePostResponseComparePlugins(
- CompareOperation compareOperation)
+ PostResponseCompareOperation compareOperation)
{
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 1b6e445..448f6fa 100644
--- a/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -954,8 +954,8 @@
String attributeType,
ByteString assertionValue)
{
- CompareOperation compareOperation =
- new CompareOperation(this, nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(this, nextOperationID(),
nextMessageID(),
new ArrayList<Control>(0), rawEntryDN,
attributeType, assertionValue);
@@ -985,8 +985,8 @@
AttributeType attributeType,
ByteString assertionValue)
{
- CompareOperation compareOperation =
- new CompareOperation(this, nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(this, nextOperationID(),
nextMessageID(),
new ArrayList<Control>(0), entryDN,
attributeType, assertionValue);
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 d872b3b..ce06fad 100644
--- a/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -589,8 +589,8 @@
String attributeType,
ASN1OctetString assertionValue)
{
- CompareOperation compareOperation =
- new CompareOperation(this, nextOperationID(), nextMessageID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(this, nextOperationID(), nextMessageID(),
new ArrayList<Control>(0), rawEntryDN,
attributeType, assertionValue);
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 41072fb..518f834 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -56,7 +56,7 @@
import org.opends.server.core.AbandonOperation;
import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.BindOperationBasis;
-import org.opends.server.core.CompareOperation;
+import org.opends.server.core.CompareOperationBasis;
import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ExtendedOperation;
@@ -2063,8 +2063,8 @@
}
CompareRequestProtocolOp protocolOp = message.getCompareRequestProtocolOp();
- CompareOperation compareOp =
- new CompareOperation(this, nextOperationID.getAndIncrement(),
+ CompareOperationBasis compareOp =
+ new CompareOperationBasis(this, nextOperationID.getAndIncrement(),
message.getMessageID(), controls,
protocolOp.getDN(), protocolOp.getAttributeType(),
protocolOp.getAssertionValue());
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java
new file mode 100644
index 0000000..947b3cc
--- /dev/null
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendCompareOperation.java
@@ -0,0 +1,86 @@
+/*
+ * 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 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.workflowelement.localbackend;
+
+
+import org.opends.server.core.CompareOperation;
+import org.opends.server.core.CompareOperationWrapper;
+import org.opends.server.types.Entry;
+import org.opends.server.types.operation.PostOperationCompareOperation;
+import org.opends.server.types.operation.PostResponseCompareOperation;
+import org.opends.server.types.operation.PreOperationCompareOperation;
+
+
+/**
+ * This class defines an operation that may be used to determine whether a
+ * specified entry in the Directory Server contains a given attribute-value
+ * pair.
+ */
+public class LocalBackendCompareOperation extends CompareOperationWrapper
+ implements PreOperationCompareOperation,
+ PostOperationCompareOperation,
+ PostResponseCompareOperation
+{
+ // The entry to be compared.
+ private Entry entry = null;
+
+
+ /**
+ * Creates a new compare operation based on the provided compare operation.
+ *
+ * @param compare the compare operation
+ */
+ public LocalBackendCompareOperation(CompareOperation compare)
+ {
+ super(compare);
+ LocalBackendWorkflowElement.attachLocalOperation (compare, this);
+ }
+
+
+ /**
+ * Retrieves the entry to target with the compare operation.
+ *
+ * @return The entry to target with the compare operation, or
+ * <CODE>null</CODE> if the entry is not yet available.
+ */
+ public Entry getEntryToCompare()
+ {
+ return entry;
+ }
+
+
+ /**
+ * Set the entry to target with the compare operation.
+ *
+ * @param entry The entry to target with the compare operation.
+ */
+ public void setEntryToCompare(Entry entry)
+ {
+ this.entry = entry;
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
index e7919f2..5f95e28 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -74,6 +74,7 @@
import org.opends.server.core.AccessControlConfigManager;
import org.opends.server.core.AddOperation;
import org.opends.server.core.BindOperation;
+import org.opends.server.core.CompareOperation;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
@@ -178,6 +179,9 @@
case MODIFY:
processModify((ModifyOperation) operation);
break;
+ case COMPARE:
+ processCompare((CompareOperation) operation);
+ break;
default:
// jdemendi - temporary code, just make sure that we don't fell into
// that incomplete code...
@@ -5860,9 +5864,9 @@
/**
- * Perform a delete operation against a local backend.
+ * Performs a delete operation against a local backend.
*
- * @param operation - The operation to perform
+ * @param operation the operation to perform
*/
public void processDelete(DeleteOperation operation){
LocalBackendDeleteOperation localOperation =
@@ -5871,9 +5875,9 @@
}
/**
- * Perform a local delete operation against a local backend.
+ * Performs a local delete operation against a local backend.
*
- * @param operation - The operation to perform
+ * @param operation the operation to perform
*/
private void processLocalDelete(LocalBackendDeleteOperation localOp)
{
@@ -6673,6 +6677,576 @@
/**
+ * Perform a compare operation against a local backend.
+ *
+ * @param operation - The operation to perform
+ */
+ public void processCompare(CompareOperation operation)
+ {
+ LocalBackendCompareOperation localOperation =
+ new LocalBackendCompareOperation(operation);
+ processLocalCompare(localOperation);
+ }
+
+
+ /**
+ * Perform a local compare operation against a local backend.
+ *
+ * @param operation - The operation to perform
+ */
+ private void processLocalCompare(LocalBackendCompareOperation localOp)
+ {
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+ boolean skipPostOperation = false;
+
+
+ // Get a reference to the client connection
+ ClientConnection clientConnection = localOp.getClientConnection();
+
+
+ // Check for and handle a request to cancel this operation.
+ if (localOp.getCancelRequest() != null)
+ {
+ return;
+ }
+
+
+ // Create a labeled block of code that we can break out of if a problem is
+ // detected.
+compareProcessing:
+ {
+ // Process the entry DN to convert it from the raw form to the form
+ // required for the rest of the compare processing.
+ DN entryDN = localOp.getEntryDN();
+ if (entryDN == null)
+ {
+ skipPostOperation = true;
+ break compareProcessing;
+ }
+
+
+ // If the target entry is in the server configuration, then make sure the
+ // requester has the CONFIG_READ privilege.
+ if (DirectoryServer.getConfigHandler().handlesEntry(entryDN) &&
+ (! clientConnection.hasPrivilege(Privilege.CONFIG_READ, localOp)))
+ {
+ int msgID = MSGID_COMPARE_CONFIG_INSUFFICIENT_PRIVILEGES;
+ localOp.appendErrorMessage(getMessage(msgID));
+ localOp.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+ skipPostOperation = true;
+ break compareProcessing;
+ }
+
+
+ // Check for and handle a request to cancel this operation.
+ if (localOp.getCancelRequest() != null)
+ {
+ return;
+ }
+
+
+ // Grab a read lock on the entry.
+ Lock readLock = null;
+ for (int i=0; i < 3; i++)
+ {
+ readLock = LockManager.lockRead(entryDN);
+ if (readLock != null)
+ {
+ break;
+ }
+ }
+
+ if (readLock == null)
+ {
+ int msgID = MSGID_COMPARE_CANNOT_LOCK_ENTRY;
+ String message = getMessage(msgID, String.valueOf(entryDN));
+
+ localOp.setResultCode(DirectoryServer.getServerErrorResultCode());
+ localOp.appendErrorMessage(message);
+ skipPostOperation = true;
+ break compareProcessing;
+ }
+
+ Entry entry = null;
+ try
+ {
+ // Get the entry. If it does not exist, then fail.
+ try
+ {
+ entry = DirectoryServer.getEntry(entryDN);
+ localOp.setEntryToCompare(entry);
+
+ if (entry == null)
+ {
+ localOp.setResultCode(ResultCode.NO_SUCH_OBJECT);
+ localOp.appendErrorMessage(getMessage(MSGID_COMPARE_NO_SUCH_ENTRY,
+ String.valueOf(entryDN)));
+
+ // See if one of the entry's ancestors exists.
+ DN parentDN = entryDN.getParentDNInSuffix();
+ while (parentDN != null)
+ {
+ try
+ {
+ if (DirectoryServer.entryExists(parentDN))
+ {
+ localOp.setMatchedDN(parentDN);
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ break;
+ }
+
+ parentDN = parentDN.getParentDNInSuffix();
+ }
+
+ break compareProcessing;
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ localOp.setResultCode(de.getResultCode());
+ localOp.appendErrorMessage(de.getErrorMessage());
+ break compareProcessing;
+ }
+
+ // Check to see if there are any controls in the request. If so, then
+ // see if there is any special processing required.
+ List<Control> requestControls = localOp.getRequestControls();
+ if ((requestControls != null) && (! requestControls.isEmpty()))
+ {
+ for (int i=0; i < requestControls.size(); i++)
+ {
+ Control c = requestControls.get(i);
+ String oid = c.getOID();
+
+ if (oid.equals(OID_LDAP_ASSERTION))
+ {
+ LDAPAssertionRequestControl assertControl;
+ if (c instanceof LDAPAssertionRequestControl)
+ {
+ assertControl = (LDAPAssertionRequestControl) c;
+ }
+ else
+ {
+ try
+ {
+ assertControl = LDAPAssertionRequestControl.decodeControl(c);
+ requestControls.set(i, assertControl);
+ }
+ catch (LDAPException le)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, le);
+ }
+
+ localOp.setResultCode(ResultCode.valueOf(le.getResultCode()));
+ localOp.appendErrorMessage(le.getMessage());
+
+ break compareProcessing;
+ }
+ }
+
+ try
+ {
+ // FIXME -- We need to determine whether the current user has
+ // permission to make this determination.
+ SearchFilter filter = assertControl.getSearchFilter();
+ if (! filter.matchesEntry(entry))
+ {
+ localOp.setResultCode(ResultCode.ASSERTION_FAILED);
+
+ localOp.appendErrorMessage(
+ getMessage(MSGID_COMPARE_ASSERTION_FAILED,
+ String.valueOf(entryDN)));
+
+ break compareProcessing;
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ localOp.setResultCode(ResultCode.PROTOCOL_ERROR);
+
+ int msgID = MSGID_COMPARE_CANNOT_PROCESS_ASSERTION_FILTER;
+ localOp.appendErrorMessage(
+ getMessage(msgID, String.valueOf(entryDN),
+ de.getErrorMessage()));
+
+ break compareProcessing;
+ }
+ }
+ else if (oid.equals(OID_PROXIED_AUTH_V1))
+ {
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(
+ Privilege.PROXIED_AUTH, localOp))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ localOp.appendErrorMessage(getMessage(msgID));
+ localOp.setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break compareProcessing;
+ }
+
+
+ ProxiedAuthV1Control proxyControl;
+ if (c instanceof ProxiedAuthV1Control)
+ {
+ proxyControl = (ProxiedAuthV1Control) c;
+ }
+ else
+ {
+ try
+ {
+ proxyControl = ProxiedAuthV1Control.decodeControl(c);
+ }
+ catch (LDAPException le)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, le);
+ }
+
+ localOp.setResultCode(ResultCode.valueOf(le.getResultCode()));
+ localOp.appendErrorMessage(le.getMessage());
+
+ break compareProcessing;
+ }
+ }
+
+
+ Entry authorizationEntry;
+ try
+ {
+ authorizationEntry = proxyControl.getAuthorizationEntry();
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ localOp.setResultCode(de.getResultCode());
+ localOp.appendErrorMessage(de.getErrorMessage());
+
+ break compareProcessing;
+ }
+
+ if (AccessControlConfigManager.getInstance()
+ .getAccessControlHandler().isProxiedAuthAllowed(localOp,
+ authorizationEntry) == false) {
+ localOp.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+
+ int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
+ localOp.appendErrorMessage(
+ getMessage(msgID, String.valueOf(entryDN)));
+
+ skipPostOperation = true;
+ break compareProcessing;
+ }
+ localOp.setAuthorizationEntry(authorizationEntry);
+ if (authorizationEntry == null)
+ {
+ localOp.setProxiedAuthorizationDN(DN.nullDN());
+ }
+ else
+ {
+ localOp.setProxiedAuthorizationDN(authorizationEntry.getDN());
+ }
+ }
+ else if (oid.equals(OID_PROXIED_AUTH_V2))
+ {
+ // The requester must have the PROXIED_AUTH privilige in order to
+ // be able to use this control.
+ if (! clientConnection.hasPrivilege(
+ Privilege.PROXIED_AUTH, localOp))
+ {
+ int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
+ localOp.appendErrorMessage(getMessage(msgID));
+ localOp.setResultCode(ResultCode.AUTHORIZATION_DENIED);
+ break compareProcessing;
+ }
+
+
+ ProxiedAuthV2Control proxyControl;
+ if (c instanceof ProxiedAuthV2Control)
+ {
+ proxyControl = (ProxiedAuthV2Control) c;
+ }
+ else
+ {
+ try
+ {
+ proxyControl = ProxiedAuthV2Control.decodeControl(c);
+ }
+ catch (LDAPException le)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, le);
+ }
+
+ localOp.setResultCode(ResultCode.valueOf(le.getResultCode()));
+ localOp.appendErrorMessage(le.getMessage());
+
+ break compareProcessing;
+ }
+ }
+
+
+ Entry authorizationEntry;
+ try
+ {
+ authorizationEntry = proxyControl.getAuthorizationEntry();
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ localOp.setResultCode(de.getResultCode());
+ localOp.appendErrorMessage(de.getErrorMessage());
+
+ break compareProcessing;
+ }
+
+ if (AccessControlConfigManager.getInstance()
+ .getAccessControlHandler().isProxiedAuthAllowed(localOp,
+ authorizationEntry) == false) {
+ localOp.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+
+ int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
+ localOp.appendErrorMessage(
+ getMessage(msgID, String.valueOf(entryDN)));
+
+ skipPostOperation = true;
+ break compareProcessing;
+ }
+ localOp.setAuthorizationEntry(authorizationEntry);
+ if (authorizationEntry == null)
+ {
+ localOp.setProxiedAuthorizationDN(DN.nullDN());
+ }
+ else
+ {
+ localOp.setProxiedAuthorizationDN(authorizationEntry.getDN());
+ }
+ }
+
+ // NYI -- Add support for additional controls.
+ else if (c.isCritical())
+ {
+ Backend backend = DirectoryServer.getBackend(entryDN);
+ if ((backend == null) || (! backend.supportsControl(oid)))
+ {
+ localOp.setResultCode(
+ ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
+
+ int msgID = MSGID_COMPARE_UNSUPPORTED_CRITICAL_CONTROL;
+ localOp.appendErrorMessage(
+ getMessage(msgID, String.valueOf(entryDN), oid));
+
+ break compareProcessing;
+ }
+ }
+ }
+ }
+
+
+ // Check to see if the client has permission to perform the
+ // compare.
+
+ // FIXME: for now assume that this will check all permission
+ // pertinent to the operation. This includes proxy authorization
+ // and any other controls specified.
+
+ // FIXME: earlier checks to see if the entry already exists may
+ // have already exposed sensitive information to the client.
+ if (AccessControlConfigManager.getInstance()
+ .getAccessControlHandler().isAllowed(localOp) == false) {
+ localOp.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
+
+ int msgID = MSGID_COMPARE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
+ localOp.appendErrorMessage(
+ getMessage(msgID, String.valueOf(entryDN)));
+
+ skipPostOperation = true;
+ break compareProcessing;
+ }
+
+ // Check for and handle a request to cancel this operation.
+ if (localOp.getCancelRequest() != null)
+ {
+ return;
+ }
+
+
+ // Invoke the pre-operation compare plugins.
+ PreOperationPluginResult preOpResult =
+ pluginConfigManager.invokePreOperationComparePlugins(localOp);
+ if (preOpResult.connectionTerminated())
+ {
+ // There's no point in continuing with anything. Log the request and
+ // result and return.
+ localOp.setResultCode(ResultCode.CANCELED);
+
+ int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
+ localOp.appendErrorMessage(getMessage(msgID));
+
+ return;
+ }
+ else if (preOpResult.sendResponseImmediately())
+ {
+ skipPostOperation = true;
+ break compareProcessing;
+ }
+ else if (preOpResult.skipCoreProcessing())
+ {
+ skipPostOperation = false;
+ break compareProcessing;
+ }
+
+
+ // Get the base attribute type and set of options.
+ String baseName;
+ HashSet<String> options;
+ String rawAttributeType = localOp.getRawAttributeType();
+ int semicolonPos = rawAttributeType.indexOf(';');
+ if (semicolonPos > 0)
+ {
+ baseName = toLowerCase(rawAttributeType.substring(0, semicolonPos));
+
+ options = new HashSet<String>();
+ int nextPos = rawAttributeType.indexOf(';', semicolonPos+1);
+ while (nextPos > 0)
+ {
+ options.add(rawAttributeType.substring(semicolonPos+1, nextPos));
+ semicolonPos = nextPos;
+ nextPos = rawAttributeType.indexOf(';', semicolonPos+1);
+ }
+
+ options.add(rawAttributeType.substring(semicolonPos+1));
+ }
+ else
+ {
+ baseName = toLowerCase(rawAttributeType);
+ options = null;
+ }
+
+
+ // Actually perform the compare operation.
+ List<Attribute> attrList = null;
+ if (localOp.getAttributeType() == null)
+ {
+ localOp.setAttributeType(DirectoryServer.getAttributeType(baseName));
+ }
+ if (localOp.getAttributeType() == null)
+ {
+ attrList = entry.getAttribute(baseName, options);
+ localOp.setAttributeType(
+ DirectoryServer.getDefaultAttributeType(baseName));
+ }
+ else
+ {
+ attrList = entry.getAttribute(localOp.getAttributeType(), options);
+ }
+
+ if ((attrList == null) || attrList.isEmpty())
+ {
+ localOp.setResultCode(ResultCode.NO_SUCH_ATTRIBUTE);
+ if (options == null)
+ {
+ localOp.appendErrorMessage(getMessage(MSGID_COMPARE_OP_NO_SUCH_ATTR,
+ String.valueOf(entryDN), baseName));
+ }
+ else
+ {
+ localOp.appendErrorMessage(getMessage(
+ MSGID_COMPARE_OP_NO_SUCH_ATTR_WITH_OPTIONS,
+ String.valueOf(entryDN), baseName));
+ }
+ }
+ else
+ {
+ AttributeValue value = new AttributeValue(
+ localOp.getAttributeType(),
+ localOp.getAssertionValue());
+
+ boolean matchFound = false;
+ for (Attribute a : attrList)
+ {
+ if (a.hasValue(value))
+ {
+ matchFound = true;
+ break;
+ }
+ }
+
+ if (matchFound)
+ {
+ localOp.setResultCode(ResultCode.COMPARE_TRUE);
+ }
+ else
+ {
+ localOp.setResultCode(ResultCode.COMPARE_FALSE);
+ }
+ }
+ }
+ finally
+ {
+ LockManager.unlock(entryDN, readLock);
+ }
+ }
+
+
+ // Check for and handle a request to cancel this operation.
+ if (localOp.getCancelRequest() != null)
+ {
+ return;
+ }
+
+
+ // Invoke the post-operation compare plugins.
+ if (! skipPostOperation)
+ {
+ PostOperationPluginResult postOperationResult =
+ pluginConfigManager.invokePostOperationComparePlugins(localOp);
+ if (postOperationResult.connectionTerminated())
+ {
+ localOp.setResultCode(ResultCode.CANCELED);
+
+ int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT;
+ localOp.appendErrorMessage(getMessage(msgID));
+
+ return;
+ }
+ }
+ }
+
+
+ /**
* Attaches the current local operation to the global operation so that
* operation runner can execute local operation post response later on.
*
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java
index 77b150f..d6ad1d6 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/CompareOperationTestCase.java
@@ -48,7 +48,6 @@
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
-import static org.testng.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
@@ -138,7 +137,8 @@
return new Operation[]
{
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -216,8 +216,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -240,8 +241,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -263,8 +265,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString("o=nonexistent,o=test"),
@@ -285,8 +288,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString("rogasawara,o=test"),
@@ -307,8 +311,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -330,8 +335,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -352,8 +358,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -371,8 +378,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -390,8 +398,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -409,8 +418,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString(entry.getDN().toString()),
@@ -436,8 +446,9 @@
List<Control> controls = new ArrayList<Control>();
controls.add(assertControl);
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
new ASN1OctetString(entry.getDN().toString()),
@@ -465,8 +476,9 @@
List<Control> controls = new ArrayList<Control>();
controls.add(assertControl);
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
new ASN1OctetString(entry.getDN().toString()),
@@ -490,8 +502,9 @@
List<Control> controls = new ArrayList<Control>();
controls.add(authV1Control);
- CompareOperation compareOperation =
- new CompareOperation(proxyUserConn,
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
@@ -518,8 +531,9 @@
List<Control> controls = new ArrayList<Control>();
controls.add(authV1Control);
- CompareOperation compareOperation =
- new CompareOperation(proxyUserConn,
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
@@ -544,8 +558,9 @@
List<Control> controls = new ArrayList<Control>();
controls.add(authV2Control);
- CompareOperation compareOperation =
- new CompareOperation(proxyUserConn,
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
@@ -570,8 +585,9 @@
List<Control> controls = new ArrayList<Control>();
controls.add(authV2Control);
- CompareOperation compareOperation =
- new CompareOperation(proxyUserConn,
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
@@ -597,8 +613,9 @@
List<Control> controls = new ArrayList<Control>();
controls.add(authV2Control);
- CompareOperation compareOperation =
- new CompareOperation(proxyUserConn,
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ proxyUserConn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
@@ -625,8 +642,9 @@
new LDAPAssertionRequestControl("1.1.1.1.1.1", true, ldapFilter);
List<Control> controls = new ArrayList<Control>();
controls.add(assertControl);
- CompareOperation compareOperation =
- new CompareOperation(conn, InternalClientConnection.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(
+ conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
controls,
new ASN1OctetString(entry.getDN().toString()),
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxPrivilegeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxPrivilegeTestCase.java
index fd0d383..2e259ff 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxPrivilegeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxPrivilegeTestCase.java
@@ -44,7 +44,6 @@
import java.util.UUID;
import org.opends.server.TestCaseUtils;
-import org.opends.server.admin.ClassLoaderProvider;
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskBackend;
import org.opends.server.backends.task.TaskState;
@@ -53,6 +52,7 @@
import org.opends.server.core.AddOperation;
import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.CompareOperation;
+import org.opends.server.core.CompareOperationBasis;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
@@ -1260,8 +1260,8 @@
// Test a compare operation against the PWReset Target user.
- CompareOperation compareOperation =
- new CompareOperation(conn, conn.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), controls, targetDN,
DirectoryServer.getAttributeType("cn", true),
ByteStringFactory.create("PWReset Target"));
@@ -1467,8 +1467,8 @@
// Test a compare operation against the PWReset Target user.
- CompareOperation compareOperation =
- new CompareOperation(conn, conn.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), controls, targetDN,
DirectoryServer.getAttributeType("cn", true),
ByteStringFactory.create("PWReset Target"));
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
index 87e4bf6..8eea58b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
@@ -48,6 +48,7 @@
import org.opends.server.core.AddOperation;
import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.CompareOperation;
+import org.opends.server.core.CompareOperationBasis;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
@@ -1319,8 +1320,8 @@
// Test a compare operation against the PWReset Target user.
- CompareOperation compareOperation =
- new CompareOperation(conn, conn.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), controls, targetDN,
DirectoryServer.getAttributeType("cn", true),
ByteStringFactory.create("PWReset Target"));
@@ -1524,8 +1525,8 @@
// Test a compare operation against the PWReset Target user.
- CompareOperation compareOperation =
- new CompareOperation(conn, conn.nextOperationID(),
+ CompareOperationBasis compareOperation =
+ new CompareOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), controls, targetDN,
DirectoryServer.getAttributeType("cn", true),
ByteStringFactory.create("PWReset Target"));
--
Gitblit v1.10.0