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

kenneth_suter
30.31.2007 cfb5767d9216efaf0c1738b5ce1ae243630fd8f5
This commit is mainly intended to prevent the sort of false positives that occur when the upgrader assumes the server has been upgraded properly but leaves the server in a corrupt state (see issues 1546 and 1559).  The following changes are introduced:

- An additional stipulation is put on successful completion of the upgrade process: early on in the process the server is started to see if it logs and severe messages upon startup. If there are any severe messages the upgrade tool won't run. Later when the upgraded server is being verified, the messages are checked again to see if there are any severe messages. If so the upgrade is aborted and any changes are backed out. The error message are returned from startServer methods in a new class OperationOutput.

- The upgrade tool no longer allows a reversion to an older version and now checks to make sure the current version is older than the proposed version by comparing the major, minor, point, and SVN revision numbers obtained by running start-ds -F and storing the values in a new class BuildInformation.

- The choose version screen now takes web proxy host and port from that standard system properties if they are set.
9 files modified
2 files added
588 ■■■■ changed files
opends/src/quicksetup/org/opends/quicksetup/ApplicationException.java 5 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/BuildInformation.java 205 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/Installation.java 83 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties 5 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/upgrader/RemoteBuildManager.java 5 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java 36 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java 119 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/UpgraderReviewPanel.java 3 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/WelcomePanel.java 2 ●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/util/OperationOutput.java 76 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java 49 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ApplicationException.java
@@ -89,6 +89,11 @@
    APPLICATION,
    /**
     * Error invoking an OpenDS tool.
     */
    TOOL_ERROR,
    /**
     * A bug (for instance when we throw an IllegalStateException).
     */
    BUG
opends/src/quicksetup/org/opends/quicksetup/BuildInformation.java
New file
@@ -0,0 +1,205 @@
/*
 * 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 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.quicksetup;
import org.opends.quicksetup.util.Utils;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
/**
 * Represents information about the current build that is
 * publicly obtainable by invoking start-ds -F.
 */
public class BuildInformation implements Comparable {
  static private final String NAME = "Name";
  static private final String BUILD_ID = "Build ID";
  static private final String MAJOR_VERSION = "Major Version";
  static private final String MINOR_VERSION = "Minor Version";
  static private final String POINT_VERSION = "Point Version";
  static private final String REVISION_NUMBER = "Revision Number";
  /**
   * Reads build information for a particular installation by reading the
   * output from invoking the start-ds tool with the full information option.
   * @param installation from which to gather build information
   * @return BuildInformation object populated with information
   * @throws ApplicationException if all or some important information could
   * not be determined
   */
  static public BuildInformation create(Installation installation)
          throws ApplicationException {
    BuildInformation bi = new BuildInformation();
    List<String> args = new ArrayList<String>();
    args.add(Utils.getPath(installation.getServerStartCommandFile()));
    args.add("-F"); // full verbose
    ProcessBuilder pb = new ProcessBuilder(args);
    InputStream is = null;
    try {
      Process process = pb.start();
      is = process.getInputStream();
      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      String line = reader.readLine();
      bi.values.put(NAME, line);
      while (null != (line = reader.readLine())) {
        int colonIndex = line.indexOf(':');
        if (-1 != colonIndex) {
          String name = line.substring(0, colonIndex).trim();
          String value = line.substring(colonIndex + 1).trim();
          bi.values.put(name, value);
        }
      }
    } catch (IOException e) {
      throw new ApplicationException(ApplicationException.Type.START_ERROR,
              "Error creating build info", e);
    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException e) {
          // ignore;
        }
      }
    }
    // Make sure we got values for import properties
    checkNotNull(bi.values,
            NAME,
            MAJOR_VERSION,
            MINOR_VERSION,
            POINT_VERSION,
            REVISION_NUMBER);
    return bi;
  }
  private Map<String, String> values = new HashMap<String, String>();
  /**
   * Gets the name of this build.  This is the first line of the output
   * from invoking start-ds -F.
   * @return String representing the name of the build
   */
  public String getName() {
    return values.get(NAME);
  }
  /**
   * Gets the build ID which is the 14 digit number code like 20070420110336.
   *
   * @return String representing the build ID
   */
  public String getBuildId() {
    return values.get(BUILD_ID);
  }
  /**
   * Gets the major version.
   *
   * @return String representing the major version
   */
  public Integer getMajorVersion() {
    return new Integer(values.get(MAJOR_VERSION));
  }
  /**
   * Gets the minor version.
   *
   * @return String representing the minor version
   */
  public Integer getMinorVersion() {
    return new Integer(values.get(MINOR_VERSION));
  }
  /**
   * Gets the point version.
   *
   * @return String representing the point version
   */
  public Integer getPointVersion() {
    return new Integer(values.get(POINT_VERSION));
  }
  /**
   * Gets the SVN revision number.
   *
   * @return Integer representing the SVN revision number
   */
  public Integer getRevisionNumber() {
    return new Integer(values.get(REVISION_NUMBER));
  }
  /**
   * {@inheritDoc}
   */
  public String toString() {
    return getName();
  }
  /**
   * {@inheritDoc}
   */
  public int compareTo(Object o) {
    BuildInformation bi = (BuildInformation) o;
    if (getMajorVersion().equals(bi.getMajorVersion())) {
      if (getMinorVersion().equals(bi.getMinorVersion())) {
        if (getPointVersion().equals(bi.getPointVersion())) {
          if (getRevisionNumber().equals(bi.getRevisionNumber())) {
            return 0;
          } else if (getRevisionNumber() < bi.getRevisionNumber()) {
            return -1;
          }
        } else if (getPointVersion() < bi.getPointVersion()) {
          return -1;
        }
      } else if (getMinorVersion() < bi.getMinorVersion()) {
        return -1;
      }
    } else if (getMajorVersion() < bi.getMajorVersion()) {
      return -1;
    }
    return 1;
  }
  static private void checkNotNull(Map values, String... props)
          throws ApplicationException {
    for (String prop : props) {
      if (null == values.get(prop)) {
        throw new ApplicationException(ApplicationException.Type.TOOL_ERROR,
                "'" + prop + "' could not be determined", null);
      }
    }
  }
}
opends/src/quicksetup/org/opends/quicksetup/Installation.java
@@ -29,8 +29,6 @@
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.opends.quicksetup.util.Utils;
@@ -209,7 +207,9 @@
          throws IllegalArgumentException {
    // TODO:  i18n
    String failureReason = null;
    if (!rootDirectory.exists()) {
    if (rootDirectory == null) {
      failureReason = "root directory is null";
    } else if (!rootDirectory.exists()) {
      failureReason = "is not a directory";
    } else if (!rootDirectory.isDirectory()) {
      failureReason = "does not exist";
@@ -230,7 +230,7 @@
    }
    if (failureReason != null) {
      throw new IllegalArgumentException("Install root '" +
              Utils.getPath(rootDirectory) +
              (rootDirectory != null ? Utils.getPath(rootDirectory) : "null") +
              "' is not an OpenDS installation root: " +
              " " + failureReason);
    }
@@ -244,7 +244,7 @@
  private Configuration baseConfiguration;
  private String buildId;
  private BuildInformation buildInformation;
  /**
   * Creates a new instance from a root directory specified as a string.
@@ -278,14 +278,10 @@
   * Sets the root directory of this installation.
   *
   * @param rootDirectory File of this installation
   * @throws NullPointerException if root directory is null
   */
  public void setRootDirectory(File rootDirectory) throws NullPointerException {
    if (rootDirectory == null) {
      throw new NullPointerException("Install root cannot be null");
    }
  public void setRootDirectory(File rootDirectory) {
    // Hold off on doing more validation of rootDirectory since
    // Hold off on doing validation of rootDirectory since
    // some applications (like the Installer) create an Installation
    // before the actual bits have been laid down on the filesyste.
@@ -456,46 +452,6 @@
  }
  /**
   * Gets the build ID which is the 14 digit number code like 20070420110336.
   * @return String representing the build ID
   * @throws ApplicationException if something goes wrong
   */
  public String getBuildId() throws ApplicationException {
    if (buildId == null) {
      List<String> args = new ArrayList<String>();
      args.add(Utils.getPath(getServerStartCommandFile()));
      args.add("-V"); // verbose
      ProcessBuilder pb = new ProcessBuilder(args);
      InputStream is = null;
      try {
        Process process = pb.start();
        is = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        String line = null;
        Pattern p = Pattern.compile("(Build )(\\d{14})");
        while (null != (line = reader.readLine())) {
          Matcher m = p.matcher(line);
          if (m.matches()) {
            buildId = line.substring(m.start(2), m.end(2));
          }
        }
      } catch (IOException e) {
        throw new ApplicationException(ApplicationException.Type.START_ERROR,
                "Error attempting to determine build ID", e);
      } finally {
        if (is != null) {
          try {
            is.close();
          } catch (IOException e) {
            // ignore;
          }
        }
      }
    }
    return buildId;
  }
  /**
   * Returns the path to the configuration file of the directory server.  Note
   * that this method assumes that this code is being run locally.
   *
@@ -542,15 +498,6 @@
  }
  /**
   * Returns the path to the LDIF files under the install path.
   *
   * @return the path to the LDIF files under the install path.
   */
  public File geLdifDirectory() {
    return new File(getRootDirectory(), LDIFS_PATH_RELATIVE);
  }
  /**
   * Returns the path to the config files under the install path.
   *
   * @return the path to the config files under the install path.
@@ -725,4 +672,18 @@
    }
    return statusPanelCommandFile;
  }
}
  /**
   * Gets information about the build that was used to produce the bits
   * for this installation.
   * @return BuildInformation object describing this installation
   * @throws ApplicationException if there is a problem obtaining the
   * build information
   */
  public BuildInformation getBuildInformation() throws ApplicationException {
    if (buildInformation == null) {
      buildInformation = BuildInformation.create(this);
    }
    return buildInformation;
  }
}
opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -779,6 +779,7 @@
summary-upgrade-extracting=Extracting Build...
summary-upgrade-backing-up-db=Backing Up Data...
summary-upgrade-backing-up-files=Backing Up Files...
summary-upgrade-check-server-health=Checking Server Health...
summary-upgrade-calculating-schema-customization=Calculating Schema \
  Customizations...
summary-upgrade-calculating-config-customization=Calculating Configuration \
@@ -798,7 +799,7 @@
summary-upgrade-finished-successfully-cli=OpenDS QuickSetup Completed \
  Successfully.  The OpenDS installation at {0} has now been upgraded \
  to version {1}.
summary-upgrade-finished-with-errors=Upgrade Finished with Errors
summary-upgrade-finished-with-errors=Upgrade Operation Aborted
#
# Progress messages
@@ -903,7 +904,7 @@
upgrade-hypothetical-reversion-failure=Reversion from version {0} to version \
  {1} is not supported.  To revert versions you must uninstall the current \
  server, install the new server, and manually migrate your data.
upgrade-hypothetical-versions-the-same=This operation is unnecessary.  Both \
upgrade-hypothetical-versions-the-same=Both \
  new current and proposed version numbers are the same: {0}
upgrade-mod-no-schema=Processed server modifications \
  (schema checking disabled): {0}
opends/src/quicksetup/org/opends/quicksetup/upgrader/RemoteBuildManager.java
@@ -68,10 +68,13 @@
   * Creates an instance.
   * @param app using this tool
   * @param url base context for an OpenDS build list
   * @param proxy Proxy to use for connections; can be null if not proxy is
   * to be used
   */
  public RemoteBuildManager(Application app, URL url) {
  public RemoteBuildManager(Application app, URL url, Proxy proxy) {
    this.app = app;
    this.buildListUrl = url;
    this.proxy = proxy;
  }
  /**
opends/src/quicksetup/org/opends/quicksetup/upgrader/UpgradeOracle.java
@@ -28,6 +28,7 @@
package org.opends.quicksetup.upgrader;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.BuildInformation;
/**
 * This class can answer questions important upgrade/reversion questions
@@ -35,18 +36,18 @@
 */
public class UpgradeOracle {
  private Integer currentVersion;
  private Integer newVersion;
  private BuildInformation currentBuildInfo;
  private BuildInformation newBuildInfo;
  /**
   * Creates a new instance that can analyze a hypothetical upgrade/reversion
   * operation from one version to another.
   * @param currentVersion Integer representing the current version
   * @param newVersion Integer representing the proposed next version
   * @param current BuildInformation representing the current version
   * @param neu BuildInformation representing the proposed next version
   */
  public UpgradeOracle(Integer currentVersion, Integer newVersion) {
    this.currentVersion = currentVersion;
    this.newVersion = newVersion;
  public UpgradeOracle(BuildInformation current, BuildInformation neu) {
    this.currentBuildInfo = current;
    this.newBuildInfo = neu;
  }
  /**
@@ -56,7 +57,7 @@
   *         false indicates that this would be a reversion.
   */
  public boolean isUpgrade() {
    return newVersion > currentVersion;
    return currentBuildInfo.compareTo(newBuildInfo) < 0;
  }
  /**
@@ -66,7 +67,7 @@
   *         false indicates that this would be an upgrade.
   */
  public boolean isReversion() {
    return newVersion < currentVersion;
    return currentBuildInfo.compareTo(newBuildInfo) < 0;
  }
  /**
@@ -76,14 +77,7 @@
   * an operation will succeed
   */
  public boolean isSupported() {
    boolean supported;
    if (// newVersion.equals(currentVersion) || // support this for reinstall?
        newVersion < 1565) {
      supported = false;
    }else {
      supported = true;
    }
    return supported;
    return isUpgrade();
  }
  /**
@@ -95,8 +89,8 @@
   */
  public String getSummaryMessage() {
    String msg;
    String[] args = { currentVersion.toString(),
            newVersion.toString() };
    String[] args = { currentBuildInfo.toString(),
            currentBuildInfo.toString() };
    ResourceProvider rp = ResourceProvider.getInstance();
    if (isSupported()) {
      if (isUpgrade()) {
@@ -109,8 +103,10 @@
    } else {
      if (isUpgrade()) {
        msg = rp.getMsg("upgrade-hypothetical-upgrade-failure", args);
      } else {
      } else if (isReversion()) {
        msg = rp.getMsg("upgrade-hypothetical-reversion-failure", args);
      } else {
        msg = rp.getMsg("upgrade-hypothetical-versions-the-same", args);
      }
    }
    return msg;
opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -35,6 +35,7 @@
import org.opends.quicksetup.util.FileManager;
import org.opends.quicksetup.util.ServerController;
import org.opends.quicksetup.util.ZipExtractor;
import org.opends.quicksetup.util.OperationOutput;
import org.opends.quicksetup.ui.*;
import java.awt.event.WindowEvent;
@@ -44,6 +45,9 @@
import java.io.*;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.InetSocketAddress;
import static org.opends.quicksetup.Installation.*;
@@ -93,6 +97,8 @@
    INITIALIZING("summary-upgrade-initializing"),
    CHECK_SERVER_HEALTH("summary-upgrade-check-server-health"),
    CALCULATING_SCHEMA_CUSTOMIZATIONS(
            "summary-upgrade-calculating-schema-customization"),
@@ -246,9 +252,24 @@
          listUrlString = "http://www.opends.org/upgrade-builds";
        }
        URL buildRepo = new URL(listUrlString);
        remoteBuildManager = new RemoteBuildManager(this, buildRepo);
        // See if system properties dictate use of a proxy
        Proxy proxy = null;
        String proxyHost = System.getProperty("http.proxyHost");
        String proxyPort = System.getProperty("http.proxyPort");
        if (proxyHost != null && proxyPort != null) {
          try {
            SocketAddress addr =
                    new InetSocketAddress(proxyHost, new Integer(proxyPort));
            proxy = new Proxy(Proxy.Type.HTTP, addr);
          } catch (NumberFormatException nfe) {
            LOG.log(Level.INFO, "Illegal proxy port number " + proxyPort);
          }
        }
        remoteBuildManager = new RemoteBuildManager(this, buildRepo, proxy);
      } catch (MalformedURLException e) {
        LOG.log(Level.INFO, "error", e);
        LOG.log(Level.INFO, "", e);
      }
    }
    return remoteBuildManager;
@@ -438,7 +459,7 @@
            new Thread(new Runnable() {
              public void run() {
                try {
                  installation.getBuildId();
                  installation.getBuildInformation().getBuildId();
                } catch (ApplicationException e) {
                  LOG.log(Level.INFO, "error", e);
                }
@@ -609,27 +630,12 @@
        throw e;
      }
      // If the server has never been started and schema changes
      // have been made, the server will have never had the chance
      // to write schema.current.
      if (!getInstallation().getStatus().isServerRunning()) {
        try {
          startServerWithoutConnectionHandlers();
          getServerController().stopServerInProcess();
        } catch (ApplicationException e) {
          LOG.log(Level.INFO, "Error starting server to insure configuration" +
                  " changes have been written to the filesystem", e);
          throw e;
        }
      }
      if (getInstallation().getStatus().isServerRunning()) {
        try {
          new ServerController(this).stopServer();
        } catch (ApplicationException e) {
          LOG.log(Level.INFO, "Error stopping server", e);
          throw e;
        }
      try {
        setCurrentProgressStep(UpgradeProgressStep.CHECK_SERVER_HEALTH);
        checkServerHealth();
      } catch (ApplicationException e) {
        LOG.log(Level.INFO, "Server failed initial health check", e);
        throw e;
      }
      try {
@@ -819,12 +825,41 @@
  }
  /**
   * 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
   * Stops and starts the server checking for serious errors.  Also
   * has the side effect of having the server write schema.current
   * if it has never done so.
   */
  private void checkServerHealth() throws ApplicationException {
    Installation installation = getInstallation();
    ServerController control = new ServerController(this, installation);
    try {
      if (installation.getStatus().isServerRunning()) {
        control.stopServer();
      }
      OperationOutput op = control.startServer();
      List<String> errors = op.getErrors();
      if (errors != null) {
        throw new ApplicationException(
                ApplicationException.Type.APPLICATION,
                "The server currently starts with errors with must" +
                        "be resolved before an upgrade can occur: " +
                        Utils.listToString(errors, " "),
                null);
      }
      control.stopServer();
    } catch (Exception e) {
      throw new ApplicationException(ApplicationException.Type.APPLICATION,
              "Server health check failed", e);
    }
  }
    /**
    * 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 =
@@ -866,11 +901,13 @@
  }
  private void verifyUpgrade() throws ApplicationException {
    try {
      new ServerController(this).startServer();
    } catch (ApplicationException e) {
      LOG.log(Level.INFO, "Error starting server: " +
              e.getLocalizedMessage(), e);
    ServerController sc = new ServerController(this);
    OperationOutput op = sc.startServer();
    if (op.getErrors() != null) {
      throw new ApplicationException(ApplicationException.Type.APPLICATION,
              "Upgraded server failed verification test by signaling " +
                      "errors during startup: " +
                      Utils.listToString(op.getErrors(), " "), null);
    }
  }
@@ -1253,24 +1290,24 @@
   * day' types of changes to the codebase.
   */
  private void insureUpgradability() throws ApplicationException {
    Integer currentVersion;
    Integer newVersion;
    BuildInformation currentVersion;
    BuildInformation newVersion;
    try {
      currentVersion = getInstallation().getSvnRev();
      currentVersion = getInstallation().getBuildInformation();
    } catch (ApplicationException e) {
      LOG.log(Level.INFO, "error", e);
      throw ApplicationException.createFileSystemException(
              "Could not determine current version number: " +
              "Could not determine current build information: " +
              e.getLocalizedMessage(), e);
    }
    try {
      newVersion = getStagedInstallation().getSvnRev();
      newVersion = getStagedInstallation().getBuildInformation();
    } catch (Exception e) {
      LOG.log(Level.INFO, "error", e);
      throw ApplicationException.createFileSystemException(
              "Could not determine upgrade version number: " +
              "Could not determine upgrade build information: " +
              e.getLocalizedMessage(), e);
    }
@@ -1346,7 +1383,7 @@
    String installPath = Utils.getPath(getInstallation().getRootDirectory());
    String newVersion = null;
    try {
      newVersion = getInstallation().getBuildId();
      newVersion = getInstallation().getBuildInformation().getBuildId();
    } catch (ApplicationException e) {
      newVersion = getMsg("upgrade-build-id-unknown");
    }
opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/UpgraderReviewPanel.java
@@ -185,7 +185,8 @@
  private String getOldBuildString() {
    String oldVersion;
    try {
      oldVersion = getApplication().getInstallation().getBuildId();
      oldVersion = getApplication().getInstallation().
              getBuildInformation().getBuildId();
    } catch (ApplicationException e) {
      LOG.log(Level.INFO, "error", e);
      oldVersion = getMsg("upgrade-build-id-unknown");
opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/WelcomePanel.java
@@ -192,7 +192,7 @@
      String buildId = null;
      Installation installation = getApplication().getInstallation();
      try {
        buildId = installation.getBuildId();
        buildId = installation.getBuildInformation().getBuildId();
      } catch (Exception e) {
        buildId = getMsg("upgrade-build-id-unknown");
      }
opends/src/quicksetup/org/opends/quicksetup/util/OperationOutput.java
New file
@@ -0,0 +1,76 @@
/*
 * 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 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.util;
import java.util.List;
/**
 * Contains information about an operation invoked by this class.
 */
public class OperationOutput {
  private Exception exception = null;
  private List<String> errors = null;
  /**
   * Gets a list of string representing error messages obtained
   * by invoking the operation.  Null if there were no errors.
   * @return List of Strings representing errors
   */
  public List<String> getErrors() {
    return errors;
  }
  /**
   * Gets an exception that occurred by invoking the operation.  Null
   * if there were no exceptions.
   * @return Exception error
   */
  public Exception getException() {
    return exception;
  }
  /**
   * Sets the exception that occurred during execution.  Can be null to
   * indicate no exception was encountered.
   * @param exception Exception that occurred during invocation of the operation
   */
  void setException(Exception exception) {
    this.exception = exception;
  }
  /**
   * Sets the list of error messages that occurred during execution.
   * Can be null to indicate no errors were encountered.
   * @param errors List of Strings representing error messages
   */
  void setErrors(List<String> errors) {
    this.errors = errors;
  }
}
opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
@@ -33,6 +33,7 @@
import javax.naming.NamingException;
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
@@ -224,19 +225,26 @@
  /**
   * This methods starts the server.
   * @return OperationOutput object containing output from the start server
   * command invocation.
   * @throws org.opends.quicksetup.ApplicationException if something goes wrong.
   */
  public void startServer() throws ApplicationException {
    startServer(true);
  public OperationOutput startServer() throws ApplicationException {
    return 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.
   * @return OperationOutput object containing output from the start server
   * command invocation.
   * @throws org.opends.quicksetup.ApplicationException if something goes wrong.
   */
  private void startServer(boolean verify) throws ApplicationException {
  private OperationOutput startServer(boolean verify)
          throws ApplicationException
  {
    OperationOutput output = new OperationOutput();
    application.notifyListeners(
            application.getFormattedProgress(
                    application.getMsg("progress-starting")) +
@@ -275,7 +283,7 @@
      StartReader errReader = new StartReader(err, startedId, true);
      StartReader outputReader = new StartReader(out, startedId, false);
      while (!errReader.isFinished() && !outputReader.isFinished())
      while (!errReader.isFinished() || !outputReader.isFinished())
      {
        try
        {
@@ -284,6 +292,17 @@
        {
        }
      }
      // Collect any errors found in the output
      List<String> errors = errReader.getErrors();
      if (outputReader.getErrors() != null) {
        if (errors == null) {
          errors = new ArrayList<String>();
        }
        errors.addAll(outputReader.getErrors());
      }
      output.setErrors(errors);
      // Check if something wrong occurred reading the starting of the server
      ApplicationException ex = errReader.getException();
      if (ex == null)
@@ -292,6 +311,11 @@
      }
      if (ex != null)
      {
        // This is meaningless right now since we throw
        // the exception below, but in case we change out
        // minds later or add the ability to return exceptions
        // in the output only instead of throwing...
        output.setException(ex);
        throw ex;
      } else if (verify)
@@ -369,6 +393,7 @@
      throw new ApplicationException(ApplicationException.Type.START_ERROR,
          application.getThrowableMsg("error-starting-server", ioe), ioe);
    }
    return output;
  }
  /**
@@ -481,6 +506,8 @@
  {
    private ApplicationException ex;
    private List<String> errors;
    private boolean isFinished;
    private boolean isFirstLine;
@@ -530,6 +557,16 @@
              {
                isFinished = true;
              }
              // Collect lines that would seem to indicate all is
              // not well with the server
              if (line.indexOf("severity=SEVERE_ERROR") != -1) {
                if (errors == null) {
                  errors = new ArrayList<String>();
                }
                errors.add(line);
              }
              line = reader.readLine();
            }
          } catch (IOException ioe)
@@ -563,6 +600,10 @@
      return ex;
    }
    public List<String> getErrors() {
      return errors;
    }
    /**
     * Returns <CODE>true</CODE> if the server starting process finished
     * (successfully or not) and <CODE>false</CODE> otherwise.