From f73b655466092169abac34833fb628fce1fcdebe Mon Sep 17 00:00:00 2001
From: jcduff <jcduff@localhost>
Date: Thu, 23 Oct 2008 14:04:24 +0000
Subject: [PATCH] The commit will bring the following features : - An updated version of the underlying database. BDB JE 3.3 is now used. - Attribute API refactoring providing a better abstraction and offering improved performances. - A new GUI called the Control-Panel to replace the Status-Panel: the specifications for this GUI are available on OpenDS Wiki and contains a link to a mockup. See <https://www.opends.org/wiki/page/ControlPanelUISpecification>. - Some changes in the replication protocol to implement "Assured Replication Mode". The specifications are on OpenDS Wiki at <https://www.opends.org/wiki/page/AssuredMode> and section 7 described some of the replication changes required to support this. Assured Replication is not finished, but the main replication protocol changes to support it are done. As explained by Gilles on an email on the Dev mailing list (http://markmail.org/message/46rgo3meq3vriy4a), with these changes the newer versions of OpenDS may not be able to replicate with OpenDS 1.0 instances. - Support for Service Tags on the platforms where the functionality is available and enabled. Specifications are published at <https://www.opends.org/wiki/page/OpenDSServiceTagEnabled>. For more information on Service Tags see <http://wikis.sun.com/display/ServiceTag/Sun+Service+Tag+FAQ>. - The Admin Connector service. In order to provide agentry of the OpenDS server at any time, a new service has been added, dedicated to the administration, configuration and monitoring of the server. An overview of the Admin Connector service and it's use is available on the OpenDS wiki <https://www.opends.org/wiki/page/ManagingAdministrationTrafficToTheServer> - Updates to the various command line tools to support the Admin Connector service. - Some internal re-architecting of the server to put the foundation of future developments such as virtual directory services. The new NetworkGroups and WorkFlow internal services which have been specified in <https://www.opends.org/wiki/page/BasicOperationRoutingThroughNetworkGroup> are now implemented. - Many bug fixes...
---
opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java | 799 ++++++++++++++++++++++++++------------------------------
1 files changed, 370 insertions(+), 429 deletions(-)
diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
index 59a1fc0..0f903f0 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
@@ -28,11 +28,16 @@
-import java.util.ArrayList;
+import static org.opends.messages.CoreMessages.*;
+import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
+
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Lock;
@@ -66,24 +71,26 @@
import org.opends.server.schema.AuthPasswordSyntax;
import org.opends.server.schema.BooleanSyntax;
import org.opends.server.schema.UserPasswordSyntax;
+import org.opends.server.types.AcceptRejectWarn;
import org.opends.server.types.AccountStatusNotification;
import org.opends.server.types.AccountStatusNotificationType;
-import org.opends.server.types.AcceptRejectWarn;
import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeBuilder;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.ByteString;
import org.opends.server.types.CanceledOperationException;
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.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.LDAPException;
import org.opends.server.types.LockManager;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
+import org.opends.server.types.ObjectClass;
import org.opends.server.types.Privilege;
import org.opends.server.types.RDN;
import org.opends.server.types.ResultCode;
@@ -92,16 +99,10 @@
import org.opends.server.types.SynchronizationProviderResult;
import org.opends.server.types.operation.PostOperationModifyOperation;
import org.opends.server.types.operation.PostResponseModifyOperation;
-import org.opends.server.types.operation.PreOperationModifyOperation;
import org.opends.server.types.operation.PostSynchronizationModifyOperation;
+import org.opends.server.types.operation.PreOperationModifyOperation;
import org.opends.server.util.TimeThread;
-
-import static org.opends.messages.CoreMessages.*;
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
+import org.opends.server.util.Validator;
@@ -463,38 +464,9 @@
if (! noOp)
{
- // 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.continueProcessing())
- {
- setResultCode(result.getResultCode());
- appendErrorMessage(result.getErrorMessage());
- setMatchedDN(result.getMatchedDN());
- setReferralURLs(result.getReferralURLs());
+ if(!handleConflictResolution()) {
break modifyProcessing;
- }
}
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ERR_MODIFY_SYNCH_CONFLICT_RESOLUTION_FAILED.get(
- getConnectionID(), getOperationID(),
- getExceptionMessage(de)));
- setResponseData(de);
- break modifyProcessing;
- }
- }
}
@@ -641,37 +613,11 @@
}
else
{
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.doPreOperation(this);
- if (! result.continueProcessing())
- {
- setResultCode(result.getResultCode());
- appendErrorMessage(result.getErrorMessage());
- setMatchedDN(result.getMatchedDN());
- setReferralURLs(result.getReferralURLs());
+ if(!processPreOperation()) {
break modifyProcessing;
- }
}
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
- logError(ERR_MODIFY_SYNCH_PREOP_FAILED.get(getConnectionID(),
- getOperationID(), getExceptionMessage(de)));
- setResponseData(de);
- break modifyProcessing;
- }
- }
-
- backend.replaceEntry(modifiedEntry, this);
+ backend.replaceEntry(currentEntry, modifiedEntry, this);
@@ -707,27 +653,7 @@
}
finally
{
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- provider.doPostOperation(this);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ERR_MODIFY_SYNCH_POSTOP_FAILED.get(getConnectionID(),
- getOperationID(), getExceptionMessage(de)));
- setResponseData(de);
- break;
- }
- }
-
+ processPostOperation();
LockManager.unlock(entryDN, entryLock);
}
}
@@ -1060,7 +986,7 @@
// is related to synchronization in some way.
if (t.isObsolete())
{
- if (a.hasValue() &&
+ if (!a.isEmpty() &&
(m.getModificationType() != ModificationType.DELETE))
{
if (! (isInternalOperation() || isSynchronizationOperation() ||
@@ -1100,7 +1026,7 @@
if (t.equals(disabledAttr))
{
enabledStateChanged = true;
- for (AttributeValue v : a.getValues())
+ for (AttributeValue v : a)
{
try
{
@@ -1259,27 +1185,26 @@
// password values (increment doesn't make any sense for passwords).
// Then perform the appropriate type of processing for that kind of
// modification.
- boolean isAdd = (m.getModificationType() == ModificationType.ADD);
- LinkedHashSet<AttributeValue> pwValues = a.getValues();
- LinkedHashSet<AttributeValue> encodedValues =
- new LinkedHashSet<AttributeValue>();
switch (m.getModificationType())
{
case ADD:
case REPLACE:
- processInitialAddOrReplacePW(isAdd, pwValues, encodedValues, a);
+ processInitialAddOrReplacePW(m);
break;
case DELETE:
- processInitialDeletePW(pwValues, encodedValues, a);
+ processInitialDeletePW(m);
break;
default:
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- ERR_MODIFY_INVALID_MOD_TYPE_FOR_PASSWORD.get(
- String.valueOf(m.getModificationType()),
- a.getName()));
+ ERR_MODIFY_INVALID_MOD_TYPE_FOR_PASSWORD.get(String.valueOf(m
+ .getModificationType()), a.getName()));
}
+
+ // Password processing may have changed the attribute in
+ // this modification.
+ a = m.getAttribute();
}
switch (m.getModificationType())
@@ -1309,24 +1234,19 @@
/**
* Performs the initial password policy add or replace processing.
*
- * @param isAdd Indicates whether it is an add or replace update.
- * @param pwValues The set of password values as included in the
- * request.
- * @param encodedValues The set of encoded password values.
- * @param pwAttr The attribute involved in the password change.
- *
- * @throws DirectoryException If a problem occurs that should cause the
- * modify operation to fail.
+ * @param m
+ * The modification involved in the password change.
+ * @throws DirectoryException
+ * If a problem occurs that should cause the modify
+ * operation to fail.
*/
- private void processInitialAddOrReplacePW(boolean isAdd,
- LinkedHashSet<AttributeValue> pwValues,
- LinkedHashSet<AttributeValue> encodedValues,
- Attribute pwAttr)
- throws DirectoryException
+ private void processInitialAddOrReplacePW(Modification m)
+ throws DirectoryException
{
- int passwordsToAdd = pwValues.size();
+ Attribute pwAttr = m.getAttribute();
+ int passwordsToAdd = pwAttr.size();
- if (isAdd)
+ if (m.getModificationType() == ModificationType.ADD)
{
numPasswords += passwordsToAdd;
}
@@ -1335,48 +1255,48 @@
numPasswords = passwordsToAdd;
}
-
- // If there were multiple password values, then make sure that's OK.
- if ((! isInternalOperation()) &&
- (! pwPolicyState.getPolicy().allowMultiplePasswordValues()) &&
- (passwordsToAdd > 1))
+ // If there were multiple password values, then make sure that's
+ // OK.
+ if ((!isInternalOperation())
+ && (!pwPolicyState.getPolicy().allowMultiplePasswordValues())
+ && (passwordsToAdd > 1))
{
pwpErrorType = PasswordPolicyErrorType.PASSWORD_MOD_NOT_ALLOWED;
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- ERR_MODIFY_MULTIPLE_VALUES_NOT_ALLOWED.get());
+ ERR_MODIFY_MULTIPLE_VALUES_NOT_ALLOWED.get());
}
-
// Iterate through the password values and see if any of them are
- // pre-encoded. If so, then check to see if we'll allow it. Otherwise,
- // store the clear-text values for later validation and update the attribute
- // with the encoded values.
- for (AttributeValue v : pwValues)
+ // pre-encoded. If so, then check to see if we'll allow it.
+ // Otherwise, store the clear-text values for later validation and
+ // update the attribute with the encoded values.
+ AttributeBuilder builder = new AttributeBuilder(pwAttr, true);
+ for (AttributeValue v : pwAttr)
{
if (pwPolicyState.passwordIsPreEncoded(v.getValue()))
{
- if ((! isInternalOperation()) &&
- ! pwPolicyState.getPolicy().allowPreEncodedPasswords())
+ if ((!isInternalOperation())
+ && !pwPolicyState.getPolicy().allowPreEncodedPasswords())
{
pwpErrorType = PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY;
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- ERR_MODIFY_NO_PREENCODED_PASSWORDS.get());
+ ERR_MODIFY_NO_PREENCODED_PASSWORDS.get());
}
else
{
- encodedValues.add(v);
+ builder.add(v);
}
}
else
{
- if (isAdd)
+ if (m.getModificationType() == ModificationType.ADD)
{
// Make sure that the password value doesn't already exist.
if (pwPolicyState.passwordMatches(v.getValue()))
{
pwpErrorType = PasswordPolicyErrorType.PASSWORD_IN_HISTORY;
throw new DirectoryException(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS,
- ERR_MODIFY_PASSWORD_EXISTS.get());
+ ERR_MODIFY_PASSWORD_EXISTS.get());
}
}
@@ -1389,12 +1309,12 @@
for (ByteString s : pwPolicyState.encodePassword(v.getValue()))
{
- encodedValues.add(new AttributeValue(pwAttr.getAttributeType(), s));
+ builder.add(new AttributeValue(pwAttr.getAttributeType(), s));
}
}
}
- pwAttr.setValues(encodedValues);
+ m.setAttribute(builder.toAttribute());
}
@@ -1402,69 +1322,65 @@
/**
* Performs the initial password policy delete processing.
*
- * @param pwValues The set of password values as included in the
- * request.
- * @param encodedValues The set of encoded password values.
- * @param pwAttr The attribute involved in the password change.
- *
- * @throws DirectoryException If a problem occurs that should cause the
- * modify operation to fail.
+ * @param m
+ * The modification involved in the password change.
+ * @throws DirectoryException
+ * If a problem occurs that should cause the modify
+ * operation to fail.
*/
- private void processInitialDeletePW(LinkedHashSet<AttributeValue> pwValues,
- LinkedHashSet<AttributeValue> encodedValues,
- Attribute pwAttr)
- throws DirectoryException
+ private void processInitialDeletePW(Modification m) throws DirectoryException
{
// Iterate through the password values and see if any of them are
- // pre-encoded. We will never allow pre-encoded passwords for user password
- // changes, but we will allow them for administrators. For each clear-text
- // value, verify that at least one value in the entry matches and replace
- // the clear-text value with the appropriate encoded forms.
- for (AttributeValue v : pwValues)
+ // pre-encoded. We will never allow pre-encoded passwords for user
+ // password changes, but we will allow them for administrators.
+ // For each clear-text value, verify that at least one value in the
+ // entry matches and replace the clear-text value with the appropriate
+ // encoded forms.
+ Attribute pwAttr = m.getAttribute();
+ AttributeBuilder builder = new AttributeBuilder(pwAttr, true);
+ for (AttributeValue v : pwAttr)
{
if (pwPolicyState.passwordIsPreEncoded(v.getValue()))
{
- if ((! isInternalOperation()) && selfChange)
+ if ((!isInternalOperation()) && selfChange)
{
pwpErrorType = PasswordPolicyErrorType.INSUFFICIENT_PASSWORD_QUALITY;
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- ERR_MODIFY_NO_PREENCODED_PASSWORDS.get());
+ ERR_MODIFY_NO_PREENCODED_PASSWORDS.get());
}
else
{
- encodedValues.add(v);
+ builder.add(v);
}
}
else
{
- List<Attribute> attrList =
- currentEntry.getAttribute(pwAttr.getAttributeType());
+ List<Attribute> attrList = currentEntry.getAttribute(pwAttr
+ .getAttributeType());
if ((attrList == null) || (attrList.isEmpty()))
{
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- ERR_MODIFY_NO_EXISTING_VALUES.get());
+ ERR_MODIFY_NO_EXISTING_VALUES.get());
}
boolean found = false;
for (Attribute attr : attrList)
{
- for (AttributeValue av : attr.getValues())
+ for (AttributeValue av : attr)
{
if (pwPolicyState.getPolicy().usesAuthPasswordSyntax())
{
if (AuthPasswordSyntax.isEncoded(av.getValue()))
{
- StringBuilder[] compoenents =
- AuthPasswordSyntax.decodeAuthPassword(av.getStringValue());
- PasswordStorageScheme scheme =
- DirectoryServer.getAuthPasswordStorageScheme(
- compoenents[0].toString());
+ StringBuilder[] components = AuthPasswordSyntax
+ .decodeAuthPassword(av.getStringValue());
+ PasswordStorageScheme<?> scheme = DirectoryServer
+ .getAuthPasswordStorageScheme(components[0].toString());
if (scheme != null)
{
- if (scheme.authPasswordMatches(v.getValue(),
- compoenents[1].toString(),
- compoenents[2].toString()))
+ if (scheme.authPasswordMatches(v.getValue(), components[1]
+ .toString(), components[2].toString()))
{
- encodedValues.add(av);
+ builder.add(av);
found = true;
}
}
@@ -1473,7 +1389,7 @@
{
if (av.equals(v))
{
- encodedValues.add(v);
+ builder.add(v);
found = true;
}
}
@@ -1482,17 +1398,16 @@
{
if (UserPasswordSyntax.isEncoded(av.getValue()))
{
- String[] compoenents = UserPasswordSyntax.decodeUserPassword(
- av.getStringValue());
- PasswordStorageScheme scheme =
- DirectoryServer.getPasswordStorageScheme(
- toLowerCase(compoenents[0]));
+ String[] components = UserPasswordSyntax.decodeUserPassword(av
+ .getStringValue());
+ PasswordStorageScheme<?> scheme = DirectoryServer
+ .getPasswordStorageScheme(toLowerCase(components[0]));
if (scheme != null)
{
- if (scheme.passwordMatches(v.getValue(),
- new ASN1OctetString(compoenents[1])))
+ if (scheme.passwordMatches(v.getValue(), new ASN1OctetString(
+ components[1])))
{
- encodedValues.add(av);
+ builder.add(av);
found = true;
}
}
@@ -1501,7 +1416,7 @@
{
if (av.equals(v))
{
- encodedValues.add(v);
+ builder.add(v);
found = true;
}
}
@@ -1521,105 +1436,156 @@
else
{
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- ERR_MODIFY_INVALID_PASSWORD.get());
+ ERR_MODIFY_INVALID_PASSWORD.get());
}
currentPasswordProvided = true;
}
}
- pwAttr.setValues(encodedValues);
+ m.setAttribute(builder.toAttribute());
}
/**
- * Performs the initial schema processing for an add modification and updates
- * the entry appropriately.
+ * Performs the initial schema processing for an add modification
+ * and updates the entry appropriately.
*
- * @param attr The attribute being added.
- *
- * @throws DirectoryException If a problem occurs that should cause the
- * modify operation to fail.
+ * @param attr
+ * The attribute being added.
+ * @throws DirectoryException
+ * If a problem occurs that should cause the modify
+ * operation to fail.
*/
private void processInitialAddSchema(Attribute attr)
- throws DirectoryException
+ throws DirectoryException
{
- // Make sure that one or more values have been provided for the attribute.
- LinkedHashSet<AttributeValue> newValues = attr.getValues();
- if ((newValues == null) || newValues.isEmpty())
+ // Make sure that one or more values have been provided for the
+ // attribute.
+ if (attr.isEmpty())
{
throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
- ERR_MODIFY_ADD_NO_VALUES.get(String.valueOf(entryDN),
- attr.getName()));
+ ERR_MODIFY_ADD_NO_VALUES.get(String.valueOf(entryDN),
+ attr.getName()));
}
- // If the server is configured to check schema and the operation is not a
- // synchronization operation, make sure that all the new values are valid
- // according to the associated syntax.
- if ((DirectoryServer.checkSchema()) && (! isSynchronizationOperation()))
+ // If the server is configured to check schema and the operation
+ // is not a synchronization operation, make sure that all the new
+ // values are valid according to the associated syntax.
+ if ((DirectoryServer.checkSchema()) && (!isSynchronizationOperation()))
{
- AcceptRejectWarn syntaxPolicy =
- DirectoryServer.getSyntaxEnforcementPolicy();
- AttributeSyntax syntax = attr.getAttributeType().getSyntax();
+ AcceptRejectWarn syntaxPolicy = DirectoryServer
+ .getSyntaxEnforcementPolicy();
+ AttributeSyntax<?> syntax = attr.getAttributeType().getSyntax();
if (syntaxPolicy == AcceptRejectWarn.REJECT)
{
MessageBuilder invalidReason = new MessageBuilder();
- for (AttributeValue v : newValues)
+ for (AttributeValue v : attr)
{
- if (! syntax.valueIsAcceptable(v.getValue(), invalidReason))
+ if (!syntax.valueIsAcceptable(v.getValue(), invalidReason))
{
throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- ERR_MODIFY_ADD_INVALID_SYNTAX.get(
- String.valueOf(entryDN), attr.getName(),
- v.getStringValue(), invalidReason));
+ ERR_MODIFY_ADD_INVALID_SYNTAX.get(String.valueOf(entryDN), attr
+ .getName(), v.getStringValue(), invalidReason));
}
}
}
else if (syntaxPolicy == AcceptRejectWarn.WARN)
{
MessageBuilder invalidReason = new MessageBuilder();
- for (AttributeValue v : newValues)
+ for (AttributeValue v : attr)
{
- if (! syntax.valueIsAcceptable(v.getValue(), invalidReason))
+ if (!syntax.valueIsAcceptable(v.getValue(), invalidReason))
{
setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
logError(ERR_MODIFY_ADD_INVALID_SYNTAX.get(String.valueOf(entryDN),
- attr.getName(), v.getStringValue(), invalidReason));
+ attr.getName(), v.getStringValue(), invalidReason));
invalidReason = new MessageBuilder();
}
}
}
}
-
- // Add the provided attribute or merge an existing attribute with
- // the values of the new attribute. If there are any duplicates,
- // then fail.
+ // If the attribute to be added is the object class attribute then
+ // make sure that all the object classes are known and not
+ // obsoleted.
if (attr.getAttributeType().isObjectClassType())
{
- modifiedEntry.addObjectClasses(newValues);
+ validateObjectClasses(attr);
}
- else
+
+ // Add the provided attribute or merge an existing attribute with
+ // the values of the new attribute. If there are any duplicates,
+ // then fail.
+ LinkedList<AttributeValue> duplicateValues =
+ new LinkedList<AttributeValue>();
+ modifiedEntry.addAttribute(attr, duplicateValues);
+ if (!duplicateValues.isEmpty())
{
- LinkedList<AttributeValue> duplicateValues =
- new LinkedList<AttributeValue>();
- modifiedEntry.addAttribute(attr, duplicateValues);
- if (! duplicateValues.isEmpty())
+ StringBuilder buffer = new StringBuilder();
+ Iterator<AttributeValue> iterator = duplicateValues.iterator();
+ buffer.append(iterator.next().getStringValue());
+ while (iterator.hasNext())
{
- StringBuilder buffer = new StringBuilder();
- Iterator<AttributeValue> iterator = duplicateValues.iterator();
+ buffer.append(", ");
buffer.append(iterator.next().getStringValue());
- while (iterator.hasNext())
+ }
+
+ throw new DirectoryException(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS,
+ ERR_MODIFY_ADD_DUPLICATE_VALUE.get(String.valueOf(entryDN), attr
+ .getName(), buffer));
+ }
+ }
+
+
+
+ /**
+ * Ensures that the provided object class attribute contains known
+ * non-obsolete object classes.
+ *
+ * @param attr
+ * The object class attribute to validate.
+ * @throws DirectoryException
+ * If the attribute contained unknown or obsolete object
+ * classes.
+ */
+ private void validateObjectClasses(Attribute attr) throws DirectoryException
+ {
+ Validator.ensureTrue(attr.getAttributeType().isObjectClassType());
+ for (AttributeValue v : attr)
+ {
+ String name = v.getStringValue();
+
+ String lowerName;
+ try
+ {
+ lowerName = v.getNormalizedStringValue();
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
{
- buffer.append(", ");
- buffer.append(iterator.next().getStringValue());
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
- throw new DirectoryException(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS,
- ERR_MODIFY_ADD_DUPLICATE_VALUE.get(
- String.valueOf(entryDN), attr.getName(), buffer));
+ lowerName = toLowerCase(v.getStringValue());
+ }
+
+ ObjectClass oc = DirectoryServer.getObjectClass(lowerName);
+ if (oc == null)
+ {
+ Message message = ERR_ENTRY_ADD_UNKNOWN_OC.get(name, String
+ .valueOf(entryDN));
+ throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message);
+ }
+
+ if (oc.isObsolete())
+ {
+ Message message = ERR_ENTRY_ADD_OBSOLETE_OC.get(name, String
+ .valueOf(entryDN));
+ throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message);
}
}
}
@@ -1627,13 +1593,14 @@
/**
- * Performs the initial schema processing for a delete modification and
- * updates the entry appropriately.
+ * Performs the initial schema processing for a delete modification
+ * and updates the entry appropriately.
*
- * @param attr The attribute being deleted.
- *
- * @throws DirectoryException If a problem occurs that should cause the
- * modify operation to fail.
+ * @param attr
+ * The attribute being deleted.
+ * @throws DirectoryException
+ * If a problem occurs that should cause the modify
+ * operation to fail.
*/
private void processInitialDeleteSchema(Attribute attr)
throws DirectoryException
@@ -1688,209 +1655,124 @@
/**
- * Performs the initial schema processing for a replace modification and
- * updates the entry appropriately.
+ * Performs the initial schema processing for a replace modification
+ * and updates the entry appropriately.
*
- * @param attr The attribute being replaced.
- *
- * @throws DirectoryException If a problem occurs that should cause the
- * modify operation to fail.
+ * @param attr
+ * The attribute being replaced.
+ * @throws DirectoryException
+ * If a problem occurs that should cause the modify
+ * operation to fail.
*/
private void processInitialReplaceSchema(Attribute attr)
- throws DirectoryException
+ throws DirectoryException
{
- // If it is the objectclass attribute, then treat that separately.
- if (attr.getAttributeType().isObjectClassType())
+ // If the server is configured to check schema and the operation
+ // is not a synchronization operation, make sure that all the
+ // new values are valid according to the associated syntax.
+ if ((DirectoryServer.checkSchema()) && (!isSynchronizationOperation()))
{
- modifiedEntry.setObjectClasses(attr.getValues());
- return;
- }
-
-
- // If the provided attribute does not have any values, then we will simply
- // remove the attribute from the entry (if it exists).
- AttributeType t = attr.getAttributeType();
- if (! attr.hasValue())
- {
- modifiedEntry.removeAttribute(t, attr.getOptions());
- RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, attr.getOptions(),
- rdn.getAttributeValue(t))))
- {
- throw new DirectoryException(ResultCode.NOT_ALLOWED_ON_RDN,
- ERR_MODIFY_DELETE_RDN_ATTR.get(String.valueOf(entryDN),
- attr.getName()));
- }
-
- return;
- }
-
- // If the server is configured to check schema and the operation is not a
- // synchronization operation, make sure that all the new values are valid
- // according to the associated syntax.
- LinkedHashSet<AttributeValue> newValues = attr.getValues();
- if ((DirectoryServer.checkSchema()) && (! isSynchronizationOperation()))
- {
- AcceptRejectWarn syntaxPolicy =
- DirectoryServer.getSyntaxEnforcementPolicy();
- AttributeSyntax syntax = t.getSyntax();
+ AcceptRejectWarn syntaxPolicy = DirectoryServer
+ .getSyntaxEnforcementPolicy();
+ AttributeSyntax<?> syntax = attr.getAttributeType().getSyntax();
if (syntaxPolicy == AcceptRejectWarn.REJECT)
{
MessageBuilder invalidReason = new MessageBuilder();
- for (AttributeValue v : newValues)
+ for (AttributeValue v : attr)
{
- if (! syntax.valueIsAcceptable(v.getValue(), invalidReason))
+ if (!syntax.valueIsAcceptable(v.getValue(), invalidReason))
{
throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- ERR_MODIFY_REPLACE_INVALID_SYNTAX.get(
- String.valueOf(entryDN), attr.getName(),
- v.getStringValue(), invalidReason));
+ ERR_MODIFY_REPLACE_INVALID_SYNTAX.get(String.valueOf(entryDN),
+ attr.getName(), v.getStringValue(), invalidReason));
}
}
}
else if (syntaxPolicy == AcceptRejectWarn.WARN)
{
MessageBuilder invalidReason = new MessageBuilder();
- for (AttributeValue v : newValues)
+ for (AttributeValue v : attr)
{
- if (! syntax.valueIsAcceptable(v.getValue(), invalidReason))
+ if (!syntax.valueIsAcceptable(v.getValue(), invalidReason))
{
setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
- logError(ERR_MODIFY_REPLACE_INVALID_SYNTAX.get(
- String.valueOf(entryDN), attr.getName(),
- v.getStringValue(), invalidReason));
+ logError(ERR_MODIFY_REPLACE_INVALID_SYNTAX.get(String
+ .valueOf(entryDN), attr.getName(), v.getStringValue(),
+ invalidReason));
invalidReason = new MessageBuilder();
}
}
}
}
-
- // If the provided attribute does not have any options, then we will simply
- // use it in place of any existing attribute of the provided type (or add it
- // if it doesn't exist).
- if (! attr.hasOptions())
+ // If the attribute to be replaced is the object class attribute
+ // then make sure that all the object classes are known and not
+ // obsoleted.
+ if (attr.getAttributeType().isObjectClassType())
{
- List<Attribute> attrList = new ArrayList<Attribute>(1);
- attrList.add(attr);
- modifiedEntry.putAttribute(t, attrList);
-
- RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, attr.getOptions(),
- rdn.getAttributeValue(t))))
- {
- throw new DirectoryException(ResultCode.NOT_ALLOWED_ON_RDN,
- ERR_MODIFY_DELETE_RDN_ATTR.get(
- String.valueOf(entryDN),
- attr.getName()));
- }
-
- return;
+ validateObjectClasses(attr);
}
+ // Replace the provided attribute.
+ modifiedEntry.replaceAttribute(attr);
- // See if there is an existing attribute of the provided type. If not, then
- // we'll use the new one.
- List<Attribute> attrList = modifiedEntry.getAttribute(t);
- if ((attrList == null) || attrList.isEmpty())
- {
- attrList = new ArrayList<Attribute>(1);
- attrList.add(attr);
- modifiedEntry.putAttribute(t, attrList);
-
- RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, attr.getOptions(),
- rdn.getAttributeValue(t))))
- {
- throw new DirectoryException(ResultCode.NOT_ALLOWED_ON_RDN,
- ERR_MODIFY_DELETE_RDN_ATTR.get(
- String.valueOf(entryDN),
- attr.getName()));
- }
-
- return;
- }
-
-
- // There must be an existing occurrence of the provided attribute in the
- // entry. If there is a version with exactly the set of options provided,
- // then replace it. Otherwise, add a new one.
- boolean found = false;
- for (int i=0; i < attrList.size(); i++)
- {
- if (attrList.get(i).optionsEqual(attr.getOptions()))
- {
- attrList.set(i, attr);
- found = true;
- break;
- }
- }
-
- if (! found)
- {
- attrList.add(attr);
- }
-
+ // Make sure that the RDN attribute value(s) has not been removed.
+ AttributeType t = attr.getAttributeType();
RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, attr.getOptions(),
- rdn.getAttributeValue(t))))
+ if ((rdn != null)
+ && rdn.hasAttributeType(t)
+ && (!modifiedEntry.hasValue(t, attr.getOptions(), rdn
+ .getAttributeValue(t))))
{
throw new DirectoryException(ResultCode.NOT_ALLOWED_ON_RDN,
- ERR_MODIFY_DELETE_RDN_ATTR.get(
- String.valueOf(entryDN),
- attr.getName()));
+ ERR_MODIFY_DELETE_RDN_ATTR.get(String.valueOf(entryDN), attr
+ .getName()));
}
}
/**
- * Performs the initial schema processing for an increment modification and
- * updates the entry appropriately.
+ * Performs the initial schema processing for an increment
+ * modification and updates the entry appropriately.
*
- * @param attr The attribute being incremented.
- *
- * @throws DirectoryException If a problem occurs that should cause the
- * modify operation to fail.
+ * @param attr
+ * The attribute being incremented.
+ * @throws DirectoryException
+ * If a problem occurs that should cause the modify
+ * operation to fail.
*/
private void processInitialIncrementSchema(Attribute attr)
- throws DirectoryException
+ throws DirectoryException
{
// The specified attribute type must not be an RDN attribute.
AttributeType t = attr.getAttributeType();
RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t))
+ if ((rdn != null) && rdn.hasAttributeType(t))
{
throw new DirectoryException(ResultCode.NOT_ALLOWED_ON_RDN,
- ERR_MODIFY_INCREMENT_RDN.get(
- String.valueOf(entryDN),
- attr.getName()));
+ ERR_MODIFY_INCREMENT_RDN.get(String.valueOf(entryDN),
+ attr.getName()));
}
-
- // The provided attribute must have a single value, and it must be an
- // integer.
- LinkedHashSet<AttributeValue> values = attr.getValues();
- if ((values == null) || values.isEmpty())
+ // The provided attribute must have a single value, and it must be
+ // an integer.
+ if (attr.isEmpty())
{
throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
- ERR_MODIFY_INCREMENT_REQUIRES_VALUE.get(
- String.valueOf(entryDN),
- attr.getName()));
- }
- else if (values.size() > 1)
- {
- throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
- ERR_MODIFY_INCREMENT_REQUIRES_SINGLE_VALUE.get(
- String.valueOf(entryDN), attr.getName()));
+ ERR_MODIFY_INCREMENT_REQUIRES_VALUE.get(String.valueOf(entryDN), attr
+ .getName()));
}
- AttributeValue v = values.iterator().next();
+ if (attr.size() > 1)
+ {
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
+ ERR_MODIFY_INCREMENT_REQUIRES_SINGLE_VALUE.get(String
+ .valueOf(entryDN), attr.getName()));
+ }
+
+ AttributeValue v = attr.iterator().next();
long incrementValue;
try
@@ -1905,79 +1787,60 @@
}
throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- ERR_MODIFY_INCREMENT_PROVIDED_VALUE_NOT_INTEGER.get(
- String.valueOf(entryDN), attr.getName(),
- v.getStringValue()), e);
+ ERR_MODIFY_INCREMENT_PROVIDED_VALUE_NOT_INTEGER.get(String
+ .valueOf(entryDN), attr.getName(), v.getStringValue()), e);
}
-
- // Get the corresponding attribute from the entry and make sure that it has
- // a single integer value.
- List<Attribute> attrList = modifiedEntry.getAttribute(t, attr.getOptions());
- if ((attrList == null) || attrList.isEmpty())
+ // Get the attribute that is to be incremented.
+ Attribute a = modifiedEntry.getExactAttribute(t, attr.getOptions());
+ if (a == null)
{
throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- ERR_MODIFY_INCREMENT_REQUIRES_EXISTING_VALUE.get(
- String.valueOf(entryDN), attr.getName()));
+ ERR_MODIFY_INCREMENT_REQUIRES_EXISTING_VALUE.get(String
+ .valueOf(entryDN), attr.getName()));
}
- boolean updated = false;
- for (Attribute a : attrList)
+ // Increment each attribute value by the specified amount.
+ AttributeBuilder builder = new AttributeBuilder(a, true);
+ for (AttributeValue existingValue : a)
{
- LinkedHashSet<AttributeValue> valueList = a.getValues();
- if ((valueList == null) || valueList.isEmpty())
+ String s = existingValue.getStringValue();
+ long currentValue;
+ try
{
- continue;
+ currentValue = Long.parseLong(s);
}
-
- LinkedHashSet<AttributeValue> newValueList =
- new LinkedHashSet<AttributeValue>(valueList.size());
- for (AttributeValue existingValue : valueList)
+ catch (Exception e)
{
- long newIntValue;
- try
+ if (debugEnabled())
{
- long existingIntValue =
- Long.parseLong(existingValue.getStringValue());
- newIntValue = existingIntValue + incrementValue;
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- ERR_MODIFY_INCREMENT_REQUIRES_INTEGER_VALUE.get(
- String.valueOf(entryDN), a.getName(),
- existingValue.getStringValue()), e);
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
- ByteString newValue = new ASN1OctetString(String.valueOf(newIntValue));
- newValueList.add(new AttributeValue(t, newValue));
+ throw new DirectoryException(
+ ResultCode.INVALID_ATTRIBUTE_SYNTAX,
+ ERR_MODIFY_INCREMENT_REQUIRES_INTEGER_VALUE.get(String
+ .valueOf(entryDN), a.getName(), existingValue.getStringValue()),
+ e);
}
- a.setValues(newValueList);
- updated = true;
+ long newValue = currentValue + incrementValue;
+ builder.add(new AttributeValue(t, String.valueOf(newValue)));
}
- if (! updated)
- {
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- ERR_MODIFY_INCREMENT_REQUIRES_EXISTING_VALUE.get(
- String.valueOf(entryDN), attr.getName()));
- }
+ // Replace the existing attribute with the incremented version.
+ modifiedEntry.replaceAttribute(builder.toAttribute());
}
/**
- * Performs additional preliminary processing that is required for a password
- * change.
+ * Performs additional preliminary processing that is required for a
+ * password change.
*
- * @throws DirectoryException If a problem occurs that should cause the
- * modify operation to fail.
+ * @throws DirectoryException
+ * If a problem occurs that should cause the modify
+ * operation to fail.
*/
public void performAdditionalPasswordChangedProcessing()
throws DirectoryException
@@ -2390,5 +2253,83 @@
}
}
}
+
+ private boolean handleConflictResolution() {
+ boolean returnVal = true;
+
+ for (SynchronizationProvider<?> provider :
+ DirectoryServer.getSynchronizationProviders()) {
+ try {
+ SynchronizationProviderResult result =
+ provider.handleConflictResolution(this);
+ if (! result.continueProcessing()) {
+ setResultCode(result.getResultCode());
+ appendErrorMessage(result.getErrorMessage());
+ setMatchedDN(result.getMatchedDN());
+ setReferralURLs(result.getReferralURLs());
+ returnVal = false;
+ break;
+ }
+ } catch (DirectoryException de) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+ logError(ERR_MODIFY_SYNCH_CONFLICT_RESOLUTION_FAILED.get(
+ getConnectionID(), getOperationID(),
+ getExceptionMessage(de)));
+ setResponseData(de);
+ returnVal = false;
+ break;
+ }
+ }
+ return returnVal;
+ }
+
+ private boolean processPreOperation() {
+ boolean returnVal = true;
+ for (SynchronizationProvider<?> provider :
+ DirectoryServer.getSynchronizationProviders()) {
+ try {
+ SynchronizationProviderResult result =
+ provider.doPreOperation(this);
+ if (! result.continueProcessing()) {
+ setResultCode(result.getResultCode());
+ appendErrorMessage(result.getErrorMessage());
+ setMatchedDN(result.getMatchedDN());
+ setReferralURLs(result.getReferralURLs());
+ returnVal = false;
+ break;
+ }
+ } catch (DirectoryException de) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+ logError(ERR_MODIFY_SYNCH_PREOP_FAILED.get(getConnectionID(),
+ getOperationID(), getExceptionMessage(de)));
+ setResponseData(de);
+ returnVal = false;
+ break;
+ }
+ }
+ return returnVal;
+ }
+
+ private void processPostOperation() {
+ for (SynchronizationProvider<?> provider :
+ DirectoryServer.getSynchronizationProviders()) {
+ try {
+ provider.doPostOperation(this);
+ } catch (DirectoryException de) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+ logError(ERR_MODIFY_SYNCH_POSTOP_FAILED.get(getConnectionID(),
+ getOperationID(), getExceptionMessage(de)));
+ setResponseData(de);
+ break;
+ }
+ }
+ }
}
+
--
Gitblit v1.10.0