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

gbellato
20.04.2007 972103091b00d019b98516adf64a2db12c20c749
opendj-sdk/opends/resource/config/config.ldif
@@ -601,6 +601,23 @@
ds-cfg-rotation-policy-dn: cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config
ds-cfg-retention-policy-dn: cn=File Count Retention Policy,cn=Log Retention Policies,cn=config
dn: cn=Replication Repair Logger,cn=Loggers,cn=config
objectClass: top
objectClass: ds-cfg-logger
objectClass: ds-cfg-error-logger
objectClass: ds-cfg-file-based-error-logger
cn: File-Based Error Logger
ds-cfg-logger-class: org.opends.server.loggers.TextErrorLogPublisher
ds-cfg-logger-enabled: true
ds-cfg-log-file: logs/replication
ds-cfg-log-file-mode: 640
ds-cfg-default-severity: none
ds-cfg-override-severity: SYNC=INFO,MILD_ERROR,MILD_WARNING,NOTICE
ds-cfg-asynchronous-writes: false
ds-cfg-rotation-policy-dn: cn=7 Days Time Limit Rotation Policy,cn=Log Rotation Policies,cn=config
ds-cfg-rotation-policy-dn: cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config
ds-cfg-retention-policy-dn: cn=File Count Retention Policy,cn=Log Retention Policies,cn=config
dn: cn=File-Based Debug Logger,cn=Loggers,cn=config
objectClass: top
objectClass: ds-cfg-logger
@@ -1921,3 +1938,15 @@
ds-cfg-num-worker-threads: 24
ds-cfg-max-work-queue-capacity: 0
dn: cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-synchronization-provider
objectClass: ds-cfg-multimaster-synchronization-provider
cn: Multimaster Synchronization
ds-cfg-synchronization-provider-enabled: true
ds-cfg-synchronization-provider-class: org.opends.server.replication.plugin.MultimasterReplication
dn: cn=domains,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: domains
opendj-sdk/opends/resource/config/replication.ldif
@@ -9,20 +9,6 @@
# cn=Replication Server, cn=Multimaster Synchronization, cn=Synchronization Providers, cn=config
# entry.
dn: cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-synchronization-provider
objectClass: ds-cfg-multimaster-synchronization-provider
cn: Multimaster Synchronization
ds-cfg-synchronization-provider-enabled: true
ds-cfg-synchronization-provider-class: org.opends.server.replication.plugin.MultimasterReplication
dn: cn=domains,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: domains
dn: cn=example,cn=domains,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-replication-domain-config
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml
@@ -57,6 +57,15 @@
            Messages of all severity levels will be logged.
          </adm:synopsis>
        </adm:value>
        <adm:value name="none">
          <adm:synopsis>
            No messages of any severity will be logged by default.
            This value is intended to be used in conjunction with
            the override-severity property to define an error
            logger that will publish no error message beside the errors
            of a given category.
          </adm:synopsis>
        </adm:value>
        <adm:value name="fatal-error">
          <adm:synopsis>
            The error log severity that will be used for messages that
opendj-sdk/opends/src/messages/messages/replication.properties
@@ -21,7 +21,12 @@
# CDDL HEADER END
#
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration.  It must not
# be directly edited while the server is online.  The server configuration
# should only be managed using the administration utilities provided with the
# Directory Server.
#
@@ -55,8 +60,6 @@
MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=Changelog failed to start : could not \
 bind to the changelog listen port : %d. Error : %s
MILD_ERR_UNKNOWN_TYPE_7=Unknown operation type : %s
MILD_ERR_ERROR_REPLAYING_OPERATION_8=Error %s when replaying operation with \
 changenumber %s %s : %s
MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=Internal Error : Operation %s \
 change number %s was not found in pending list
MILD_ERR_COULD_NOT_INITIALIZE_DB_10=Changelog failed to start because the \
@@ -66,7 +69,7 @@
MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=An Exception was caught while \
 replaying operation %s : %s
MILD_ERR_NEED_CHANGELOG_PORT_13=The replication server port must be defined
MILD_ERR_ERROR_UPDATING_RUV_14=Error %s when updating server state %s : %s \
DEBUG_ERROR_UPDATING_RUV_14=Error %s when updating server state %s : %s \
 base dn : %s
MILD_ERR_ERROR_SEARCHING_RUV_15=Error %s when searching for server state %s : \
 %s base dn : %s
@@ -79,8 +82,8 @@
 server should be configured
NOTICE_EXCEPTION_STARTING_SESSION_20=Caught Exception during initial \
 communication with replication server :
NOTICE_CANNOT_RECOVER_CHANGES_21=Error when searching old changes from the \
 database
MILD_ERR_CANNOT_RECOVER_CHANGES_21=Error when searching old changes from the \
 database for base DN %s
NOTICE_COULD_NOT_FIND_CHANGELOG_WITH_MY_CHANGES_22=Could not find a \
 replication server that has seen all the local changes. Going to replay \
 changes
@@ -110,7 +113,7 @@
SEVERE_ERR_EXCEPTION_RECEIVING_REPLICATION_MESSAGE_34=An Exception was caught \
 while receiving replication message : %s
MILD_ERR_LOOP_REPLAYING_OPERATION_35=A loop was detected while replaying \
 operation: %s
 operation: %s error %s
MILD_ERR_FILE_CHECK_CREATE_FAILED_36=An Exception was caught while testing \
 existence or trying  to create the directory for the changelog database : %s
INFO_CHANGELOG_SERVER_ATTR_37=Specifies the list of replication servers to \
@@ -156,12 +159,12 @@
 have the same ServerId : %d
SEVERE_ERR_BAD_HISTORICAL_56=Entry %s was containing some unknown historical \
 information, This may cause some inconsistency for this entry
SEVERE_ERR_CANNOT_ADD_CONFLICT_ATTRIBUTE_57=A conflict was detected but the \
MILD_ERR_CANNOT_ADD_CONFLICT_ATTRIBUTE_57=A conflict was detected but the \
 conflict information could not be added. Operation :
SEVERE_ERR_CANNOT_RENAME_CONFLICT_ENTRY_58=An error happened trying the \
MILD_ERR_CANNOT_RENAME_CONFLICT_ENTRY_58=An error happened trying to \
 rename a conflicting entry :
SEVERE_ERR_EXCEPTION_RENAME_CONFLICT_ENTRY_59=An Exception happened when \
 trying the rename a conflicting entry :
MILD_ERR_EXCEPTION_RENAME_CONFLICT_ENTRY_59=An Exception happened when \
 trying to rename a conflicting entry :
SEVERE_ERR_CHANGELOG_UNSUPPORTED_UTF8_ENCODING_60=The JVM does not support \
 UTF-8. This is required to be able to encode the changes in the database. \
 This replication server will now shutdown
@@ -179,3 +182,8 @@
 and reopened
SEVERE_ERR_CHANGELOG_ERROR_SENDING_MSG_66=An unexpected error occurred  while \
 sending a Message to %s. This connection is going to be closed and reopened
MILD_ERR_ERROR_REPLAYING_OPERATION_67=Could not replay operation %s with \
 ChangeNumber %s error %s %s
MILD_ERR_UNKNOWN_ATTRIBUTE_IN_HISTORICAL_68=The entry %s has historical \
 information for attribute %s which is not defined in the schema. This \
 information will be ignored
opendj-sdk/opends/src/server/org/opends/server/loggers/TextErrorLogPublisher.java
@@ -194,6 +194,10 @@
          defaultSeverities.add(Severity.SEVERE_ERROR);
          defaultSeverities.add(Severity.SEVERE_WARNING);
        }
        else if (defSev.toString().equalsIgnoreCase(LOG_SEVERITY_NONE))
        {
          // don't add any severity
        }
        else
        {
          Severity errorSeverity =
@@ -424,6 +428,10 @@
          defaultSeverities.add(Severity.SEVERE_ERROR);
          defaultSeverities.add(Severity.SEVERE_WARNING);
        }
        else if (defSev.toString().equalsIgnoreCase(LOG_SEVERITY_NONE))
        {
          // don't add any severity
        }
        else
        {
          Severity errorSeverity =
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/FakeOperation.java
@@ -80,9 +80,7 @@
   *
   * @param mod A modification that must be adde to the list of modifications
   *            included in this fake operation.
   * @throws Exception when the addition of this type of modification
   *         is not valid for this FakeOperation.
   */
  abstract public void addModification(Modification mod) throws Exception;
  abstract public void addModification(Modification mod);
}
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
@@ -374,8 +374,11 @@
             * This attribute is unknown from the schema
             * Just skip it, the modification will be processed but no
             * historical information is going to be kept.
             * TODO : REPAIR tool should deal with this, add some logging.
             * Log information for the repair tool.
             */
            Message message = ERR_UNKNOWN_ATTRIBUTE_IN_HISTORICAL.get(
                entry.getDN().toNormalizedString(), histVal.getAttrString());
            logError(message);
            continue;
          }
@@ -453,19 +456,7 @@
          if (fakeOperation != null)
          {
            try
            {
              fakeOperation.addModification(mod);
            } catch (Exception e)
            {
              /*
               *  TODO : REPAIR : This Exception shows that there are some
               *  inconsistency in the historical information.
               *  This method can't fix the problem.
               *  This should be logged and somehow the repair
               *  service should get called to fix the problem.
               */
            }
            fakeOperation.addModification(mod);
          }
          else
          {
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
@@ -45,6 +45,7 @@
import org.opends.server.types.BackupConfig;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.Control;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
@@ -67,6 +68,8 @@
import org.opends.server.types.operation.PreOperationModifyOperation;
import org.opends.messages.Message;
import static org.opends.server.replication.plugin.
              ReplicationRepairRequestControl.*;
/**
 * This class is used to load the Replication code inside the JVM
@@ -91,20 +94,51 @@
  /**
   * Finds the domain for a given DN.
   *
   * @param dn   The DN for which the domain must be returned.
   * @param op   An optional operation for which the check is done.
   *             Can be null is the request has no associated operation.
   * @return     The domain for this DN.
   * @param dn         The DN for which the domain must be returned.
   * @param pluginOp   An optional operation for which the check is done.
   *                   Can be null is the request has no associated operation.
   * @return           The domain for this DN.
   */
  public static ReplicationDomain findDomain(DN dn, PluginOperation op)
  public static ReplicationDomain findDomain(DN dn, PluginOperation pluginOp)
  {
    /*
     * Don't run the special replication code on Operation that are
     * specifically marked as don't synchronize.
     */
    if ((op != null) && (op instanceof Operation) &&
        (((Operation) op).dontSynchronize()))
      return null;
    if ((pluginOp != null) && (pluginOp instanceof Operation))
    {
        Operation op = ((Operation) pluginOp);
        if (op.dontSynchronize())
          return null;
        /*
         * Check if the provided operation is a repair operation and set
         * the synchronization flags if necessary.
         * The repair operations are tagged as synchronization operations
         * so that the core server let the operation modify the entryuuid
         * and ds-sync-hist attributes.
         * They are also tagged as dontSynchronize so that the replication
         * code running later do not generate ChnageNumber, solve conflicts
         * and forward the operation to the replication server.
         */
        for (Control c : op.getRequestControls())
        {
          if (c.getOID().equals(OID_REPLICATION_REPAIR_CONTROL))
          {
            op.setSynchronizationOperation(true);
            op.setDontSynchronize(true);
            // remove this control from the list of controls since
            // it has now been processed and the local backend will
            // fail if it finds a control that it does not know about and
            // that is marked as critical.
            List<Control> controls = op.getRequestControls();
            controls.remove(c);
            return null;
          }
        }
    }
    ReplicationDomain domain = null;
    DN temp = dn;
@@ -188,6 +222,9 @@
    DirectoryServer.registerRestoreTaskListener(this);
    DirectoryServer.registerExportTaskListener(this);
    DirectoryServer.registerImportTaskListener(this);
    DirectoryServer.registerSupportedControl(
        ReplicationRepairRequestControl.OID_REPLICATION_REPAIR_CONTROL);
  }
  /**
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java
@@ -224,9 +224,10 @@
    op.run();
    ResultCode result = op.getResultCode();
    if (result != ResultCode.SUCCESS)
    if ((result != ResultCode.SUCCESS) &&
        ((result != ResultCode.NO_SUCH_OBJECT)))
    {
      Message message = ERR_ERROR_UPDATING_RUV.get(
      Message message = DEBUG_ERROR_UPDATING_RUV.get(
              op.getResultCode().getResultCodeName().toString(),
              op.toString(),
              op.getErrorMessage().toString(),
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
@@ -330,10 +330,11 @@
                   * An error happened trying to search for the updates
                   * This server will start acepting again new updates but
                   * some inconsistencies will stay between servers.
                   * TODO : REPAIR : log an error for the repair tool
                   * Log an error for the repair tool
                   * that will need to resynchronize the servers.
                   */
                  Message message = NOTE_CANNOT_RECOVER_CHANGES.get();
                  Message message = ERR_CANNOT_RECOVER_CHANGES.get(
                      baseDn.toNormalizedString());
                  logError(message);
                }
                else
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
@@ -1272,8 +1272,9 @@
      {
        // Continue with the next change but the servers could now become
        // inconsistent.
        // TODO : REPAIR : Should let the repair tool know about this
        Message message = ERR_LOOP_REPLAYING_OPERATION.get(op.toString());
        // Let the repair tool know about this.
        Message message = ERR_LOOP_REPLAYING_OPERATION.get(op.toString(),
            op.getErrorMessage().toString());
        logError(message);
        numUnresolvedNamingConflicts.incrementAndGet();
@@ -1306,7 +1307,7 @@
         * An Exception happened during the replay process.
         * Continue with the next change but the servers will now start
         * to be inconsistent.
         * TODO : REPAIR : Should let the repair tool know about this
         * Let the repair tool know about this.
         */
        Message message = ERR_EXCEPTION_REPLAYING_OPERATION.get(
            stackTraceToSingleLineString(e), op.toString());
@@ -1473,7 +1474,11 @@
    else
    {
      // The other type of errors can not be caused by naming conflicts.
      // TODO log a message for the repair tool.
      // Log a message for the repair tool.
      Message message = ERR_ERROR_REPLAYING_OPERATION.get(
          op.toString(), ctx.getChangeNumber().toString(),
          result.toString(), op.getErrorMessage().toString());
      logError(message);
      return true;
    }
  }
@@ -1538,7 +1543,11 @@
   else
   {
     // The other type of errors can not be caused by naming conflicts.
     // TODO log a message for the repair tool.
     // Log a message for the repair tool.
     Message message = ERR_ERROR_REPLAYING_OPERATION.get(
         op.toString(), ctx.getChangeNumber().toString(),
         result.toString(), op.getErrorMessage().toString());
     logError(message);
     return true;
   }
 }
@@ -1651,7 +1660,11 @@
  else
  {
    // The other type of errors can not be caused by naming conflicts.
    // TODO log a message for the repair tool.
    // Log a message for the repair tool.
    Message message = ERR_ERROR_REPLAYING_OPERATION.get(
        op.toString(), ctx.getChangeNumber().toString(),
        result.toString(), op.getErrorMessage().toString());
    logError(message);
    return true;
  }
}
@@ -1745,7 +1758,11 @@
    else
    {
      // The other type of errors can not be caused by naming conflicts.
      // TODO log a message for the repair tool.
      // log a message for the repair tool.
      Message message = ERR_ERROR_REPLAYING_OPERATION.get(
          op.toString(), ctx.getChangeNumber().toString(),
          result.toString(), op.getErrorMessage().toString());
      logError(message);
      return true;
    }
  }
@@ -1793,6 +1810,7 @@
      }
      else
      {
        // log error and information for the REPAIR tool.
        MessageBuilder mb = new MessageBuilder();
        mb.append(ERR_CANNOT_RENAME_CONFLICT_ENTRY.get());
        mb.append(String.valueOf(entryDN));
@@ -1801,10 +1819,10 @@
        mb.append(" ");
        mb.append(String.valueOf(op.getResultCode()));
        logError(mb.toMessage());
        // TODO : log error and information for the REPAIR tool.
      }
    } catch (DirectoryException e)
    {
      // log errror and information for the REPAIR tool.
      MessageBuilder mb = new MessageBuilder();
      mb.append(ERR_EXCEPTION_RENAME_CONFLICT_ENTRY.get());
      mb.append(String.valueOf(entryDN));
@@ -1813,7 +1831,6 @@
      mb.append(" ");
      mb.append(e.getLocalizedMessage());
      logError(mb.toMessage());
      // TODO log errror and information for the REPAIR tool.
    }
  }
@@ -1836,6 +1853,7 @@
    if (newOp.getResultCode() != ResultCode.SUCCESS)
    {
      // log information for the repair tool.
      MessageBuilder mb = new MessageBuilder();
      mb.append(ERR_CANNOT_RENAME_CONFLICT_ENTRY.get());
      mb.append(String.valueOf(dn));
@@ -1844,9 +1862,6 @@
      mb.append(" ");
      mb.append(String.valueOf(newOp.getResultCode()));
      logError(mb.toMessage());
      /*
       * TODO : REPAIR should log information for the repair tool.
       */
    }
  }
@@ -1876,15 +1891,13 @@
    ModifyOperation newOp = conn.processModify(currentDN, mods);
    if (newOp.getResultCode() != ResultCode.SUCCESS)
    {
      // Log information for the repair tool.
      MessageBuilder mb = new MessageBuilder();
      mb.append(ERR_CANNOT_ADD_CONFLICT_ATTRIBUTE.get());
      mb.append(String.valueOf(op));
      mb.append(" ");
      mb.append(String.valueOf(newOp.getResultCode()));
      logError(mb.toMessage());
      /*
       * TODO : REPAIR should log information for the repair tool.
       */
    }
  }
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationRepairRequestControl.java
New file
@@ -0,0 +1,130 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.replication.plugin;
import org.opends.server.types.Control;
import org.opends.server.types.LDAPException;
/**
 * This class implements the Sun-defined replication repair control.
 * This control can be used to modify the content of a replicated database
 * on a single server without impacting the other servers that are replicated
 * with this server.
 * It also allows to modify attributes like entryuuid and ds-sync-hist that
 * are normally not modifiable from an external connection.
 */
public class ReplicationRepairRequestControl
       extends Control
{
  /**
   * The OID of the Replication repair Control.
   */
  public static final String
          OID_REPLICATION_REPAIR_CONTROL = "1.3.6.1.4.1.26027.1.5.2";
  /**
   * Creates a new instance of the replication repair request control with the
   * default settings.
   */
  public ReplicationRepairRequestControl()
  {
    super(OID_REPLICATION_REPAIR_CONTROL, false);
  }
  /**
   * Creates a new instance of the replication repair control with the
   * provided information.
   *
   * @param  oid         The OID to use for this control.
   * @param  isCritical  Indicates whether support for this control should be
   *                     considered a critical part of the client processing.
   */
  public ReplicationRepairRequestControl(String oid, boolean isCritical)
  {
    super(oid, isCritical);
  }
  /**
   * Creates a new replication repair request control from the contents of the
   * provided control.
   *
   * @param  control  The generic control containing the information to use to
   *                  create this replication repair request control.
   *
   * @return  The replication repair request control decoded from the provided
   *          control.
   *
   * @throws  LDAPException  If this control cannot be decoded as a valid
   *                         replication repair request control.
   */
  public static ReplicationRepairRequestControl decodeControl(Control control)
         throws LDAPException
  {
    return new ReplicationRepairRequestControl(control.getOID(),
                                           control.isCritical());
  }
  /**
   * Retrieves a string representation of this replication repair request
   * control.
   *
   * @return  A string representation of this replication repair request
   *          control.
   */
  public String toString()
  {
    StringBuilder buffer = new StringBuilder();
    toString(buffer);
    return buffer.toString();
  }
  /**
   * Appends a string representation of this replication repair request control
   * to the provided buffer.
   *
   * @param  buffer  The buffer to which the information should be appended.
   */
  public void toString(StringBuilder buffer)
  {
    buffer.append("ReplicationRepairRequestControl()");
  }
}
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -903,6 +903,13 @@
   */
  public static final String LOG_SEVERITY_ALL = "all";
  /**
   * The English name for the basic none log severity used to log
   * no error message beside some specific category.
   */
  public static final String LOG_SEVERITY_NONE = "none";
  /**
opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -4702,6 +4702,47 @@
          }
        }
        // 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.
        // This must be done before running the password policy code
        // and any other code that may add attributes marked as
        // "NO-USER-MODIFICATION"
        //
        // Note that doing this checks at this time
        // of the processing does not make it possible for pre-parse plugins
        // to add NO-USER-MODIFICATION attributes to the entry.
        for (AttributeType at : userAttributes.keySet())
        {
          if (at.isNoUserModification())
          {
            if (! (localOp.isInternalOperation() ||
              localOp.isSynchronizationOperation()))
            {
              localOp.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
              localOp.appendErrorMessage(ERR_ADD_ATTR_IS_NO_USER_MOD.get(
                  String.valueOf(entryDN), at.getNameOrOID()));
              break addProcessing;
            }
          }
        }
        for (AttributeType at : operationalAttributes.keySet())
        {
          if (at.isNoUserModification())
          {
            if (! (localOp.isInternalOperation() ||
              localOp.isSynchronizationOperation()))
            {
              localOp.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
              localOp.appendErrorMessage(ERR_ADD_ATTR_IS_NO_USER_MOD.get(
                  String.valueOf(entryDN), at.getNameOrOID()));
              break addProcessing;
            }
          }
        }
        // Check to see if the entry already exists.  We do this before
        // checking whether the parent exists to ensure a referral entry
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
@@ -322,33 +322,6 @@
   */
  protected void configureReplication() throws Exception
  {
    // Add the Multimaster replication plugin
    String synchroPluginLdif = "dn: " + synchroPluginStringDN + "\n"
         + "objectClass: top\n"
         + "objectClass: ds-cfg-synchronization-provider\n"
         + "objectClass: ds-cfg-multimaster-synchronization-provider\n"
         + "ds-cfg-synchronization-provider-enabled: true\n"
         + "ds-cfg-synchronization-provider-class: " +
         "org.opends.server.replication.plugin.MultimasterReplication\n";
    Entry synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
    DirectoryServer.getConfigHandler().addEntry(synchroPluginEntry, null);
    configEntryList.add(synchroPluginEntry.getDN());
    assertNotNull(DirectoryServer.getConfigEntry(DN
        .decode(synchroPluginStringDN)),
        "Unable to add the Multimaster replication plugin");
    // domains container entry.
    String domainsLdif = "dn: "
      + "cn=domains," + synchroPluginStringDN + "\n"
      + "objectClass: top\n"
      + "objectClass: ds-cfg-branch\n";
    Entry domainsEntry = TestCaseUtils.entryFromLdifString(domainsLdif);
    DirectoryServer.getConfigHandler().addEntry(domainsEntry, null);
    configEntryList.add(domainsEntry.getDN());
    assertNotNull(DirectoryServer.getConfigEntry(
      DN.decode(synchroPluginStringDN)),
      "Unable to add the Multimaster replication plugin");
    if (replServerEntry != null)
    {
      // Add the replication server
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ReplicationRepairControlTest.java
New file
@@ -0,0 +1,133 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.replication.plugin;
import org.opends.server.TestCaseUtils;
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.tools.LDAPModify;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class ReplicationRepairControlTest extends ReplicationTestCase
{
  @Test()
  public void testRepairControl()
         throws Exception
  {
    TestCaseUtils.startServer();
    TestCaseUtils.initializeTestBackend(true);
    // Test that we can't add an entry with the entryuuid attribute
    // without specifying the replication repair control.
    String path = TestCaseUtils.createTempFile(
        "dn: uid=test.repair,o=test\n" +
        "changetype: add\n" +
        "objectClass: top\n" +
        "objectClass: person" +
        "objectClass: organizationalPerson" +
        "objectClass: inetOrgPerson" +
        "uid: test.repair" +
        "givenName: Test" +
        "sn: User" +
        "cn: Test User" +
        "userPassword: password" +
        "entryuuid: d5b910d8-47cb-4ac0-9e5f-0f4a77de58d4");
    String[] args =
    {
      "-h", "127.0.0.1",
      "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
      "-D", "cn=Directory Manager",
      "-w", "password",
      "-a",
      "-f", path
    };
    assertEquals(LDAPModify.mainModify(args, false, null, null), 65);
    // Test that we can't add an entry with the ds-sync-hist attribute
    // without specifying the replication repair control.
    String path1 = TestCaseUtils.createTempFile(
        "dn: uid=test.repair,o=test\n" +
        "changetype: add\n" +
        "objectClass: top\n" +
        "objectClass: person" +
        "objectClass: organizationalPerson" +
        "objectClass: inetOrgPerson" +
        "uid: test.repair" +
        "givenName: Test" +
        "sn: User" +
        "cn: Test User" +
        "userPassword: password" +
        "ds-sync-hist: description:00000108b3a6cbb800000001:del:deleted_value");
    String[] args1 =
    {
      "-h", "127.0.0.1",
      "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
      "-D", "cn=Directory Manager",
      "-w", "password",
      "-a",
      "-f", path1
    };
    assertEquals(LDAPModify.mainModify(args1, false, null, null), 65);
    // Now Test specifying the replication repair control makes
    // possible to add an entry with the entryuuid and ds-sync-hist attributes
    // (notice the -J repairControlOid in the ldapmodify arguments)
    String path2 = TestCaseUtils.createTempFile(
        "dn: uid=test.repair,o=test\n" +
        "changetype: add\n" +
        "objectClass: top\n" +
        "objectClass: person" +
        "objectClass: organizationalPerson" +
        "objectClass: inetOrgPerson" +
        "uid: test.repair" +
        "givenName: Test" +
        "sn: User" +
        "cn: Test User" +
        "userPassword: password" +
        "ds-sync-hist: description:00000108b3a6cbb800000001:del:deleted_value" +
        "entryuuid: d5b910d8-47cb-4ac0-9e5f-0f4a77de58d4");
    String[] args2 =
    {
      "-h", "127.0.0.1",
      "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
      "-D", "cn=Directory Manager",
      "-w", "password",
      "-J", "1.3.6.1.4.1.26027.1.5.2",
      "-a",
      "-f", path2
    };
    assertEquals(LDAPModify.mainModify(args2, false, null, null), 0);
  }
}