From 04ead8f1c81d759108686bbd4add4b9eee542c2e Mon Sep 17 00:00:00 2001
From: kenneth_suter <kenneth_suter@localhost>
Date: Wed, 11 Apr 2007 18:51:40 +0000
Subject: [PATCH] During schema and configuration upgrade, the server is started 'in process' without any connection handlers and the changes are made using an internal connection to the server.  During configuration/schema updates:

---
 opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java                |   97 +++++
 opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties            |    9 
 opends/src/quicksetup/org/opends/quicksetup/util/ZipExtractor.java                    |   44 --
 opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java               |    5 
 opends/src/quicksetup/org/opends/quicksetup/util/Utils.java                           |   69 ++++
 opends/src/quicksetup/org/opends/quicksetup/Installation.java                         |    4 
 opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java |    2 
 opends/src/quicksetup/org/opends/quicksetup/util/FileManager.java                     |  110 ++++++
 opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java                    |  569 +++++++++++++++++++++++++---------
 opends/src/quicksetup/org/opends/quicksetup/Application.java                          |   24 +
 10 files changed, 706 insertions(+), 227 deletions(-)

diff --git a/opends/src/quicksetup/org/opends/quicksetup/Application.java b/opends/src/quicksetup/org/opends/quicksetup/Application.java
index 93fc59a..b0420e6 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/Application.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/Application.java
@@ -33,6 +33,7 @@
 import org.opends.quicksetup.i18n.ResourceProvider;
 import org.opends.quicksetup.util.Utils;
 import org.opends.quicksetup.util.ProgressMessageFormatter;
+import org.opends.quicksetup.util.ServerController;
 import org.opends.quicksetup.ui.QuickSetupDialog;
 import org.opends.quicksetup.ui.QuickSetupStepPanel;
 import org.opends.quicksetup.ui.FramePanel;
@@ -110,6 +111,8 @@
 
   private Installation installation;
 
+  private ServerController serverController;
+
   /** Formats progress messages. */
   protected ProgressMessageFormatter formatter;
 
@@ -190,6 +193,25 @@
   }
 
   /**
+   * Sets the application's installation.
+   * @param installation describing the application's OpenDS installation
+   */
+  protected void setInstallation(Installation installation) {
+    this.installation = installation;
+  }
+
+  /**
+   * Gets a server controller for use by this application.
+   * @return ServerController that can be used to start and stop the server.
+   */
+  public ServerController getServerController() {
+    if (serverController == null) {
+      serverController = new ServerController(this);
+    }
+    return serverController;
+  }
+
+  /**
    * Returns the UserData object representing the parameters provided by
    * the user to do the installation.
    *
@@ -281,7 +303,7 @@
    * @param args the arguments to be passed to generate the resulting value.
    * @return the value associated to the key in the properties file.
    */
-  public String getMsg(String key, String[] args)
+  public String getMsg(String key, String... args)
   {
     return getI18n().getMsg(key, args);
   }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/Installation.java b/opends/src/quicksetup/org/opends/quicksetup/Installation.java
index 35f8a8b..f12c1cd 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/Installation.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/Installation.java
@@ -311,7 +311,7 @@
    */
   public File getBaseSchemaFile() throws QuickSetupException {
     return new File(getConfigurationUpgradeDirectory(),
-                  "config/upgrade/schema.ldif." + getSvnRev().toString());
+                  "schema.ldif." + getSvnRev().toString());
   }
 
   /**
@@ -471,7 +471,7 @@
   public File createHistoryBackupDirectory() throws IOException {
     File backupDirectory =
             new File(getHistoryDirectory(),
-                    "upgrade-" + System.currentTimeMillis());
+                     Long.toString(System.currentTimeMillis()));
     if (backupDirectory.exists()) {
       backupDirectory.delete();
     }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
index 74f6b0f..28672c7 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
@@ -115,6 +115,8 @@
           getRatio(InstallProgressStep.CONFIGURING_SERVER));
       notifyListeners(getTaskSeparator());
 
+      setInstallation(new Installation(getUserData().getServerLocation()));
+
       status = InstallProgressStep.CONFIGURING_SERVER;
       configureServer();
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
index 0f787e9..b0feaf7 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
+++ b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -588,7 +588,7 @@
 summary-upgrade-backing-up-files=Backing Up Files...
 summary-upgrade-calculating-schema-customization=Calculating Schema \
   Customizations...
-summary-upgrade-calculating-config-customization=Calculating Configuration\
+summary-upgrade-calculating-config-customization=Calculating Configuration \
   Customizations...
 summary-upgrade-upgrading-components=Upgrading Components...
 summary-upgrade-applying-schema-customization=Applying Schema \
@@ -597,7 +597,8 @@
   Customizations...
 summary-upgrade-verifying=Verifying Upgrade...
 summary-upgrade-history=Recording Upgrade History...
-summary-upgrade-cleanup=Cleanup...
+summary-upgrade-cleanup=Cleaning Up...
+summary-upgrade-abort=Aborting Upgrade Due to Error...
 summary-upgrade-finished-successfully=Upgrade Finished Successfully
 summary-upgrade-finished-with-errors=Upgrade Finished with Errors
 
@@ -701,3 +702,7 @@
   server, install the new server, and manually migrate your data.
 upgrade-hypothetical-versions-the-same=This operation is unnecessary.  Both \
   new current and proposed version numbers are the same: {0}
+upgrade-mod-no-schema=Processed server modifications \
+  (schema checking disabled): {0}
+upgrade-mod=Processed server modifications: {0}
+upgrade-mod-ignore=Attribute or value already exists: {0}
\ No newline at end of file
diff --git a/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java b/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java
index 7831319..3ea00eb 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java
@@ -77,9 +77,10 @@
    */
   public boolean isSupported() {
     boolean supported;
-    if (newVersion == currentVersion) {
+    if (// newVersion.equals(currentVersion) || // support this for reinstall?
+        newVersion < 1565) {
       supported = false;
-    } else {
+    }else {
       supported = true;
     }
     return supported;
diff --git a/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java b/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
index a6ce096..500ac5f 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -36,6 +36,12 @@
 import org.opends.quicksetup.ui.QuickSetupStepPanel;
 import org.opends.server.tools.BackUpDB;
 import org.opends.server.tools.LDIFDiff;
+import org.opends.server.util.*;
+import org.opends.server.types.*;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.DirectoryServer;
 
 import java.awt.event.WindowEvent;
 import java.util.*;
@@ -51,7 +57,9 @@
  */
 public class Upgrader extends Application implements CliApplication {
 
-  /** Steps in the Upgrade wizard. */
+  /**
+   * Steps in the Upgrade wizard.
+   */
   enum UpgradeWizardStep implements WizardStep {
 
     WELCOME("welcome-step"),
@@ -76,7 +84,9 @@
     }
   }
 
-  /** Steps during the upgrade process. */
+  /**
+   * Steps during the upgrade process.
+   */
   enum UpgradeProgressStep implements ProgressStep {
 
     NOT_STARTED("summary-upgrade-not-started"),
@@ -85,16 +95,16 @@
 
     STOPPING_SERVER("summary-stopping"),
 
-    BACKING_UP_DATABASES("summary-upgrade-backing-up-db"),
-
-    BACKING_UP_FILESYSTEM("summary-upgrade-backing-up-files"),
-
     CALCULATING_SCHEMA_CUSTOMIZATIONS(
             "summary-upgrade-calculating-schema-customization"),
 
     CALCULATING_CONFIGURATION_CUSTOMIZATIONS(
             "summary-upgrade-calculating-config-customization"),
 
+    BACKING_UP_DATABASES("summary-upgrade-backing-up-db"),
+
+    BACKING_UP_FILESYSTEM("summary-upgrade-backing-up-files"),
+
     UPGRADING_COMPONENTS("summary-upgrade-upgrading-components"),
 
     APPLYING_SCHEMA_CUSTOMIZATIONS(
@@ -109,6 +119,8 @@
 
     CLEANUP("summary-upgrade-cleanup"),
 
+    ABORT("summary-upgrade-abort"),
+
     FINISHED_WITH_ERRORS("summary-upgrade-finished-with-errors"),
 
     FINISHED("summary-upgrade-finished-successfully");
@@ -121,6 +133,7 @@
 
     /**
      * Return a key for access a summary message.
+     *
      * @return String representing key for access summary in resource bundle
      */
     public String getSummaryMesssageKey() {
@@ -147,32 +160,47 @@
 
   // Root files that will be ignored during backup
   static private final String[] ROOT_FILES_TO_IGNORE_DURING_BACKUP = {
-    CHANGELOG_PATH_RELATIVE, // changelogDb
-    DATABASES_PATH_RELATIVE, // db
-    LOGS_PATH_RELATIVE, // logs
-    LOCKS_PATH_RELATIVE, // locks
-    HISTORY_PATH_RELATIVE // history
+          CHANGELOG_PATH_RELATIVE, // changelogDb
+          DATABASES_PATH_RELATIVE, // db
+          LOGS_PATH_RELATIVE, // logs
+          LOCKS_PATH_RELATIVE, // locks
+          HISTORY_PATH_RELATIVE // history
   };
 
   private ProgressStep currentProgressStep = UpgradeProgressStep.NOT_STARTED;
 
-  /** Assigned if an exception occurs during run(). */
+  /**
+   * Assigned if an exception occurs during run().
+   */
   private ApplicationException runException = null;
 
-  /** Helps with CLI specific tasks. */
+  /**
+   * Helps with CLI specific tasks.
+   */
   private UpgraderCliHelper cliHelper = null;
 
-  /** Directory where we keep files temporarily. */
+  /**
+   * Directory where we keep files temporarily.
+   */
   private File stagingDirectory = null;
 
-  /** Directory where backup is kept in case the upgrade needs reversion. */
+  /**
+   * Directory where backup is kept in case the upgrade needs reversion.
+   */
   private File backupDirectory = null;
 
-  /** ID that uniquely identifieds this invocation of the Upgrader in the
+  /**
+   * ID that uniquely identifieds this invocation of the Upgrader in the
    * historical logs.
    */
   private Long historicalOperationId;
 
+  /** SVN rev number of the current build. */
+  private Integer currentVersion = null;
+
+  /** SVN rev number of the build in the stage directory. */
+  private Integer stagedVersion = null;
+
   /**
    * {@inheritDoc}
    */
@@ -214,7 +242,7 @@
    * {@inheritDoc}
    */
   public Integer getRatio(ProgressStep step) {
-    return 100 * ((UpgradeProgressStep)step).ordinal() /
+    return 100 * ((UpgradeProgressStep) step).ordinal() /
             EnumSet.allOf(UpgradeWizardStep.class).size();
   }
 
@@ -222,7 +250,7 @@
    * {@inheritDoc}
    */
   public String getSummary(ProgressStep step) {
-    return getMsg(((UpgradeProgressStep)step).getSummaryMesssageKey());
+    return getMsg(((UpgradeProgressStep) step).getSummaryMesssageKey());
   }
 
   /**
@@ -278,8 +306,7 @@
    * {@inheritDoc}
    */
   protected void updateUserData(WizardStep cStep, QuickSetup qs)
-          throws UserDataException
-  {
+          throws UserDataException {
   }
 
   /**
@@ -319,17 +346,11 @@
     // Reset exception just in case this application is rerun
     // for some reason
     runException = null;
-    Integer fromVersion = null;
-    Integer toVersion = null;
 
     try {
       try {
         setCurrentProgressStep(UpgradeProgressStep.INITIALIZING);
         initialize();
-        fromVersion = getStagedInstallation().getSvnRev();
-        toVersion = getInstallation().getSvnRev();
-        this.historicalOperationId =
-                writeInitialHistoricalRecord(fromVersion, toVersion);
       } catch (ApplicationException e) {
         LOG.log(Level.INFO, "error initializing upgrader", e);
         throw e;
@@ -346,6 +367,25 @@
       }
 
       try {
+        setCurrentProgressStep(
+                UpgradeProgressStep.CALCULATING_SCHEMA_CUSTOMIZATIONS);
+        calculateSchemaCustomizations();
+      } catch (ApplicationException e) {
+        LOG.log(Level.INFO, "error calculating schema customizations", e);
+        throw e;
+      }
+
+      try {
+        setCurrentProgressStep(
+                UpgradeProgressStep.CALCULATING_CONFIGURATION_CUSTOMIZATIONS);
+        calculateConfigCustomizations();
+      } catch (ApplicationException e) {
+        LOG.log(Level.INFO,
+                "error calculating config customizations", e);
+        throw e;
+      }
+
+      try {
         setCurrentProgressStep(UpgradeProgressStep.BACKING_UP_DATABASES);
         backupDatabases();
       } catch (ApplicationException e) {
@@ -361,28 +401,9 @@
         throw e;
       }
 
-        try {
-          setCurrentProgressStep(
-              UpgradeProgressStep.CALCULATING_SCHEMA_CUSTOMIZATIONS);
-          calculateSchemaCustomizations();
-        } catch (ApplicationException e) {
-          LOG.log(Level.INFO, "error calculating schema customizations", e);
-          throw e;
-        }
-
-        try {
-          setCurrentProgressStep(
-              UpgradeProgressStep.CALCULATING_CONFIGURATION_CUSTOMIZATIONS);
-          calculateConfigCustomizations();
-        } catch (ApplicationException e) {
-          LOG.log(Level.INFO,
-                  "error calculating config customizations", e);
-          throw e;
-        }
-
       try {
         setCurrentProgressStep(
-            UpgradeProgressStep.UPGRADING_COMPONENTS);
+                UpgradeProgressStep.UPGRADING_COMPONENTS);
         upgradeComponents();
       } catch (ApplicationException e) {
         LOG.log(Level.INFO,
@@ -390,16 +411,42 @@
         throw e;
       }
 
-//      setCurrentProgressStep(
-//              UpgradeProgressStep.APPLYING_SCHEMA_CUSTOMIZATIONS);
-//      sleepFor1();
-//      setCurrentProgressStep(
-//              UpgradeProgressStep.APPLYING_CONFIGURATION_CUSTOMIZATIONS);
-//      sleepFor1();
-//      setCurrentProgressStep(UpgradeProgressStep.VERIFYING);
-//      sleepFor1();
+      try {
+        setCurrentProgressStep(
+                UpgradeProgressStep.APPLYING_SCHEMA_CUSTOMIZATIONS);
+        applySchemaCustomizations();
+      } catch (ApplicationException e) {
+        LOG.log(Level.INFO,
+                "error applying schema customizations", e);
+        throw e;
+      }
 
+      try {
+        setCurrentProgressStep(
+                UpgradeProgressStep.APPLYING_CONFIGURATION_CUSTOMIZATIONS);
+        applyConfigurationCustomizations();
+      } catch (ApplicationException e) {
+        LOG.log(Level.INFO,
+                "error applying configuration customizations", e);
+        throw e;
+      }
 
+      if ("true".equals(
+              System.getProperty(
+                      "org.opends.upgrader.Upgrader.CreateError.CreateError")))
+      {
+        throw new ApplicationException(
+                null, "ARTIFICIAL ERROR FOR TESTING ABORT PROCESS", null);
+      }
+
+      try {
+        setCurrentProgressStep(UpgradeProgressStep.VERIFYING);
+        verifyUpgrade();
+      } catch (ApplicationException e) {
+        LOG.log(Level.INFO,
+                "error verifying upgrade", e);
+        throw e;
+      }
 
     } catch (ApplicationException ae) {
       this.runException = ae;
@@ -410,11 +457,6 @@
                       t);
     } finally {
       try {
-        setCurrentProgressStep(UpgradeProgressStep.CLEANUP);
-        cleanup();
-
-        // Write a record in the log file indicating success/failure
-        setCurrentProgressStep(UpgradeProgressStep.RECORDING_HISTORY);
         HistoricalRecord.Status status;
         String note = null;
         if (runException == null) {
@@ -422,16 +464,29 @@
         } else {
           status = HistoricalRecord.Status.FAILURE;
           note = runException.getLocalizedMessage();
+
+          // Abort the upgrade and put things back like we found it
+          ProgressStep lastProgressStep = getCurrentProgressStep();
+          setCurrentProgressStep(UpgradeProgressStep.ABORT);
+          abort(lastProgressStep);
         }
+
+        setCurrentProgressStep(UpgradeProgressStep.CLEANUP);
+        cleanup();
+
+        // Write a record in the log file indicating success/failure
+        setCurrentProgressStep(UpgradeProgressStep.RECORDING_HISTORY);
         writeHistoricalRecord(historicalOperationId,
-                fromVersion,
-                toVersion,
+                getCurrentVersion(),
+                getStagedVersion(),
                 status,
                 note);
 
       } catch (ApplicationException e) {
         System.err.print("error cleaning up after upgrade: " +
                 e.getLocalizedMessage());
+      } finally {
+
       }
     }
 
@@ -440,19 +495,213 @@
       setCurrentProgressStep(UpgradeProgressStep.FINISHED);
     } else {
       setCurrentProgressStep(UpgradeProgressStep.FINISHED_WITH_ERRORS);
+      notifyListeners(runException.getLocalizedMessage() +
+              formatter.getLineBreak());
     }
 
   }
 
+  /**
+   * Abort this upgrade and repair the installation.
+   *
+   * @param lastStep ProgressStep indicating how much work we will have to
+   *                 do to get the installation back like we left it
+   * @throws ApplicationException of something goes wrong
+   */
+  private void abort(ProgressStep lastStep) throws ApplicationException {
+    UpgradeProgressStep lastUpgradeStep = (UpgradeProgressStep) lastStep;
+    EnumSet<UpgradeProgressStep> stepsStarted =
+            EnumSet.range(UpgradeProgressStep.INITIALIZING, lastUpgradeStep);
+
+    if (stepsStarted.contains(UpgradeProgressStep.BACKING_UP_FILESYSTEM)) {
+
+      // Files were copied from the stage directory to the current
+      // directory.  Repair things by overwriting file in the
+      // root with those that were copied to the backup directory
+      // during backupFiles()
+
+      File root = getInstallation().getRootDirectory();
+      File backupDirectory;
+      try {
+        backupDirectory = getFilesBackupDirectory();
+        FileManager fm = new FileManager(this);
+        for (String fileName : backupDirectory.list()) {
+          File f = new File(backupDirectory, fileName);
+
+          // Do our best to restore the filesystem like
+          // we found it.  Just report potential problems
+          // to the user.
+          try {
+            fm.move(f, root, null);
+          } catch (Throwable t) {
+            notifyListeners("The following could not be restored after the" +
+                    "failed upgrade attempt.  You should restore this " +
+                    "file/directory manually: " + f + " to " + root);
+          }
+        }
+        fm.deleteRecursively(backupDirectory);
+      } catch (IOException e) {
+        LOG.log(Level.INFO, "error getting backup directory", e);
+      }
+    }
+
+
+  }
+
+  private void verifyUpgrade() throws ApplicationException {
+    try {
+      new ServerController(this).startServer();
+    } catch (QuickSetupException e) {
+      LOG.log(Level.INFO, "error starting server", e);
+    }
+  }
+
+  private void applyConfigurationCustomizations() throws ApplicationException {
+    try {
+      File configDiff = getCustomConfigDiffFile();
+      if (configDiff.exists()) {
+        applyCustomizationLdifFile(configDiff);
+      }
+    } catch (IOException e) {
+      LOG.log(Level.INFO, "error getting schema diff file", e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              "error applying configuration customization", e);
+    } catch (LDIFException e) {
+      LOG.log(Level.INFO, "error reading change record", e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              "error applying configuration customization", e);
+    }
+  }
+
+  private void applySchemaCustomizations() throws ApplicationException {
+    try {
+      File schemaDiff = getCustomSchemaDiffFile();
+      if (schemaDiff.exists()) {
+        applyCustomizationLdifFile(schemaDiff);
+      }
+    } catch (IOException e) {
+      LOG.log(Level.INFO, "error getting schema diff file", e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              "error applying schema customization", e);
+    } catch (LDIFException e) {
+      LOG.log(Level.INFO, "error reading change record", e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              "error applying schema customization", e);
+    }
+  }
+
+  private void startServerWithoutConnectionHandlers()
+          throws ApplicationException {
+    try {
+      ServerController control = new ServerController(this);
+      if (getInstallation().getStatus().isServerRunning()) {
+        control.stopServer();
+      }
+      control.startServerInProcess(true);
+    } catch (IOException e) {
+      LOG.log(Level.INFO, "could not determine server state", e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              "error trying to determine server state", e);
+    } catch (InitializationException e) {
+      LOG.log(Level.INFO, "could not start server", e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              "could not start server with handlers", e);
+    } catch (ConfigException e) {
+      LOG.log(Level.INFO, "configuration error starting server", e);
+      throw new ApplicationException(ApplicationException.Type.IMPORT_ERROR,
+              "configuration error starting server", e);
+    }
+  }
+
+  private void applyCustomizationLdifFile(File ldifFile)
+          throws IOException, LDIFException, ApplicationException {
+    try {
+      startServerWithoutConnectionHandlers();
+      InternalClientConnection cc =
+              InternalClientConnection.getRootConnection();
+      LDIFImportConfig importCfg =
+              new LDIFImportConfig(Utils.getPath(ldifFile));
+      LDIFReader ldifReader = new LDIFReader(importCfg);
+      ChangeRecordEntry cre;
+      while (null != (cre = ldifReader.readChangeRecord(false))) {
+        if (cre instanceof ModifyChangeRecordEntry) {
+          ModifyChangeRecordEntry mcre = (ModifyChangeRecordEntry) cre;
+          ByteString dnByteString =
+                  ByteStringFactory.create(mcre.getDN().toString());
+          ModifyOperation op =
+                  cc.processModify(dnByteString, mcre.getModifications());
+          ResultCode rc = op.getResultCode();
+          if (rc.equals(ResultCode.OBJECTCLASS_VIOLATION)) {
+            // try again without schema checking
+            DirectoryServer.setCheckSchema(false);
+            op = cc.processModify(dnByteString, mcre.getModifications());
+            rc = op.getResultCode();
+          }
+          if (rc.equals(ResultCode.SUCCESS)) {
+            if (DirectoryServer.checkSchema()) {
+              notifyListeners(
+                      getMsg("upgrade-mod",
+                              modListToString(op.getModifications()))
+                      + formatter.getLineBreak());
+            } else {
+              notifyListeners(
+                      getMsg("upgrade-mod-no-schema",
+                              modListToString(op.getModifications()))
+                      + formatter.getLineBreak());
+              DirectoryServer.setCheckSchema(true);
+            }
+          } else if (rc.equals(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS)) {
+            // ignore this error
+            notifyListeners(
+                    getMsg("upgrade-mod-ignore",
+                            modListToString(op.getModifications()))
+                    + formatter.getLineBreak());
+          } else {
+            // report the error to the user
+            StringBuilder error = op.getErrorMessage();
+            if (error != null) {
+              throw new ApplicationException(
+                      ApplicationException.Type.IMPORT_ERROR,
+                      "error processing custom configuration "
+                              + error.toString(),
+                      null);
+            }
+          }
+        } else {
+          throw new ApplicationException(
+                  ApplicationException.Type.IMPORT_ERROR,
+                  "unexpected change record type " + cre.getClass(),
+                  null);
+        }
+      }
+    } catch (Throwable t) {
+      // t.printStackTrace(System.out);
+      throw new ApplicationException(ApplicationException.Type.BUG,
+              t.getMessage(), t);
+    } finally {
+      getServerController().stopServerInProcess();
+    }
+  }
+
+  private String modListToString(List<Modification> modifications) {
+    StringBuilder modsMsg = new StringBuilder();
+    for(int i = 0; i < modifications.size(); i++) {
+      modsMsg.append(modifications.get(i).toString());
+      if (i < modifications.size() - 1) {
+        modsMsg.append(" ");
+      }
+    }
+    return modsMsg.toString();
+  }
+
   private Long writeInitialHistoricalRecord(
           Integer fromVersion,
           Integer toVersion)
-          throws ApplicationException
-  {
+          throws ApplicationException {
     Long id;
     try {
       HistoricalLog log =
-            new HistoricalLog(getInstallation().getHistoryLogFile());
+              new HistoricalLog(getInstallation().getHistoryLogFile());
       id = log.append(fromVersion, toVersion,
               HistoricalRecord.Status.STARTED, null);
     } catch (IOException e) {
@@ -471,15 +720,8 @@
           throws ApplicationException {
     try {
       HistoricalLog log =
-            new HistoricalLog(getInstallation().getHistoryLogFile());
+              new HistoricalLog(getInstallation().getHistoryLogFile());
       log.append(id, from, to, status, note);
-
-      // FOR TESTING
-      List<HistoricalRecord> records = log.getRecords();
-      for(HistoricalRecord record : records) {
-        System.out.println(record);
-      }
-
     } catch (IOException e) {
       throw ApplicationException.createFileSystemException(
               "error logging operation", e);
@@ -493,7 +735,9 @@
       FileManager fm = new FileManager(this);
       for (String fileName : stageDir.list()) {
         File f = new File(stageDir, fileName);
-        fm.copyRecursively(f, root, new UpgradeFileFilter(stageDir));
+        fm.copyRecursively(f, root,
+                new UpgradeFileFilter(stageDir),
+                /*overwrite=*/true);
       }
     } catch (IOException e) {
       throw ApplicationException.createFileSystemException(
@@ -503,47 +747,20 @@
 
   private void calculateConfigCustomizations() throws ApplicationException {
     try {
-    if (getInstallation().getCurrentConfiguration().hasBeenModified()) {
-
-      try {
-        List<String> args = new ArrayList<String>();
-
-        args.add("-s"); // source LDIF
-        args.add(getInstallation().getCurrentConfigurationFile().
-                getCanonicalPath());
-
-        args.add("-t"); // target LDIF
-        args.add(getInstallation().getBaseConfigurationFile().
-                getCanonicalPath());
-
-        args.add("-o"); // output LDIF
-        args.add(getCustomConfigDiffFile().
-                getCanonicalPath());
-
-        // TODO i18n
-        notifyListeners("Diff'ing configuration with base configuration...");
-
-        int ret = LDIFDiff.mainDiff(args.toArray(new String[]{}), false);
-        if (ret != 0) {
-          StringBuffer msg = new StringBuffer()
-                  .append("'ldif-diff' tool returned error code ")
-                  .append(ret)
-                  .append(" when invoked with args :")
-                  .append(Utils.listToString(args, " "));
+      if (getInstallation().getCurrentConfiguration().hasBeenModified()) {
+        try {
+          ldifDiff(getInstallation().getBaseConfigurationFile(),
+                   getInstallation().getCurrentConfigurationFile(),
+                   getCustomConfigDiffFile());
+        } catch (Exception e) {
           throw ApplicationException.createFileSystemException(
-                  msg.toString(), null);
-        } else {
-          notifyListeners(formatter.getFormattedDone());
+                  "error determining configuration customizations", e);
         }
-      } catch (Exception e) {
-        throw ApplicationException.createFileSystemException(
-                "error determining configuration customizations", e);
+      } else {
+        // TODO i18n
+        notifyListeners("No configuration customizations to migrate" +
+                formatter.getLineBreak());
       }
-    } else {
-      // TODO i18n
-      notifyListeners("No configuration customizations to migrate" +
-                      formatter.getLineBreak());
-    }
     } catch (IOException e) {
       // TODO i18n
       throw ApplicationException.createFileSystemException(
@@ -551,44 +768,52 @@
     }
   }
 
+  private void ldifDiff(File source, File target, File output)
+          throws ApplicationException {
+    List<String> args = new ArrayList<String>();
+
+    args.add("-s"); // source LDIF
+    args.add(Utils.getPath(source));
+
+    args.add("-t"); // target LDIF
+    args.add(Utils.getPath(target));
+
+    args.add("-o"); // output LDIF
+    args.add(Utils.getPath(output));
+
+    args.add("-O"); // overwrite
+    args.add("-S"); // single-value changes
+
+    // TODO i18n
+    notifyListeners(formatter.getFormattedWithPoints("Diff'ing " +
+            Utils.getPath(source) + " with " +
+            Utils.getPath(target)));
+
+    int ret = LDIFDiff.mainDiff(args.toArray(new String[]{}), false);
+    if (ret != 0) {
+      StringBuffer sb = new StringBuffer()
+              .append("'ldif-diff' tool returned error code ")
+              .append(ret)
+              .append(" when invoked with args: ")
+              .append(Utils.listToString(args, " "));
+      notifyListeners(formatter.getLineBreak());
+      throw ApplicationException.createFileSystemException(sb.toString(),
+              null);
+    } else {
+      notifyListeners(formatter.getFormattedDone() + formatter.getLineBreak());
+    }
+  }
+
   private void calculateSchemaCustomizations() throws ApplicationException {
     if (getInstallation().getStatus().schemaHasBeenModified()) {
 
       // TODO i18n
       notifyListeners(
-              "Schema contains customizations and needs to be migrated");
-
+              "Schema contains customizations and needs to be migrated\n");
       try {
-        List<String> args = new ArrayList<String>();
-
-        args.add("-s"); // source LDIF
-        args.add(getInstallation().getSchemaConcatFile().
-                getCanonicalPath());
-
-        args.add("-t"); // target LDIF
-        args.add(getInstallation().getBaseSchemaFile().
-                getCanonicalPath());
-
-        args.add("-o"); // output LDIF
-        args.add(getCustomSchemaDiffFile().
-                getCanonicalPath());
-
-        // TODO i18n
-        notifyListeners("Diff'ing schema with base schema...");
-
-        int ret = LDIFDiff.mainDiff(args.toArray(new String[]{}), false);
-        if (ret != 0) {
-          StringBuffer sb = new StringBuffer()
-                  .append("'ldif-diff' tool returned error code ")
-                  .append(ret)
-                  .append(" when invoked with args: ")
-                  .append(Utils.listToString(args, " "));
-          throw ApplicationException.createFileSystemException(sb.toString(),
-                  null);
-        } else {
-          notifyListeners(formatter.getFormattedDone());
-        }
-
+        ldifDiff(getInstallation().getBaseSchemaFile(),
+                 getInstallation().getSchemaConcatFile(),
+                 getCustomSchemaDiffFile());
       } catch (Exception e) {
         throw ApplicationException.createFileSystemException(
                 "error determining schema customizations", e);
@@ -596,7 +821,7 @@
     } else {
       // TODO i18n
       notifyListeners("No schema customizations to migrate" +
-          formatter.getLineBreak());
+              formatter.getLineBreak());
     }
   }
 
@@ -605,10 +830,11 @@
       File filesBackupDirectory = getFilesBackupDirectory();
       FileManager fm = new FileManager(this);
       File root = getInstallation().getRootDirectory();
+      FileFilter filter = new UpgradeFileFilter(root);
       for (String fileName : root.list()) {
         File f = new File(root, fileName);
-        fm.copyRecursively(f, filesBackupDirectory,
-                new UpgradeFileFilter(root));
+        //fm.copyRecursively(f, filesBackupDirectory,
+        fm.move(f, filesBackupDirectory, filter);
       }
     } catch (Exception e) {
       throw new ApplicationException(
@@ -657,12 +883,16 @@
     try {
       stagingDir = getStageDirectory();
       FileManager fm = new FileManager(this);
+
+      // doing this seems to work betterh than just plain
+      // old delete
       fm.deleteRecursively(stagingDir);
+
     } catch (IOException e) {
       // TODO i18n
       throw ApplicationException.createFileSystemException(
               "error attempting to clean up tmp directory " +
-              stagingDir != null ? stagingDir.getName() : "null",
+                      stagingDir != null ? stagingDir.getName() : "null",
               e);
     }
   }
@@ -670,7 +900,14 @@
   private void initialize() throws ApplicationException {
     try {
       expandZipFile();
+
+      Integer fromVersion = getStagedVersion();
+      Integer toVersion = getCurrentVersion();
+      this.historicalOperationId =
+              writeInitialHistoricalRecord(fromVersion, toVersion);
+
       insureUpgradability();
+
     } catch (Exception e) {
       throw new ApplicationException(
               ApplicationException.Type.FILE_SYSTEM_ERROR,
@@ -713,14 +950,12 @@
   }
 
   private Installation getStagedInstallation()
-          throws IOException, ApplicationException
-  {
+          throws IOException, ApplicationException {
     return new Installation(getStageDirectory());
   }
 
   private void expandZipFile()
-          throws ApplicationException, IOException, QuickSetupException
-  {
+          throws ApplicationException, IOException, QuickSetupException {
     File installPackage = getUpgradeUserData().getInstallPackage();
     FileInputStream fis = new FileInputStream(installPackage);
     ZipExtractor extractor = new ZipExtractor(fis,
@@ -746,8 +981,7 @@
    * {@inheritDoc}
    */
   public UserData createUserData(String[] args, CurrentInstallStatus cis)
-          throws UserDataException
-  {
+          throws UserDataException {
     return getCliHelper().createUserData(args, cis);
   }
 
@@ -776,8 +1010,7 @@
   }
 
   private File getStageDirectory()
-          throws ApplicationException, IOException
-  {
+          throws ApplicationException, IOException {
     if (stagingDirectory == null) {
       File tmpDir = getTempDirectory();
       stagingDirectory =
@@ -793,7 +1026,7 @@
   }
 
   private UpgradeUserData getUpgradeUserData() {
-    return (UpgradeUserData)getUserData();
+    return (UpgradeUserData) getUserData();
   }
 
   private File getFilesBackupDirectory() throws IOException {
@@ -821,6 +1054,30 @@
     return new File(getUpgradeBackupDirectory(), "schema.custom.diff");
   }
 
+  private Integer getCurrentVersion() {
+    if (this.currentVersion == null) {
+      try {
+        currentVersion = getInstallation().getSvnRev();
+      } catch (QuickSetupException e) {
+        LOG.log(Level.INFO, "error trying to determine current version", e);
+      }
+    }
+    return currentVersion;
+  }
+
+  private Integer getStagedVersion() {
+    if (stagedVersion == null) {
+      try {
+        stagedVersion = getStagedInstallation().getSvnRev();
+      } catch (Exception e) {
+        LOG.log(Level.INFO, "error", e);
+      }
+    }
+    return stagedVersion;
+  }
+
+
+
   /**
    * Filter defining files we want to manage in the upgrade
    * process.
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/FileManager.java b/opends/src/quicksetup/org/opends/quicksetup/util/FileManager.java
index a1d53bd..fa1d269 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/FileManager.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/FileManager.java
@@ -50,6 +50,38 @@
   }
 
   /**
+   * Move a file.
+   * @param object File to move
+   * @param newParent File representing new parent directory
+   * @param filter that will be asked whether or not the operation should be
+   *        performed
+   * @throws ApplicationException if something goes wrong
+   */
+  public void move(File object, File newParent, FileFilter filter)
+          throws ApplicationException
+  {
+    // TODO: application notification
+    if (filter == null || filter.accept(object)) {
+      new MoveOperation(object, newParent).apply();
+    }
+  }
+
+  /**
+   * Deletes a single file or directory.
+   * @param object File to delete
+   * @param filter that will be asked whether or not the operation should be
+   *        performed
+   * @throws ApplicationException if something goes wrong
+   */
+  public void delete(File object, FileFilter filter)
+          throws ApplicationException
+  {
+    if (filter == null || filter.accept(object)) {
+      new DeleteOperation(object).apply();
+    }
+  }
+
+  /**
    * Deletes everything below the specified file.
    *
    * @param file the path to be deleted.
@@ -252,16 +284,17 @@
       String[] args = {objectFile.getAbsolutePath(),
               destination.getAbsolutePath()};
 
-      // If overwriting and the destination exists then kill it
-      if (destination.exists() && overwrite) {
-        deleteRecursively(destination);
-      }
-
       if (objectFile.isDirectory()) {
         if (!destination.exists()) {
             destination.mkdirs();
         }
       } else {
+
+        // If overwriting and the destination exists then kill it
+        if (destination.exists() && overwrite) {
+          deleteRecursively(destination);
+        }
+
         if (!destination.exists()) {
           if (insureParentsExist(destination)) {
             application.notifyListeners(application.getFormattedWithPoints(
@@ -278,6 +311,18 @@
               fis.close();
               fos.close();
 
+              if (destination.exists()) {
+                // TODO:  set the file's permissions.  This is made easier in
+                // Java 1.6 but until then use the Utils methods
+                if (Utils.isUnix()) {
+                  String permissions =
+                          Utils.getFileSystemPermissions(objectFile);
+                  Utils.setPermissionsUnix(
+                          Utils.getPath(destination),
+                          permissions);
+                }
+              }
+
               application.notifyListeners(application.getFormattedDone() +
                       application.getLineBreak());
 
@@ -299,14 +344,6 @@
       }
     }
 
-    private boolean insureParentsExist(File f) {
-      File parent = f.getParentFile();
-      boolean b = parent.exists();
-      if (!b) {
-        b = parent.mkdirs();
-      }
-      return b;
-    }
   }
 
   /**
@@ -380,6 +417,53 @@
     }
   }
 
+  /**
+   * A delete operation.
+   */
+  private class MoveOperation extends FileOperation {
+
+    File destination = null;
+
+    /**
+     * Creates a delete operation.
+     * @param objectFile to delete
+     */
+    public MoveOperation(File objectFile, File newParent) {
+      super(objectFile);
+      this.destination = new File(newParent, objectFile.getName());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public FileOperation copyForChild(File child) {
+      return new MoveOperation(child, destination);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void apply() throws ApplicationException {
+      File objectFile = getObjectFile();
+      if (destination.exists()) {
+        deleteRecursively(destination);
+      }
+      if (!objectFile.renameTo(destination)) {
+        throw ApplicationException.createFileSystemException(
+                "failed to move " + objectFile + " to " + destination, null);
+      }
+    }
+  }
+
+  private boolean insureParentsExist(File f) {
+    File parent = f.getParentFile();
+    boolean b = parent.exists();
+    if (!b) {
+      b = parent.mkdirs();
+    }
+    return b;
+  }
+
   private String getMsg(String key) {
     return ResourceProvider.getInstance().getMsg(key);
   }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java b/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
index 0b917b5..7ebc621 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
@@ -29,6 +29,9 @@
 
 import org.opends.quicksetup.*;
 import org.opends.server.protocols.ldap.LDAPResultCode;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.InitializationException;
+import org.opends.server.config.ConfigException;
 
 import javax.naming.NamingException;
 import java.util.ArrayList;
@@ -181,10 +184,54 @@
   }
 
   /**
+   * Starts the directory server within this process.
+   * @param disableConnectionHandlers boolean that when true starts the
+   * the server mode that is otherwise up and running but will not accept any
+   * connections from external clients (i.e., does not create or initialize the
+   * connection handlers). This could be useful, for example, in an upgrade mode
+   * where it might be helpful to start the server but don't want it to appear
+   * externally as if the server is online without connection handlers
+   * listening.
+   *
+   * @throws  ConfigException  If there is a problem with the Directory Server
+   *                           configuration that prevents a critical component
+   *                           from being instantiated.
+   *
+   * @throws  InitializationException  If some other problem occurs while
+   *                                   attempting to initialize and start the
+   *                                   Directory Server.
+   */
+  public void startServerInProcess(boolean disableConnectionHandlers)
+          throws InitializationException, ConfigException {
+    System.setProperty(
+            "org.opends.server.DisableConnectionHandlers",
+            disableConnectionHandlers ? "true" : null);
+    startServerInProcess();
+  }
+
+  /**
+   * Stops a server that had been running 'in process'.
+   */
+  public void stopServerInProcess() {
+    DirectoryServer.shutDown(ServerController.class.getName(),
+            "quicksetup requests shutdown");
+  }
+
+  /**
    * This methods starts the server.
    * @throws org.opends.quicksetup.QuickSetupException if something goes wrong.
    */
   public void startServer() throws QuickSetupException {
+    startServer(true);
+  }
+
+  /**
+   * This methods starts the server.
+   * @param verify boolean indicating whether this method will attempt to
+   * connect to the server after starting to verify that it is listening.
+   * @throws org.opends.quicksetup.QuickSetupException if something goes wrong.
+   */
+  private void startServer(boolean verify) throws QuickSetupException {
     application.notifyListeners(
             application.getFormattedProgress(
                     application.getMsg("progress-starting")) +
@@ -235,7 +282,7 @@
       {
         throw ex;
 
-      } else
+      } else if (verify)
       {
         /*
          * There are no exceptions from the readers and they are marked as
@@ -248,17 +295,27 @@
          * Try 5 times with an interval of 1 second between try.
          */
         boolean connected = false;
+        Configuration config =
+                application.getInstallation().getCurrentConfiguration();
+        int port = config.getPort();
+        String ldapUrl = "ldap://localhost:" + port;
+
+        // See if the application has prompted for credentials.  If
+        // not we'll just try to connect anonymously.
+        String userDn = application.getUserData().getDirectoryManagerDn();
+        String userPw = application.getUserData().getDirectoryManagerPwd();
+        if (userDn == null || userPw == null) {
+          userDn = null;
+          userPw = null;
+        }
+
         for (int i=0; i<5 && !connected; i++)
         {
-          // TODO: get this information from the installation instead
-          UserData userData = application.getUserData();
-          String ldapUrl = "ldap://localhost:" + userData.getServerPort();
           try
           {
             Utils.createLdapContext(
                 ldapUrl,
-                userData.getDirectoryManagerDn(),
-                userData.getDirectoryManagerPwd(), 3000, null);
+                userDn, userPw, 3000, null);
             connected = true;
           }
           catch (NamingException ne)
@@ -277,8 +334,7 @@
         }
         if (!connected)
         {
-          String[] arg = {String.valueOf(application.getUserData().
-                  getServerPort())};
+          String[] arg = {String.valueOf(port)};
           if (Utils.isWindows())
           {
 
@@ -302,6 +358,31 @@
   }
 
   /**
+   * Starts the OpenDS server in this process.
+   *
+   * @throws  ConfigException  If there is a problem with the Directory Server
+   *                           configuration that prevents a critical component
+   *                           from being instantiated.
+   *
+   * @throws  InitializationException  If some other problem occurs while
+   *                                   attempting to initialize and start the
+   *                                   Directory Server.
+   */
+  public void startServerInProcess()
+          throws InitializationException, ConfigException
+  {
+    // Bootstrap and start the Directory Server.
+    DirectoryServer directoryServer = DirectoryServer.getInstance();
+
+    directoryServer.bootstrapServer();
+    String configClass = "org.opends.server.extensions.ConfigFileHandler";
+    String configPath = Utils.getPath(
+            application.getInstallation().getCurrentConfigurationFile());
+    directoryServer.initializeConfiguration(configClass, configPath);
+    directoryServer.startServer();
+  }
+
+  /**
    * This class is used to read the standard error and standard output of the
    * Stop process.
    * <p/>
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
index 2ac5655..92583af 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -679,6 +679,27 @@
     return p.waitFor();
   }
 
+  /**
+   * Sets the permissions of the provided paths with the provided permission
+   * String.
+   * @param path to set permissions on.
+   * @param permissions the UNIX-mode file system permission representation
+   * (for example "644" or "755")
+   * @return the return code of the chmod command.
+   * @throws IOException if something goes wrong.
+   * @throws InterruptedException if the Runtime.exec method is interrupted.
+   */
+  public static int setPermissionsUnix(String path,
+      String permissions) throws IOException, InterruptedException
+  {
+    String[] args = new String[3];
+    args[0] = "chmod";
+    args[1] = permissions;
+    args[2] = path;
+    Process p = Runtime.getRuntime().exec(args);
+    return p.waitFor();
+  }
+
   // Very limited for the moment: apply only permissions to the current user and
   // does not work in non-English environments... to work in non English we
   // should use xcalcs but it does not come in the windows default install...
@@ -1204,4 +1225,52 @@
     return sb.toString();
   }
 
+  /**
+   * Returns the file system permissions for a file.
+   * @param path the file for which we want the file permissions.
+   * @return the file system permissions for the file.
+   */
+  static public String getFileSystemPermissions(String path)
+  {
+    return getFileSystemPermissions(new File(path));
+  }
+
+  /**
+   * Returns the file system permissions for a file.
+   * @param file the file for which we want the file permissions.
+   * @return the file system permissions for the file.
+   */
+  static public String getFileSystemPermissions(File file)
+    {
+    String perm;
+    String name = file.getName();
+    if (file.getParent().endsWith(
+        File.separator + Installation.WINDOWS_BINARIES_PATH_RELATIVE) ||
+        file.getParent().endsWith(
+        File.separator + Installation.UNIX_BINARIES_PATH_RELATIVE))
+    {
+      if (name.endsWith(".bat"))
+      {
+        perm = "644";
+      }
+      else
+      {
+        perm = "755";
+      }
+    }
+    else if (name.endsWith(".sh"))
+    {
+      perm = "755";
+    } else if (name.endsWith(Installation.UNIX_SETUP_FILE_NAME) ||
+            name.endsWith(Installation.UNIX_UNINSTALL_FILE_NAME) ||
+            name.endsWith(Installation.UNIX_UPGRADE_FILE_NAME))
+    {
+      perm = "755";
+    } else
+    {
+      perm = "644";
+    }
+    return perm;
+  }
+
 }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/ZipExtractor.java b/opends/src/quicksetup/org/opends/quicksetup/util/ZipExtractor.java
index f0b8301..6219fff 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/ZipExtractor.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/ZipExtractor.java
@@ -29,12 +29,10 @@
 
 import org.opends.quicksetup.QuickSetupException;
 import org.opends.quicksetup.Application;
-import org.opends.quicksetup.Installation;
 import org.opends.quicksetup.i18n.ResourceProvider;
 
 import java.io.InputStream;
 import java.io.IOException;
-import java.io.File;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipEntry;
 import java.util.ArrayList;
@@ -228,7 +226,7 @@
         }
       } else
       {
-        String perm = getFileSystemPermissions(path);
+        String perm = Utils.getFileSystemPermissions(path);
         ArrayList<String> list = permissions.get(perm);
         if (list == null)
         {
@@ -255,44 +253,4 @@
     return "755";
   }
 
-  /**
-   * Returns the file system permissions for a file.
-   * @param path the file for which we want the file permissions.
-   * @return the file system permissions for the file.
-   */
-  private String getFileSystemPermissions(String path)
-  {
-    // TODO We should get this dynamically during build?
-    String perm;
-
-    File file = new File(path);
-    if (file.getParent().endsWith(
-        File.separator + Installation.WINDOWS_BINARIES_PATH_RELATIVE) ||
-        file.getParent().endsWith(
-        File.separator + Installation.UNIX_BINARIES_PATH_RELATIVE))
-    {
-      if (path.endsWith(".bat"))
-      {
-        perm = "644";
-      }
-      else
-      {
-        perm = "755";
-      }
-    }
-    else if (path.endsWith(".sh"))
-    {
-      perm = "755";
-    } else if (path.endsWith(Installation.UNIX_SETUP_FILE_NAME) ||
-            path.endsWith(Installation.UNIX_UNINSTALL_FILE_NAME) ||
-            path.endsWith(Installation.UNIX_UPGRADE_FILE_NAME))
-    {
-      perm = "755";
-    } else
-    {
-      perm = "644";
-    }
-    return perm;
-  }
-
 }

--
Gitblit v1.10.0