From f10eeefc3ab93b6173fd4edbf196ca863344b4dc Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Mon, 11 Dec 2006 15:34:39 +0000
Subject: [PATCH] The following modifications include the comments from Neil and Brian (thanks to both for your help):

---
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java               |   25 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ProgressMessageFormatter.java           |   31 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java                     |  308 +-
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java                  |   30 
 opendj-sdk/opends/resource/uninstall.bat                                                            |   63 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java   |   14 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java      |   66 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java                            |   54 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java                   |    4 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java       |    2 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java                     |   32 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/InstallWelcomePanel.java                  |   30 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java                              |  447 +++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java                         |   75 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java                 | 1211 ++++++++++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/PlainTextProgressMessageFormatter.java  |  284 ++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java                     |   54 
 opendj-sdk/opends/resource/setup.bat                                                                |   10 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateListener.java     |    8 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java       |   12 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java       |   50 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateEvent.java        |   10 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateEvent.java      |   22 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java              |    2 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java |  513 ++++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallException.java          |   92 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties               |  312 ++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateListener.java   |   12 
 opendj-sdk/opends/resource/setup                                                                    |   19 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallLauncher.java               |   10 
 opendj-sdk/opends/build.xml                                                                         |   13 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java                | 1108 +++++++++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java           |  250 ++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java                              |  511 +++-
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java                              |    6 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java                     |   34 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java                |    2 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java                    |  226 +
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java                  |   34 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java                          |    4 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallDataException.java  |   76 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java                |  266 ++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java                 |    2 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallData.java           |  271 ++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java    |   49 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java                        |   44 
 opendj-sdk/opends/resource/uninstall                                                                |  123 +
 47 files changed, 6,216 insertions(+), 605 deletions(-)

diff --git a/opendj-sdk/opends/build.xml b/opendj-sdk/opends/build.xml
index 10c2524..2cc0618 100644
--- a/opendj-sdk/opends/build.xml
+++ b/opendj-sdk/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>
diff --git a/opendj-sdk/opends/resource/setup b/opendj-sdk/opends/resource/setup
index cfc8f56..bb4e26a 100755
--- a/opendj-sdk/opends/resource/setup
+++ b/opendj-sdk/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 "${@}"
 
diff --git a/opendj-sdk/opends/resource/setup.bat b/opendj-sdk/opends/resource/setup.bat
index 7806468..825263e 100644
--- a/opendj-sdk/opends/resource/setup.bat
+++ b/opendj-sdk/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
diff --git a/opendj-sdk/opends/resource/uninstall b/opendj-sdk/opends/resource/uninstall
new file mode 100644
index 0000000..687f1b7
--- /dev/null
+++ b/opendj-sdk/opends/resource/uninstall
@@ -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 "${@}"
diff --git a/opendj-sdk/opends/resource/uninstall.bat b/opendj-sdk/opends/resource/uninstall.bat
new file mode 100644
index 0000000..5a11a3e
--- /dev/null
+++ b/opendj-sdk/opends/resource/uninstall.bat
@@ -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
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
index 3ee5135..11132fb 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
@@ -52,5 +52,9 @@
   /**
    * The Finish button.
    */
-  FINISH
+  FINISH,
+  /**
+   * The Cancel button.
+   */
+  CANCEL
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
index f13b349..9fb8074 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
+++ b/opendj-sdk/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());
+    }
+  }
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
index cea1060..7eedf95 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
+++ b/opendj-sdk/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;
   }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateEvent.java
similarity index 91%
rename from opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
rename to opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateEvent.java
index f3c0e69..8d594ff 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateEvent.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;
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateListener.java
similarity index 84%
rename from opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
rename to opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateListener.java
index 5556a63..8467540 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/InstallProgressUpdateListener.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);
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateEvent.java
similarity index 83%
copy from opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
copy to opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateEvent.java
index f3c0e69..34bdc8b 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateEvent.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;
   }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateListener.java
similarity index 76%
copy from opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
copy to opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateListener.java
index 5556a63..4202e2e 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/event/UninstallProgressUpdateListener.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);
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
index 0d90ee8..873b535 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
+++ b/opendj-sdk/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);
 
       }
     }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java
index c3d9dcf..bdb0904 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java
+++ b/opendj-sdk/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
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java
index 6642d4e..67e61df 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java
+++ b/opendj-sdk/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;
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallLauncher.java
similarity index 96%
rename from opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java
rename to opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallLauncher.java
index dbc2d44..8712cb1 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallLauncher.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);
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index a5e5142..b01ccce 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opendj-sdk/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) {}
   }
 
   /**
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
index bd333a9..7b9464f 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
+++ b/opendj-sdk/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;
   }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
index e6bbdf7..e9ac9fd 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
+++ b/opendj-sdk/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();
   }
 
   /**
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java
index e8fa8d4..c5987cc 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java
+++ b/opendj-sdk/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.
  *
  */
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java
index 7f50479..1e13c89 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java
+++ b/opendj-sdk/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)
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
index 061f795..8efd4f1 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
+++ b/opendj-sdk/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);
-  }
-}
+}
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
index a465cb9..fe13de9 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
+++ b/opendj-sdk/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
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java
index d8ae55f..dd69390 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java
+++ b/opendj-sdk/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);
   }
 
   /**
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java
index 1085350..80a868d 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java
+++ b/opendj-sdk/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;
+  }
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
index 906f4c3..9155a1e 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
+++ b/opendj-sdk/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.
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java
new file mode 100644
index 0000000..054cf81
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java
@@ -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();
+    }
+  }
+}
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/InstallWelcomePanel.java
similarity index 66%
rename from opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java
rename to opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/InstallWelcomePanel.java
index b672d19..f7b8cec 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/InstallWelcomePanel.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);
   }
 
   /**
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
index 71ece54..3bccf01 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
+++ b/opendj-sdk/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;
-  }
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
index f166232..13bd825 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
+++ b/opendj-sdk/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;
   }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
index 7a046c8..0fb0107 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
+++ b/opendj-sdk/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;
 
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
index 0e22ab4..a6c03c6 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
+++ b/opendj-sdk/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);
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java
index 10d71f9..684a49d 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java
+++ b/opendj-sdk/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;
   }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
index 517c871..f31edcc 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
+++ b/opendj-sdk/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;
+  }
 }
 
 /**
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java
new file mode 100644
index 0000000..d83ae91
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java
@@ -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();
+  }
+}
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallException.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallException.java
new file mode 100644
index 0000000..88ca9e1
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallException.java
@@ -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();
+  }
+}
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java
new file mode 100644
index 0000000..73c2bac
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java
@@ -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)
+    {
+    }
+  }
+}
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java
index 3ef8ae4..83624fd 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java
+++ b/opendj-sdk/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,
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java
index b21091f..01e5a71 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java
+++ b/opendj-sdk/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;
+    }
   }
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallData.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallData.java
new file mode 100644
index 0000000..a6816b8
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallData.java
@@ -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;
+  }
+}
+
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallDataException.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallDataException.java
new file mode 100644
index 0000000..3cfbbae
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UserUninstallDataException.java
@@ -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;
+  }
+}
+
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java
index 23799fc..5f05d21 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java
+++ b/opendj-sdk/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.
    */
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/PlainTextProgressMessageFormatter.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/PlainTextProgressMessageFormatter.java
new file mode 100644
index 0000000..fdeb097
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/PlainTextProgressMessageFormatter.java
@@ -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();
+  }
+}
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ProgressMessageFormatter.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ProgressMessageFormatter.java
index 6dbcf62..1c90519 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/ProgressMessageFormatter.java
+++ b/opendj-sdk/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.
    */
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java
index fa9ed26..ee35db4 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java
+++ b/opendj-sdk/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;
   }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
index 99a67aa..12b16be 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
+++ b/opendj-sdk/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];
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java
index c44614c..061008e 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java
+++ b/opendj-sdk/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;

--
Gitblit v1.10.0