mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
21.15.2012 d2d863001e51eb3f0f678123b11f9ab1b77ebd6c
Fix OPENDJ-181: DirectoryException provided value has an invalid length for a UUID

Generate entryUUID if none is present using the same algorithm as the virtual attribute provider.
3 files modified
98 ■■■■■ changed files
opends/src/server/org/opends/server/replication/plugin/EntryHistorical.java 90 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java 2 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/SchemaReplicationTest.java 6 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/EntryHistorical.java
@@ -29,18 +29,15 @@
import static org.opends.messages.ReplicationMessages.*;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
import static org.opends.server.util.StaticUtils.getBytes;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.*;
import org.opends.messages.Message;
import org.opends.server.core.DirectoryServer;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.protocol.OperationContext;
import org.opends.server.types.*;
@@ -85,6 +82,13 @@
   */
  public static final String ENTRYUUID_ATTRIBUTE_NAME = "entryuuid";
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  /* The delay to purge the historical informations
   * This delay indicates the time the domain keeps the historical
   * information necessary to solve conflicts.When a change stored in the
@@ -838,11 +842,8 @@
            else
            {
              String uuidString = getEntryUUID(entry);
              if (uuidString != null)
              {
                modifyFakeOperation = new FakeModifyOperation(entry.getDN(),
                    cn, uuidString);
              modifyFakeOperation = new FakeModifyOperation(entry.getDN(), cn,
                  uuidString);
                modifyFakeOperation.addModification(mod);
                operations.put(histVal.getCn(), modifyFakeOperation);
              }
@@ -850,7 +851,6 @@
          }
        }
      }
    }
    return operations.values();
  }
@@ -874,25 +874,15 @@
   *
   * @param entry The entry for which the unique id should be returned.
   *
   * @return The Unique Id of the entry if it has one. null, otherwise.
   * @return The Unique Id of the entry, or a fake one if none is found.
   */
  public static String getEntryUUID(Entry entry)
  {
    String uuidString = null;
    AttributeType entryuuidAttrType =
      DirectoryServer.getSchema().getAttributeType(ENTRYUUID_ATTRIBUTE_NAME);
    List<Attribute> uuidAttrs =
             entry.getOperationalAttribute(entryuuidAttrType);
    if (uuidAttrs != null)
    {
      Attribute uuid = uuidAttrs.get(0);
      if (!uuid.isEmpty())
      {
        AttributeValue uuidVal = uuid.iterator().next();
        uuidString =  uuidVal.getValue().toString();
      }
    }
    return uuidString;
    return extractEntryUUID(uuidAttrs, entry.getDN());
  }
  /**
@@ -905,22 +895,11 @@
   */
  public static String getEntryUUID(PreOperationAddOperation op)
  {
    String uuidString = null;
    Map<AttributeType, List<Attribute>> attrs = op.getOperationalAttributes();
    AttributeType entryuuidAttrType =
      DirectoryServer.getSchema().getAttributeType(ENTRYUUID_ATTRIBUTE_NAME);
    List<Attribute> uuidAttrs = attrs.get(entryuuidAttrType);
    if (uuidAttrs != null)
    {
      Attribute uuid = uuidAttrs.get(0);
      if (!uuid.isEmpty())
      {
        AttributeValue uuidVal = uuid.iterator().next();
        uuidString =  uuidVal.getValue().toString();
      }
    }
    return uuidString;
    return extractEntryUUID(uuidAttrs, op.getEntryDN());
  }
  /**
@@ -969,5 +948,40 @@
  {
    return this.oldestChangeNumber;
  }
  // Extracts the entryUUID attribute value from the provided list of
  // attributes. If the attribute is not present one is generated from the DN
  // using the same algorithm as the entryUUID virtual attribute provider.
  private static String extractEntryUUID(List<Attribute> entryUUIDAttributes,
      DN entryDN)
  {
    if (entryUUIDAttributes != null)
    {
      Attribute uuid = entryUUIDAttributes.get(0);
      if (!uuid.isEmpty())
      {
        AttributeValue uuidVal = uuid.iterator().next();
        return uuidVal.getValue().toString();
      }
    }
    // Generate a fake entryUUID: see OPENDJ-181. In rare pathological cases
    // an entryUUID attribute may not be present and this causes severe side
    // effects for replication which requires the attribute to always be
    // present.
    if (debugEnabled())
    {
      TRACER.debugWarning(
          "Replication requires an entryUUID attribute in order "
              + "to perform conflict resolution, but none was "
              + "found in entry \"%s\": generating virtual entryUUID instead",
          entryDN);
    }
    String normDNString = entryDN.toNormalizedString();
    return UUID.nameUUIDFromBytes(getBytes(normDNString)).toString();
  }
}
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -2209,8 +2209,6 @@
      ChangeNumber changeNumber = generateChangeNumber(modifyOperation);
      String modifiedEntryUUID = EntryHistorical.getEntryUUID(modifiedEntry);
      if (modifiedEntryUUID == null)
        modifiedEntryUUID = modifyOperation.getEntryDN().toString();
      ctx = new ModifyContext(changeNumber, modifiedEntryUUID);
      modifyOperation.setAttachment(SYNCHROCONTEXT, ctx);
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/SchemaReplicationTest.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 */
package org.opends.server.replication;
@@ -48,6 +49,7 @@
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.service.ReplicationBroker;
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.plugin.EntryHistorical;
import org.opends.server.replication.protocol.ModifyMsg;
import org.opends.server.replication.protocol.ReplicationMsg;
import org.opends.server.types.Attribute;
@@ -229,8 +231,8 @@
    {
      ChangeNumberGenerator gen = new ChangeNumberGenerator( 2, 0);
      ModifyMsg modMsg = new ModifyMsg(gen.newChangeNumber(),
        baseDn, rcvdMods, "cn=schema");
      ModifyMsg modMsg = new ModifyMsg(gen.newChangeNumber(), baseDn, rcvdMods,
          EntryHistorical.getEntryUUID(DirectoryServer.getEntry(baseDn)));
      broker.publish(modMsg);
      boolean found = checkEntryHasAttribute(baseDn, "attributetypes",