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

kenneth_suter
11.51.2007 0858489afe74eb7942935079bcd169a40e3a533a
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:

- If an 'object class violation' occurs the modification is processed again with schema turned off. This seems to be required for instance to change the port number since the value is always required to be part of the LDAP connection handler's configuration entry.

- If an 'attribute or value already exists' error is returned the situation is logged and processing continues.

10 files modified
933 ■■■■ changed files
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java 24 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Installation.java 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java 2 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties 9 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java 5 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java 569 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/FileManager.java 110 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java 97 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java 69 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ZipExtractor.java 44 ●●●●● patch | view | raw | blame | history
opendj-sdk/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);
  }
opendj-sdk/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();
    }
opendj-sdk/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();
opendj-sdk/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}
opendj-sdk/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;
opendj-sdk/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.
opendj-sdk/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);
  }
opendj-sdk/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/>
opendj-sdk/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;
  }
}
opendj-sdk/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;
  }
}