From d00c43b28a6cac711412231562b74e135255d3de Mon Sep 17 00:00:00 2001
From: kenneth_suter <kenneth_suter@localhost>
Date: Thu, 12 Jul 2007 14:41:36 +0000
Subject: [PATCH] This commit addresses issue 1851 "upgrader does not handle new config entries also present in current configuration".  This issue is somewhat of a corner case but this code will allow a user to better deal with problems that might arise migrating the configuration or schema of a server.

---
 opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java              |    4 
 opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties      |   13 +
 opends/src/quicksetup/org/opends/quicksetup/util/Utils.java                     |   34 ++
 opends/src/quicksetup/org/opends/quicksetup/Constants.java                      |    6 
 opends/src/quicksetup/org/opends/quicksetup/upgrader/MigrationManager.java      |  358 +++++++++++++++++++++++++++
 opends/src/quicksetup/org/opends/quicksetup/CliUserInteraction.java             |    4 
 opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java              |  144 +---------
 opends/src/quicksetup/org/opends/quicksetup/Application.java                    |    2 
 opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java |  192 ++++++--------
 9 files changed, 523 insertions(+), 234 deletions(-)

diff --git a/opends/src/quicksetup/org/opends/quicksetup/Application.java b/opends/src/quicksetup/org/opends/quicksetup/Application.java
index bb9a906..594c160 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/Application.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/Application.java
@@ -576,7 +576,7 @@
    * a silent session this method returns null.
    * @return UserInteraction object
    */
-  protected UserInteraction userInteraction() {
+  public UserInteraction userInteraction() {
     // Note:  overridden in GuiApplication
     UserInteraction ui = null;
     if (!getUserData().isSilent()) {
diff --git a/opends/src/quicksetup/org/opends/quicksetup/CliUserInteraction.java b/opends/src/quicksetup/org/opends/quicksetup/CliUserInteraction.java
index d0021ba..516c8e7 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/CliUserInteraction.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/CliUserInteraction.java
@@ -95,9 +95,9 @@
     }
 
     println();
-    println(summary);
+    println(Utils.stripHtml(summary));
     println();
-    println(details);
+    println(Utils.stripHtml(details));
 
     String returnValue = null;
     while (returnValue == null) {
diff --git a/opends/src/quicksetup/org/opends/quicksetup/Constants.java b/opends/src/quicksetup/org/opends/quicksetup/Constants.java
index 0b31cf4..0b92672 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/Constants.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/Constants.java
@@ -45,6 +45,12 @@
   /** HTML bold close tag. */
   public static final String HTML_BOLD_CLOSE = "</b>";
 
+  /** HTML italics open tag. */
+  public static final String HTML_ITALICS_OPEN = "<i>";
+
+  /** HTML italics close tag. */
+  public static final String HTML_ITALICS_CLOSE = "</i>";
+
   /** Default dynamic name of directory manager. */
   public static final String DIRECTORY_MANAGER_DN = "cn=Directory Manager";
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
index 23444ca..9139fe0 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
+++ b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -1112,6 +1112,19 @@
   to access its contents.
 error-empty-response=ERROR:  The response value may not be an empty string
 
+error-upgrade-migration=Migration Error
+error-upgrade-migration-schema=Schema Migration Error
+error-upgrade-migration-config=Configuration Migration Error
+error-upgrade-migration-add=An attempt to add entry <b>{0}</b> to the newly upgraded \
+  server was unsuccessful.
+error-upgrade-migration-delete=An attempt to delete entry <b>{0}</b> to the newly upgraded \
+  server was unsuccessful.
+error-upgrade-migration-modify=An attempt to modify entry <b>{0}</b> to the newly upgraded \
+  server was unsuccessful.
+error-upgrade-migration-unexpected=An unexpected error occured while processing entry \
+  <b>{0}</b>.
+error-upgrade-migration-note=You can cancel this upgrade altogether, continue anyway or retry this operation.  If you cancel the server will be restored to the state it was in before the upgrade was attempted.  If you continue you should be aware that the server may not configured as it was before this upgrade.  A copy of the original installation files will be kept in <i>{0}</i>.
+
 #
 # Install Status: messages displayed in the offline quick setup
 # if server is already installed.
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java b/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java
index 57a3bf5..c467196 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java
@@ -307,7 +307,7 @@
    * step from <code>step</code>
    */
   public boolean canGoForward(WizardStep step) {
-    return getNextWizardStep(step) != null;
+    return !step.isProgressStep() && getNextWizardStep(step) != null;
   }
 
   /**
@@ -595,7 +595,7 @@
   /**
    * {@inheritDoc}
    */
-  protected UserInteraction userInteraction() {
+  public UserInteraction userInteraction() {
     UserInteraction ui = null;
     if (!getUserData().isSilent()) {
       if (Utils.isCli()) {
diff --git a/opends/src/quicksetup/org/opends/quicksetup/upgrader/MigrationManager.java b/opends/src/quicksetup/org/opends/quicksetup/upgrader/MigrationManager.java
new file mode 100644
index 0000000..e3c3410
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/upgrader/MigrationManager.java
@@ -0,0 +1,358 @@
+/*
+ * 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.quicksetup.upgrader;
+
+import org.opends.quicksetup.ApplicationException;
+import org.opends.quicksetup.Installation;
+import org.opends.quicksetup.UserInteraction;
+import org.opends.quicksetup.Constants;
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.util.ExternalTools;
+import org.opends.quicksetup.util.Utils;
+import org.opends.quicksetup.util.OperationOutput;
+import org.opends.quicksetup.util.InProcessServerController;
+import org.opends.server.util.LDIFReader;
+import org.opends.server.util.ChangeRecordEntry;
+import org.opends.server.types.LDIFImportConfig;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This class handles migration of both schema and configuration
+ * for an installation that is in the process of being upgraded.
+ *
+ * This class is intented to be used in two differnt stages of the
+ * upgrade process:  first, before installation's filesystem bits
+ * have been upgraded, a call to both {@link #calculateConfigCustomizations()}
+ * and {@link #calculateSchemaCustomizations()} should be made in
+ * order to capture what changes will need to be made to the server
+ * later on.  Then once the filesystem bit have been upgraded calls to
+ * {@link #migrateConfiguration()} and {@link #migrateSchema()} are
+ * made to actually perform the migration.
+ */
+public class MigrationManager {
+
+  static private final Logger LOG =
+          Logger.getLogger(MigrationManager.class.getName());
+
+  /** Describes a particular component to be migrated. */
+  private enum Component { SCHEMA, CONFIGURATION }
+
+  private Installation installation;
+  private File backupDir;
+  private UserInteraction ui;
+
+  /**
+   * Creates a new parameterized instance.
+   * @param installation describing the file layout of the installation
+   *        to be migrated
+   * @param backupDir directory where diffs between the base configuration
+   *        and schema are to be stored
+   * @param ui user interaction allowing this class to prompt the user
+   *        for feedback if necessary.  This object can be null in which
+   *        case this class will throw an exception rather than prompt
+   *        the user for more information if necessary.
+   */
+  public MigrationManager(Installation installation, File backupDir,
+                          UserInteraction ui)
+  {
+    if (installation == null) {
+      throw new NullPointerException("installation cannot be null");
+    }
+    if (backupDir == null) {
+      throw new NullPointerException("backup directory cannot be null");
+    }
+    this.installation = installation;
+    this.backupDir = backupDir;
+    this.ui = ui;
+  }
+
+  /**
+   * Diffs the current and base schema for the
+   * <code>Installation</code> associated with this class and
+   * generates a diff file that can later be used to migrate
+   * an upgraded server.
+   *
+   * @throws ApplicationException if there is a problem performing
+   *         the diff operation
+   */
+  public void calculateSchemaCustomizations() throws ApplicationException {
+    if (installation.getStatus().schemaHasBeenModified()) {
+      LOG.log(Level.INFO, "Schema contains customizations that will " +
+              "be migrated");
+      try {
+        ldifDiff(installation.getBaseSchemaFile(),
+                installation.getSchemaConcatFile(),
+                getCustomSchemaDiffFile());
+      } catch (ApplicationException ae) {
+        throw ae;
+      } catch (Exception e) {
+        throw ApplicationException.createFileSystemException(
+                getMsg("error-determining-custom-schema"), e);
+      }
+    } else {
+      LOG.log(Level.INFO, "No schema customizations to migrate");
+    }
+  }
+
+  /**
+   * Diffs the current and base configuration for the
+   * <code>Installation</code> associated with this class and
+   * generates a diff file that can later be used to migrate
+   * an upgraded server.
+   *
+   * @throws ApplicationException if there is a problem performing
+   *         the diff operation
+   */
+  public void calculateConfigCustomizations() throws ApplicationException {
+    try {
+      if (installation.getCurrentConfiguration().hasBeenModified()) {
+        LOG.log(Level.INFO, "Configuration contains customizations that will " +
+                "be migrated");
+        try {
+          ldifDiff(installation.getBaseConfigurationFile(),
+                  installation.getCurrentConfigurationFile(),
+                  getCustomConfigDiffFile());
+        } catch (ApplicationException ae) {
+          throw ae;
+        } catch (Exception e) {
+          throw ApplicationException.createFileSystemException(
+                  getMsg("error-determining-custom-config"), e);
+        }
+      } else {
+        LOG.log(Level.INFO, "No configuration customizations to migrate");
+      }
+    } catch (IOException e) {
+      throw ApplicationException.createFileSystemException(
+              getMsg("error-determining-custom-config"), e);
+    }
+  }
+
+  /**
+   * Migrates a configuration using the diff file generated by a call
+   * to {@link MigrationManager#calculateConfigCustomizations()}.
+   * @throws ApplicationException if there is an error migrating the
+   *         configuration
+   */
+  public void migrateConfiguration() throws ApplicationException {
+    try {
+      File configDiff = getCustomConfigDiffFile();
+      if (configDiff.exists()) {
+        modify(configDiff, Component.CONFIGURATION);
+      }
+    } catch (ApplicationException ae) {
+      throw ae;
+    } catch (Exception e) {
+      String msg = getMsg("error-applying-custom-config");
+      LOG.log(Level.INFO, msg, e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              msg, e);
+    }
+  }
+
+  /**
+   * Migrates a schema using the diff file generated by a call
+   * to {@link MigrationManager#calculateSchemaCustomizations()}.
+   * @throws ApplicationException if there is an error migrating the
+   *         schema
+   */
+  public void migrateSchema() throws ApplicationException {
+    try {
+      File schemaDiff = getCustomSchemaDiffFile();
+      if (schemaDiff.exists()) {
+        modify(schemaDiff, Component.SCHEMA);
+      }
+    } catch (ApplicationException ae) {
+      throw ae;
+    } catch (Exception e) {
+      String msg = getMsg("error-applying-custom-schema");
+      LOG.log(Level.INFO, msg, e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              msg, e);
+    }
+  }
+
+  /**
+   * Returns a value to indicate whether the installation associated
+   * with this class contains schema customizations.  A call to
+   * {@link #calculateSchemaCustomizations()} must first be made in
+   * order for this value to be valid.
+   *
+   * @return boolean where true indicates schema customization
+   */
+  public boolean isSchemaCustomized() {
+    return installation.getStatus().schemaHasBeenModified();
+  }
+
+  /**
+   * Returns a value to indicate whether the installation associated
+   * with this class contains configuration customizations.  A call to
+   * {@link #calculateConfigCustomizations()} must first be made in
+   * order for this value to be valid.
+   *
+   * @return boolean where true indicates schema customization
+   * @throws java.io.IOException if there was a problem reading the
+   *         current configuration file.
+   */
+  public boolean isConfigurationCustomized() throws IOException {
+    return installation.getCurrentConfiguration().hasBeenModified();
+  }
+
+  /**
+   * Applies modifications contained in an LDIF file to the server.
+   *
+   * @param ldifFile LDIF file to apply
+   * @param component being modified
+   * @throws Exception if something goes wrong. This may be an
+   *         ApplicationException if the user cancels the application
+   *         altogether or an LDIFException or IOException should other
+   *         problems occur.
+   */
+  private void modify(File ldifFile, Component component)
+          throws Exception {
+    InProcessServerController ipsc =
+            new InProcessServerController(installation);
+    LDIFImportConfig importCfg =
+            new LDIFImportConfig(
+                    Utils.getPath(ldifFile));
+    LDIFReader ldifReader =
+            new LDIFReader(importCfg);
+    ChangeRecordEntry cre = ldifReader.readChangeRecord(false);
+    while (cre != null) {
+      try {
+        ipsc.modify(cre);
+        cre = ldifReader.readChangeRecord(false);
+      } catch (Exception e) {
+        if (ui != null) {
+          String cancel = getMsg("cancel-button-label");
+          String cont = getMsg("continue-button-label");
+          String retry = getMsg("retry-button-label");
+          Object r = ui.confirm(
+                  getModificationErrorSummary(component),
+                  getModificationErrorMessage(cre),
+                  e.getLocalizedMessage(),
+                  getMsg("error-upgrade-migration"),
+                  UserInteraction.MessageType.ERROR,
+                  new String[]{cancel, cont, retry},
+                  cancel, null);
+          if (cont.equals(r)) {
+            cre = ldifReader.readChangeRecord(false);
+          } else if (retry.equals(r)) {
+            // do nothing; will retry;
+          } else {
+            throw new ApplicationException(ApplicationException.Type.CANCEL,
+                    getMsg("upgrade-canceled"), e);
+          }
+        } else {
+          throw e;
+        }
+      }
+    }
+  }
+
+  private String getModificationErrorSummary(Component c) {
+    String summary;
+    switch(c) {
+      case SCHEMA:
+        summary = getMsg("error-upgrade-migration-schema");
+        break;
+      case CONFIGURATION:
+        summary = getMsg("error-upgrade-migration-config");
+        break;
+      default:
+        summary = "";
+    }
+    return summary;
+  }
+
+  private String getModificationErrorMessage(ChangeRecordEntry cre) {
+    StringBuilder msg = new StringBuilder();
+    msg.append(Constants.HTML_LINE_BREAK);
+    if (cre != null) {
+      switch (cre.getChangeOperationType()) {
+        case MODIFY:
+          msg.append(getMsg("error-upgrade-migration-modify",
+                  cre.getDN().toNormalizedString()));
+          break;
+        case ADD:
+          msg.append(getMsg("error-upgrade-migration-add",
+                  cre.getDN().toNormalizedString()));
+          break;
+        case DELETE:
+          msg.append(getMsg("error-upgrade-migration-delete",
+                  cre.getDN().toNormalizedString()));
+          break;
+        default:
+          LOG.log(Level.INFO, "Unexpected change operation type " +
+                cre.getChangeOperationType());
+          msg.append(getMsg("error-upgrade-migration-unexpected",
+                  cre.getDN().toNormalizedString()));
+          break;
+      }
+    }
+    msg.append(Constants.HTML_LINE_BREAK);
+    msg.append(Constants.HTML_LINE_BREAK);
+    msg.append(getMsg("error-upgrade-migration-note",
+            Utils.getPath(backupDir)));
+    return msg.toString();
+  }
+
+  private void ldifDiff(File source, File target, File output)
+          throws ApplicationException, IOException, InterruptedException {
+    ExternalTools et = new ExternalTools(installation);
+    String[] args = new String[]{
+            "-o", Utils.getPath(output),
+            "-O",
+    };
+    OperationOutput oo = et.ldifDiff(source, target, args);
+    int ret = oo.getReturnCode();
+    if (ret != 0) {
+      throw new ApplicationException(
+              ApplicationException.Type.TOOL_ERROR,
+              getMsg("error-ldif-diff-tool-return-code",
+                      Integer.toString(ret)),
+              null);
+    }
+  }
+
+  private File getCustomConfigDiffFile() throws IOException {
+    return new File(backupDir, "config.custom.diff");
+  }
+
+  private File getCustomSchemaDiffFile() throws IOException {
+    return new File(backupDir, "schema.custom.diff");
+  }
+
+  static private String getMsg(String key, String... args) {
+    return ResourceProvider.getInstance().getMsg(key, args);
+  }
+
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java b/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
index 2aa9b35..a54bcac 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -81,11 +81,13 @@
 import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+
 /**
  * QuickSetup application of upgrading the bits of an installation of
  * OpenDS.
  */
 public class Upgrader extends GuiApplication implements CliApplication {
+
   /**
    * Steps during the upgrade process.
    */
@@ -770,12 +772,15 @@
 
       checkAbort();
 
-      boolean schemaCustomizationPresent;
+      MigrationManager migration =
+              new MigrationManager(getInstallation(),
+                      getUpgradeBackupDirectory(),
+                      userInteraction());
       try {
         LOG.log(Level.INFO, "checking for schema customizations");
         setCurrentProgressStep(
                 UpgradeProgressStep.CALCULATING_SCHEMA_CUSTOMIZATIONS);
-        schemaCustomizationPresent = calculateSchemaCustomizations();
+        migration.calculateSchemaCustomizations();
         notifyListeners(formatter.getFormattedDone() +
                 formatter.getLineBreak());
         LOG.log(Level.INFO, "check for schema customizations finished");
@@ -788,12 +793,11 @@
 
       checkAbort();
 
-      boolean configCustimizationPresent;
       try {
         LOG.log(Level.INFO, "checking for config customizations");
         setCurrentProgressStep(
                 UpgradeProgressStep.CALCULATING_CONFIGURATION_CUSTOMIZATIONS);
-        configCustimizationPresent = calculateConfigCustomizations();
+        migration.calculateConfigCustomizations();
         notifyListeners(formatter.getFormattedDone() +
                 formatter.getLineBreak());
         LOG.log(Level.INFO, "check for config customizations finished");
@@ -865,10 +869,11 @@
       //*  the server to be started 'in process'.
       // *******************************************
       LOG.log(Level.INFO, "schema customization " +
-              (schemaCustomizationPresent ? "":"not ") + "present");
+              (migration.isSchemaCustomized() ? "":"not ") + "present");
       LOG.log(Level.INFO, "config customization " +
-              (configCustimizationPresent ? "":"not ") + "present");
-      if (schemaCustomizationPresent || configCustimizationPresent) {
+              (migration.isConfigurationCustomized() ? "":"not ") + "present");
+      if (migration.isSchemaCustomized() ||
+              migration.isConfigurationCustomized()) {
         try {
           LOG.log(Level.INFO, "starting server");
           setCurrentProgressStep(
@@ -892,12 +897,12 @@
 
         checkAbort();
 
-        if (schemaCustomizationPresent) {
+        if (migration.isSchemaCustomized()) {
           try {
-            LOG.log(Level.INFO, "applying schema customizatoin");
+            LOG.log(Level.INFO, "Applying schema customizations");
             setCurrentProgressStep(
                     UpgradeProgressStep.APPLYING_SCHEMA_CUSTOMIZATIONS);
-            applySchemaCustomizations();
+            migration.migrateSchema();
             notifyListeners(formatter.getFormattedDone() +
                     formatter.getLineBreak());
             LOG.log(Level.INFO, "custom schema application finished");
@@ -912,12 +917,12 @@
 
         checkAbort();
 
-        if (configCustimizationPresent) {
+        if (migration.isConfigurationCustomized()) {
           try {
-            LOG.log(Level.INFO, "applying config customizatoin");
+            LOG.log(Level.INFO, "Applying config customizations");
             setCurrentProgressStep(
                     UpgradeProgressStep.APPLYING_CONFIGURATION_CUSTOMIZATIONS);
-            applyConfigurationCustomizations();
+            migration.migrateConfiguration();
             notifyListeners(formatter.getFormattedDone() +
                     formatter.getLineBreak());
             LOG.log(Level.INFO, "custom config application finished");
@@ -1078,6 +1083,8 @@
       // to be an error.
       if (ae.getType() != ApplicationException.Type.CANCEL) {
         this.runError = ae;
+      } else {
+        this.abort = true;
       }
 
     } catch (Throwable t) {
@@ -1272,40 +1279,8 @@
 
   }
 
-  private void applyConfigurationCustomizations() throws ApplicationException {
-    try {
-      File configDiff = getCustomConfigDiffFile();
-      if (configDiff.exists()) {
-        new InProcessServerController(
-                getInstallation()).modify(configDiff);
 
-      }
-    } catch (ApplicationException ae) {
-      throw ae;
-    } catch (Exception e) {
-      String msg = getMsg("error-applying-custom-config");
-      LOG.log(Level.INFO, msg, e);
-      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
-              msg, e);
-    }
-  }
 
-  private void applySchemaCustomizations() throws ApplicationException {
-    try {
-      File schemaDiff = getCustomSchemaDiffFile();
-      if (schemaDiff.exists()) {
-        new InProcessServerController(
-                getInstallation()).modify(schemaDiff);
-      }
-    } catch (ApplicationException ae) {
-      throw ae;
-    } catch (Exception e) {
-      String msg = getMsg("error-applying-custom-schema");
-      LOG.log(Level.INFO, msg, e);
-      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
-              msg, e);
-    }
-  }
 
   private Long writeInitialHistoricalRecord(
           BuildInformation fromVersion,
@@ -1316,7 +1291,8 @@
       HistoricalLog log =
               new HistoricalLog(getInstallation().getHistoryLogFile());
       id = log.append(fromVersion, toVersion,
-              HistoricalRecord.Status.STARTED, null);
+              HistoricalRecord.Status.STARTED,
+              "log file '" + QuickSetupLog.getLogFile().getPath() + "'");
     } catch (IOException e) {
       String msg = getMsg("error-logging-operation");
       throw ApplicationException.createFileSystemException(
@@ -1393,74 +1369,6 @@
     fm.synchronize(oldConfigDir, newConfigDir, filter);
   }
 
-  private boolean calculateConfigCustomizations() throws ApplicationException {
-    boolean isCustom = false;
-    try {
-      if (getInstallation().getCurrentConfiguration().hasBeenModified()) {
-        isCustom = true;
-        LOG.log(Level.INFO, "Configuration contains customizations that will " +
-                "be migrated");
-        try {
-          ldifDiff(getInstallation().getBaseConfigurationFile(),
-                  getInstallation().getCurrentConfigurationFile(),
-                  getCustomConfigDiffFile());
-        } catch (ApplicationException ae) {
-          throw ae;
-        } catch (Exception e) {
-          throw ApplicationException.createFileSystemException(
-                  getMsg("error-determining-custom-config"), e);
-        }
-      } else {
-        LOG.log(Level.INFO, "No configuration customizations to migrate");
-      }
-    } catch (IOException e) {
-      throw ApplicationException.createFileSystemException(
-              getMsg("error-determining-custom-config"), e);
-    }
-    return isCustom;
-  }
-
-  private void ldifDiff(File source, File target, File output)
-          throws ApplicationException, IOException, InterruptedException {
-    ExternalTools et = new ExternalTools(getInstallation());
-    String[] args = new String[]{
-            "-o", Utils.getPath(output),
-            "-O",
-    };
-    OperationOutput oo = et.ldifDiff(source, target, args);
-    int ret = oo.getReturnCode();
-    if (ret != 0) {
-      throw new ApplicationException(
-              ApplicationException.Type.TOOL_ERROR,
-              getMsg("error-ldif-diff-tool-return-code",
-                      Integer.toString(ret)),
-              null);
-    }
-  }
-
-
-  private boolean calculateSchemaCustomizations() throws ApplicationException {
-    boolean isCustom = false;
-    if (getInstallation().getStatus().schemaHasBeenModified()) {
-      isCustom = true;
-      LOG.log(Level.INFO, "Schema contains customizations that will " +
-              "be migrated");
-      try {
-        ldifDiff(getInstallation().getBaseSchemaFile(),
-                getInstallation().getSchemaConcatFile(),
-                getCustomSchemaDiffFile());
-      } catch (ApplicationException ae) {
-        throw ae;
-      } catch (Exception e) {
-        throw ApplicationException.createFileSystemException(
-                getMsg("error-determining-custom-schema"), e);
-      }
-    } else {
-      LOG.log(Level.INFO, "No schema customizations to migrate");
-    }
-    return isCustom;
-  }
-
   private void backupFilesytem() throws ApplicationException {
     try {
       File filesBackupDirectory = getFilesBackupDirectory();
@@ -1733,14 +1641,6 @@
     return backupDirectory;
   }
 
-  private File getCustomConfigDiffFile() throws IOException {
-    return new File(getUpgradeBackupDirectory(), "config.custom.diff");
-  }
-
-  private File getCustomSchemaDiffFile() throws IOException {
-    return new File(getUpgradeBackupDirectory(), "schema.custom.diff");
-  }
-
   private BuildInformation getCurrentBuildInformation() {
     if (this.currentVersion == null) {
       try {
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java b/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
index 6863f20..eb6dd0c 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
@@ -38,7 +38,6 @@
 import org.opends.server.loggers.AccessLogger;
 import org.opends.server.types.Modification;
 import org.opends.server.types.ResultCode;
-import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.ByteStringFactory;
 import org.opends.server.types.ByteString;
 import org.opends.server.types.InitializationException;
@@ -48,7 +47,6 @@
 import org.opends.server.api.ErrorLogPublisher;
 import org.opends.server.api.AccessLogPublisher;
 import org.opends.server.util.LDIFException;
-import org.opends.server.util.LDIFReader;
 import org.opends.server.util.ModifyChangeRecordEntry;
 import org.opends.server.util.ChangeRecordEntry;
 import org.opends.server.util.AddChangeRecordEntry;
@@ -64,7 +62,6 @@
 import java.util.logging.Level;
 import java.util.List;
 import java.util.ArrayList;
-import java.io.File;
 import java.io.IOException;
 
 /**
@@ -361,113 +358,100 @@
   /**
    * Applies modifications contained in an LDIF file to the server.
    *
-   * @param ldifFile LDIF file to apply
+   * @param cre changes to apply to the directory data
    * @throws IOException if there is an IO Error
    * @throws LDIFException if there is an LDIF error
    * @throws ApplicationException if there is an application specific error
    */
-  public void modify(File ldifFile)
-          throws IOException, LDIFException,
-          ApplicationException {
-    try {
-      InternalClientConnection cc =
-              InternalClientConnection.getRootConnection();
-      LDIFImportConfig importCfg =
-              new LDIFImportConfig(
-                      Utils.getPath(ldifFile));
-      LDIFReader ldifReader =
-              new LDIFReader(importCfg);
-      ChangeRecordEntry cre;
-      while (null != (cre = ldifReader.readChangeRecord(false))) {
-        ByteString dnByteString =
-                ByteStringFactory.create(
-                        cre.getDN().toString());
-        ResultCode rc;
-        switch(cre.getChangeOperationType()) {
-        case MODIFY:
-          LOG.log(Level.INFO, "proparing to modify " + dnByteString);
-          ModifyChangeRecordEntry mcre =
-                  (ModifyChangeRecordEntry) cre;
-          ModifyOperation op =
-                  cc.processModify(dnByteString, mcre.getModifications());
-          rc = op.getResultCode();
-          if (rc.equals(ResultCode.
-                  SUCCESS)) {
-            LOG.log(Level.INFO, "processed server modification " +
-                            modListToString(op.getModifications()));
-          } else if (rc.equals(
-                  ResultCode.
-                          ATTRIBUTE_OR_VALUE_EXISTS)) {
-            // ignore this error
-            LOG.log(Level.INFO, "ignoring attribute that already exists: " +
-                    modListToString(op.getModifications()));
-          } else if (rc.equals(ResultCode.NO_SUCH_ATTRIBUTE)) {
-            // This can happen if for instance the old configuration was
-            // changed so that the value of an attribute matches the default
-            // value of the attribute in the new configuration.
-            // Just log it and move on.
-            LOG.log(Level.INFO, "Ignoring attribute not found: " +
-                    modListToString(op.getModifications()));
-          } else {
-            // report the error to the user
-            StringBuilder error = op.getErrorMessage();
-            throw new ApplicationException(
-                    ApplicationException.Type.IMPORT_ERROR,
-                    getMsg("error-apply-ldif-modify", dnByteString.toString(),
-                            error != null ? error.toString() : ""),
-                    null);
-          }
-          break;
-        case ADD:
-          LOG.log(Level.INFO, "proparing to add " + dnByteString);
-          AddChangeRecordEntry acre = (AddChangeRecordEntry) cre;
-          List<Attribute> attrs = acre.getAttributes();
-          ArrayList<RawAttribute> rawAttrs =
-                  new ArrayList<RawAttribute>(attrs.size());
-          for (Attribute a : attrs) {
-            rawAttrs.add(new LDAPAttribute(a));
-          }
-          AddOperation addOp = cc.processAdd(dnByteString, rawAttrs);
-          rc = addOp.getResultCode();
-          if (rc.equals(ResultCode.SUCCESS)) {
-            LOG.log(Level.INFO, "processed server add " + addOp.getEntryDN());
-          } else {
-            // report the error to the user
-            StringBuilder error = addOp.getErrorMessage();
-            throw new ApplicationException(
-                    ApplicationException.Type.IMPORT_ERROR,
-                    getMsg("error-apply-ldif-add", dnByteString.toString(),
-                            error != null ? error.toString() : ""),
-                    null);
-          }
-          break;
-        case DELETE:
-          LOG.log(Level.INFO, "proparing to delete " + dnByteString);
-          DeleteOperation delOp = cc.processDelete(dnByteString);
-          rc = delOp.getResultCode();
-          if (rc.equals(ResultCode.SUCCESS)) {
-            LOG.log(Level.INFO, "processed server delete " +
-                    delOp.getEntryDN());
-          } else {
-            // report the error to the user
-            StringBuilder error = delOp.getErrorMessage();
-            throw new ApplicationException(
-                    ApplicationException.Type.IMPORT_ERROR,
-                    getMsg("error-apply-ldif-delete", dnByteString.toString(),
-                            error != null ? error.toString() : ""),
-                    null);
-          }
-          break;
-        default:
-          LOG.log(Level.SEVERE, "Unexpected record type " + cre.getClass());
-          throw new ApplicationException(ApplicationException.Type.BUG,
-                  getMsg("bug-msg"),
+  public void modify(ChangeRecordEntry cre)
+          throws IOException, LDIFException, ApplicationException
+  {
+    InternalClientConnection cc =
+            InternalClientConnection.getRootConnection();
+    ByteString dnByteString =
+            ByteStringFactory.create(
+                    cre.getDN().toString());
+    ResultCode rc;
+    switch (cre.getChangeOperationType()) {
+      case MODIFY:
+        LOG.log(Level.INFO, "proparing to modify " + dnByteString);
+        ModifyChangeRecordEntry mcre =
+                (ModifyChangeRecordEntry) cre;
+        ModifyOperation op =
+                cc.processModify(dnByteString, mcre.getModifications());
+        rc = op.getResultCode();
+        if (rc.equals(ResultCode.
+                SUCCESS)) {
+          LOG.log(Level.INFO, "processed server modification " +
+                  modListToString(op.getModifications()));
+        } else if (rc.equals(
+                ResultCode.
+                        ATTRIBUTE_OR_VALUE_EXISTS)) {
+          // ignore this error
+          LOG.log(Level.INFO, "ignoring attribute that already exists: " +
+                  modListToString(op.getModifications()));
+        } else if (rc.equals(ResultCode.NO_SUCH_ATTRIBUTE)) {
+          // This can happen if for instance the old configuration was
+          // changed so that the value of an attribute matches the default
+          // value of the attribute in the new configuration.
+          // Just log it and move on.
+          LOG.log(Level.INFO, "Ignoring attribute not found: " +
+                  modListToString(op.getModifications()));
+        } else {
+          // report the error to the user
+          StringBuilder error = op.getErrorMessage();
+          throw new ApplicationException(
+                  ApplicationException.Type.IMPORT_ERROR,
+                  getMsg("error-apply-ldif-modify", dnByteString.toString(),
+                          error != null ? error.toString() : ""),
                   null);
         }
-      }
-    } catch (Throwable t) {
-      throw new ApplicationException(ApplicationException.Type.BUG,
-              getMsg("bug-msg"), t);
+        break;
+      case ADD:
+        LOG.log(Level.INFO, "preparing to add " + dnByteString);
+        AddChangeRecordEntry acre = (AddChangeRecordEntry) cre;
+        List<Attribute> attrs = acre.getAttributes();
+        ArrayList<RawAttribute> rawAttrs =
+                new ArrayList<RawAttribute>(attrs.size());
+        for (Attribute a : attrs) {
+          rawAttrs.add(new LDAPAttribute(a));
+        }
+        AddOperation addOp = cc.processAdd(dnByteString, rawAttrs);
+        rc = addOp.getResultCode();
+        if (rc.equals(ResultCode.SUCCESS)) {
+          LOG.log(Level.INFO, "processed server add " + addOp.getEntryDN());
+        } else {
+          // report the error to the user
+          StringBuilder error = addOp.getErrorMessage();
+          throw new ApplicationException(
+                  ApplicationException.Type.IMPORT_ERROR,
+                  getMsg("error-apply-ldif-add", dnByteString.toString(),
+                          error != null ? error.toString() : ""),
+                  null);
+        }
+        break;
+      case DELETE:
+        LOG.log(Level.INFO, "preparing to delete " + dnByteString);
+        DeleteOperation delOp = cc.processDelete(dnByteString);
+        rc = delOp.getResultCode();
+        if (rc.equals(ResultCode.SUCCESS)) {
+          LOG.log(Level.INFO, "processed server delete " +
+                  delOp.getEntryDN());
+        } else {
+          // report the error to the user
+          StringBuilder error = delOp.getErrorMessage();
+          throw new ApplicationException(
+                  ApplicationException.Type.IMPORT_ERROR,
+                  getMsg("error-apply-ldif-delete", dnByteString.toString(),
+                          error != null ? error.toString() : ""),
+                  null);
+        }
+        break;
+      default:
+        LOG.log(Level.SEVERE, "Unexpected record type " + cre.getClass());
+        throw new ApplicationException(ApplicationException.Type.BUG,
+                getMsg("bug-msg"),
+                null);
     }
   }
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
index 5e0ae68..c69dab6 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -1419,9 +1419,18 @@
     if (len <= 0)
       return d;
     if (len > maxll) {
-      int p = d.lastIndexOf(' ', maxll);
-      if (p <= 0)
-        p = d.indexOf(' ', maxll);
+      int p = d.lastIndexOf(Constants.HTML_LINE_BREAK, maxll);
+      if (p > 0 && p < len) {
+        return d.substring(0, p + Constants.HTML_LINE_BREAK.length()) +
+               breakHtmlString(
+                       d.substring(p + Constants.HTML_LINE_BREAK.length()),
+                       maxll);
+      } else {
+        p = d.lastIndexOf(' ', maxll);
+        if (p <= 0) {
+          p = d.indexOf(' ', maxll);
+        }
+      }
       if (p > 0 && p < len) {
         return d.substring(0, p) +
                 Constants.HTML_LINE_BREAK +
@@ -1435,6 +1444,25 @@
   }
 
   /**
+   * Strips any potential HTML markup from a given string.
+   * @param s string to strip
+   * @return resulting string
+   */
+  static public String stripHtml(String s) {
+    String o = null;
+    if (s != null) {
+
+      // This is not a comprehensive solution but addresses
+      // the few tags that we have in Resources.properties
+      // at the moment.  See test class for cases that might
+      // cause problems.
+      o = s.replaceAll("\\<.*?\\>","");
+
+    }
+    return o;
+  }
+
+  /**
    * Tests a text string to see if it contains HTML.
    * @param text String to test
    * @return true if the string contains HTML

--
Gitblit v1.10.0