From fbda6e0892dcfcc8dd43d21f6fb134aabb8d0cac Mon Sep 17 00:00:00 2001
From: jarnou <jarnou@localhost>
Date: Tue, 03 Jul 2007 09:29:17 +0000
Subject: [PATCH] Commits the refactoring of the core server to provide support for proxy/distribution/virtual functionnalities. This includes the new set of local operations, as well as the workflow and networkgroup support.
---
opends/src/server/org/opends/server/core/AddOperation.java | 2516 +----------------------------------------------------------
1 files changed, 57 insertions(+), 2,459 deletions(-)
diff --git a/opends/src/server/org/opends/server/core/AddOperation.java b/opends/src/server/org/opends/server/core/AddOperation.java
index 8b265d1..a81b672 100644
--- a/opends/src/server/org/opends/server/core/AddOperation.java
+++ b/opends/src/server/org/opends/server/core/AddOperation.java
@@ -26,248 +26,23 @@
*/
package org.opends.server.core;
-
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.locks.Lock;
-import org.opends.server.api.AttributeSyntax;
-import org.opends.server.api.Backend;
-import org.opends.server.api.ChangeNotificationListener;
-import org.opends.server.api.ClientConnection;
-import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.api.PasswordValidator;
-import org.opends.server.api.SynchronizationProvider;
-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.LDAPPostReadRequestControl;
-import org.opends.server.controls.LDAPPostReadResponseControl;
-import org.opends.server.controls.ProxiedAuthV1Control;
-import org.opends.server.controls.ProxiedAuthV2Control;
-import org.opends.server.schema.AuthPasswordSyntax;
-import org.opends.server.schema.BooleanSyntax;
-import org.opends.server.schema.UserPasswordSyntax;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.ldap.LDAPAttribute;
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.CancelledOperationException;
-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.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.LDAPException;
-import org.opends.server.types.LockManager;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Operation;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.Privilege;
import org.opends.server.types.RawAttribute;
-import org.opends.server.types.RDN;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SynchronizationProviderResult;
-import org.opends.server.types.operation.PostOperationAddOperation;
-import org.opends.server.types.operation.PostResponseAddOperation;
-import org.opends.server.types.operation.PreOperationAddOperation;
-import org.opends.server.types.operation.PreParseAddOperation;
-import org.opends.server.util.TimeThread;
-
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.core.CoreConstants.*;
-import static org.opends.server.loggers.AccessLogger.*;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-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.*;
-
-
-
/**
- * This class defines an operation that may be used to add a new entry to the
- * Directory Server.
+ * This interface defines an operation that may be used to add a new entry to
+ * the Directory Server.
*/
-public class AddOperation
- extends Operation
- implements PreParseAddOperation, PreOperationAddOperation,
- PostOperationAddOperation, PostResponseAddOperation
+public interface AddOperation extends Operation
{
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- // The set of response controls to send to the client.
- private ArrayList<Control> responseControls;
-
- // The raw, unprocessed entry DN as provided in the request. This may or may
- // not be a valid DN.
- private ByteString rawEntryDN;
-
- // The cancel request that has been issued for this add operation.
- private CancelRequest cancelRequest;
-
- // The processed DN of the entry to add.
- private DN entryDN;
-
- // The proxied authorization target DN for this operation.
- private DN proxiedAuthorizationDN;
-
- // The entry being added to the server.
- private Entry entry;
-
- // The set of attributes (including the objectclass attribute) in a raw,
- // unprocessed form as provided in the request. One or more of these
- // attributes may be invalid.
- private List<RawAttribute> rawAttributes;
-
- // The set of operational attributes for the entry to add.
- private Map<AttributeType,List<Attribute>> operationalAttributes;
-
- // The set of user attributes for the entry to add.
- private Map<AttributeType,List<Attribute>> userAttributes;
-
- // The set of objectclasses for the entry to add.
- private Map<ObjectClass,String> objectClasses;
-
- // The change number that has been assigned to this operation.
- private long changeNumber;
-
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
-
-
- /**
- * Creates a new add 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 DN of the entry to add from the client
- * request. This may or may not be a valid DN.
- * @param rawAttributes The raw set of attributes from the client
- * request (including the objectclass attribute).
- * This may contain invalid attributes.
- */
- public AddOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- ByteString rawEntryDN, List<RawAttribute> rawAttributes)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.rawEntryDN = rawEntryDN;
- this.rawAttributes = rawAttributes;
-
- responseControls = new ArrayList<Control>();
- cancelRequest = null;
- entry = null;
- entryDN = null;
- userAttributes = null;
- operationalAttributes = null;
- objectClasses = null;
- proxiedAuthorizationDN = null;
- changeNumber = -1;
- }
-
-
-
- /**
- * Creates a new add 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 DN for the entry.
- * @param objectClasses The set of objectclasses for the entry.
- * @param userAttributes The set of user attributes for the entry.
- * @param operationalAttributes The set of operational attributes for the
- * entry.
- */
- public AddOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- DN entryDN, Map<ObjectClass,String> objectClasses,
- Map<AttributeType,List<Attribute>> userAttributes,
- Map<AttributeType,List<Attribute>> operationalAttributes)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.entryDN = entryDN;
- this.objectClasses = objectClasses;
- this.userAttributes = userAttributes;
- this.operationalAttributes = operationalAttributes;
-
- entry = null;
-
- rawEntryDN = new ASN1OctetString(entryDN.toString());
-
- rawAttributes = new ArrayList<RawAttribute>();
-
- ArrayList<ASN1OctetString> ocValues = new ArrayList<ASN1OctetString>();
- for (String s : objectClasses.values())
- {
- ocValues.add(new ASN1OctetString(s));
- }
-
- LDAPAttribute ocAttr = new LDAPAttribute(ATTR_OBJECTCLASS, ocValues);
- rawAttributes.add(ocAttr);
-
- for (List<Attribute> attrList : userAttributes.values())
- {
- for (Attribute a : attrList)
- {
- rawAttributes.add(new LDAPAttribute(a));
- }
- }
-
- for (List<Attribute> attrList : operationalAttributes.values())
- {
- for (Attribute a : attrList)
- {
- rawAttributes.add(new LDAPAttribute(a));
- }
- }
-
- responseControls = new ArrayList<Control>();
- proxiedAuthorizationDN = null;
- cancelRequest = null;
- changeNumber = -1;
- }
-
-
/**
* Retrieves the DN of the entry to add in a raw, unparsed form as it was
@@ -276,12 +51,7 @@
*
* @return The DN of the entry in a raw, unparsed form.
*/
- public final ByteString getRawEntryDN()
- {
- return rawEntryDN;
- }
-
-
+ public abstract ByteString getRawEntryDN();
/**
* Specifies the raw entry DN for the entry to add. This should only be
@@ -292,14 +62,7 @@
*
* @param rawEntryDN The raw entry DN for the entry to add.
*/
- public final void setRawEntryDN(ByteString rawEntryDN)
- {
- this.rawEntryDN = rawEntryDN;
-
- entryDN = null;
- }
-
-
+ public abstract void setRawEntryDN(ByteString rawEntryDN);
/**
* Retrieves the DN of the entry to add. This method should not be called
@@ -309,12 +72,7 @@
* @return The DN of the entry to add, or <CODE>null</CODE> if it has not yet
* been parsed from the raw DN.
*/
- public final DN getEntryDN()
- {
- return entryDN;
- }
-
-
+ public abstract DN getEntryDN();
/**
* Retrieves the set of attributes in their raw, unparsed form as read from
@@ -325,12 +83,7 @@
* @return The set of attributes in their raw, unparsed form as read from the
* client request.
*/
- public final List<RawAttribute> getRawAttributes()
- {
- return rawAttributes;
- }
-
-
+ public abstract List<RawAttribute> getRawAttributes();
/**
* Adds the provided attribute to the set of raw attributes for this add
@@ -339,16 +92,7 @@
* @param rawAttribute The attribute to add to the set of raw attributes for
* this add operation.
*/
- public final void addRawAttribute(RawAttribute rawAttribute)
- {
- rawAttributes.add(rawAttribute);
-
- objectClasses = null;
- userAttributes = null;
- operationalAttributes = null;
- }
-
-
+ public abstract void addRawAttribute(RawAttribute rawAttribute);
/**
* Replaces the set of raw attributes for this add operation. This should
@@ -356,65 +100,7 @@
*
* @param rawAttributes The set of raw attributes for this add operation.
*/
- public final void setRawAttributes(List<RawAttribute> rawAttributes)
- {
- this.rawAttributes = rawAttributes;
-
- objectClasses = null;
- userAttributes = null;
- operationalAttributes = null;
- }
-
-
-
- /**
- * Retrieves the set of processed objectclasses for the entry to add. This
- * should not be called by pre-parse plugins because this information will not
- * yet be available. The contents of the returned map may not be altered by
- * the caller.
- *
- * @return The set of processed objectclasses for the entry to add, or
- * <CODE>null</CODE> if that information is not yet available.
- */
- public final Map<ObjectClass,String> getObjectClasses()
- {
- return objectClasses;
- }
-
-
-
- /**
- * Adds the provided objectclass to the entry to add. This should only be
- * called from pre-operation plugins. Note that pre-operation plugin
- * processing is invoked after access control and schema validation, so
- * plugins should be careful to only make changes that will not violate either
- * schema or access control rules.
- *
- * @param objectClass The objectclass to add to the entry.
- * @param name The name to use for the objectclass.
- */
- public final void addObjectClass(ObjectClass objectClass, String name)
- {
- objectClasses.put(objectClass, name);
- }
-
-
-
- /**
- * Removes the provided objectclass from the entry to add. This should only
- * be called from pre-operation plugins. Note that pre-operation plugin
- * processing is invoked after access control and schema validation, so
- * plugins should be careful to only make changes that will not violate either
- * schema or access control rules.
- *
- * @param objectClass The objectclass to remove from the entry.
- */
- public final void removeObjectClass(ObjectClass objectClass)
- {
- objectClasses.remove(objectClass);
- }
-
-
+ public abstract void setRawAttributes(List<RawAttribute> rawAttributes);
/**
* Retrieves the set of processed user attributes for the entry to add. This
@@ -425,28 +111,7 @@
* @return The set of processed user attributes for the entry to add, or
* <CODE>null</CODE> if that information is not yet available.
*/
- public final Map<AttributeType,List<Attribute>> getUserAttributes()
- {
- return userAttributes;
- }
-
-
-
- /**
- * Retrieves the set of processed operational attributes for the entry to add.
- * This should not be called by pre-parse plugins because this information
- * will not yet be available. The contents of the returned map may be altered
- * by the caller.
- *
- * @return The set of processed operational attributes for the entry to add,
- * or <CODE>null</CODE> if that information is not yet available.
- */
- public final Map<AttributeType,List<Attribute>> getOperationalAttributes()
- {
- return operationalAttributes;
- }
-
-
+ public abstract Map<AttributeType, List<Attribute>> getUserAttributes();
/**
* Sets the specified attribute in the entry to add, overwriting any existing
@@ -459,34 +124,8 @@
* @param attributeType The attribute type for the attribute.
* @param attributeList The attribute list for the provided attribute type.
*/
- public final void setAttribute(AttributeType attributeType,
- List<Attribute> attributeList)
- {
- if (attributeType.isOperational())
- {
- if ((attributeList == null) || (attributeList.isEmpty()))
- {
- operationalAttributes.remove(attributeType);
- }
- else
- {
- operationalAttributes.put(attributeType, attributeList);
- }
- }
- else
- {
- if ((attributeList == null) || (attributeList.isEmpty()))
- {
- userAttributes.remove(attributeType);
- }
- else
- {
- userAttributes.put(attributeType, attributeList);
- }
- }
- }
-
-
+ public abstract void setAttribute(AttributeType attributeType,
+ List<Attribute> attributeList);
/**
* Removes the specified attribute from the entry to add. This should only be
@@ -497,67 +136,7 @@
*
* @param attributeType The attribute tyep for the attribute to remove.
*/
- public final void removeAttribute(AttributeType attributeType)
- {
- if (attributeType.isOperational())
- {
- operationalAttributes.remove(attributeType);
- }
- else
- {
- userAttributes.remove(attributeType);
- }
- }
-
-
-
- /**
- * Retrieves the entry to be added to the server. Note that this will not be
- * available to pre-parse plugins or during the conflict resolution portion of
- * the synchronization processing.
- *
- * @return The entry to be added to the server, or <CODE>null</CODE> if it is
- * not yet available.
- */
- public final Entry getEntryToAdd()
- {
- return entry;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
+ public abstract void removeAttribute(AttributeType attributeType);
/**
* Retrieves the change number that has been assigned to this operation.
@@ -566,12 +145,7 @@
* if none has been assigned yet or if there is no applicable
* synchronization mechanism in place that uses change numbers.
*/
- public final long getChangeNumber()
- {
- return changeNumber;
- }
-
-
+ public abstract long getChangeNumber();
/**
* Specifies the change number that has been assigned to this operation by the
@@ -580,131 +154,52 @@
* @param changeNumber The change number that has been assigned to this
* operation by the synchronization mechanism.
*/
- public final void setChangeNumber(long changeNumber)
- {
- this.changeNumber = changeNumber;
- }
-
-
+ public abstract void setChangeNumber(long changeNumber);
/**
- * {@inheritDoc}
+ * Retrieves the set of processed objectclasses for the entry to add. This
+ * should not be called by pre-parse plugins because this information will not
+ * yet be available. The contents of the returned map may not be altered by
+ * the caller.
+ *
+ * @return The set of processed objectclasses for the entry to add, or
+ * <CODE>null</CODE> if that information is not yet available.
*/
- @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.ADD;
- }
-
-
+ public abstract Map<ObjectClass,String> getObjectClasses();
/**
- * {@inheritDoc}
+ * Adds the provided objectclass to the entry to add. This should only be
+ * called from pre-operation plugins. Note that pre-operation plugin
+ * processing is invoked after access control and schema validation, so
+ * plugins should be careful to only make changes that will not violate either
+ * schema or access control rules.
+ *
+ * @param objectClass The objectclass to add to the entry.
+ * @param name The name to use for the objectclass.
*/
- @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);
- }
-
-
+ public abstract void addObjectClass(ObjectClass objectClass, String name);
/**
- * {@inheritDoc}
+ * Removes the provided objectclass from the entry to add. This should only
+ * be called from pre-operation plugins. Note that pre-operation plugin
+ * processing is invoked after access control and schema validation, so
+ * plugins should be careful to only make changes that will not violate either
+ * schema or access control rules.
+ *
+ * @param objectClass The objectclass to remove from the entry.
*/
- @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) }
- };
- }
-
-
+ public abstract void removeObjectClass(ObjectClass objectClass);
/**
- * {@inheritDoc}
+ * Retrieves the set of processed operational attributes for the entry to add.
+ * This should not be called by pre-parse plugins because this information
+ * will not yet be available. The contents of the returned map may be altered
+ * by the caller.
+ *
+ * @return The set of processed operational attributes for the entry to add,
+ * or <CODE>null</CODE> if that information is not yet available.
*/
- @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(processingStopTime - processingStartTime);
-
- 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 }
- };
- }
-
-
+ public abstract Map<AttributeType,List<Attribute>> getOperationalAttributes();
/**
* Retrieves the proxied authorization DN for this operation if proxied
@@ -714,1914 +209,17 @@
* authorization has been requested, or {@code null} if proxied
* authorization has not been requested.
*/
- public DN getProxiedAuthorizationDN()
- {
- return proxiedAuthorizationDN;
- }
-
-
+ public abstract DN getProxiedAuthorizationDN();
/**
- * {@inheritDoc}
- */
- @Override()
- public final ArrayList<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);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void run()
- {
- // Start the processing timer.
- processingStartTime = System.currentTimeMillis();
- setResultCode(ResultCode.UNDEFINED);
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- return;
- }
-
-
- // Get the plugin config manager that will be used for invoking plugins.
- PluginConfigManager pluginConfigManager =
- DirectoryServer.getPluginConfigManager();
- boolean skipPostOperation = false;
-
-
- // Create a labeled block of code that we can break out of if a problem is
- // detected.
-addProcessing:
- {
- // Invoke the pre-parse add plugins.
- PreParsePluginResult preParseResult =
- pluginConfigManager.invokePreParseAddPlugins(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));
-
- processingStopTime = System.currentTimeMillis();
-
- logAddRequest(this);
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
- else if (preParseResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- logAddRequest(this);
- break addProcessing;
- }
- else if (preParseResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break addProcessing;
- }
-
-
- // Log the add request message.
- logAddRequest(this);
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // Process the entry DN and set of attributes to convert them from their
- // raw forms as provided by the client to the forms required for the rest
- // of the add 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());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break addProcessing;
- }
-
-
- if ((objectClasses == null) || (userAttributes == null) ||
- (operationalAttributes == null))
- {
- objectClasses = new HashMap<ObjectClass,String>();
- userAttributes = new HashMap<AttributeType,List<Attribute>>();
- operationalAttributes = new HashMap<AttributeType,List<Attribute>>();
- for (RawAttribute a : rawAttributes)
- {
- try
- {
- Attribute attr = a.toAttribute();
- AttributeType attrType = attr.getAttributeType();
-
-
- // If the attribute type is marked "NO-USER-MODIFICATION" then fail
- // unless this is an internal operation or is related to
- // synchronization in some way.
- if (attrType.isNoUserModification())
- {
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_ATTR_IS_NO_USER_MOD,
- String.valueOf(entryDN),
- attr.getName()));
- break addProcessing;
- }
- }
-
-
- if (attrType.isObjectClassType())
- {
- for (ByteString os : a.getValues())
- {
- String ocName = os.toString();
- ObjectClass oc =
- DirectoryServer.getObjectClass(toLowerCase(ocName));
- if (oc == null)
- {
- oc = DirectoryServer.getDefaultObjectClass(ocName);
- }
-
- objectClasses.put(oc,ocName);
- }
- }
- else if (attrType.isOperational())
- {
- List<Attribute> attrs = operationalAttributes.get(attrType);
- if (attrs == null)
- {
- attrs = new ArrayList<Attribute>(1);
- attrs.add(attr);
- operationalAttributes.put(attrType, attrs);
- }
- else
- {
- attrs.add(attr);
- }
- }
- else
- {
- List<Attribute> attrs = userAttributes.get(attrType);
- if (attrs == null)
- {
- attrs = new ArrayList<Attribute>(1);
- attrs.add(attr);
- userAttributes.put(attrType, attrs);
- }
- else
- {
- // Check to see if any of the existing attributes in the list
- // have the same set of options. If so, then add the values
- // to that attribute.
- boolean attributeSeen = false;
- for (Attribute ea : attrs)
- {
- if (ea.optionsEqual(attr.getOptions()))
- {
- LinkedHashSet<AttributeValue> valueSet = ea.getValues();
- valueSet.addAll(attr.getValues());
- attributeSeen = true;
- }
- }
- if (!attributeSeen)
- {
- // This is the first occurrence of the attribute and options.
- attrs.add(attr);
- }
- }
- }
- }
- catch (LDAPException le)
- {
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break addProcessing;
- }
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // Grab a read lock on the parent entry, if there is one. We need to do
- // this to ensure that the parent is not deleted or renamed while this add
- // is in progress, and we could also need it to check the entry against
- // a DIT structure rule.
- Lock parentLock = null;
- Lock entryLock = null;
-
- DN parentDN = entryDN.getParentDNInSuffix();
- if (parentDN == null)
- {
- // Either this entry is a suffix or doesn't belong in the directory.
- if (DirectoryServer.isNamingContext(entryDN))
- {
- // This is fine. This entry is one of the configured suffixes.
- parentLock = null;
- }
- else if (entryDN.isNullDN())
- {
- // This is not fine. The root DSE cannot be added.
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_CANNOT_ADD_ROOT_DSE));
- break addProcessing;
- }
- else
- {
- // The entry doesn't have a parent but isn't a suffix. This is not
- // allowed.
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_ADD_ENTRY_NOT_SUFFIX,
- String.valueOf(entryDN)));
- break addProcessing;
- }
- }
- else
- {
- for (int i=0; i < 3; i++)
- {
- parentLock = LockManager.lockRead(parentDN);
- if (parentLock != null)
- {
- break;
- }
- }
-
- if (parentLock == null)
- {
- setResultCode(DirectoryServer.getServerErrorResultCode());
- appendErrorMessage(getMessage(MSGID_ADD_CANNOT_LOCK_PARENT,
- String.valueOf(entryDN),
- String.valueOf(parentDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
- }
-
-
- try
- {
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // Grab a write lock on the target entry. We'll need to do this
- // eventually anyway, and we want to make sure that the two locks are
- // always released when exiting this method, no matter what. Since
- // the entry shouldn't exist yet, locking earlier than necessary
- // shouldn't cause a problem.
- for (int i=0; i < 3; i++)
- {
- entryLock = LockManager.lockWrite(entryDN);
- if (entryLock != null)
- {
- break;
- }
- }
-
- if (entryLock == null)
- {
- setResultCode(DirectoryServer.getServerErrorResultCode());
- appendErrorMessage(getMessage(MSGID_ADD_CANNOT_LOCK_ENTRY,
- String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
-
-
- // Invoke any conflict resolution processing that might be needed by the
- // synchronization provider.
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.handleConflictResolution(this);
- if (! result.continueOperationProcessing())
- {
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_ADD_SYNCH_CONFLICT_RESOLUTION_FAILED,
- getConnectionID(), getOperationID(),
- getExceptionMessage(de));
-
- setResponseData(de);
- break addProcessing;
- }
- }
-
-
- // Check to see if the entry already exists. We do this before
- // checking whether the parent exists to ensure a referral entry
- // above the parent results in a correct referral.
- try
- {
- if (DirectoryServer.entryExists(entryDN))
- {
- setResultCode(ResultCode.ENTRY_ALREADY_EXISTS);
- appendErrorMessage(getMessage(MSGID_ADD_ENTRY_ALREADY_EXISTS,
- String.valueOf(entryDN)));
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
- break addProcessing;
- }
-
-
- // Get the parent entry, if it exists.
- Entry parentEntry = null;
- if (parentDN != null)
- {
- try
- {
- parentEntry = DirectoryServer.getEntry(parentDN);
-
- if (parentEntry == null)
- {
- DN matchedDN = parentDN.getParentDNInSuffix();
- while (matchedDN != null)
- {
- try
- {
- if (DirectoryServer.entryExists(matchedDN))
- {
- setMatchedDN(matchedDN);
- break;
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- break;
- }
-
- matchedDN = matchedDN.getParentDNInSuffix();
- }
-
-
- // The parent doesn't exist, so this add can't be successful.
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_ADD_NO_PARENT,
- String.valueOf(entryDN),
- String.valueOf(parentDN)));
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
- break addProcessing;
- }
- }
-
-
- // Check to make sure that all of the RDN attributes are included as
- // attribute values. If not, then either add them or report an error.
- RDN rdn = entryDN.getRDN();
- int numAVAs = rdn.getNumValues();
- for (int i=0; i < numAVAs; i++)
- {
- AttributeType t = rdn.getAttributeType(i);
- AttributeValue v = rdn.getAttributeValue(i);
- String n = rdn.getAttributeName(i);
- if (t.isOperational())
- {
- List<Attribute> attrList = operationalAttributes.get(t);
- if (attrList == null)
- {
- if (isSynchronizationOperation() ||
- DirectoryServer.addMissingRDNAttributes())
- {
- LinkedHashSet<AttributeValue> valueList =
- new LinkedHashSet<AttributeValue>(1);
- valueList.add(v);
-
- attrList = new ArrayList<Attribute>();
- attrList.add(new Attribute(t, n, valueList));
-
- operationalAttributes.put(t, attrList);
- }
- else
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- n));
-
- break addProcessing;
- }
- }
- else
- {
- boolean found = false;
- for (Attribute a : attrList)
- {
- if (a.hasOptions())
- {
- continue;
- }
- else
- {
- if (! a.hasValue(v))
- {
- a.getValues().add(v);
- }
-
- found = true;
- break;
- }
- }
-
- if (! found)
- {
- if (isSynchronizationOperation() ||
- DirectoryServer.addMissingRDNAttributes())
- {
- LinkedHashSet<AttributeValue> valueList =
- new LinkedHashSet<AttributeValue>(1);
- valueList.add(v);
- attrList.add(new Attribute(t, n, valueList));
- }
- else
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- n));
-
- break addProcessing;
- }
- }
- }
- }
- else
- {
- List<Attribute> attrList = userAttributes.get(t);
- if (attrList == null)
- {
- if (isSynchronizationOperation() ||
- DirectoryServer.addMissingRDNAttributes())
- {
- LinkedHashSet<AttributeValue> valueList =
- new LinkedHashSet<AttributeValue>(1);
- valueList.add(v);
-
- attrList = new ArrayList<Attribute>();
- attrList.add(new Attribute(t, n, valueList));
-
- userAttributes.put(t, attrList);
- }
- else
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- n));
-
- break addProcessing;
- }
- }
- else
- {
- boolean found = false;
- for (Attribute a : attrList)
- {
- if (a.hasOptions())
- {
- continue;
- }
- else
- {
- if (! a.hasValue(v))
- {
- a.getValues().add(v);
- }
-
- found = true;
- break;
- }
- }
-
- if (! found)
- {
- if (isSynchronizationOperation() ||
- DirectoryServer.addMissingRDNAttributes())
- {
- LinkedHashSet<AttributeValue> valueList =
- new LinkedHashSet<AttributeValue>(1);
- valueList.add(v);
- attrList.add(new Attribute(t, n, valueList));
- }
- else
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- n));
-
- break addProcessing;
- }
- }
- }
- }
- }
-
-
- // Check to make sure that all objectclasses have their superior classes
- // listed in the entry. If not, then add them.
- HashSet<ObjectClass> additionalClasses = null;
- for (ObjectClass oc : objectClasses.keySet())
- {
- ObjectClass superiorClass = oc.getSuperiorClass();
- if ((superiorClass != null) &&
- (! objectClasses.containsKey(superiorClass)))
- {
- if (additionalClasses == null)
- {
- additionalClasses = new HashSet<ObjectClass>();
- }
-
- additionalClasses.add(superiorClass);
- }
- }
-
- if (additionalClasses != null)
- {
- for (ObjectClass oc : additionalClasses)
- {
- addObjectClassChain(oc);
- }
- }
-
-
- // Create an entry object to encapsulate the set of attributes and
- // objectclasses.
- entry = new Entry(entryDN, objectClasses, userAttributes,
- operationalAttributes);
-
-
- // Check to see if the entry includes a privilege specification. If so,
- // then the requester must have the PRIVILEGE_CHANGE privilege.
- AttributeType privType =
- DirectoryServer.getAttributeType(OP_ATTR_PRIVILEGE_NAME, true);
- if (entry.hasAttribute(privType) &&
- (! clientConnection.hasPrivilege(Privilege.PRIVILEGE_CHANGE, this)))
- {
- int msgID = MSGID_ADD_CHANGE_PRIVILEGE_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
- break addProcessing;
- }
-
- // If it's not a synchronization operation, then check
- // to see if the entry contains one or more passwords and if they
- // are valid in accordance with the password policies associated with
- // the user. Also perform any encoding that might be required by
- // password storage schemes.
- if (! isSynchronizationOperation())
- {
- // FIXME -- We need to check to see if the password policy subentry
- // might be specified virtually rather than as a real
- // attribute.
- PasswordPolicy pwPolicy = null;
- List<Attribute> pwAttrList =
- entry.getAttribute(OP_ATTR_PWPOLICY_POLICY_DN);
- if ((pwAttrList != null) && (! pwAttrList.isEmpty()))
- {
- Attribute a = pwAttrList.get(0);
- LinkedHashSet<AttributeValue> valueSet = a.getValues();
- Iterator<AttributeValue> iterator = valueSet.iterator();
- if (iterator.hasNext())
- {
- DN policyDN;
- try
- {
- policyDN = DN.decode(iterator.next().getValue());
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- int msgID = MSGID_ADD_INVALID_PWPOLICY_DN_SYNTAX;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- de.getErrorMessage()));
-
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
- break addProcessing;
- }
-
- pwPolicy = DirectoryServer.getPasswordPolicy(policyDN);
- if (pwPolicy == null)
- {
- int msgID = MSGID_ADD_NO_SUCH_PWPOLICY;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- String.valueOf(policyDN)));
-
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- break addProcessing;
- }
- }
- }
-
- if (pwPolicy == null)
- {
- pwPolicy = DirectoryServer.getDefaultPasswordPolicy();
- }
-
- try
- {
- handlePasswordPolicy(pwPolicy, entry);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResponseData(de);
- break addProcessing;
- }
- }
-
-
- // Check to see if the entry is valid according to the server schema,
- // and also whether its attributes are valid according to their syntax.
- if (DirectoryServer.checkSchema())
- {
- StringBuilder invalidReason = new StringBuilder();
- if (! entry.conformsToSchema(parentEntry, true, true, true,
- invalidReason))
- {
- setResultCode(ResultCode.OBJECTCLASS_VIOLATION);
- setErrorMessage(invalidReason);
- break addProcessing;
- }
- else
- {
- switch (DirectoryServer.getSyntaxEnforcementPolicy())
- {
- case REJECT:
- invalidReason = new StringBuilder();
- for (List<Attribute> attrList : userAttributes.values())
- {
- for (Attribute a : attrList)
- {
- AttributeSyntax syntax = a.getAttributeType().getSyntax();
- if (syntax != null)
- {
- for (AttributeValue v : a.getValues())
- {
- if (! syntax.valueIsAcceptable(v.getValue(),
- invalidReason))
- {
- String message =
- getMessage(MSGID_ADD_OP_INVALID_SYNTAX,
- String.valueOf(entryDN),
- String.valueOf(v.getStringValue()),
- String.valueOf(a.getName()),
- String.valueOf(invalidReason));
- invalidReason = new StringBuilder(message);
-
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
- setErrorMessage(invalidReason);
- break addProcessing;
- }
- }
- }
- }
- }
-
- for (List<Attribute> attrList :
- operationalAttributes.values())
- {
- for (Attribute a : attrList)
- {
- AttributeSyntax syntax = a.getAttributeType().getSyntax();
- if (syntax != null)
- {
- for (AttributeValue v : a.getValues())
- {
- if (! syntax.valueIsAcceptable(v.getValue(),
- invalidReason))
- {
- String message =
- getMessage(MSGID_ADD_OP_INVALID_SYNTAX,
- String.valueOf(entryDN),
- String.valueOf(v.getStringValue()),
- String.valueOf(a.getName()),
- String.valueOf(invalidReason));
- invalidReason = new StringBuilder(message);
-
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
- setErrorMessage(invalidReason);
- break addProcessing;
- }
- }
- }
- }
- }
-
- break;
-
-
- case WARN:
- invalidReason = new StringBuilder();
- for (List<Attribute> attrList : userAttributes.values())
- {
- for (Attribute a : attrList)
- {
- AttributeSyntax syntax = a.getAttributeType().getSyntax();
- if (syntax != null)
- {
- for (AttributeValue v : a.getValues())
- {
- if (! syntax.valueIsAcceptable(v.getValue(),
- invalidReason))
- {
- logError(ErrorLogCategory.SCHEMA,
- ErrorLogSeverity.SEVERE_WARNING,
- MSGID_ADD_OP_INVALID_SYNTAX,
- String.valueOf(entryDN),
- String.valueOf(v.getStringValue()),
- String.valueOf(a.getName()),
- String.valueOf(invalidReason));
- }
- }
- }
- }
- }
-
- for (List<Attribute> attrList : operationalAttributes.values())
- {
- for (Attribute a : attrList)
- {
- AttributeSyntax syntax = a.getAttributeType().getSyntax();
- if (syntax != null)
- {
- for (AttributeValue v : a.getValues())
- {
- if (! syntax.valueIsAcceptable(v.getValue(),
- invalidReason))
- {
- logError(ErrorLogCategory.SCHEMA,
- ErrorLogSeverity.SEVERE_WARNING,
- MSGID_ADD_OP_INVALID_SYNTAX,
- String.valueOf(entryDN),
- String.valueOf(v.getStringValue()),
- String.valueOf(a.getName()),
- String.valueOf(invalidReason));
- }
- }
- }
- }
- }
-
- break;
- }
- }
-
-
- // See if the entry contains any attributes or object classes marked
- // OBSOLETE. If so, then reject the entry.
- for (AttributeType at : userAttributes.keySet())
- {
- if (at.isObsolete())
- {
- int msgID = MSGID_ADD_ATTR_IS_OBSOLETE;
- String message = getMessage(msgID, String.valueOf(entryDN),
- at.getNameOrOID());
- appendErrorMessage(message);
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- break addProcessing;
- }
- }
-
- for (AttributeType at : operationalAttributes.keySet())
- {
- if (at.isObsolete())
- {
- int msgID = MSGID_ADD_ATTR_IS_OBSOLETE;
- String message = getMessage(msgID, String.valueOf(entryDN),
- at.getNameOrOID());
- appendErrorMessage(message);
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- break addProcessing;
- }
- }
-
- for (ObjectClass oc : objectClasses.keySet())
- {
- if (oc.isObsolete())
- {
- int msgID = MSGID_ADD_OC_IS_OBSOLETE;
- String message = getMessage(msgID, String.valueOf(entryDN),
- oc.getNameOrOID());
- appendErrorMessage(message);
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- break addProcessing;
- }
- }
- }
-
- // Check to see if there are any controls in the request. If so,
- // then
- // see if there is any special processing required.
- boolean noOp = false;
- LDAPPostReadRequestControl postReadRequest = null;
- 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 addProcessing;
- }
- }
-
- 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_ADD_ASSERTION_FAILED,
- String.valueOf(entryDN)));
-
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(ResultCode.PROTOCOL_ERROR);
-
- int msgID = MSGID_ADD_CANNOT_PROCESS_ASSERTION_FILTER;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- de.getErrorMessage()));
-
- break addProcessing;
- }
- }
- else if (oid.equals(OID_LDAP_NOOP_OPENLDAP_ASSIGNED))
- {
- noOp = true;
- }
- else if (oid.equals(OID_LDAP_READENTRY_POSTREAD))
- {
- if (c instanceof LDAPAssertionRequestControl)
- {
- postReadRequest = (LDAPPostReadRequestControl) c;
- }
- else
- {
- try
- {
- postReadRequest = LDAPPostReadRequestControl.decodeControl(c);
- requestControls.set(i, postReadRequest);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break addProcessing;
- }
- }
- }
- 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 addProcessing;
- }
-
-
- 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 addProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break addProcessing;
- }
-
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_ADD_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
- 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 addProcessing;
- }
-
-
- 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 addProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break addProcessing;
- }
-
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_ADD_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
- 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_ADD_UNSUPPORTED_CRITICAL_CONTROL;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- oid));
-
- break addProcessing;
- }
- }
- }
- }
-
-
- // Check to see if the client has permission to perform the add.
-
- // 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 or
- // if the parent entry does not exist may have already exposed
- // sensitive information to the client.
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isAllowed(this) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_ADD_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // If the operation is not a synchronization operation,
- // Invoke the pre-operation modify plugins.
- if (!isSynchronizationOperation())
- {
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationAddPlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result
- // and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break addProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break addProcessing;
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // Actually perform the add operation. This should also include taking
- // care of any synchronization that might be needed.
- Backend backend = DirectoryServer.getBackend(entryDN);
- if (backend == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage("No backend for entry " + entryDN.toString());
- }
- else
- {
- // If it is not a private backend, then check to see if the server or
- // backend is operating in read-only mode.
- if (! backend.isPrivateBackend())
- {
- switch (DirectoryServer.getWritabilityMode())
- {
- case DISABLED:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_SERVER_READONLY,
- String.valueOf(entryDN)));
- break addProcessing;
-
- case INTERNAL_ONLY:
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_SERVER_READONLY,
- String.valueOf(entryDN)));
- break addProcessing;
- }
- }
-
- switch (backend.getWritabilityMode())
- {
- case DISABLED:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_BACKEND_READONLY,
- String.valueOf(entryDN)));
- break addProcessing;
-
- case INTERNAL_ONLY:
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_BACKEND_READONLY,
- String.valueOf(entryDN)));
- break addProcessing;
- }
- }
- }
-
-
- try
- {
- if (noOp)
- {
- appendErrorMessage(getMessage(MSGID_ADD_NOOP));
-
- // FIXME -- We must set a result code other than SUCCESS.
- }
- else
- {
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.doPreOperation(this);
- if (! result.continueOperationProcessing())
- {
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_ADD_SYNCH_PREOP_FAILED, getConnectionID(),
- getOperationID(), getExceptionMessage(de));
-
- setResponseData(de);
- break addProcessing;
- }
- }
-
- backend.addEntry(entry, this);
- }
-
- if (postReadRequest != null)
- {
- Entry addedEntry = entry.duplicate(true);
-
- if (! postReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- addedEntry.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! postReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- addedEntry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! postReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- addedEntry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // FIXME -- Check access controls on the entry to see if it should
- // be returned or if any attributes need to be stripped
- // out..
- SearchResultEntry searchEntry = new SearchResultEntry(addedEntry);
- LDAPPostReadResponseControl responseControl =
- new LDAPPostReadResponseControl(postReadRequest.getOID(),
- postReadRequest.isCritical(),
- searchEntry);
-
- responseControls.add(responseControl);
- }
-
- setResultCode(ResultCode.SUCCESS);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break addProcessing;
- }
- catch (CancelledOperationException coe)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, coe);
- }
-
- CancelResult cancelResult = coe.getCancelResult();
-
- setCancelResult(cancelResult);
- setResultCode(cancelResult.getResultCode());
-
- String message = coe.getMessage();
- if ((message != null) && (message.length() > 0))
- {
- appendErrorMessage(message);
- }
-
- break addProcessing;
- }
- }
- }
- finally
- {
- if (entryLock != null)
- {
- LockManager.unlock(entryDN, entryLock);
- }
-
- if (parentLock != null)
- {
- LockManager.unlock(parentDN, parentLock);
- }
-
-
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- provider.doPostOperation(this);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_ADD_SYNCH_POSTOP_FAILED, getConnectionID(),
- getOperationID(), getExceptionMessage(de));
-
- setResponseData(de);
- break;
- }
- }
- }
- }
-
-
- // Indicate that it is now too late to attempt to cancel the operation.
- setCancelResult(CancelResult.TOO_LATE);
-
-
- // Invoke the post-operation add plugins.
- if (! skipPostOperation)
- {
- // FIXME -- Should this also be done while holding the locks?
- PostOperationPluginResult postOpResult =
- pluginConfigManager.invokePostOperationAddPlugins(this);
- if (postOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result and
- // return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
- }
-
-
- // Notify any change notification listeners that might be registered with
- // the server.
- if ((getResultCode() == ResultCode.SUCCESS) && (entry != null))
- {
- for (ChangeNotificationListener changeListener :
- DirectoryServer.getChangeNotificationListeners())
- {
- try
- {
- changeListener.handleAddOperation(this, entry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_ADD_ERROR_NOTIFYING_CHANGE_LISTENER;
- String message = getMessage(msgID, getExceptionMessage(e));
- logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
- }
- }
- }
-
-
- // Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
-
-
- // Send the add response to the client.
- getClientConnection().sendResponse(this);
-
-
- // Log the add response.
- logAddResponse(this);
-
-
- // Notify any persistent searches that might be registered with the server.
- if ((getResultCode() == ResultCode.SUCCESS) && (entry != null))
- {
- for (PersistentSearch persistentSearch :
- DirectoryServer.getPersistentSearches())
- {
- try
- {
- persistentSearch.processAdd(this, entry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_ADD_ERROR_NOTIFYING_PERSISTENT_SEARCH;
- String message = getMessage(msgID, String.valueOf(persistentSearch),
- getExceptionMessage(e));
- logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
-
- DirectoryServer.deregisterPersistentSearch(persistentSearch);
- }
- }
- }
-
-
- // Invoke the post-response add plugins.
- pluginConfigManager.invokePostResponseAddPlugins(this);
- }
-
-
-
- /**
- * Adds the provided objectClass to the entry, along with its superior classes
- * if appropriate.
+ * Set the proxied authorization DN for this operation if proxied
+ * authorization has been requested.
*
- * @param objectClass The objectclass to add to the entry.
+ * @param proxiedAuthorizationDN
+ * The proxied authorization DN for this operation if proxied
+ * authorization has been requested, or {@code null} if proxied
+ * authorization has not been requested.
*/
- private final void addObjectClassChain(ObjectClass objectClass)
- {
- if (! objectClasses.containsKey(objectClass))
- {
- objectClasses.put(objectClass, objectClass.getNameOrOID());
- }
+ public abstract void setProxiedAuthorizationDN(DN proxiedAuthorizationDN);
- ObjectClass superiorClass = objectClass.getSuperiorClass();
- if ((superiorClass != null) &&
- (! objectClasses.containsKey(superiorClass)))
- {
- addObjectClassChain(superiorClass);
- }
- }
-
-
-
- /**
- * Performs all password policy processing necessary for the provided add
- * operation.
- *
- * @param passwordPolicy The password policy associated with the entry to be
- * added.
- * @param userEntry The user entry being added.
- *
- * @throws DirectoryException If a problem occurs while performing password
- * policy processing for the add operation.
- */
- private final void handlePasswordPolicy(PasswordPolicy passwordPolicy,
- Entry userEntry)
- throws DirectoryException
- {
- // See if a password was specified.
- AttributeType passwordAttribute = passwordPolicy.getPasswordAttribute();
- List<Attribute> attrList = userEntry.getAttribute(passwordAttribute);
- if ((attrList == null) || attrList.isEmpty())
- {
- // The entry doesn't have a password, so no action is required.
- return;
- }
- else if (attrList.size() > 1)
- {
- // This must mean there are attribute options, which we won't allow for
- // passwords.
- int msgID = MSGID_PWPOLICY_ATTRIBUTE_OPTIONS_NOT_ALLOWED;
- String message = getMessage(msgID, passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message,
- msgID);
- }
-
- Attribute passwordAttr = attrList.get(0);
- if (passwordAttr.hasOptions())
- {
- int msgID = MSGID_PWPOLICY_ATTRIBUTE_OPTIONS_NOT_ALLOWED;
- String message = getMessage(msgID, passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message,
- msgID);
- }
-
- LinkedHashSet<AttributeValue> values = passwordAttr.getValues();
- if (values.isEmpty())
- {
- // This will be treated the same as not having a password.
- return;
- }
-
- if ((! passwordPolicy.allowMultiplePasswordValues()) && (values.size() > 1))
- {
- // FIXME -- What if they're pre-encoded and might all be the same?
- int msgID = MSGID_PWPOLICY_MULTIPLE_PW_VALUES_NOT_ALLOWED;
- String message = getMessage(msgID, passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message,
- msgID);
- }
-
- CopyOnWriteArrayList<PasswordStorageScheme> defaultStorageSchemes =
- passwordPolicy.getDefaultStorageSchemes();
- LinkedHashSet<AttributeValue> newValues =
- new LinkedHashSet<AttributeValue>(defaultStorageSchemes.size());
- for (AttributeValue v : values)
- {
- ByteString value = v.getValue();
-
- // See if the password is pre-encoded.
- if (passwordPolicy.usesAuthPasswordSyntax())
- {
- if (AuthPasswordSyntax.isEncoded(value))
- {
- if (passwordPolicy.allowPreEncodedPasswords())
- {
- newValues.add(v);
- continue;
- }
- else
- {
- int msgID = MSGID_PWPOLICY_PREENCODED_NOT_ALLOWED;
- String message = getMessage(msgID,
- passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- message, msgID);
- }
- }
- }
- else
- {
- if (UserPasswordSyntax.isEncoded(value))
- {
- if (passwordPolicy.allowPreEncodedPasswords())
- {
- newValues.add(v);
- continue;
- }
- else
- {
- int msgID = MSGID_PWPOLICY_PREENCODED_NOT_ALLOWED;
- String message = getMessage(msgID,
- passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- message, msgID);
- }
- }
- }
-
-
- // See if the password passes validation. We should only do this if
- // validation should be performed for administrators.
- if (! passwordPolicy.skipValidationForAdministrators())
- {
- // There are never any current passwords for an add operation.
- HashSet<ByteString> currentPasswords = new HashSet<ByteString>(0);
- StringBuilder invalidReason = new StringBuilder();
- for (PasswordValidator<?> validator :
- passwordPolicy.getPasswordValidators().values())
- {
- if (! validator.passwordIsAcceptable(value, currentPasswords, this,
- userEntry, invalidReason))
- {
- int msgID = MSGID_PWPOLICY_VALIDATION_FAILED;
- String message = getMessage(msgID, passwordAttribute.getNameOrOID(),
- String.valueOf(invalidReason));
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- message, msgID);
- }
- }
- }
-
-
- // Encode the password.
- if (passwordPolicy.usesAuthPasswordSyntax())
- {
- for (PasswordStorageScheme s : defaultStorageSchemes)
- {
- ByteString encodedValue = s.encodeAuthPassword(value);
- newValues.add(new AttributeValue(passwordAttribute, encodedValue));
- }
- }
- else
- {
- for (PasswordStorageScheme s : defaultStorageSchemes)
- {
- ByteString encodedValue = s.encodePasswordWithScheme(value);
- newValues.add(new AttributeValue(passwordAttribute, encodedValue));
- }
- }
- }
-
-
- // Put the new encoded values in the entry.
- passwordAttr.setValues(newValues);
-
-
- // Set the password changed time attribute.
- ByteString timeString =
- new ASN1OctetString(TimeThread.getGeneralizedTime());
- AttributeType changedTimeType =
- DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_CHANGED_TIME_LC);
- if (changedTimeType == null)
- {
- changedTimeType = DirectoryServer.getDefaultAttributeType(
- OP_ATTR_PWPOLICY_CHANGED_TIME);
- }
-
- LinkedHashSet<AttributeValue> changedTimeValues =
- new LinkedHashSet<AttributeValue>(1);
- changedTimeValues.add(new AttributeValue(changedTimeType, timeString));
-
- ArrayList<Attribute> changedTimeList = new ArrayList<Attribute>(1);
- changedTimeList.add(new Attribute(changedTimeType,
- OP_ATTR_PWPOLICY_CHANGED_TIME,
- changedTimeValues));
-
- userEntry.putAttribute(changedTimeType, changedTimeList);
-
-
- // If we should force change on add, then set the appropriate flag.
- if (passwordPolicy.forceChangeOnAdd())
- {
- AttributeType resetType =
- DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_RESET_REQUIRED_LC);
- if (resetType == null)
- {
- resetType = DirectoryServer.getDefaultAttributeType(
- OP_ATTR_PWPOLICY_RESET_REQUIRED);
- }
-
- LinkedHashSet<AttributeValue> resetValues = new
- LinkedHashSet<AttributeValue>(1);
- resetValues.add(BooleanSyntax.createBooleanValue(true));
-
- ArrayList<Attribute> resetList = new ArrayList<Attribute>(1);
- resetList.add(new Attribute(resetType, OP_ATTR_PWPOLICY_RESET_REQUIRED,
- resetValues));
- userEntry.putAttribute(resetType, resetList);
- }
- }
-
-
-
- /**
- * {@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()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
- return true;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void toString(StringBuilder buffer)
- {
- buffer.append("AddOperation(connID=");
- buffer.append(clientConnection.getConnectionID());
- buffer.append(", opID=");
- buffer.append(operationID);
- buffer.append(", dn=");
- buffer.append(rawEntryDN);
- buffer.append(")");
- }
-}
-
+}
\ No newline at end of file
--
Gitblit v1.10.0