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

pgamba
15.15.2009 943c10cc9d2d60660c53271a25848ecad77a91e7
Fix #4263 ECL entries should include creatorsName and createTimestamp
6 files modified
272 ■■■■ changed files
opends/resource/schema/03-changelog.ldif 6 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java 14 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java 47 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java 120 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java 82 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java 3 ●●●● patch | view | raw | blame | history
opends/resource/schema/03-changelog.ldif
@@ -89,6 +89,12 @@
  SINGLE-VALUE
  USAGE directoryOperation
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.604 NAME 'changeInitiatorsName'
  DESC 'The initiator user of the change'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  USAGE directoryOperation
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' SUP top
  STRUCTURAL 
  MUST ( changeNumber $ targetDN $ changeType $ changeTime )
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -4537,6 +4537,20 @@
          newattrs.add(a);
      }
      ((DeleteMsg)msg).setEclIncludes(newattrs);
      // For delete only, add the modifiersName since they are required in the
      // ECL entry but are not part of other parts of the message
      AttributeType atype = DirectoryServer.getAttributeType("modifiersname");
      List<Attribute> attrs = entry.getAttribute(atype);
      if (attrs != null)
      {
        for (Attribute a : attrs)
        {
          ((DeleteMsg)msg).setInitiatorsName(a.iterator().next().toString());
          break;
        }
      }
    }
    else if (op instanceof PostOperationModifyOperation)
    {
opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java
@@ -43,6 +43,8 @@
 */
public class DeleteMsg extends LDAPUpdateMsg
{
  String initiatorsName;
  /**
   * Creates a new delete message.
   *
@@ -137,13 +139,28 @@
    byte[] byteEntryAttrLen =
      String.valueOf(encodedEclIncludes.length).getBytes("UTF-8");
    bodyLength += byteEntryAttrLen.length + 1;
    bodyLength += encodedEclIncludes.length + 1;
    byte[] byteInitiatorsName = null;
    if (initiatorsName != null)
    {
      byteInitiatorsName = initiatorsName.getBytes("UTF-8");
      bodyLength += byteInitiatorsName.length + 1;
    }
    else
    {
      bodyLength++;
    }
    /* encode the header in a byte[] large enough to also contain the mods */
    byte [] encodedMsg = encodeHeader(MSG_TYPE_DELETE, bodyLength,
        ProtocolVersion.REPLICATION_PROTOCOL_V4);
    int pos = encodedMsg.length - bodyLength;
    if (byteInitiatorsName != null)
      pos = addByteArray(byteInitiatorsName, encodedMsg, pos);
    else
      encodedMsg[pos++] = 0;
    pos = addByteArray(byteEntryAttrLen, encodedMsg, pos);
    pos = addByteArray(encodedEclIncludes, encodedMsg, pos);
    return encodedMsg;
@@ -158,6 +175,17 @@
  {
    // Read ecl attr len
    int length = getNextLength(in, pos);
    if (length != 0)
    {
      initiatorsName = new String(in, pos, length, "UTF-8");
      pos += length + 1;
    }
    else
    {
      initiatorsName = null;
      pos += 1;
    }
    length = getNextLength(in, pos);
    int eclAttrLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
    pos += length + 1;
@@ -216,4 +244,23 @@
    return encodedEclIncludes.length + headerSize();
  }
  /**
   * Set the initiator's name of this change.
   *
   * @param iname the initiator's name.
   */
  public void setInitiatorsName(String iname)
  {
    initiatorsName = iname;
  }
  /**
   * Get the initiator's name of this change.
   * @return the initiator's name.
   */
  public String getInitiatorsName()
  {
    return initiatorsName;
  }
}
opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
@@ -62,6 +62,7 @@
import org.opends.server.core.AccessControlConfigManager;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.PersistentSearch;
import org.opends.server.core.PluginConfigManager;
@@ -733,7 +734,7 @@
          null, // real time current entry
          eclAttributes, // entry attributes
          eclmsg.getDraftChangeNumber(),
      "add");
      "add", null);
    } else
      if (msg instanceof ModifyMsg)
@@ -761,7 +762,7 @@
              null, // real time current entry
              eclAttributes, // entry attributes
              eclmsg.getDraftChangeNumber(),
              "modify");
              "modify",null);
        }
        catch(Exception e)
@@ -774,21 +775,28 @@
      }
      else if (msg instanceof ModifyDNMsg)
      {
        try
        {
          InternalClientConnection conn =
            InternalClientConnection.getRootConnection();
        ModifyDNMsg modDNMsg = (ModifyDNMsg)msg;
        ArrayList<RawAttribute> eclAttributes = modDNMsg.getEclIncludes();
          ModifyDNOperation modifyDNOperation =
            (ModifyDNOperation)modDNMsg.createOperation(conn);
          String LDIFchanges = modToLDIF(modifyDNOperation.getModifications());
        clEntry = createChangelogEntry(
            eclmsg.getServiceId(),
            eclmsg.getCookie().toString(),
            DN.decode(modDNMsg.getDn()),
            modDNMsg.getChangeNumber(),
            null,
              LDIFchanges,
            modDNMsg.getUniqueId(),
            null, // real time current entry
            eclAttributes, // entry attributes
            eclmsg.getDraftChangeNumber(),
           "modrdn");
          "modrdn", null);
        Attribute a = Attributes.create("newrdn", modDNMsg.getNewRDN());
        clEntry.addAttribute(a, null);
@@ -803,6 +811,14 @@
        Attribute c = Attributes.create("deleteoldrdn",
            String.valueOf(modDNMsg.deleteOldRdn()));
        clEntry.addAttribute(c, null);
        }
        catch(Exception e)
        {
          // Exceptions raised by createOperation for example
          throw new DirectoryException(ResultCode.OTHER,
              Message.raw(Category.SYNC, Severity.NOTICE,
                  " Server fails to create entry: "),e);
        }
      }
      else if (msg instanceof DeleteMsg)
@@ -821,7 +837,7 @@
            null,
            eclAttributes, // entry attributes
            eclmsg.getDraftChangeNumber(),
           "delete");
           "delete", delMsg.getInitiatorsName());
      }
    return clEntry;
  }
@@ -861,6 +877,7 @@
   * @param histEntryAttributes TODO:ECL Adress hist entry attributes
   * @param draftChangenumber The provided draft change number (integer)
   * @param changetype      The provided change type (add, ...)
   * @param delInitiatorsName The provided del initiatiors name
   * @return                The created ECL entry.
   * @throws DirectoryException
   *         When any error occurs.
@@ -875,12 +892,14 @@
      Entry entry,
      List<RawAttribute> histEntryAttributes,
      int draftChangenumber,
      String changetype)
      String changetype,
      String delInitiatorsName)
  throws DirectoryException
  {
    AttributeType attributeType;
    String dnString = "";
    String pattern;
    if (draftChangenumber == 0)
    {
      // Draft uncompat mode
@@ -1007,6 +1026,8 @@
    if (clearLDIFchanges != null)
    {
      if (changetype.equals("add"))
      {
      if((attributeType =
        DirectoryServer.getAttributeType("changes")) == null)
        attributeType =
@@ -1020,6 +1041,85 @@
        operationalAttrs.put(attributeType, attrList);
      else
        uAttrs.put(attributeType, attrList);
        pattern = "creatorsName: ";
        int att_cr = clearLDIFchanges.indexOf(pattern);
        if (att_cr>0)
        {
          int start_val_cr = clearLDIFchanges.indexOf(':', att_cr);
          int end_val_cr = clearLDIFchanges.indexOf(EOL, att_cr);
          String creatorsName =
            clearLDIFchanges.substring(start_val_cr+2, end_val_cr);
          if((attributeType =
            DirectoryServer.getAttributeType("changeInitiatorsName")) == null)
            attributeType =
              DirectoryServer.getDefaultAttributeType("changeInitiatorsName");
          a = Attributes.create(attributeType, creatorsName);
          attrList = new ArrayList<Attribute>(1);
          attrList.add(a);
          if(attributeType.isOperational())
            operationalAttrs.put(attributeType, attrList);
          else
            uAttrs.put(attributeType, attrList);
        }
      }
      else if (changetype.equals("modify")||changetype.equals("modrdn"))
      {
        if (changetype.equals("modify"))
        {
          if((attributeType =
            DirectoryServer.getAttributeType("changes")) == null)
            attributeType =
              DirectoryServer.getDefaultAttributeType("changes");
          a = Attributes.create(attributeType, clearLDIFchanges + "\n");
          // force base64
          attrList = new ArrayList<Attribute>(1);
          attrList.add(a);
          if(attributeType.isOperational())
            operationalAttrs.put(attributeType, attrList);
          else
            uAttrs.put(attributeType, attrList);
        }
        pattern = "modifiersName: ";
        int att_cr = clearLDIFchanges.indexOf(pattern);
        if (att_cr>0)
        {
          int start_val_cr = att_cr + pattern.length();
          int end_val_cr = clearLDIFchanges.indexOf(EOL, att_cr);
          String modifiersName =
            clearLDIFchanges.substring(start_val_cr, end_val_cr);
          if((attributeType =
            DirectoryServer.getAttributeType("changeInitiatorsName")) == null)
            attributeType =
              DirectoryServer.getDefaultAttributeType("changeInitiatorsName");
          a = Attributes.create(attributeType, modifiersName);
          attrList = new ArrayList<Attribute>(1);
          attrList.add(a);
          if(attributeType.isOperational())
            operationalAttrs.put(attributeType, attrList);
          else
            uAttrs.put(attributeType, attrList);
        }
      }
    }
    if (changetype.equals("delete") && (delInitiatorsName!=null))
    {
      if((attributeType =
        DirectoryServer.getAttributeType("changeInitiatorsName")) == null)
        attributeType =
          DirectoryServer.getDefaultAttributeType("changeInitiatorsName");
      a = Attributes.create(attributeType, delInitiatorsName);
      attrList = new ArrayList<Attribute>(1);
      attrList.add(a);
      if(attributeType.isOperational())
        operationalAttrs.put(attributeType, attrList);
      else
        uAttrs.put(attributeType, attrList);
    }
    if (targetUUID != null)
@@ -1072,7 +1172,8 @@
      {
        try
        {
          String eclName = "target" + ra.getAttributeType().toLowerCase();
          String attrName = ra.getAttributeType().toLowerCase();
          String eclName = "target" + attrName;
          AttributeBuilder builder = new AttributeBuilder(
              DirectoryServer.getDefaultAttributeType(eclName));
          AttributeType at = builder.getAttributeType();
@@ -1250,6 +1351,11 @@
   */
  public static String modToLDIF(List<Modification> mods)
  {
    if (mods==null)
    {
      // test case only
      return null;
    }
    StringBuilder modTypeLine = new StringBuilder();
    Iterator<Modification> iterator = mods.iterator();
    while (iterator.hasNext())
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
@@ -27,6 +27,7 @@
package org.opends.server.replication;
import static org.opends.server.TestCaseUtils.TEST_ROOT_DN_STRING;
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.replication.protocol.OperationContext.SYNCHROCONTEXT;
@@ -54,6 +55,9 @@
import java.util.SortedSet;
import java.util.TreeSet;
import org.opends.messages.Category;
import org.opends.messages.Message;
import org.opends.messages.Severity;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.Backend;
import org.opends.server.api.ConnectionHandler;
@@ -226,6 +230,7 @@
    // Write additional changes and read ECL from a provided draft change number
    ts = ECLCompatWriteReadAllOps(5);replicationServer.clearDb();
    // ECLIncludeAttributes();replicationServer.clearDb();
  }
  @Test(enabled=true, groups="slow", dependsOnMethods = { "ECLReplicationServerTest"})
@@ -2428,10 +2433,10 @@
  {
    if (debugEnabled())
    {
//      logError(Message.raw(Category.SYNC, Severity.NOTICE,
//         "** TEST " + tn + " ** " + s));
      TRACER.debugInfo("** TEST " + tn + " ** " + s);
    }
    // logError(Message.raw(Category.SYNC, Severity.NOTICE,
    // "** TEST " + tn + " ** " + s));
  }
  /**
@@ -3434,14 +3439,25 @@
  {
    String tn = "ECLIncludeAttributes";
    debugInfo(tn, "Starting test\n\n");
    Backend backend2 = null;
    Backend backend3 = null;
    ReplicationBroker server01 = null;
    DeleteOperationBasis delOp =null;
    LDAPReplicationDomain domain2 = null;
    LDAPReplicationDomain domain3 = null;
    LDAPReplicationDomain domain21 = null;
    SynchronizationProvider replicationPlugin2 = null;
    SynchronizationProvider replicationPlugin3 = null;
    DN baseDn2 = null;
    DN baseDn3 = null;
    try
    {
      // Initialize a second test backend o=test2, in addtion to o=test
      // Configure replication on this backend
      // Add the root entry in the backend
      Backend backend2 = initializeTestBackend(false,
      backend2 = initializeTestBackend(false,
          TEST_ROOT_DN_STRING2, TEST_BACKEND_ID2);
      DN baseDn2 = DN.decode(TEST_ROOT_DN_STRING2);
      baseDn2 = DN.decode(TEST_ROOT_DN_STRING2);
      SortedSet<String> replServers = new TreeSet<String>();
      replServers.add("localhost:"+replicationServerPort);
      DomainFakeCfg domainConf =
@@ -3449,20 +3465,20 @@
      SortedSet<String> includeAttributes = new TreeSet<String>();
      includeAttributes.add("sn");
      domainConf.setEclIncludes(includeAttributes);
      LDAPReplicationDomain domain2 = MultimasterReplication.createNewDomain(domainConf);
      SynchronizationProvider replicationPlugin2 = new MultimasterReplication();
      domain2 = MultimasterReplication.createNewDomain(domainConf);
      replicationPlugin2 = new MultimasterReplication();
      replicationPlugin2.completeSynchronizationProvider();
      Backend backend3 = initializeTestBackend(false,
      backend3 = initializeTestBackend(false,
          TEST_ROOT_DN_STRING3, TEST_BACKEND_ID3);
      DN baseDn3 = DN.decode(TEST_ROOT_DN_STRING3);
      baseDn3 = DN.decode(TEST_ROOT_DN_STRING3);
      domainConf =
        new DomainFakeCfg(baseDn3, 1703, replServers);
      includeAttributes = new TreeSet<String>();
      includeAttributes.add("objectclass");
      domainConf.setEclIncludes(includeAttributes);
      LDAPReplicationDomain domain3 = MultimasterReplication.createNewDomain(domainConf);
      SynchronizationProvider replicationPlugin3 = new MultimasterReplication();
      domain3 = MultimasterReplication.createNewDomain(domainConf);
      replicationPlugin3 = new MultimasterReplication();
      replicationPlugin3.completeSynchronizationProvider();
      domainConf =
@@ -3470,11 +3486,11 @@
      includeAttributes = new TreeSet<String>();
      includeAttributes.add("cn");
      domainConf.setEclIncludes(includeAttributes);
      LDAPReplicationDomain domain21 = MultimasterReplication.createNewDomain(domainConf);
      domain21 = MultimasterReplication.createNewDomain(domainConf);
      Set<String> attrList = new HashSet<String>();
      attrList.add(new String("cn"));
      ReplicationBroker server01 = openReplicationSession(
      server01 = openReplicationSession(
          DN.decode(TEST_ROOT_DN_STRING2), 1206,
          100, replicationServerPort,
          1000, true, -1 , domain21);
@@ -3550,7 +3566,7 @@
      waitOpResult(modDNOp, ResultCode.SUCCESS);
      //
      DeleteOperationBasis delOp = new DeleteOperationBasis(connection,
      delOp = new DeleteOperationBasis(connection,
          InternalClientConnection.nextOperationID(),
          InternalClientConnection.nextMessageID(), null,
          DN.decode("cn=Robert Hue2," + TEST_ROOT_DN_STRING3));
@@ -3611,10 +3627,40 @@
            checkValue(resultEntry,"targetsn","jensen");
            checkValue(resultEntry,"targetcn","Fiona Jensen");
          }
          checkValue(resultEntry,"changeinitiatorsname", "cn=Internal Client,cn=Root DNs,cn=config");
        }
      }
      assertEquals(entries.size(),8, "Entries number returned by search" + s);
    }
    catch(Exception e)
    {
      fail("Ending "+tn+" test with exception:\n"
          +  stackTraceToSingleLineString(e));
    }
    finally
    {
      try
      {
      server01.stop();
        //
        delOp = new DeleteOperationBasis(connection,
            InternalClientConnection.nextOperationID(),
            InternalClientConnection.nextMessageID(), null,
            DN.decode("cn=Fiona Jensen," + TEST_ROOT_DN_STRING2));
        delOp.run();
        waitOpResult(delOp, ResultCode.SUCCESS);
        delOp = new DeleteOperationBasis(connection,
            InternalClientConnection.nextOperationID(),
            InternalClientConnection.nextMessageID(), null,
            DN.decode(TEST_ROOT_DN_STRING2));
        delOp.run();
        waitOpResult(delOp, ResultCode.SUCCESS);
        delOp = new DeleteOperationBasis(connection,
            InternalClientConnection.nextOperationID(),
            InternalClientConnection.nextMessageID(), null,
            DN.decode(TEST_ROOT_DN_STRING3));
        delOp.run();
        waitOpResult(delOp, ResultCode.SUCCESS);
      // Cleaning
      if (domain2 != null)
@@ -3628,16 +3674,8 @@
      if (replicationPlugin3 != null)
        DirectoryServer.deregisterSynchronizationProvider(replicationPlugin3);
      removeTestBackend2(backend3);
    }
    catch(Exception e)
    {
      fail("Ending "+tn+" test with exception:\n"
          +  stackTraceToSingleLineString(e));
    }
    finally
    {
      catch(Exception e) {}
    }
    debugInfo(tn, "Ending test with success");
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
@@ -350,11 +350,12 @@
    {
      msg.setEclIncludes(entryAttrList);
    }
    msg.setInitiatorsName("johnny h");
    DeleteMsg generatedMsg = (DeleteMsg) ReplicationMsg.generateMsg(
        msg.getBytes(), ProtocolVersion.getCurrentVersion());
    assertEquals(msg.toString(), generatedMsg.toString());
    assertEquals(msg.getInitiatorsName(), generatedMsg.getInitiatorsName());
    assertEquals(msg.getChangeNumber(), generatedMsg.getChangeNumber());