From dc69513f1be2b6e00c1e7418664513299dab8548 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Fri, 17 Jun 2016 08:42:29 +0000
Subject: [PATCH] OPENDJ-3081 restore ds-cfg-csv-delimiter-char in the concatenated schema during upgrade to OpenDJ 3.5

---
 opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java      |    3 +
 opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++
 opendj-server-legacy/src/messages/org/opends/messages/tool.properties                |    5 ++
 opendj-server-legacy/src/main/java/org/opends/quicksetup/Installation.java           |    3 +
 opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeUtils.java |    5 ++
 5 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/quicksetup/Installation.java b/opendj-server-legacy/src/main/java/org/opends/quicksetup/Installation.java
index 08e178b..d69e6c3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/quicksetup/Installation.java
+++ b/opendj-server-legacy/src/main/java/org/opends/quicksetup/Installation.java
@@ -19,6 +19,7 @@
 import static com.forgerock.opendj.util.OperatingSystem.*;
 
 import static org.opends.messages.QuickSetupMessages.*;
+import static org.opends.server.util.ServerConstants.*;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -485,7 +486,7 @@
    */
   public File getSchemaConcatFile()
   {
-    return new File(getConfigurationUpgradeDirectory(), "schema.ldif.current");
+    return new File(getConfigurationUpgradeDirectory(), SCHEMA_CONCAT_FILE_NAME);
   }
 
   /**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java
index f79be75..48f3fe9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java
@@ -588,6 +588,9 @@
         deleteConfigEntry(INFO_UPGRADE_TASK_CONFIGURATION_BACKEND_NOT_CONFIGURABLE.get(),
             "dn: ds-cfg-backend-id=config,cn=Backends,cn=config"));
 
+    register("3.5.0",
+        restoreCsvDelimiterAttributeTypeInConcatenatedSchemaFile());
+
     /** All upgrades will refresh the server configuration schema and generate a new upgrade folder. */
     registerLast(
         performOEMMigrationIfNeeded(),
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java
index a68875c..e0707b5 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeTasks.java
@@ -15,6 +15,8 @@
  */
 package org.opends.server.tools.upgrade;
 
+import static java.nio.charset.StandardCharsets.*;
+import static java.nio.file.StandardOpenOption.*;
 import static javax.security.auth.callback.ConfirmationCallback.NO;
 import static javax.security.auth.callback.ConfirmationCallback.YES;
 import static javax.security.auth.callback.TextOutputCallback.*;
@@ -23,10 +25,13 @@
 import static org.opends.messages.ToolMessages.*;
 import static org.opends.server.tools.upgrade.FileManager.copy;
 import static org.opends.server.tools.upgrade.UpgradeUtils.*;
-import static org.opends.server.util.StaticUtils.isClassAvailable;
+import static org.opends.server.util.StaticUtils.*;
 
+import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileReader;
 import java.io.IOException;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -48,7 +53,14 @@
 import org.forgerock.opendj.ldap.SearchScope;
 import org.forgerock.opendj.ldap.requests.Requests;
 import org.forgerock.opendj.ldap.requests.SearchRequest;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.CoreSchema;
+import org.forgerock.opendj.ldap.schema.MatchingRule;
+import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldap.schema.SchemaBuilder;
+import org.forgerock.opendj.ldap.schema.Syntax;
 import org.forgerock.opendj.ldif.EntryReader;
+import org.forgerock.opendj.ldif.LDIFEntryReader;
 import org.opends.server.backends.pluggable.spi.TreeName;
 import org.opends.server.tools.JavaPropertiesTool;
 import org.opends.server.tools.RebuildIndex;
@@ -1374,4 +1386,94 @@
   {
     // Do nothing.
   }
+
+  /**
+   * This task exists because OpenDJ 3.0.0 added an attribute type definition for
+   * {@code ds-cfg-csv-delimiter-char}, but unfortunately trailing spaces existed after the closing
+   * parenthesis. As a consequence, this definition was not added to the concatenated schema.
+   * <p>
+   * This task restores this definition in the concatenated schema using the following algorithm:
+   * <p>
+   * If {@code ds-cfg-csv-delimiter-char} attribute type definition exists in 02-config.ldif,
+   * but not in the concatenated schema then append its definition to the concatenated schema,
+   * omitting the trailing spaces.
+   *
+   * @return The relevant upgrade task
+   * @see OPENDJ-3081
+   */
+  static UpgradeTask restoreCsvDelimiterAttributeTypeInConcatenatedSchemaFile()
+  {
+    return new AbstractUpgradeTask()
+    {
+      @Override
+      public void perform(UpgradeContext context) throws ClientException
+      {
+        final ProgressNotificationCallback pnc = new ProgressNotificationCallback(INFORMATION, getSummary(), 0);
+
+        final File configFile = new File(configSchemaDirectory, "02-config.ldif");
+        AttributeType configCsvCharAT = readCsvDelimiterCharAttributeType(configFile, context, pnc);
+        context.notifyProgress(pnc.setProgress(33));
+
+        AttributeType concatenatedCsvCharAT = readCsvDelimiterCharAttributeType(concatenatedSchemaFile, context, pnc);
+        context.notifyProgress(pnc.setProgress(66));
+
+        if (!configCsvCharAT.isPlaceHolder() && concatenatedCsvCharAT.isPlaceHolder())
+        {
+          try (BufferedWriter writer = Files.newBufferedWriter(concatenatedSchemaFile.toPath(), UTF_8, APPEND))
+          {
+            writer.append(CoreSchema.getAttributeTypesAttributeType().getNameOrOID());
+            writer.append(": ");
+            writer.append(configCsvCharAT.toString().trim());
+            writer.newLine();
+          }
+          catch (IOException e)
+          {
+            throw unexpectedException(context, pnc, INFO_UPGRADE_TASK_CANNOT_WRITE_TO_CONCATENATED_SCHEMA_FILE.get(
+                concatenatedSchemaFile.toPath(), stackTraceToSingleLineString(e)));
+          }
+        }
+        context.notifyProgress(pnc.setProgress(100));
+      }
+
+      private AttributeType readCsvDelimiterCharAttributeType(final File schemaFile,
+          final UpgradeContext context, final ProgressNotificationCallback pnc) throws ClientException
+      {
+        final Schema coreSchema = Schema.getCoreSchema();
+        try (EntryReader entryReader = new LDIFEntryReader(new FileReader(schemaFile)))
+        {
+          final Entry schemaEntry = entryReader.readEntry();
+          final SchemaBuilder builder = new SchemaBuilder();
+          for (Syntax syntax : coreSchema.getSyntaxes())
+          {
+            builder.buildSyntax(syntax).addToSchema();
+          }
+          for (MatchingRule rule : coreSchema.getMatchingRules())
+          {
+            builder.buildMatchingRule(rule).addToSchema();
+          }
+          return builder
+              .addSchema(schemaEntry, false)
+              .toSchema()
+              .asNonStrictSchema()
+              .getAttributeType("ds-cfg-csv-delimiter-char");
+        }
+        catch (IOException e)
+        {
+          throw unexpectedException(context, pnc, INFO_UPGRADE_TASK_CANNOT_READ_SCHEMA_FILE.get(
+              schemaFile.getAbsolutePath(), stackTraceToSingleLineString(e)));
+        }
+      }
+
+      private LocalizableMessage getSummary()
+      {
+        return INFO_UPGRADE_TASK_SUMMARY_RESTORE_CSV_DELIMITER_CHAR.get();
+      }
+
+      @Override
+      public String toString()
+      {
+        return getSummary().toString();
+      }
+    };
+  }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeUtils.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeUtils.java
index 09f561a..22074c4 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeUtils.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/UpgradeUtils.java
@@ -66,6 +66,7 @@
 import static org.opends.server.tools.upgrade.FileManager.*;
 import static org.opends.server.tools.upgrade.Installation.*;
 import static org.opends.server.util.ChangeOperationType.*;
+import static org.opends.server.util.ServerConstants.*;
 
 /** Common utility methods needed by the upgrade. */
 final class UpgradeUtils
@@ -76,6 +77,8 @@
   static final File configDirectory = new File(getInstancePath(), CONFIG_PATH_RELATIVE);
   /** The {@code config/schema} folder of the current instance. */
   static final File configSchemaDirectory = new File(configDirectory, SCHEMA_PATH_RELATIVE);
+  /** The {@code config/upgrade} folder of the current instance. */
+  static final File configUpgradeDirectory = new File(configDirectory, "upgrade");
   /** The {@code template} folder of the current installation. */
   private static final File templateDirectory = new File(getInstallationPath(), TEMPLATE_RELATIVE_PATH);
   /** The {@code template/config} folder of the current installation. */
@@ -93,6 +96,8 @@
   static final File batDirectory = new File(getInstallationPath(), WINDOWS_BINARIES_PATH_RELATIVE);
   /** The server configuration file path. */
   static final File configFile = new File(configDirectory, CURRENT_CONFIG_FILE_NAME);
+  /** The concatenated schema file of the current installation. */
+  static final File concatenatedSchemaFile = new File(configUpgradeDirectory, SCHEMA_CONCAT_FILE_NAME);
 
   /**
    * Returns the path of the installation of the directory server. Note that
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/tool.properties b/opendj-server-legacy/src/messages/org/opends/messages/tool.properties
index bab1bc2..d8b6308 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/tool.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/tool.properties
@@ -2565,6 +2565,11 @@
 Do you want to launch this process automatically at the end of the upgrade?
 INFO_UPGRADE_TASK_UNABLE_TO_REMOVE_OLD_JARS_10069=Unable to determine whether the file system is case sensitive. \
   If the file system is case sensitive, then remove OpenDJ.jar and all OpenDJ_*.jar before starting the upgraded server.
+INFO_UPGRADE_TASK_SUMMARY_RESTORE_CSV_DELIMITER_CHAR_10070=Restoring 'ds-cfg-delimiter-char' \
+ attribute type in concatenated schema
+INFO_UPGRADE_TASK_CANNOT_READ_SCHEMA_FILE_10071=An error occurred reading schema file %s: %s
+INFO_UPGRADE_TASK_CANNOT_WRITE_TO_CONCATENATED_SCHEMA_FILE_10072=An error occurred \
+ appending 'ds-cfg-delimiter-char' attribute type to concatenated schema file %s: %s
 
 # Strings for generated reference documentation.
 REF_SHORT_DESC_BACKUP_15000=back up OpenDJ directory data

--
Gitblit v1.10.0