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

kenneth_suter
14.21.2007 92ce4633648268f705f2d0b439425bcf8d5ec40f
This commit does the following:

- Creates a new class ServerHealthChecker for consolidating logic related to determining whether or not the server is healthy which is done both before and after an upgrade takes place.

- Creates a new class InProcessServerController where I've moved the methods for managing an instance of DS running in the same JVM process. I did this because the methods there now return OperationOutput objects and the implementation for the InProcess version required lots of server classes related to server logging. These classes that are now imported have been added to the quicksetup.jar (see build.xml).
2 files added
6 files modified
613 ■■■■ changed files
opendj-sdk/opends/build.xml 17 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java 9 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java 3 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java 50 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java 225 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/OperationOutput.java 94 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java 108 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ServerHealthChecker.java 107 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/build.xml
@@ -530,7 +530,24 @@
      <include name="**/org/opends/server/util/CertificateManager.java"/>
      <include name="**/org/opends/server/util/DynamicConstants.java"/>
      <include name="**/org/opends/server/types/OperatingSystem.java"/>
      <include name="**/org/opends/server/loggers/debug/TextDebugLogPublisher.java"/>
      <include name="**/org/opends/server/loggers/debug/DebugLogger.java"/>
      <include name="**/org/opends/server/loggers/TextErrorLogPublisher.java"/>
      <include name="**/org/opends/server/loggers/TextWriter.java"/>
      <include name="**/org/opends/server/loggers/ErrorLogger.java"/>
      <include name="**/org/opends/server/loggers/TextAccessLogPublisher.java"/>
      <include name="**/org/opends/server/loggers/AccessLogger.java"/>
      <include name="**/org/opends/server/types/DN.java"/>
      <include name="**/org/opends/server/api/DebugLogPublisher.java"/>
      <include name="**/org/opends/server/api/ErrorLogPublisher.java"/>
      <include name="**/org/opends/server/api/AccessLogPublisher.java"/>
      <compilerarg value="-Xlint:all" />
      <classpath>
        <fileset dir="${lib.dir}">
          <include name="*.jar" />
        </fileset>
        <pathelement path="${classes.dir}"/>
      </classpath>
    </javac>
    <javac srcdir="${quicksetup.src.dir}" destdir="${quicksetup.classes.dir}"
         debug="on" debuglevel="${build.debuglevel}" source="1.5"
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -49,6 +49,7 @@
import org.opends.admin.ads.SuffixDescriptor;
import org.opends.quicksetup.ui.*;
import org.opends.quicksetup.util.Utils;
import org.opends.quicksetup.util.InProcessServerController;
import org.opends.quicksetup.*;
import org.opends.server.util.CertificateManager;
import org.opends.quicksetup.installer.ui.DataOptionsPanel;
@@ -1204,7 +1205,7 @@
      }
      if (startedServer)
      {
        getServerController().stopServerInProcess();
        new InProcessServerController(getInstallation()).stopServer();
      }
    }
  }
@@ -1966,7 +1967,7 @@
   * panel and update the UserInstallData object according to that content.
   *
   * @throws
   *           UserInstallDataException if the data provided by the user is not
   *           UserDataException if the data provided by the user is not
   *           valid.
   *
   */
@@ -2038,7 +2039,7 @@
   * panel and update the UserInstallData object according to that content.
   *
   * @throws
   *           UserInstallDataException if the data provided by the user is not
   *           UserDataException if the data provided by the user is not
   *           valid.
   *
   */
@@ -2099,7 +2100,7 @@
   * Validate the data provided by the user in the new suffix data options panel
   * and update the UserInstallData object according to that content.
   *
   * @throws UserInstallDataException if the data provided by the user is not
   * @throws UserDataException if the data provided by the user is not
   *           valid.
   *
   */
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java
@@ -29,6 +29,7 @@
import org.opends.quicksetup.*;
import org.opends.quicksetup.util.ServerController;
import org.opends.quicksetup.util.InProcessServerController;
import org.opends.quicksetup.webstart.WebStartDownloader;
import javax.swing.*;
@@ -490,7 +491,7 @@
      if (getInstallation().getStatus().isServerRunning()) {
        control.stopServer();
      }
      control.startServerInProcess(true);
      new InProcessServerController(getInstallation()).startServer(true);
    } catch (IOException e) {
      String msg = "Failed to determine server state: " +
      e.getLocalizedMessage();
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -31,11 +31,7 @@
import org.opends.quicksetup.upgrader.ui.WelcomePanel;
import org.opends.quicksetup.upgrader.ui.ChooseVersionPanel;
import org.opends.quicksetup.upgrader.ui.UpgraderReviewPanel;
import org.opends.quicksetup.util.Utils;
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.util.*;
import org.opends.quicksetup.ui.*;
import java.awt.event.WindowEvent;
@@ -51,6 +47,7 @@
import static org.opends.quicksetup.Installation.*;
import javax.swing.*;
/**
@@ -209,7 +206,6 @@
  static private final String SYS_PROP_NO_ABORT =
          "org.opends.upgrader.Upgrader.NoAbort";
  // Root files that will be ignored during backup
  static private final String[] ROOT_FILES_TO_IGNORE_DURING_BACKUP = {
          CHANGELOG_PATH_RELATIVE, // changelogDb
@@ -950,7 +946,7 @@
        try {
          LOG.log(Level.INFO, "stopping server");
          getServerController().stopServerInProcess();
          new InProcessServerController(getInstallation()).stopServer();
          LOG.log(Level.INFO, "server stopped");
        } catch (Throwable t) {
          LOG.log(Level.INFO, "Error stopping server", t);
@@ -1134,27 +1130,27 @@
   */
  private void checkServerHealth() throws ApplicationException {
    Installation installation = getInstallation();
    ServerController control = new ServerController(installation);
    ServerHealthChecker healthChecker = new ServerHealthChecker(installation);
    try {
      if (installation.getStatus().isServerRunning()) {
        control.stopServer();
      }
      OperationOutput op = control.startServer();
      List<String> errors = op.getErrors();
      if (errors != null) {
      healthChecker.checkServer();
      List<String> problems = healthChecker.getProblemMessages();
      if (problems != null && problems.size() > 0) {
        throw new ApplicationException(
                ApplicationException.Type.APPLICATION,
                "The server currently starts with errors which must" +
                        "be resolved before an upgrade can occur: " +
                        Utils.listToString(errors, " "),
                "The server currently starts with errors which must " +
                        "be resolved before an upgrade can occur: \n\n" +
                        Utils.listToString(problems, "\n\n"),
                null);
      }
      control.stopServer();
    } catch (Exception e) {
      throw new ApplicationException(ApplicationException.Type.APPLICATION,
              "Server health check failed.  Please resolve the following " +
                      "before running the upgrade " +
                      "tool: " + e.getLocalizedMessage(), e);
      if (e instanceof ApplicationException) {
        throw (ApplicationException)e;
      } else {
        throw new ApplicationException(ApplicationException.Type.APPLICATION,
                "Server health check failed.  Please resolve the following " +
                        "before running the upgrade " +
                        "tool: " + e.getLocalizedMessage(), e);
      }
    }
  }
@@ -1224,13 +1220,15 @@
  }
  private void verifyUpgrade() throws ApplicationException {
    ServerController sc = new ServerController(getInstallation());
    OperationOutput op = sc.startServer();
    if (op.getErrors() != null) {
    Installation installation = getInstallation();
    ServerHealthChecker healthChecker = new ServerHealthChecker(installation);
    healthChecker.checkServer();
    List<String> errors = healthChecker.getProblemMessages();
    if (errors != null && errors.size() > 0) {
      throw new ApplicationException(ApplicationException.Type.APPLICATION,
              "Upgraded server failed verification test by signaling " +
                      "errors during startup: " +
                      Utils.listToString(op.getErrors(), " "), null);
                      Utils.listToString(errors, " "), null);
    }
  }
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
New file
@@ -0,0 +1,225 @@
/*
 * 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.*;
import org.opends.server.loggers.debug.TextDebugLogPublisher;
import org.opends.server.loggers.debug.DebugLogger;
import org.opends.server.loggers.TextErrorLogPublisher;
import org.opends.server.loggers.TextWriter;
import org.opends.server.loggers.ErrorLogger;
import org.opends.server.loggers.TextAccessLogPublisher;
import org.opends.server.loggers.AccessLogger;
import org.opends.server.types.DN;
import org.opends.server.api.DebugLogPublisher;
import org.opends.server.api.ErrorLogPublisher;
import org.opends.server.api.AccessLogPublisher;
import java.util.logging.Logger;
import java.util.logging.Level;
/**
 * Class used to manipulate an OpenDS server in the same JVM process as
 * the client class.
 */
public class InProcessServerController {
  static private final Logger LOG =
          Logger.getLogger(InProcessServerController.class.getName());
  private Installation installation;
  /**
   * Creates a new instance that will operate on <code>application</code>'s
   * installation.
   * @param installation representing the server instance to control
   */
  public InProcessServerController(Installation installation) {
    this.installation = installation;
  }
  /**
   * 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.
   * @return OperationOutput object containing output from the start server
   * command invocation.
   * @throws org.opends.server.config.ConfigException
   *         If there is a problem with the Directory Server
   *         configuration that prevents a critical component
   *         from being instantiated.
   *
   * @throws org.opends.server.types.InitializationException
   *         If some other problem occurs while
   *         attempting to initialize and start the
   *         Directory Server.
   */
  public OperationOutput startServer(boolean disableConnectionHandlers)
          throws
          org.opends.server.types.InitializationException,
          org.opends.server.config.ConfigException {
    LOG.log(Level.INFO, "Starting in process server with connection handlers " +
            (disableConnectionHandlers ? "disabled" : "enabled"));
    System.setProperty(
            "org.opends.server.DisableConnectionHandlers",
            disableConnectionHandlers ? "true" : null);
    return startServer();
  }
  /**
   * Stops a server that had been running 'in process'.
   */
  public void stopServer() {
    LOG.log(Level.INFO, "Shutting down in process server");
    org.opends.server.core.DirectoryServer.shutDown(
            ServerController.class.getName(),
            "quicksetup requests shutdown");
  }
  /**
   * Starts the OpenDS server in this process.
   * @return OperationOutput with the results of the operation.
   * @throws org.opends.server.config.ConfigException
   *  If there is a problem with the Directory Server
   *  configuration that prevents a critical component
   *  from being instantiated.
   *
   * @throws org.opends.server.types.InitializationException
   *  If some other problem occurs while
   *  attempting to initialize and start the
   *  Directory Server.
   */
  public OperationOutput startServer()
          throws
          org.opends.server.types.InitializationException,
          org.opends.server.config.ConfigException
  {
    OperationOutput output = new OperationOutput();
    // Bootstrap and start the Directory Server.
    LOG.log(Level.FINER, "Bootstrapping directory server");
    org.opends.server.core.DirectoryServer directoryServer =
            org.opends.server.core.DirectoryServer.getInstance();
    directoryServer.bootstrapServer();
    String configClass = "org.opends.server.extensions.ConfigFileHandler";
    String configPath = Utils.getPath(
            installation.getCurrentConfigurationFile());
    directoryServer.initializeConfiguration(configClass, configPath);
    try {
      DebugLogPublisher startupDebugPublisher =
              TextDebugLogPublisher.getStartupTextDebugPublisher(
                      new ServerControllerTextWriter(output) {
                        void storeRecord(String record, OperationOutput output)
                        {
                          output.addDebugMessage(record);
                        }
                      });
      DebugLogger.removeAllDebugLogPublishers();
      DebugLogger.addDebugLogPublisher(DN.NULL_DN,
              startupDebugPublisher);
      ErrorLogPublisher startupErrorPublisher =
              TextErrorLogPublisher.getStartupTextErrorPublisher(
                      new ServerControllerTextWriter(output) {
                        void storeRecord(String record, OperationOutput output)
                        {
                          output.addErrorMessage(record);
                        }
                      });
      ErrorLogger.removeAllErrorLogPublishers();
      ErrorLogger.addErrorLogPublisher(DN.NULL_DN,
              startupErrorPublisher);
      AccessLogPublisher startupAccessPublisher =
              TextAccessLogPublisher.getStartupTextAccessPublisher(
                      new ServerControllerTextWriter(output) {
                        void storeRecord(String record, OperationOutput output)
                        {
                          output.addAccessMessage(record);
                        }
                      });
      AccessLogger.removeAllAccessLogPublishers();
      AccessLogger.addAccessLogPublisher(DN.NULL_DN,
              startupAccessPublisher);
    } catch (Exception e) {
      LOG.log(Level.INFO, "Error installing test log publishers: " +
              e.toString());
    }
    LOG.log(Level.FINER, "Invoking start server");
    directoryServer.startServer();
    return output;
  }
  /**
   * Pushes messages published by the server loggers into OperationOutput.
   */
  private abstract class ServerControllerTextWriter implements TextWriter {
    private int bytesWritten = 0;
    private OperationOutput output = null;
    abstract void storeRecord(String record, OperationOutput output);
    ServerControllerTextWriter(OperationOutput output) {
      this.output = output;
    }
    public void writeRecord(String record) {
      if (record != null) {
        bytesWritten += bytesWritten;
        storeRecord(record, output);
      }
    }
    public void flush() {
      // do nothing;
    }
    public void shutdown() {
      // do nothing;
    }
    public long getBytesWritten() {
      return bytesWritten;
    }
  }
}
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/OperationOutput.java
@@ -28,6 +28,8 @@
package org.opends.quicksetup.util;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
/**
 * Contains information about an operation invoked by this class.
@@ -36,15 +38,52 @@
  private Exception exception = null;
  private List<String> errors = null;
  private List<String> errorMessages = new ArrayList<String>();
  private List<String> debugMessages = new ArrayList<String>();
  private List<String> accessMessages = new ArrayList<String>();
  /**
   * 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
   * Gets a list of strings representing error messages obtained
   * by invoking the operation that match <code>regex</code>.
   * @param regex String used to find particular error messages
   * @return List of Strings representing errorMessages that contain
   * the provided <code>regex</code> string.
   */
  public List<String> getErrors() {
    return errors;
  public List<String> getErrorMessages(String regex) {
    List<String> errorMessagesSubset = new ArrayList<String>();
    for (String msg : errorMessages) {
      if (msg.matches(regex)) {
        errorMessagesSubset.add(msg);
      }
    }
    return Collections.unmodifiableList(errorMessagesSubset);
  }
  /**
   * Gets a list of strings representing error messages obtained
   * by invoking the operation.
   * @return List of Strings representing errorMessages
   */
  public List<String> getErrorMessages() {
    return Collections.unmodifiableList(errorMessages);
  }
  /**
   * Gets a list of strings representing error messages obtained
   * by invoking the operation.
   * @return List of Strings representing errorMessages
   */
  public List<String> getDebugMessages() {
    return Collections.unmodifiableList(debugMessages);
  }
  /**
   * Gets a list of strings representing error messages obtained
   * by invoking the operation.
   * @return List of Strings representing errorMessages
   */
  public List<String> getAccessMessages() {
    return Collections.unmodifiableList(accessMessages);
  }
  /**
@@ -66,11 +105,44 @@
  }
  /**
   * 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
   * Adds an error message.
   * @param errorMessage an error message
   */
  void setErrors(List<String> errors) {
    this.errors = errors;
  void addErrorMessage(String errorMessage) {
    this.errorMessages.add(errorMessage);
  }
  /**
   * Adds an access message.
   * @param accessMessage an error message
   */
  void addAccessMessage(String accessMessage) {
    this.accessMessages.add(accessMessage);
  }
  /**
   * Adds an error message.
   * @param debugMessage an error message
   */
  void addDebugMessage(String debugMessage) {
    this.debugMessages.add(debugMessage);
  }
  /**
   * Sets the list of error messages that occurred during execution.
   * @param accessMessages List of Strings representing error messages
   */
  void setAccessMessages(List<String> accessMessages) {
    this.accessMessages = accessMessages;
  }
  /**
   * Sets the list of error messages that occurred during execution.
   * @param debugMessages List of Strings representing error messages
   */
  void setDebugMessages(List<String> debugMessages) {
    this.debugMessages = debugMessages;
  }
}
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
@@ -206,45 +206,6 @@
  }
  /**
   * 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 org.opends.server.config.ConfigException
   *         If there is a problem with the Directory Server
   *         configuration that prevents a critical component
   *         from being instantiated.
   *
   * @throws org.opends.server.types.InitializationException
   *         If some other problem occurs while
   *         attempting to initialize and start the
   *         Directory Server.
   */
  public void startServerInProcess(boolean disableConnectionHandlers)
          throws
          org.opends.server.types.InitializationException,
          org.opends.server.config.ConfigException {
    System.setProperty(
            "org.opends.server.DisableConnectionHandlers",
            disableConnectionHandlers ? "true" : null);
    startServerInProcess();
  }
  /**
   * Stops a server that had been running 'in process'.
   */
  public void stopServerInProcess() {
    org.opends.server.core.DirectoryServer.shutDown(
            ServerController.class.getName(),
            "quicksetup requests shutdown");
  }
  /**
   * This methods starts the server.
   * @return OperationOutput object containing output from the start server
   * command invocation.
@@ -317,15 +278,25 @@
        }
      }
      // Collect any errors found in the output
      List<String> errors = errReader.getErrors();
      if (outputReader.getErrors() != null) {
        if (errors == null) {
          errors = new ArrayList<String>();
      // Collect any messages found in the output
      List<String> errors = errReader.getMessages();
      if (errors != null) {
        for(String error : errors) {
          output.addErrorMessage(error);
        }
        errors.addAll(outputReader.getErrors());
      }
      output.setErrors(errors);
      List<String> messages = outputReader.getMessages();
      if (messages != null) {
        for (String msg : messages) {
          // NOTE:  this may not be the best place to drop these.
          // However upon startup the server seems to log all messages,
          // regardless of whether or not they signal an error condition,
          // to its error log.
          output.addErrorMessage(msg);
        }
      }
      // Check if something wrong occurred reading the starting of the server
      ApplicationException ex = errReader.getException();
@@ -426,36 +397,6 @@
  }
  /**
   * Starts the OpenDS server in this process.
   *
   * @throws org.opends.server.config.ConfigException
   *  If there is a problem with the Directory Server
   *  configuration that prevents a critical component
   *  from being instantiated.
   *
   * @throws org.opends.server.types.InitializationException
   *  If some other problem occurs while
   *  attempting to initialize and start the
   *  Directory Server.
   */
  public void startServerInProcess()
          throws
          org.opends.server.types.InitializationException,
          org.opends.server.config.ConfigException
  {
    // Bootstrap and start the Directory Server.
    org.opends.server.core.DirectoryServer directoryServer =
            org.opends.server.core.DirectoryServer.getInstance();
    directoryServer.bootstrapServer();
    String configClass = "org.opends.server.extensions.ConfigFileHandler";
    String configPath = Utils.getPath(
            installation.getCurrentConfigurationFile());
    directoryServer.initializeConfiguration(configClass, configPath);
    directoryServer.startServer();
  }
  /**
   * This class is used to read the standard error and standard output of the
   * Stop process.
   * <p/>
@@ -536,7 +477,7 @@
  {
    private ApplicationException ex;
    private List<String> errors;
    private List<String> messages = new ArrayList<String>();
    private boolean isFinished;
@@ -590,14 +531,7 @@
                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);
              }
              messages.add(line);
              line = reader.readLine();
            }
@@ -625,8 +559,8 @@
      return ex;
    }
    public List<String> getErrors() {
      return errors;
    public List<String> getMessages() {
      return messages;
    }
    /**
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ServerHealthChecker.java
New file
@@ -0,0 +1,107 @@
/*
 * 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 org.opends.quicksetup.ApplicationException;
import org.opends.server.util.ServerConstants;
import java.util.List;
/**
 * Checks a server health by starting a server and looking through its
 * log messages for signs that things may not be well.
 */
public class ServerHealthChecker {
  private Installation installation = null;
  private List<String> errors = null;
  /**
   * Regular expression used to determine whether or not a server
   * is healthy enough for upgrade by looking through its startup
   * logs.
   */
  static private final String UNHEALTHY_SERVER_LOG_REGEX =
    new StringBuilder()
    .append(".*(")
    .append(ServerConstants.ERROR_SEVERITY_FATAL)
    .append("|")
    .append(ServerConstants.ERROR_SEVERITY_SEVERE_ERROR)
    .append(")+.*").toString();
  /**
   * Creates an instance.
   * @param installation of the server to check
   */
  public ServerHealthChecker(Installation installation) {
    this.installation = installation;
  }
  /**
   * Diagnoses the server's health by stopping (if necessary) and starting
   * the server in process and analyzing the resulting log messages.
   * Following the call to this method the server is left in a stopped state.
   * @throws ApplicationException if things go wrong
   */
  public void checkServer() throws ApplicationException {
    InProcessServerController control =
            new InProcessServerController(installation);
    try {
      if (installation.getStatus().isServerRunning()) {
        new ServerController(installation).stopServer();
      }
      OperationOutput op = control.startServer(true);
      errors = op.getErrorMessages(UNHEALTHY_SERVER_LOG_REGEX);
    } catch (Exception e) {
      if (e instanceof ApplicationException) {
        throw (ApplicationException)e;
      } else {
        throw new ApplicationException(ApplicationException.Type.APPLICATION,
                "Server health check failed.  Please resolve the following " +
                        "before running the upgrade " +
                        "tool: " + e.getLocalizedMessage(), e);
      }
    } finally {
      control.stopServer();
    }
  }
  /**
   * Gets a list of Strings representing error messages that resulted
   * from calling <code>checkServer</code>; null if <code>checkServer</code>
   * has not been called.
   * @return List of strings containing error messages
   */
  public List<String> getProblemMessages() {
    return errors;
  }
}