From 7240414922d397035a29ce49cd7281e5eec5e724 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 16 Jun 2014 13:12:30 +0000
Subject: [PATCH] OPENDJ-1490 (CR-3724) Replicated server fails to start after upgrade due to missing ReplicationBackend class

---
 opendj-sdk/opendj3-server-dev/src/messages/messages/tools.properties                                                                      |    8 +-
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java                                                |  115 +++++++++++++++-------------
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/Upgrade.java                                                     |   15 +++
 opendj-sdk/opendj3-server-dev/src/messages/messages/admin_tool.properties                                                                 |    6 
 opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java |   17 ---
 opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java                                                |   79 ++++++++++---------
 6 files changed, 125 insertions(+), 115 deletions(-)

diff --git a/opendj-sdk/opendj3-server-dev/src/messages/messages/admin_tool.properties b/opendj-sdk/opendj3-server-dev/src/messages/messages/admin_tool.properties
index 040999f..bbf0d3c 100644
--- a/opendj-sdk/opendj3-server-dev/src/messages/messages/admin_tool.properties
+++ b/opendj-sdk/opendj3-server-dev/src/messages/messages/admin_tool.properties
@@ -641,12 +641,12 @@
  following suffixes:%n%s%nTo avoid a single point of failure at least two \
  replication servers must be configured.%nDo you want to continue?
 INFO_DISABLE_REPLICATION_DISABLE_IN_REMOTE=You have decided to disable the \
- replication server (replication changelog).  At least one replicaton server \
+ replication server (replication changelog).  At least one replication server \
  is required in a replication topology and this is the last replication server \
  for the following suffixes:%n%s%nReplication will be disabled for these \
  servers.
 INFO_DISABLE_REPLICATION_DISABLE_IN_REMOTE_PROMPT=You have decided to disable \
- the replication server (replication changelog).  At least one replicaton \
+ the replication server (replication changelog).  At least one replication \
  server is required in a replication topology and this is the last replication \
  server for the following suffixes:%n%s%nReplication will be disabled for \
  these servers.%nDo you want to continue?
@@ -688,7 +688,7 @@
 INFO_REPLICATION_WARNING_NO_REPLICATION_SERVER_TO_DISABLE=There is no \
  replication server configured in '%s'.
 INFO_REPLICATION_PROMPT_DISABLE_REPLICATION_SERVER=Do you want to disable the \
- replication server (changelog and replicatin port '%d') on the server?
+ replication server (changelog and replication port '%d') on the server?
 INFO_REPLICATION_CONFIRM_INITIALIZE_ADS=You chose to initialize the contents \
  of base DN %s on server %s with the contents in server %s.  This base DN is \
  used by the replication mechanism and by some administrative tools and it is \
diff --git a/opendj-sdk/opendj3-server-dev/src/messages/messages/tools.properties b/opendj-sdk/opendj3-server-dev/src/messages/messages/tools.properties
index 930a875..32b878e 100644
--- a/opendj-sdk/opendj3-server-dev/src/messages/messages/tools.properties
+++ b/opendj-sdk/opendj3-server-dev/src/messages/messages/tools.properties
@@ -2347,7 +2347,7 @@
  provided LDIF files must be conform to the server schema
 WARN_LDIFDIFF_NO_CONFIG_FILE_1675=WARNING:  no configuration file was \
  provided as argument.  No schema check will be performed.  If this is being \
- called throught the '%s' command-line, verify that the script has not been \
+ called through the '%s' command-line, verify that the script has not been \
  modified
 INFO_LDAPAUTH_NON_EMPTY_PASSWORD_1676=You must provide a non-empty password \
 to continue
@@ -2375,10 +2375,8 @@
 INFO_LDIFIMPORT_THREAD_COUNT_PLACEHOLDER_1687={count}
 ERR_LDIFIMPORT_CANNOT_PARSE_THREAD_COUNT_1688=The value %s for \
 threadCount cannot be parsed: %s
-
 INFO_LDAPSEARCH_PUBLIC_CHANGELOG_COOKIE_EXC_1689=# Public \
  changelog exchange control(%s): %s
-
 INFO_ENCPW_DESCRIPTION_INPUT_PW_1690=The password to encode or to compare \
  against an encoded password is interactively asked to the user
 INFO_ENCPW_INPUT_PWD_1_1691=Please enter the password :
@@ -2540,7 +2538,7 @@
 INFO_UPGRADE_REBUILD_INDEX_ENDS_1840=Rebuild index task ends
 INFO_UPGRADE_PERFORMING_POST_TASKS_1841=Performing post upgrade tasks
 INFO_UPGRADE_POST_TASKS_COMPLETE_1842=Post upgrade tasks complete
-ERR_UPGRADE_PERFORMING_POST_TASKS_FAIL_1843=An error occured during post \
+ERR_UPGRADE_PERFORMING_POST_TASKS_FAIL_1843=An error occurred during post \
 upgrade task. Process aborted. Please check log for further details
 INFO_UPGRADE_REBUILD_INDEX_DECLINED_1844 =You have to rebuild the '%s' index \
 manually to get a fully functional server
@@ -2589,3 +2587,5 @@
 INFO_UPGRADE_TASK_10232_1_SUMMARY_10024=Deleting ds-cfg-default-debug-level attribute in File-Based Debug Logger
 INFO_UPGRADE_TASK_10329_1_SUMMARY_10025=Updating ds-cfg-default-severity attribute in File-Based Error Logger
 INFO_UPGRADE_TASK_10339_1_SUMMARY_10026=Updating ds-cfg-override-severity attribute in Replication Repair Logger
+INFO_UPGRADE_TASK_10733_1_SUMMARY_10027=Removing 'dc=replicationchanges' backend
+INFO_UPGRADE_TASK_10733_2_SUMMARY_10028=Removing ACI for 'dc=replicationchanges'
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/Upgrade.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/Upgrade.java
index 960fcee..436b2c7 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/Upgrade.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/Upgrade.java
@@ -132,7 +132,7 @@
         "delete: objectClass",
         "objectClass: ds-cfg-file-based-access-log-publisher"));
 
-    register ("2.5.0.7466",
+    register("2.5.0.7466",
         renameSnmpSecurityConfig(INFO_UPGRADE_TASK_7466_SUMMARY.get()));
 
     register("2.5.0.7748",
@@ -353,6 +353,19 @@
              "add:ds-cfg-override-severity",
              "ds-cfg-override-severity: SYNC=INFO,ERROR,WARNING,NOTICE"));
 
+    /** See OPENDJ-1490 and OPENDJ-1454 */
+    register("2.7.0.10703",
+        deleteConfigEntry(INFO_UPGRADE_TASK_10733_1_SUMMARY.get(),
+        "dn: ds-cfg-backend-id=replicationChanges,cn=Backends,cn=config"),
+        modifyConfigEntry(INFO_UPGRADE_TASK_10733_2_SUMMARY.get(),
+        "(objectClass=ds-cfg-dsee-compat-access-control-handler)",
+        "delete: ds-cfg-global-aci",
+        "ds-cfg-global-aci: "
+            + "(target=\"ldap:///dc=replicationchanges\")"
+            + "(targetattr=\"*\")"
+            + "(version 3.0; acl \"Replication backend access\"; "
+            + "deny (all) userdn=\"ldap:///anyone\";)"));
+
     /*
      * All upgrades will refresh the server configuration schema and generate
      * a new upgrade folder.
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java
index 4b56b59..f2bad5c 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeTasks.java
@@ -83,8 +83,8 @@
   static boolean isRebuildAllIndexesTaskAccepted = false;
 
   /**
-   * Returns a new upgrade task which applies an LDIF record to all
-   * configuration entries matching the provided filter.
+   * Returns a new upgrade task which adds a config entry to the underlying
+   * config file.
    *
    * @param summary
    *          The summary of this upgrade task.
@@ -205,6 +205,30 @@
   }
 
   /**
+   * Returns a new upgrade task which deletes a config entry from the underlying
+   * config file.
+   *
+   * @param summary
+   *          The summary of this upgrade task.
+   * @param dnInLDIF
+   *          The dn to delete in the form of LDIF.
+   * @return A new upgrade task which applies an LDIF record to all
+   *         configuration entries matching the provided filter.
+   */
+  public static UpgradeTask deleteConfigEntry(final LocalizableMessage summary,
+      final String dnInLDIF)
+  {
+    return new AbstractUpgradeTask()
+    {
+      @Override
+      public void perform(final UpgradeContext context) throws ClientException
+      {
+        perform0(summary, null, ChangeOperationType.DELETE, context, dnInLDIF);
+      }
+    };
+  }
+
+  /**
    * Returns a new upgrade task which applies an LDIF record to all
    * configuration entries matching the provided filter.
    *
@@ -803,33 +827,7 @@
       {
         if (userConfirmation)
         {
-          displayTaskLogInformation(summary.toString(), null, ldif);
-
-          final ProgressNotificationCallback pnc =
-              new ProgressNotificationCallback(0, summary, 20);
-
-          context.notifyProgress(pnc);
-
-          try
-          {
-            // TODO change the directory to the config if it exists.
-            final File configFile =
-                new File(configDirectory,
-                    Installation.CURRENT_CONFIG_FILE_NAME);
-
-            final int changeCount =
-                updateConfigFile(configFile.getPath(), null,
-                    ChangeOperationType.ADD, ldif);
-
-            displayChangeCount(configFile.getPath(), changeCount);
-
-            context.notifyProgress(pnc.setProgress(100));
-          }
-          catch (final Exception e)
-          {
-            manageTaskException(context,
-                LocalizableMessage.raw(e.getMessage()), pnc);
-          }
+          perform0(summary, null, ChangeOperationType.ADD, context, ldif);
         }
       }
     };
@@ -907,37 +905,44 @@
       {
         if (userConfirmation)
         {
-          displayTaskLogInformation(summary.toString(), filter, ldif);
-
-          final ProgressNotificationCallback pnc =
-              new ProgressNotificationCallback(0, summary, 20);
-
-          context.notifyProgress(pnc);
-
-          try
-          {
-            final File configFile =
-                new File(configDirectory,
-                    Installation.CURRENT_CONFIG_FILE_NAME);
-
-            final int changeCount =
-                updateConfigFile(configFile.getPath(), Filter.valueOf(filter),
-                    ChangeOperationType.MODIFY, ldif);
-
-            displayChangeCount(configFile.getPath(), changeCount);
-
-            context.notifyProgress(pnc.setProgress(100));
-          }
-          catch (final Exception e)
-          {
-            manageTaskException(context,
-                LocalizableMessage.raw(e.getMessage()), pnc);
-          }
+          perform0(summary, filter, ChangeOperationType.MODIFY, context, ldif);
         }
       }
+
     };
   }
 
+  private static void perform0(final LocalizableMessage summary, final String filter,
+      final ChangeOperationType changeOperationType,
+      final UpgradeContext context, final String... ldif)
+      throws ClientException
+  {
+    displayTaskLogInformation(summary.toString(), filter, ldif);
+
+    final ProgressNotificationCallback pnc =
+        new ProgressNotificationCallback(0, summary, 20);
+
+    context.notifyProgress(pnc);
+
+    try
+    {
+      final File configFile =
+          new File(configDirectory, Installation.CURRENT_CONFIG_FILE_NAME);
+
+      final Filter filterVal = filter != null ? Filter.valueOf(filter) : null;
+      final int changeCount =
+          updateConfigFile(configFile.getPath(), filterVal,
+              changeOperationType, ldif);
+
+      displayChangeCount(configFile.getPath(), changeCount);
+
+      context.notifyProgress(pnc.setProgress(100));
+    }
+    catch (final Exception e)
+    {
+      manageTaskException(context, LocalizableMessage.raw(e.getMessage()), pnc);
+    }
+  }
 
   // Prevent instantiation.
   private UpgradeTasks()
diff --git a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java
index 86f7ec5..f557369 100644
--- a/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java
+++ b/opendj-sdk/opendj3-server-dev/src/server/org/opends/server/tools/upgrade/UpgradeUtils.java
@@ -56,6 +56,7 @@
 import static org.opends.server.tools.upgrade.FileManager.deleteRecursively;
 import static org.opends.server.tools.upgrade.FileManager.rename;
 import static org.opends.server.tools.upgrade.Installation.*;
+import static org.opends.server.util.ChangeOperationType.*;
 
 /**
  * Common utility methods needed by the upgrade.
@@ -407,22 +408,23 @@
   /**
    * Updates the config file during the upgrade process.
    *
-   *
    * @param configPath
    *          The original path to the file.
    * @param filter
-   *          The filter to avoid files.
+   *          The filter to select entries. Only useful for modify change type.
    * @param changeType
    *          The change type which must be applied to ldif lines.
-   * @param lines
+   * @param ldifLines
    *          The change record ldif lines.
+   *          For ADD change type, the first line must be the dn.
+   *          For DELETE change type, the first and only line must be the dn.
    * @throws IOException
    *           If an Exception occurs during the input output methods.
    * @return The changes number that have occurred.
    */
   static int updateConfigFile(final String configPath,
       final Filter filter, final ChangeOperationType changeType,
-      final String... lines) throws IOException
+      final String... ldifLines) throws IOException
   {
     final File original = new File(configPath);
     final File copyConfig =
@@ -445,54 +447,64 @@
       writer.writeComment(INFO_CONFIG_FILE_HEADER.get());
       writer.setWrapColumn(0);
 
-      boolean alreadyExist = false;
-      String dn = null;
-      if (filter == null && changeType == ChangeOperationType.ADD)
+      boolean entryAlreadyExist = false;
+      DN ldifDN = null;
+      if (filter == null && (changeType == ADD || changeType == DELETE))
       {
-        // For an Add, the first line should start with dn:
-        dn = lines[0].replaceFirst("dn: ","");
+        // The first line should start with dn:
+        ldifDN = DN.valueOf(ldifLines[0].replaceFirst("dn: ", ""));
       }
-      final Matcher matcher =
-          filter != null ? filter.matcher(schema) : Filter.alwaysFalse()
-              .matcher(schema);
+      final Filter f = filter != null ? filter : Filter.alwaysFalse();
+      final Matcher matcher = f.matcher(schema);
       while (entryReader.hasNext())
       {
         Entry entry = entryReader.readEntry();
+        final DN entryDN = entry.getName();
         // Searching for the related entries
-        if (matcher.matches(entry) == ConditionResult.TRUE)
+        if (changeType == MODIFY
+            && matcher.matches(entry) == ConditionResult.TRUE)
         {
           try
           {
-            final ModifyRequest mr =
-                Requests.newModifyRequest(readLDIFLines(entry.getName(),
-                    changeType, lines));
+            final ModifyRequest mr = Requests.newModifyRequest(
+                readLDIFLines(entryDN, changeType, ldifLines));
             entry = Entries.modifyEntryPermissive(entry, mr.getModifications());
             changeCount++;
             logger.debug(LocalizableMessage.raw(
-                String.format("The following entry has been modified : %s",
-                    entry.getName())));
+                "The following entry has been modified : %s", entryDN));
           }
           catch (Exception ex)
           {
             logger.error(LocalizableMessage.raw(ex.getMessage()));
           }
         }
-        if (dn != null // This is an ADD
-            && entry.getName().equals(DN.valueOf(dn)))
+
+        if (entryDN.equals(ldifDN))
         {
-          logger.debug(LocalizableMessage.raw(String.format("Entry %s found", entry.getName())));
-          alreadyExist = true;
+          logger.debug(LocalizableMessage.raw("Entry %s found", entryDN));
+          entryAlreadyExist = true;
+
+          if (changeType == DELETE)
+          {
+            entry = null;
+            changeCount++;
+            logger.debug(LocalizableMessage.raw(
+                "The following entry has been deleted : %s", entryDN));
+          }
         }
-        writer.writeEntry(entry);
+
+        if (entry != null)
+        {
+          writer.writeEntry(entry);
+        }
       }
 
-      // If it's an ADD and the entry doesn't exist yet
-      if (dn != null && !alreadyExist)
+      if (changeType == ADD && !entryAlreadyExist)
       {
-        final AddRequest ar = Requests.newAddRequest(lines);
+        final AddRequest ar = Requests.newAddRequest(ldifLines);
         writer.writeEntry(ar);
-        logger.debug(LocalizableMessage.raw(String.format("Entry successfully added %s in %s",
-            dn, original.getAbsolutePath())));
+        logger.debug(LocalizableMessage.raw("Entry successfully added %s in %s",
+            ldifDN, original.getAbsolutePath()));
         changeCount++;
       }
     }
@@ -840,19 +852,12 @@
       final ChangeOperationType changeType, final String... lines)
   {
     final String[] modifiedLines = new String[lines.length + 2];
-
-    int index = 0;
-    if (changeType == ChangeOperationType.MODIFY)
+    if (changeType == MODIFY)
     {
       modifiedLines[0] = "dn: " + dn;
       modifiedLines[1] = "changetype: modify";
-      index = 2;
     }
-    for (final String line : lines)
-    {
-      modifiedLines[index] = line;
-      index++;
-    }
+    System.arraycopy(lines, 0, modifiedLines, 2, lines.length);
     return modifiedLines;
   }
 
diff --git a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
index fe182ed..4fd82db 100644
--- a/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
+++ b/opendj-sdk/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/extensions/SaltedMD5PasswordStorageSchemeTestCase.java
@@ -26,20 +26,16 @@
  */
 package org.opends.server.extensions;
 
-
-
 import org.testng.annotations.Test;
 
 import org.opends.server.admin.server.AdminTestCaseUtils;
 import org.opends.server.admin.std.meta.SaltedMD5PasswordStorageSchemeCfgDefn;
 import org.opends.server.admin.std.server.SaltedMD5PasswordStorageSchemeCfg;
 import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.schema.UserPasswordSyntax;
 import org.forgerock.opendj.ldap.ByteString;
 
 import static org.testng.Assert.*;
 
-
 /**
  * A set of test cases for the salted MD5 password storage scheme.
  */
@@ -54,17 +50,12 @@
     super("cn=Salted MD5,cn=Password Storage Schemes,cn=config");
   }
 
-
-
   /**
    * Retrieves an initialized instance of this password storage scheme.
    *
    * @return  An initialized instance of this password storage scheme.
-   *
-   * @throws  Exception  If an unexpected problem occurs.
    */
-  protected PasswordStorageScheme getScheme()
-         throws Exception
+  protected PasswordStorageScheme getScheme() throws Exception
   {
     SaltedMD5PasswordStorageScheme scheme =
          new SaltedMD5PasswordStorageScheme();
@@ -83,12 +74,9 @@
 
   /**
    * Tests matching with a different salt size.
-   *
-   * @throws  Exception  If an unexpected problem occurs.
    */
   @Test
-  public void testDifferentSaltSize()
-    throws Exception {
+  public void testDifferentSaltSize() throws Exception {
     SaltedMD5PasswordStorageScheme scheme =
       new SaltedMD5PasswordStorageScheme();
 
@@ -104,4 +92,3 @@
       ByteString.valueOf("so5s1vK3oEi4uL/oVY3bqs5LRlKjgMN+u4A4bw==")));
   }
 }
-

--
Gitblit v1.10.0