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

jvergara
11.34.2006 c40f084a6d3e897785f2fbff3ddb97545644cddc
The following modifications include the comments from Neil and Brian (thanks to both for your help):

1. Fix a bug with the setup script. Know this script is executable after the Web Start based installation.

2. Provide a different welcome message in the setup depending on whether we are launching the setup from the command line or Web Start. If we are launching the command line setup we make reference in the message to the Web Start installation and provide a link to the downloads page.

3. When the setup is successful, include in the message the path of the installation as was requested by William Hathaway.

4. Try to find a valid default port (of type []389) and not limit the search to 389. This implies not having any explanatory message to be displayed if we cannot connect to 389.

5. Update the code to better handle bug scenarii. Previously the code assumed that only RuntimeException could occur in case of a bug. This is not true in the general case, so know the code handles Throwable objects to detect bugs.

6. Provide the first implementation for the Uninstaller. Some code has been rearranged to maximize code re-use. The first implementation of the uninstaller basically does the following:

- Display a confirmation message informing of what will happen with the installation files and the consequences of uninstalling the server.

Ask the user which parts of the server must be uninstalled.

Check if we have configuration references outside the installation path (for the moment this check is limited to database files and log files). If these references exist show them to the user and ask the user whether these 'external' files must be deteled or not.

If the server is running we ask for confirmation to stop the server and if we are in windows we ask the user to provide a DN and a password to authenticate.

If the user continues and the server is running the code calls stop-ds script, if the script succeeds the code tries to delete the files in the installation that the user wanted to uninstall and in the case there are external files to the installation path and the user wants to delete them delete also these external files.

If everything works properly the uninstaller will delete all the files except the <install-root>/lib/quicksetup.jar and <install-root>/lib/OpenDS.jar file.

OpenDS.jar file is required by the command line uninstaller to share some code.

I preferred not to try to delete these files from the scripts as we cannot provide proper feedback (for instance localization) if we encounter a problem deleting these files.

In both cases we inform the user that there are some files that must be deleted manually.

7. Provide the code to launch uninstall through command line that is analogous in terms of interaction to the graphical one.

I have included two scripts to launch the uninstallation. The uninstall script for Unix is very similar to the setup script. However the uninstall.bat script has a difference with setup.bat.

The difference is that I limit the class path to include only quicksetup.jar. This is done because I have not found a way to delete the jar files that are in the class path of the java application using pure java code, so as the uninstaller does only require OpenDS.jar and quicksetup.jar files I have chosen to minimize the jar files in the class path.

This way the only files that are not deleted during installation is quicksetup.jar and OpenDS.jar.

8. Improve the wording of the install wizard as proposed by Brian and Neil.

9 . One minor tweak to the QuickSetup Welcome screen: make the reference to the "setup" command a monospace font to highlight it a bit more.

10. Fix for issue 1057 (stop-ds.bat and start-ds.bat do not work when called using Runtime.exec). The quicksetup code used to overwrite the environment variables when calling Runtime.exec which made the server not be able to start/stop correctly.

11. Fix some minor bugs with the default focus on some panels.

12. Update the setup scripts to use the java home file if the setup was previously called.
2 files copied
9 files added
4 files renamed
32 files modified
6821 ■■■■■ changed files
opends/build.xml 13 ●●●● patch | view | raw | blame | history
opends/resource/setup 19 ●●●●● patch | view | raw | blame | history
opends/resource/setup.bat 10 ●●●●● patch | view | raw | blame | history
opends/resource/uninstall 123 ●●●●● patch | view | raw | blame | history
opends/resource/uninstall.bat 63 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ButtonName.java 6 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java 226 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java 511 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateEvent.java 10 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateListener.java 8 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateEvent.java 22 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateListener.java 12 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java 4 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java 34 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java 2 ●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/InstallLauncher.java 10 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java 308 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java 25 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java 66 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java 2 ●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java 14 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java 49 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties 312 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java 75 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java 266 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java 32 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java 513 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/InstallWelcomePanel.java 30 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java 44 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java 54 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java 2 ●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java 30 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java 34 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java 54 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java 1108 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallException.java 92 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java 250 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java 12 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java 1211 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallData.java 271 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallDataException.java 76 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java 50 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/util/PlainTextProgressMessageFormatter.java 284 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/util/ProgressMessageFormatter.java 31 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java 4 ●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/util/Utils.java 447 ●●●●● patch | view | raw | blame | history
opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java 2 ●●● patch | view | raw | blame | history
opends/build.xml
@@ -232,12 +232,12 @@
    <taskdef resource="checkstyletask.properties"
         classpath="${checkstyle.dir}/checkstyle-all-4.1.jar" />
    <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
    <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
         failOnViolation="true">
      <fileset dir="${src.dir}" includes="**/*.java" />
      <formatter type="plain" />
    </checkstyle>
    <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
         failOnViolation="true">
      <fileset dir="${quicksetup.src.dir}" includes="**/*.java" />
@@ -470,12 +470,13 @@
      <fileset file="${resource.dir}/README" />
    </copy>
    <fixcrlf srcDir="${resource.dir}" destDir="${pdir}" includes="setup"
    <fixcrlf srcDir="${resource.dir}" destDir="${pdir}" includes="setup,uninstall"
         eol="lf" />
    <fixcrlf srcDir="${resource.dir}" destDir="${pdir}" includes="setup.bat"
    <fixcrlf srcDir="${resource.dir}" destDir="${pdir}" includes="setup.bat,uninstall.bat"
         eol="crlf" />
    <chmod file="${pdir}/setup" perm="755" />
    <chmod file="${pdir}/uninstall" perm="755" />
    <chmod perm="755">
      <fileset dir="${pdir}/bin">
        <exclude name="*.bat"/>
@@ -492,7 +493,7 @@
    <zip destfile="${package.dir}/OpenDS-${pkgversion}.zip">
      <zipfileset dir="${package.dir}" includes="OpenDS-${pkgversion}/**/*"
           excludes="OpenDS-${pkgversion}/bin/*,OpenDS-${pkgversion}/setup"
           excludes="OpenDS-${pkgversion}/bin/*,OpenDS-${pkgversion}/setup,OpenDS-${pkgversion}/uninstall"
           filemode="644" dirmode="755" />
      <zipfileset dir="${package.dir}"
           includes="OpenDS-${pkgversion}/bin/*.bat"
@@ -500,7 +501,7 @@
      <zipfileset dir="${package.dir}" includes="OpenDS-${pkgversion}/bin/*"
           excludes="OpenDS-${pkgversion}/bin/*.bat"
           filemode="755" dirmode="755" />
      <zipfileset dir="${package.dir}" includes="OpenDS-${pkgversion}/setup"
      <zipfileset dir="${package.dir}" includes="OpenDS-${pkgversion}/setup,OpenDS-${pkgversion}/uninstall"
           filemode="755" dirmode="755" />
    </zip>
  </target>
opends/resource/setup
@@ -32,16 +32,23 @@
then
  if test -z "${JAVA_HOME}"
  then
    JAVA_BIN=`which java 2> /dev/null`
    if test ${?} -eq 0
    if test -f "${INSTANCE_ROOT}/bin/set-java-home"
    then
      . "${INSTANCE_ROOT}/bin/set-java-home"
      JAVA_BIN="${JAVA_HOME}/bin/java"
      export JAVA_BIN
    else
      echo "Please set JAVA_HOME to the root of a Java 5.0 installation."
      exit 1
      JAVA_BIN=`which java 2> /dev/null`
      if test ${?} -eq 0
      then
        export JAVA_BIN
      else
        echo "Please set JAVA_HOME to the root of a Java 5.0 installation."
        exit 1
      fi
    fi
  else
    JAVA_BIN=${JAVA_HOME}/bin/java
    JAVA_BIN="${JAVA_HOME}/bin/java"
    export JAVA_BIN
  fi
fi
@@ -111,5 +118,5 @@
# Launch the setup process.
"${JAVA_BIN}" org.opends.quicksetup.SetupLauncher -P setup "${@}"
"${JAVA_BIN}" org.opends.quicksetup.installer.InstallLauncher -P setup "${@}"
opends/resource/setup.bat
@@ -30,6 +30,7 @@
set DIR_HOME=%~dP0
set INSTANCE_ROOT=%DIR_HOME%
:checkJavaBin
if "%JAVA_BIN%" == "" goto noJavaBin
goto setClassPath
@@ -38,7 +39,14 @@
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
set JAVA_BIN=%JAVA_HOME%\bin\java.exe
goto setClassPath
:noJavaHome
if not exist "%DIR_HOME%\bin\set-java-home.bat" goto noSetJavaHome
call "%DIR_HOME%\bin\set-java-home.bat"
set JAVA_BIN=%JAVA_HOME%\bin\java.exe
goto setClassPath
:noSetJavaHome
echo Error: JAVA_HOME environment variable is not set.
echo        Please set it to a valid Java 5 installation.
goto end
@@ -49,7 +57,7 @@
set PATH=%SystemRoot%
"%JAVA_BIN%" %JAVA_ARGS% org.opends.quicksetup.SetupLauncher -P setup.bat %*
"%JAVA_BIN%" %JAVA_ARGS% org.opends.quicksetup.installer.InstallLauncher -P setup.bat %*
:end
opends/resource/uninstall
New file
@@ -0,0 +1,123 @@
#!/bin/sh
#
# 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 Sun Microsystems, Inc.
# See if JAVA_HOME is set.  If not, then see if there is a java executable in
# the path and try to figure it out.
if test -z "${JAVA_BIN}"
then
  if test -z "${JAVA_HOME}"
  then
    if test -f "${INSTANCE_ROOT}/bin/set-java-home"
    then
      . "${INSTANCE_ROOT}/bin/set-java-home"
      JAVA_BIN="${JAVA_HOME}/bin/java"
      export JAVA_BIN
    else
      JAVA_BIN=`which java 2> /dev/null`
      if test ${?} -eq 0
      then
        export JAVA_BIN
      else
        echo "Please set JAVA_HOME to the root of a Java 5.0 installation."
        exit 1
      fi
    fi
  else
    JAVA_BIN="${JAVA_HOME}/bin/java"
    export JAVA_BIN
  fi
fi
# Explicitly set the PATH, LD_LIBRARY_PATH, LD_PRELOAD, and other important
# system environment variables for security and compatibility reasons.
PATH=/bin:/usr/bin
LD_LIBRARY_PATH=
LD_LIBRARY_PATH_32=
LD_LIBRARY_PATH_64=
LD_PRELOAD=
LD_PRELOAD_32=
LD_PRELOAD_64=
export PATH LD_LIBRARY_PATH LD_LIBRARY_PATH_32 LD_LIBRARY_PATH_64 \
       LD_PRELOAD LD_PRELOAD_32 LD_PRELOAD_34
# Capture the current working directory so that we can change to it later.
# Then capture the location of this script and the Directory Server instance
# root so that we can use them to create appropriate paths.
WORKING_DIR=`pwd`
cd `dirname "${0}"`
SCRIPT_DIR=`pwd`
INSTANCE_ROOT=${SCRIPT_DIR}
export INSTANCE_ROOT
cd "${WORKING_DIR}"
# Configure the appropriate CLASSPATH to test.
CLASSPATH=${INSTANCE_ROOT}/classes
for JAR in ${INSTANCE_ROOT}/lib/*.jar
do
  CLASSPATH=${CLASSPATH}:${JAR}
done
export CLASSPATH
# Determine whether the detected Java environment is acceptable for use.
if test -z "${JAVA_ARGS}"
then
  "${JAVA_BIN}" -client org.opends.server.tools.InstallDS -t 2> /dev/null
  if test ${?} -eq 0
  then
    JAVA_ARGS="-client"
  else
    "${JAVA_BIN}" org.opends.server.tools.InstallDS -t 2> /dev/null
    if test ${?} -ne 0
    then
      echo "ERROR:  The detected Java version could not be used.  Please set "
      echo "        JAVA_HOME to the root of a Java 5.0 installation."
      exit 1
    fi
  fi
else
  "${JAVA_BIN}" ${JAVA_ARGS} org.opends.server.tools.InstallDS -t 2> /dev/null
  if test ${?} -ne 0
  then
    echo "ERROR:  The detected Java version could not be used.  Please set "
    echo "        JAVA_HOME to the root of a Java 5.0 installation."
    exit 1
  fi
fi
# Configure the appropriate CLASSPATH to run uninstall.
CLASSPATH=${INSTANCE_ROOT}/lib/quicksetup.jar:${INSTANCE_ROOT}/lib/OpenDS.jar
export CLASSPATH
# Launch the uninstall process.
"${JAVA_BIN}" org.opends.quicksetup.uninstaller.UninstallLauncher "${@}"
opends/resource/uninstall.bat
New file
@@ -0,0 +1,63 @@
@echo off
rem CDDL HEADER START
rem
rem The contents of this file are subject to the terms of the
rem Common Development and Distribution License, Version 1.0 only
rem (the "License").  You may not use this file except in compliance
rem with the License.
rem
rem You can obtain a copy of the license at
rem trunk/opends/resource/legal-notices/OpenDS.LICENSE
rem or https://OpenDS.dev.java.net/OpenDS.LICENSE.
rem See the License for the specific language governing permissions
rem and limitations under the License.
rem
rem When distributing Covered Code, include this CDDL HEADER in each
rem file and include the License file at
rem trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
rem add the following below this CDDL HEADER, with the fields enclosed
rem by brackets "[]" replaced with your own identifying * information:
rem      Portions Copyright [yyyy] [name of copyright owner]
rem
rem CDDL HEADER END
rem
rem
rem      Portions Copyright 2006 Sun Microsystems, Inc.
setlocal
set DIR_HOME=%~dP0
set INSTANCE_ROOT=%DIR_HOME%
:checkJavaBin
if "%JAVA_BIN%" == "" goto noJavaBin
goto setClassPath
:noJavaBin
if "%JAVA_HOME%" == "" goto noJavaHome
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
set JAVA_BIN=%JAVA_HOME%\bin\java.exe
goto setClassPath
:noJavaHome
if not exist "%DIR_HOME%\bin\set-java-home.bat" goto noSetJavaHome
call "%DIR_HOME%\bin\set-java-home.bat"
set JAVA_BIN=%JAVA_HOME%\bin\java.exe
goto setClassPath
:noSetJavaHome
echo Error: JAVA_HOME environment variable is not set.
echo        Please set it to a valid Java 5 installation.
goto end
:setClassPath
call "%DIR_HOME%\bin\setcp.bat" %DIR_HOME%\lib\quicksetup.jar
call "%DIR_HOME%\bin\setcp.bat" %DIR_HOME%\lib\OpenDS.jar
set PATH=%SystemRoot%
"%JAVA_BIN%" %JAVA_ARGS% org.opends.quicksetup.uninstaller.UninstallLauncher %*
:end
opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
@@ -52,5 +52,9 @@
  /**
   * The Finish button.
   */
  FINISH
  FINISH,
  /**
   * The Cancel button.
   */
  CANCEL
}
opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
@@ -32,11 +32,12 @@
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import javax.naming.NamingException;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.installer.offline.OfflineInstaller;
import org.opends.quicksetup.util.Utils;
/**
@@ -57,6 +58,16 @@
  private String configFileContents;
  private Set<String> directoryManagerDns;
  private Set<String> dbPaths;
  private Set<String> logPaths;
  private String ldapUrl;
  private String ldapsUrl;
  /**
   * The constructor of a CurrentInstallStatus object.
   *
@@ -136,13 +147,129 @@
  }
  /**
   * Returns the list of directory manager dns as they appear in the
   * configuration file.
   *
   * @return the list of directory manager dns as they appear in the
   * configuration file.
   */
  public Set<String> getDirectoryManagerDns()
  {
    if (directoryManagerDns == null)
    {
      directoryManagerDns = new HashSet<String>();
      String directoryManagerDnAttr = "ds-cfg-alternate-bind-dn";
      updateSetWithValues(directoryManagerDns, directoryManagerDnAttr);
    }
    return directoryManagerDns;
  }
  /**
   * Returns the list of paths where the databases are installed as they appear
   * in the configuration file.
   *
   * @return the list of paths where the databases are installed as they appear
   * in the configuration file.
   */
  public Set<String> getDatabasePaths()
  {
    if (dbPaths == null)
    {
      dbPaths = new HashSet<String>();
      String dbFileAttr = "ds-cfg-backend-directory";
      updateSetWithValues(dbPaths, dbFileAttr);
    }
    return dbPaths;
  }
  /**
   * Returns the list of paths where the logs files are located as they appear
   * in the configuration file.
   *
   * @return the list of paths where the logs files are located as they appear
   * in the configuration file.
   */
  public Set<String> getLogPaths()
  {
    if (logPaths == null)
    {
      logPaths = new HashSet<String>();
      String logFileAttr = "ds-cfg-log-file";
      updateSetWithValues(logPaths, logFileAttr);
    }
    return logPaths;
  }
  /**
   * Indicates whether there is the server is running in the localhost on the
   * LDAP port specified in config.ldif file.  Note that this method performs
   * LDAP requests which can be time consuming.
   *
   * @return <CODE>true</CODE> if the server is running, or <CODE>false</CODE>
   *         if not.
   */
  public boolean isServerRunning()
  {
    boolean isServerRunning = false;
    try
    {
      Utils.createLdapContext(getLdapUrl(), null, null, 3000, null);
      isServerRunning = true;
    } catch (NamingException ne)
    {
      try
      {
        if (getSecurePort() != -1)
        {
          Utils.createLdapContext(getLdapsUrl(), null, null, 3000, null);
          isServerRunning = true;
        }
      } catch (NamingException ne2)
      {
      }
    }
    return isServerRunning;
  }
  /**
   * Provides the ldap url to the server (assumes we are calling this locally).
   *
   * @return the ldap url to the server.
   */
  public String getLdapUrl()
  {
    if (ldapUrl == null)
    {
      ldapUrl = "ldap://localhost:"+getPort();
    }
    return ldapUrl;
  }
  /**
   * Provides the ldap secure url to the server (assumes we are calling this
   * locally).
   *
   * @return the ldap secure url to the server.
   */
  public String getLdapsUrl()
  {
    if (ldapsUrl == null)
    {
      ldapsUrl = "ldaps://localhost:"+getSecurePort();
    }
    return ldapsUrl;
  }
  /**
   * Provides the config file path (path to config.ldif file).
   *
   * @return the config file path.
   */
  private String getConfigFilePath()
  {
    return OfflineInstaller.CONFIG_FILE_NAME;
    return Utils.getConfigFileFromClasspath();
  }
  /**
@@ -152,14 +279,30 @@
   */
  private int getPort()
  {
    return getPort("ds-cfg-listen-port");
  }
  /**
   * Provides the LDAP secure port as is specified in the config.ldif file.
   *
   * @return the LDAP secure port specified in the config.ldif file.
   */
  private int getSecurePort()
  {
    // TODO find out which is the attribute for this port.
    return getPort("ds-cfg-listen-secure-port");
  }
  private int getPort(String portAttr)
  {
    int port = -1;
    int index = getConfigFileContents().indexOf("cn=ldap connection handler");
    if (index != -1)
    {
      String portAttr = "ds-cfg-listen-port:";
      int index1 = getConfigFileContents().indexOf(portAttr, index);
      String attrWithPoints = portAttr+":";
      int index1 = getConfigFileContents().indexOf(attrWithPoints, index);
      if (index1 != -1)
      {
        int index2 =
@@ -168,7 +311,8 @@
        if (index2 != -1)
        {
          String sPort =
              getConfigFileContents().substring(portAttr.length() + index1,
              getConfigFileContents().substring(attrWithPoints.length() +
                  index1,
                  index2).trim();
          try
          {
@@ -183,34 +327,6 @@
  }
  /**
   * Indicates whether there is the server is running in the localhost on the
   * LDAP port specified in config.ldif file.
   *
   * @return <CODE>true</CODE> if the server is running, or <CODE>false</CODE>
   *         if not.
   */
  private boolean isServerRunning()
  {
    boolean isServerRunning = false;
    int port = getPort();
    if (port > 0)
    {
      String ldapURL = "ldap://localhost:" + port;
      try
      {
        Utils.createLdapContext(ldapURL, null, null, 3000, null);
        isServerRunning = true;
      } catch (NamingException ne)
      {
      }
    }
    return isServerRunning;
  }
  /**
   * Indicates whether there are database files under this installation.
   *
   * @return <CODE>true</CODE> if there are database files, or
@@ -219,7 +335,7 @@
  private boolean dbFilesExist()
  {
    boolean dbFilesExist = false;
    File dbDir = new File(OfflineInstaller.FULL_INSTALL_PATH, "db");
    File dbDir = new File(Utils.getInstallPathFromClasspath(), "db");
    File[] children = dbDir.listFiles();
    if ((children != null) && (children.length > 0))
    {
@@ -262,18 +378,19 @@
      StringBuffer buf = new StringBuffer();
      try
      {
        BufferedReader in =
            new BufferedReader(new FileReader(getConfigFilePath()));
        FileReader reader = new FileReader(getConfigFilePath());
        BufferedReader in = new BufferedReader(reader);
        String line;
        // We do not care about encoding: we are just interested in the ports
        while ((line = in.readLine()) != null)
        {
          buf.append(line + System.getProperty("line.separator"));
        }
        configFileContents = buf.toString().toLowerCase();
        reader.close();
      } catch (IOException ioe)
      {
      }
      configFileContents = buf.toString().toLowerCase();
    }
    return configFileContents;
  }
@@ -296,4 +413,39 @@
  {
    return ResourceProvider.getInstance();
  }
  private void updateSetWithValues(Set<String> set, String attrName)
  {
    attrName += ":";
    int index1 = getConfigFileContents().indexOf(attrName);
    while (index1 != -1)
    {
      int index2 = getConfigFileContents().indexOf(
            System.getProperty("line.separator"), index1);
      String value;
      if (index2 > (index1 + attrName.length()))
      {
        value = getConfigFileContents().substring(attrName.length() + index1,
              index2).trim();
      }
      else if (getConfigFileContents().length() > (index1 + attrName.length()))
      {
        // Assume end of file
        value = getConfigFileContents().substring(
            attrName.length() + index1).trim();
      }
      else
      {
        value = null;
      }
      if ((value != null) && (value.length() > 0))
      {
        set.add(value);
      }
      index1 = getConfigFileContents().indexOf(attrName,
          index1 + attrName.length());
    }
  }
}
opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
@@ -28,16 +28,19 @@
package org.opends.quicksetup;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.swing.SwingUtilities;
import org.opends.quicksetup.event.ButtonActionListener;
import org.opends.quicksetup.event.ButtonEvent;
import org.opends.quicksetup.event.ProgressUpdateEvent;
import org.opends.quicksetup.event.ProgressUpdateListener;
import org.opends.quicksetup.event.InstallProgressUpdateEvent;
import org.opends.quicksetup.event.InstallProgressUpdateListener;
import org.opends.quicksetup.event.UninstallProgressUpdateEvent;
import org.opends.quicksetup.event.UninstallProgressUpdateListener;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.installer.DataOptions;
import org.opends.quicksetup.installer.FieldName;
@@ -49,11 +52,15 @@
import org.opends.quicksetup.installer.offline.OfflineInstaller;
import org.opends.quicksetup.installer.webstart.WebStartDownloader;
import org.opends.quicksetup.installer.webstart.WebStartInstaller;
import org.opends.quicksetup.ui.DirectoryManagerAuthenticationDialog;
import org.opends.quicksetup.ui.QuickSetupDialog;
import org.opends.quicksetup.ui.UIFactory;
import org.opends.quicksetup.uninstaller.UninstallProgressDescriptor;
import org.opends.quicksetup.uninstaller.UninstallProgressStep;
import org.opends.quicksetup.uninstaller.Uninstaller;
import org.opends.quicksetup.uninstaller.UserUninstallData;
import org.opends.quicksetup.uninstaller.UserUninstallDataException;
import org.opends.quicksetup.util.BackgroundTask;
import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.util.Utils;
@@ -78,10 +85,14 @@
 * the InstallProgressStep.DOWNLOADING step.
 *
 */
class QuickSetup implements ButtonActionListener, ProgressUpdateListener
class QuickSetup implements ButtonActionListener, InstallProgressUpdateListener,
UninstallProgressUpdateListener
{
  // Contains the data provided by the user
  private UserInstallData userData;
  // Contains the data provided by the user in the install
  private UserInstallData userInstallData;
  // Contains the data provided by the user in the uninstall
  private UserUninstallData userUninstallData;
  private Installer installer;
@@ -97,11 +108,17 @@
  private StringBuffer progressDetails = new StringBuffer();
  private InstallProgressDescriptor lastDescriptor;
  private InstallProgressDescriptor lastInstallDescriptor;
  private InstallProgressDescriptor lastDisplayedDescriptor;
  private InstallProgressDescriptor lastDisplayedInstallDescriptor;
  private InstallProgressDescriptor descriptorToDisplay;
  private InstallProgressDescriptor installDescriptorToDisplay;
  private UninstallProgressDescriptor lastUninstallDescriptor;
  private UninstallProgressDescriptor lastDisplayedUninstallDescriptor;
  private UninstallProgressDescriptor uninstallDescriptorToDisplay;
  // Constants used to do checks
  private static final int MIN_DIRECTORY_MANAGER_PWD = 1;
@@ -135,6 +152,7 @@
    }
    installStatus = new CurrentInstallStatus();
    initLookAndFeel();
    /* In the calls to setCurrentStep the dialog will be created */
    if (Utils.isUninstall())
    {
      setCurrentStep(Step.CONFIRM_UNINSTALL);
@@ -183,6 +201,10 @@
      previousClicked();
      break;
    case CANCEL:
      cancelClicked();
      break;
    default:
      throw new IllegalArgumentException("Unknown button name: "
          + ev.getButtonName());
@@ -190,42 +212,70 @@
  }
  /**
   * ProgressUpdateListener implementation. Here we take the ProgressUpdateEvent
   * and create a ProgressDescriptor that will be used to update the progress
   * dialog.
   * InstallProgressUpdateListener implementation. Here we take the
   * InstallProgressUpdateEvent and create an InstallProgressDescriptor that
   * will be used to update the progress dialog.
   *
   * @param ev the ProgressUpdateEvent we receive.
   * @param ev the InstallProgressUpdateEvent we receive.
   *
   * @see #runDisplayUpdater()
   */
  public void progressUpdate(ProgressUpdateEvent ev)
  public void progressUpdate(InstallProgressUpdateEvent ev)
  {
    synchronized (this)
    {
      InstallProgressDescriptor desc = createProgressDescriptor(ev);
      InstallProgressDescriptor desc = createInstallProgressDescriptor(ev);
      boolean isLastDescriptor =
          desc.getProgressStep() == InstallProgressStep.FINISHED_SUCCESSFULLY
              || desc.getProgressStep() ==
                InstallProgressStep.FINISHED_WITH_ERROR;
      if (isLastDescriptor)
      {
        lastDescriptor = desc;
        lastInstallDescriptor = desc;
      }
      descriptorToDisplay = desc;
      installDescriptorToDisplay = desc;
    }
  }
  /**
   * UninstallProgressUpdateListener implementation. Here we take the
   * UninstallProgressUpdateEvent and create an UninstallProgressDescriptor that
   * will be used to update the progress dialog.
   *
   * @param ev the UninstallProgressUpdateEvent we receive.
   *
   * @see #runDisplayUpdater()
   */
  public void progressUpdate(UninstallProgressUpdateEvent ev)
  {
    synchronized (this)
    {
      UninstallProgressDescriptor desc = createUninstallProgressDescriptor(ev);
      boolean isLastDescriptor =
          desc.getProgressStep() == UninstallProgressStep.FINISHED_SUCCESSFULLY
              || desc.getProgressStep() ==
                UninstallProgressStep.FINISHED_WITH_ERROR;
      if (isLastDescriptor)
      {
        lastUninstallDescriptor = desc;
      }
      uninstallDescriptorToDisplay = desc;
    }
  }
  /**
   * This method is used to update the progress dialog.
   *
   * We are receiving notifications from the installer (this class is a
   * ProgressListener). However if we lots of notifications updating the
   * progress panel every time we get a progress update can result of a lot of
   * flickering. So the idea here is to have a minimal time between 2 updates of
   * the progress dialog (specified by UPDATE_PERIOD).
   * We are receiving notifications from the installer and uninstaller (this
   * class is a ProgressListener). However if we lots of notifications updating
   * the progress panel every time we get a progress update can result of a lot
   * of flickering. So the idea here is to have a minimal time between 2 updates
   * of the progress dialog (specified by UPDATE_PERIOD).
   *
   * @see #progressUpdate(ProgressUpdateEvent ev)
   * @see #progressUpdate(InstallProgressUpdateEvent ev)
   * @see #progressUpdate(UninstallProgressUpdateEvent ev)
   *
   */
  private void runDisplayUpdater()
@@ -241,22 +291,45 @@
      }
      synchronized (this)
      {
        final InstallProgressDescriptor desc = descriptorToDisplay;
        if (desc != null)
        if (Utils.isUninstall())
        {
          if (desc != lastDisplayedDescriptor)
          final UninstallProgressDescriptor desc = uninstallDescriptorToDisplay;
          if (desc != null)
          {
            lastDisplayedDescriptor = desc;
            SwingUtilities.invokeLater(new Runnable()
            if (desc != lastDisplayedUninstallDescriptor)
            {
              public void run()
              lastDisplayedUninstallDescriptor = desc;
              SwingUtilities.invokeLater(new Runnable()
              {
                getDialog().displayProgress(desc);
              }
            });
                public void run()
                {
                  getDialog().displayProgress(desc);
                }
              });
            }
            doPool = desc != lastUninstallDescriptor;
          }
          doPool = desc != lastDescriptor;
        }
        else
        {
          final InstallProgressDescriptor desc = installDescriptorToDisplay;
          if (desc != null)
          {
            if (desc != lastDisplayedInstallDescriptor)
            {
              lastDisplayedInstallDescriptor = desc;
              SwingUtilities.invokeLater(new Runnable()
              {
                public void run()
                {
                  getDialog().displayProgress(desc);
                }
              });
            }
            doPool = desc != lastInstallDescriptor;
          }
        }
      }
    }
@@ -285,11 +358,16 @@
        {
          try
          {
            updateUserData(cStep);
          } catch (RuntimeException re)
            updateUserInstallData(cStep);
          }
          catch (UserInstallDataException uide)
          {
            throw new UserInstallDataException(getCurrentStep(),
                getExceptionMsg("bug-msg", re));
            throw uide;
          }
          catch (Throwable t)
          {
            throw new UserInstallDataException(cStep,
                getThrowableMsg("bug-msg", t));
          }
          return null;
        }
@@ -298,11 +376,13 @@
            Throwable throwable)
        {
          getDialog().workerFinished();
          UserInstallDataException ude = (UserInstallDataException)throwable;
          if (ude != null)
          if (throwable != null)
          {
            UserInstallDataException ude = (UserInstallDataException)throwable;
            displayError(ude.getLocalizedMessage(), getMsg("error-title"));
          } else
          }
          else
          {
            setCurrentStep(nextStep(cStep));
          }
@@ -319,7 +399,7 @@
   */
  private void finishClicked()
  {
    Step cStep = getCurrentStep();
    final Step cStep = getCurrentStep();
    switch (cStep)
    {
    case REVIEW:
@@ -329,8 +409,93 @@
      break;
    case CONFIRM_UNINSTALL:
      launchUninstallation();
      setCurrentStep(Step.PROGRESS);
      BackgroundTask worker = new BackgroundTask()
      {
        public Object processBackgroundTask() throws UserUninstallDataException
        {
          try
          {
            updateUserDataForConfirmUninstallPanel();
          }
          catch (UserUninstallDataException uude)
          {
            throw uude;
          } catch (Throwable t)
          {
            throw new UserUninstallDataException(cStep,
                getThrowableMsg("bug-msg", t));
          }
          return new Boolean(installStatus.isServerRunning());
        }
        public void backgroundTaskCompleted(Object returnValue,
            Throwable throwable)
        {
          getDialog().workerFinished();
          if (throwable != null)
          {
            UserUninstallDataException ude =
              (UserUninstallDataException)throwable;
            displayError(ude.getLocalizedMessage(), getMsg("error-title"));
          } else
          {
            boolean serverRunning = ((Boolean)returnValue).booleanValue();
            if (!serverRunning)
            {
              getUserUninstallData().setStopServer(false);
              if (displayConfirmation(
                  getMsg("confirm-uninstall-server-not-running-msg"),
                  getMsg("confirm-uninstall-server-not-running-title")))
              {
                launchUninstallation();
                setCurrentStep(nextStep(cStep));
              }
            }
            else
            {
              if (Utils.isUnix())
              {
                if (displayConfirmation(
                    getMsg("confirm-uninstall-server-running-unix-msg"),
                    getMsg("confirm-uninstall-server-running-unix-title")))
                {
                  getUserUninstallData().setStopServer(true);
                  launchUninstallation();
                  setCurrentStep(nextStep(cStep));
                }
                else
                {
                  getUserUninstallData().setStopServer(false);
                }
              }
              else
              {
                DirectoryManagerAuthenticationDialog dlg =
                  new DirectoryManagerAuthenticationDialog(
                      getDialog().getFrame(), installStatus);
                dlg.setModal(true);
                dlg.packAndShow();
                if (dlg.isCancelled())
                {
                  getUserUninstallData().setStopServer(false);
                }
                else
                {
                  getUserUninstallData().setStopServer(dlg.getStopServer());
                  getUserUninstallData().setDirectoryManagerDn(
                      dlg.getDirectoryManagerDn());
                  getUserUninstallData().setDirectoryManagerPwd(
                      dlg.getDirectoryManagerPwd());
                  launchUninstallation();
                  setCurrentStep(nextStep(cStep));
                }
              }
            }
          }
        }
      };
      getDialog().workerStarted();
      worker.startBackgroundTask();
      break;
    default:
@@ -375,11 +540,16 @@
          "Cannot click on quit from progress step");
    default:
      if (installStatus.isInstalled())
      if (Utils.isUninstall())
      {
        quit();
      } else if (displayConfirmation(getMsg("confirm-quit-quicksetup-msg"),
          getMsg("confirm-quit-quicksetup-title")))
      }
      else if (installStatus.isInstalled())
      {
        quit();
      } else if (displayConfirmation(getMsg("confirm-quit-install-msg"),
          getMsg("confirm-quit-install-title")))
      {
        quit();
      }
@@ -409,8 +579,8 @@
      {
        boolean finished = installer.isFinished();
        if (finished
            || displayConfirmation(getMsg("confirm-close-quicksetup-msg"),
                getMsg("confirm-close-quicksetup-title")))
            || displayConfirmation(getMsg("confirm-close-install-msg"),
                getMsg("confirm-close-install-title")))
        {
          quit();
        }
@@ -424,6 +594,25 @@
  }
  /**
   * Method called when user clicks 'Cancel' button of the wizard.
   *
   */
  private void cancelClicked()
  {
    Step cStep = getCurrentStep();
    switch (cStep)
    {
    case CONFIRM_UNINSTALL:
      quit();
      break;
    default:
      throw new IllegalStateException(
          "Cancel only can be clicked on CONFIRM_UNINSTALL step");
    }
  }
  /**
   * Method called when we want to quit the setup (for instance when the user
   * clicks on 'Close' or 'Quit' buttons and has confirmed that (s)he wants to
   * quit the program.
@@ -436,7 +625,7 @@
  /**
   * These methods validate the data provided by the user in the panels and
   * update the UserData object according to that content.
   * update the UserInstallData object according to that content.
   *
   * @param cStep
   *          the current step of the wizard
@@ -446,12 +635,12 @@
   *           valid.
   *
   */
  private void updateUserData(Step cStep) throws UserInstallDataException
  private void updateUserInstallData(Step cStep) throws UserInstallDataException
  {
    switch (cStep)
    {
    case SERVER_SETTINGS:
      updateUserDataForServerSettingsPanel();
      updateUserInstallDataForServerSettingsPanel();
      break;
    case DATA_OPTIONS:
@@ -466,14 +655,14 @@
  /**
   * Validate the data provided by the user in the server settings panel and
   * update the UserData object according to that content.
   * update the UserInstallData object according to that content.
   *
   * @throws an
   *           UserInstallDataException if the data provided by the user is not
   *           valid.
   *
   */
  private void updateUserDataForServerSettingsPanel()
  private void updateUserInstallDataForServerSettingsPanel()
      throws UserInstallDataException
  {
    ArrayList<String> errorMsgs = new ArrayList<String>();
@@ -523,7 +712,7 @@
      } else
      {
        getUserData().setServerLocation(serverLocation);
        getUserInstallData().setServerLocation(serverLocation);
        displayFieldInvalid(FieldName.SERVER_LOCATION, false);
      }
    }
@@ -554,7 +743,7 @@
      } else
      {
        getUserData().setServerPort(port);
        getUserInstallData().setServerPort(port);
        displayFieldInvalid(FieldName.SERVER_PORT, false);
      }
@@ -583,7 +772,7 @@
      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true);
    } else
    {
      getUserData().setDirectoryManagerDn(dmDn);
      getUserInstallData().setDirectoryManagerDn(dmDn);
      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, false);
    }
@@ -617,7 +806,7 @@
    if (pwdValid)
    {
      getUserData().setDirectoryManagerPwd(pwd1);
      getUserInstallData().setDirectoryManagerPwd(pwd1);
      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD, false);
      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, false);
    }
@@ -625,13 +814,13 @@
    if (errorMsgs.size() > 0)
    {
      throw new UserInstallDataException(Step.SERVER_SETTINGS,
          getStringFromCollection(errorMsgs));
          Utils.getStringFromCollection(errorMsgs, "\n"));
    }
  }
  /**
   * Validate the data provided by the user in the data options panel and update
   * the UserData object according to that content.
   * the UserInstallData object according to that content.
   *
   * @throws an
   *           UserInstallDataException if the data provided by the user is not
@@ -742,24 +931,77 @@
    if (dataOptions != null)
    {
      getUserData().setDataOptions(dataOptions);
      getUserInstallData().setDataOptions(dataOptions);
    }
    if (errorMsgs.size() > 0)
    {
      throw new UserInstallDataException(Step.DATA_OPTIONS,
          getStringFromCollection(errorMsgs));
          Utils.getStringFromCollection(errorMsgs, "\n"));
    }
  }
  /**
   * Update the UserData object according to the content of the review panel.
   * Update the UserInstallData object according to the content of the review
   * panel.
   *
   */
  private void updateUserDataForReviewPanel()
  {
    Boolean b = (Boolean) getFieldValue(FieldName.SERVER_START);
    getUserData().setStartServer(b.booleanValue());
    getUserInstallData().setStartServer(b.booleanValue());
  }
  /**
   * Update the UserUninstallData object according to the content of the review
   * panel.
   *
   */
  private void updateUserDataForConfirmUninstallPanel()
  throws UserUninstallDataException
  {
    getUserUninstallData().setRemoveLibrariesAndTools(
        (Boolean)getFieldValue(FieldName.REMOVE_LIBRARIES_AND_TOOLS));
    getUserUninstallData().setRemoveDatabases(
        (Boolean)getFieldValue(FieldName.REMOVE_DATABASES));
    getUserUninstallData().setRemoveConfigurationAndSchema(
        (Boolean)getFieldValue(FieldName.REMOVE_CONFIGURATION_AND_SCHEMA));
    getUserUninstallData().setRemoveBackups(
        (Boolean)getFieldValue(FieldName.REMOVE_BACKUPS));
    getUserUninstallData().setRemoveLDIFs(
        (Boolean)getFieldValue(FieldName.REMOVE_LDIFS));
    getUserUninstallData().setRemoveLogs(
        (Boolean)getFieldValue(FieldName.REMOVE_LOGS));
    Set<String> dbs = new HashSet<String>();
    Set s = (Set)getFieldValue(FieldName.EXTERNAL_DB_DIRECTORIES);
    for (Object v: s)
    {
      dbs.add((String)v);
    }
    Set<String> logs = new HashSet<String>();
    s = (Set)getFieldValue(FieldName.EXTERNAL_LOG_FILES);
    for (Object v: s)
    {
      logs.add((String)v);
    }
    getUserUninstallData().setExternalDbsToRemove(dbs);
    getUserUninstallData().setExternalLogsToRemove(logs);
    if ((dbs.size() == 0) &&
        (logs.size() == 0) &&
        !getUserUninstallData().getRemoveLibrariesAndTools() &&
        !getUserUninstallData().getRemoveDatabases() &&
        !getUserUninstallData().getRemoveConfigurationAndSchema() &&
        !getUserUninstallData().getRemoveBackups() &&
        !getUserUninstallData().getRemoveLDIFs() &&
        !getUserUninstallData().getRemoveLogs())
    {
      throw new UserUninstallDataException(Step.CONFIRM_UNINSTALL,
          getMsg("nothing-selected-to-uninstall"));
    }
  }
  /**
@@ -769,14 +1011,14 @@
   */
  private void launchInstallation()
  {
    ProgressMessageFormatter formatter = new HtmlProgressMessageFormatter();
    ProgressMessageFormatter formatter = getDialog().getFormatter();
    if (isWebStart())
    {
      installer = new WebStartInstaller(getUserData(), jnlpDownloader,
      installer = new WebStartInstaller(getUserInstallData(), jnlpDownloader,
          formatter);
    } else
    {
      installer = new OfflineInstaller(getUserData(), formatter);
      installer = new OfflineInstaller(getUserInstallData(), formatter);
    }
    installer.addProgressUpdateListener(this);
    installer.start();
@@ -796,8 +1038,18 @@
   */
  private void launchUninstallation()
  {
    uninstaller = new Uninstaller();
    // TO COMPLETE
    uninstaller = new Uninstaller(getUserUninstallData(),
        getDialog().getFormatter());
    uninstaller.addProgressUpdateListener(this);
    uninstaller.start();
    Thread t = new Thread(new Runnable()
    {
      public void run()
      {
        runDisplayUpdater();
      }
    });
    t.start();
  }
  /**
@@ -807,13 +1059,29 @@
   * @return the UserInstallData representing the data provided by the user in
   *         the Install wizard.
   */
  private UserInstallData getUserData()
  private UserInstallData getUserInstallData()
  {
    if (userData == null)
    if (userInstallData == null)
    {
      userData = new UserInstallData();
      userInstallData = new UserInstallData();
    }
    return userData;
    return userInstallData;
  }
  /**
   * Provides the object representing the data provided by the user in the
   * uninstall.
   *
   * @return the UserUninstallData representing the data provided by the user in
   *         the Uninstall wizard.
   */
  private UserUninstallData getUserUninstallData()
  {
    if (userUninstallData == null)
    {
      userUninstallData = new UserUninstallData();
    }
    return userUninstallData;
  }
  /**
@@ -860,9 +1128,9 @@
    return getI18n().getMsg(key, args);
  }
  private String getExceptionMsg(String key, Exception ex)
  private String getThrowableMsg(String key, Throwable t)
  {
    return Utils.getExceptionMsg(getI18n(), key, null, ex);
    return Utils.getThrowableMsg(getI18n(), key, null, t);
  }
  private ResourceProvider getI18n()
@@ -895,7 +1163,7 @@
      throw new NullPointerException("step is null");
    }
    currentStep = step;
    getDialog().setDisplayedStep(step, getUserData());
    getDialog().setDisplayedStep(step, getUserInstallData());
  }
  /**
@@ -909,13 +1177,22 @@
   */
  private Step nextStep(Step step)
  {
    Iterator<Step> it = EnumSet.range(step, Step.PROGRESS).iterator();
    it.next();
    if (!it.hasNext())
    Step nextStep;
    if (step == Step.CONFIRM_UNINSTALL)
    {
      throw new IllegalArgumentException("No next for step: " + step);
      nextStep = Step.PROGRESS;
    }
    return it.next();
    else
    {
      Iterator<Step> it = EnumSet.range(step, Step.PROGRESS).iterator();
      it.next();
      if (!it.hasNext())
      {
        throw new IllegalArgumentException("No next for step: " + step);
      }
      nextStep = it.next();
    }
    return nextStep;
  }
  /**
@@ -1038,31 +1315,6 @@
  }
  /**
   * This is a helper method that gets a String representation of the elements
   * in the Collection. The String will display the different elements separated
   * by a '\n' character.
   *
   * @param col
   *          the collection containing the String.
   * @return the String representation for the collection.
   */
  private String getStringFromCollection(Collection<String> col)
  {
    String msg = null;
    for (String m : col)
    {
      if (msg == null)
      {
        msg = m;
      } else
      {
        msg += "\n" + m;
      }
    }
    return msg;
  }
  /**
   * A method to initialize the look and feel.
   *
   */
@@ -1072,16 +1324,16 @@
  }
  /**
   * A methods that creates a InstallProgressDescriptor based on the value of a
   * ProgressUpdateEvent.
   * A methods that creates an InstallProgressDescriptor based on the value of a
   * InstallProgressUpdateEvent.
   *
   * @param ev
   *          the ProgressUpdateEvent used to generate the
   *          the InstallProgressUpdateEvent used to generate the
   *          InstallProgressDescriptor.
   * @return the InstallProgressDescriptor.
   */
  private InstallProgressDescriptor createProgressDescriptor(
      ProgressUpdateEvent ev)
  private InstallProgressDescriptor createInstallProgressDescriptor(
      InstallProgressUpdateEvent ev)
  {
    InstallProgressStep status = ev.getProgressStep();
    String newProgressLabel = ev.getCurrentPhaseSummary();
@@ -1098,6 +1350,32 @@
  }
  /**
   * A methods that creates an UninstallProgressDescriptor based on the value of
   * a UninstallProgressUpdateEvent.
   *
   * @param ev
   *          the UninstallProgressUpdateEvent used to generate the
   *          UninstallProgressDescriptor.
   * @return the InstallProgressDescriptor.
   */
  private UninstallProgressDescriptor createUninstallProgressDescriptor(
      UninstallProgressUpdateEvent ev)
  {
    UninstallProgressStep status = ev.getProgressStep();
    String newProgressLabel = ev.getCurrentPhaseSummary();
    String additionalDetails = ev.getNewLogs();
    Integer ratio = ev.getProgressRatio();
    if (additionalDetails != null)
    {
      progressDetails.append(additionalDetails);
    }
    return new UninstallProgressDescriptor(status, ratio, newProgressLabel,
        progressDetails.toString());
  }
  /**
   * Indicates whether we are in a web start installation or not.
   *
   * @return <CODE>true</CODE> if we are in a web start installation and
@@ -1118,9 +1396,14 @@
  private int getDefaultPort()
  {
    int defaultPort = -1;
    if (Utils.canUseAsPort(389))
    for (int i=0;i<10000 && (defaultPort == -1);i+=1000)
    {
      defaultPort = 389;
      int port = i + 389;
      if (Utils.canUseAsPort(port))
      {
        defaultPort = port;
      }
    }
    return defaultPort;
  }
opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateEvent.java
File was renamed from opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
@@ -35,11 +35,11 @@
 * configuring the server for instance).
 *
 * In the current implementation this events are generated by the Installer
 * objects and are notified to the objects implementing ProgressUpdateListener
 * (QuickSetup object).
 * objects and are notified to the objects implementing
 * InstallProgressUpdateListener (QuickSetup object).
 *
 */
public class ProgressUpdateEvent
public class InstallProgressUpdateEvent
{
  private InstallProgressStep step;
@@ -50,7 +50,7 @@
  private String newLogs;
  /**
   * Constructor of the ProgressUpdateEvent.
   * Constructor of the InstallProgressUpdateEvent.
   * @param step the InstallProgressStep object describing in which step
   * of the installation we are (configuring server, starting server, etc.)
   * @param progressRatio the integer that specifies which percentage of
@@ -59,7 +59,7 @@
   * current installation progress.
   * @param newLogs the new log messages that we have for the installation.
   */
  public ProgressUpdateEvent(InstallProgressStep step,
  public InstallProgressUpdateEvent(InstallProgressStep step,
      Integer progressRatio, String currentPhaseSummary, String newLogs)
  {
    this.step = step;
opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateListener.java
File was renamed from opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
@@ -32,13 +32,13 @@
 * updates in the installation progress.
 *
 */
public interface ProgressUpdateListener
public interface InstallProgressUpdateListener
{
  /**
   * Method called when an update in the installation progress occurs.
   *
   * @param ev the ProgressUpdateEvent describing the update that occurred in
   * the installation progress.
   * @param ev the InstallProgressUpdateEvent describing the update that
   * occurred in the installation progress.
   */
  public void progressUpdate(ProgressUpdateEvent ev);
  public void progressUpdate(InstallProgressUpdateEvent ev);
}
opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateEvent.java
copy from opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java copy to opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateEvent.java
File was copied from opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
@@ -27,21 +27,21 @@
package org.opends.quicksetup.event;
import org.opends.quicksetup.installer.InstallProgressStep;
import org.opends.quicksetup.uninstaller.UninstallProgressStep;
/**
 * The event that is generated when there is a change during the installation
 * The event that is generated when there is a change during the uninstallation
 * process (we get a new log message when starting the server, or we finished
 * configuring the server for instance).
 *
 * In the current implementation this events are generated by the Installer
 * objects and are notified to the objects implementing ProgressUpdateListener
 * (QuickSetup object).
 * In the current implementation this events are generated by the Uninstaller
 * object and are notified to the objects implementing
 * UninstallProgressUpdateListener (QuickSetup object).
 *
 */
public class ProgressUpdateEvent
public class UninstallProgressUpdateEvent
{
  private InstallProgressStep step;
  private UninstallProgressStep step;
  private Integer progressRatio;
@@ -50,8 +50,8 @@
  private String newLogs;
  /**
   * Constructor of the ProgressUpdateEvent.
   * @param step the InstallProgressStep object describing in which step
   * Constructor of the UninstallProgressUpdateEvent.
   * @param step the UninstallProgressStep object describing in which step
   * of the installation we are (configuring server, starting server, etc.)
   * @param progressRatio the integer that specifies which percentage of
   * the whole installation has been completed.
@@ -59,7 +59,7 @@
   * current installation progress.
   * @param newLogs the new log messages that we have for the installation.
   */
  public ProgressUpdateEvent(InstallProgressStep step,
  public UninstallProgressUpdateEvent(UninstallProgressStep step,
      Integer progressRatio, String currentPhaseSummary, String newLogs)
  {
    this.step = step;
@@ -100,7 +100,7 @@
   * Gets the current progress step.
   * @return the current progress step.
   */
  public InstallProgressStep getProgressStep()
  public UninstallProgressStep getProgressStep()
  {
    return step;
  }
opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateListener.java
copy from opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java copy to opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateListener.java
File was copied from opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
@@ -29,16 +29,16 @@
/**
 * Interface that implement the objects that want to receive notifications of
 * updates in the installation progress.
 * updates in the uninstallation progress.
 *
 */
public interface ProgressUpdateListener
public interface UninstallProgressUpdateListener
{
  /**
   * Method called when an update in the installation progress occurs.
   * Method called when an update in the uninstallation progress occurs.
   *
   * @param ev the ProgressUpdateEvent describing the update that occurred in
   * the installation progress.
   * @param ev the UninstallProgressUpdateEvent describing the update that
   * occurred in the installation progress.
   */
  public void progressUpdate(ProgressUpdateEvent ev);
  public void progressUpdate(UninstallProgressUpdateEvent ev);
}
opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
@@ -182,8 +182,8 @@
        }
      } catch (java.util.MissingResourceException e)
      {
        throw new IllegalStateException("Missing Resource Bundle: "
            + BUNDLE_NAME);
        throw new IllegalStateException("Could not retrieve Resource Bundle: "
            + BUNDLE_NAME, e);
      }
    }
opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java
@@ -78,5 +78,37 @@
  /**
   * The value associated with this is a Boolean.
   */
  SERVER_START
  SERVER_START,
  /**
   * The value associated with this is a Boolean.
   */
  REMOVE_LIBRARIES_AND_TOOLS,
  /**
   * The value associated with this is a Boolean.
   */
  REMOVE_DATABASES,
  /**
   * The value associated with this is a Boolean.
   */
  REMOVE_LOGS,
  /**
   * The value associated with this is a Boolean.
   */
  REMOVE_CONFIGURATION_AND_SCHEMA,
  /**
   * The value associated with this is a Boolean.
   */
  REMOVE_BACKUPS,
  /**
   * The value associated with this is a Boolean.
   */
  REMOVE_LDIFS,
  /**
   * The value associated with this is a Set of String.
   */
  EXTERNAL_DB_DIRECTORIES,
  /**
   * The value associated with this is a Set of String.
   */
  EXTERNAL_LOG_FILES
}
opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java
@@ -82,7 +82,7 @@
   * @param localizedMsg a localized string describing the problem.
   * @param rootCause the root cause of this exception.
   */
  public InstallException(Type type, String localizedMsg, Exception rootCause)
  public InstallException(Type type, String localizedMsg, Throwable rootCause)
  {
    super(localizedMsg, rootCause);
    this.type = type;
opends/src/quicksetup/org/opends/quicksetup/installer/InstallLauncher.java
File was renamed from opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java
@@ -24,14 +24,14 @@
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.quicksetup;
package org.opends.quicksetup.installer;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import org.opends.quicksetup.SplashScreen;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.installer.offline.OfflineInstaller;
import org.opends.quicksetup.util.Utils;
/**
@@ -41,7 +41,7 @@
 * based setup much be launched.
 *
 */
public class SetupLauncher
public class InstallLauncher
{
  private static String COMMAND_NAME_WINDOWS = "setup.bat";
@@ -137,6 +137,8 @@
   */
  private static int launchCliSetup(String[] args)
  {
    System.setProperty("org.opends.quicksetup.cli", "true");
    if (Utils.isWindows())
    {
      System.setProperty("org.opends.server.scriptName",
@@ -160,7 +162,7 @@
    newArgList.add("--configClass");
    newArgList.add("org.opends.server.extensions.ConfigFileHandler");
    newArgList.add("--configFile");
    newArgList.add(OfflineInstaller.CONFIG_FILE_NAME);
    newArgList.add(Utils.getConfigFileFromClasspath());
    String[] newArgs = new String[newArgList.size()];
    newArgList.toArray(newArgs);
opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -36,8 +36,10 @@
import java.util.HashSet;
import java.util.Map;
import org.opends.quicksetup.event.ProgressUpdateEvent;
import org.opends.quicksetup.event.ProgressUpdateListener;
import javax.naming.NamingException;
import org.opends.quicksetup.event.InstallProgressUpdateEvent;
import org.opends.quicksetup.event.InstallProgressUpdateListener;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.util.Utils;
@@ -50,11 +52,14 @@
 * It just takes a UserInstallData object and based on that installs OpenDS.
 *
 * When there is an update during the installation it will notify the
 * ProgressUpdateListener objects that have been added to it.  The notification
 * will send a ProgressUpdateEvent.
 * InstallProgressUpdateListener objects that have been added to it.  The
 * notification will send a InstallProgressUpdateEvent.
 *
 * This class is supposed to be fully independent of the graphical layout.
 *
 * Note that we can use freely the class org.opends.server.util.SetupUtils as
 * it is included in quicksetup.jar.
 *
 */
public abstract class Installer
{
@@ -64,19 +69,8 @@
  protected static final String CONFIG_PATH_RELATIVE =
      "config" + File.separator + "config.ldif";
  /**
   * The relative path where all the binaries (scripts) are.
   */
  protected static final String BINARIES_PATH_RELATIVE = "bin";
  /**
   * The relative paths to the jar files required by the install.
   */
  protected static final String[] OPEN_DS_JAR_RELATIVE_PATHS =
    { "lib/OpenDS.jar", "lib/je.jar" };
  private HashSet<ProgressUpdateListener> listeners =
      new HashSet<ProgressUpdateListener>();
  private HashSet<InstallProgressUpdateListener> listeners =
      new HashSet<InstallProgressUpdateListener>();
  private UserInstallData userData;
@@ -87,7 +81,7 @@
   * @param userData the user data definining the parameters of the
   * installation.
   * @param formatter the message formatter to be used to generate the text of
   * the ProgressUpdateEvent
   * the InstallProgressUpdateEvent
   */
  protected Installer(UserInstallData userData,
      ProgressMessageFormatter formatter)
@@ -97,20 +91,20 @@
  }
  /**
   * Adds a ProgressUpdateListener that will be notified of updates in the
   * install progress.
   * @param l the ProgressUpdateListener to be added.
   * Adds a InstallProgressUpdateListener that will be notified of updates in
   * the install progress.
   * @param l the InstallProgressUpdateListener to be added.
   */
  public void addProgressUpdateListener(ProgressUpdateListener l)
  public void addProgressUpdateListener(InstallProgressUpdateListener l)
  {
    listeners.add(l);
  }
  /**
   * Removes a ProgressUpdateListener.
   * @param l the ProgressUpdateListener to be removed.
   * Removes a InstallProgressUpdateListener.
   * @param l the InstallProgressUpdateListener to be removed.
   */
  public void removeProgressUpdateListener(ProgressUpdateListener l)
  public void removeProgressUpdateListener(InstallProgressUpdateListener l)
  {
    listeners.remove(l);
  }
@@ -152,22 +146,22 @@
  }
  /**
   * This method notifies the ProgressUpdateListeners that there was an update
   * in the installation progress.
   * This method notifies the InstallProgressUpdateListeners that there was an
   * update in the installation progress.
   * @param ratio the integer that specifies which percentage of
   * the whole installation has been completed.
   * @param currentPhaseSummary the localized summary message for the
   * current installation progress in HTML form.
   * current installation progress in formatted form.
   * @param newLogDetail the new log messages that we have for the
   * installation in HTML form.
   * installation in formatted form.
   */
  protected void notifyListeners(Integer ratio, String currentPhaseSummary,
      String newLogDetail)
  {
    ProgressUpdateEvent ev =
        new ProgressUpdateEvent(getStatus(), ratio, currentPhaseSummary,
    InstallProgressUpdateEvent ev =
        new InstallProgressUpdateEvent(getStatus(), ratio, currentPhaseSummary,
            newLogDetail);
    for (ProgressUpdateListener l : listeners)
    for (InstallProgressUpdateListener l : listeners)
    {
      l.progressUpdate(ev);
    }
@@ -218,27 +212,27 @@
  }
  /**
   * Returns a localized message for a given properties key an exception.
   * Returns a localized message for a given properties key and throwable.
   * @param key the key of the message in the properties file.
   * @param ex the exception for which we want to get a message.
   * @return a localized message for a given properties key an exception.
   * @param t the throwable for which we want to get a message.
   * @return a localized message for a given properties key and throwable.
   */
  protected String getExceptionMsg(String key, Exception ex)
  protected String getThrowableMsg(String key, Throwable t)
  {
    return getExceptionMsg(key, null, ex);
    return getThrowableMsg(key, null, t);
  }
  /**
   * Returns a localized message for a given properties key an exception.
   * Returns a localized message for a given properties key and throwable.
   * @param key the key of the message in the properties file.
   * @param args the arguments of the message in the properties file.
   * @param ex the exception for which we want to get a message.
   * @param t the throwable for which we want to get a message.
   *
   * @return a localized message for a given properties key an exception.
   * @return a localized message for a given properties key and throwable.
   */
  protected String getExceptionMsg(String key, String[] args, Exception ex)
  protected String getThrowableMsg(String key, String[] args, Throwable t)
  {
    return Utils.getExceptionMsg(getI18n(), key, args, ex);
    return Utils.getThrowableMsg(getI18n(), key, args, t);
  }
  /**
@@ -262,7 +256,7 @@
   */
  protected String getFormattedError(String text)
  {
    return formatter.getFormattedError(text);
    return formatter.getFormattedError(text, false);
  }
  /**
@@ -271,9 +265,9 @@
   * representation
   * @return the formatted representation of an warning for the given text.
   */
  public String getFormattedWarning(String text)
  protected String getFormattedWarning(String text)
  {
    return formatter.getFormattedWarning(text);
    return formatter.getFormattedWarning(text, false);
  }
  /**
@@ -283,7 +277,7 @@
   * @return the formatted representation of an success message for the given
   * text.
   */
  public String getFormattedSuccess(String text)
  protected String getFormattedSuccess(String text)
  {
    return formatter.getFormattedSuccess(text);
  }
@@ -302,10 +296,10 @@
  }
  /**
   * Returns the HTML representation of a log message for a given text.
   * @param text the source text from which we want to get the HTML
   * Returns the formatted representation of a log message for a given text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the HTML representation of a log message for the given text.
   * @return the formatted representation of a log message for the given text.
   */
  protected String getFormattedLog(String text)
  {
@@ -334,10 +328,12 @@
  }
  /**
   * Returns the HTML representation of a progress message for a given text.
   * @param text the source text from which we want to get the HTML
   * Returns the formatted representation of a progress message for a given
   * text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the HTML representation of a progress message for the given text.
   * @return the formatted representation of a progress message for the given
   * text.
   */
  protected String getFormattedProgress(String text)
  {
@@ -397,7 +393,7 @@
    }
    catch (IOException ioe)
    {
      String failedMsg = getExceptionMsg("error-creating-temp-file", null, ioe);
      String failedMsg = getThrowableMsg("error-creating-temp-file", null, ioe);
      throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
          failedMsg, ioe);
    }
@@ -405,7 +401,7 @@
  /**
   * This method is called when a new log message has been received.  It will
   * notify the ProgressUpdateListeners of this fact.
   * notify the InstallProgressUpdateListeners of this fact.
   * @param newLogDetail the new log detail.
   */
  protected void notifyListeners(String newLogDetail)
@@ -431,10 +427,10 @@
  protected abstract Integer getRatio(InstallProgressStep step);
  /**
   * Returns an HTML representation of the summary for the specified
   * Returns an formatted representation of the summary for the specified
   * InstallProgressStep.
   * @param step the InstallProgressStep for which we want to get the summary
   * @return an HTML representation of the summary for the specified
   * @return an formatted representation of the summary for the specified
   * InstallProgressStep.
   */
  protected abstract String getSummary(InstallProgressStep step);
@@ -443,11 +439,11 @@
   * This class is used to read the standard error and standard output of the
   * Start process.
   *
   * When a new log message is found notifies the ProgressUpdateListeners of
   * it. If an error occurs it also notifies the listeners.
   * When a new log message is found notifies the InstallProgressUpdateListeners
   * of it. If an error occurs it also notifies the listeners.
   *
   */
  abstract class StartReader
  private class StartReader
  {
    private InstallException ex;
@@ -463,7 +459,7 @@
     * @param isError a boolean indicating whether the BufferedReader
     * corresponds to the standard error or to the standard output.
     */
    protected StartReader(final BufferedReader reader, final String startedId,
    public StartReader(final BufferedReader reader, final String startedId,
        final boolean isError)
    {
      final String errorTag =
@@ -503,17 +499,17 @@
            }
          } catch (IOException ioe)
          {
            String errorMsg = getExceptionMsg(errorTag, ioe);
            String errorMsg = getThrowableMsg(errorTag, ioe);
            ex =
                new InstallException(InstallException.Type.START_ERROR,
                    errorMsg, ioe);
          } catch (RuntimeException re)
          } catch (Throwable t)
          {
            String errorMsg = getExceptionMsg(errorTag, re);
            String errorMsg = getThrowableMsg(errorTag, t);
            ex =
                new InstallException(InstallException.Type.START_ERROR,
                    errorMsg, re);
                    errorMsg, t);
          }
          isFinished = true;
        }
@@ -545,52 +541,14 @@
  }
  /**
   * A subclass of the StartReader class used to read the standard error of the
   * server start.
   *
   */
  protected class StartErrorReader extends StartReader
  {
    /**
     * Constructor of the StartErrorReader.
     * @param reader the BufferedReader that reads the standard error of the
     * Start process.
     * @param startedId the Message ID that
     */
    public StartErrorReader(BufferedReader reader, String startedId)
    {
      super(reader, startedId, true);
    }
  }
  /**
   * A subclass of the StartReader class used to read the standard output of
   * the server start.
   *
   */
  protected class StartOutputReader extends StartReader
  {
    /**
     * Constructor of the StartOutputReader.
     * @param reader the BufferedReader that reads the standard output of the
     * Start process.
     * @param startedId the Message ID that
     */
    public StartOutputReader(BufferedReader reader, String startedId)
    {
      super(reader, startedId, false);
    }
  }
  /**
   * This class is used to notify the ProgressUpdateListeners of events that
   * are written to the standard error.  It is used in WebStartInstaller and in
   * OfflineInstaller.  These classes just create a ErrorPrintStream and then
   * they do a call to System.err with it.
   * This class is used to notify the InstallProgressUpdateListeners of events
   * that are written to the standard error.  It is used in WebStartInstaller
   * and in OfflineInstaller.  These classes just create a ErrorPrintStream and
   * then they do a call to System.err with it.
   *
   * The class just reads what is written to the standard error, obtains an
   * HTML representation of it and then notifies the ProgressUpdateListeners
   * with the HTML messages.
   * formatted representation of it and then notifies the
   * InstallProgressUpdateListeners with the formatted messages.
   *
   */
  protected class ErrorPrintStream extends PrintStream
@@ -642,14 +600,14 @@
  }
  /**
   * This class is used to notify the ProgressUpdateListeners of events that are
   * written to the standard output. It is used in WebStartInstaller and in
   * OfflineInstaller. These classes just create a OutputPrintStream and then
   * they do a call to System.err with it.
   * This class is used to notify the InstallProgressUpdateListeners of events
   * that are written to the standard output. It is used in WebStartInstaller
   * and in OfflineInstaller. These classes just create a OutputPrintStream and
   * then they do a call to System.out with it.
   *
   * The class just reads what is written to the standard output, obtains an
   * HTML representation of it and then notifies the ProgressUpdateListeners
   * with the HTML messages.
   * formatted representation of it and then notifies the
   * InstallProgressUpdateListeners with the formatted messages.
   *
   */
  protected class OutputPrintStream extends PrintStream
@@ -741,11 +699,11 @@
            InstallException.Type.CONFIGURATION_ERROR,
            getMsg("error-configuring"), null);
      }
    } catch (RuntimeException re)
    } catch (Throwable t)
    {
      throw new InstallException(
          InstallException.Type.CONFIGURATION_ERROR,
          getExceptionMsg("error-configuring", null, re), re);
          getThrowableMsg("error-configuring", null, t), t);
    }
  }
@@ -793,11 +751,11 @@
            InstallException.Type.CONFIGURATION_ERROR,
            getMsg("error-creating-base-entry"), null);
      }
    } catch (RuntimeException re)
    } catch (Throwable t)
    {
      throw new InstallException(
          InstallException.Type.CONFIGURATION_ERROR,
          getExceptionMsg("error-creating-base-entry", null, re), re);
          getThrowableMsg("error-creating-base-entry", null, t), t);
    }
    notifyListeners(getFormattedDone());
@@ -840,11 +798,11 @@
            InstallException.Type.CONFIGURATION_ERROR,
            getMsg("error-importing-ldif"), null);
      }
    } catch (RuntimeException re)
    } catch (Throwable t)
    {
      throw new InstallException(
          InstallException.Type.CONFIGURATION_ERROR,
          getExceptionMsg("error-importing-ldif", null, re), re);
          getThrowableMsg("error-importing-ldif", null, t), t);
    }
  }
@@ -890,12 +848,11 @@
            InstallException.Type.CONFIGURATION_ERROR,
            getMsg("error-import-automatically-generated"), null);
      }
    } catch (RuntimeException re)
    } catch (Throwable t)
    {
      throw new InstallException(
          InstallException.Type.CONFIGURATION_ERROR,
          getExceptionMsg("error-import-automatically-generated", null, re),
          re);
          getThrowableMsg("error-import-automatically-generated", null, t), t);
    }
  }
@@ -917,25 +874,30 @@
    {
      argList.add(Utils.getPath(getBinariesPath(), "start-ds"));
    }
    String[] env =
      { "JAVA_HOME=" + System.getProperty("java.home") };
    String[] args = new String[argList.size()];
    argList.toArray(args);
    ProcessBuilder pb = new ProcessBuilder(args);
    Map<String, String> env = pb.environment();
    env.put("JAVA_HOME", System.getProperty("java.home"));
    /* Remove JAVA_BIN to be sure that we use the JVM running the installer
     * JVM to start the server.
     */
    env.remove("JAVA_BIN");
    try
    {
      String startedId = getStartedId();
      String[] args = new String[argList.size()];
      argList.toArray(args);
      // Process process = Runtime.getRuntime().exec(args);
      Process process = Runtime.getRuntime().exec(args, env);
      Process process = pb.start();
      BufferedReader err =
          new BufferedReader(new InputStreamReader(process.getErrorStream()));
      BufferedReader out =
          new BufferedReader(new InputStreamReader(process.getInputStream()));
      StartErrorReader errReader = new StartErrorReader(err, startedId);
      StartOutputReader outputReader = new StartOutputReader(out, startedId);
      StartReader errReader = new StartReader(err, startedId, true);
      StartReader outputReader = new StartReader(out, startedId, false);
      while (!errReader.isFinished() && !outputReader.isFinished())
      {
@@ -963,13 +925,49 @@
         * finished. This means that the server has written in its output the
         * message id informing that it started. So it seems that everything
         * went fine.
         *
         * However in Windows we can have issues with the firewalls.  Just check
         * if we can connect to the server.  Try 5 times with an interval of
         * 1 second between try.
         */
        boolean connected = false;
        for (int i=0; i<5 && !connected; i++)
        {
          String ldapUrl = "ldap://localhost:"+userData.getServerPort();
          try
          {
            Utils.createLdapContext(
                ldapUrl,
                userData.getDirectoryManagerDn(),
                userData.getDirectoryManagerPwd(), 3000, null);
            connected = true;
          }
          catch (NamingException ne)
          {
          }
          if (!connected)
          {
            try
            {
              Thread.sleep(1000);
            }
            catch (Throwable t)
            {
            }
          }
        }
        if (!connected)
        {
          String[] arg = {String.valueOf(userData.getServerPort())};
          throw new InstallException(InstallException.Type.START_ERROR,
              getMsg("error-starting-server-in-windows", arg), null);
        }
      }
    } catch (IOException ioe)
    {
      throw new InstallException(InstallException.Type.START_ERROR,
          getExceptionMsg("error-starting-server", ioe), ioe);
          getThrowableMsg("error-starting-server", ioe), ioe);
    }
  }
@@ -981,16 +979,29 @@
  protected abstract String getOpenDSClassPath();
  /**
   * Returns the installation path.
   * @return the installation path.
   */
  protected abstract String getInstallationPath();
  /**
   * Returns the config file path.
   * @return the config file path.
   */
  protected abstract String getConfigFilePath();
  protected String getConfigFilePath()
  {
    return Utils.getPath(getInstallationPath(), CONFIG_PATH_RELATIVE);
  }
  /**
   * Returns the path to the binaries.
   * @return the path to the binaries.
   */
  protected abstract String getBinariesPath();
  protected String getBinariesPath()
  {
    return Utils.getPath(getInstallationPath(),
        Utils.getBinariesRelativePath());
  }
  /**
   * Updates the contents of the provided map with the localized summary
@@ -1001,7 +1012,7 @@
      Map<InstallProgressStep, String> hmSummary)
  {
    hmSummary.put(InstallProgressStep.NOT_STARTED,
        getFormattedSummary(getMsg("summary-not-started")));
        getFormattedSummary(getMsg("summary-install-not-started")));
    hmSummary.put(InstallProgressStep.DOWNLOADING,
        getFormattedSummary(getMsg("summary-downloading")));
    hmSummary.put(InstallProgressStep.EXTRACTING,
@@ -1018,10 +1029,29 @@
            getMsg("summary-importing-automatically-generated")));
    hmSummary.put(InstallProgressStep.STARTING_SERVER,
        getFormattedSummary(getMsg("summary-starting")));
    hmSummary.put(InstallProgressStep.FINISHED_SUCCESSFULLY, "<html>"
        + getFormattedSuccess(getMsg("summary-finished-successfully")));
    hmSummary.put(InstallProgressStep.FINISHED_WITH_ERROR, "<html>"
        + getFormattedError(getMsg("summary-finished-with-error")));
    String[] arg = {formatter.getFormattedText(getInstallationPath())};
    hmSummary.put(InstallProgressStep.FINISHED_SUCCESSFULLY,
        getFormattedSuccess(
            getMsg("summary-install-finished-successfully", arg)));
    hmSummary.put(InstallProgressStep.FINISHED_WITH_ERROR,
        getFormattedError(getMsg("summary-install-finished-with-error")));
  }
  /**
   * Writes the java home that we are using for the setup in a file.
   * This way we can use this java home even if the user has not set JAVA_HOME
   * when running the different scripts.
   *
   */
  protected void writeJavaHome()
  {
    try
    {
      // This isn't likely to happen, and it's not a serious problem even if
      // it does.
      SetupUtils.writeSetJavaHome(getInstallationPath());
    } catch (Exception e) {}
  }
  /**
opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
@@ -36,7 +36,8 @@
/**
 * This is the only class that uses classes in org.opends.server (excluding the
 * case of org.opends.server.util.DynamicConstants which is already included in
 * case of org.opends.server.util.DynamicConstants and
 * org.opends.server.util.SetupUtils which are already included in
 * quicksetup.jar).
 *
 * Important note: do not include references to the classes in package
@@ -83,14 +84,14 @@
        MSGID_DIRECTORY_SERVER_STARTED);
  }
  private String getExceptionMsg(String key, Exception ex)
  private String getThrowableMsg(String key, Throwable t)
  {
    return getExceptionMsg(key, null, ex);
    return getThrowableMsg(key, null, t);
  }
  private String getExceptionMsg(String key, String[] args, Exception ex)
  private String getThrowableMsg(String key, String[] args, Throwable t)
  {
    return Utils.getExceptionMsg(ResourceProvider.getInstance(), key, args, ex);
    return Utils.getThrowableMsg(ResourceProvider.getInstance(), key, args, t);
  }
  /**
@@ -109,7 +110,7 @@
      ldifFile.deleteOnExit();
    } catch (IOException ioe)
    {
      String failedMsg = getExceptionMsg("error-creating-temp-file", null, ioe);
      String failedMsg = getThrowableMsg("error-creating-temp-file", null, ioe);
      throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
          failedMsg, ioe);
    }
@@ -134,19 +135,19 @@
    } catch (org.opends.server.types.DirectoryException de)
    {
      throw new InstallException(InstallException.Type.CONFIGURATION_ERROR,
          getExceptionMsg("error-importing-ldif", null, de), de);
          getThrowableMsg("error-importing-ldif", null, de), de);
    } catch (org.opends.server.util.LDIFException le)
    {
      throw new InstallException(InstallException.Type.CONFIGURATION_ERROR,
          getExceptionMsg("error-importing-ldif", null, le), le);
          getThrowableMsg("error-importing-ldif", null, le), le);
    } catch (IOException ioe)
    {
      throw new InstallException(InstallException.Type.CONFIGURATION_ERROR,
          getExceptionMsg("error-importing-ldif", null, ioe), ioe);
    } catch (RuntimeException re)
          getThrowableMsg("error-importing-ldif", null, ioe), ioe);
    } catch (Throwable t)
    {
      throw new InstallException(InstallException.Type.BUG, getExceptionMsg(
          "bug-msg", re), re);
      throw new InstallException(InstallException.Type.BUG, getThrowableMsg(
          "bug-msg", t), t);
    }
    return ldifFile;
  }
opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
@@ -27,7 +27,6 @@
package org.opends.quicksetup.installer.offline;
import java.io.File;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
@@ -38,7 +37,6 @@
import org.opends.quicksetup.installer.UserInstallData;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.util.Utils;
import org.opends.server.util.SetupUtils;
/**
 * This is an implementation of the Installer class that is used to install
@@ -56,8 +54,6 @@
 */
public class OfflineInstaller extends Installer
{
  private static String fullInstallPath;
  /* This map contains the ratio associated with each step */
  private HashMap<InstallProgressStep, Integer> hmRatio =
      new HashMap<InstallProgressStep, Integer>();
@@ -68,39 +64,6 @@
  private InstallProgressStep status;
  static
  {
    /* Get the install path from the Class Path */
    String sep = System.getProperty("path.separator");
    String[] classPaths = System.getProperty("java.class.path").split(sep);
    String path = null;
    for (int i = 0; i < classPaths.length && (path == null); i++)
    {
      for (int j = 0; j < OPEN_DS_JAR_RELATIVE_PATHS.length &&
      (path == null); j++)
      {
        String normPath = classPaths[i].replace(File.separatorChar, '/');
        if (normPath.endsWith(OPEN_DS_JAR_RELATIVE_PATHS[j]))
        {
          path = classPaths[i];
        }
      }
    }
    File f = new File(path);
    File binariesDir = f.getParentFile();
    fullInstallPath = binariesDir.getParent();
  }
  /**
   * A constant used to retrieve the full install path.
   */
  public static String FULL_INSTALL_PATH = fullInstallPath;
  /**
   * A constant used to retrieve the config file name.
   */
  public static String CONFIG_FILE_NAME =
    Utils.getPath(FULL_INSTALL_PATH, CONFIG_PATH_RELATIVE);
  /**
   * OfflineInstaller constructor.
   * @param userData the UserInstallData with the parameters provided by the
@@ -141,7 +104,7 @@
  }
  /**
   * Actually performs the start in this thread.  The thread is blocked.
   * Actually performs the install in this thread.  The thread is blocked.
   *
   */
  private void doInstall()
@@ -175,12 +138,7 @@
        break;
      }
      try
      {
        // This isn't likely to happen, and it's not a serious problem even if
        // it does.
        SetupUtils.writeSetJavaHome(FULL_INSTALL_PATH);
      } catch (Exception e) {}
      writeJavaHome();
      if (getUserData().getStartServer())
      {
@@ -205,6 +163,14 @@
      String html = getFormattedError(ex, true);
      notifyListeners(html);
    }
    catch (Throwable t)
    {
      status = InstallProgressStep.FINISHED_WITH_ERROR;
      InstallException ex = new InstallException(
          InstallException.Type.BUG, getThrowableMsg("bug-msg", t), t);
      String msg = getFormattedError(ex, true);
      notifyListeners(msg);
    }
  }
  /**
@@ -290,17 +256,9 @@
  /**
   * {@inheritDoc}
   */
  protected String getConfigFilePath()
  protected String getInstallationPath()
  {
    return CONFIG_FILE_NAME;
  }
  /**
   * {@inheritDoc}
   */
  protected String getBinariesPath()
  {
    return Utils.getPath(FULL_INSTALL_PATH, BINARIES_PATH_RELATIVE);
    return Utils.getInstallPathFromClasspath();
  }
  /**
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java
@@ -28,7 +28,7 @@
package org.opends.quicksetup.installer.webstart;
/**
 * The following properties are set in the OpenDSQuickSetup.jnlp file to provide
 * The following properties are set in the QuickSetup.jnlp file to provide
 * informations.
 *
 */
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java
@@ -42,7 +42,7 @@
/**
 * This class is used to download the files that have been marked as lazy
 * in the OpenDSQuickSetup.jnlp file.
 * in the QuickSetup.jnlp file.
 *
 * The global idea is to force the user to download just one jar file
 * (quicksetup.jar) to display the Web Start installer dialog.  Then QuickSetup
@@ -132,12 +132,12 @@
          ex =
              new InstallException(InstallException.Type.DOWNLOAD_ERROR,
                  getExceptionMsg("downloading-error", arg, ioe), ioe);
        } catch (RuntimeException re)
        } catch (Throwable t)
        {
          // This is a bug
          ex =
              new InstallException(InstallException.Type.BUG, getExceptionMsg(
                  "bug-msg", re), re);
                  "bug-msg", t), t);
        }
      }
    });
@@ -403,14 +403,14 @@
  }
  /* Some commodity methods to get localized messages */
  private String getExceptionMsg(String key, Exception ex)
  private String getExceptionMsg(String key, Throwable t)
  {
    return getExceptionMsg(key, null, ex);
    return getExceptionMsg(key, null, t);
  }
  private String getExceptionMsg(String key, String[] args, Exception ex)
  private String getExceptionMsg(String key, String[] args, Throwable t)
  {
    return Utils.getExceptionMsg(ResourceProvider.getInstance(), key, args, ex);
    return Utils.getThrowableMsg(ResourceProvider.getInstance(), key, args, t);
  }
  private String getMsg(String key, String[] args)
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
@@ -43,7 +43,6 @@
import org.opends.quicksetup.installer.UserInstallData;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.util.Utils;
import org.opends.server.util.SetupUtils;
/**
 * This is an implementation of the Installer class that is used to install
@@ -58,7 +57,7 @@
 * we require all the jar files to be downloaded in order to install and
 * configure the Directory Server.
 *
 * Based on the Java properties set through the OpenDSQuickSetup.jnlp file this
 * Based on the Java properties set through the QuickSetup.jnlp file this
 * class will retrieve the zip file containing the install, unzip it and extract
 * it in the path specified by the user and that is contained in the
 * UserInstallData object.
@@ -125,7 +124,7 @@
  }
  /**
   * Actually performs the start in this thread.  The thread is blocked.
   * Actually performs the install in this thread.  The thread is blocked.
   *
   */
  private void doInstall()
@@ -170,12 +169,7 @@
        break;
      }
      try
      {
        // This isn't likely to happen, and it's not a serious problem even if
        // it does.
        SetupUtils.writeSetJavaHome(getUserData().getServerLocation());
      } catch (Exception e) {}
      writeJavaHome();
      if (getUserData().getStartServer())
      {
@@ -193,6 +187,14 @@
      String html = getFormattedError(ex, true);
      notifyListeners(html);
    }
    catch (Throwable t)
    {
      status = InstallProgressStep.FINISHED_WITH_ERROR;
      InstallException ex = new InstallException(
          InstallException.Type.BUG, getThrowableMsg("bug-msg", t), t);
      String msg = getFormattedError(ex, true);
      notifyListeners(msg);
    }
  }
  /**
@@ -424,7 +426,7 @@
          {
            String[] arg =
              { entry.getName() };
            String errorMsg = getExceptionMsg("error-copying", arg, ioe);
            String errorMsg = getThrowableMsg("error-copying", arg, ioe);
            throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
                errorMsg, ioe);
@@ -465,7 +467,7 @@
    {
      String[] arg =
        { getZipFileName() };
      String errorMsg = getExceptionMsg("error-zip-stream", arg, ioe);
      String errorMsg = getThrowableMsg("error-zip-stream", arg, ioe);
      throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
          errorMsg, ioe);
    }
@@ -565,11 +567,11 @@
   */
  private String[] getOpenDSJarPaths()
  {
    String[] jarPaths = new String[OPEN_DS_JAR_RELATIVE_PATHS.length];
    String[] jarPaths = new String[Utils.getOpenDSJarPaths().length];
    File parentDir = new File(getUserData().getServerLocation());
    for (int i = 0; i < jarPaths.length; i++)
    {
      File f = new File(parentDir, OPEN_DS_JAR_RELATIVE_PATHS[i]);
      File f = new File(parentDir, Utils.getOpenDSJarPaths()[i]);
      jarPaths[i] = f.getAbsolutePath();
    }
    return jarPaths;
@@ -619,6 +621,9 @@
    } else if (path.endsWith(".sh"))
    {
      perm = "755";
    } else if (path.endsWith("setup") || path.endsWith("uninstall"))
    {
      perm = "755";
    } else
    {
      perm = "644";
@@ -640,20 +645,8 @@
  /**
   * {@inheritDoc}
   */
  protected String getConfigFilePath()
  protected String getInstallationPath()
  {
    String fullInstallPath = getUserData().getServerLocation();
    return Utils.getPath(fullInstallPath, CONFIG_PATH_RELATIVE);
    return getUserData().getServerLocation();
  }
  /**
   * {@inheritDoc}
   */
  protected String getBinariesPath()
  {
    String fullInstallPath = getUserData().getServerLocation();
    return Utils.getPath(fullInstallPath, BINARIES_PATH_RELATIVE);
  }
}
}
opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -26,20 +26,115 @@
-S  or   --skipPortCheck\n    Skip the check to determine whether the \
specified LDAP port is usable.\n\
-D {rootDN}  or   --rootUserDN {rootDN}\n    Specifies the DN for the initial \
root user for the Directory Server.\n\
Administrative User for the Directory Server.\n\
-w {password}  or   --rootUserPassword {password}\n    Specifies the password \
for the initial root user for the Directory Server.\n\
for the initial Administrative User for the Directory Server.\n\
-W {filename}  or   --rootUserPasswordFile {filename}\n    Specifies the path \
to a file containing the password for the initial root\n\    user for the \
Directory Server.
to a file containing the password for the initial Administrative\n\    User \
for the Directory Server.
setup-launcher-launching-gui=Launching graphical setup...
setup-launcher-gui-launched-failed=\n\nThe graphical Setup launch failed.\n\n\
Launching command line Setup...
#
# Uninstall command line messages
#
uninstall-launcher-usage-windows=This utility may be used to uninstall the \
Directory Server.\n\Usage:  {0} {options}\n        where {options} include:\n\
--cli\n\    Specifies to use the command line uninstall.  If not specified the \
graphical\n\    interface will be launched.\n\
-H  or   --help\n    Displays usage information for this program.\n\n\
The following options will only be taken into account if the option --cli \n\
(command line) is specified\n\
-D {rootDN}  or   --rootUserDN {rootDN}\n    Specifies the DN of the \
Administrative User (Directory Manager) of the Directory Server.\n\
-w {password}  or   --rootUserPassword {password}\n    Specifies the password \
of the Administrative User (Directory Manager) of the Directory Server.\n\
-W {filename}  or   --rootUserPasswordFile {filename}\n    Specifies the path \
to a file containing the password for the initial Administrative\n\    User \
for the Directory Server.\n\
-s  or   --silentUninstall\n    Perform a silent uninstall.
uninstall-launcher-usage-unix=This utility may be used to uninstall the \
Directory Server.\n\
Usage:  {0} {options}\n        where {options} include:\n\
--cli\n\    Specifies to use the command line uninstall.  If not specified the \
graphical\n\    interface will be launched.\n\
-H  or   --help\n    Displays usage information for this program.\n\n\
The following options will only be taken into account if the option --cli \n\
(command line) is specified\n\
-s  or   --silentUninstall\n    Perform a silent uninstall.
uninstall-launcher-launching-gui=Launching graphical uninstall...
uninstall-launcher-launching-cli=Launching command line uninstall...
uninstall-launcher-gui-launched-failed=\n\nThe graphical Uninstall launch \
failed.\n\nLaunching command line Uninstall...
cli-uninstall-root-user-dn-not-provided=You must provide a value for the \
option -D (or --rootUserDN)
cli-uninstall-root-user-pwd-not-provided=You must provide a value for the \
option -w (or --rootUserPassword)
cli-uninstall-root-user-pwd-file-not-provided=You must provide a value for the \
option -W (or --rootUserPasswordFile)
cli-uninstall-data-missing-to-shutdown-server=The server is currently running \
and must be stopped before uninstallation can \
continue.  You must provide the Authentication DN (option -D or \
--rootUserDN) and the password (option -w or --rootUserPassword) or the file \
containing the password (option -W or --rootUserPasswordFile) of the \
Administrative User.
cli-uninstall-unknown-argument=Unknown argument {0}
cli-uninstall-pwd-and-pwd-file-provided=You cannot provide Authentication User \
Password (-w or --rootUserPassword) and Authentication User Password File \
(-W or --rootUserPasswordFile) at the same time.
cli-uninstall-yes-short=y
cli-uninstall-yes-long=yes
cli-uninstall-no-short=n
cli-uninstall-no-long=no
cli-uninstall-confirm-prompt={0}\n[{1}]:
cli-uninstall-string-prompt={0}\n[{1}]:
cli-uninstall-error-reading-stdin=Unexpected error reading standard input.
cli-uninstall-what-to-delete=Do you want to remove all components of OpenDS or \
select the components to remove?\n\
1. Remove all components\n\
2. Select the components to be removed\n\
3. Neither; Quit the uninstaller
cli-uninstall-confirm-libraries-binaries=Remove Server Libraries and \
Administrative Tools?
cli-uninstall-confirm-databases=Remove Database Contents?
cli-uninstall-confirm-logs=Remove Log Files?
cli-uninstall-confirm-configuration-schema=Remove Configuration and Schema \
Files?
cli-uninstall-confirm-backups=Remove Backup Files Contained in bak Directory?
cli-uninstall-confirm-ldifs=Remove LDIF Export Files Contained in ldif \
Directory?
cli-uninstall-confirm-outsidedbs=The Directory Server contains database files \
in the following locations outside the server path:\n{0}\nRemove these files?
cli-uninstall-confirm-outsidelogs=The Directory Server contains log files in \
the following locations outside the server path:\n{0}\nRemove these files?
cli-uninstall-nothing-to-be-uninstalled=You must select something to be \
uninstalled.
cli-uninstall-confirm-stop=The OpenDS server is currently running and \
must be stopped before uninstallation can continue.\nStop the Server and \
permanently delete the files?
cli-uninstall-confirm-delete-files=The files will be permanently deleted, are \
you sure you want to continue?
cli-uninstall-stop-authentication-generic-prompt1=The server is currently \
running and must be stopped before uninstallation can continue.
cli-uninstall-stop-authentication-generic-prompt2=You must provide the \
Administrative User DN and password to stop the server.
cli-uninstall-error-reading-pwd-file=Could not read the password from \
file {0}.  Check that the file path is correct, that you have access rights to \
it and that it contains a password.
cli-uninstall-prompt-dn=Administrative User DN
cli-uninstall-prompt-pwd=Administrative User Password:
cli-uninstall-server-stopped=The Server is Stopped.
cli-uninstall-cannot-connect-to-shutdown-with-cause=Could not connect to the \
Directory Server with the provided credentials.  The possible causes for this \
are:\n{0}
cli-uninstall-cannot-connect-to-shutdown-without-cause=Could not connect to \
the Directory Server with the provided credentials.
#
# Dialog titles
#
frame-quicksetup-title=OpenDS QuickSetup
frame-install-title=OpenDS QuickSetup
frame-uninstall-title=OpenDS Uninstall
#
@@ -49,26 +144,43 @@
next-button-tooltip=Go to Next Step
previous-button-label=< Previous
previous-button-tooltip=Go to Previous Step
finish-button-label=Finish
finish-button-tooltip=Finish Installation and Setup
finish-button-install-label=Finish
finish-button-uninstall-label=Uninstall
finish-button-install-tooltip=Finish Installation and Setup
finish-button-uninstall-tooltip=Finish Uninstall
close-button-label=Close
close-button-tooltip=Close QuickSetup Window
close-button-install-tooltip=Close QuickSetup Window
close-button-uninstall-tooltip=Close Uninstall Window
quit-button-label=Quit
quit-button-tooltip=Quit QuickSetup Tool
quit-button-install-tooltip=Quit QuickSetup Tool
cancel-button-label=Cancel
cancel-button-uninstall-tooltip=Cancel Uninstall
shutdown-button-label=Shutdown
#
# Confirmation dialogs
#
confirm-close-quicksetup-title=Confirmation Required
confirm-close-quicksetup-msg=OpenDS QuickSetup has not yet completed.\nAre you \
confirm-close-install-title=Confirmation Required
confirm-close-install-msg=OpenDS QuickSetup has not yet completed.\nAre you \
sure you want to close the QuickSetup Window?
confirm-quit-quicksetup-title=Confirmation Required
confirm-quit-quicksetup-msg=Are you sure you want to quit OpenDS \
confirm-quit-install-title=Confirmation Required
confirm-quit-install-msg=Are you sure you want to quit OpenDS \
QuickSetup?\nIf you click 'Yes' nothing will be installed on your system.
confirm-close-uninstall-title=Confirmation Required
confirm-close-uninstall-msg=OpenDS Uninstall has not yet completed.\nAre you \
sure you want to close the Uninstall Window?
confirm-uninstall-server-not-running-msg=Confirm Uninstall\n\
All selected files will be permanently deleted, are you sure you\n\
want to continue?
confirm-uninstall-server-not-running-title=Confirm Uninstall
confirm-uninstall-server-running-unix-msg=Server is Running\n\
The OpenDS server is currently running and must be stopped before\n\
uninstallation can continue. Do you want the uninstaller to stop\n\
the server for you and continue with the uninstall? If you click\n\
No, you will need to stop the server manually to continue.
confirm-uninstall-server-running-unix-title=Server is Running
#
# Error dialog title
#
@@ -86,6 +198,24 @@
error-browser-close-button-tooltip=Close this window
#
# Dialog asking Directory manager credentials to shutdown server in Windows.
#
shutdown-directory-manager-dialog-title=Authentication Required
shutdown-directory-manager-dialog-msg=<b>Directory Server is Running</b><br>\
The server is currently running and must be stopped before uninstallation can \
continue.  Provide the information below to allow the uninstaller to \
shut it down. You can also click Cancel and then shut the server down yourself.
shutdown-directory-manager-dn-label=Administrative User DN:
shutdown-directory-manager-dn-tooltip=Enter the distinguished name (DN) of the \
Administrative User account that will used to shutdown OpenDS
shutdown-directory-manager-pwd-label=Password:
shutdown-directory-manager-pwd-tooltip=Enter the password of the OpenDS \
Administrative User account
shutdown-directory-manager-cancel-button-tooltip=Close this window
shutdown-directory-manager-shutdown-button-tooltip=Click here to shutdown the \
server with the provided authentication
#
# Data validation errors
#
# Server Settings
@@ -99,8 +229,11 @@
least {1} megabytes of free disk space are required to install OpenDS.
invalid-port-value-range=The LDAP Listener Port must be an integer between \
{0} and {1}.
cannot-bind-priviledged-port=Cannot bind to privileged port {0}.
cannot-bind-port=Cannot bind to port {0}.
cannot-bind-priviledged-port=Cannot bind to privileged port {0}.\n\nThe port \
could be already in use by another application or maybe you do not have the \
rights to access it.
cannot-bind-port=Cannot bind to port {0}.\n\nThe port could be already in use \
by another application or maybe you do not have the rights to access it.
empty-directory-manager-dn=You must provide an Administrative User DN.
not-a-directory-manager-dn=The provided Administrative User DN is not a valid \
DN.
@@ -120,7 +253,20 @@
automatically.
invalid-number-entries-range=The number of user entries to generate \
automatically must be an integer between {0} and {1}.
# Confirm Uninstall Panel
nothing-selected-to-uninstall=You must select something to be uninstalled.
# Directory Manager authentication to shutdown in Windows
not-a-directory-manager-in-config=The provided DN is not one of the \
Administrative User DN.
empty-pwd=You must provide the password of the Administrative User.
cannot-connect-to-shutdown-with-cause=Could not connect to the Directory \
Server with the provided credentials.  The possible causes for this are:\n{0}
cannot-connect-to-shutdown-without-cause=Could not connect to the Directory \
Server with the provided credentials.\nCheck that the Administrative User DN \
and password are valid.
server-not-running-msg=The Directory Server is not running.  Click OK to \
continue the uninstall.
server-not-running-title=Directory Server not Running
#
# Steps labels (on the left side of the wizard)
@@ -130,7 +276,7 @@
data-options-step=Data Options
review-step=Review
progress-step=Progress
confirm-uninstall-step=Confirm Uninstallation
confirm-uninstall-step=Uninstall Options
#
# Icon descriptions.  Used for accessibility.
@@ -179,24 +325,35 @@
# have to modify it or not: if the server uses the locale of the browser to display
# a language there is no translation to be done but if we have specific URL for
# each language the URL must be localized.
welcome-panel-instructions=The OpenDS QuickSetup tool will ask you for some \
basic server and data configuration settings and will get your server up \
and running quickly.<br><br>If you are running this tool via Java Web Start, \
QuickSetup will install and configure the latest weekly build. You can also \
use QuickSetup to set up a weekly build you have downloaded manually. To run \
QuickSetup in this case, use the setup command at the top level of the \
OpenDS directory.  This instance of QuickSetup will use the following OpenDS \
welcome-panel-offline-instructions=The OpenDS QuickSetup tool will ask you for \
some basic server and data configuration settings and will get your server up \
and running quickly.<br><br>Note that you can also install the latest weekly \
build launching the setup via Java Web Start from the <a \
href="https://opends.dev.java.net/public/downloads_index.html">OpenDS \
Downloads Page</a>.  This instance of QuickSetup will use the following OpenDS \
build: {0} (Build ID: {1}) <br><br> \
OpenDS requires a Java SE 5.0 or higher runtime.<br><br> \
Additional information on QuickSetup is available in the <a href="https://opends.dev.java.net/public/docs/index.html"> \
Documentation Depot</a> section of OpenDS project web site.<br><br>
Documentation Depot</a> section of OpenDS project web site.
welcome-panel-webstart-instructions=The OpenDS QuickSetup tool will ask you for some \
basic server and data configuration settings and will get your server up \
and running quickly.<br><br>QuickSetup will install and configure the latest \
weekly build. You can also use QuickSetup to set up a weekly build you have \
downloaded manually. To run QuickSetup in this case, use the {0} command at \
the top level of the OpenDS directory.  This instance of QuickSetup will use \
the following OpenDS build: {1} (Build ID: {2}) <br><br> \
OpenDS requires a Java SE 5.0 or higher runtime.<br><br> \
Additional information on QuickSetup is available in the <a href="https://opends.dev.java.net/public/docs/index.html"> \
Documentation Depot</a> section of OpenDS project web site.
#
# Server Settings Panel specific labels
#
server-settings-panel-title=Server Settings
server-settings-panel-instructions=Choose a location for the server files and \
enter a password for the OpenDS administrative user.
server-settings-panel-instructions-webstart=Choose a location for the server \
files and enter a password for the OpenDS administrative user.
server-settings-panel-instructions=Enter a port to listen for LDAP requests \
and enter a password for the OpenDS administrative user.
server-location-label=Installation Path:
server-location-parent-tooltip=Enter the full path to the parent location \
where the server files will be stored
@@ -214,9 +371,7 @@
server-directory-manager-pwd-confirm-label=Password (confirm):
server-directory-manager-pwd-confirm-tooltip=Re-enter the password for the \
OpenDS Administrative User account
cannot-find-default-port-unix=Note: Cannot use port 389.
cannot-find-default-port-windows=Note: Port 389 is already in use.
cannot-use-default-port=Could not use 389. Port in use or user not authorized.
#
# Data Options Panel specific labels
@@ -264,25 +419,46 @@
#
progress-panel-title=Progress
progress-details-label=Details:
progressbar-initial-label=Starting Setup...
progressbar-initial-label=Starting...
progressbar-tooltip=Progress Bar
#
# Confirm Uninstall Panel specific labels
#
confirm-uninstall-panel-title=Confirm uninstall
confirm-uninstall-panel-title=Uninstall Options
# The following line contains some HTML tags.  translators should respect them.
# Concerning the URL, depending on how works the product page translators
# have to modify it or not: if the server uses the locale of the browser to display
# a language there is no translation to be done but if we have specific URL for
# each language the URL must be localized.
confirm-uninstall-panel-instructions=The OpenDS Uninstall tool will \
stop the OpenDS server if it is running and will delete all the user data \
from it.  All the binary files will also be deleted.<br><br> \
Click on 'Finish' to start the uninstallation of OpenDS.<br><br> \
Additional information on QuickSetup is available in the <a href="https://opends.dev.java.net/public/docs/index.html"> \
Documentation Depot</a> section of OpenDS project web site.<br><br>
confirm-uninstall-panel-instructions=The OpenDS Uninstall tool will remove all \
parts of the OpenDS server you have selected below from your system. If all \
are selected, the server will be removed entirely.
server-path-label=Server Path:
remove-label=Remove:
remove-libraries-and-tools-label=Server Libraries and Administrative Tools
remove-databases-label=Database Contents
remove-logs-label=Log Files
remove-schema-and-configuration-label=Configuration and Schema Files
remove-backups-label=Backup Files Contained in bak Directory
remove-ldifs-label=LDIF Export Files Contained in ldif Directory
remove-libraries-and-tools-tooltip=Remove Server Libraries and Administrative \
Tools
remove-databases-tooltip=Remove Database Contents
remove-logs-tooltip=Remove Log Files
remove-schema-and-configuration-tooltip=Remove Configuration and Schema Files
remove-backups-tooltip=Remove Backup Files Contained in bak Directory
remove-ldifs-tooltip=Remove LDIF Export Files Contained in ldif Directory
delete-outside-dbs-msg=The Directory Server contains database files in the \
following locations outside the server path:
delete-outside-dbs-label=Delete these Database Files
delete-outside-dbs-tooltip=Check this box to Delete the Database Files located \
outside the install directory.
delete-outside-logs-msg=The Directory Server contains log files in the \
following locations outside the server path:
delete-outside-logs-label=Delete these Log Files
delete-outside-logs-tooltip=Check this box to Delete the Log Files located \
outside the install directory.
#
# Miscellaneous labels
@@ -296,8 +472,8 @@
#
# Progress Summary Labels
#
summary-not-started=Starting QuickSetup...
summary-not-started=Launching Installation...
summary-install-not-started=Starting QuickSetup...
summary-uninstall-not-started=Starting Uninstallation...
summary-downloading=Downloading Binary Files...
summary-extracting=Extracting Binary Files...
summary-configuring=Configuring Directory Server...
@@ -306,13 +482,33 @@
summary-importing-automatically-generated=Importing Automatically-Generated \
Data...
summary-starting=Starting Directory Server...
summary-finished-successfully=<b>OpenDS QuickSetup completed successfully.</b>\
<br> Visit the \
summary-install-finished-successfully=<b>OpenDS QuickSetup Completed \
Successfully.</b><br>OpenDS is now installed in {0}.<br><br>Visit the \
<a href="https://opends.dev.java.net/public/docs/user-docs/OpenDS-QuickReference.html"> \
OpenDS Quick Reference</a> page for an overview of server management and \
configuration.
summary-finished-with-error=An error occurred.  Check 'Details' text area for \
more information.
summary-install-finished-with-error=An error occurred.  Check 'Details' text \
area for more information.
summary-stopping=Stopping Directory Server...
summary-deleting-external-db-files=Deleting Database Files outside the \
Installation Path...
summary-deleting-external-log-files=Deleting Log Files outside the \
Installation Path...
summary-deleting-external-references=Deleting External References...
summary-deleting-installation-files=Deleting Files under the Installation \
Path...
summary-uninstall-finished-successfully-remove-jarfiles=<b>OpenDS Uninstall \
Completed Successfully.</b><br><br>To complete the uninstallation, you must \
delete manually the following files:<br>{0}
summary-uninstall-finished-successfully=<b>OpenDS Uninstall Completed \
Successfully.</b>
summary-uninstall-finished-successfully-remove-jarfiles-cli=OpenDS Uninstall \
Completed Successfully.\nTo complete the uninstallation, you must \
delete manually the following files:\n{0}
summary-uninstall-finished-successfully-cli=OpenDS Uninstall Completed \
Successfully.
summary-uninstall-finished-with-error=An error occurred.  Check 'Details' text \
area for more information.
#
# Progress messages
@@ -330,13 +526,25 @@
progress-import-automatically-generated=Importing Automatically-Generated Data \
({0} Entries):
progress-starting=Starting Directory Server:
progress-stopping=Stopping Directory Server:
progress-deleting-external-db-files=Deleting Database Files outside the \
Installation Path:
progress-deleting-external-log-files=Deleting Log Files outside the \
Installation Path:
progress-deleting-installation-files=Deleting Files under the Installation Path:
progress-deleting-file=Deleting file {0}
progress-deleting-directory=Deleting directory {0}
progress-server-already-stopped=The Directory Server is already stopped.
progress-server-waiting-to-stop=Waiting for Server to stop...
progress-server-stopped=Server stopped.
deleting-file-does-not-exist=Path {0} does not exist.
#
# Progress errors
#
error-copying=An unexpected error occurred extracting file {0}.
error-zip-stream=An unexpected error occurred reading the zip file {0}.
exception-details=Details: {0}.
exception-details=Details: {0}
downloading-error=An error occurred downloading remote file(s) {0}.
error-zipinputstreamnull=Could not retrieve zip file.  The input stream \
is null.
@@ -351,12 +559,20 @@
error-import-automatically-generated=Error Importing Automatically- Generated \
Data.
error-starting-server=Error Starting Directory Server.
error-starting-server-code=Error Starting Directory Server.  Error code: {0}.
error-starting-server-in-windows=Could not connect to Server after Start.  \
If you have a firewall configured check that it allows connections to port {0}.
error-stopping-server=Error Stopping Directory Server.
error-stopping-server-code=Error Stopping Directory Server.  Error code: {0}.
error-reading-erroroutput=Error Reading error output.
error-reading-output=Error Reading output.
hide-exception-details=Hide Details
show-exception-details=Show Details
exception-root-cause=Root Cause:
error-deleting-file=Error deleting file {0}.  Check that you have the rights \
to delete this file and that there is no other application using it.
error-deleting-directory=Error deleting directory {0}.  Check that you have \
the rights to delete this directory and that there is no other application \
using it.
#
# Install Status: messages displayed in the offline quick setup
opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java
@@ -42,6 +42,7 @@
import org.opends.quicksetup.Step;
import org.opends.quicksetup.event.ButtonActionListener;
import org.opends.quicksetup.event.ButtonEvent;
import org.opends.quicksetup.util.Utils;
/**
 * This class contains the buttons in the bottom of the Install/Uninstall
@@ -66,6 +67,8 @@
  private JButton finishButton;
  private JButton cancelButton;
  /**
   * Default constructor.
   *
@@ -112,6 +115,7 @@
      finishButton.setVisible(false);
      quitButton.setVisible(true);
      closeButton.setVisible(false);
      cancelButton.setVisible(false);
      break;
@@ -122,6 +126,7 @@
      finishButton.setVisible(true);
      quitButton.setVisible(true);
      closeButton.setVisible(false);
      cancelButton.setVisible(false);
      break;
@@ -135,6 +140,7 @@
      finishButton.setVisible(false);
      quitButton.setVisible(false);
      closeButton.setVisible(true);
      cancelButton.setVisible(false);
      break;
@@ -143,8 +149,9 @@
      previousButton.setVisible(false);
      nextButton.setVisible(false);
      finishButton.setVisible(true);
      quitButton.setVisible(true);
      quitButton.setVisible(false);
      closeButton.setVisible(false);
      cancelButton.setVisible(true);
      break;
@@ -155,6 +162,7 @@
      finishButton.setVisible(false);
      quitButton.setVisible(true);
      closeButton.setVisible(false);
      cancelButton.setVisible(false);
    }
  }
@@ -188,6 +196,10 @@
      b = finishButton;
      break;
    case CANCEL:
      b = cancelButton;
      break;
    default:
      throw new IllegalArgumentException("Unknown button name: " +
          buttonName);
@@ -209,17 +221,25 @@
        createButton("previous-button-label", "previous-button-tooltip",
            ButtonName.PREVIOUS);
    String tooltip;
    tooltip = "quit-button-install-tooltip";
    quitButton =
        createButton("quit-button-label", "quit-button-tooltip",
            ButtonName.QUIT);
        createButton("quit-button-label", tooltip, ButtonName.QUIT);
    closeButton =
        createButton("close-button-label", "close-button-tooltip",
            ButtonName.CLOSE);
    tooltip = Utils.isUninstall()?
        "close-button-uninstall-tooltip":"close-button-install-tooltip";
    closeButton = createButton("close-button-label", tooltip, ButtonName.CLOSE);
    finishButton =
        createButton("finish-button-label", "finish-button-tooltip",
            ButtonName.FINISH);
    String label = Utils.isUninstall()?
        "finish-button-uninstall-label":"finish-button-install-label";
    tooltip = Utils.isUninstall()?
        "finish-button-uninstall-tooltip":"finish-button-install-tooltip";
    finishButton = createButton(label, tooltip, ButtonName.FINISH);
    cancelButton =
      createButton("cancel-button-label", "cancel-button-uninstall-tooltip",
          ButtonName.CANCEL);
  }
  /**
@@ -241,7 +261,7 @@
    int width = (int) previousButton.getPreferredSize().getWidth();
    previousPanel.add(Box.createHorizontalStrut(width), gbcAux);
    gbc.gridwidth = 4;
    gbc.gridwidth = 5;
    gbc.weightx = 0.0;
    gbc.weighty = 0.0;
    gbc.insets.bottom = 0;
@@ -255,7 +275,10 @@
    // Set as opaque to inherit the background color of ButtonsPanel
    nextFinishPanel.setOpaque(false);
    nextFinishPanel.add(nextButton, gbcAux);
    nextFinishPanel.add(finishButton, gbcAux);
    if (!Utils.isUninstall())
    {
      nextFinishPanel.add(finishButton, gbcAux);
    }
    width =
        (int) Math.max(nextButton.getPreferredSize().getWidth(), finishButton
            .getPreferredSize().getWidth());
@@ -268,20 +291,36 @@
    gbc.insets.right = 0;
    add(Box.createHorizontalGlue(), gbc);
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.gridwidth = GridBagConstraints.RELATIVE;
    gbc.weightx = 0.0;
    gbc.fill = GridBagConstraints.NONE;
    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
    JPanel quitClosePanel = new JPanel(new GridBagLayout());
    if (Utils.isUninstall())
    {
      gbc.insets.right = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
      add(finishButton, gbc);
      gbc.insets.right = 0;
    }
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.weightx = 0.0;
    gbc.fill = GridBagConstraints.NONE;
    gbc.insets.left = 0;
    JPanel quitCloseCancelPanel = new JPanel(new GridBagLayout());
    // Set as opaque to inherit the background color of ButtonsPanel
    quitClosePanel.setOpaque(false);
    quitClosePanel.add(quitButton, gbcAux);
    quitClosePanel.add(closeButton, gbcAux);
    quitCloseCancelPanel.setOpaque(false);
    quitCloseCancelPanel.add(
        Box.createHorizontalStrut(UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS),
        gbcAux);
    quitCloseCancelPanel.add(quitButton, gbcAux);
    quitCloseCancelPanel.add(closeButton, gbcAux);
    quitCloseCancelPanel.add(cancelButton, gbcAux);
    width =
        (int) Math.max(quitButton.getPreferredSize().getWidth(), closeButton
            .getPreferredSize().getWidth());
    quitClosePanel.add(Box.createHorizontalStrut(width), gbcAux);
    add(quitClosePanel, gbc);
    width = (int) Math.max(width, cancelButton.getPreferredSize().getWidth());
    quitCloseCancelPanel.add(Box.createHorizontalStrut(width), gbcAux);
    add(quitCloseCancelPanel, gbc);
  }
  /**
opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java
@@ -28,6 +28,23 @@
package org.opends.quicksetup.ui;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import org.opends.quicksetup.CurrentInstallStatus;
import org.opends.quicksetup.installer.FieldName;
import org.opends.quicksetup.util.Utils;
/**
 * This is the panel displayed when the user is uninstalling Open DS.  It is
@@ -39,18 +56,66 @@
{
  private static final long serialVersionUID = 81730510134697056L;
  private CurrentInstallStatus installStatus;
  private Set<String> outsideDbs;
  private Set<String> outsideLogs;
  private HashMap<FieldName, JCheckBox> hmCbs =
    new HashMap<FieldName, JCheckBox>();
  /**
   * Default constructor.
   * The constructor of this class.
   * @param installStatus the object describing the current installation status.
   *
   */
  public ConfirmUninstallPanel()
  public ConfirmUninstallPanel(CurrentInstallStatus installStatus)
  {
    this.installStatus = installStatus;
    createLayout();
  }
  /**
   * {@inheritDoc}
   */
  public Object getFieldValue(FieldName fieldName)
  {
    Object value = null;
    switch (fieldName)
    {
    case EXTERNAL_DB_DIRECTORIES:
      Set<String> s1 = new HashSet<String>();
      if (outsideDbs.size() > 0)
      {
        if (getCheckBox(FieldName.EXTERNAL_DB_DIRECTORIES).isSelected())
        {
          s1.addAll(outsideDbs);
        }
      }
      value = s1;
      break;
    case EXTERNAL_LOG_FILES:
      Set<String> s2 = new HashSet<String>();
      if (outsideLogs.size() > 0)
      {
        if (getCheckBox(FieldName.EXTERNAL_LOG_FILES).isSelected())
        {
          s2.addAll(outsideLogs);
        }
      }
      value = s2;
      break;
    default:
      JCheckBox cb = getCheckBox(fieldName);
    value = new Boolean(cb.isSelected());
    break;
    }
    return value;
  }
  /**
   * {@inheritDoc}
   */
  protected String getTitle()
  {
    return getMsg("confirm-uninstall-panel-title");
@@ -61,8 +126,111 @@
   */
  protected Component createInputPanel()
  {
    // No input in this panel
    return null;
    FieldName[] fieldNames = {
        FieldName.REMOVE_LIBRARIES_AND_TOOLS,
        FieldName.REMOVE_DATABASES,
        FieldName.REMOVE_LOGS,
        FieldName.REMOVE_CONFIGURATION_AND_SCHEMA,
        FieldName.REMOVE_BACKUPS,
        FieldName.REMOVE_LDIFS,
    };
    String[] labels = {
        getMsg("remove-libraries-and-tools-label"),
        getMsg("remove-databases-label"),
        getMsg("remove-logs-label"),
        getMsg("remove-schema-and-configuration-label"),
        getMsg("remove-backups-label"),
        getMsg("remove-ldifs-label"),
    };
    String[] tooltips = {
        getMsg("remove-libraries-and-tools-tooltip"),
        getMsg("remove-databases-tooltip"),
        getMsg("remove-logs-tooltip"),
        getMsg("remove-schema-and-configuration-tooltip"),
        getMsg("remove-backups-tooltip"),
        getMsg("remove-ldifs-tooltip"),
    };
    for (int i=0; i<fieldNames.length; i++)
    {
      JCheckBox cb = UIFactory.makeJCheckBox(labels[i], tooltips[i],
          UIFactory.TextStyle.INSTRUCTIONS);
      cb.setOpaque(false);
      cb.setSelected(true);
      hmCbs.put(fieldNames[i], cb);
    }
    JPanel panel = new JPanel(new GridBagLayout());
    panel.setOpaque(false);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.insets = UIFactory.getEmptyInsets();
    JPanel p = new JPanel(new GridBagLayout());
    p.setOpaque(false);
    gbc.weightx = 0.0;
    gbc.gridwidth = GridBagConstraints.RELATIVE;
    gbc.anchor = GridBagConstraints.WEST;
    p.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
        getMsg("server-path-label"),
        UIFactory.TextStyle.PRIMARY_FIELD_VALID), gbc);
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
    p.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
        Utils.getInstallPathFromClasspath(), UIFactory.TextStyle.INSTRUCTIONS),
        gbc);
    FieldName[] names = {
        FieldName.REMOVE_LIBRARIES_AND_TOOLS,
        FieldName.REMOVE_DATABASES,
        FieldName.REMOVE_LOGS,
        FieldName.REMOVE_CONFIGURATION_AND_SCHEMA,
        FieldName.REMOVE_BACKUPS,
        FieldName.REMOVE_LDIFS
    };
    for (int i=0; i<names.length; i++)
    {
      gbc.gridwidth = GridBagConstraints.RELATIVE;
      p.add(Box.createHorizontalGlue(), gbc);
      gbc.insets.left = 0;
      gbc.gridwidth = GridBagConstraints.REMAINDER;
      gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
      p.add(getCheckBox(names[i]), gbc);
    }
    gbc.weightx = 1.0;
    gbc.fill = GridBagConstraints.NONE;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.anchor = GridBagConstraints.WEST;
    gbc.insets.left = 0;
    panel.add(p, gbc);
    outsideDbs = Utils.getOutsideDbs(installStatus);
    outsideLogs = Utils.getOutsideLogs(installStatus);
    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 1.0;
    if (outsideDbs.size() > 0)
    {
      JPanel dbPanel = createDbPanel();
      panel.add(dbPanel, gbc);
    }
    if (outsideLogs.size() > 0)
    {
      JPanel logPanel = createLogPanel();
      panel.add(logPanel, gbc);
    }
    addVerticalGlue(panel);
    return panel;
  }
  /**
@@ -72,4 +240,94 @@
  {
    return getMsg("confirm-uninstall-panel-instructions");
  }
  /**
   * Creates a panel to ask the user if (s)he wants to remove the databases
   * located outside the installation path.
   * @return a panel to ask the user if (s)he wants to remove the databases
   * located outside the installation path.
   */
  private JPanel createDbPanel()
  {
    JCheckBox cbOutsideDbs = UIFactory.makeJCheckBox(
        getMsg("delete-outside-dbs-label"),
        getMsg("delete-outside-dbs-tooltip"), UIFactory.TextStyle.INSTRUCTIONS);
    cbOutsideDbs.setOpaque(false);
    cbOutsideDbs.setSelected(true);
    hmCbs.put(FieldName.EXTERNAL_DB_DIRECTORIES, cbOutsideDbs);
    return createOutsidePathPanel(cbOutsideDbs, outsideDbs,
        "delete-outside-dbs-msg");
  }
  /**
   * Creates a panel to ask the user if (s)he wants to remove the logs located
   * outside the installation path.
   * @return a panel to ask the user if (s)he wants to remove the logs located
   * outside the installation path.
   */
  private JPanel createLogPanel()
  {
    JCheckBox cbOutsideLogs = UIFactory.makeJCheckBox(
        getMsg("delete-outside-logs-label"),
        getMsg("delete-outside-logs-tooltip"),
        UIFactory.TextStyle.INSTRUCTIONS);
    cbOutsideLogs.setOpaque(false);
    cbOutsideLogs.setSelected(true);
    hmCbs.put(FieldName.EXTERNAL_LOG_FILES, cbOutsideLogs);
    return createOutsidePathPanel(cbOutsideLogs, outsideLogs,
        "delete-outside-logs-msg");
  }
  private JPanel createOutsidePathPanel(JCheckBox cb, Set<String> paths,
      String msgKey)
  {
    JPanel panel = new JPanel(new GridBagLayout());
    panel.setOpaque(false);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.insets = UIFactory.getEmptyInsets();
    gbc.weightx = 1.0;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.anchor = GridBagConstraints.WEST;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, getMsg(msgKey),
        UIFactory.TextStyle.INSTRUCTIONS), gbc);
    DefaultListModel listModel = new DefaultListModel();
    for (String path : paths)
    {
      listModel.addElement(path);
    }
    JList list = UIFactory.makeJList(UIFactory.TextStyle.INSTRUCTIONS);
    list.setModel(listModel);
    list.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
    list.setVisibleRowCount(Math.min(3, listModel.getSize()));
    JScrollPane scroll = new JScrollPane(list);
    scroll.setViewportBorder(new EmptyBorder(0, 0, 0, 0));
    gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
    panel.add(scroll, gbc);
    gbc.insets.left = 0;
    panel.add(cb, gbc);
    return panel;
  }
  /**
   * Returns the checkbox corresponding to the provided FieldName.
   * @param fieldName the FieldName object.
   * @return the checkbox corresponding to the provided FieldName.
   */
  private JCheckBox getCheckBox(FieldName fieldName)
  {
    JCheckBox cb = hmCbs.get(fieldName);
    if (cb == null)
    {
      throw new IllegalArgumentException("The FieldName "+fieldName+
          " has no checkbox associated.");
    }
    return cb;
  }
}
opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
@@ -32,10 +32,13 @@
import java.util.HashMap;
import org.opends.quicksetup.CurrentInstallStatus;
import org.opends.quicksetup.Step;
import org.opends.quicksetup.installer.FieldName;
import org.opends.quicksetup.installer.InstallProgressDescriptor;
import org.opends.quicksetup.installer.UserInstallData;
import org.opends.quicksetup.uninstaller.UninstallProgressDescriptor;
import org.opends.quicksetup.util.Utils;
/**
 * This is the class that contains the panel on the right-top part of the
@@ -54,6 +57,8 @@
{
  private UserInstallData defaultUserData;
  private CurrentInstallStatus installStatus;
  private static final long serialVersionUID = 5474803491510999334L;
  private HashMap<Step, QuickSetupStepPanel> hmPanels =
@@ -63,12 +68,14 @@
   * The constructor of this class.
   * @param defaultUserData the default data that is used to initialize the
   * contents of the panels (the proposed values).
   * @param installStatus the object describing the current installation status.
   * @param isUninstall boolean telling whether we are uninstalling or not.
   */
  public CurrentStepPanel(UserInstallData defaultUserData,
      boolean isUninstall)
      CurrentInstallStatus installStatus, boolean isUninstall)
  {
    this.defaultUserData = defaultUserData;
    this.installStatus = installStatus;
    createLayout(isUninstall);
  }
@@ -125,11 +132,12 @@
  {
    if (isUninstall)
    {
      hmPanels.put(Step.CONFIRM_UNINSTALL, new ConfirmUninstallPanel());
      hmPanels.put(Step.CONFIRM_UNINSTALL,
          new ConfirmUninstallPanel(installStatus));
      hmPanels.put(Step.PROGRESS, new ProgressPanel());
    } else
    {
      hmPanels.put(Step.WELCOME, new WelcomePanel());
      hmPanels.put(Step.WELCOME, new InstallWelcomePanel());
      hmPanels.put(Step.SERVER_SETTINGS, new ServerSettingsPanel(
          defaultUserData));
      hmPanels.put(Step.DATA_OPTIONS,
@@ -149,7 +157,10 @@
    }
    // For aesthetical reasons we add a little bit of height
    minHeight += UIFactory.EXTRA_DIALOG_HEIGHT;
    if (!Utils.isUninstall())
    {
      minHeight += UIFactory.EXTRA_DIALOG_HEIGHT;
    }
    setPreferredSize(new Dimension(minWidth, minHeight));
    setMinimumSize(new Dimension(minWidth, minHeight));
@@ -184,6 +195,19 @@
  }
  /**
   * Forwards the different panels the UninstallProgressDescriptor so that they
   * can update their contents accordingly.
   * @param descriptor the descriptor of the Uninstallation progress.
   */
  public void displayProgress(UninstallProgressDescriptor descriptor)
  {
    for (Step s : hmPanels.keySet())
    {
      getPanel(s).displayProgress(descriptor);
    }
  }
  /**
   * Retrieves the panel for the provided step.
   * @param step the step for which we want to get the panel.
   * @return the panel for the provided step.
opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java
New file
@@ -0,0 +1,513 @@
/*
 * 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 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.ui;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.InitialLdapContext;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
import org.opends.quicksetup.CurrentInstallStatus;
import org.opends.quicksetup.event.MinimumSizeComponentListener;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.util.BackgroundTask;
import org.opends.quicksetup.util.Utils;
/**
 * This class is a dialog that appears when the user must provide authentication
 * of Directory Manager to connect to the Directory Server in order to be
 * able to do a shutdown. This is currently required for Windows.
 */
public class DirectoryManagerAuthenticationDialog extends JDialog
{
  private static final long serialVersionUID = 9049409381101152000L;
  private JFrame parent;
  private CurrentInstallStatus installStatus;
  private JLabel lDn;
  private JLabel lPwd;
  private JTextField tfDn;
  private JTextField tfPwd;
  private JButton cancelButton;
  private JButton shutDownButton;
  private boolean isCancelled;
  private boolean isServerRunning;
  /**
   * Constructor of the DirectoryManagerAuthenticationDialog.
   * @param parent the parent frame for this dialog.
   * @param installStatus the object describing the current installation
   * status.
   */
  public DirectoryManagerAuthenticationDialog(JFrame parent,
      CurrentInstallStatus installStatus)
  {
    super(parent);
    setTitle(getMsg("shutdown-directory-manager-dialog-title"));
    this.parent = parent;
    this.installStatus = installStatus;
    getContentPane().add(createPanel());
//  TODO: find a way to calculate this dynamically
    setPreferredSize(new Dimension(500, 300));
    addComponentListener(new MinimumSizeComponentListener(this,
        500, 300));
  }
  /**
   * Returns <CODE>true</CODE> if the user clicked on cancel and
   * <CODE>false</CODE> otherwise.
   * @return <CODE>true</CODE> if the user clicked on cancel and
   * <CODE>false</CODE> otherwise.
   */
  public boolean isCancelled()
  {
    return isCancelled;
  }
  /**
   * Packs and displays this dialog.
   *
   */
  public void packAndShow()
  {
    pack();
    Utils.centerOnComponent(this, parent);
    tfPwd.requestFocusInWindow();
    getRootPane().setDefaultButton(shutDownButton);
    setVisible(true);
  }
  /**
   * Tells whether we must stop the server or not.
   * @return <CODE>true</CODE> if we must stop the server and <CODE>false</CODE>
   * otherwise
   */
  public boolean getStopServer()
  {
    return isServerRunning;
  }
  /**
   * Returns the Directory Manager DN provided by the user.
   * @return the Directory Manager DN provided by the user.
   */
  public String getDirectoryManagerDn()
  {
    return tfDn.getText();
  }
  /**
   * Returns the Directory Manager password provided by the user.
   * @return the Directory Manager password provided by the user.
   */
  public String getDirectoryManagerPwd()
  {
    return tfPwd.getText();
  }
  /* The following three methods are just commodity methods to retrieve
   * localized messages */
  private String getMsg(String key)
  {
    return getI18n().getMsg(key);
  }
  private String getMsg(String key, String[] args)
  {
    return getI18n().getMsg(key, args);
  }
  private ResourceProvider getI18n()
  {
    return ResourceProvider.getInstance();
  }
  /**
   * Creates and returns the panel of the dialog.
   * @return the panel of the dialog.
   */
  private JPanel createPanel()
  {
    JPanel p1 = new JPanel(new GridBagLayout());
    p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
    p1.setBorder(UIFactory.DIALOG_PANEL_BORDER);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridwidth = GridBagConstraints.RELATIVE;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.insets = UIFactory.getCurrentStepPanelInsets();
    p1.add(UIFactory.makeJLabel(UIFactory.IconType.WARNING_LARGE, null,
        UIFactory.TextStyle.NO_STYLE), gbc);
    gbc.weightx = 1.0;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.insets.left = 0;
    String msg = getMsg("shutdown-directory-manager-dialog-msg");
    JTextComponent textPane =
      UIFactory.makeHtmlPane(msg, UIFactory.INSTRUCTIONS_FONT);
    textPane.setOpaque(false);
    p1.add(textPane, gbc);
    JPanel p2 = new JPanel(new GridBagLayout());
    p2.setOpaque(false);
    gbc.gridwidth = GridBagConstraints.RELATIVE;
    gbc.weightx = 0.0;
    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
    gbc.insets.left = 0;
    gbc.anchor = GridBagConstraints.WEST;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    lDn = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
        getMsg("shutdown-directory-manager-dn-label"),
        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
    p2.add(lDn, gbc);
    gbc.weightx = 1.0;
    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    tfDn = UIFactory.makeJTextField(getProposedDirectoryManagerDn(),
        getMsg("shutdown-directory-manager-dn-tooltip"),
        UIFactory.DN_FIELD_SIZE, UIFactory.TextStyle.TEXTFIELD);
    p2.add(tfDn, gbc);
    gbc.insets.top = 0;
    gbc.gridwidth = GridBagConstraints.RELATIVE;
    gbc.weightx = 0.0;
    gbc.insets.left = 0;
    lPwd = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
        getMsg("shutdown-directory-manager-pwd-label"),
        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
    p2.add(lPwd, gbc);
    gbc.weightx = 1.0;
    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
    gbc.fill = GridBagConstraints.NONE;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    tfPwd = UIFactory.makeJPasswordField(null,
        getMsg("shutdown-directory-manager-pwd-tooltip"),
        UIFactory.PASSWORD_FIELD_SIZE, UIFactory.TextStyle.PASSWORD_FIELD);
    p2.add(tfPwd, gbc);
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.insets = UIFactory.getEmptyInsets();
    gbc.gridwidth = GridBagConstraints.RELATIVE;
    gbc.weightx = 0.0;
    gbc.insets.top = 0;
    p1.add(Box.createHorizontalGlue(), gbc);
    gbc.weightx = 1.0;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    p1.add(p2, gbc);
    gbc.weighty = 1.0;
    gbc.fill = GridBagConstraints.VERTICAL;
    p1.add(Box.createVerticalGlue(), gbc);
    JPanel buttonPanel = new JPanel(new GridBagLayout());
    buttonPanel.setOpaque(false);
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 1.0;
    gbc.insets = UIFactory.getEmptyInsets();
    gbc.gridwidth = 3;
    buttonPanel.add(Box.createHorizontalGlue(), gbc);
    gbc.gridwidth = GridBagConstraints.RELATIVE;
    gbc.fill = GridBagConstraints.NONE;
    gbc.weightx = 0.0;
    shutDownButton =
      UIFactory.makeJButton(getMsg("shutdown-button-label"),
          getMsg("shutdown-directory-manager-shutdown-button-tooltip"));
    buttonPanel.add(shutDownButton, gbc);
    shutDownButton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ev)
      {
        shutDownClicked();
      }
    });
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
    cancelButton =
      UIFactory.makeJButton(getMsg("cancel-button-label"),
          getMsg("shutdown-directory-manager-cancel-button-tooltip"));
    buttonPanel.add(cancelButton, gbc);
    cancelButton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ev)
      {
        cancelClicked();
      }
    });
    JPanel p = new JPanel(new GridBagLayout());
    p.setBackground(UIFactory.DEFAULT_BACKGROUND);
    gbc.insets = UIFactory.getEmptyInsets();
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.weightx = 1.0;
    gbc.weighty = 1.0;
    p.add(p1, gbc);
    gbc.weighty = 0.0;
    gbc.insets = UIFactory.getButtonsPanelInsets();
    p.add(buttonPanel, gbc);
    return p;
  }
  private String getProposedDirectoryManagerDn()
  {
    String dn;
    Set<String> dns = installStatus.getDirectoryManagerDns();
    if (dns.size() > 0)
    {
      dn = dns.iterator().next();
    }
    else
    {
      dn = null;
    }
    return dn;
  }
  private void cancelClicked()
  {
    isCancelled = true;
    dispose();
  }
  private void shutDownClicked()
  {
    isCancelled = false;
    BackgroundTask worker = new BackgroundTask()
    {
      public Object processBackgroundTask() throws NamingException
      {
        Boolean isServerRunning = Boolean.TRUE;
        try
        {
          InitialLdapContext ctx =
            Utils.createLdapContext(installStatus.getLdapUrl(), tfDn.getText(),
              tfPwd.getText(), 3000, null);
          /*
           * Search for the config to check that it is the directory manager.
           */
          SearchControls searchControls = new SearchControls();
          searchControls.setCountLimit(1);
          searchControls.setSearchScope(
          SearchControls. OBJECT_SCOPE);
          searchControls.setReturningAttributes(
          new String[] {"dn"});
          ctx.search("cn=config", "objectclass=*", searchControls);
        } catch (NamingException ne)
        {
          if (installStatus.isServerRunning())
          {
            throw ne;
          }
          isServerRunning = Boolean.FALSE;
        } catch (Throwable t)
        {
          throw new IllegalStateException("Unexpected throwable.", t);
        }
        return isServerRunning;
      }
      public void backgroundTaskCompleted(Object returnValue,
          Throwable throwable)
      {
        if (throwable != null)
        {
          if (throwable instanceof NamingException)
          {
            boolean dnInvalid = false;
            boolean pwdInvalid = false;
            String dn = tfDn.getText();
            ArrayList<String> possibleCauses = new ArrayList<String>();
            if ("".equals(dn.trim()))
            {
              dnInvalid = true;
              possibleCauses.add(getMsg("empty-directory-manager-dn"));
            }
            else if (!Utils.isDn(dn))
            {
              dnInvalid = true;
              possibleCauses.add(getMsg("not-a-directory-manager-dn"));
            }
            else
            {
              boolean found = false;
              Iterator<String> it =
                installStatus.getDirectoryManagerDns().iterator();
              while (it.hasNext() && !found)
              {
                found = Utils.areDnsEqual(dn, it.next());
              }
              if (!found)
              {
                dnInvalid = true;
                possibleCauses.add(getMsg("not-a-directory-manager-in-config"));
              }
            }
            if ("".equals(tfPwd.getText()))
            {
              pwdInvalid = true;
              possibleCauses.add(getMsg("empty-pwd"));
            }
            if (possibleCauses.size() > 0)
            {
              // Message with causes
              String[] arg = {
                  Utils.getStringFromCollection(possibleCauses, "\n")
              };
              displayError(
                  getMsg("cannot-connect-to-shutdown-with-cause", arg),
                  getMsg("error-title"));
            }
            else
            {
              // Generic message
              displayError(
                  getMsg("cannot-connect-to-shutdown-without-cause"),
                  getMsg("error-title"));
            }
            if (dnInvalid)
            {
              UIFactory.setTextStyle(lDn,
                UIFactory.TextStyle.PRIMARY_FIELD_INVALID);
            }
            else
            {
              UIFactory.setTextStyle(lDn,
                  UIFactory.TextStyle.PRIMARY_FIELD_VALID);
              pwdInvalid = true;
            }
            if (pwdInvalid)
            {
              UIFactory.setTextStyle(lPwd,
                UIFactory.TextStyle.PRIMARY_FIELD_INVALID);
            }
            else
            {
              UIFactory.setTextStyle(lPwd,
                  UIFactory.TextStyle.PRIMARY_FIELD_VALID);
            }
          }
          else
          {
            // This is a bug
            throwable.printStackTrace();
            displayError(
                Utils.getThrowableMsg(getI18n(), "bug-msg", null, throwable),
                getMsg("error-title"));
          }
          cancelButton.setEnabled(true);
          shutDownButton.setEnabled(true);
        } else
        {
          isServerRunning = Boolean.TRUE.equals(returnValue);
          if (!isServerRunning)
          {
            displayInformationMessage(getMsg("server-not-running-msg"),
                getMsg("server-not-running-title"));
          }
          isCancelled = false;
          dispose();
        }
      }
    };
    cancelButton.setEnabled(false);
    shutDownButton.setEnabled(false);
    worker.startBackgroundTask();
  }
  /**
   * Displays an error message dialog.
   *
   * @param msg
   *          the error message.
   * @param title
   *          the title for the dialog.
   */
  private void displayError(String msg, String title)
  {
    Utils.displayError(parent, msg, title);
  }
  /**
   * Displays an information message dialog.
   *
   * @param msg
   *          the information message.
   * @param title
   *          the title for the dialog.
   */
  private void displayInformationMessage(String msg, String title)
  {
    Utils.displayInformationMessage(parent, msg, title);
  }
  /**
   * Method written for testing purposes.
   * @param args the arguments to be passed to the test program.
   */
  public static void main(String[] args)
  {
    try
    {
      // UIFactory.initialize();
      DirectoryManagerAuthenticationDialog dlg =
          new DirectoryManagerAuthenticationDialog(new JFrame(),
              new CurrentInstallStatus());
      dlg.packAndShow();
    } catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}
opends/src/quicksetup/org/opends/quicksetup/ui/InstallWelcomePanel.java
File was renamed from opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java
@@ -29,11 +29,13 @@
import java.awt.Component;
import org.opends.quicksetup.util.Utils;
/**
 * This panel is used to show a welcome message.
 *
 */
class WelcomePanel extends QuickSetupStepPanel
class InstallWelcomePanel extends QuickSetupStepPanel
{
  private static final long serialVersionUID = 6209217138897900860L;
@@ -41,7 +43,7 @@
   * Default constructor.
   *
   */
  public WelcomePanel()
  public InstallWelcomePanel()
  {
    createLayout();
  }
@@ -63,10 +65,26 @@
     * We can use org.opends.server.util.DynamicConstants without problems as it
     * has been added to quicksetup.jar during build time.
     */
    String[] args =
          { org.opends.server.util.DynamicConstants.COMPACT_VERSION_STRING,
              org.opends.server.util.DynamicConstants.BUILD_ID };
    return getMsg("welcome-panel-instructions", args);
    String[] args;
    String msgKey;
    if (Utils.isWebStart())
    {
      msgKey = "welcome-panel-webstart-instructions";
      args = new String[3];
      String cmd = Utils.isWindows()?"setup.bat":"setup";
      args[0] = UIFactory.applyFontToHtml(cmd,
          UIFactory.INSTRUCTIONS_MONOSPACE_FONT);
      args[1] = org.opends.server.util.DynamicConstants.COMPACT_VERSION_STRING;
      args[2] = org.opends.server.util.DynamicConstants.BUILD_ID;
    }
    else
    {
      args = new String[2];
      args[0] = org.opends.server.util.DynamicConstants.COMPACT_VERSION_STRING;
      args[1] = org.opends.server.util.DynamicConstants.BUILD_ID;
      msgKey = "welcome-panel-offline-instructions";
    }
    return getMsg(msgKey, args);
  }
  /**
opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
@@ -42,8 +42,8 @@
import org.opends.quicksetup.installer.InstallProgressDescriptor;
import org.opends.quicksetup.installer.InstallProgressStep;
import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.uninstaller.UninstallProgressDescriptor;
import org.opends.quicksetup.uninstaller.UninstallProgressStep;
/**
 * This panel is used to show the progress of the install or the uninstall.
@@ -63,8 +63,6 @@
  private String lastText;
  private ProgressMessageFormatter formatter;
  /**
   * ProgressPanel constructor.
   */
@@ -180,6 +178,29 @@
  }
  /**
   * {@inheritDoc}
   */
  public void displayProgress(UninstallProgressDescriptor descriptor)
  {
    progressBarLabel.setText(UIFactory.applyFontToHtml(descriptor
        .getProgressBarMsg(), UIFactory.PROGRESS_FONT));
    UninstallProgressStep status = descriptor.getProgressStep();
    if ((status == UninstallProgressStep.FINISHED_WITH_ERROR)
        || (status == UninstallProgressStep.FINISHED_SUCCESSFULLY))
    {
      progressBar.setVisible(false);
    }
    int v = descriptor.getProgressBarRatio().intValue();
    if (v > 0)
    {
      progressBar.setIndeterminate(false);
      progressBar.setValue(v);
    }
    lastText = descriptor.getDetailsMsg();
    detailsTextArea.setText(lastText);
  }
  /**
   * Creates the progress bar panel.
   * @return the created panel.
   */
@@ -212,19 +233,4 @@
    return panel;
  }
  /**
   * Returns the formatter that will be used to display the messages in this
   * panel.
   * @return the formatter that will be used to display the messages in this
   * panel.
   */
  ProgressMessageFormatter getFormatter()
  {
    if (formatter == null)
    {
      formatter = new HtmlProgressMessageFormatter();
    }
    return formatter;
  }
}
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
@@ -33,7 +33,6 @@
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
@@ -48,6 +47,8 @@
import org.opends.quicksetup.installer.InstallProgressDescriptor;
import org.opends.quicksetup.installer.InstallProgressStep;
import org.opends.quicksetup.installer.UserInstallData;
import org.opends.quicksetup.uninstaller.UninstallProgressDescriptor;
import org.opends.quicksetup.uninstaller.UninstallProgressStep;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.util.Utils;
@@ -103,7 +104,7 @@
      frame = new JFrame(getMsg("frame-uninstall-title"));
    } else
    {
      frame = new JFrame(getMsg("frame-quicksetup-title"));
      frame = new JFrame(getMsg("frame-install-title"));
    }
    frame.getContentPane().add(getFramePanel());
@@ -295,6 +296,22 @@
  }
  /**
   * Forwards to the displayed panel the UninstallProgressDescriptor so that
   * they can update their contents accordingly.
   * @param descriptor the descriptor of the Uninstallation progress.
   */
  public void displayProgress(UninstallProgressDescriptor descriptor)
  {
    getCurrentStepPanel().displayProgress(descriptor);
    UninstallProgressStep status = descriptor.getProgressStep();
    if ((status == UninstallProgressStep.FINISHED_SUCCESSFULLY)
        || (status == UninstallProgressStep.FINISHED_WITH_ERROR))
    {
      setButtonEnabled(ButtonName.CLOSE, true);
    }
  }
  /**
   * Displays an error message dialog.
   *
   * @param msg
@@ -304,8 +321,7 @@
   */
  public void displayError(String msg, String title)
  {
    JOptionPane.showMessageDialog(getFrame(), msg, title,
        JOptionPane.ERROR_MESSAGE);
    Utils.displayError(getFrame(), msg, title);
  }
  /**
@@ -320,12 +336,7 @@
   */
  public boolean displayConfirmation(String msg, String title)
  {
    return JOptionPane.YES_OPTION == JOptionPane.showOptionDialog(
        getFrame(), msg, title, JOptionPane.YES_NO_OPTION,
        JOptionPane.QUESTION_MESSAGE, null, // don't use a custom
        // Icon
        null, // the titles of buttons
        null); // default button title
    return Utils.displayConfirmation(getFrame(), msg, title);
  }
  /**
@@ -421,6 +432,7 @@
        // TODO: here we could have an animated gif.
        setButtonEnabled(ButtonName.NEXT, false);
        setButtonEnabled(ButtonName.PREVIOUS, false);
        setButtonEnabled(ButtonName.FINISH, false);
      }
    };
    runOnEventThread(r);
@@ -443,6 +455,7 @@
        // TO COMPLETE: here we could have an animated gif.
        setButtonEnabled(ButtonName.NEXT, true);
        setButtonEnabled(ButtonName.PREVIOUS, true);
        setButtonEnabled(ButtonName.FINISH, true);
      }
    };
    runOnEventThread(r);
@@ -472,6 +485,15 @@
  }
  /**
   * Returns the frame containing the dialog.
   * @return the frame containing the dialog.
   */
  public JFrame getFrame()
  {
    return frame;
  }
  /**
   * Enables a button associated with the given Button Name.
   * @param buttonName the button name of the button.
   * @param enable boolean indicating to enable or to disable the button.
@@ -482,15 +504,6 @@
  }
  /**
   * Returns the frame containing the dialog.
   * @return the frame containing the dialog.
   */
  private JFrame getFrame()
  {
    return frame;
  }
  /**
   * Returns the panel of the dialog.
   * @return the panel of the dialog.
   */
@@ -543,7 +556,8 @@
  {
    if (currentStepPanel == null)
    {
      currentStepPanel = new CurrentStepPanel(defaultUserData, isUninstall());
      currentStepPanel = new CurrentStepPanel(defaultUserData, installStatus,
          isUninstall());
    }
    return currentStepPanel;
  }
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
@@ -95,7 +95,7 @@
    p2.add(Box.createHorizontalGlue(), gbc);
    quitButton =
        UIFactory.makeJButton(getMsg("quit-button-label"),
            getMsg("quit-button-tooltip"));
            getMsg("quit-button-install-tooltip"));
    final ButtonName fButtonName = ButtonName.QUIT;
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
@@ -45,6 +45,9 @@
import org.opends.quicksetup.installer.InstallProgressDescriptor;
import org.opends.quicksetup.installer.LabelFieldDescriptor;
import org.opends.quicksetup.installer.UserInstallData;
import org.opends.quicksetup.uninstaller.UninstallProgressDescriptor;
import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.util.URLWorker;
import org.opends.quicksetup.util.Utils;
@@ -60,6 +63,8 @@
{
  private Component inputPanel;
  private ProgressMessageFormatter formatter;
  // We can use a HashMap (not multi-thread safe) because all
  // the calls to this object are done in the event-thread.
  private HashMap<String, URLWorker> hmURLWorkers =
@@ -92,6 +97,15 @@
  }
  /**
   * Called when a progress change must be reflected in the panels.  Only
   * ProgressPanel overwrites this method and for all the others it stays empty.
   * @param descriptor the descriptor of the Uninstallation progress.
   */
  public void displayProgress(UninstallProgressDescriptor descriptor)
  {
  }
  /**
   * Implements HyperlinkListener.  When the user clicks on a link we will
   * try to display the associated URL in the browser of the user.
   *
@@ -363,6 +377,21 @@
  }
  /**
   * Returns the formatter that will be used to display the messages in this
   * panel.
   * @return the formatter that will be used to display the messages in this
   * panel.
   */
  ProgressMessageFormatter getFormatter()
  {
    if (formatter == null)
    {
      formatter = new HtmlProgressMessageFormatter();
    }
    return formatter;
  }
  /**
   * Creates and returns the title panel.
   * @return the title panel.
   */
@@ -404,7 +433,6 @@
    String instructions = getInstructions();
    if (instructions != null)
    {
      JEditorPane p =
          UIFactory.makeHtmlPane(instructions, UIFactory.INSTRUCTIONS_FONT);
      p.setOpaque(false);
opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java
@@ -240,9 +240,9 @@
      if (isPortField)
      {
        JLabel l =
            UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
                getPortHelpMessage(),
                UIFactory.TextStyle.SECONDARY_FIELD_VALID);
          UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
              getPortHelpMessage(),
              UIFactory.TextStyle.SECONDARY_FIELD_VALID);
        gbc.gridwidth = GridBagConstraints.RELATIVE;
        gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
        auxPanel.add(l, gbc);
@@ -261,7 +261,14 @@
   */
  protected String getInstructions()
  {
    return getMsg("server-settings-panel-instructions");
    if (Utils.isWebStart())
    {
      return getMsg("server-settings-panel-instructions-webstart");
    }
    else
    {
      return getMsg("server-settings-panel-instructions");
    }
  }
  /**
@@ -471,7 +478,14 @@
      tf.addFocusListener(l);
    }
    getBrowseButton().addFocusListener(l);
    lastFocusComponent = getField(FieldName.SERVER_LOCATION);
    if (Utils.isWebStart())
    {
      lastFocusComponent = tfServerLocationRelativePath;
    }
    else
    {
      lastFocusComponent = getField(FieldName.DIRECTORY_MANAGER_PWD);
    }
  }
  /**
@@ -483,15 +497,9 @@
  private String getPortHelpMessage()
  {
    String s = "";
    if (defaultUserData.getServerPort() <= 0)
    if (defaultUserData.getServerPort() != 389)
    {
      if (Utils.isUnix())
      {
        s = getMsg("cannot-find-default-port-unix");
      } else
      {
        s = getMsg("cannot-find-default-port-windows");
      }
      s = getMsg("cannot-use-default-port");
    }
    return s;
  }
opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
@@ -28,6 +28,7 @@
package org.opends.quicksetup.ui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Image;
import java.awt.Insets;
@@ -43,11 +44,13 @@
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
@@ -275,6 +278,11 @@
  public static final Color PROGRESS_COLOR = Color.BLACK;
  /**
   * Specifies the instructions text color.
   */
  public static final Color INSTRUCTIONS_COLOR = Color.BLACK;
  /**
   * Specifies the text field text color.
   */
  public static final Color TEXTFIELD_COLOR = Color.BLACK;
@@ -329,6 +337,12 @@
    Font.decode("Arial-PLAIN-14");
  /**
   * Specifies the font for the instructions of the current panel.
   */
  public static final Font INSTRUCTIONS_MONOSPACE_FONT =
    Font.decode("Monospaced-PLAIN-14");
  /**
   * Specifies the font for the primary valid field.
   */
  public static final Font PRIMARY_FIELD_VALID_FONT =
@@ -559,6 +573,10 @@
     */
    PROGRESS,
    /**
     * Text style for the instructions.
     */
    INSTRUCTIONS,
    /**
     * No text style.
     */
    NO_STYLE
@@ -733,6 +751,19 @@
  }
  /**
   * Creates a JList.
   *
   * @param textStyle the style to be used for the renderer.
   * @return a JList.
   */
  public static JList makeJList(TextStyle textStyle)
  {
    JList list = new JList();
    list.setCellRenderer(makeCellRenderer(textStyle));
    return list;
  }
  /**
   * Sets the specified text style to the component passed as parameter.
   * @param l the component to update.
   * @param style the text style to use.
@@ -791,6 +822,11 @@
      l.setForeground(PROGRESS_COLOR);
      break;
    case INSTRUCTIONS:
      l.setFont(INSTRUCTIONS_FONT);
      l.setForeground(INSTRUCTIONS_COLOR);
      break;
    case TEXTFIELD:
      l.setFont(UIFactory.TEXTFIELD_FONT);
      l.setForeground(TEXTFIELD_COLOR);
@@ -1279,6 +1315,24 @@
    }
    return tooltip;
  }
  private static ListCellRenderer makeCellRenderer(final TextStyle textStyle)
  {
    ListCellRenderer renderer = new ListCellRenderer()
    {
      public Component getListCellRendererComponent(JList list,
          Object value,
          int index,
          boolean isSelected,
          boolean cellHasFocus)
      {
        JLabel l = makeJLabel(IconType.NO_ICON, (String)value, textStyle);
        l.setBorder(new EmptyBorder(TOP_INSET_SECONDARY_FIELD, 0, 0, 0));
        return l;
      }
    };
    return renderer;
  }
}
/**
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java
New file
@@ -0,0 +1,1108 @@
/*
 * 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 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.uninstaller;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import org.opends.quicksetup.CurrentInstallStatus;
import org.opends.quicksetup.event.UninstallProgressUpdateEvent;
import org.opends.quicksetup.event.UninstallProgressUpdateListener;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.util.PlainTextProgressMessageFormatter;
import org.opends.quicksetup.util.Utils;
/**
 * The class used to provide some CLI interface in the uninstall.
 *
 * This class basically is in charge of parsing the data provided by the user
 * in the command line and displaying messages asking the user for information.
 *
 * Once the user has provided all the required information it calls Uninstaller
 * and launches it.
 *
 */
class UninstallCli
{
  /**
   * Return code: Uninstall successful.
   */
  static int SUCCESSFUL = 0;
  /**
   * Return code: User Cancelled uninstall.
   */
  static int CANCELLED = 1;
  /**
   * Return code: User provided invalid data.
   */
  static int USER_DATA_ERROR = 2;
  /**
   * Return code: Error accessing file system (reading/writing).
   */
  static int ERROR_ACCESSING_FILE_SYSTEM = 3;
  /**
   * Return code: Error stopping server.
   */
  static int ERROR_STOPPING_SERVER = 4;
  /**
   * Return code: Bug.
   */
  static int BUG = 5;
  private static String LINE_SEPARATOR = System.getProperty("line.separator");
  static int MAX_LINE_WIDTH = 80;
  private String[] args;
  /**
   * The constructor for this object.
   * @param args the arguments of the uninstall command line.
   */
  UninstallCli(String[] args)
  {
    this.args = args;
  }
  /**
   * Parses the user data and prompts the user for data if required.  If the
   * user provides all the required data it launches the Uninstaller.
   *
   * @return the return code (SUCCESSFUL, CANCELLED, USER_DATA_ERROR,
   * ERROR_ACCESSING_FILE_SYSTEM, ERROR_STOPPING_SERVER or BUG.
   */
  int run()
  {
    int returnValue;
    System.out.println(getMsg("uninstall-launcher-launching-cli"));
    // Parse the arguments
    try
    {
      CurrentInstallStatus installStatus = new CurrentInstallStatus();
      UserUninstallData userData = getUserUninstallData(args, installStatus);
      if (userData != null)
      {
        Uninstaller uninstaller = new Uninstaller(userData,
            new PlainTextProgressMessageFormatter());
        uninstaller.addProgressUpdateListener(
            new UninstallProgressUpdateListener()
            {
              /**
               * UninstallProgressUpdateListener implementation.
               * @param ev the UninstallProgressUpdateEvent we receive.
               *
               */
              public void progressUpdate(UninstallProgressUpdateEvent ev)
              {
                System.out.print(
                    org.opends.server.util.StaticUtils.wrapText(ev.getNewLogs(),
                        MAX_LINE_WIDTH));
              }
            });
        uninstaller.start();
        while (!uninstaller.isFinished())
        {
          try
          {
            Thread.sleep(100);
          }
          catch (Exception ex)
          {
          }
        }
        UninstallException ue = uninstaller.getException();
        if (ue != null)
        {
          switch (ue.getType())
          {
          case FILE_SYSTEM_ERROR:
            returnValue = ERROR_ACCESSING_FILE_SYSTEM;
            break;
          case STOP_ERROR:
            returnValue = ERROR_STOPPING_SERVER;
            break;
          case BUG:
            returnValue = BUG;
            break;
            default:
              throw new IllegalStateException(
                  "Unknown UninstallException type: "+ue.getType());
          }
        }
        else
        {
          returnValue = SUCCESSFUL;
        }
      }
      else
      {
        // User cancelled installation.
        returnValue = CANCELLED;
      }
    }
    catch (UserUninstallDataException uude)
    {
      System.err.println(LINE_SEPARATOR+uude.getLocalizedMessage()+
          LINE_SEPARATOR);
      returnValue = USER_DATA_ERROR;
    }
    return returnValue;
  }
  /**
   * Creates a UserUninstallData based in the arguments provided.  It asks
   * user for additional information if what is provided in the arguments is not
   * enough.
   * @param args the arguments provided in the command line.
   * @param installStatus the current install status.
   * @return the UserUninstallData object with what the user wants to uninstall
   * and null if the user cancels the uninstallation.
   * @throws UserUninstallDataException if there is an error parsing the data
   * in the arguments.
   */
  private UserUninstallData getUserUninstallData(String[] args,
      CurrentInstallStatus installStatus) throws UserUninstallDataException
  {
    UserUninstallData userData = new UserUninstallData();
    boolean silentUninstall = false;
    boolean isCancelled = false;
    /* Step 1: validate the arguments
     */
    validateArguments(userData, args);
    silentUninstall = isSilent(args);
    /* Step 2: If this is not a silent install ask for confirmation to delete
     * the different parts of the installation
     */
    Set<String> outsideDbs = getOutsideDbs(installStatus);
    Set<String> outsideLogs = getOutsideLogs(installStatus);
    if (silentUninstall)
    {
      userData.setRemoveBackups(true);
      userData.setRemoveConfigurationAndSchema(true);
      userData.setRemoveDatabases(true);
      userData.setRemoveLDIFs(true);
      userData.setRemoveLibrariesAndTools(true);
      userData.setRemoveLogs(true);
      userData.setExternalDbsToRemove(outsideDbs);
      userData.setExternalLogsToRemove(outsideLogs);
    }
    else
    {
      isCancelled = askWhatToDelete(userData, outsideDbs, outsideLogs);
    }
    /*
     * Step 3: check if server is running.  Depending if it is running and the
     * OS we are running, ask for authentication information.
     */
    if (!isCancelled)
    {
      isCancelled = askConfirmationToStop(userData, installStatus,
          silentUninstall);
    }
    if (isCancelled)
    {
      userData = null;
    }
    return userData;
  }
  /**
   * Interactively prompts (on standard output) the user to provide a string
   * value.  Any non-empty string will be allowed (the empty string will
   * indicate that the default should be used).  The method will display the
   * message until the user provides one of the values in the validValues
   * parameter.
   *
   * @param  prompt        The prompt to present to the user.
   * @param  defaultValue  The default value returned if the user clicks enter.
   * @param  validValues   The valid values that can be accepted as user input.
   *
   * @return  The string value read from the user.
   */
  private String promptConfirm(String prompt, String defaultValue,
      String[] validValues)
  {
    System.out.println();
    boolean isValid = false;
    String response = null;
    while (!isValid)
    {
      String msg = getMsg("cli-uninstall-confirm-prompt",
          new String[] {prompt, defaultValue});
      System.out.print(msg);
      System.out.flush();
      response = readLine();
      if (response.equals(""))
      {
        response = defaultValue;
      }
      for (int i=0; i<validValues.length && !isValid; i++)
      {
        isValid = validValues[i].equalsIgnoreCase(response);
      }
    }
    return response;
  }
  /**
   * Interactively prompts (on standard output) the user to provide a string
   * value.  Any non-empty string will be allowed (the empty string will
   * indicate that the default should be used).
   *
   * @param  prompt        The prompt to present to the user.
   * @param  defaultValue  The default value returned if the user clicks enter.
   *
   * @return  The string value read from the user.
   */
  private String promptForString(String prompt, String defaultValue)
  {
    System.out.println();
    String response = null;
    String msg = getMsg("cli-uninstall-string-prompt",
        new String[] {prompt, defaultValue});
    System.out.print(msg);
    System.out.flush();
    response = readLine();
    if (response.equals(""))
    {
      response = defaultValue;
    }
    return response;
  }
  /**
   * Reads a line of text from standard input.
   *
   * @return  The line of text read from standard input, or <CODE>null</CODE>
   *          if the end of the stream is reached or an error occurs while
   *          attempting to read the response.
   */
  private String readLine()
  {
    try
    {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      while (true)
      {
        int b = System.in.read();
        if ((b < 0) || (b == '\n'))
        {
          break;
        }
        else if (b == '\r')
        {
          int b2 = System.in.read();
          if (b2 == '\n')
          {
            break;
          }
          else
          {
            baos.write(b);
            baos.write(b2);
          }
        }
        else
        {
          baos.write(b);
        }
      }
      return new String(baos.toByteArray(), "UTF-8");
    }
    catch (Exception e)
    {
      System.err.println(getMsg("cli-uninstall-error-reading-stdin"));
      return null;
    }
  }
  /**
   * Returns a Set of relative paths containing the db paths outside the
   * installation.
   * @param installStatus the Current Install Status object.
   * @return a Set of relative paths containing the db paths outside the
   * installation.
   */
  private Set<String> getOutsideDbs(CurrentInstallStatus installStatus)
  {
    return Utils.getOutsideDbs(installStatus);
  }
  /**
   * Returns a Set of relative paths containing the log paths outside the
   * installation.
   * @param installStatus the Current Install Status object.
   * @return a Set of relative paths containing the log paths outside the
   * installation.
   */
  private Set<String> getOutsideLogs(CurrentInstallStatus installStatus)
  {
    return Utils.getOutsideLogs(installStatus);
  }
  /**
   * Commodity method used to ask the user to confirm the deletion of certain
   * parts of the server.  It updates the provided UserUninstallData object
   * accordingly.  Returns <CODE>true</CODE> if the user cancels and <CODE>
   * false</CODE> otherwise.
   * @param userData the UserUninstallData object to be updated.
   * @param outsideDbs the set of relative paths of databases located outside
   * the installation path of the server.
   * @param outsideLogs the set of relative paths of log files located outside
   * the installation path of the server.
   * @returns <CODE>true</CODE> if the user cancels and <CODE>false</CODE>
   * otherwise.
   */
  private boolean askWhatToDelete(UserUninstallData userData,
      Set<String> outsideDbs, Set<String> outsideLogs)
  {
    boolean cancelled = false;
    String answer = promptConfirm(getMsg("cli-uninstall-what-to-delete"),
        "1", new String[] {"1", "2", "3"});
    if ("3".equals(answer))
    {
      cancelled = true;
    }
    else if ("1".equals(answer))
    {
      userData.setRemoveBackups(true);
      userData.setRemoveConfigurationAndSchema(true);
      userData.setRemoveDatabases(true);
      userData.setRemoveLDIFs(true);
      userData.setRemoveLibrariesAndTools(true);
      userData.setRemoveLogs(true);
      userData.setExternalDbsToRemove(outsideDbs);
      userData.setExternalLogsToRemove(outsideLogs);
    }
    else
    {
      boolean somethingSelected = false;
      while (!somethingSelected)
      {
//      Ask for confirmation for the different items
        String[] keys = {
            "cli-uninstall-confirm-libraries-binaries",
            "cli-uninstall-confirm-databases",
            "cli-uninstall-confirm-logs",
            "cli-uninstall-confirm-configuration-schema",
            "cli-uninstall-confirm-backups",
            "cli-uninstall-confirm-ldifs",
            "cli-uninstall-confirm-outsidedbs",
            "cli-uninstall-confirm-outsidelogs"
        };
        String[] validValues = {
            getMsg("cli-uninstall-yes-long"), getMsg("cli-uninstall-no-long"),
            getMsg("cli-uninstall-yes-short"), getMsg("cli-uninstall-no-short")
        };
        boolean[] answers = new boolean[keys.length];
        for (int i=0; i<keys.length; i++)
        {
          boolean ignore = ((i == 6) && (outsideDbs.size() == 0)) ||
          ((i == 7) && (outsideLogs.size() == 0));
          if (!ignore)
          {
            String msg;
            if (i == 6)
            {
              String[] arg = {Utils.getStringFromCollection(outsideDbs,
                  LINE_SEPARATOR)};
              msg = getMsg(keys[i], arg);
            }
            else if (i == 7)
            {
              String[] arg = {Utils.getStringFromCollection(outsideLogs,
                  LINE_SEPARATOR)};
              msg = getMsg(keys[i], arg);
            }
            else
            {
              msg = getMsg(keys[i]);
            }
            answer = promptConfirm(msg, getMsg("cli-uninstall-yes-long"),
                validValues);
            if (getMsg("cli-uninstall-yes-long").equalsIgnoreCase(answer) ||
                getMsg("cli-uninstall-yes-short").equalsIgnoreCase(answer))
            {
              answers[i] = true;
            }
            else
            {
              answers[i] = false;
            }
          }
          else
          {
            answers[i] = false;
          }
        }
        for (int i=0; i<answers.length; i++)
        {
          switch (i)
          {
          case 0:
            userData.setRemoveLibrariesAndTools(answers[i]);
            break;
          case 1:
            userData.setRemoveDatabases(answers[i]);
            break;
          case 2:
            userData.setRemoveLogs(answers[i]);
            break;
          case 3:
            userData.setRemoveConfigurationAndSchema(answers[i]);
            break;
          case 4:
            userData.setRemoveBackups(answers[i]);
            break;
          case 5:
            userData.setRemoveLDIFs(answers[i]);
            break;
          case 6:
            if (answers[i])
            {
              userData.setExternalDbsToRemove(outsideDbs);
            }
            break;
          case 7:
            if (answers[i])
            {
              userData.setExternalLogsToRemove(outsideLogs);
            }
            break;
          }
        }
        if ((userData.getExternalDbsToRemove().size() == 0) &&
            (userData.getExternalLogsToRemove().size() == 0) &&
            !userData.getRemoveLibrariesAndTools() &&
            !userData.getRemoveDatabases() &&
            !userData.getRemoveConfigurationAndSchema() &&
            !userData.getRemoveBackups() &&
            !userData.getRemoveLDIFs() &&
            !userData.getRemoveLogs())
        {
          somethingSelected = false;
          System.out.println(LINE_SEPARATOR+
              getMsg("cli-uninstall-nothing-to-be-uninstalled"));
        }
        else
        {
          somethingSelected = true;
        }
      }
    }
    return cancelled;
  }
  /**
   * Commodity method used to ask the user (when necessary) if the server must
   * be stopped or not.  If required it also asks the user authentication to
   * be able to shut down the server in Windows.
   * @param userData the UserUninstallData object to be updated with the
   * authentication of the user.
   * @param installStatus the CurrentInstallStatus object.
   * @param silentUninstall boolean telling whether this is a silent uninstall
   * or not.
   * @return <CODE>true</CODE> if the user wants to continue with uninstall and
   * <CODE>false</CODE> otherwise.
   * @throws UserUninstallDataException if there is a problem with the data
   * provided by the user (in the particular case where we are on silent
   * uninstall and some data is missing or not valid).
   */
  private boolean askConfirmationToStop(UserUninstallData userData,
      CurrentInstallStatus installStatus, boolean silentUninstall)
  throws UserUninstallDataException
  {
    boolean cancelled = false;
    String errorMsg = null;
    if (installStatus.isServerRunning())
    {
      if (Utils.isWindows())
      {
        if (silentUninstall)
        {
          String dn = userData.getDirectoryManagerDn();
          String pwd = userData.getDirectoryManagerPwd();
          if ((dn == null) || (pwd == null))
          {
            errorMsg = getMsg("cli-uninstall-data-missing-to-shutdown-server");
          }
          else
          {
            if (!canConnectAsAdministrativeUser(installStatus.getLdapUrl(),
                userData.getDirectoryManagerDn(),
                userData.getDirectoryManagerPwd()))
            {
              errorMsg = getErrorMsgConnecting(dn, pwd, installStatus);
            }
          }
          if (errorMsg != null)
          {
            throw new UserUninstallDataException(null, errorMsg);
          }
        }
        else
        {
          /* Ask for the Directory Manager Dn and password if they were not
           * provided.
           */
          boolean askForDn = userData.getDirectoryManagerDn() == null;
          boolean askForPwd = userData.getDirectoryManagerPwd() == null;
          boolean prompted = false;
          if (!askForDn && !askForPwd)
          {
            String dn = userData.getDirectoryManagerDn();
            String pwd = userData.getDirectoryManagerPwd();
            if (!canConnectAsAdministrativeUser(installStatus.getLdapUrl(),
                dn, pwd))
            {
              System.out.println(LINE_SEPARATOR+LINE_SEPARATOR+getMsg(
              "cli-uninstall-stop-authentication-generic-prompt1"));
              System.out.println(getErrorMsgConnecting(dn, pwd, installStatus));
              askForDn = true;
              askForPwd = true;
            }
            else
            {
              String[] validValues = {
                  getMsg("cli-uninstall-yes-short"),
                  getMsg("cli-uninstall-no-short"),
                  getMsg("cli-uninstall-yes-long"),
                  getMsg("cli-uninstall-no-long")
              };
              String answer = promptConfirm(
                  getMsg("cli-uninstall-confirm-stop"),
                  getMsg("cli-uninstall-yes-long"), validValues);
              if (getMsg("cli-uninstall-no-short").equalsIgnoreCase(answer) ||
                  getMsg("cli-uninstall-no-long").equalsIgnoreCase(answer))
              {
                cancelled = true;
              }
            }
          }
          else
          {
            System.out.println(
                getMsg("cli-uninstall-stop-authentication-generic-prompt1"));
          }
          while (askForDn || askForPwd)
          {
            if (!prompted)
            {
              System.out.println(
                getMsg("cli-uninstall-stop-authentication-generic-prompt2"));
            }
            if (askForDn)
            {
              String defaultDn = userData.getDirectoryManagerDn();
              if ((defaultDn == null) || !Utils.isDn(defaultDn))
              {
                Set<String> dns = installStatus.getDirectoryManagerDns();
                if (dns.size() > 0)
                {
                  defaultDn = dns.iterator().next();
                }
                else
                {
                  defaultDn = "cn=Directory Manager";
                }
              }
              userData.setDirectoryManagerDn(
                  promptForString(getMsg("cli-uninstall-prompt-dn"),
                  defaultDn));
              prompted = true;
            }
            if (askForPwd)
            {
              userData.setDirectoryManagerPwd(promptForPassword(
                  getMsg("cli-uninstall-prompt-pwd")));
              prompted = true;
            }
            String dn = userData.getDirectoryManagerDn();
            String pwd = userData.getDirectoryManagerPwd();
            if (!canConnectAsAdministrativeUser(installStatus.getLdapUrl(),
                dn, pwd))
            {
              if (installStatus.isServerRunning())
              {
                System.out.println(LINE_SEPARATOR+getErrorMsgConnecting(dn, pwd,
                    installStatus));
                askForDn = true;
                askForPwd = true;
              }
              else
              {
                /* The server was stopped while we asked the user to provide
                 * authentication.  Inform of this and return.
                 */
                System.out.println(
                    getMsg("cli-uninstall-server-stopped"));
                askForDn = false;
                askForPwd = false;
                /* Ask for confirmation to delete files */
                cancelled = !confirmDeleteFiles();
              }
            }
            else
            {
              askForDn = false;
              askForPwd = false;
              /* Ask for confirmation to stop server */
              cancelled = !confirmToStopServer();
            }
          }
        }
      }
      else
      {
        if (!silentUninstall)
        {
          /* Ask for confirmation to stop server */
          cancelled = !confirmToStopServer();
        }
      }
      if (!cancelled)
      {
        /* During all the confirmations, the server might be stopped. */
        userData.setStopServer(installStatus.isServerRunning());
      }
    }
    else
    {
      userData.setStopServer(false);
      if (!silentUninstall)
      {
        /* Ask for confirmation to delete files */
        cancelled = !confirmDeleteFiles();
      }
    }
    return cancelled;
  }
  /**
   * Commodity method providing a localized message when we cannot connect to
   * the server.
   * @param dn the DN used to connect to the server.
   * @param pwd the password used to connect to the server.
   * @param installStatus the CurrentInstallStatus object describing the
   * status of the installation.
   * @return a localized message when we cannot connect to the server.
   */
  private String getErrorMsgConnecting(String dn, String pwd,
      CurrentInstallStatus installStatus)
  {
    String msg;
    ArrayList<String> possibleCauses = new ArrayList<String>();
    if ("".equals(dn.trim()))
    {
      possibleCauses.add(getMsg("empty-directory-manager-dn"));
    }
    else if (!Utils.isDn(dn))
    {
      possibleCauses.add(getMsg("not-a-directory-manager-dn"));
    }
    else
    {
      boolean found = false;
      Iterator<String> it =
        installStatus.getDirectoryManagerDns().iterator();
      while (it.hasNext() && !found)
      {
        found = Utils.areDnsEqual(dn, it.next());
      }
      if (!found)
      {
        possibleCauses.add(getMsg("not-a-directory-manager-in-config"));
      }
    }
    if ("".equals(pwd))
    {
      possibleCauses.add(getMsg("empty-pwd"));
    }
    if (possibleCauses.size() > 0)
    {
      // Message with causes
      String[] arg = {
          Utils.getStringFromCollection(possibleCauses, "\n")
      };
      msg = getMsg("cli-uninstall-cannot-connect-to-shutdown-with-cause", arg);
    }
    else
    {
      // Generic message
      msg = getMsg("cli-uninstall-cannot-connect-to-shutdown-without-cause");
    }
    return msg;
  }
  /**
   * Returns <CODE>true</CODE> if this is a silent uninstall and
   * <CODE>false</CODE> otherwise.
   * @param args the arguments passed in the command line.
   * @return <CODE>true</CODE> if this is a silent uninstall and
   * <CODE>false</CODE> otherwise.
   */
  private boolean isSilent(String[] args)
  {
    boolean isSilent = false;
    for (int i=0; i<args.length && !isSilent; i++)
    {
      if (args[i].equalsIgnoreCase("--silentUninstall") ||
          args[i].equalsIgnoreCase("-s"))
      {
        isSilent = true;
      }
    }
    return isSilent;
  }
  /**
   * Commodity method used to validate the arguments provided by the user in
   * the command line and updating the UserUninstallData object accordingly.
   * @param userData the UserUninstallData object to be updated.
   * @param args the arguments passed in the command line.
   * @throws UserUninstallDataException if there is an error with the data
   * provided by the user.
   */
  private void validateArguments(UserUninstallData userData,
      String[] args) throws UserUninstallDataException
  {
    String directoryManagerPwd = null;
    String directoryManagerPwdFile = null;
    ArrayList<String> errors = new ArrayList<String>();
    for (int i=0; i<args.length; i++)
    {
      if (args[i].equalsIgnoreCase("--cli") ||
          args[i].equalsIgnoreCase("-H") ||
          args[i].equalsIgnoreCase("--help") ||
          args[i].equalsIgnoreCase("--silentUninstall") ||
          args[i].equalsIgnoreCase("-s"))
      {
        // Ignore
      }
      else if (Utils.isWindows() &&
          (args[i].equalsIgnoreCase("-D") ||
          args[i].equalsIgnoreCase("--rootUserDN")))
      {
        if (i+1 >= args.length)
        {
          errors.add(getMsg("cli-uninstall-root-user-dn-not-provided"));
        }
        else
        {
          if (args[i+1].indexOf("-") == 0)
          {
            errors.add(getMsg("cli-uninstall-root-user-dn-not-provided"));
          }
          else
          {
            userData.setDirectoryManagerDn(args[i+1]);
            i++;
          }
        }
      }
      else if (Utils.isWindows() &&
          (args[i].equals("-w") ||
          args[i].equalsIgnoreCase("--rootUserPassword")))
      {
        if (i+1 >= args.length)
        {
          errors.add(getMsg("cli-uninstall-root-user-pwd-not-provided"));
        }
        else
        {
          if (args[i+1].indexOf("-") == 0)
          {
            errors.add(getMsg("cli-uninstall-root-user-pwd-not-provided"));
          }
          else
          {
            directoryManagerPwd = args[i+1];
            i++;
          }
        }
      }
      else if (Utils.isWindows() &&
          (args[i].equals("-W") ||
          args[i].equalsIgnoreCase("--rootUserPasswordFile")))
      {
        if (i+1 >= args.length)
        {
          errors.add(getMsg("cli-uninstall-root-user-pwd-file-not-provided"));
        }
        else
        {
          if (args[i+1].indexOf("-") == 0)
          {
            errors.add(getMsg("cli-uninstall-root-user-pwd-file-not-provided"));
          }
          else
          {
            directoryManagerPwdFile = args[i+1];
            i++;
          }
        }
      }
      else
      {
        String[] arg = {args[i]};
        errors.add(getMsg("cli-uninstall-unknown-argument", arg));
      }
    }
    if ((directoryManagerPwdFile != null) && (directoryManagerPwd != null))
    {
      errors.add(getMsg("cli-uninstall-pwd-and-pwd-file-provided"));
    }
    else
    {
      String pwd;
      if (directoryManagerPwdFile != null)
      {
        pwd = readPwdFromFile(directoryManagerPwdFile);
        if (pwd == null)
        {
          String[] arg = {directoryManagerPwdFile};
          errors.add(getMsg("cli-uninstall-error-reading-pwd-file", arg));
        }
      }
      else
      {
        pwd = directoryManagerPwd;
      }
      userData.setDirectoryManagerPwd(pwd);
    }
    if (errors.size() > 0)
    {
      String msg = Utils.getStringFromCollection(errors,
          LINE_SEPARATOR+LINE_SEPARATOR);
      throw new UserUninstallDataException(null, msg);
    }
  }
  /**
   * Interactively prompts (on standard output) the user to provide a string
   * value.
   *
   * @param  prompt  The prompt to present to the user.
   *
   * @return  The string value read from the user.
   */
  private String promptForPassword(String prompt)
  {
    char[] password = null;
    while ((password == null) || (password.length == 0))
    {
      System.out.println();
      System.out.print(prompt);
      System.out.flush();
      password = org.opends.server.util.PasswordReader.readPassword();
    }
    return new String(password);
  }
  /**
   * Returns the password stored in a file.  Returns <CODE>null</CODE> if no
   * password is found.
   * @param path the path of the file containing the password.
   * @return the password stored in a file.  Returns <CODE>null</CODE> if no
   * password is found.
   */
  private String readPwdFromFile(String path)
  {
    String pwd = null;
    BufferedReader reader = null;
    try
    {
      reader = new BufferedReader(new FileReader(path));
      pwd = reader.readLine();
    }
    catch (Exception e)
    {
    }
    finally
    {
      try
      {
        if (reader != null)
        {
          reader.close();
        }
      } catch (Exception e) {}
    }
    return pwd;
  }
  /**
   * Method used to know if we can connect as administrator in a server with a
   * given password and dn.
   * @param ldapUrl the ldap URL of the server.
   * @param dn the dn to be used.
   * @param pwd the password to be used.
   * @return <CODE>true</CODE> if we can connect and read the configuration and
   * <CODE>false</CODE> otherwise.
   */
  private boolean canConnectAsAdministrativeUser(String ldapUrl, String dn,
      String pwd)
  {
    return Utils.canConnectAsAdministrativeUser(ldapUrl, dn, pwd);
  }
  /**
   *  Ask for confirmation to stop server.
   *  @return <CODE>true</CODE> if the user wants to continue and stop the
   *  server.  <CODE>false</CODE> otherwise.
   */
  private boolean confirmToStopServer()
  {
    boolean confirm = true;
    String[] validValues = {
        getMsg("cli-uninstall-yes-short"),
        getMsg("cli-uninstall-no-short"),
        getMsg("cli-uninstall-yes-long"),
        getMsg("cli-uninstall-no-long")
    };
    String answer = promptConfirm(
        getMsg("cli-uninstall-confirm-stop"),
        getMsg("cli-uninstall-yes-long"), validValues);
    if (getMsg("cli-uninstall-no-short").equalsIgnoreCase(answer) ||
        getMsg("cli-uninstall-no-long").equalsIgnoreCase(answer))
    {
      confirm = false;
    }
    return confirm;
  }
  /**
   *  Ask for confirmation to delete files.
   *  @return <CODE>true</CODE> if the user wants to continue and delete the
   *  files.  <CODE>false</CODE> otherwise.
   */
  private boolean confirmDeleteFiles()
  {
    boolean confirm = true;
    String[] validValues = {
        getMsg("cli-uninstall-yes-short"),
        getMsg("cli-uninstall-no-short"),
        getMsg("cli-uninstall-yes-long"),
        getMsg("cli-uninstall-no-long")
    };
    String answer = promptConfirm(
        getMsg("cli-uninstall-confirm-delete-files"),
        getMsg("cli-uninstall-yes-long"), validValues);
    if (getMsg("cli-uninstall-no-short").equalsIgnoreCase(answer) ||
        getMsg("cli-uninstall-no-long").equalsIgnoreCase(answer))
    {
      confirm = false;
    }
    return confirm;
  }
  /**
   * The following three methods are just commodity methods to get localized
   * messages.
   */
  private static String getMsg(String key)
  {
    return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key),
        MAX_LINE_WIDTH);
  }
  private static String getMsg(String key, String[] args)
  {
    return org.opends.server.util.StaticUtils.wrapText(
        getI18n().getMsg(key, args), MAX_LINE_WIDTH);
  }
  private static ResourceProvider getI18n()
  {
    return ResourceProvider.getInstance();
  }
}
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallException.java
New file
@@ -0,0 +1,92 @@
/*
 * 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 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.uninstaller;
/**
 * This exception is used to encapsulate all the error that we might have
 * during the uninstallation.
 *
 * @see Uninstaller.
 *
 */
public class UninstallException extends Exception
{
  private static final long serialVersionUID = 5988129928117915261L;
  private Type type;
  /**
   * This enum contains the different type of UninstallException that we can
   * have.
   *
   */
  public enum Type
  {
    /**
     * Error related to file system error: IOException deleting files,
     * permission errors, etc.
     */
    FILE_SYSTEM_ERROR,
    /**
     * Error stopping the Open DS server.
     */
    STOP_ERROR,
    /**
     * A bug (for instance when we throw an IllegalStateException).
     */
    BUG
  };
  /**
   * The constructor of the UninstallException.
   * @param type the type of error we have.
   * @param localizedMsg a localized string describing the problem.
   * @param rootCause the root cause of this exception.
   */
  public UninstallException(Type type, String localizedMsg, Throwable rootCause)
  {
    super(localizedMsg, rootCause);
    this.type = type;
  }
  /**
   * Returns the Type of this exception.
   * @return the Type of this exception.
   */
  public Type getType()
  {
    return type;
  }
  /**
   * {@inheritDoc}
   */
  public String toString()
  {
    return getMessage();
  }
}
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java
New file
@@ -0,0 +1,250 @@
/*
 * 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 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.uninstaller;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.opends.quicksetup.SplashScreen;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.util.Utils;
/**
 * This class is called by the uninstall command lines to launch the uninstall
 * of the Directory Server. It just checks the command line arguments and the
 * environment and determines whether the graphical or the command line
 * based uninstall much be launched.
 *
 */
public class UninstallLauncher
{
  private static String COMMAND_NAME_WINDOWS = "uninstall.bat";
  private static String COMMAND_NAME_UNIX = "uninstall";
  /**
   * The main method which is called by the uninstall command lines.
   * @param args the arguments passed by the command lines.
   */
  public static void main(String[] args)
  {
    boolean printUsage = false;
    boolean useCli = false;
    if ((args != null) && (args.length > 0))
    {
      for (int i = 0; i < args.length; i++)
      {
        if (args[i].equalsIgnoreCase("--cli"))
        {
          useCli = true;
        }
        else if (args[i].equalsIgnoreCase("-H") ||
            args[i].equalsIgnoreCase("--help"))
        {
          printUsage = true;
        }
      }
      if (!useCli)
      {
        if (args.length > 0)
        {
          printUsage = true;
        }
      }
    }
    if (printUsage)
    {
      printUsage();
      System.exit(1);
    } else if (useCli)
    {
      int exitCode = launchCliUninstall(args);
      if (exitCode != 0)
      {
        System.exit(exitCode);
      }
    } else
    {
      System.setProperty("org.opends.quicksetup.uninstall", "true");
      int exitCode = launchGuiUninstall(args);
      if (exitCode != 0)
      {
        System.err.println(getMsg("uninstall-launcher-gui-launched-failed"));
        exitCode = launchCliUninstall(args);
        if (exitCode != 0)
        {
          System.exit(exitCode);
        }
      }
    }
  }
  /**
   * Launches the command line based uninstall.
   * @param args the arguments passed
   * @return 0 if everything worked fine, and an error code if something wrong
   * occurred.
   */
  private static int launchCliUninstall(String[] args)
  {
    System.setProperty("org.opends.quicksetup.cli", "true");
    UninstallCli cli = new UninstallCli(args);
    int returnValue = cli.run();
    if (returnValue == UninstallCli.USER_DATA_ERROR)
    {
      printUsage();
    }
//    Add an extra space systematically
    System.out.println();
    return returnValue;
  }
  /**
   * Launches the graphical uninstall. The graphical uninstall is launched in a
   * different thread that the main thread because if we have a problem with the
   * graphical system (for instance the DISPLAY environment variable is not
   * correctly set) the native libraries will call exit. However if we launch
   * this from another thread, the thread will just be killed.
   *
   * This code also assumes that if the call to SplashWindow.main worked (and
   * the splash screen was displayed) we will never get out of it (we will call
   * a System.exit() when we close the graphical uninstall dialog).
   *
   * @params String[] args the arguments used to call the SplashWindow main
   *         method
   * @return 0 if everything worked fine, or 1 if we could not display properly
   *         the SplashWindow.
   */
  private static int launchGuiUninstall(final String[] args)
  {
    System.out.println(getMsg("uninstall-launcher-launching-gui"));
    final int[] returnValue =
      { -1 };
    Thread t = new Thread(new Runnable()
    {
      public void run()
      {
        SplashScreen.main(args);
        returnValue[0] = 0;
      }
    });
    /*
     * This is done to avoid displaying the stack that might occur if there are
     * problems with the display environment.
     */
    PrintStream printStream = System.err;
    System.setErr(new EmptyPrintStream());
    t.start();
    try
    {
      t.join();
    }
    catch (InterruptedException ie)
    {
      /* An error occurred, so the return value will be -1.  We got nothing to
      do with this exception. */
    }
    System.setErr(printStream);
    return returnValue[0];
  }
  private static void printUsage()
  {
    String arg;
    if (Utils.isWindows())
    {
      arg = COMMAND_NAME_WINDOWS;
    } else
    {
      arg = COMMAND_NAME_UNIX;
    }
    /*
     * This is required because the usage message contains '{' characters that
     * mess up the MessageFormat.format method.
     */
    String msg;
    if (Utils.isWindows())
    {
      msg = getMsg("uninstall-launcher-usage-windows");
    }
    else
    {
      msg = getMsg("uninstall-launcher-usage-unix");
    }
    msg = msg.replace("{0}", arg);
    System.err.println(msg);
  }
  /**
   * The following three methods are just commodity methods to get localized
   * messages.
   */
  private static String getMsg(String key)
  {
    return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key),
        UninstallCli.MAX_LINE_WIDTH);
  }
  private static String getMsg(String key, String[] args)
  {
    return org.opends.server.util.StaticUtils.wrapText(
        getI18n().getMsg(key, args), UninstallCli.MAX_LINE_WIDTH);
  }
  private static ResourceProvider getI18n()
  {
    return ResourceProvider.getInstance();
  }
  /**
   * This class is used to avoid displaying the error message related to display
   * problems that we might have when trying to display the SplashWindow.
   *
   */
  static class EmptyPrintStream extends PrintStream
  {
    /**
     * Default constructor.
     *
     */
    public EmptyPrintStream()
    {
      super(new ByteArrayOutputStream(), true);
    }
    /**
     * {@inheritDoc}
     */
    public void println(String msg)
    {
    }
  }
}
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java
@@ -43,14 +43,22 @@
   */
  STOPPING_SERVER,
  /**
   * Removing Database files.
   * Removing External Database files.
   */
  REMOVING_DATABASE_FILES,
  DELETING_EXTERNAL_DATABASE_FILES,
  /**
   * Removing External Log files.
   */
  DELETING_EXTERNAL_LOG_FILES,
  /**
   * Removing external references.
   */
  REMOVING_EXTERNAL_REFERENCES,
  /**
   * Removing installation files.
   */
  DELETING_INSTALLATION_FILES,
  /**
   * Installation finished successfully.
   */
  FINISHED_SUCCESSFULLY,
opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java
@@ -27,14 +27,79 @@
package org.opends.quicksetup.uninstaller;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.opends.quicksetup.event.UninstallProgressUpdateEvent;
import org.opends.quicksetup.event.UninstallProgressUpdateListener;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.util.ProgressMessageFormatter;
import org.opends.quicksetup.util.Utils;
/**
 * This class is in charge of performing the uninstallation of Open DS.
 *
 * TODO implement this class.
 *
 */
public class Uninstaller
{
  private UserUninstallData userData;
  private ProgressMessageFormatter formatter;
  private UninstallProgressStep status;
  private HashMap<UninstallProgressStep, Integer> hmRatio =
    new HashMap<UninstallProgressStep, Integer>();
  private HashMap<UninstallProgressStep, String> hmSummary =
    new HashMap<UninstallProgressStep, String>();
  private HashSet<UninstallProgressUpdateListener> listeners =
    new HashSet<UninstallProgressUpdateListener>();
  private UninstallException ue;
  /**
   * Uninstaller constructor.
   * @param userData the object containing the information provided by the user
   * in the uninstallation.
   * @param formatter the message formatter to be used to generate the text of
   * the UninstallProgressUpdateEvent.
   */
  public Uninstaller(UserUninstallData userData,
      ProgressMessageFormatter formatter)
  {
    this.userData = userData;
    this.formatter = formatter;
    initMaps();
    status = UninstallProgressStep.NOT_STARTED;
  }
  /**
   * Start the uninstall process.  This method will not block the thread on
   * which is invoked.
   */
  public void start()
  {
    Thread t = new Thread(new Runnable()
    {
      public void run()
      {
        doUninstall();
      }
    });
    t.start();
  }
  /**
   * Returns whether the uninstaller has finished or not.
   * @return <CODE>true</CODE> if the install is finished or <CODE>false
@@ -42,7 +107,1145 @@
   */
  public boolean isFinished()
  {
    /* TODO implement this */
    return false;
    return getStatus() == UninstallProgressStep.FINISHED_SUCCESSFULLY
    || getStatus() == UninstallProgressStep.FINISHED_WITH_ERROR;
  }
  /**
   * Adds a UninstallProgressUpdateListener that will be notified of updates in
   * the uninstall progress.
   * @param l the UninstallProgressUpdateListener to be added.
   */
  public void addProgressUpdateListener(UninstallProgressUpdateListener l)
  {
    listeners.add(l);
  }
  /**
   * Removes a UninstallProgressUpdateListener.
   * @param l the UninstallProgressUpdateListener to be removed.
   */
  public void removeProgressUpdateListener(UninstallProgressUpdateListener l)
  {
    listeners.remove(l);
  }
  /**
   * Returns the UninstallException that might occur during installation or
   * <CODE>null</CODE> if no exception occurred.
   * @return the UninstallException that might occur during installation or
   * <CODE>null</CODE> if no exception occurred.
   */
  public UninstallException getException()
  {
    return ue;
  }
  /**
   * Initialize the different map used in this class.
   *
   */
  private void initMaps()
  {
    hmSummary.put(UninstallProgressStep.NOT_STARTED,
        getFormattedSummary(getMsg("summary-uninstall-not-started")));
    hmSummary.put(UninstallProgressStep.STOPPING_SERVER,
        getFormattedSummary(getMsg("summary-stopping")));
    hmSummary.put(UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES,
        getFormattedSummary(getMsg("summary-deleting-external-db-files")));
    hmSummary.put(UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES,
        getFormattedSummary(getMsg("summary-deleting-external-log-files")));
    hmSummary.put(UninstallProgressStep.REMOVING_EXTERNAL_REFERENCES,
        getFormattedSummary(getMsg("summary-deleting-external-references")));
    hmSummary.put(UninstallProgressStep.DELETING_INSTALLATION_FILES,
        getFormattedSummary(getMsg("summary-deleting-installation-files")));
    String successMsg;
    if (Utils.isCli())
    {
      if (userData.getRemoveLibrariesAndTools())
      {
        String[] arg = {getTab()+getQuicksetupJarPath()+
            getLineBreak()+getTab()+getOpenDSJarPath()};
        successMsg = getMsg(
            "summary-uninstall-finished-successfully-remove-jarfiles-cli",
            arg);
      }
      else
      {
        successMsg = getMsg("summary-uninstall-finished-successfully-cli");
      }
    }
    else
    {
      if (userData.getRemoveLibrariesAndTools())
      {
        String[] arg = {getTab()+getQuicksetupJarPath()+
            getLineBreak()+getTab()+getOpenDSJarPath()};
        successMsg = getMsg(
            "summary-uninstall-finished-successfully-remove-jarfiles", arg);
      }
      else
      {
        successMsg = getMsg("summary-uninstall-finished-successfully");
      }
    }
    hmSummary.put(UninstallProgressStep.FINISHED_SUCCESSFULLY,
        getFormattedSuccess(successMsg));
    hmSummary.put(UninstallProgressStep.FINISHED_WITH_ERROR,
        getFormattedError(getMsg("summary-uninstall-finished-with-error")));
    /*
     * hmTime contains the relative time that takes for each task to be
     * accomplished. For instance if stopping takes twice the time of
     * deleting files, the value for downloading will be the double of the
     * value for extracting.
     */
    HashMap<UninstallProgressStep, Integer> hmTime =
        new HashMap<UninstallProgressStep, Integer>();
    hmTime.put(UninstallProgressStep.STOPPING_SERVER, 15);
    hmTime.put(UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES, 30);
    hmTime.put(UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES, 5);
    hmTime.put(UninstallProgressStep.REMOVING_EXTERNAL_REFERENCES, 5);
    hmTime.put(UninstallProgressStep.DELETING_INSTALLATION_FILES, 10);
    int totalTime = 0;
    ArrayList<UninstallProgressStep> steps =
      new ArrayList<UninstallProgressStep>();
    if (getUserData().getStopServer())
    {
      totalTime += hmTime.get(UninstallProgressStep.STOPPING_SERVER);
      steps.add(UninstallProgressStep.STOPPING_SERVER);
    }
    totalTime += hmTime.get(UninstallProgressStep.DELETING_INSTALLATION_FILES);
    steps.add(UninstallProgressStep.DELETING_INSTALLATION_FILES);
    if (getUserData().getExternalDbsToRemove().size() > 0)
    {
      totalTime += hmTime.get(
          UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES);
      steps.add(UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES);
    }
    if (getUserData().getExternalLogsToRemove().size() > 0)
    {
      totalTime += hmTime.get(
          UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES);
      steps.add(UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES);
    }
    int cumulatedTime = 0;
    for (UninstallProgressStep s : steps)
    {
      Integer statusTime = hmTime.get(s);
      hmRatio.put(s, (100 * cumulatedTime) / totalTime);
      if (statusTime != null)
      {
        cumulatedTime += statusTime;
      }
    }
    hmRatio.put(UninstallProgressStep.FINISHED_SUCCESSFULLY, 100);
    hmRatio.put(UninstallProgressStep.FINISHED_WITH_ERROR, 100);
  }
  /**
   * Returns a localized message for a key value.  In  the properties file we
   * have something of type:
   * key=value
   *
   * @see ResourceProvider.getMsg(String key)
   * @param key the key in the properties file.
   * @return the value associated to the key in the properties file.
   * properties file.
   */
  private String getMsg(String key)
  {
    return getI18n().getMsg(key);
  }
  /**
   * Returns a localized message for a key value.  In  the properties file we
   * have something of type:
   * key=value
   *
   * For instance if we pass as key "mykey" and as arguments {"value1"} and
   * in the properties file we have:
   * mykey=value with argument {0}.
   *
   * This method will return "value with argument value1".
   * @see ResourceProvider.getMsg(String key, String[] args)
   * @param key the key in the properties file.
   * @param args the arguments to be passed to generate the resulting value.
   * @return the value associated to the key in the properties file.
   */
  private String getMsg(String key, String[] args)
  {
    return getI18n().getMsg(key, args);
  }
  /**
   * Returns a ResourceProvider instance.
   * @return a ResourceProvider instance.
   */
  private ResourceProvider getI18n()
  {
    return ResourceProvider.getInstance();
  }
  /**
   * Returns a localized message for a given properties key and throwable.
   * @param key the key of the message in the properties file.
   * @param t the throwable for which we want to get a message.
   * @return a localized message for a given properties key and throwable.
   */
  private String getThrowableMsg(String key, Throwable t)
  {
    return getThrowableMsg(key, null, t);
  }
  /**
   * Returns a localized message for a given properties key and throwable.
   * @param key the key of the message in the properties file.
   * @param args the arguments of the message in the properties file.
   * @param t the throwable for which we want to get a message.
   *
   * @return a localized message for a given properties key and throwable.
   */
  private String getThrowableMsg(String key, String[] args, Throwable t)
  {
    return Utils.getThrowableMsg(getI18n(), key, args, t);
  }
  /**
   * Returns the formatted representation of the text that is the summary of the
   * installation process (the one that goes in the UI next to the progress
   * bar).
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of an error for the given text.
   */
  private String getFormattedSummary(String text)
  {
    return formatter.getFormattedSummary(text);
  }
  /**
   * Returns the formatted representation of a success message for a given text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of an success message for the given
   * text.
   */
  private String getFormattedSuccess(String text)
  {
    return formatter.getFormattedSuccess(text);
  }
  /**
   * Returns the formatted representation of an warning for a given text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of an warning for the given text.
   */
  private String getFormattedWarning(String text)
  {
    return formatter.getFormattedWarning(text, true);
  }
  /**
   * Returns the formatted representation of an error for a given text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of an error for the given text.
   */
  private String getFormattedError(String text)
  {
    return formatter.getFormattedError(text, false);
  }
  /**
   * Returns the formatted representation of a log error message for a given
   * text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of a log error message for the given
   * text.
   */
  private String getFormattedLogError(String text)
  {
    return formatter.getFormattedLogError(text);
  }
  /**
   * Returns the formatted representation of a log message for a given text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of a log message for the given text.
   */
  private String getFormattedLog(String text)
  {
    return formatter.getFormattedLog(text);
  }
  /**
   * Returns the formatted representation of the 'Done' text string.
   * @return the formatted representation of the 'Done' text string.
   */
  private String getFormattedDone()
  {
    return formatter.getFormattedDone();
  }
  /**
   * Returns the formatted representation of the argument text to which we add
   * points.  For instance if we pass as argument 'Deleting file' the
   * return value will be 'Deleting file .....'.
   * @param text the String to which add points.
   * @return the formatted representation of the '.....' text string.
   */
  private String getFormattedWithPoints(String text)
  {
    return formatter.getFormattedWithPoints(text);
  }
  /**
   * Returns the formatted representation of an error message for a given
   * exception.
   * This method applies a margin if the applyMargin parameter is
   * <CODE>true</CODE>.
   * @param ex the exception.
   * @param applyMargin specifies whether we apply a margin or not to the
   * resulting formatted text.
   * @return the formatted representation of an error message for the given
   * exception.
   */
  private String getFormattedError(Exception ex, boolean applyMargin)
  {
    return formatter.getFormattedError(ex, applyMargin);
  }
  /**
   * Returns the line break formatted.
   * @return the line break formatted.
   */
  private String getLineBreak()
  {
    return formatter.getLineBreak();
  }
  /**
   * Returns the tab formatted.
   * @return the tab formatted.
   */
  private String getTab()
  {
    return formatter.getTab();
  }
  /**
   * Returns the task separator formatted.
   * @return the task separator formatted.
   */
  private String getTaskSeparator()
  {
    return formatter.getTaskSeparator();
  }
  /**
   * Returns the formatted representation of a progress message for a given
   * text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of a progress message for the given
   * text.
   */
  private String getFormattedProgress(String text)
  {
    return formatter.getFormattedProgress(text);
  }
  /**
   * Returns the current UninstallProgressStep of the installation process.
   * @return the current UninstallProgressStep of the installation process.
   */
  private UninstallProgressStep getStatus()
  {
    return status;
  }
  private UserUninstallData getUserData()
  {
    return userData;
  }
  /**
   * Actually performs the uninstall in this thread.  The thread is blocked.
   *
   */
  private void doUninstall()
  {
    try
    {
      boolean displaySeparator = false;
      if (getUserData().getStopServer())
      {
        status = UninstallProgressStep.STOPPING_SERVER;
        stopServer();
        displaySeparator = true;
      }
      Set<String> dbsToDelete = getUserData().getExternalDbsToRemove();
      if (dbsToDelete.size() > 0)
      {
        status = UninstallProgressStep.DELETING_EXTERNAL_DATABASE_FILES;
        if (displaySeparator)
        {
          notifyListeners(getTaskSeparator());
        }
        deleteExternalDatabaseFiles(dbsToDelete);
        displaySeparator = true;
      }
      Set<String> logsToDelete = getUserData().getExternalLogsToRemove();
      if (logsToDelete.size() > 0)
      {
        status = UninstallProgressStep.DELETING_EXTERNAL_LOG_FILES;
        if (displaySeparator)
        {
          notifyListeners(getTaskSeparator());
        }
        deleteExternalLogFiles(logsToDelete);
        displaySeparator = true;
      }
      boolean somethingToDelete = userData.getRemoveBackups() ||
      userData.getRemoveConfigurationAndSchema() ||
      userData.getRemoveDatabases() ||
      userData.getRemoveLDIFs() ||
      userData.getRemoveLibrariesAndTools() ||
      userData.getRemoveLogs();
      if (displaySeparator && somethingToDelete)
      {
        notifyListeners(getTaskSeparator());
      }
      if (somethingToDelete)
      {
        status = UninstallProgressStep.DELETING_INSTALLATION_FILES;
        deleteInstallationFiles(getRatio(status),
            getRatio(UninstallProgressStep.FINISHED_SUCCESSFULLY));
      }
      status = UninstallProgressStep.FINISHED_SUCCESSFULLY;
      if (Utils.isCli())
      {
        notifyListeners(getLineBreak()+getLineBreak()+getSummary(status));
      }
      else
      {
        notifyListeners(null);
      }
    } catch (UninstallException ex)
    {
      ue = ex;
      status = UninstallProgressStep.FINISHED_WITH_ERROR;
      String msg = getFormattedError(ex, true);
      notifyListeners(msg);
    }
    catch (Throwable t)
    {
      ue = new UninstallException(
          UninstallException.Type.BUG,
          getThrowableMsg("bug-msg", t), t);
      status = UninstallProgressStep.FINISHED_WITH_ERROR;
      String msg = getFormattedError(ue, true);
      notifyListeners(msg);
    }
  }
  /**
   * This method notifies the UninstallProgressUpdateListeners that there was an
   * update in the installation progress.
   * @param ratio the integer that specifies which percentage of
   * the whole installation has been completed.
   * @param currentPhaseSummary the localized summary message for the
   * current installation progress in formatted form.
   * @param newLogDetail the new log messages that we have for the
   * installation in formatted form.
   */
  private void notifyListeners(Integer ratio, String currentPhaseSummary,
      String newLogDetail)
  {
    UninstallProgressUpdateEvent ev =
        new UninstallProgressUpdateEvent(getStatus(), ratio,
            currentPhaseSummary, newLogDetail);
    for (UninstallProgressUpdateListener l : listeners)
    {
      l.progressUpdate(ev);
    }
  }
  /**
   * This method is called when a new log message has been received.  It will
   * notify the UninstallProgressUpdateListeners of this fact.
   * @param newLogDetail the new log detail.
   */
  private void notifyListeners(String newLogDetail)
  {
    Integer ratio = getRatio(getStatus());
    String currentPhaseSummary = getSummary(getStatus());
    notifyListeners(ratio, currentPhaseSummary, newLogDetail);
  }
  /**
   * Returns an integer that specifies which percentage of the whole
   * installation has been completed.
   * @param step the UninstallProgressStep for which we want to get the ratio.
   * @return an integer that specifies which percentage of the whole
   * uninstallation has been completed.
   */
  private Integer getRatio(UninstallProgressStep status)
  {
    return hmRatio.get(status);
  }
  /**
   * Returns an formatted representation of the summary for the specified
   * UninstallProgressStep.
   * @param step the UninstallProgressStep for which we want to get the summary.
   * @return an formatted representation of the summary for the specified
   * UninstallProgressStep.
   */
  private String getSummary(UninstallProgressStep status)
  {
    return hmSummary.get(status);
  }
  /**
   * This methods stops the server.
   * @throws UninstallException if something goes wrong.
   */
  private void stopServer() throws UninstallException
  {
    notifyListeners(getFormattedProgress(getMsg("progress-stopping")) +
        getLineBreak());
    ArrayList<String> argList = new ArrayList<String>();
    if (Utils.isWindows())
    {
      argList.add(Utils.getPath(getBinariesPath(), "stop-ds.bat"));
      argList.add("--bindDN");
      argList.add(userData.getDirectoryManagerDn());
      argList.add("--bindPassword");
      argList.add(userData.getDirectoryManagerPwd());
    } else
    {
      argList.add(Utils.getPath(getBinariesPath(), "stop-ds"));
    }
    String[] args = new String[argList.size()];
    argList.toArray(args);
    ProcessBuilder pb = new ProcessBuilder(args);
    Map<String, String> env = pb.environment();
    env.put("JAVA_HOME", System.getProperty("java.home"));
    /* Remove JAVA_BIN to be sure that we use the JVM running the uninstaller
     * JVM to stop the server.
     */
    env.remove("JAVA_BIN");
    try
    {
      Process process = pb.start();
      BufferedReader err =
          new BufferedReader(new InputStreamReader(process.getErrorStream()));
      BufferedReader out =
          new BufferedReader(new InputStreamReader(process.getInputStream()));
      /* Create these objects to resend the stop process output to the details
       * area.
       */
      new StopReader(err, true);
      new StopReader(out, false);
      int returnValue = process.waitFor();
      int clientSideError =
      org.opends.server.protocols.ldap.LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR;
      if ((returnValue == clientSideError) || (returnValue == 0))
      {
        if (Utils.isWindows())
        {
          /*
           * Sometimes the server keeps some locks on the files.
           * TODO: remove this code once stop-ds returns properly when server
           * is stopped.
           */
          int nTries = 10;
          boolean stopped = false;
          String testPath = Utils.getInstallPathFromClasspath()+File.separator+
          "locks"+File.separator+"server.lock";
          File testFile = new File(testPath);
          for (int i=0; i<nTries && !stopped; i++)
          {
            stopped = canWriteFile(testFile);
            if (!stopped)
            {
              String msg =
                getFormattedLog(getMsg("progress-server-waiting-to-stop"))+
              getLineBreak();
              notifyListeners(msg);
              try
              {
                Thread.sleep(5000);
              }
              catch (Exception ex)
              {
              }
            }
          }
          if (!stopped)
          {
            returnValue = -1;
          }
        }
      }
      if (returnValue == clientSideError)
      {
        String msg = getLineBreak() +
            getFormattedLog(getMsg("progress-server-already-stopped"))+
            getLineBreak();
        notifyListeners(msg);
      }
      else if (returnValue != 0)
      {
        String[] arg = {String.valueOf(returnValue)};
        String msg = getMsg("error-stopping-server-code", arg);
        /*
         * The return code is not the one expected, assume the server could
         * not be stopped.
         */
        throw new UninstallException(UninstallException.Type.STOP_ERROR, msg,
            null);
      }
      else
      {
        String msg = getFormattedLog(getMsg("progress-server-stopped"));
        notifyListeners(msg);
      }
    } catch (IOException ioe)
    {
      throw new UninstallException(UninstallException.Type.STOP_ERROR,
          getThrowableMsg("error-stopping-server", ioe), ioe);
    }
    catch (InterruptedException ie)
    {
      throw new UninstallException(UninstallException.Type.BUG,
          getThrowableMsg("error-stopping-server", ie), ie);
    }
  }
  /**
   * Deletes the external database files specified in the provided Set.
   * @param dbFiles the database directories to be deleted.
   * @throws UninstallException if something goes wrong.
   */
  private void deleteExternalDatabaseFiles(Set<String> dbFiles)
  throws UninstallException
  {
    notifyListeners(getFormattedProgress(
        getMsg("progress-deleting-external-db-files")) +
        getLineBreak());
    for (String path : dbFiles)
    {
      deleteRecursively(new File(path));
    }
  }
  /**
   * Deletes the external database files specified in the provided Set.
   * @param logFiles the log files to be deleted.
   * @throws UninstallException if something goes wrong.
   */
  private void deleteExternalLogFiles(Set<String> logFiles)
  throws UninstallException
  {
    notifyListeners(getFormattedProgress(
        getMsg("progress-deleting-external-log-files")) +
        getLineBreak());
    for (String path : logFiles)
    {
      deleteRecursively(new File(path));
    }
  }
  /**
   * Deletes the files under the installation path.
   * @throws UninstallException if something goes wrong.
   */
  private void deleteInstallationFiles(int minRatio, int maxRatio)
  throws UninstallException
  {
    notifyListeners(getFormattedProgress(
        getMsg("progress-deleting-installation-files")) +
        getLineBreak());
    File f = new File(Utils.getInstallPathFromClasspath());
    InstallationFilesToDeleteFilter filter =
      new InstallationFilesToDeleteFilter();
    File[] rootFiles = f.listFiles();
    if (rootFiles != null)
    {
      /* The following is done to have a moving progress bar when we delete
       * the installation files.
       */
      int totalRatio = 0;
      ArrayList<Integer> cumulatedRatio = new ArrayList<Integer>();
      for (int i=0; i<rootFiles.length; i++)
      {
       if (filter.accept(rootFiles[i]))
       {
         int relativeRatio;
         if (equalsOrDescendant(rootFiles[i], new File(getLibrariesPath())))
         {
           relativeRatio = 10;
         }
         else if (equalsOrDescendant(rootFiles[i], new File(getBinariesPath())))
         {
           relativeRatio = 5;
         }
         else if (equalsOrDescendant(rootFiles[i], new File(getConfigPath())))
         {
           relativeRatio = 5;
         }
         else if (equalsOrDescendant(rootFiles[i], new File(getBackupsPath())))
         {
           relativeRatio = 20;
         }
         else if (equalsOrDescendant(rootFiles[i], new File(getLDIFsPath())))
         {
           relativeRatio = 20;
         }
         else if (equalsOrDescendant(rootFiles[i],
             new File(getDatabasesPath())))
         {
           relativeRatio = 50;
         }
         else if (equalsOrDescendant(rootFiles[i], new File(getLogsPath())))
         {
           relativeRatio = 30;
         }
         else
         {
           relativeRatio = 2;
         }
         cumulatedRatio.add(totalRatio);
         totalRatio += relativeRatio;
       }
       else
       {
         cumulatedRatio.add(totalRatio);
       }
      }
      Iterator<Integer> it = cumulatedRatio.iterator();
      for (int i=0; i<rootFiles.length; i++)
      {
        int beforeRatio = minRatio +
        ((it.next() * (maxRatio - minRatio)) / totalRatio);
        hmRatio.put(UninstallProgressStep.DELETING_INSTALLATION_FILES,
            beforeRatio);
        deleteRecursively(rootFiles[i], filter);
      }
      hmRatio.put(UninstallProgressStep.DELETING_INSTALLATION_FILES, maxRatio);
    }
  }
  /**
   * Returns the path to the binaries.
   * @return the path to the binaries.
   */
  private String getBinariesPath()
  {
    return Utils.getPath(Utils.getInstallPathFromClasspath(),
        Utils.getBinariesRelativePath());
  }
  /**
   * Returns the path to the libraries.
   * @return the path to the libraries.
   */
  private String getLibrariesPath()
  {
    return Utils.getPath(Utils.getInstallPathFromClasspath(),
        Utils.getLibrariesRelativePath());
  }
  /**
   * Returns the path to the quicksetup jar file.
   * @return the path to the quicksetup jar file.
   */
  private String getQuicksetupJarPath()
  {
    return Utils.getPath(getLibrariesPath(), "quicksetup.jar");
  }
  /**
   * Returns the path to the open ds jar file.
   * @return the path to the open ds jar file.
   */
  private String getOpenDSJarPath()
  {
    return Utils.getPath(getLibrariesPath(), "OpenDS.jar");
  }
  /**
   * Returns the path to the backup files under the install path.
   * @return the path to the backup files under the install path.
   */
  private String getBackupsPath()
  {
    return Utils.getPath(Utils.getInstallPathFromClasspath(),
        Utils.getBackupsRelativePath());
  }
  /**
   * Returns the path to the LDIF files under the install path.
   * @return the path to the LDIF files under the install path.
   */
  private String getLDIFsPath()
  {
    return Utils.getPath(Utils.getInstallPathFromClasspath(),
        Utils.getLDIFsRelativePath());
  }
  /**
   * Returns the path to the config files under the install path.
   * @return the path to the config files under the install path.
   */
  private String getConfigPath()
  {
    return Utils.getPath(Utils.getInstallPathFromClasspath(),
        Utils.getConfigRelativePath());
  }
  /**
   * Returns the path to the log files under the install path.
   * @return the path to the log files under the install path.
   */
  private String getLogsPath()
  {
    return Utils.getPath(Utils.getInstallPathFromClasspath(),
        Utils.getLogsRelativePath());
  }
  /**
   * Returns the path to the database files under the install path.
   * @return the path to the database files under the install path.
   */
  private String getDatabasesPath()
  {
    return Utils.getPath(Utils.getInstallPathFromClasspath(),
        Utils.getDatabasesRelativePath());
  }
  /**
   * Deletes everything below the specified file.
   * @param file the path to be deleted.
   * @throws UninstallException if something goes wrong.
   */
  private void deleteRecursively(File file) throws UninstallException
  {
    deleteRecursively(file, null);
  }
  /**
   * Deletes everything below the specified file.
   * @param file the path to be deleted.
   * @param filter the filter of the files to know if the file can be deleted
   * directly or not.
   * @throws UninstallException if something goes wrong.
   */
  private void deleteRecursively(File file, FileFilter filter)
  throws UninstallException
  {
    if (file.exists())
    {
      if (file.isFile())
      {
        if (filter != null)
        {
          if (filter.accept(file))
          {
            delete(file);
          }
        }
        else
        {
          delete(file);
        }
      }
      else
      {
        File[] children = file.listFiles();
        if (children != null)
        {
          for (int i=0; i<children.length; i++)
          {
            deleteRecursively(children[i], filter);
          }
        }
        if (filter != null)
        {
          if (filter.accept(file))
          {
            delete(file);
          }
        }
        else
        {
          delete(file);
        }
      }
    }
    else
    {
      // Just tell that the file/directory does not exist.
      String[] arg = {file.toString()};
      notifyListeners(getFormattedWarning(
          getMsg("deleting-file-does-not-exist", arg)));
    }
  }
  /**
   * Deletes the specified file.
   * @param file the file to be deleted.
   * @throws UninstallException if something goes wrong.
   */
  private void delete(File file) throws UninstallException
  {
    String[] arg = {file.getAbsolutePath()};
    boolean isFile = file.isFile();
    if (isFile)
    {
      notifyListeners(getFormattedWithPoints(
          getMsg("progress-deleting-file", arg)));
    }
    else
    {
      notifyListeners(getFormattedWithPoints(
          getMsg("progress-deleting-directory", arg)));
    }
    boolean delete = false;
    /*
     * Sometimes the server keeps some locks on the files.
     * TODO: remove this code once stop-ds returns properly when server
     * is stopped.
     */
    int nTries = 5;
    for (int i=0; i<nTries && !delete; i++)
    {
      delete = file.delete();
      if (!delete)
      {
        try
        {
          Thread.sleep(1000);
        }
        catch (Exception ex)
        {
        }
      }
    }
    if (!delete)
    {
      String errMsg;
      if (isFile)
      {
        errMsg = getMsg("error-deleting-file", arg);
      }
      else
      {
        errMsg = getMsg("error-deleting-directory", arg);
      }
      throw new UninstallException(
          UninstallException.Type.FILE_SYSTEM_ERROR, errMsg, null);
    }
    notifyListeners(getFormattedDone()+getLineBreak());
  }
  private boolean equalsOrDescendant(File file, File directory)
  {
    return file.equals(directory) ||
    Utils.isDescendant(file.toString(), directory.toString());
  }
  /**
   * This class is used to read the standard error and standard output of the
   * Stop process.
   *
   * When a new log message is found notifies the
   * UninstallProgressUpdateListeners of it. If an error occurs it also
   * notifies the listeners.
   *
   */
  private class StopReader
  {
    private UninstallException ex;
    private boolean isFirstLine;
    /**
     * The protected constructor.
     * @param reader the BufferedReader of the stop process.
     * @param isError a boolean indicating whether the BufferedReader
     * corresponds to the standard error or to the standard output.
     */
    public StopReader(final BufferedReader reader,final boolean isError)
    {
      final String errorTag =
          isError ? "error-reading-erroroutput" : "error-reading-output";
      isFirstLine = true;
      Thread t = new Thread(new Runnable()
      {
        public void run()
        {
          try
          {
            String line = reader.readLine();
            while (line != null)
            {
              StringBuffer buf = new StringBuffer();
              if (!isFirstLine)
              {
                buf.append(formatter.getLineBreak());
              }
              if (isError)
              {
                buf.append(getFormattedLogError(line));
              } else
              {
                buf.append(getFormattedLog(line));
              }
              notifyListeners(buf.toString());
              isFirstLine = false;
              line = reader.readLine();
            }
          } catch (IOException ioe)
          {
            String errorMsg = getThrowableMsg(errorTag, ioe);
            ex =
                new UninstallException(UninstallException.Type.STOP_ERROR,
                    errorMsg, ioe);
          } catch (Throwable t)
          {
            String errorMsg = getThrowableMsg(errorTag, t);
            ex =
                new UninstallException(UninstallException.Type.STOP_ERROR,
                    errorMsg, t);
          }
        }
      });
      t.start();
    }
    /**
     * Returns the UninstallException that occurred reading the Stop error and
     * output or <CODE>null</CODE> if no exception occurred.
     * @return the exception that occurred reading or <CODE>null</CODE> if
     * no exception occurred.
     */
    public UninstallException getException()
    {
      return ex;
    }
  }
  private boolean canWriteFile(File file)
  {
    boolean canWriteFile = false;
    Writer output = null;
    try {
      //use buffering
      //FileWriter always assumes default encoding is OK!
      output = new BufferedWriter( new FileWriter(file) );
      output.write("test");
      output.close();
      canWriteFile = true;
    }
    catch (Throwable t)
    {
    }
    return canWriteFile;
  }
  /**
   * This class is used to get the files that are not binaries.  This is
   * required to know which are the files that can be deleted directly and which
   * not.
   */
  class InstallationFilesToDeleteFilter implements FileFilter
  {
    File quicksetupFile = new File(getQuicksetupJarPath());
    File openDSFile = new File(getOpenDSJarPath());
    File librariesFile = new File(getLibrariesPath());
    File installationPath = new File(Utils.getInstallPathFromClasspath());
    /**
     * {@inheritDoc}
     */
    public boolean accept(File file)
    {
      boolean[] uData = {
          userData.getRemoveLibrariesAndTools(),
          userData.getRemoveLibrariesAndTools(),
          userData.getRemoveDatabases(),
          userData.getRemoveLogs(),
          userData.getRemoveConfigurationAndSchema(),
          userData.getRemoveBackups(),
          userData.getRemoveLDIFs()
      };
      String[] parentFiles = {
          getLibrariesPath(),
          getBinariesPath(),
          getDatabasesPath(),
          getLogsPath(),
          getConfigPath(),
          getBackupsPath(),
          getLDIFsPath()
      };
     boolean accept =
          !installationPath.equals(file)
              && !librariesFile.equals(file)
              && !quicksetupFile.equals(file)
              && !openDSFile.equals(file);
     for (int i=0; i<uData.length && accept; i++)
     {
       accept &= uData[i] ||
       !equalsOrDescendant(file, new File(parentFiles[i]));
     }
     return accept;
    }
  }
}
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallData.java
New file
@@ -0,0 +1,271 @@
/*
 * 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 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.uninstaller;
import java.util.HashSet;
import java.util.Set;
/**
 * This class is used to provide a data model for the different parameters
 * that the user can provide in the uninstall wizard.
 *
 */
public class UserUninstallData
{
  private Set<String> externalDbsToRemove = new HashSet<String>();
  private Set<String> externalLogsToRemove = new HashSet<String>();
  private boolean removeDatabases;
  private boolean removeLogs;
  private boolean removeLibrariesAndTools;
  private boolean removeBackups;
  private boolean removeLDIFs;
  private boolean removeConfigurationAndSchema;
  private boolean stopServer;
  private String directoryManagerDn;
  private String directoryManagerPwd;
  /**
   * Sets the database directories located outside the installation which must
   * be removed.
   * @param dbPaths the directories of the database files.
   */
  public void setExternalDbsToRemove(Set<String> dbPaths)
  {
    externalDbsToRemove.clear();
    externalDbsToRemove.addAll(dbPaths);
  }
  /**
   * Returns the list of databases located outside the installation that must
   * be removed.
   * @return the list of databases located outside the installation that must
   * be removed.
   */
  public Set<String> getExternalDbsToRemove()
  {
    return new HashSet<String>(externalDbsToRemove);
  }
  /**
   * Sets the log files located outside the installation which must
   * be removed.
   * @param logFiles the log files.
   */
  public void setExternalLogsToRemove(Set<String> logFiles)
  {
    externalLogsToRemove.clear();
    externalLogsToRemove.addAll(logFiles);
  }
  /**
   * Returns the list of log files located outside the installation that must
   * be removed.
   * @return the list of log files located outside the installation that must
   * be removed.
   */
  public Set<String> getExternalLogsToRemove()
  {
    return new HashSet<String>(externalLogsToRemove);
  }
  /**
   * Returns whether the user wants to remove libraries and tools or not.
   * @return <CODE>true</CODE> if the user wants to remove the libraries and
   * tools and <CODE>false</CODE> otherwise.
   */
  public boolean getRemoveLibrariesAndTools()
  {
    return removeLibrariesAndTools;
  }
  /**
   * Sets whether to remove libraries and tools or not.
   * @param removeLibrariesAndTools remove libraries and tools or not.
   */
  public void setRemoveLibrariesAndTools(boolean removeLibrariesAndTools)
  {
    this.removeLibrariesAndTools = removeLibrariesAndTools;
  }
  /**
   * Sets whether to remove databases or not.
   * @param removeDatabases remove databases or not.
   */
  public void setRemoveDatabases(boolean removeDatabases)
  {
    this.removeDatabases = removeDatabases;
  }
  /**
   * Returns whether the user wants to remove databases or not.
   * @return <CODE>true</CODE> if the user wants to remove the databases and
   * <CODE>false</CODE> otherwise.
   */
  public boolean getRemoveDatabases()
  {
    return removeDatabases;
  }
  /**
   * Sets whether to remove backups or not.
   * @param removeBackups remove backups or not.
   */
  public void setRemoveBackups(boolean removeBackups)
  {
    this.removeBackups = removeBackups;
  }
  /**
   * Returns whether the user wants to remove backups or not.
   * @return <CODE>true</CODE> if the user wants to remove the backups and
   * <CODE>false</CODE> otherwise.
   */
  public boolean getRemoveBackups()
  {
    return removeBackups;
  }
  /**
   * Sets whether to remove log files or not.
   * @param removeLogs remove log files or not.
   */
  public void setRemoveLogs(boolean removeLogs)
  {
    this.removeLogs = removeLogs;
  }
  /**
   * Returns whether the user wants to remove logs or not.
   * @return <CODE>true</CODE> if the user wants to remove the log files and
   * <CODE>false</CODE> otherwise.
   */
  public boolean getRemoveLogs()
  {
    return removeLogs;
  }
  /**
   * Sets whether to remove LDIF files or not.
   * @param removeLDIFs remove LDIF files or not.
   */
  public void setRemoveLDIFs(boolean removeLDIFs)
  {
    this.removeLDIFs = removeLDIFs;
  }
  /**
   * Returns whether the user wants to remove LDIF files or not.
   * @return <CODE>true</CODE> if the user wants to remove the LDIF files and
   * <CODE>false</CODE> otherwise.
   */
  public boolean getRemoveLDIFs()
  {
    return removeLDIFs;
  }
  /**
   * Sets whether to remove configuration and schema files or not.
   * @param removeConfigurationAndSchema remove configuration and schema files
   * or not.
   */
  public void setRemoveConfigurationAndSchema(
      boolean removeConfigurationAndSchema)
  {
    this.removeConfigurationAndSchema = removeConfigurationAndSchema;
  }
  /**
   * Returns whether the user wants to remove configuration and schema files or
   * not.
   * @return <CODE>true</CODE> if the user wants to remove the configuration
   * and schema files and <CODE>false</CODE> otherwise.
   */
  public boolean getRemoveConfigurationAndSchema()
  {
    return removeConfigurationAndSchema;
  }
  /**
   * Sets whether to stop the server or not.
   * @param stopServer stop the server or not.
   */
  public void setStopServer(boolean stopServer)
  {
    this.stopServer = stopServer;
  }
  /**
   * Returns whether the user wants to stop the server or not.
   * @return <CODE>true</CODE> if the user wants to stop the server and <CODE>\
   * false</CODE> otherwise.
   */
  public boolean getStopServer()
  {
    return stopServer;
  }
  /**
   * Sets the DN to be used to shut down the server in Windows.
   * @param directoryManagerDn the DN to be used to shut down the server in
   * Windows.
   */
  public void setDirectoryManagerDn(String directoryManagerDn)
  {
    this.directoryManagerDn = directoryManagerDn;
  }
  /**
   * Returns the DN to be used to shut down the server in Windows.
   * @return the DN to be used to shut down the server in Windows.
   */
  public String getDirectoryManagerDn()
  {
    return directoryManagerDn;
  }
  /**
   * Sets the password to be used to shut down the server in Windows.
   * @param password the password to be used to shut down the server in Windows.
   */
  public void setDirectoryManagerPwd(String password)
  {
    this.directoryManagerPwd = password;
  }
  /**
   * Returns the password to be used to shut down the server in Windows.
   * @return the password to be used to shut down the server in Windows.
   */
  public String getDirectoryManagerPwd()
  {
    return directoryManagerPwd;
  }
}
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallDataException.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 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.uninstaller;
import org.opends.quicksetup.Step;
/**
 * This exception is used when there is an error with the data provided by
 * the user.  It will be thrown by the class that is in charge of validating
 * the user data (QuickSetup).
 *
 */
public class UserUninstallDataException extends Exception
{
  private static final long serialVersionUID = 3984412143277614443L;
  private Step step;
  private String localizedMessage;
  /**
   * Constructor for UserInstallDataException.
   * @param step the step in the wizard where the exception occurred.
   * @param localizedMessage the localized message describing the error.
   */
  public UserUninstallDataException(Step step, String localizedMessage)
  {
    super(localizedMessage);
    this.step = step;
    this.localizedMessage = localizedMessage;
  }
  /**
   * Returns the localized message describing the error that occurred.
   * @return the localized message describing the error that occurred.
   */
  public String getLocalizedMessage()
  {
    return localizedMessage;
  }
  /**
   * Returns the step of the wizard in which this exception occurred.
   * @return the step of the wizard in which this exception occurred.
   */
  public Step getStep()
  {
    return step;
  }
}
opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java
@@ -59,25 +59,38 @@
  private static String SPACE = "&nbsp;";
  /**
   * Returns the HTML representation of the text without providing any style.
   * @param text the source text from which we want to get the HTML
   * representation
   * @return the HTML representation for the given text.
   */
  public String getFormattedText(String text)
  {
    return getHtml(text);
  }
  /**
   * Returns the HTML representation of the text that is the summary of the
   * installation process (the one that goes in the UI next to the progress
   * bar).
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the HTML representation of an error for the given text.
   * @return the HTML representation of the summary for the given text.
   */
  public String getFormattedSummary(String text)
  {
    return UIFactory.applyFontToHtml(text, UIFactory.PROGRESS_FONT);
    return "<html>"+UIFactory.applyFontToHtml(text, UIFactory.PROGRESS_FONT);
  }
  /**
   * Returns the HTML representation of an error for a given text.
   * @param text the source text from which we want to get the HTML
   * representation
   * @param applyMargin specifies whether we apply a margin or not to the
   * resulting HTML.
   * @return the HTML representation of an error for the given text.
   */
  public String getFormattedError(String text)
  public String getFormattedError(String text, boolean applyMargin)
  {
    String html =
        UIFactory.getIconHtml(UIFactory.IconType.ERROR)
@@ -87,16 +100,24 @@
                UIFactory.PROGRESS_ERROR_FONT);
    String result = UIFactory.applyErrorBackgroundToHtml(html);
    if (applyMargin)
    {
      result =
          UIFactory.applyMargin(result,
              UIFactory.TOP_INSET_ERROR_MESSAGE, 0, 0, 0);
    }
    return result;
  }
  /**
   * Returns the HTML representation of an warning for a given text.
   * Returns the HTML representation of a warning for a given text.
   * @param text the source text from which we want to get the HTML
   * representation
   * @return the HTML representation of an warning for the given text.
   * @param applyMargin specifies whether we apply a margin or not to the
   * resulting HTML.
   * @return the HTML representation of a warning for the given text.
   */
  public String getFormattedWarning(String text)
  public String getFormattedWarning(String text, boolean applyMargin)
  {
    String html =
        UIFactory.getIconHtml(UIFactory.IconType.WARNING)
@@ -106,6 +127,12 @@
                UIFactory.PROGRESS_WARNING_FONT);
    String result = UIFactory.applyWarningBackgroundToHtml(html);
    if (applyMargin)
    {
      result =
          UIFactory.applyMargin(result,
              UIFactory.TOP_INSET_ERROR_MESSAGE, 0, 0, 0);
    }
    return result;
  }
@@ -113,7 +140,7 @@
   * Returns the HTML representation of a success message for a given text.
   * @param text the source text from which we want to get the HTML
   * representation
   * @return the HTML representation of an success message for the given text.
   * @return the HTML representation of a success message for the given text.
   */
  public String getFormattedSuccess(String text)
  {
@@ -278,6 +305,15 @@
  }
  /**
   * Returns the tab in HTML.
   * @return the tab in HTML.
   */
  public String getTab()
  {
    return SPACE+SPACE+SPACE+SPACE+SPACE;
  }
  /**
   * Returns the task separator in HTML.
   * @return the task separator in HTML.
   */
opends/src/quicksetup/org/opends/quicksetup/util/PlainTextProgressMessageFormatter.java
New file
@@ -0,0 +1,284 @@
/*
 * 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 Sun Microsystems, Inc.
 */
package org.opends.quicksetup.util;
import org.opends.quicksetup.i18n.ResourceProvider;
/**
 * This is an implementation of the ProgressMessageFormatter class that
 * provides format in plain text.
 *
 */
public class PlainTextProgressMessageFormatter
implements ProgressMessageFormatter
{
  private String doneText;
  /**
   * The line break in plain text.
   */
  private static String LINE_BREAK = System.getProperty("line.separator");
  /**
   * The space in plain text.
   */
  private static String SPACE = " ";
  /**
   * Returns the text representation of the text without providing any style.
   * @param text the source text from which we want to get the text
   * representation
   * @return the text representation for the given text.
   */
  public String getFormattedText(String text)
  {
    return text;
  }
  /**
   * Returns the plain text representation of the text that is the summary of
   * the installation process (the one that goes in the UI next to the progress
   * bar).
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the text representation of the summary for the given text.
   */
  public String getFormattedSummary(String text)
  {
    return text;
  }
  /**
   * Returns the plain text representation of an error for a given text.
   * @param text the source text from which we want to get the plain text
   * representation
   * @param applyMargin specifies whether we apply a margin or not to the
   * resulting formatted text.
   * @return the plain text representation of an error for the given text.
   */
  public String getFormattedError(String text, boolean applyMargin)
  {
    String result;
    if (applyMargin)
    {
      result = LINE_BREAK+text;
    } else
    {
      result = text;
    }
    return result;
  }
  /**
   * Returns the plain text representation of a warning for a given text.
   * @param text the source text from which we want to get the plain text
   * representation
   * @param applyMargin specifies whether we apply a margin or not to the
   * resulting formatted text.
   * @return the plain text representation of a warning for the given text.
   */
  public String getFormattedWarning(String text, boolean applyMargin)
  {
    String result;
    if (applyMargin)
    {
      result = LINE_BREAK+text;
    } else
    {
      result = text;
    }
    return result;
  }
  /**
   * Returns the plain text representation of a success message for a given
   * text.
   * @param text the source text from which we want to get the plain text
   * representation
   * @return the plain text representation of a success message for the given
   * text.
   */
  public String getFormattedSuccess(String text)
  {
    return text;
  }
  /**
   * Returns the plain text representation of a log error message for a given
   * text.
   * @param text the source text from which we want to get the plain text
   * representation
   * @return the plain text representation of a log error message for the given
   * text.
   */
  public String getFormattedLogError(String text)
  {
    return text;
  }
  /**
   * Returns the plain text representation of a log message for a given text.
   * @param text the source text from which we want to get the plain text
   * representation
   * @return the plain text representation of a log message for the given text.
   */
  public String getFormattedLog(String text)
  {
    return text;
  }
  /**
   * Returns the plain text representation of the 'Done' text string.
   * @return the plain text representation of the 'Done' text string.
   */
  public String getFormattedDone()
  {
    if (doneText == null)
    {
      doneText = getMsg("progress-done");
    }
    return doneText;
  }
  /**
   * Returns the plain text representation of the argument text to which we add
   * points.  For instance if we pass as argument 'Configuring Server' the
   * return value will be 'Configuring Server .....'.
   * @param text the String to which add points.
   * @return the plain text representation of the '.....' text string.
   */
  public String getFormattedWithPoints(String text)
  {
    return text + SPACE + getMsg("progress-points");
  }
  /**
   * Returns the formatted representation of a progress message for a given
   * text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of a progress message for the given
   * text.
   */
  public String getFormattedProgress(String text)
  {
    return text;
  }
  /**
   * Returns the plain text representation of an error message for a given
   * exception.
   * This method applies a margin if the applyMargin parameter is
   * <CODE>true</CODE>.
   * @param ex the exception.
   * @param applyMargin specifies whether we apply a margin or not to the
   * resulting plain text.
   * @return the plain text representation of an error message for the given
   * exception.
   */
  public String getFormattedError(Exception ex, boolean applyMargin)
  {
    String msg = ex.getMessage();
    if (msg == null)
    {
      msg = ex.toString();
    }
    String result;
    if (applyMargin)
    {
      result = LINE_BREAK+msg;
    } else
    {
      result = msg;
    }
    return result;
  }
  /**
   * Returns the line break in plain text.
   * @return the line break in plain text.
   */
  public String getLineBreak()
  {
    return LINE_BREAK;
  }
  /**
   * Returns the tab in plain text.
   * @return the tab in plain text.
   */
  public String getTab()
  {
    return "     ";
  }
  /**
   * Returns the task separator in plain text.
   * @return the task separator in plain text.
   */
  public String getTaskSeparator()
  {
    return
    "\n\n-----------------------------------------------------------------\n\n";
  }
  /**
   * {@inheritDoc}
   */
  public String getFormattedAfterUrlClick(String url, String lastText)
  {
    throw new IllegalStateException(
        "PlainTextProgressMessageFormatter.getFormattedAfterUrlClick must not "+
        "be called");
  }
  /**
   * Returns a localized message for a key value.  In  the properties file we
   * have something of type:
   * key=value
   *
   * @see ResourceProvider.getMsg(String key)
   * @param key the key in the properties file.
   * @return the value associated to the key in the properties file.
   * properties file.
   */
  private String getMsg(String key)
  {
    return getI18n().getMsg(key);
  }
  /**
   * Returns a ResourceProvider instance.
   * @return a ResourceProvider instance.
   */
  private ResourceProvider getI18n()
  {
    return ResourceProvider.getInstance();
  }
}
opends/src/quicksetup/org/opends/quicksetup/util/ProgressMessageFormatter.java
@@ -40,12 +40,21 @@
{
  /**
   * Returns the formatted representation of the text without providing any
   * style.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation for the given text.
   */
  public String getFormattedText(String text);
  /**
   * Returns the formatted representation of the text that is the summary of the
   * installation process (the one that goes in the UI next to the progress
   * bar).
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of an error for the given text.
   * @return the formatted representation of a summary for the given text.
   */
  public String getFormattedSummary(String text);
@@ -53,23 +62,27 @@
   * Returns the formatted representation of an error for a given text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @param applyMargin specifies whether we apply a margin or not to the
   * resulting formatted text.
   * @return the formatted representation of an error for the given text.
   */
  public String getFormattedError(String text);
  public String getFormattedError(String text, boolean applyMargin);
  /**
   * Returns the formatted representation of an warning for a given text.
   * Returns the formatted representation of a warning for a given text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of an warning for the given text.
   * @param applyMargin specifies whether we apply a margin or not to the
   * resulting formatted text.
   * @return the formatted representation of a warning for the given text.
   */
  public String getFormattedWarning(String text);
  public String getFormattedWarning(String text, boolean applyMargin);
  /**
   * Returns the formatted representation of a success message for a given text.
   * @param text the source text from which we want to get the formatted
   * representation
   * @return the formatted representation of an success message for the given
   * @return the formatted representation of a success message for the given
   * text.
   */
  public String getFormattedSuccess(String text);
@@ -137,6 +150,12 @@
  public String getLineBreak();
  /**
   * Returns the tab formatted.
   * @return the tab formatted.
   */
  public String getTab();
  /**
   * Returns the task separator formatted.
   * @return the task separator formatted.
   */
opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java
@@ -71,9 +71,9 @@
    try
    {
      WebBrowserLauncher.openURL(url);
    } catch (RuntimeException re)
    } catch (Throwable t)
    {
      throw new WebBrowserException(url, "Bug: run time exception", re);
      throw new WebBrowserException(url, "Bug: throwable", t);
    }
    return null;
  }
opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -42,14 +42,21 @@
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
import javax.naming.CommunicationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapName;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import org.opends.quicksetup.CurrentInstallStatus;
import org.opends.quicksetup.i18n.ResourceProvider;
import org.opends.quicksetup.installer.webstart.JnlpProperties;
@@ -62,6 +69,49 @@
{
  private static final int BUFFER_SIZE = 1024;
  private static final String[] OPEN_DS_JAR_RELATIVE_PATHS =
    { "lib/quicksetup.jar", "lib/OpenDS.jar", "lib/je.jar" };
  /**
   * The relative path where all the binaries (scripts) are.
   */
  private static final String BINARIES_PATH_RELATIVE = "bin";
  /**
   * The relative path where all the libraries (jar files) are.
   */
  private static final String LIBRARIES_PATH_RELATIVE = "lib";
  /**
   * The relative path where the database files are.
   */
  private static final String DATABASES_PATH_RELATIVE = "db";
  /**
   * The relative path where the log files are.
   */
  private static final String LOGS_PATH_RELATIVE = "logs";
  /**
   * The relative path where the LDIF files are.
   */
  private static final String LDIFS_PATH_RELATIVE = "ldif";
  /**
   * The relative path where the backup files are.
   */
  private static final String BACKUPS_PATH_RELATIVE = "bak";
  /**
   * The relative path where the config files are.
   */
  private static final String CONFIG_PATH_RELATIVE = "config";
  /**
   * The relative path to the Configuration LDIF file.
   */
  private static final String CONFIG_FILE_PATH_RELATIVE = "config/config.ldif";
  private Utils()
  {
  }
@@ -166,10 +216,71 @@
  public static String getPath(String parentPath, String relativePath)
  {
    File f = new File(new File(parentPath), relativePath);
    try
    {
      /*
       * Do a best effort to avoid having a relative representation (for
       * instance to avoid having ../../../).
       */
      File canonical = f.getCanonicalFile();
      f = canonical;
    }
    catch (IOException ioe)
    {
      /* This is a best effort to get the best possible representation of the
       * file: reporting the error is not necessary.
       */
    }
    return f.toString();
  }
  /**
   * Returns <CODE>true</CODE> if the first provided path is under the second
   * path in the file system.
   * @param descendant the descendant candidate path.
   * @param path the path.
   * @return <CODE>true</CODE> if the first provided path is under the second
   * path in the file system.
   */
  public static boolean isDescendant(String descendant, String path)
  {
    boolean isDescendant = false;
    File f1;
    File f2;
    try
    {
      f1 = (new File(path)).getCanonicalFile();
    }
    catch (IOException ioe)
    {
      f1 = new File(path);
    }
    try
    {
      f2 = (new File(descendant)).getCanonicalFile();
    }
    catch (IOException ioe)
    {
      f2 = new File(descendant);
    }
    f2 = f2.getParentFile();
    while ((f2 != null) && !isDescendant)
    {
      isDescendant = f1.equals(f2);
      if (!isDescendant)
      {
        f2 = f2.getParentFile();
      }
    }
    return isDescendant;
  }
  /**
   * Returns <CODE>true</CODE> if we are running under windows and
   * <CODE>false</CODE> otherwise.
   * @return <CODE>true</CODE> if we are running under windows and
@@ -446,6 +557,34 @@
  }
  /**
   * This is a helper method that gets a String representation of the elements
   * in the Collection. The String will display the different elements separated
   * by the separator String.
   *
   * @param col
   *          the collection containing the String.
   * @param separator
   *          the separator String to be used.
   * @return the String representation for the collection.
   */
  public static String getStringFromCollection(Collection<String> col,
      String separator)
  {
    String msg = null;
    for (String m : col)
    {
      if (msg == null)
      {
        msg = m;
      } else
      {
        msg += separator + m;
      }
    }
    return msg;
  }
  /**
   * Returns the default server location that will be proposed to the user
   * in the installation.
   * @return the default server location that will be proposed to the user
@@ -522,16 +661,16 @@
  }
  /**
   * Returns a localized message for a given properties key an exception.
   * Returns a localized message for a given properties key an throwable.
   * @param key the key of the message in the properties file.
   * @param i18n the ResourceProvider to be used.
   * @param args the arguments of the message in the properties file.
   * @param ex the exception for which we want to get a message.
   * @param t the throwable for which we want to get a message.
   *
   * @return a localized message for a given properties key an exception.
   * @return a localized message for a given properties key and throwable.
   */
  public static String getExceptionMsg(ResourceProvider i18n, String key,
      String[] args, Exception ex)
  public static String getThrowableMsg(ResourceProvider i18n, String key,
      String[] args, Throwable t)
  {
    String msg;
    if (args != null)
@@ -542,7 +681,7 @@
      msg = i18n.getMsg(key);
    }
    String detail = ex.toString();
    String detail = t.toString();
    if (detail != null)
    {
      String[] arg =
@@ -659,6 +798,17 @@
  }
  /**
   * Returns <CODE>true</CODE> if this is executed from command line and
   * <CODE>false</CODE> otherwise.
   * @return <CODE>true</CODE> if this is executed from command line and
   * <CODE>false</CODE> otherwise.
   */
  public static boolean isCli()
  {
    return "true".equals(System.getProperty("org.opends.quicksetup.cli"));
  }
  /**
   * Creates a clear LDAP connection and returns the corresponding LdapContext.
   * This methods uses the specified parameters to create a JNDI environment
   * hashtable and creates an InitialLdapContext instance.
@@ -725,19 +875,293 @@
        {
          pair[1] = ne;
        } catch (RuntimeException re)
        } catch (Throwable t)
        {
          pair[1] = re;
          pair[1] = t;
        }
      }
    });
    return getInitialLdapContext(t, pair, timeout);
  }
  /**
   * Method used to know if we can connect as administrator in a server with a
   * given password and dn.
   * @param ldapUrl the ldap URL of the server.
   * @param dn the dn to be used.
   * @param pwd the password to be used.
   * @return <CODE>true</CODE> if we can connect and read the configuration and
   * <CODE>false</CODE> otherwise.
   */
  public static boolean canConnectAsAdministrativeUser(String ldapUrl,
      String dn, String pwd)
  {
    boolean canConnectAsAdministrativeUser = false;
    try
    {
      InitialLdapContext ctx =
        Utils.createLdapContext(ldapUrl, dn, pwd, 3000, null);
      /*
       * Search for the config to check that it is the directory manager.
       */
      SearchControls searchControls = new SearchControls();
      searchControls.setCountLimit(1);
      searchControls.setSearchScope(
      SearchControls. OBJECT_SCOPE);
      searchControls.setReturningAttributes(
      new String[] {"dn"});
      ctx.search("cn=config", "objectclass=*", searchControls);
      canConnectAsAdministrativeUser = true;
    } catch (NamingException ne)
    {
      // Nothing to do.
    } catch (Throwable t)
    {
      throw new IllegalStateException("Unexpected throwable.", t);
    }
    return canConnectAsAdministrativeUser;
  }
  /**
   * Returns the path of the installation of the directory server.  Note that
   * this method assumes that this code is being run locally.
   * @return the path of the installation of the directory server.
   */
  public static String getInstallPathFromClasspath()
  {
    /* Get the install path from the Class Path */
    String sep = System.getProperty("path.separator");
    String[] classPaths = System.getProperty("java.class.path").split(sep);
    String path = null;
    for (int i = 0; i < classPaths.length && (path == null); i++)
    {
      for (int j = 0; j < OPEN_DS_JAR_RELATIVE_PATHS.length &&
      (path == null); j++)
      {
        String normPath = classPaths[i].replace(File.separatorChar, '/');
        if (normPath.endsWith(OPEN_DS_JAR_RELATIVE_PATHS[j]))
        {
          path = classPaths[i];
        }
      }
    }
    File f = new File(path).getAbsoluteFile();
    File binariesDir = f.getParentFile();
    return binariesDir.getParent();
  }
  /**
   * Returns the path to the configuration file of the directory server.  Note
   * that this method assumes that this code is being run locally.
   * @return the path of the configuration file of the directory server.
   */
  public static String getConfigFileFromClasspath()
  {
    return getPath(getInstallPathFromClasspath(), CONFIG_FILE_PATH_RELATIVE);
  }
  /**
   * Returns the list of jar files that might be used to execute the code of
   * the installation and uninstallation.
   * @return the list of jar files that might be used to execute the code of
   * the installation and uninstallation.
   */
  public static String[] getOpenDSJarPaths()
  {
    return OPEN_DS_JAR_RELATIVE_PATHS;
  }
  /**
   * Returns the relative path of the directory containing the binaries of the
   * Open DS installation.  The path is relative to the installation path.
   * @return the relative path of the directory containing the binaries of the
   * Open DS installation.
   */
  public static String getBinariesRelativePath()
  {
    return BINARIES_PATH_RELATIVE;
  }
  /**
   * Returns the relative path of the directory containing the libraries of the
   * Open DS installation.  The path is relative to the installation path.
   * @return the relative path of the directory containing the libraries of the
   * Open DS installation.
   */
  public static String getLibrariesRelativePath()
  {
    return LIBRARIES_PATH_RELATIVE;
  }
  /**
   * Returns the relative path of the directory containing the databases of the
   * Open DS installation.  The path is relative to the installation path.
   * @return the relative path of the directory containing the databases of the
   * Open DS installation.
   */
  public static String getDatabasesRelativePath()
  {
    return DATABASES_PATH_RELATIVE;
  }
  /**
   * Returns the relative path of the directory containing the logs of the
   * Open DS installation.  The path is relative to the installation path.
   * @return the relative path of the directory containing the logs of the
   * Open DS installation.
   */
  public static String getLogsRelativePath()
  {
    return LOGS_PATH_RELATIVE;
  }
  /**
   * Returns the relative path of the directory containing the LDIF files of the
   * Open DS installation.  The path is relative to the installation path.
   * @return the relative path of the directory containing the LDIF files of the
   * Open DS installation.
   */
  public static String getLDIFsRelativePath()
  {
    return LDIFS_PATH_RELATIVE;
  }
  /**
   * Returns the relative path of the directory containing the backup files of
   * the Open DS installation.  The path is relative to the installation path.
   * @return the relative path of the directory containing the backup files of
   * the Open DS installation.
   */
  public static String getBackupsRelativePath()
  {
    return BACKUPS_PATH_RELATIVE;
  }
  /**
   * Returns the relative path of the directory containing the config files of
   * the Open DS installation.  The path is relative to the installation path.
   * @return the relative path of the directory containing the config files of
   * the Open DS installation.
   */
  public static String getConfigRelativePath()
  {
    return CONFIG_PATH_RELATIVE;
  }
  /**
   * Displays a confirmation message dialog.
  *
  * @param parent
   *          the parent frame of the confirmation dialog.
   * @param msg
  *          the confirmation message.
  * @param title
  *          the title of the dialog.
  * @return <CODE>true</CODE> if the user confirms the message, or
  * <CODE>false</CODE> if not.
  */
 public static boolean displayConfirmation(JFrame parent, String msg,
     String title)
 {
   return JOptionPane.YES_OPTION == JOptionPane.showOptionDialog(
       parent, msg, title, JOptionPane.YES_NO_OPTION,
       JOptionPane.QUESTION_MESSAGE, null, // don't use a custom
       // Icon
       null, // the titles of buttons
       null); // default button title
 }
  /**
   * Displays an error message dialog.
   *
   * @param parent
   *          the parent frame of the error dialog.
   * @param msg
   *          the error message.
   * @param title
   *          the title for the dialog.
   */
  public static void displayError(JFrame parent, String msg, String title)
  {
    JOptionPane.showMessageDialog(parent, msg, title,
        JOptionPane.ERROR_MESSAGE);
  }
  /**
   * Displays an information message dialog.
   *
   * @param parent
   *          the parent frame of the information dialog.
   * @param msg
   *          the error message.
   * @param title
   *          the title for the dialog.
   */
  public static void displayInformationMessage(JFrame parent, String msg,
      String title)
  {
    JOptionPane.showMessageDialog(parent, msg, title,
        JOptionPane.INFORMATION_MESSAGE);
  }
  /**
   * Returns a Set of relative paths containing the db paths outside the
   * installation.
   * @param installStatus the Current Install Status object.
   * @return a Set of relative paths containing the db paths outside the
   * installation.
   */
  public static Set<String> getOutsideDbs(CurrentInstallStatus installStatus)
  {
    String installPath = getInstallPathFromClasspath();
    Set<String> dbs = installStatus.getDatabasePaths();
    Set<String> outsideDbs = new HashSet<String>();
    for (String relativePath : dbs)
    {
      /* The db paths are relative */
      String fullDbPath = getPath(installPath, relativePath);
      if (!isDescendant(fullDbPath, installPath))
      {
        outsideDbs.add(fullDbPath);
      }
    }
    return outsideDbs;
  }
  /**
   * Returns a Set of relative paths containing the log paths outside the
   * installation.
   * @param installStatus the Current Install Status object.
   * @return a Set of relative paths containing the log paths outside the
   * installation.
   */
  public static Set<String> getOutsideLogs(CurrentInstallStatus installStatus)
  {
    String installPath = getInstallPathFromClasspath();
    Set<String> logs = installStatus.getLogPaths();
    Set<String> outsideLogs = new HashSet<String>();
    for (String relativePath : logs)
    {
      /* The db paths are relative */
      String fullDbPath = getPath(installPath, relativePath);
      if (!isDescendant(fullDbPath, installPath))
      {
        outsideLogs.add(fullDbPath);
      }
    }
    return outsideLogs;
  }
  /**
   * This is just a commodity method used to try to get an InitialLdapContext.
   * @param t the Thread to be used to create the InitialLdapContext.
   * @param pair an Object[] array that contains the InitialLdapContext and the
   * Exception if any occurred.
   * Throwable if any occurred.
   * @param timeout the timeout.  If we do not get to create the connection
   * before the timeout a CommunicationException will be thrown.
   * @return the created InitialLdapContext
@@ -802,6 +1226,11 @@
      } else if (pair[1] instanceof RuntimeException)
      {
        throw (RuntimeException) pair[1];
      } else if (pair[1] instanceof Throwable)
      {
        throw new IllegalStateException("Unexpected throwable occurred",
            (Throwable) pair[1]);
      }
    }
    return (InitialLdapContext) pair[0];
opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java
@@ -44,7 +44,7 @@
   * @param msg the error message.
   * @param rootCause the root cause.
   */
  public WebBrowserException(String url, String msg, Exception rootCause)
  public WebBrowserException(String url, String msg, Throwable rootCause)
  {
    super(msg, rootCause);
    this.url = url;