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

kenneth_suter
17.05.2007 293d6dd9da947951ac774636e97f6667ed669a18
The upgrader determines schema and configuration customization by performing an ldif-diff of the base schema and configuration files with those in the current server.  Previously the invocation of this command just used the internal LDIFDiff class to perform this work.  Given the recent discovery of problems associated with using DirectoryServer in the same process when the filesystem bits and the jars are different version, this commit externalizes the command invocation to an external process using the currently installed jars.

I have created a new class ExternalTools for managing invocation of OpenDS tools in a different process, similar to what has been done with the ServerController. In fact I have moved the backupDatabases method from ServerController to the new ExternalTools class since conceptually its not really about controlling the server.
2 files added
4 files modified
350 ■■■■■ changed files
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Installation.java 10 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java 61 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ExternalTools.java 135 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/OutputReader.java 67 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java 75 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Installation.java
@@ -202,6 +202,16 @@
  public static final String HISTORY_LOG_FILE_NAME = "log";
  /**
   * Generic name for the backup tool.
   */
  public static final String BACKUP = "backup";
  /**
   * Generic name for the ldif-diff tool.
   */
  public static final String LDIF_DIFF = "ldif-diff";
  /**
   * Performs validation on the specified file to make sure that it is
   * an actual OpenDS installation.
   * @param rootDirectory File directory candidate
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -48,6 +48,7 @@
import org.opends.quicksetup.util.ServerHealthChecker;
import org.opends.quicksetup.util.FileManager;
import org.opends.quicksetup.util.OperationOutput;
import org.opends.quicksetup.util.ExternalTools;
import org.opends.quicksetup.ui.GuiApplication;
import org.opends.quicksetup.ui.QuickSetupDialog;
import org.opends.quicksetup.ui.UIFactory;
@@ -1221,7 +1222,7 @@
      File configDiff = getCustomConfigDiffFile();
      if (configDiff.exists()) {
        new InProcessServerController(
                getInstallation()).applyCustomizationLdifFile(configDiff);
                getInstallation()).modify(configDiff);
      }
    } catch (IOException e) {
@@ -1244,7 +1245,7 @@
      File schemaDiff = getCustomSchemaDiffFile();
      if (schemaDiff.exists()) {
        new InProcessServerController(
                getInstallation()).applyCustomizationLdifFile(schemaDiff);
                getInstallation()).modify(schemaDiff);
      }
    } catch (IOException e) {
      String msg = "I/O Error applying schema customization: " +
@@ -1351,35 +1352,20 @@
  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
    LOG.log(Level.INFO, "Diff'ing " +
            Utils.getPath(source) + " with " +
            Utils.getPath(target));
    int ret = org.opends.server.tools.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);
    ExternalTools et = new ExternalTools(getInstallation());
    try {
      OperationOutput oo = et.ldifDiff(source, target, output);
      int ret = oo.getReturnCode();
      if (ret != 0) {
        throw new ApplicationException(
                ApplicationException.Type.TOOL_ERROR,
                "ldif-diff tool returned error code " + ret,
                null);
      }
    } catch (Exception e) {
      throw new ApplicationException(
              ApplicationException.Type.TOOL_ERROR,
              "Error performing determining customizations", e);
    }
  }
@@ -1424,22 +1410,21 @@
  }
  private void backupDatabases() throws ApplicationException {
    ServerController sc = getServerController();
    try {
      OperationOutput output = sc.backupDatabases(getUpgradeBackupDirectory());
      ExternalTools et = new ExternalTools(getInstallation());
      OperationOutput output = et.backup(getUpgradeBackupDirectory());
      int ret = output.getReturnCode();
      if (ret != 0) {
        StringBuffer sb = new StringBuffer()
                .append("'backup utility returned error code " + ret);
        throw new ApplicationException(
                ApplicationException.Type.FILE_SYSTEM_ERROR,
                sb.toString(), null);
                ApplicationException.Type.TOOL_ERROR,
                "backup tool returned error code " + ret,
                null);
      }
    } catch (Exception e) {
      throw new ApplicationException(
              ApplicationException.Type.TOOL_ERROR,
              "error backup up databases", e);
              "Error backing up databases", e);
    }
  }
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ExternalTools.java
New file
@@ -0,0 +1,135 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.util;
import org.opends.quicksetup.Installation;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.List;
import java.util.ArrayList;
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
 * Class for invoking OpenDS tools in external processes.
 */
public class ExternalTools {
  static private final Logger LOG =
          Logger.getLogger(ServerController.class.getName());
  private Installation installation;
  /**
   * Creates a new instance that will invoke tools from a particular
   * installation in external JVM processes.
   * @param installation representing the tools location
   */
  public ExternalTools(Installation installation) {
    this.installation = installation;
  }
  /**
   * Backs up all the databases to a specified directory.
   * @param backupDir File representing the directory where the backups will
   * be stored
   * @return OperationOutput containing information about the operation
   * @throws java.io.IOException if the process could not be started
   * @throws InterruptedException if the process was prematurely interrupted
   */
  public OperationOutput backup(File backupDir)
          throws IOException, InterruptedException {
    String toolName = Installation.BACKUP;
    List<String> args = new ArrayList<String>();
    args.add(Utils.getPath(installation.getCommandFile(toolName)));
    args.add("-a"); // backup all
    args.add("-d"); // backup to directory
    args.add(Utils.getPath(backupDir));
    return startProcess(toolName, args);
  }
  /**
   * Backs up all the databases to a specified directory.
   * @param source File representing the source data
   * @param target File representing the target data
   * @param output File representing the output data
   * @return OperationOutput containing information about the operation
   * @throws java.io.IOException if the process could not be started
   * @throws InterruptedException if the process was prematurely interrupted
   */
  public OperationOutput ldifDiff(File source, File target, File output)
          throws IOException, InterruptedException {
    String toolName = Installation.LDIF_DIFF;
    List<String> args = new ArrayList<String>();
    args.add(Utils.getPath(installation.getCommandFile(toolName)));
    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
    return startProcess(toolName, args);
  }
  private OperationOutput startProcess(final String toolName, List<String> args)
          throws IOException, InterruptedException
  {
    final OperationOutput oo = new OperationOutput();
    LOG.log(Level.INFO, "Invoking " + Utils.listToString(args, " "));
    ProcessBuilder pb = new ProcessBuilder(args);
    Process p = pb.start();
    BufferedReader out =
            new BufferedReader(new InputStreamReader(p.getErrorStream()));
    new OutputReader(out) {
      public void processLine(String line) {
        oo.addErrorMessage(line);
        LOG.log(Level.INFO, toolName + ": " + line);
      }
    };
    BufferedReader err =
            new BufferedReader(new InputStreamReader(p.getInputStream()));
    new OutputReader(err) {
      public void processLine(String line) {
        oo.addOutputMessage(line);
        LOG.log(Level.INFO, toolName + ": " + line);
      }
    };
    oo.setReturnCode(p.waitFor());
    return oo;
  }
}
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
@@ -256,7 +256,7 @@
   * @throws LDIFException if there is an LDIF error
   * @throws ApplicationException if there is an application specific error
   */
  public void applyCustomizationLdifFile(File ldifFile)
  public void modify(File ldifFile)
          throws IOException, LDIFException,
          ApplicationException {
    try {
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/OutputReader.java
New file
@@ -0,0 +1,67 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.util;
import java.io.BufferedReader;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
   * This class is used to read an input stream and process ouput.
 */
abstract public class OutputReader {
  static private Logger LOG = Logger.getLogger(OutputReader.class.getName());
  /**
   * Called whenever new input is read from the reader.
   * @param line String representing new input
   */
  public abstract void processLine(String line);
  /**
   * The protected constructor.
   *
   * @param reader  the BufferedReader of the stop process.
   */
  public OutputReader(final BufferedReader reader) {
    Thread t = new Thread(new Runnable() {
      public void run() {
        try {
          String line;
          while (null != (line = reader.readLine())) {
            processLine(line);
          }
        } catch (Throwable t) {
          LOG.log(Level.INFO, "error reading output", t);
        }
      }
    });
    t.start();
  }
}
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
@@ -40,7 +40,6 @@
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.File;
/**
 * Class used to manipulate an OpenDS server.
@@ -449,47 +448,6 @@
  }
  /**
   * Backs up all the databases to a specified directory.
   * @param backupDir File representing the directory where the backups will
   * be stored
   * @return OperationOutput containing information about the operation
   * @throws IOException if the process could not be started
   * @throws InterruptedException if the process was prematurely interrupted
   */
  public OperationOutput backupDatabases(File backupDir)
          throws IOException, InterruptedException {
    final OperationOutput output = new OperationOutput();
    List<String> args = new ArrayList<String>();
    args.add(Utils.getPath(installation.getCommandFile("backup")));
    args.add("-a"); // backup all
    args.add("-d"); // backup to directory
    args.add(Utils.getPath(backupDir));
    ProcessBuilder pb = new ProcessBuilder(args);
    Process p = pb.start();
    BufferedReader out =
            new BufferedReader(new InputStreamReader(p.getErrorStream()));
    new OutputReader(out) {
      public void processLine(String line) {
        output.addErrorMessage(line);
        LOG.log(Level.INFO, "backup operation: " + line);
      }
    };
    BufferedReader err =
            new BufferedReader(new InputStreamReader(p.getInputStream()));
    new OutputReader(err) {
      public void processLine(String line) {
        output.addOutputMessage(line);
        LOG.log(Level.INFO, "backup operation: " + line);
      }
    };
    output.setReturnCode(p.waitFor());
    return output;
  }
  /**
   * This class is used to read the standard error and standard output of the
   * Stop process.
   * <p/>
@@ -549,39 +507,6 @@
  }
  /**
   * This class is used to read an input stream and process ouput.
   */
  abstract private class OutputReader {
    /**
     * Called whenever new input is read from the reader.
     * @param line String representing new input
     */
    public abstract void processLine(String line);
    /**
     * The protected constructor.
     *
     * @param reader  the BufferedReader of the stop process.
     */
    public OutputReader(final BufferedReader reader) {
      Thread t = new Thread(new Runnable() {
        public void run() {
          try {
            String line;
            while (null != (line = reader.readLine())) {
              processLine(line);
            }
          } catch (Throwable t) {
            LOG.log(Level.INFO, "error reading output", t);
          }
        }
      });
      t.start();
    }
  }
  /**
   * Returns the Message ID indicating that the server has started.
   * @return the Message ID indicating that the server has started.
   */