From 8a1a1478c28acdc7376fc7e57d76cca61b901441 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Fri, 17 Nov 2006 17:40:50 +0000
Subject: [PATCH] The modifications basically do the following:

---
 opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java                          |  358 +
 opends/ext/build-tools.jar                                                               |    0 
 opends/build-tools/src/javax/jnlp/UnavailableServiceException.java                       |   51 
 opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif                     |    0 
 opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java    |  647 ++
 opends/build-tools/src/javax/jnlp/ServiceManager.java                                    |   54 
 opends/src/quicksetup/org/opends/quicksetup/util/ExtensionFileFilter.java                |   86 
 opends/src/quicksetup/org/opends/quicksetup/images/error.gif                             |    0 
 opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallDataException.java      |   75 
 opends/src/server/org/opends/server/tools/ImportLDIF.java                                |   36 
 opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java               |  153 
 opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java   |  316 +
 opends/src/quicksetup/org/opends/quicksetup/images/currentstep.gif                       |    0 
 opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java                  |  498 ++
 opends/build-tools/src/javax/jnlp/DownloadServiceListener.java                           |   57 
 opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java                     |  682 ++
 opends/src/quicksetup/org/opends/quicksetup/installer/DataOptions.java                   |  142 
 opends/src/quicksetup/org/opends/quicksetup/ui/StepsPanel.java                           |  213 
 opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java                  |  439 +
 opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java       |   57 
 opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java                 |   48 
 opends/src/quicksetup/org/opends/quicksetup/images/information.gif                       |    0 
 opends/resource/setup.bat                                                                |    2 
 opends/src/quicksetup/org/opends/quicksetup/util/BackgroundThreadTask.java               |   71 
 opends/src/quicksetup/org/opends/quicksetup/images/currentstep.png                       |    0 
 opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java                            |  281 +
 opends/src/quicksetup/org/opends/quicksetup/util/BackgroundTask.java                     |   82 
 opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java            |   44 
 opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties               |  365 +
 opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java                     |  185 
 opends/src/quicksetup/org/opends/quicksetup/images/opendsminimizedmac.png                |    0 
 opends/build-tools/src/org/opends/build/tools/PrepTestNG.java                            |   26 
 opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressDescriptor.java     |  108 
 opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java      |  308 +
 opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java                |   75 
 opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java           |   78 
 opends/src/quicksetup/org/opends/quicksetup/event/ButtonActionListener.java              |   43 
 opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java                         |  317 +
 opends/src/quicksetup/org/opends/quicksetup/Step.java                                    |   62 
 opends/build-tools/src/javax/jnlp/DownloadService.java                                   |   55 
 opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java                     | 1429 +++++
 opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressDescriptor.java |  108 
 opends/resource/setup.sh                                                                 |    5 
 opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java                   |  202 
 opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java       |   61 
 opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java              |  107 
 opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java                    |  299 +
 opends/src/quicksetup/org/opends/quicksetup/images/warning.gif                           |    0 
 opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupPanel.java                      |  126 
 opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java                            | 1356 +++++
 opends/src/quicksetup/org/opends/quicksetup/event/ButtonEvent.java                       |   64 
 opends/src/quicksetup/org/opends/quicksetup/images/opendssplash.png                      |    0 
 opends/src/quicksetup/org/opends/quicksetup/ButtonName.java                              |   56 
 opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java               |  107 
 opends/src/quicksetup/org/opends/quicksetup/installer/LabelFieldDescriptor.java          |  151 
 opends/src/quicksetup/org/opends/quicksetup/ui/DataOptionsPanel.java                     |  619 ++
 opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java                        |  211 
 opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallData.java               |  166 
 opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java                          |  107 
 opends/src/quicksetup/org/opends/quicksetup/images/opendsbackground.png                  |    0 
 opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java                     |   82 
 opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java                 |  160 
 opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java                         |   80 
 opends/build.xml                                                                         |   89 
 opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java                           |  257 +
 opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java                |  210 
 opends/src/quicksetup/org/opends/quicksetup/util/Utils.java                              |  809 +++
 opends/src/quicksetup/org/opends/quicksetup/event/BrowseActionListener.java              |  177 
 opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java                           |  186 
 opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java                |   61 
 opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java                              | 1164 ++++
 opends/src/quicksetup/org/opends/quicksetup/event/MinimumSizeComponentListener.java      |  131 
 opends/src/quicksetup/org/opends/quicksetup/images/opendsminimized.gif                   |    0 
 opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserLauncher.java                 |  109 
 74 files changed, 14,647 insertions(+), 56 deletions(-)

diff --git a/opends/build-tools/src/javax/jnlp/DownloadService.java b/opends/build-tools/src/javax/jnlp/DownloadService.java
new file mode 100644
index 0000000..d142ee6
--- /dev/null
+++ b/opends/build-tools/src/javax/jnlp/DownloadService.java
@@ -0,0 +1,55 @@
+/*
+ * 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 javax.jnlp;
+
+/**
+ * This is just an empty implementation of DownloadService.  It does define
+ * only the methods of the JNLP API used in the class 
+ * org.opends.quicksetup.webstart.WebstartDownloader.
+ * 
+ * We have chosen to do this because we we require the JNLP API to be compiled
+ * but the location of the javaws.jar depends on the java distribution, so
+ * instead of trying to figure out where javaws.jar is on the java distribution
+ * that is being used to compile the source, we just add these classes to the
+ * build-tools.jar file that will be used to compile que QuickSetup.
+ * 
+ * It must be noted that the class 
+ * org.opends.quicksetup.webstart.WebstartDownloader will be only executed in
+ * the context of a Java Web Start application and that in this case the
+ * javaws.jar will be provided by the Java Web Start Runtime environment.  So
+ * we are not providing the javaws-stub.jar during runtime: it is used only
+ * for compilation.
+ *
+ */
+public interface DownloadService {
+	public boolean isResourceCached(java.net.URL url, String version);
+	public void removeResource(java.net.URL url, String version)
+	 throws java.io.IOException;
+	public void loadResource(java.net.URL ref, String version,
+			DownloadServiceListener listener) throws java.io.IOException;
+}
diff --git a/opends/build-tools/src/javax/jnlp/DownloadServiceListener.java b/opends/build-tools/src/javax/jnlp/DownloadServiceListener.java
new file mode 100644
index 0000000..aed1c12
--- /dev/null
+++ b/opends/build-tools/src/javax/jnlp/DownloadServiceListener.java
@@ -0,0 +1,57 @@
+/*
+ * 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 javax.jnlp;
+
+/**
+ * This is the interface definition of DownloadServiceListener.
+ * 
+ * We have chosen to do this because we we require the JNLP API to be compiled
+ * but the location of the javaws.jar depends on the java distribution, so
+ * instead of trying to figure out where javaws.jar is on the java distribution
+ * that is being used to compile the source, we just add these classes to the
+ * build-tools.jar file that will be used to compile que QuickSetup.
+ * 
+ * It must be noted that the class 
+ * org.opends.quicksetup.webstart.WebstartDownloader will be only executed in
+ * the context of a Java Web Start application and that in this case the
+ * javaws.jar will be provided by the Java Web Start Runtime environment.  So
+ * we are not providing the javaws-stub.jar during runtime: it is used only
+ * for compilation.
+ *
+ */
+import java.net.URL;
+
+public interface DownloadServiceListener {
+	public void downloadFailed(URL url, String version);
+	public void progress(URL url, String version, long readSoFar, long total,
+		      int overallPercent);
+	public void upgradingArchive(URL url, String version, int patchPercent,
+		      int overallPercent);
+	public void validating(URL url, String version, long entry, long total,
+		      int overallPercent);
+}
diff --git a/opends/build-tools/src/javax/jnlp/ServiceManager.java b/opends/build-tools/src/javax/jnlp/ServiceManager.java
new file mode 100644
index 0000000..0d57b6d
--- /dev/null
+++ b/opends/build-tools/src/javax/jnlp/ServiceManager.java
@@ -0,0 +1,54 @@
+/*
+ * 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 javax.jnlp;
+
+/**
+ * This is just an empty implementation of ServiceManager.  It does define
+ * only the methods of the JNLP API used in the class 
+ * org.opends.quicksetup.webstart.WebstartDownloader.
+ * 
+ * We have chosen to do this because we we require the JNLP API to be compiled
+ * but the location of the javaws.jar depends on the java distribution, so
+ * instead of trying to figure out where javaws.jar is on the java distribution
+ * that is being used to compile the source, we just add these classes to the
+ * build-tools.jar file that will be used to compile que QuickSetup.
+ * 
+ * It must be noted that the class 
+ * org.opends.quicksetup.webstart.WebstartDownloader will be only executed in
+ * the context of a Java Web Start application and that in this case the
+ * javaws.jar will be provided by the Java Web Start Runtime environment.  So
+ * we are not providing the javaws-stub.jar during runtime: it is used only
+ * for compilation.
+ *
+ */
+public class ServiceManager {
+	public static Object lookup(String name) throws UnavailableServiceException
+	{
+		return null;
+	}
+}
diff --git a/opends/build-tools/src/javax/jnlp/UnavailableServiceException.java b/opends/build-tools/src/javax/jnlp/UnavailableServiceException.java
new file mode 100644
index 0000000..54f6e10
--- /dev/null
+++ b/opends/build-tools/src/javax/jnlp/UnavailableServiceException.java
@@ -0,0 +1,51 @@
+/*
+ * 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 javax.jnlp;
+
+/**
+ * This is just an empty implementation of UnavailableServiceException.  This
+ * class is used in the class 
+ * org.opends.quicksetup.webstart.WebstartDownloader.
+ * 
+ * We have chosen to do this because we we require the JNLP API to be compiled
+ * but the location of the javaws.jar depends on the java distribution, so
+ * instead of trying to figure out where javaws.jar is on the java distribution
+ * that is being used to compile the source, we just add these classes to the
+ * build-tools.jar file that will be used to compile que QuickSetup.
+ * 
+ * It must be noted that the class 
+ * org.opends.quicksetup.webstart.WebstartDownloader will be only executed in
+ * the context of a Java Web Start application and that in this case the
+ * javaws.jar will be provided by the Java Web Start Runtime environment.  So
+ * we are not providing the javaws-stub.jar during runtime: it is used only
+ * for compilation.
+ *
+ */
+public class UnavailableServiceException extends Exception {
+  private static final long serialVersionUID = 286996071734385910L;
+}
diff --git a/opends/build-tools/src/org/opends/build/tools/PrepTestNG.java b/opends/build-tools/src/org/opends/build/tools/PrepTestNG.java
index bcaed48..27d43ed 100644
--- a/opends/build-tools/src/org/opends/build/tools/PrepTestNG.java
+++ b/opends/build-tools/src/org/opends/build/tools/PrepTestNG.java
@@ -24,32 +24,6 @@
  *
  *      Portions Copyright 2006 Sun Microsystems, Inc.
  */
-/*
- * 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.build.tools;
 
diff --git a/opends/build.xml b/opends/build.xml
index 889b0ff..4ba6399 100644
--- a/opends/build.xml
+++ b/opends/build.xml
@@ -76,6 +76,10 @@
   <property name="dsml.gen.dir"     location="${build.dir}/dsml/gen"     />
   <property name="dsml.classes.dir" location="${build.dir}/dsml/classes" />
 
+	<!-- Properties for use with the Quick Setup.                      -->
+	<property name="quicksetup.src.dir"         location="src/quicksetup"             />
+	<property name="quicksetup.classes.dir"    location="${build.dir}/quicksetup/classes"    />
+	
   <!-- Properties for code coverage testing.                            -->
   <property name="coverage.dir"         location="build/coverage"            />
   <property name="coverage.report.dir"  
@@ -226,12 +230,18 @@
 
     <taskdef resource="checkstyletask.properties"
          classpath="${checkstyle.dir}/checkstyle-all-4.1.jar" />
-
+  	
     <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" />
+      <formatter type="plain" />
+     </checkstyle>
 
     <checkstyle config="${checkstyle.dir}/opends-doctarget-checkstyle.xml"
          failOnViolation="true">
@@ -259,7 +269,7 @@
 
 
   <!-- Compile the Directory Server source files. -->
-  <target name="cleancompile" depends="cleaninit,compile"
+  <target name="cleancompile" depends="cleaninit,compile,compilequicksetup"
        description="Recompile the Directory Server source files.">
   </target>
 
@@ -284,11 +294,36 @@
     </javac>
   </target>
 
+	<!-- Compile the Quick Setup source files. -->
+	<target name="compilequicksetup"
+		depends="buildtools,compile"
+	    description="Compile the Quick Setup source files.">
+		
+	    <mkdir dir="${quicksetup.classes.dir}" />
+	    <javac srcdir="${quicksetup.src.dir}" destdir="${quicksetup.classes.dir}" optimize="true"
+	    	debug="on" debuglevel="lines,source" source="1.5" target="1.5"
+	        deprecation="true" fork="true" memoryInitialSize="${MEM}"
+	        memoryMaximumSize="${MEM}">
+	        <compilerarg value="-Xlint:all" />
 
-
-
+	    	<classpath>
+	        	<fileset dir="${ext.dir}">
+	            	<include name="build-tools.jar" />
+	            </fileset>
+	            <pathelement path="${classes.dir}"/>
+	        </classpath>
+	   	</javac>
+	   	<copy todir="${quicksetup.classes.dir}">
+	   		<fileset dir="${quicksetup.src.dir}" includes="**/*.properties, **/*.gif, **/*.png" />
+	   	</copy>
+	    <copy todir="${quicksetup.classes.dir}">
+	    	<fileset dir="${classes.dir}"
+	        	includes="**/DynamicConstants.class"/>
+	    </copy>
+  </target>
+	
   <!--
-   ! Rebuild the Directory Server without destorying any existing configuration
+   ! Rebuild the Directory Server without destroying any existing configuration
    ! or data.  It will only overwrite the libraries, classes, and scripts, and
    ! it will not re-package.  It will also not do a complete initialization, so
    ! DynamicConstants.java won't be regenerated.
@@ -313,7 +348,9 @@
     <delete dir="${classes.dir}" />
     <delete file="${package.dir}/lib/OpenDS.jar" />
     <delete file="${pdir}.zip" />
-
+    <delete dir="${quicksetup.classes.dir}" />
+    <delete file="${package.dir}/lib/quicksetup.jar" />
+    
     <!-- Recreate the classes directory and recompile into it. -->
     <mkdir dir="${classes.dir}" />
     <javac srcdir="${src.dir}" destdir="${classes.dir}" optimize="true"
@@ -332,6 +369,37 @@
     <!-- Generate the OpenDS.jar file -->
     <jar jarfile="${pdir}/lib/OpenDS.jar"
          basedir="${classes.dir}" compress="true" index="true" />
+         
+    <!-- Recreate the quicksetup classes directory and recompile into it. -->
+    <mkdir dir="${quicksetup.classes.dir}" />
+    <javac srcdir="${quicksetup.src.dir}" destdir="${quicksetup.classes.dir}" optimize="true"
+        debug="on" debuglevel="lines,source" source="1.5" target="1.5"
+        deprecation="true" fork="true" memoryInitialSize="${MEM}"
+        memoryMaximumSize="${MEM}">
+        <compilerarg value="-Xlint:all" />
+        <classpath>
+            <fileset dir="${ext.dir}">
+                <include name="build-tools.jar" />
+            </fileset>
+            <fileset dir="${pdir}/lib">
+                <include name="OpenDS.jar" />
+            </fileset>
+        </classpath>
+    </javac>
+
+    <copy todir="${quicksetup.classes.dir}">
+        <fileset dir="${quicksetup.src.dir}"
+            includes="**/*.properties, **/*.gif, **/*.png"/>
+    </copy>
+
+    <copy todir="${quicksetup.classes.dir}">
+        <fileset dir="${classes.dir}"
+            includes="**/DynamicConstants.class"/>
+    </copy>
+
+    <!-- Generate the quicksetup.jar file -->
+    <jar jarfile="${pdir}/lib/quicksetup.jar"
+         basedir="${quicksetup.classes.dir}" compress="true" index="true" />
   </target>
 
 
@@ -365,7 +433,10 @@
 
     <jar jarfile="${pdir}/lib/OpenDS.jar"
          basedir="${classes.dir}" compress="true" index="true" />
-
+    
+    <jar jarfile="${pdir}/lib/quicksetup.jar"
+         basedir="${quicksetup.classes.dir}" compress="true" index="true" />
+         
     <copy todir="${pdir}/lib">
       <fileset file="${lib.dir}/*.jar" />
     </copy>
@@ -434,9 +505,6 @@
     </zip>
   </target>
 
-
-
-
   <!-- Prepare the Directory Server DSML library. -->
   <target name="predsml" depends="prepackage"
        description="Prepare the Directory Server DSML library.">
@@ -794,4 +862,3 @@
   </target>
         
 </project>
-
diff --git a/opends/ext/build-tools.jar b/opends/ext/build-tools.jar
index 484deea..dee1b38 100644
--- a/opends/ext/build-tools.jar
+++ b/opends/ext/build-tools.jar
Binary files differ
diff --git a/opends/resource/setup.bat b/opends/resource/setup.bat
index ef636b8..912385c 100644
--- a/opends/resource/setup.bat
+++ b/opends/resource/setup.bat
@@ -49,7 +49,7 @@
 
 set PATH=%SystemRoot%
 
-%JAVA_BIN% %JAVA_ARGS% -Dorg.opends.server.scriptName=setup org.opends.server.tools.InstallDS --configClass org.opends.server.extensions.ConfigFileHandler --configFile "%DIR_HOME%\config\config.ldif" -P setup.bat %*
+%JAVA_BIN% %JAVA_ARGS% org.opends.quicksetup.SetupLauncher -P setup.bat %*
 
 
 :end
diff --git a/opends/resource/setup.sh b/opends/resource/setup.sh
index e3195a6..9ddac4c 100755
--- a/opends/resource/setup.sh
+++ b/opends/resource/setup.sh
@@ -111,8 +111,5 @@
 
 
 # Launch the setup process.
-"${JAVA_BIN}" ${JAVA_ARGS} -Dorg.opends.server.scriptName=setup \
-     org.opends.server.tools.InstallDS \
-     --configClass org.opends.server.extensions.ConfigFileHandler \
-     --configFile "${INSTANCE_ROOT}/config/config.ldif" -P "${0}" "${@}"
+"${JAVA_BIN}" org.opends.quicksetup.SetupLauncher -P setup.sh "${@}"
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java b/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
new file mode 100644
index 0000000..3ee5135
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+/**
+ * This enumeration defines the logical names of the buttons that appear on the
+ * bottom of the wizard dialog.
+ */
+public enum ButtonName
+{
+  /**
+   * The Next button.
+   */
+  NEXT,
+  /**
+   * The Previous button.
+   */
+  PREVIOUS,
+  /**
+   * The Quit button.
+   */
+  QUIT,
+  /**
+   * The Close button.
+   */
+  CLOSE,
+  /**
+   * The Finish button.
+   */
+  FINISH
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java b/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
new file mode 100644
index 0000000..f13b349
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
@@ -0,0 +1,299 @@
+/*
+ * 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;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import javax.naming.NamingException;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.offline.OfflineInstaller;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to know which is the status of the install. This class is
+ * not used when we install Open DS using java web start. However it is required
+ * when do an offline installation after the user has unzipped the zip file. The
+ * main goal of the class is to help identifying whether there is already
+ * something installed or not.
+ *
+ * This class assumes that we are running in the case of an offline install.
+ */
+
+public class CurrentInstallStatus
+{
+  private boolean isInstalled;
+
+  private String installationMsg;
+
+  private String configFileContents;
+
+  /**
+   * The constructor of a CurrentInstallStatus object.
+   *
+   */
+  public CurrentInstallStatus()
+  {
+    if (Utils.isWebStart())
+    {
+      isInstalled = false;
+    } else
+    {
+      ArrayList<String> msgs = new ArrayList<String>();
+
+      if (isServerRunning())
+      {
+        if (isConfigFileModified() || (getPort() != 389))
+        {
+          /*
+           * If the config file is not modified and the port is 389 the common
+           * case is that there is already a server running on the default port,
+           * so it does not correspond to this install.
+           */
+          msgs.add(getMsg("installstatus-serverrunning", new String[]
+            { String.valueOf(getPort()) }));
+        }
+      }
+
+      if (dbFilesExist())
+      {
+        msgs.add(getMsg("installstatus-dbfileexist"));
+      }
+
+      if (isConfigFileModified())
+      {
+        msgs.add(getMsg("installstatus-configfilemodified"));
+      }
+      isInstalled = msgs.size() > 0;
+      if (isInstalled)
+      {
+        StringBuffer buf = new StringBuffer();
+        buf.append("<ul>");
+        for (String msg : msgs)
+        {
+          buf.append("\n<li>").append(msg).append("</li>");
+        }
+        buf.append("</ul>");
+        installationMsg = getMsg("installstatus-installed", new String[]
+          { buf.toString() });
+      }
+    }
+    if (!isInstalled)
+    {
+      installationMsg = getMsg("installstatus-not-installed");
+    }
+  }
+
+  /**
+   * Indicates whether there is something installed or not.
+   *
+   * @return <CODE>true</CODE> if there is something installed under the
+   *         binaries that we are running, or <CODE>false</CODE> if not.
+   */
+  public boolean isInstalled()
+  {
+    return isInstalled;
+  }
+
+  /**
+   * Provides a localized message to be displayed to the user in HTML format
+   * informing of the installation status.
+   *
+   * @return an String in HTML format describing the status of the installation.
+   */
+  public String getInstallationMsg()
+  {
+    return installationMsg;
+  }
+
+  /**
+   * Provides the config file path (path to config.ldif file).
+   *
+   * @return the config file path.
+   */
+  private String getConfigFilePath()
+  {
+    return OfflineInstaller.CONFIG_FILE_NAME;
+  }
+
+  /**
+   * Provides the LDAP port as is specified in the config.ldif file.
+   *
+   * @return the LDAP port specified in the config.ldif file.
+   */
+  private int getPort()
+  {
+    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);
+      if (index1 != -1)
+      {
+        int index2 =
+            getConfigFileContents().indexOf(
+                System.getProperty("line.separator"), index1);
+        if (index2 != -1)
+        {
+          String sPort =
+              getConfigFileContents().substring(portAttr.length() + index1,
+                  index2).trim();
+          try
+          {
+            port = Integer.parseInt(sPort);
+          } catch (NumberFormatException nfe)
+          {
+          }
+        }
+      }
+    }
+    return port;
+  }
+
+  /**
+   * 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
+   * <CODE>false</CODE> if not.
+   */
+  private boolean dbFilesExist()
+  {
+    boolean dbFilesExist = false;
+    File dbDir = new File(OfflineInstaller.FULL_INSTALL_PATH, "db");
+    File[] children = dbDir.listFiles();
+    if ((children != null) && (children.length > 0))
+    {
+      dbFilesExist = true;
+    }
+    return dbFilesExist;
+  }
+
+  /**
+   * Indicates whether the config.ldif file has been modified (compared to what
+   * we had in the zip file). This is used to know if we have configured the
+   * current binaries or not.
+   *
+   * @return <CODE>true</CODE> if the config.ldif file has been modified, or
+   *         <CODE>false</CODE> if not.
+   */
+  private boolean isConfigFileModified()
+  {
+    boolean isConfigFileModified = getPort() != 389;
+
+    if (!isConfigFileModified)
+    {
+      // TODO: this is not really stable
+      isConfigFileModified =
+          getConfigFileContents().indexOf("# cddl header start") == -1;
+    }
+
+    return isConfigFileModified;
+  }
+
+  /**
+   * Provides the contents of the config.ldif file in a String.
+   *
+   * @return a String representing the contents of the config.ldif file.
+   */
+  private String getConfigFileContents()
+  {
+    if (configFileContents == null)
+    {
+      StringBuffer buf = new StringBuffer();
+      try
+      {
+        BufferedReader in =
+            new BufferedReader(new FileReader(getConfigFilePath()));
+        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();
+      } catch (IOException ioe)
+      {
+      }
+    }
+    return configFileContents;
+  }
+
+  /**
+   * The following three methods are just commodity methods to get 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();
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java b/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
new file mode 100644
index 0000000..d156a3b
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
@@ -0,0 +1,1164 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Iterator;
+
+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.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.DataOptions;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.Installer;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.installer.UserInstallDataException;
+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.QuickSetupDialog;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.uninstaller.Uninstaller;
+import org.opends.quicksetup.util.BackgroundTask;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is responsible for doing the following:
+ *
+ * Check whether we are installing or uninstalling and which type of
+ * installation we are running.
+ *
+ * Performs all the checks and validation of the data provided by the user
+ * during the setup.
+ *
+ * It will launch also the installation once the user clicks on 'Finish' if we
+ * are installing the product.
+ *
+ * If we are running a web start installation it will start the background
+ * downloading of the jar files that are required to perform the installation
+ * (OpenDS.jar, je.jar, etc.).  The global idea is to force the user to
+ * download just one jar file (quicksetup.jar) to launch the Web Start
+ * installer.  Then QuickSetup will call WebStartDownloader to download the jar
+ * files.  Until this class is not finished the WebStart Installer will be on
+ * the InstallProgressStep.DOWNLOADING step.
+ *
+ */
+class QuickSetup implements ButtonActionListener, ProgressUpdateListener
+{
+  // Contains the data provided by the user
+  private UserInstallData userData;
+
+  private Installer installer;
+
+  private Uninstaller uninstaller;
+
+  private WebStartDownloader jnlpDownloader;
+
+  private CurrentInstallStatus installStatus;
+
+  private Step currentStep = Step.WELCOME;
+
+  private QuickSetupDialog dialog;
+
+  private StringBuffer progressDetails = new StringBuffer();
+
+  private InstallProgressDescriptor lastDescriptor;
+
+  private InstallProgressDescriptor lastDisplayedDescriptor;
+
+  private InstallProgressDescriptor descriptorToDisplay;
+
+  // Constants used to do checks
+  private static final int MIN_DIRECTORY_MANAGER_PWD = 1;
+
+  private static final int MIN_PORT_VALUE = 1;
+
+  private static final int MAX_PORT_VALUE = 65535;
+
+  private static final int MIN_NUMBER_ENTRIES = 1;
+
+  private static final int MAX_NUMBER_ENTRIES = 10000000;
+
+  // Update period of the dialogs.
+  private static final int UPDATE_PERIOD = 500;
+
+  /**
+   * This method creates the install/uninstall dialogs and to check the current
+   * install status. This method must be called outside the event thread because
+   * it can perform long operations which can make the user think that the UI is
+   * blocked.
+   *
+   * @param args for the moment this parameter is not used but we keep it in
+   * order to (in case of need) pass parameters through the command line.
+   */
+  public void initialize(String[] args)
+  {
+    if (isWebStart())
+    {
+      jnlpDownloader = new WebStartDownloader();
+      jnlpDownloader.start(false);
+    }
+    installStatus = new CurrentInstallStatus();
+    initLookAndFeel();
+    if (Utils.isUninstall())
+    {
+      setCurrentStep(Step.CONFIRM_UNINSTALL);
+    } else
+    {
+      setCurrentStep(Step.WELCOME);
+    }
+  }
+
+  /**
+   * This method displays the setup dialog. This method must be called from the
+   * event thread.
+   */
+  public void display()
+  {
+    getDialog().packAndShow();
+  }
+
+  /**
+   * ButtonActionListener implementation. It assumes that we are called in the
+   * event thread.
+   *
+   * @param ev the ButtonEvent we receive.
+   */
+  public void buttonActionPerformed(ButtonEvent ev)
+  {
+    switch (ev.getButtonName())
+    {
+    case NEXT:
+      nextClicked();
+      break;
+
+    case CLOSE:
+      closeClicked();
+      break;
+
+    case FINISH:
+      finishClicked();
+      break;
+
+    case QUIT:
+      quitClicked();
+      break;
+
+    case PREVIOUS:
+      previousClicked();
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknown button name: "
+          + ev.getButtonName());
+    }
+  }
+
+  /**
+   * ProgressUpdateListener implementation. Here we take the ProgressUpdateEvent
+   * and create a ProgressDescriptor that will be used to update the progress
+   * dialog.
+   *
+   * @param ev the ProgressUpdateEvent we receive.
+   *
+   * @see #runDisplayUpdater()
+   */
+  public void progressUpdate(ProgressUpdateEvent ev)
+  {
+    synchronized (this)
+    {
+      InstallProgressDescriptor desc = createProgressDescriptor(ev);
+      boolean isLastDescriptor =
+          desc.getProgressStep() == InstallProgressStep.FINISHED_SUCCESSFULLY
+              || desc.getProgressStep() ==
+                InstallProgressStep.FINISHED_WITH_ERROR;
+      if (isLastDescriptor)
+      {
+        lastDescriptor = desc;
+      }
+
+      descriptorToDisplay = 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).
+   *
+   * @see #progressUpdate(ProgressUpdateEvent ev)
+   *
+   */
+  private void runDisplayUpdater()
+  {
+    boolean doPool = true;
+    while (doPool)
+    {
+      try
+      {
+        Thread.sleep(UPDATE_PERIOD);
+      } catch (Exception ex)
+      {
+      }
+      synchronized (this)
+      {
+        final InstallProgressDescriptor desc = descriptorToDisplay;
+        if (desc != null)
+        {
+          if (desc != lastDisplayedDescriptor)
+          {
+            lastDisplayedDescriptor = desc;
+
+            SwingUtilities.invokeLater(new Runnable()
+            {
+              public void run()
+              {
+                getDialog().displayProgress(desc);
+              }
+            });
+          }
+          doPool = desc != lastDescriptor;
+        }
+      }
+    }
+  }
+
+  /**
+   * Method called when user clicks 'Next' button of the wizard.
+   *
+   */
+  private void nextClicked()
+  {
+    final Step cStep = getCurrentStep();
+    switch (cStep)
+    {
+    case PROGRESS:
+      throw new IllegalStateException(
+          "Cannot click on next from progress step");
+
+    case REVIEW:
+      throw new IllegalStateException("Cannot click on next from review step");
+
+    default:
+      BackgroundTask worker = new BackgroundTask()
+      {
+        public Object processBackgroundTask() throws UserInstallDataException
+        {
+          try
+          {
+            updateUserData(cStep);
+          } catch (RuntimeException re)
+          {
+            throw new UserInstallDataException(getCurrentStep(),
+                getExceptionMsg("bug-msg", re));
+          }
+          return null;
+        }
+
+        public void backgroundTaskCompleted(Object returnValue,
+            Throwable throwable)
+        {
+          getDialog().workerFinished();
+          UserInstallDataException ude = (UserInstallDataException)throwable;
+          if (ude != null)
+          {
+            displayError(ude.getLocalizedMessage(), getMsg("error-title"));
+          } else
+          {
+            setCurrentStep(nextStep(cStep));
+          }
+        }
+      };
+      getDialog().workerStarted();
+      worker.startBackgroundTask();
+    }
+  }
+
+  /**
+   * Method called when user clicks 'Finish' button of the wizard.
+   *
+   */
+  private void finishClicked()
+  {
+    Step cStep = getCurrentStep();
+    switch (cStep)
+    {
+    case REVIEW:
+      updateUserDataForReviewPanel();
+      launchInstallation();
+      setCurrentStep(Step.PROGRESS);
+      break;
+
+    case CONFIRM_UNINSTALL:
+      launchUninstallation();
+      setCurrentStep(Step.PROGRESS);
+      break;
+
+    default:
+      throw new IllegalStateException(
+          "Cannot click on finish when we are not in the Review window");
+    }
+  }
+
+  /**
+   * Method called when user clicks 'Previous' button of the wizard.
+   *
+   */
+  private void previousClicked()
+  {
+    Step cStep = getCurrentStep();
+    switch (cStep)
+    {
+    case WELCOME:
+      throw new IllegalStateException(
+          "Cannot click on previous from progress step");
+
+    case PROGRESS:
+      throw new IllegalStateException(
+          "Cannot click on previous from progress step");
+
+    default:
+      setCurrentStep(previousStep(cStep));
+    }
+  }
+
+  /**
+   * Method called when user clicks 'Quit' button of the wizard.
+   *
+   */
+  private void quitClicked()
+  {
+    Step cStep = getCurrentStep();
+    switch (cStep)
+    {
+    case PROGRESS:
+      throw new IllegalStateException(
+          "Cannot click on quit from progress step");
+
+    default:
+      if (installStatus.isInstalled())
+      {
+        quit();
+      } else if (displayConfirmation(getMsg("confirm-quit-quicksetup-msg"),
+          getMsg("confirm-quit-quicksetup-title")))
+      {
+        quit();
+      }
+    }
+  }
+
+  /**
+   * Method called when user clicks 'Close' button of the wizard.
+   *
+   */
+  private void closeClicked()
+  {
+    Step cStep = getCurrentStep();
+    switch (cStep)
+    {
+    case PROGRESS:
+      if (Utils.isUninstall())
+      {
+        boolean finished = uninstaller.isFinished();
+        if (finished
+            || displayConfirmation(getMsg("confirm-close-uninstall-msg"),
+                getMsg("confirm-close-uninstall-title")))
+        {
+          quit();
+        }
+      } else
+      {
+        boolean finished = installer.isFinished();
+        if (finished
+            || displayConfirmation(getMsg("confirm-close-quicksetup-msg"),
+                getMsg("confirm-close-quicksetup-title")))
+        {
+          quit();
+        }
+      }
+      break;
+
+    default:
+      throw new IllegalStateException(
+          "Close only can be clicked on PROGRESS 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.
+   *
+   */
+  private void quit()
+  {
+    System.exit(0);
+  }
+
+  /**
+   * These methods validate the data provided by the user in the panels and
+   * update the UserData object according to that content.
+   *
+   * @param cStep
+   *          the current step of the wizard
+   *
+   * @throws an
+   *           UserInstallDataException if the data provided by the user is not
+   *           valid.
+   *
+   */
+  private void updateUserData(Step cStep) throws UserInstallDataException
+  {
+    switch (cStep)
+    {
+    case SERVER_SETTINGS:
+      updateUserDataForServerSettingsPanel();
+      break;
+
+    case DATA_OPTIONS:
+      updateUserDataForDataOptionsPanel();
+      break;
+
+    case REVIEW:
+      updateUserDataForReviewPanel();
+      break;
+    }
+  }
+
+  /**
+   * Validate the data provided by the user in the server settings panel and
+   * update the UserData object according to that content.
+   *
+   * @throws an
+   *           UserInstallDataException if the data provided by the user is not
+   *           valid.
+   *
+   */
+  private void updateUserDataForServerSettingsPanel()
+      throws UserInstallDataException
+  {
+    ArrayList<String> errorMsgs = new ArrayList<String>();
+
+    if (isWebStart())
+    {
+      // Check the server location
+      String serverLocation = getFieldStringValue(FieldName.SERVER_LOCATION);
+
+      if ((serverLocation == null) || ("".equals(serverLocation.trim())))
+      {
+        errorMsgs.add(getMsg("empty-server-location"));
+        displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+      } else if (!Utils.parentDirectoryExists(serverLocation))
+      {
+        String[] arg =
+          { serverLocation };
+        errorMsgs.add(getMsg("parent-directory-does-not-exist", arg));
+        displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+      } else if (Utils.fileExists(serverLocation))
+      {
+        String[] arg =
+          { serverLocation };
+        errorMsgs.add(getMsg("file-exists", arg));
+        displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+      } else if (Utils.directoryExistsAndIsNotEmpty(serverLocation))
+      {
+        String[] arg =
+          { serverLocation };
+        errorMsgs.add(getMsg("directory-exists-not-empty", arg));
+        displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+      } else if (!Utils.canWrite(serverLocation))
+      {
+        String[] arg =
+          { serverLocation };
+        errorMsgs.add(getMsg("directory-not-writable", arg));
+        displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+
+      } else if (!Utils.hasEnoughSpace(serverLocation,
+          getRequiredInstallSpace()))
+      {
+        long requiredInMb = getRequiredInstallSpace() / (1024 * 1024);
+        String[] args =
+          { serverLocation, String.valueOf(requiredInMb) };
+        errorMsgs.add(getMsg("not-enough-disk-space", args));
+        displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+
+      } else
+      {
+        getUserData().setServerLocation(serverLocation);
+        displayFieldInvalid(FieldName.SERVER_LOCATION, false);
+      }
+    }
+
+    // Check the port
+    String sPort = getFieldStringValue(FieldName.SERVER_PORT);
+    try
+    {
+      int port = Integer.parseInt(sPort);
+      if ((port < MIN_PORT_VALUE) || (port > MAX_PORT_VALUE))
+      {
+        String[] args =
+          { String.valueOf(MIN_PORT_VALUE), String.valueOf(MAX_PORT_VALUE) };
+        errorMsgs.add(getMsg("invalid-port-value-range", args));
+        displayFieldInvalid(FieldName.SERVER_PORT, true);
+      } else if (!Utils.canUseAsPort(port))
+      {
+        if (Utils.isPriviledgedPort(port))
+        {
+          errorMsgs.add(getMsg("cannot-bind-priviledged-port", new String[]
+            { String.valueOf(port) }));
+        } else
+        {
+          errorMsgs.add(getMsg("cannot-bind-port", new String[]
+            { String.valueOf(port) }));
+        }
+        displayFieldInvalid(FieldName.SERVER_PORT, true);
+
+      } else
+      {
+        getUserData().setServerPort(port);
+        displayFieldInvalid(FieldName.SERVER_PORT, false);
+      }
+
+    } catch (NumberFormatException nfe)
+    {
+      String[] args =
+        { String.valueOf(MIN_PORT_VALUE), String.valueOf(MAX_PORT_VALUE) };
+      errorMsgs.add(getMsg("invalid-port-value-range", args));
+      displayFieldInvalid(FieldName.SERVER_PORT, true);
+    }
+
+    // Check the Directory Manager DN
+    String dmDn = getFieldStringValue(FieldName.DIRECTORY_MANAGER_DN);
+
+    if ((dmDn == null) || (dmDn.trim().length() == 0))
+    {
+      errorMsgs.add(getMsg("empty-directory-manager-dn"));
+      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true);
+    } else if (!Utils.isDn(dmDn))
+    {
+      errorMsgs.add(getMsg("not-a-directory-manager-dn"));
+      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true);
+    } else if (Utils.isConfigurationDn(dmDn))
+    {
+      errorMsgs.add(getMsg("directory-manager-dn-is-config-dn"));
+      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true);
+    } else
+    {
+      getUserData().setDirectoryManagerDn(dmDn);
+      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, false);
+    }
+
+    // Check the provided passwords
+    String pwd1 = getFieldStringValue(FieldName.DIRECTORY_MANAGER_PWD);
+    String pwd2 = getFieldStringValue(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM);
+    if (pwd1 == null)
+    {
+      pwd1 = "";
+    }
+
+    boolean pwdValid = true;
+    if (!pwd1.equals(pwd2))
+    {
+      errorMsgs.add(getMsg("not-equal-pwd"));
+      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, true);
+      pwdValid = false;
+
+    }
+    if (pwd1.length() < MIN_DIRECTORY_MANAGER_PWD)
+    {
+      errorMsgs.add(getMsg(("pwd-too-short"), new String[]
+        { String.valueOf(MIN_DIRECTORY_MANAGER_PWD) }));
+      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD, true);
+      if ((pwd2 == null) || (pwd2.length() < MIN_DIRECTORY_MANAGER_PWD))
+      {
+        displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, true);
+      }
+      pwdValid = false;
+    }
+
+    if (pwdValid)
+    {
+      getUserData().setDirectoryManagerPwd(pwd1);
+      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD, false);
+      displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, false);
+    }
+
+    if (errorMsgs.size() > 0)
+    {
+      throw new UserInstallDataException(Step.SERVER_SETTINGS,
+          getStringFromCollection(errorMsgs));
+    }
+  }
+
+  /**
+   * Validate the data provided by the user in the data options panel and update
+   * the UserData object according to that content.
+   *
+   * @throws an
+   *           UserInstallDataException if the data provided by the user is not
+   *           valid.
+   *
+   */
+  private void updateUserDataForDataOptionsPanel()
+      throws UserInstallDataException
+  {
+    ArrayList<String> errorMsgs = new ArrayList<String>();
+
+    DataOptions dataOptions = null;
+
+    // Check the base dn
+    boolean validBaseDn = false;
+    String baseDn = getFieldStringValue(FieldName.DIRECTORY_BASE_DN);
+    if ((baseDn == null) || (baseDn.trim().length() == 0))
+    {
+      errorMsgs.add(getMsg("empty-base-dn"));
+      displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, true);
+    } else if (!Utils.isDn(baseDn))
+    {
+      errorMsgs.add(getMsg("not-a-base-dn"));
+      displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, true);
+    } else if (Utils.isConfigurationDn(baseDn))
+    {
+      errorMsgs.add(getMsg("base-dn-is-configuration-dn"));
+      displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, true);
+    } else
+    {
+      displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, false);
+      validBaseDn = true;
+    }
+
+    // Check the data options
+    DataOptions.Type type =
+        (DataOptions.Type) getFieldValue(FieldName.DATA_OPTIONS);
+
+    switch (type)
+    {
+    case IMPORT_FROM_LDIF_FILE:
+      String ldifPath = getFieldStringValue(FieldName.LDIF_PATH);
+      if ((ldifPath == null) || (ldifPath.trim().equals("")))
+      {
+        errorMsgs.add(getMsg("no-ldif-path"));
+        displayFieldInvalid(FieldName.LDIF_PATH, true);
+      } else if (!Utils.fileExists(ldifPath))
+      {
+        errorMsgs.add(getMsg("ldif-file-does-not-exist"));
+        displayFieldInvalid(FieldName.LDIF_PATH, true);
+      } else if (validBaseDn)
+      {
+        dataOptions = new DataOptions(type, baseDn, ldifPath);
+        displayFieldInvalid(FieldName.LDIF_PATH, false);
+      }
+      break;
+
+    case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+      // variable used to know if everything went ok during these
+      // checks
+      int startErrors = errorMsgs.size();
+
+      // Check the number of entries
+      String nEntries = getFieldStringValue(FieldName.NUMBER_ENTRIES);
+      if ((nEntries == null) || (nEntries.trim().equals("")))
+      {
+        errorMsgs.add(getMsg("no-number-entries"));
+        displayFieldInvalid(FieldName.NUMBER_ENTRIES, true);
+      } else
+      {
+        boolean nEntriesValid = false;
+        try
+        {
+          int n = Integer.parseInt(nEntries);
+
+          nEntriesValid = n >= MIN_NUMBER_ENTRIES && n <= MAX_NUMBER_ENTRIES;
+        } catch (NumberFormatException nfe)
+        {
+        }
+
+        if (!nEntriesValid)
+        {
+          String[] args =
+                { String.valueOf(MIN_NUMBER_ENTRIES),
+                    String.valueOf(MAX_NUMBER_ENTRIES) };
+          errorMsgs.add(getMsg("invalid-number-entries-range", args));
+          displayFieldInvalid(FieldName.NUMBER_ENTRIES, true);
+        } else
+        {
+          displayFieldInvalid(FieldName.NUMBER_ENTRIES, false);
+        }
+      }
+      if (startErrors == errorMsgs.size() && validBaseDn)
+      {
+        // No validation errors
+        dataOptions = new DataOptions(type, baseDn, new Integer(nEntries));
+      }
+      break;
+
+    default:
+      displayFieldInvalid(FieldName.LDIF_PATH, false);
+      displayFieldInvalid(FieldName.NUMBER_ENTRIES, false);
+      if (validBaseDn)
+      {
+        dataOptions = new DataOptions(type, baseDn);
+      }
+    }
+
+    if (dataOptions != null)
+    {
+      getUserData().setDataOptions(dataOptions);
+    }
+
+    if (errorMsgs.size() > 0)
+    {
+      throw new UserInstallDataException(Step.DATA_OPTIONS,
+          getStringFromCollection(errorMsgs));
+    }
+  }
+
+  /**
+   * Update the UserData object according to the content of the review panel.
+   *
+   */
+  private void updateUserDataForReviewPanel()
+  {
+    Boolean b = (Boolean) getFieldValue(FieldName.SERVER_START);
+    getUserData().setStartServer(b.booleanValue());
+  }
+
+  /**
+   * Launch the installation of Open DS. Depending on whether we are running a
+   * web start or not it will use on Installer object or other.
+   *
+   */
+  private void launchInstallation()
+  {
+    if (isWebStart())
+    {
+      installer = new WebStartInstaller(getUserData(), jnlpDownloader);
+    } else
+    {
+      installer = new OfflineInstaller(getUserData());
+    }
+    installer.addProgressUpdateListener(this);
+    installer.start();
+    Thread t = new Thread(new Runnable()
+    {
+      public void run()
+      {
+        runDisplayUpdater();
+      }
+    });
+    t.start();
+  }
+
+  /**
+   * Launch the uninstallation of Open DS.
+   *
+   */
+  private void launchUninstallation()
+  {
+    uninstaller = new Uninstaller();
+    // TO COMPLETE
+  }
+
+  /**
+   * Provides the object representing the data provided by the user in the
+   * install.
+   *
+   * @return the UserInstallData representing the data provided by the user in
+   *         the Install wizard.
+   */
+  private UserInstallData getUserData()
+  {
+    if (userData == null)
+    {
+      userData = new UserInstallData();
+    }
+    return userData;
+  }
+
+  /**
+   * Provides an object representing the default data/install parameters that
+   * will be proposed to the user in the Installation wizard. This data includes
+   * elements such as the default dn of the directory manager or the default
+   * install location.
+   *
+   * @return the UserInstallData representing the default data/parameters that
+   *         will be proposed to the user.
+   */
+  private UserInstallData getDefaultUserData()
+  {
+    UserInstallData defaultUserData = new UserInstallData();
+
+    DataOptions defaultDataOptions = new DefaultDataOptions();
+
+    defaultUserData.setServerLocation(Utils.getDefaultServerLocation());
+    // See what we can propose as port
+    int defaultPort = getDefaultPort();
+    if (defaultPort != -1)
+    {
+      defaultUserData.setServerPort(defaultPort);
+    }
+    defaultUserData.setDirectoryManagerDn("cn=Directory Manager");
+
+    defaultUserData.setDataOptions(defaultDataOptions);
+    defaultUserData.setStartServer(true);
+
+    return defaultUserData;
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private String getMsg(String key, String[] args)
+  {
+    return getI18n().getMsg(key, args);
+  }
+
+  private String getExceptionMsg(String key, Exception ex)
+  {
+    return Utils.getExceptionMsg(getI18n(), key, null, ex);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  /**
+   * Get the current step.
+   *
+   * @return the currently displayed Step of the wizard.
+   */
+  private Step getCurrentStep()
+  {
+    return currentStep;
+  }
+
+  /**
+   * Set the current step. This will basically make the required calls in the
+   * dialog to display the panel that corresponds to the step passed as
+   * argument.
+   *
+   * @param step.
+   *          The step to be displayed.
+   */
+  private void setCurrentStep(Step step)
+  {
+    if (step == null)
+    {
+      throw new NullPointerException("step is null");
+    }
+    currentStep = step;
+    getDialog().setDisplayedStep(step, getUserData());
+  }
+
+  /**
+   * Gets the next step corresponding to the step passed as parameter.
+   *
+   * @param step,
+   *          the step of which we want to get the new step.
+   * @return the next step for the current step.
+   * @throws IllegalArgumentException
+   *           if the current step has not a next step.
+   */
+  private Step nextStep(Step step)
+  {
+    Iterator<Step> it = EnumSet.range(step, Step.PROGRESS).iterator();
+    it.next();
+    if (!it.hasNext())
+    {
+      throw new IllegalArgumentException("No next for step: " + step);
+    }
+    return it.next();
+  }
+
+  /**
+   * Gets the previous step corresponding to the step passed as parameter.
+   *
+   * @param step,
+   *          the step of which we want to get the previous step.
+   * @return the next step for the current step.
+   * @throws IllegalArgumentException
+   *           if the current step has not a previous step.
+   */
+  private Step previousStep(Step step)
+  {
+    Step previous = null;
+    for (Step s : Step.values())
+    {
+      if (s == step)
+      {
+        return previous;
+      }
+      previous = s;
+    }
+    throw new IllegalArgumentException("No previous for step: " + step);
+  }
+
+  /**
+   * Get the dialog that is displayed.
+   *
+   * @return the dialog.
+   */
+  private QuickSetupDialog getDialog()
+  {
+    if (dialog == null)
+    {
+      dialog = new QuickSetupDialog(getDefaultUserData(), installStatus);
+      dialog.addButtonActionListener(this);
+    }
+    return dialog;
+  }
+
+  /**
+   * Displays an error message dialog.
+   *
+   * @param msg
+   *          the error message.
+   * @param title
+   *          the title for the dialog.
+   */
+  private void displayError(String msg, String title)
+  {
+    getDialog().displayError(msg, title);
+  }
+
+  /**
+   * Displays a confirmation message 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.
+   */
+  private boolean displayConfirmation(String msg, String title)
+  {
+    return getDialog().displayConfirmation(msg, title);
+  }
+
+  /**
+   * Gets the string value for a given field name.
+   *
+   * @param fieldName
+   *          the field name object.
+   * @return the string value for the field name.
+   */
+  private String getFieldStringValue(FieldName fieldName)
+  {
+    String sValue = null;
+
+    Object value = getFieldValue(fieldName);
+    if (value != null)
+    {
+      if (value instanceof String)
+      {
+        sValue = (String) value;
+      } else
+      {
+        sValue = String.valueOf(value);
+      }
+    }
+    return sValue;
+  }
+
+  /**
+   * Gets the value for a given field name.
+   *
+   * @param fieldName
+   *          the field name object.
+   * @return the value for the field name.
+   */
+  private Object getFieldValue(FieldName fieldName)
+  {
+    return getDialog().getFieldValue(fieldName);
+  }
+
+  /**
+   * Marks the fieldName as valid or invalid depending on the value of the
+   * invalid parameter. With the current implementation this implies basically
+   * using a red color in the label associated with the fieldName object. The
+   * color/style used to mark the label invalid is specified in UIFactory.
+   *
+   * @param fieldName
+   *          the field name object.
+   * @param invalid
+   *          whether to mark the field valid or invalid.
+   */
+  private void displayFieldInvalid(FieldName fieldName, boolean invalid)
+  {
+    getDialog().displayFieldInvalid(fieldName, invalid);
+  }
+
+  /**
+   * 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.
+   *
+   */
+  private void initLookAndFeel()
+  {
+    UIFactory.initialize();
+  }
+
+  /**
+   * A methods that creates a InstallProgressDescriptor based on the value of a
+   * ProgressUpdateEvent.
+   *
+   * @param ev
+   *          the ProgressUpdateEvent used to generate the
+   *          InstallProgressDescriptor.
+   * @return the InstallProgressDescriptor.
+   */
+  private InstallProgressDescriptor createProgressDescriptor(
+      ProgressUpdateEvent ev)
+  {
+    InstallProgressStep status = ev.getProgressStep();
+    String newProgressLabel = ev.getCurrentPhaseSummary();
+    String additionalDetails = ev.getNewLogs();
+    Integer ratio = ev.getProgressRatio();
+
+    if (additionalDetails != null)
+    {
+      progressDetails.append(additionalDetails);
+    }
+
+    return new InstallProgressDescriptor(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
+   *         <CODE>false</CODE> if not.
+   */
+  private boolean isWebStart()
+  {
+    return Utils.isWebStart();
+  }
+
+  /**
+   * Provides the port that will be proposed to the user in the second page of
+   * the installation wizard. It will check whether we can use 389 and if not it
+   * will return -1.
+   *
+   * @return the port 389 if it is available and we can use and -1 if not.
+   */
+  private int getDefaultPort()
+  {
+    int defaultPort = -1;
+    if (Utils.canUseAsPort(389))
+    {
+      defaultPort = 389;
+    }
+    return defaultPort;
+  }
+
+  /**
+   * Returns the number of free disk space in bytes required to install Open DS
+   *
+   * For the moment we just return 15 Megabytes. TODO we might want to have
+   * something dynamic to calculate the required free disk space for the
+   * installation.
+   *
+   * @return the number of free disk space required to install Open DS.
+   */
+  private long getRequiredInstallSpace()
+  {
+    return 15 * 1024 * 1024;
+  }
+}
+
+/**
+ * This class is just used to specify which are the default values that will be
+ * proposed to the user in the Data Options panel of the Installation wizard.
+ *
+ */
+class DefaultDataOptions extends DataOptions
+{
+  /**
+   * Default constructor.
+   *
+   */
+  public DefaultDataOptions()
+  {
+    super(Type.CREATE_BASE_ENTRY, "dc=example,dc=com");
+  }
+
+  /**
+   * Get the number of entries that will be automatically generated.
+   *
+   * @return the number of entries that will be automatically generated.
+   */
+  public int getNumberEntries()
+  {
+    return 2000;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java b/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java
new file mode 100644
index 0000000..8c61e6d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java
@@ -0,0 +1,257 @@
+/*
+ * 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;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.offline.OfflineInstaller;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is called by the setup command lines to launch the installation of
+ * the Directory Server. It just checks the command line arguments and the
+ * environment and determines whether the graphical or the command line
+ * based setup much be launched.
+ *
+ */
+public class SetupLauncher
+{
+  private static String COMMAND_NAME_WINDOWS = "setup.bat";
+
+  private static String COMMAND_NAME_UNIX = "setup.sh";
+
+  /**
+   * The main method which is called by the setup command lines.
+   * @param args the arguments passed by the command lines.  In the case
+   * we want to launch the cli setup they are basically the arguments that we
+   * will pass to the org.opends.server.tools.InstallDS class.
+   */
+  public static void main(String[] args)
+  {
+    boolean displayUsage = false;
+    boolean useCli = false;
+    if ((args != null) && (args.length > 0))
+    {
+      for (int i = 0; i < args.length; i++)
+      {
+        if (args[i].equals("--cli"))
+        {
+          useCli = true;
+        }
+      }
+
+      if (!useCli)
+      {
+        if (args.length > 0)
+        {
+          if (args.length == 2)
+          {
+            /*
+             * Just ignore the -P argument that is passed by the setup command
+             * line.
+             */
+            if (!args[0].equals("-P"))
+            {
+              displayUsage = true;
+            }
+          } else
+          {
+            displayUsage = true;
+          }
+        }
+      }
+    }
+    if (displayUsage)
+    {
+      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 = getMsg("setup-launcher-usage");
+      msg = msg.replace("{0}", arg);
+      System.err.println(msg);
+      System.exit(1);
+    } else if (useCli)
+    {
+      int exitCode = launchCliSetup(args);
+      if (exitCode != 0)
+      {
+        System.exit(exitCode);
+      }
+    } else
+    {
+      int exitCode = launchGuiSetup(args);
+      if (exitCode != 0)
+      {
+        System.err.println(getMsg("setup-launcher-gui-launched-failed"));
+        exitCode = launchCliSetup(args);
+        if (exitCode != 0)
+        {
+          System.exit(exitCode);
+        }
+      }
+    }
+  }
+
+  /**
+   * Launches the command line based setup.
+   * @param args the arguments passed
+   * @return 0 if everything worked fine, and an error code if something wrong
+   * occurred (as specified in org.opends.server.tools.InstallDS).
+   * @see org.opends.server.tools.InstallDS
+   */
+  private static int launchCliSetup(String[] args)
+  {
+    if (Utils.isWindows())
+    {
+      System.setProperty("org.opends.server.scriptName",
+          COMMAND_NAME_WINDOWS);
+    } else
+    {
+      System.setProperty("org.opends.server.scriptName",
+          COMMAND_NAME_UNIX);
+    }
+    ArrayList<String> newArgList = new ArrayList<String>();
+    if (args != null)
+    {
+      for (int i = 0; i < args.length; i++)
+      {
+        if (!args[i].equalsIgnoreCase("--cli"))
+        {
+          newArgList.add(args[i]);
+        }
+      }
+    }
+    newArgList.add("--configClass");
+    newArgList.add("org.opends.server.extensions.ConfigFileHandler");
+    newArgList.add("--configFile");
+    newArgList.add(OfflineInstaller.CONFIG_FILE_NAME);
+
+    String[] newArgs = new String[newArgList.size()];
+    newArgList.toArray(newArgs);
+
+    return org.opends.server.tools.InstallDS.installMain(newArgs);
+  }
+
+  /**
+   * Launches the graphical setup. The graphical setup 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 setup 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 launchGuiSetup(final String[] args)
+  {
+    System.out.println(getMsg("setup-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];
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private static String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  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/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java b/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java
new file mode 100644
index 0000000..74533b6
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java
@@ -0,0 +1,281 @@
+/*
+ * 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;
+
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.awt.Toolkit;
+import java.awt.Window;
+
+import javax.swing.SwingUtilities;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is the class that is called to launch QuickSetup.  It will display a
+ * splash screen and in the background it will create QuickSetup object.
+ *
+ * This class tries to minimize the time to be displayed. So it does the loading
+ * of the setup class in runtime once we already have displayed the splash
+ * screen. This is why the quickSetup variable is of type Object.
+ */
+public class SplashScreen extends Window
+{
+  private static final long serialVersionUID = 8918803902867388766L;
+
+  private Image image;
+
+  private static SplashScreen splash;
+
+  private static Object quickSetup;
+
+  private static Class<?> quickSetupClass;
+
+  // Constant for the display of the splash screen
+  private static final int MIN_SPLASH_DISPLAY = 3000;
+
+  /**
+   * The main method for this class.
+   * It can be called from the event thread and outside the event thread.
+   * @param args arguments to be passed to the method QuickSetup.initialize
+   */
+  public static void main(String[] args)
+  {
+    if (SwingUtilities.isEventDispatchThread())
+    {
+      final String[] fArgs = args;
+      Thread t = new Thread(new Runnable()
+      {
+        public void run()
+        {
+          mainOutsideEventThread(fArgs);
+        }
+      });
+      t.start();
+    } else
+    {
+      mainOutsideEventThread(args);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void update(Graphics g)
+  {
+    paint(g);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void paint(Graphics g)
+  {
+    g.drawImage(image, 0, 0, this);
+  }
+
+  /**
+   * Private constructor to force to use the main method.
+   *
+   */
+  private SplashScreen()
+  {
+    super(new Frame());
+    try
+    {
+      image = getSplashImage();
+      MediaTracker mt = new MediaTracker(this);
+      mt.addImage(image, 0);
+      mt.waitForID(0);
+
+      int width = image.getWidth(this);
+      int height = image.getHeight(this);
+      setPreferredSize(new Dimension(width, height));
+      setSize(width, height);
+      Utils.centerOnScreen(this);
+
+    } catch (Exception ex)
+    {
+      ex.printStackTrace(); // Bug
+    }
+  }
+
+  /**
+   * This method creates the image directly instead of using UIFactory to reduce
+   * class loading.
+   * @return the splash image.
+   */
+  private Image getSplashImage()
+  {
+    String resource = ResourceProvider.getInstance().getMsg("splash-icon");
+    resource = "org/opends/quicksetup/" + resource;
+    return Toolkit.getDefaultToolkit().createImage(
+        this.getClass().getClassLoader().getResource(resource));
+  }
+
+  /**
+   * This is basically the method that is execute in SplashScreen.main but it
+   * it assumes that is being called outside the event thread.
+   *
+   * @param args arguments to be passed to the method QuickSetup.initialize.
+   */
+  private static void mainOutsideEventThread(String[] args)
+  {
+    displaySplashScreen();
+    long splashDisplayStartTime = System.currentTimeMillis();
+    constructQuickSetup(args);
+    sleepIfNecessary(splashDisplayStartTime);
+    disposeSplashScreen();
+    displayQuickSetup();
+  }
+
+  /**
+   * This methods displays the splash screen.
+   * This method assumes that is being called outside the event thread.
+   */
+  private static void displaySplashScreen()
+  {
+    splash = new SplashScreen();
+    try
+    {
+      SwingUtilities.invokeAndWait(new Runnable()
+      {
+        public void run()
+        {
+          splash.setVisible(true);
+        }
+      });
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+
+  /**
+   * This methods constructs the QuickSetup object.
+   * This method assumes that is being called outside the event thread.
+   * @param args arguments to be passed to the method QuickSetup.initialize.
+   */
+  private static void constructQuickSetup(String[] args)
+  {
+    try
+    {
+      quickSetupClass = Class.forName("org.opends.quicksetup.QuickSetup");
+      quickSetup = quickSetupClass.newInstance();
+      quickSetupClass.getMethod("initialize", new Class[]
+        { String[].class }).invoke(quickSetup, new Object[]
+        { args });
+    } catch (Exception e)
+    {
+      InternalError error =
+          new InternalError("Failed to invoke initialize method");
+      error.initCause(e);
+      throw error;
+    }
+  }
+
+  /**
+   * This method displays the QuickSetup dialog.
+   * @see QuickSetup.display.
+   * This method assumes that is being called outside the event thread.
+   */
+  private static void displayQuickSetup()
+  {
+    try
+    {
+      SwingUtilities.invokeAndWait(new Runnable()
+      {
+        public void run()
+        {
+          try
+          {
+            quickSetupClass.getMethod("display").invoke(quickSetup);
+          } catch (Exception e)
+          {
+            InternalError error =
+                new InternalError("Failed to invoke display method");
+            error.initCause(e);
+            throw error;
+          }
+        }
+      });
+    } catch (Exception ex)
+    {
+    }
+  }
+
+  /**
+   * Disposes the splash screen.
+   * This method assumes that is being called outside the event thread.
+   */
+  private static void disposeSplashScreen()
+  {
+    try
+    {
+      SwingUtilities.invokeAndWait(new Runnable()
+      {
+        public void run()
+        {
+          splash.setVisible(false);
+          splash.dispose();
+        }
+      });
+    } catch (Exception ex)
+    {
+    }
+  }
+
+  /**
+   * This method just executes an sleep depending on how long the splash
+   * screen has been displayed.  The idea of calling this method is to have the
+   * splash screen displayed a minimum time (specified by
+   * MIN_SPLASH_DISPLAY).
+   * @param splashDisplayStartTime the time in milliseconds when the splash
+   * screen started displaying.
+   */
+  private static void sleepIfNecessary(long splashDisplayStartTime)
+  {
+    long t2 = System.currentTimeMillis();
+
+    long sleepTime = MIN_SPLASH_DISPLAY - (t2 - splashDisplayStartTime);
+
+    if (sleepTime > 0)
+    {
+      try
+      {
+        Thread.sleep(sleepTime);
+      } catch (Exception ex)
+      {
+      }
+    }
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/Step.java b/opends/src/quicksetup/org/opends/quicksetup/Step.java
new file mode 100644
index 0000000..bf590bb
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/Step.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+/**
+ * This enumeration just represents the different steps that we can have in
+ * the installation and uninstallation wizards.
+ *
+ */
+public enum Step
+
+{
+  /**
+   * Welcome step for the installation.
+   */
+  WELCOME,
+  /**
+   * Server Settings step (path, port, etc.).
+   */
+  SERVER_SETTINGS,
+  /**
+   * Data Options panel (suffix dn, LDIF path, etc.).
+   */
+  DATA_OPTIONS,
+  /**
+   * Review panel for the install.
+   */
+  REVIEW,
+  /**
+   * Progress panel.
+   */
+  PROGRESS,
+  /**
+   * Confirmation panel for the uninstallation.
+   */
+  CONFIRM_UNINSTALL
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/BrowseActionListener.java b/opends/src/quicksetup/org/opends/quicksetup/event/BrowseActionListener.java
new file mode 100644
index 0000000..159e9f7
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/BrowseActionListener.java
@@ -0,0 +1,177 @@
+/*
+ * 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.event;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JFileChooser;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.util.ExtensionFileFilter;
+
+/**
+ * This class is an action listener used to update a text component. When the
+ * class receives an ActionEvent it will display a File Browser Dialog and will
+ * update the text field depending on what the user chooses in the browser
+ * dialog.
+ *
+ * The class is used generally by adding it as ActionListener of a 'Browse'
+ * button.
+ *
+ */
+public class BrowseActionListener implements ActionListener
+{
+  private JFileChooser fc;
+
+  private JTextComponent field;
+
+  private Component parent;
+
+  private BrowseType type;
+
+  /**
+   * Enumeration used to specify which kind of file browser dialog must be
+   * displayed.
+   *
+   */
+  public enum BrowseType
+  {
+    /**
+     * The Browser is used to retrieve a directory.
+     */
+    LOCATION_DIRECTORY,
+    /**
+     * The Browser is used to retrieve an LDIF file.
+     */
+    OPEN_LDIF_FILE
+  }
+
+  /**
+   * Constructor for the BrowseActionListener.
+   *
+   * @param field
+   *          the text component that will be updated when the user selects
+   *          something in the file browser dialog.
+   * @param type
+   *          the type of file browse dialog that will be displayed.
+   * @param parent
+   *          component that will be used as reference to display the file
+   *          browse dialog.
+   */
+  public BrowseActionListener(JTextComponent field, BrowseType type,
+      Component parent)
+  {
+    this.field = field;
+    this.type = type;
+    this.parent = parent;
+
+    ResourceProvider i18n = ResourceProvider.getInstance();
+
+    fc = new JFileChooser();
+    switch (type)
+    {
+    case LOCATION_DIRECTORY:
+      fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+      fc.setDialogType(JFileChooser.OPEN_DIALOG);
+      fc.setDialogTitle(i18n.getMsg("open-server-location-dialog-title"));
+      break;
+
+    case OPEN_LDIF_FILE:
+      fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
+      fc.setDialogType(JFileChooser.OPEN_DIALOG);
+      fc.setDialogTitle(i18n.getMsg("open-ldif-file-dialog-title"));
+      ExtensionFileFilter ldifFiles =
+          new ExtensionFileFilter("ldif",
+              i18n.getMsg("ldif-files-description"));
+
+      fc.addChoosableFileFilter(ldifFiles);
+      fc.setFileFilter(ldifFiles);
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknown BrowseType: " + type);
+    }
+  }
+
+  /**
+   * ActionListener implementation. It will display a file browser dialog and
+   * then will update the text component if the user selects something on the
+   * dialog.
+   *
+   * @param e the ActionEvent we receive.
+   *
+   */
+  public void actionPerformed(ActionEvent e)
+  {
+    int returnVal;
+
+    /* If we can get the current field parent directory set to it */
+    String path = field.getText();
+    if (path != null)
+    {
+      if (path.trim().length() > 0)
+      {
+        File f = new File(path);
+        while ((f != null) && !f.isDirectory())
+        {
+          f = f.getParentFile();
+        }
+        if (f != null)
+        {
+          fc.setCurrentDirectory(f);
+        }
+      }
+    }
+
+    switch (type)
+    {
+    case LOCATION_DIRECTORY:
+      returnVal = fc.showSaveDialog(parent);
+      break;
+
+    case OPEN_LDIF_FILE:
+      returnVal = fc.showOpenDialog(parent);
+      break;
+
+    default:
+      throw new IllegalStateException("Unknown type: " + type);
+    }
+
+    if (returnVal == JFileChooser.APPROVE_OPTION)
+    {
+      File file = fc.getSelectedFile();
+      field.setText(file.getAbsolutePath());
+      field.requestFocusInWindow();
+      field.selectAll();
+    }
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/ButtonActionListener.java b/opends/src/quicksetup/org/opends/quicksetup/event/ButtonActionListener.java
new file mode 100644
index 0000000..9ae9cb0
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/ButtonActionListener.java
@@ -0,0 +1,43 @@
+/*
+ * 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.event;
+
+/**
+ * Interface used for the actions that are done in the wizard buttons (those
+ * specified in org.opends.quicksetup.ButtonName).
+ *
+ */
+public interface ButtonActionListener
+{
+  /**
+   * Method called when the user clicks on one of the buttons specifid in
+   * org.opends.quicksetup.ButtonName.
+   * @param event the button event
+   */
+  public void buttonActionPerformed(ButtonEvent event);
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/ButtonEvent.java b/opends/src/quicksetup/org/opends/quicksetup/event/ButtonEvent.java
new file mode 100644
index 0000000..e0fc9d8
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/ButtonEvent.java
@@ -0,0 +1,64 @@
+/*
+ * 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.event;
+
+import java.util.EventObject;
+
+import org.opends.quicksetup.ButtonName;
+
+/**
+ * The event that is generated when the user clicks in one of the wizard buttons
+ * specified in org.opends.quicksetup.ButtonName.
+ *
+ */
+public class ButtonEvent extends EventObject
+{
+  private static final long serialVersionUID = -4411929136433332009L;
+
+  private ButtonName buttonName;
+
+  /**
+   * Constructor.
+   * @param source the button that generated the event
+   * @param buttonName the button name.
+   */
+  public ButtonEvent(Object source, ButtonName buttonName)
+  {
+    super(source);
+    this.buttonName = buttonName;
+  }
+
+  /**
+   * Gets the ButtonName of the button that generated the event.
+   * @return the ButtonName of the button that generated the event.
+   */
+  public ButtonName getButtonName()
+  {
+    return buttonName;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/MinimumSizeComponentListener.java b/opends/src/quicksetup/org/opends/quicksetup/event/MinimumSizeComponentListener.java
new file mode 100644
index 0000000..76dec7c
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/MinimumSizeComponentListener.java
@@ -0,0 +1,131 @@
+/*
+ * 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.event;
+
+import java.awt.Component;
+import java.awt.Window;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+
+/**
+ * This class is used to not allowing the user to reduce the size of a component
+ * below a certain size.  When we want to set a minimum size on an object we
+ * just create the object and then we add it as ComponentListener of the object.
+ *
+ * This is used basically by the QuickSetupDialog dialog.
+ *
+ */
+public class MinimumSizeComponentListener implements ComponentListener
+{
+  private Component comp;
+
+  private int minWidth;
+
+  private int minHeight;
+
+  /**
+   * Constructor for the MinimumSizeComponentListener.
+   *
+   * @param comp the component for which we want to set a minimum size
+   * @param minWidth the minimum width for the component
+   * @param minHeight the minimum height for the component
+   */
+  public MinimumSizeComponentListener(Component comp, int minWidth,
+      int minHeight)
+  {
+    this.comp = comp;
+    this.minWidth = minWidth + 2;
+    // It seems that we must add two points to the minWidth (the border of
+    // the frame)
+    if (comp instanceof Window)
+    {
+      this.minWidth += 2;
+    }
+
+    this.minHeight = minHeight;
+  }
+
+  /**
+   * ComponentListener implementation.
+   *
+   * When the method is called check the size and if it is below the minimum
+   * size specified in the constructor, resize it to the minimum size.
+   *
+   * @param ev the component event.
+   */
+  public void componentResized(ComponentEvent ev)
+  {
+    int width = comp.getWidth();
+    int height = comp.getHeight();
+    boolean resize = false;
+    if (width < minWidth)
+    {
+      resize = true;
+      width = minWidth;
+    }
+    if (height < minHeight)
+    {
+      resize = true;
+      height = minHeight;
+    }
+    if (resize)
+    {
+      comp.setSize(width, height);
+    }
+  }
+
+  /**
+   * ComponentListener implementation.
+   *
+   * Empty implementation.
+   * @param ev the component event.
+   */
+  public void componentMoved(ComponentEvent ev)
+  {
+  }
+
+  /**
+   * ComponentListener implementation.
+   *
+   * Empty implementation.
+   * @param ev the component event.
+   */
+  public void componentShown(ComponentEvent ev)
+  {
+  }
+
+  /**
+   * ComponentListener implementation.
+   *
+   * Empty implementation.
+   * @param ev the component event.
+   */
+  public void componentHidden(ComponentEvent ev)
+  {
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java b/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
new file mode 100644
index 0000000..f3c0e69
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
@@ -0,0 +1,107 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.event;
+
+import org.opends.quicksetup.installer.InstallProgressStep;
+
+/**
+ * The event that is generated when there is a change during the installation
+ * 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).
+ *
+ */
+public class ProgressUpdateEvent
+{
+  private InstallProgressStep step;
+
+  private Integer progressRatio;
+
+  private String currentPhaseSummary;
+
+  private String newLogs;
+
+  /**
+   * Constructor of the ProgressUpdateEvent.
+   * @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
+   * the whole installation has been completed.
+   * @param currentPhaseSummary the localized summary message for the
+   * current installation progress.
+   * @param newLogs the new log messages that we have for the installation.
+   */
+  public ProgressUpdateEvent(InstallProgressStep step,
+      Integer progressRatio, String currentPhaseSummary, String newLogs)
+  {
+    this.step = step;
+    this.progressRatio = progressRatio;
+    this.currentPhaseSummary = currentPhaseSummary;
+    this.newLogs = newLogs;
+  }
+
+  /**
+   * Gets a localized message summary describing the install progress
+   * status.
+   * @return the localized message summary describing the progress status.
+   */
+  public String getCurrentPhaseSummary()
+  {
+    return currentPhaseSummary;
+  }
+
+  /**
+   * Gets the new logs for the install progress.
+   * @return the new logs for the current install progress.
+   */
+  public String getNewLogs()
+  {
+    return newLogs;
+  }
+
+  /**
+   * Gets the progress ratio for the install progress.
+   * @return the progress ratio for the install progress.
+   */
+  public Integer getProgressRatio()
+  {
+    return progressRatio;
+  }
+
+  /**
+   * Gets the current progress step.
+   * @return the current progress step.
+   */
+  public InstallProgressStep getProgressStep()
+  {
+    return step;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java b/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
new file mode 100644
index 0000000..5556a63
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
@@ -0,0 +1,44 @@
+/*
+ * 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.event;
+
+/**
+ * Interface that implement the objects that want to receive notifications of
+ * updates in the installation progress.
+ *
+ */
+public interface ProgressUpdateListener
+{
+  /**
+   * Method called when an update in the installation progress occurs.
+   *
+   * @param ev the ProgressUpdateEvent describing the update that occurred in
+   * the installation progress.
+   */
+  public void progressUpdate(ProgressUpdateEvent ev);
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java b/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
new file mode 100644
index 0000000..0d90ee8
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
@@ -0,0 +1,202 @@
+/*
+ * 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.i18n;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to retrieve localized messages from Resources.properties
+ * files.  The locale used currently is the default Locale of the JVM.
+ *
+ */
+public class ResourceProvider
+{
+  private ResourceBundle bundle;
+
+  private static ResourceProvider instance;
+
+  private static final String BUNDLE_NAME =
+      "org.opends.quicksetup.resources.Resources";
+
+  private ResourceProvider()
+  {
+  }
+
+  /**
+   * Provides an instance of the ResourceProvider.  The instance is unique for
+   * this process (which implies that during the process lifetime we can only
+   * have messages in one language).
+   *
+   * @return an instance of ResourceProvider.
+   */
+  public static ResourceProvider getInstance()
+  {
+    if (instance == null)
+    {
+      instance = new ResourceProvider();
+    }
+    return instance;
+  }
+
+  /**
+   * Gets a localized message for a key value.  In  the properties file we have
+   * something of type:
+   * key=value
+   * @param key the key in the properties file.
+   * @return the value associated to the key in the properties file.
+   * @throws IllegalArgumentException if the key could not be found in the
+   * properties file.
+   */
+  public String getMsg(String key) throws IllegalArgumentException
+  {
+    String msg;
+    try
+    {
+      msg = getResourceBundle().getString(key);
+
+    } catch (java.util.MissingResourceException e)
+    {
+      // The less brutal alternative here is to do msg = key instead
+      // of
+      // throwing an exception but this helps being strict with
+      // resources
+      // (so I prefer to keep it as it is at least at the beginning)
+      throw new IllegalArgumentException("Unknown Resource Bundle key: " +
+          key);
+    }
+    return msg;
+  }
+
+  /**
+   * Gets 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".
+   *
+   * @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.
+   * @throws IllegalArgumentException if the key could not be found in the
+   * properties file.
+   */
+  public String getMsg(String key, String[] args)
+  throws IllegalArgumentException
+  {
+    String msg;
+    try
+    {
+      String pattern = getResourceBundle().getString(key);
+      MessageFormat mf = new MessageFormat(pattern);
+
+      msg = mf.format(args);
+    } catch (java.util.MissingResourceException e)
+    {
+      // The less brutal alternative here is to do msg = key instead
+      // of
+      // throwing an exception but this helps being strict with
+      // resources
+      // (so I prefer to keep it as it is at least at the beginning)
+      throw new IllegalArgumentException("Unknown Resource Bundle key: " +
+          key);
+    }
+
+    return msg;
+  }
+
+  /**
+   * Indicates which is the Locale that will be used to determine the language
+   * of the messages.
+   *
+   * @return the Locale that will be used to determine the language of
+   * the messages.
+   */
+  public Locale getLocale()
+  {
+    return Locale.getDefault();
+  }
+
+  /**
+   * The ResourceBundle that will be used to get the localized messages.
+   * @return the ResourceBundle that will be used to get the localized
+   * messages.
+   */
+  private ResourceBundle getResourceBundle()
+  {
+    if (bundle == null)
+    {
+      try
+      {
+        if (Utils.isWebStart())
+        {
+          /*
+           * Construct a URLClassLoader using only the jar of quicksetup.jar
+           * when we are using Web Start. If we use the current classloader all
+           * the jars (including those marked as lazy) will be downloaded.
+           */
+          URL[] urls = new URL[]
+            { getQuickSetupJarURL() };
+          bundle =
+              ResourceBundle.getBundle(BUNDLE_NAME, getLocale(),
+                  new URLClassLoader(urls));
+        } else
+        {
+          bundle =
+              ResourceBundle.getBundle(BUNDLE_NAME, getLocale(), this
+                  .getClass().getClassLoader());
+        }
+      } catch (java.util.MissingResourceException e)
+      {
+        throw new IllegalStateException("Missing Resource Bundle: "
+            + BUNDLE_NAME);
+
+      }
+    }
+
+    return bundle;
+  }
+
+  /**
+   * Returns the URL of the Jar file that was used to retrieve this class.
+   * @return the URL of the Jar file that was used to retrieve this class.
+   */
+  private URL getQuickSetupJarURL()
+  {
+    return this.getClass().getProtectionDomain().getCodeSource().getLocation();
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.gif b/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.gif
new file mode 100644
index 0000000..668c644
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.png b/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.png
new file mode 100644
index 0000000..925ca3d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/error.gif b/opends/src/quicksetup/org/opends/quicksetup/images/error.gif
new file mode 100644
index 0000000..c217b20
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/error.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/information.gif b/opends/src/quicksetup/org/opends/quicksetup/images/information.gif
new file mode 100644
index 0000000..3e39ea0
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/information.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opendsbackground.png b/opends/src/quicksetup/org/opends/quicksetup/images/opendsbackground.png
new file mode 100644
index 0000000..d911533
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opendsbackground.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimized.gif b/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimized.gif
new file mode 100644
index 0000000..e6a1fc0
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimized.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimizedmac.png b/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimizedmac.png
new file mode 100644
index 0000000..7e8c236
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimizedmac.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opendssplash.png b/opends/src/quicksetup/org/opends/quicksetup/images/opendssplash.png
new file mode 100644
index 0000000..5237a7a
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opendssplash.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/warning.gif b/opends/src/quicksetup/org/opends/quicksetup/images/warning.gif
new file mode 100644
index 0000000..42cc02d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/warning.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif b/opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif
new file mode 100755
index 0000000..8c002bf
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/DataOptions.java b/opends/src/quicksetup/org/opends/quicksetup/installer/DataOptions.java
new file mode 100644
index 0000000..5b37cd6
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/DataOptions.java
@@ -0,0 +1,142 @@
+/*
+ * 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.installer;
+
+/**
+ * This class is used to provide a data model for the Data Options panel of the
+ * installer.
+ *
+ */
+public class DataOptions
+{
+  /**
+   * This enumeration is used to know what the user wants to do for the data
+   * (import data or not, what use as source of the data...).
+   *
+   */
+  public enum Type
+  {
+    /**
+     * Create base entry.
+     */
+    CREATE_BASE_ENTRY,
+    /**
+     * Do not add any entry to the suffix.
+     */
+    LEAVE_DATABASE_EMPTY,
+    /**
+     * Import data from an LDIF file.
+     */
+    IMPORT_FROM_LDIF_FILE,
+    /**
+     * Generate data and import it to the suffix.
+     */
+    IMPORT_AUTOMATICALLY_GENERATED_DATA
+  }
+
+  private Type type;
+
+  private String baseDn;
+
+  private String ldifPath;
+
+  private int numberEntries;
+
+  /**
+   * Constructor for the DataOptions object.
+   *
+   * If the Data Options is IMPORT_FROM_LDIF_FILE the args are the baseDn and
+   * a String with the ldif location.
+   *
+   * If the Data Options is IMPORT_AUTOMATICALLY_GENERATED_DATA the args
+   * are the baseDn and an Integer with the number of entries.
+   *
+   * For the rest of the types the args are just the baseDn.
+   *
+   * @param type the Type of DataOptions.
+   * @param args the different argument objects (depending on the Type
+   * specified)
+   */
+  public DataOptions(Type type, Object... args)
+  {
+    this.type = type;
+    baseDn = (String) args[0];
+
+    switch (type)
+    {
+    case IMPORT_FROM_LDIF_FILE:
+      ldifPath = (String) args[1];
+      break;
+
+    case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+      numberEntries = ((Integer) args[1]).intValue();
+      break;
+    }
+  }
+
+  /**
+   * Returns the type of DataOptions represented by this object (import data or
+   * not, what use as source of the data...).
+   *
+   * @return the type of DataOptions.
+   */
+  public Type getType()
+  {
+    return type;
+  }
+
+  /**
+   * Returns the path of the LDIF file used to import data.
+   * @return the path of the LDIF file used to import data.
+   */
+  public String getLDIFPath()
+  {
+    return ldifPath;
+  }
+
+  /**
+   * Returns the number of entries that will be automatically generated.
+   *
+   * @return the number of entries that will be automatically generated.
+   */
+  public int getNumberEntries()
+  {
+    return numberEntries;
+  }
+
+  /**
+   * Returns the base DN of the suffix that will be created in the server.
+   *
+   * @return the base DN of the suffix that will be created in the server.
+   */
+  public String getBaseDn()
+  {
+    return baseDn;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java b/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java
new file mode 100644
index 0000000..c3d9dcf
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java
@@ -0,0 +1,82 @@
+/*
+ * 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.installer;
+
+/**
+ * This is an enumeration used to identify the different fields that we have
+ * in the Installation wizard.
+ *
+ * Note that each field is not necessarily associated
+ * with a single Swing component (for instance we have two text fields for
+ * the server location).  This enumeration is used to retrieve information from
+ * the panels without having any knowledge of the actual graphical layout.
+ *
+ */
+public enum FieldName
+{
+  /**
+   * The value associated with this is a String.
+   */
+  SERVER_LOCATION,
+  /**
+   * The value associated with this is a String.
+   */
+  SERVER_PORT,
+  /**
+   * The value associated with this is a String.
+   */
+  DIRECTORY_MANAGER_DN,
+  /**
+   * The value associated with this is a String.
+   */
+  DIRECTORY_MANAGER_PWD,
+  /**
+   * The value associated with this is a String.
+   */
+  DIRECTORY_MANAGER_PWD_CONFIRM,
+  /**
+   * The value associated with this is a String.
+   */
+  DIRECTORY_BASE_DN, // the value associated with this is a String
+  /**
+   * The value associated with this is a DataOptions.Type.
+   */
+  DATA_OPTIONS,
+  /**
+   * The value associated with this is a String.
+   */
+  LDIF_PATH,
+  /**
+   * The value associated with this is a String.
+   */
+  NUMBER_ENTRIES,
+  /**
+   * The value associated with this is a Boolean.
+   */
+  SERVER_START
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java
new file mode 100644
index 0000000..6642d4e
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java
@@ -0,0 +1,107 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+/**
+ * This exception is used to encapsulate all the error that we might have
+ * during the installation.
+ *
+ * @see Installer, WebStartInstaller, OfflineInstaller.
+ *
+ */
+public class InstallException extends Exception
+{
+  private static final long serialVersionUID = -3527273444231560341L;
+
+  private Type type;
+
+  /**
+   * This enum contains the different type of InstallException that we can
+   * have.
+   *
+   */
+  public enum Type
+  {
+    /**
+     * Error related to file system error: IOException writing files, permission
+     * errors, etc.
+     */
+    FILE_SYSTEM_ERROR,
+    /**
+     * Error downloading jar files from web start server.  This is specific
+     * to the web start installation.
+     */
+    DOWNLOAD_ERROR,
+    /**
+     * Error during the configuration of the Directory Server.
+     */
+    CONFIGURATION_ERROR,
+    /**
+     * Error during the import of data (base entry, from LDIF file or
+     * automatically generated data).
+     */
+    IMPORT_ERROR,
+    /**
+     * Error starting the Open DS server.
+     */
+    START_ERROR,
+    /**
+     * A bug (for instance when we throw an IllegalStateException).
+     */
+    BUG
+  };
+
+  /**
+   * The constructor of the InstallException.
+   * @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 InstallException(Type type, String localizedMsg, Exception 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/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressDescriptor.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressDescriptor.java
new file mode 100644
index 0000000..e87340f
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressDescriptor.java
@@ -0,0 +1,108 @@
+/*
+ * 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.installer;
+
+/**
+ * This class is used to describe the current state of the installation.
+ * It contains the step in which the installation is, the current progress
+ * ratio, the progress bar message and the details message (the logs).
+ *
+ * This class is used directly by the ProgressPanel to update its content
+ * and has been designed to match the layout of that panel.  However as it
+ * does not contain any dependency in terms of code with any Swing or UI package
+ * component it has been decided to leave it on the installer package.
+ *
+ * In general the progress bar message and the details messages (log) are in
+ * HTML form (but this class is independent of the format we use for the
+ * messages).
+ *
+ */
+public class InstallProgressDescriptor
+{
+  private InstallProgressStep step;
+
+  private Integer progressBarRatio;
+
+  private String progressBarMsg;
+
+  private String detailsMsg;
+
+  /**
+   * Constructor for the InstallProgressDescriptor.
+   * @param step the current install step.
+   * @param progressBarRatio the completed progress ratio (in percentage).
+   * @param progressBarMsg the message to be displayed in the progress bar.
+   * @param detailsMsg the logs.
+   */
+  public InstallProgressDescriptor(InstallProgressStep step,
+      Integer progressBarRatio, String progressBarMsg, String detailsMsg)
+  {
+    this.step = step;
+    this.progressBarRatio = progressBarRatio;
+    this.progressBarMsg = progressBarMsg;
+    this.detailsMsg = detailsMsg;
+  }
+
+  /**
+   * Returns the details message (the log message) of the install.
+   * @return the details message (the log message) of the install.
+   */
+  public String getDetailsMsg()
+  {
+    return detailsMsg;
+  }
+
+  /**
+   * Returns the progress bar message.
+   * @return the progress bar message.
+   */
+  public String getProgressBarMsg()
+  {
+    return progressBarMsg;
+  }
+
+  /**
+   * Returns the progress bar ratio (the percentage of the install that is
+   * completed).
+   * @return the progress bar ratio (the percentage of the install that is
+   * completed).
+   */
+  public Integer getProgressBarRatio()
+  {
+    return progressBarRatio;
+  }
+
+  /**
+   * Returns the step of the install on which we are.
+   * @return the step of the install on which we are.
+   */
+  public InstallProgressStep getProgressStep()
+  {
+    return step;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java
new file mode 100644
index 0000000..0855f0d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java
@@ -0,0 +1,78 @@
+/*
+ * 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.installer;
+
+/**
+ * This enumeration describes the different installation steps in which we can
+ * be.
+ */
+public enum InstallProgressStep
+{
+  /**
+   * Install not started.
+   */
+  NOT_STARTED,
+  /**
+   * Downloading the remote jar files (this step is specific to the Web Start
+   * installation).
+   */
+  DOWNLOADING,
+  /**
+   * Extracting the zip file (this step is specific to the Web Start
+   * installation).
+   */
+  EXTRACTING,
+  /**
+   * Configuring server.
+   */
+  CONFIGURING_SERVER,
+  /**
+   * Creating base entry for the suffix.
+   */
+  CREATING_BASE_ENTRY,
+  /**
+   * Importing the contents of an LDIF file into the suffix.
+   */
+  IMPORTING_LDIF,
+  /**
+   * Importing generated data into the suffix.
+   */
+  IMPORTING_AUTOMATICALLY_GENERATED,
+  /**
+   * Starting Open DS server.
+   */
+  STARTING_SERVER,
+  /**
+   * Installation finished successfully.
+   */
+  FINISHED_SUCCESSFULLY,
+  /**
+   * Installation finished with an error.
+   */
+  FINISHED_WITH_ERROR
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
new file mode 100644
index 0000000..12110c7
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -0,0 +1,1429 @@
+/*
+ * 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.installer;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.opends.quicksetup.event.ProgressUpdateEvent;
+import org.opends.quicksetup.event.ProgressUpdateListener;
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is an abstract class that is in charge of actually performing the
+ * installation.
+ *
+ * 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.
+ *
+ * This class is supposed to be fully independent of the graphical layout.
+ * However it is the most appropriate part of the code to generate well
+ * formatted messages.  So it generates HTML messages in the
+ * ProgressUpdateEvent and to do so uses the UIFactory method.
+ *
+ * TODO pass an object in the constructor that would generate the messages.
+ * The problem of this approach is that the resulting interface of this object
+ * may be quite complex and could impact the lisibility of the code.
+ *
+ */
+public abstract class Installer
+{
+  /**
+   * The path to the Configuration LDIF file.
+   */
+  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 UserInstallData userData;
+
+  private String doneHtml;
+
+  /**
+   * The line break in HTML.
+   */
+  protected static String LINE_BREAK = "<br>";
+
+  /**
+   * The space in HTML.
+   */
+  protected static String SPACE = "&nbsp;";
+
+  /**
+   * Constructor to be used by the subclasses.
+   * @param userData the user data definining the parameters of the
+   * installation.
+   */
+  protected Installer(UserInstallData userData)
+  {
+    this.userData = userData;
+  }
+
+  /**
+   * Adds a ProgressUpdateListener that will be notified of updates in the
+   * install progress.
+   * @param l the ProgressUpdateListener to be added.
+   */
+  public void addProgressUpdateListener(ProgressUpdateListener l)
+  {
+    listeners.add(l);
+  }
+
+  /**
+   * Removes a ProgressUpdateListener.
+   * @param l the ProgressUpdateListener to be removed.
+   */
+  public void removeProgressUpdateListener(ProgressUpdateListener l)
+  {
+    listeners.remove(l);
+  }
+
+  /**
+   * Returns whether the installer has finished or not.
+   * @return <CODE>true</CODE> if the install is finished or <CODE>false
+   * </CODE> if not.
+   */
+  public boolean isFinished()
+  {
+    return getStatus() == InstallProgressStep.FINISHED_SUCCESSFULLY
+        || getStatus() == InstallProgressStep.FINISHED_WITH_ERROR;
+  }
+
+  /**
+   * Start the installation process.  This method will not block the thread on
+   * which is invoked.
+   */
+  public abstract void start();
+
+  /**
+   * An static String that contains the class name of ConfigFileHandler.
+   */
+  protected static final String CONFIG_CLASS_NAME =
+      "org.opends.server.extensions.ConfigFileHandler";
+
+
+  /**
+   * Returns the UserInstallData object representing the parameters provided by
+   * the user to do the installation.
+   *
+   * @return the UserInstallData object representing the parameters provided
+   * by the user to do the installation.
+   */
+  protected UserInstallData getUserData()
+  {
+    return userData;
+  }
+
+  /**
+   * This method notifies the ProgressUpdateListeners 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.
+   * @param newLogDetail the new log messages that we have for the
+   * installation in HTML form.
+   */
+  protected void notifyListeners(Integer ratio, String currentPhaseSummary,
+      String newLogDetail)
+  {
+    ProgressUpdateEvent ev =
+        new ProgressUpdateEvent(getStatus(), ratio, currentPhaseSummary,
+            newLogDetail);
+    for (ProgressUpdateListener l : listeners)
+    {
+      l.progressUpdate(ev);
+    }
+  }
+
+  /**
+   * 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.
+   */
+  protected 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.
+   */
+  protected String getMsg(String key, String[] args)
+  {
+    return getI18n().getMsg(key, args);
+  }
+
+  /**
+   * Returns a ResourceProvider instance.
+   * @return a ResourceProvider instance.
+   */
+  protected ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  /**
+   * Returns a localized message for a given properties key an exception.
+   * @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.
+   */
+  protected String getExceptionMsg(String key, Exception ex)
+  {
+    return getExceptionMsg(key, null, ex);
+  }
+
+  /**
+   * Returns a localized message for a given properties key an exception.
+   * @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.
+   *
+   * @return a localized message for a given properties key an exception.
+   */
+  protected String getExceptionMsg(String key, String[] args, Exception ex)
+  {
+    return Utils.getExceptionMsg(getI18n(), key, args, ex);
+  }
+
+  /**
+   * 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
+   * @return the HTML representation of an error for the given text.
+   */
+  protected String getHtmlError(String text)
+  {
+    String html =
+        UIFactory.getIconHtml(UIFactory.IconType.ERROR)
+            + SPACE
+            + SPACE
+            + UIFactory.applyFontToHtml(getHtml(text),
+                UIFactory.PROGRESS_ERROR_FONT);
+
+    String result = UIFactory.applyErrorBackgroundToHtml(html);
+    return result;
+  }
+
+  /**
+   * Returns the HTML representation of an 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.
+   */
+  protected String getHtmlWarning(String text)
+  {
+    String html =
+        UIFactory.getIconHtml(UIFactory.IconType.WARNING)
+            + SPACE
+            + SPACE
+            + UIFactory.applyFontToHtml(getHtml(text),
+                UIFactory.PROGRESS_WARNING_FONT);
+
+    String result = UIFactory.applyWarningBackgroundToHtml(html);
+    return result;
+  }
+
+  /**
+   * 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.
+   */
+  protected String getHtmlSuccess(String text)
+  {
+    // Note: the text we get already is in HTML form
+    String html =
+        UIFactory.getIconHtml(UIFactory.IconType.INFORMATION) + SPACE
+        + SPACE + UIFactory.applyFontToHtml(text, UIFactory.PROGRESS_FONT);
+
+    String result = UIFactory.applySuccessfulBackgroundToHtml(html);
+    return result;
+  }
+
+  /**
+   * Returns the HTML representation of a log error message for a given text.
+   * @param text the source text from which we want to get the HTML
+   * representation
+   * @return the HTML representation of a log error message for the given text.
+   */
+  protected String getHtmlLogError(String text)
+  {
+    String html = getHtml(text);
+    return UIFactory.applyFontToHtml(html,
+        UIFactory.PROGRESS_LOG_ERROR_FONT);
+  }
+
+  /**
+   * 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
+   * representation
+   * @return the HTML representation of a log message for the given text.
+   */
+  protected String getHtmlLog(String text)
+  {
+    String html = getHtml(text);
+    return UIFactory.applyFontToHtml(html, UIFactory.PROGRESS_LOG_FONT);
+  }
+
+  /**
+   * Returns the HTML representation of the 'Done' text string.
+   * @return the HTML representation of the 'Done' text string.
+   */
+  protected String getHtmlDone()
+  {
+    if (doneHtml == null)
+    {
+      String html = getHtml(getMsg("progress-done"));
+      doneHtml = UIFactory.applyFontToHtml(html,
+          UIFactory.PROGRESS_DONE_FONT);
+    }
+    return doneHtml;
+  }
+
+  /**
+   * Returns the HTML 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 <B>.....</B>'.
+   * @param text the String to which add points.
+   * @return the HTML representation of the '.....' text string.
+   */
+  protected String getHtmlWithPoints(String text)
+  {
+    String html = getHtml(text);
+    String points = SPACE + getHtml(getMsg("progress-points")) + SPACE;
+
+    StringBuffer buf = new StringBuffer();
+    buf.append(UIFactory.applyFontToHtml(html, UIFactory.PROGRESS_FONT))
+        .append(
+            UIFactory.applyFontToHtml(points, UIFactory.PROGRESS_POINTS_FONT));
+
+    return buf.toString();
+  }
+
+  /**
+   * Returns the HTML representation for a given text. without adding any kind
+   * of font or style elements.  Just escapes the problematic characters
+   * (like '<') and transform the break lines into '\n' characters.
+   *
+   * @param text the source text from which we want to get the HTML
+   * representation
+   * @return the HTML representation for the given text.
+   */
+  protected String getHtml(String text)
+  {
+    StringBuffer buffer = new StringBuffer();
+    text = text.replaceAll("\r\n", "\n");
+    String[] lines = text.split("[\n\r\u0085\u2028\u2029]");
+    for (int i = 0; i < lines.length; i++)
+    {
+      if (i != 0)
+      {
+        buffer.append("<br>");
+      }
+      buffer.append(escape(lines[i]));
+    }
+
+    return buffer.toString();
+  }
+
+  /**
+   * 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
+   * representation
+   * @return the HTML representation of a progress message for the given text.
+   */
+  protected String getHtmlProgress(String text)
+  {
+    return UIFactory.applyFontToHtml(getHtml(text),
+        UIFactory.PROGRESS_FONT);
+  }
+
+  /**
+   * Returns the HTML 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 HTML.
+   * @return the HTML representation of an error message for the given
+   * exception.
+   */
+  protected String getHtmlError(Exception ex, boolean applyMargin)
+  {
+    String openDiv = "<div style=\"margin-left:5px; margin-top:10px\">";
+    String hideText =
+        UIFactory.applyFontToHtml(getMsg("hide-exception-details"),
+            UIFactory.PROGRESS_FONT);
+    String showText =
+        UIFactory.applyFontToHtml(getMsg("show-exception-details"),
+            UIFactory.PROGRESS_FONT);
+    String closeDiv = "</div>";
+
+    StringBuffer stackBuf = new StringBuffer();
+    stackBuf.append(getHtmlStack(ex));
+    Throwable root = ex.getCause();
+    while (root != null)
+    {
+      stackBuf.append(getHtml(getMsg("exception-root-cause")) + LINE_BREAK);
+      stackBuf.append(getHtmlStack(root));
+      root = root.getCause();
+    }
+    String stackText =
+        UIFactory.applyFontToHtml(stackBuf.toString(), UIFactory.STACK_FONT);
+
+    StringBuffer buf = new StringBuffer();
+
+    String msg = ex.getMessage();
+    if (msg != null)
+    {
+      buf.append(UIFactory.applyFontToHtml(getHtml(ex.getMessage()),
+          UIFactory.PROGRESS_ERROR_FONT)
+          + LINE_BREAK);
+    } else
+    {
+      buf.append(ex.toString() + LINE_BREAK);
+    }
+    buf.append(getErrorWithStackHtml(openDiv, hideText, showText, stackText,
+        closeDiv, false));
+
+    String html =
+        UIFactory.getIconHtml(UIFactory.IconType.ERROR) + SPACE + SPACE
+            + buf.toString();
+
+    String result;
+    if (applyMargin)
+    {
+      result =
+          UIFactory.applyMargin(UIFactory.applyErrorBackgroundToHtml(html),
+              UIFactory.TOP_INSET_ERROR_MESSAGE, 0, 0, 0);
+    } else
+    {
+      result = UIFactory.applyErrorBackgroundToHtml(html);
+    }
+    return result;
+  }
+
+  /**
+   * Returns a HTML representation of the stack trace of a Throwable object.
+   * @param ex the throwable object from which we want to obtain the stack
+   * trace HTML representation.
+   * @return a HTML representation of the stack trace of a Throwable object.
+   */
+  private String getHtmlStack(Throwable ex)
+  {
+    StringBuffer buf = new StringBuffer();
+    StackTraceElement[] stack = ex.getStackTrace();
+    for (int i = 0; i < stack.length; i++)
+    {
+      buf.append(SPACE + SPACE + SPACE + SPACE + SPACE + SPACE + SPACE +
+          SPACE + SPACE + SPACE + getHtml(stack[i].toString()) + LINE_BREAK);
+    }
+    return buf.toString();
+  }
+
+  /**
+   * Returns the HTML representation of a plain text string which is obtained
+   * by converting some special characters (like '<') into its equivalent
+   * escaped HTML representation.
+   *
+   * @param rawString the String from which we want to obtain the HTML
+   * representation.
+   * @return the HTML representation of the plain text string.
+   */
+  private String escape(String rawString)
+  {
+    int toto;
+    StringBuffer buffer = new StringBuffer();
+    for (int i = 0; i < rawString.length(); i++)
+    {
+      char c = rawString.charAt(i);
+      switch (c)
+      {
+      case '<':
+        buffer.append("&lt;");
+        break;
+
+      case '>':
+        buffer.append("&gt;");
+        break;
+
+      case '&':
+        buffer.append("&amp;");
+        break;
+
+      case '"':
+        buffer.append("&quot;");
+        break;
+
+      default:
+        buffer.append(c);
+        break;
+      }
+    }
+
+    return buffer.toString();
+  }
+
+  /**
+   * Returns the HTML representation of an exception in the
+   * progress log.<BR>
+   * We can have something of type:<BR><BR>
+   *
+   * An error occurred.  java.io.IOException could not connect to server.<BR>
+   * <A HREF="">Show Details</A>
+   *
+   * When the user clicks on 'Show Details' the whole stack will be displayed.
+   *
+   * An error occurred.  java.io.IOException could not connect to server.<BR>
+   * <A HREF="">Hide Details</A><BR>
+   * ... And here comes all the stack trace representation<BR>
+   *
+   *
+   * As the object that listens to this hyperlink events is not here (it is
+   * QuickSetupStepPanel) we must include all the information somewhere.  The
+   * chosen solution is to include everything in the URL using parameters.
+   * This everything consists of:
+   * The open div tag for the text.
+   * The text that we display when we do not display the exception.
+   * The text that we display when we display the exception.
+   * The stack trace text.
+   * The closing div.
+   * A boolean informing if we are hiding the exception or not (to know in the
+   * next event what must be displayed).
+   *
+   * @param openDiv the open div tag for the text.
+   * @param hideText the text that we display when we do not display the
+   * exception.
+   * @param showText the text that we display when we display the exception.
+   * @param stackText the stack trace text.
+   * @param closeDiv the closing div.
+   * @param hide a boolean informing if we are hiding the exception or not.
+   * @return the HTML representation of an error message with an stack trace.
+   */
+  private static String getErrorWithStackHtml(String openDiv, String hideText,
+      String showText, String stackText, String closeDiv, boolean hide)
+  {
+    StringBuffer buf = new StringBuffer();
+
+    String params =
+        getUrlParams(openDiv, hideText, showText, stackText, closeDiv, hide);
+    try
+    {
+      String text = hide ? hideText : showText;
+      buf.append(openDiv + "<a href=\"http://").append(
+          URLEncoder.encode(params, "UTF-8") + "\">" + text + "</a>");
+      if (hide)
+      {
+        buf.append(LINE_BREAK + stackText);
+      }
+      buf.append(closeDiv);
+
+    } catch (UnsupportedEncodingException uee)
+    {
+      // Bug
+      throw new IllegalStateException("UTF-8 is not supported ", uee);
+    }
+
+    return buf.toString();
+  }
+
+  private static String PARAM_SEPARATOR = "&&&&";
+
+  /**
+   * Gets the url parameters of the href we construct in getErrorWithStackHtml.
+   * @see getErrorWithStackHtml
+   * @param openDiv the open div tag for the text.
+   * @param hideText the text that we display when we do not display the
+   * exception.
+   * @param showText the text that we display when we display the exception.
+   * @param stackText the stack trace text.
+   * @param closeDiv the closing div.
+   * @param hide a boolean informing if we are hiding the exception or not.
+   * @return the url parameters of the href we construct in getHrefString.
+   */
+  private static String getUrlParams(String openDiv, String hideText,
+      String showText, String stackText, String closeDiv, boolean hide)
+  {
+    StringBuffer buf = new StringBuffer();
+    buf.append(openDiv + PARAM_SEPARATOR);
+    buf.append(hideText + PARAM_SEPARATOR);
+    buf.append(showText + PARAM_SEPARATOR);
+    buf.append(stackText + PARAM_SEPARATOR);
+    buf.append(closeDiv + PARAM_SEPARATOR);
+    buf.append(hide);
+    return buf.toString();
+  }
+
+  /**
+   * Returns the log HTML representation after the user has clicked on a url.
+   *
+   * @see getErrorWithStackHtml
+   * @param url that has been clicked
+   * @param lastText the HTML representation of the log before clicking on the
+   * url.
+   * @return the log HTML representation after the user has clicked on a url.
+   */
+  public static String getHtmlAfterUrlClick(String url, String lastText)
+  {
+    String urlText = getErrorWithStackHtml(url, false);
+    String newUrlText = getErrorWithStackHtml(url, true);
+
+    int index = lastText.indexOf(urlText);
+    if (index == -1)
+    {
+      System.out.println("lastText: " + lastText);
+      System.out.println("does not contain: " + urlText);
+    } else
+    {
+      lastText =
+          lastText.substring(0, index) + newUrlText
+              + lastText.substring(index + urlText.length());
+    }
+    return lastText;
+  }
+
+  /**
+   * Returns the HTML representation of an exception in the
+   * progress log for a given url.
+   * @see getHrefString
+   * @param url the url containing all the information required to retrieve
+   * the HTML representation.
+   * @param inverse indicates whether we want to 'inverse' the representation
+   * or not.  For instance if the url specifies that the stack is being hidden
+   * and this parameter is <CODE>true</CODE> the resulting HTML will display
+   * the stack.
+   * @return the HTML representation of an exception in the progress log for a
+   * given url.
+   */
+  private static String getErrorWithStackHtml(String url, boolean inverse)
+  {
+    String p = url.substring("http://".length());
+    try
+    {
+      p = URLDecoder.decode(p, "UTF-8");
+    } catch (UnsupportedEncodingException uee)
+    {
+      // Bug
+      throw new IllegalStateException("UTF-8 is not supported ", uee);
+    }
+    String params[] = p.split(PARAM_SEPARATOR);
+    int i = 0;
+    String openDiv = params[i++];
+    String hideText = params[i++];
+    String showText = params[i++];
+    String stackText = params[i++];
+    String closeDiv = params[i++];
+    boolean isHide = new Boolean(params[i]);
+
+    if (isHide)
+    {
+      return getErrorWithStackHtml(openDiv, hideText, showText, stackText,
+          closeDiv, !inverse);
+    } else
+    {
+      return getErrorWithStackHtml(openDiv, hideText, showText, stackText,
+          closeDiv, inverse);
+    }
+  }
+
+  /**
+   * Creates a template file based in the contents of the UserData object.
+   * This template file is used to generate automatically data.  To generate
+   * the template file the code will basically take into account the value of
+   * the base dn and the number of entries to be generated.
+   *
+   * @return the file object pointing to the create template file.
+   * @throws InstallException if an error occurs.
+   */
+  protected File createTemplateFile() throws InstallException
+  {
+    File templateFile = null;
+    String baseDn = getUserData().getDataOptions().getBaseDn();
+    int nEntries = getUserData().getDataOptions().getNumberEntries();
+    try
+    {
+      templateFile = File.createTempFile("opends-template-file", ".template");
+      templateFile.deleteOnExit();
+    } catch (IOException ioe)
+    {
+      String failedMsg = getExceptionMsg("error-creating-temp-file", null, ioe);
+      throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+          failedMsg, ioe);
+    }
+
+    StringBuffer buf = new StringBuffer();
+    buf.append("define suffix=" + baseDn);
+    if (nEntries > 0)
+    {
+      buf.append("\ndefine numusers=" + nEntries);
+    }
+
+    buf.append("\n").append("\nbranch: [suffix]").append("\n");
+    buf.append("\nbranch: ou=People,[suffix]");
+
+    if (nEntries > 0)
+    {
+      buf.append("\nsubordinateTemplate: person:[numusers]")
+      .append("\n")
+          .append("\ntemplate: person")
+          .append("\nrdnAttr: uid")
+          .append("\nobjectClass: top")
+          .append("\nobjectClass: person")
+          .append("\nobjectClass: organizationalPerson")
+          .append("\nobjectClass: inetOrgPerson")
+          .append("\ngivenName: <first>")
+          .append("\nsn: <last>")
+          .append("\ncn: {givenName} {sn}")
+          .append("\ninitials: {givenName:1}")
+          .append("<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}")
+          .append("\nemployeeNumber: <sequential:0>")
+          .append("\nuid: user.{employeeNumber}")
+          .append("\nmail: {uid}@maildomain.net")
+          .append("\nuserPassword: password")
+          .append("\ntelephoneNumber: <random:telephone>")
+          .append("\nhomePhone: <random:telephone>")
+          .append("\npager: <random:telephone>")
+          .append("\nmobile: <random:telephone>")
+          .append("\nstreet: <random:numeric:5> <file:streets> Street")
+          .append("\nl: <file:cities>")
+          .append("\nst: <file:states>")
+          .append("\npostalCode: <random:numeric:5>")
+          .append("\npostalAddress: {cn}${street}${l}, {st}  {postalCode}")
+          .append("\ndescription: This is the description for {cn}.");
+    }
+
+    String path = templateFile.getAbsolutePath();
+    try
+    {
+      Utils.createFile(path, buf.toString());
+    } catch (IOException ioe)
+    {
+      String[] arg =
+        { path };
+      String failedMsg =
+          getExceptionMsg("error-writing-to-temp-file", arg, ioe);
+      throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+          failedMsg, ioe);
+    }
+
+    return templateFile;
+  }
+
+  /**
+   * This method is called when a new log message has been received.  It will
+   * notify the ProgressUpdateListeners of this fact.
+   * @param newLogDetail the new log detail.
+   */
+  protected void notifyListeners(String newLogDetail)
+  {
+    Integer ratio = getRatio(getStatus());
+    String currentPhaseSummary = getSummary(getStatus());
+    notifyListeners(ratio, currentPhaseSummary, newLogDetail);
+  }
+
+  /**
+   * Returns the current InstallProgressStep of the installation process.
+   * @return the current InstallProgressStep of the installation process.
+   */
+  protected abstract InstallProgressStep getStatus();
+
+  /**
+   * Returns an integer that specifies which percentage of the whole
+   * installation has been completed.
+   * @param step the InstallProgressStep for which we want to get the ratio.
+   * @return an integer that specifies which percentage of the whole
+   * installation has been completed.
+   */
+  protected abstract Integer getRatio(InstallProgressStep step);
+
+  /**
+   * Returns an HTML 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
+   * InstallProgressStep.
+   */
+  protected abstract String getSummary(InstallProgressStep step);
+
+  /**
+   * 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.
+   *
+   */
+  abstract class StartReader
+  {
+    private InstallException ex;
+
+    private boolean isFinished;
+
+    private boolean isFirstLine;
+
+    /**
+     * The protected constructor.
+     * @param reader the BufferedReader of the start process.
+     * @param startedId the message ID that this class can use to know whether
+     * the start is over or not.
+     * @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,
+        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(LINE_BREAK);
+              }
+              if (isError)
+              {
+                buf.append(getHtmlLogError(line));
+              } else
+              {
+                buf.append(getHtmlLog(line));
+              }
+              notifyListeners(buf.toString());
+              isFirstLine = false;
+
+              if (line.indexOf("id=" + startedId) != -1)
+              {
+                isFinished = true;
+              }
+              line = reader.readLine();
+            }
+          } catch (IOException ioe)
+          {
+            String errorMsg = getExceptionMsg(errorTag, ioe);
+            ex =
+                new InstallException(InstallException.Type.START_ERROR,
+                    errorMsg, ioe);
+
+          } catch (RuntimeException re)
+          {
+            String errorMsg = getExceptionMsg(errorTag, re);
+            ex =
+                new InstallException(InstallException.Type.START_ERROR,
+                    errorMsg, re);
+          }
+          isFinished = true;
+        }
+      });
+      t.start();
+    }
+
+    /**
+     * Returns the InstallException that occurred reading the Start 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 InstallException getException()
+    {
+      return ex;
+    }
+
+    /**
+     * Returns <CODE>true</CODE> if the server starting process finished
+     * (successfully or not) and <CODE>false</CODE> otherwise.
+     * @return <CODE>true</CODE> if the server starting process finished
+     * (successfully or not) and <CODE>false</CODE> otherwise.
+     */
+    public boolean isFinished()
+    {
+      return isFinished;
+    }
+  }
+
+  /**
+   * 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.
+   *
+   * 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.
+   *
+   */
+  protected class ErrorPrintStream extends PrintStream
+  {
+    private boolean isFirstLine;
+
+    /**
+     * Default constructor.
+     *
+     */
+    public ErrorPrintStream()
+    {
+      super(new ByteArrayOutputStream(), true);
+      isFirstLine = true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void println(String msg)
+    {
+      if (isFirstLine)
+      {
+        notifyListeners(getHtmlLogError(msg));
+      } else
+      {
+        notifyListeners(LINE_BREAK + getHtmlLogError(msg));
+      }
+      isFirstLine = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void write(byte[] b, int off, int len)
+    {
+      if (b == null)
+      {
+        throw new NullPointerException("b is null");
+      }
+
+      if (off + len > b.length)
+      {
+        throw new IndexOutOfBoundsException(
+            "len + off are bigger than the length of the byte array");
+      }
+      println(new String(b, off, len));
+    }
+  }
+
+  /**
+   * 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.
+   *
+   * 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.
+   *
+   */
+  protected class OutputPrintStream extends PrintStream
+  {
+    private boolean isFirstLine;
+
+    /**
+     * Default constructor.
+     *
+     */
+    public OutputPrintStream()
+    {
+      super(new ByteArrayOutputStream(), true);
+      isFirstLine = true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void println(String msg)
+    {
+      if (isFirstLine)
+      {
+        notifyListeners(getHtmlLog(msg));
+      } else
+      {
+        notifyListeners(LINE_BREAK + getHtmlLog(msg));
+      }
+      isFirstLine = false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void write(byte[] b, int off, int len)
+    {
+      if (b == null)
+      {
+        throw new NullPointerException("b is null");
+      }
+
+      if (off + len > b.length)
+      {
+        throw new IndexOutOfBoundsException(
+            "len + off are bigger than the length of the byte array");
+      }
+
+      println(new String(b, off, len));
+    }
+  }
+
+  /**
+   * This methods configures the server based on the contents of the UserData
+   * object provided in the constructor.
+   * @throws InstallException if something goes wrong.
+   */
+  protected void configureServer() throws InstallException
+  {
+    notifyListeners(getHtmlWithPoints(getMsg("progress-configuring")));
+
+    ArrayList<String> argList = new ArrayList<String>();
+    argList.add("-C");
+    argList.add(CONFIG_CLASS_NAME);
+
+    argList.add("-c");
+    argList.add(getConfigFilePath());
+    argList.add("-p");
+    argList.add(String.valueOf(getUserData().getServerPort()));
+
+    argList.add("-D");
+    argList.add(getUserData().getDirectoryManagerDn());
+
+    argList.add("-w");
+    argList.add(getUserData().getDirectoryManagerPwd());
+
+    argList.add("-b");
+    argList.add(getUserData().getDataOptions().getBaseDn());
+
+    String[] args = new String[argList.size()];
+    argList.toArray(args);
+    try
+    {
+      InstallerHelper helper = new InstallerHelper();
+      int result = helper.invokeConfigureServer(args);
+
+      if (result != 0)
+      {
+        throw new InstallException(
+            InstallException.Type.CONFIGURATION_ERROR,
+            getMsg("error-configuring"), null);
+      }
+    } catch (RuntimeException re)
+    {
+      throw new InstallException(
+          InstallException.Type.CONFIGURATION_ERROR,
+          getExceptionMsg("error-configuring", null, re), re);
+    }
+  }
+
+  /**
+   * This methods creates the base entry for the suffix based on the contents of
+   * the UserData object provided in the constructor.
+   * @throws InstallException if something goes wrong.
+   */
+  protected void createBaseEntry() throws InstallException
+  {
+    String[] arg =
+      { getUserData().getDataOptions().getBaseDn() };
+    notifyListeners(getHtmlWithPoints(getMsg("progress-creating-base-entry",
+        arg)));
+
+    InstallerHelper helper = new InstallerHelper();
+    String baseDn = getUserData().getDataOptions().getBaseDn();
+    File tempFile = helper.createBaseEntryTempFile(baseDn);
+
+    ArrayList<String> argList = new ArrayList<String>();
+    argList.add("-C");
+    argList.add(CONFIG_CLASS_NAME);
+
+    argList.add("-f");
+    argList.add(getConfigFilePath());
+
+    argList.add("-n");
+    argList.add(getBackendName());
+
+    argList.add("-l");
+    argList.add(tempFile.getAbsolutePath());
+
+    argList.add("-q");
+
+    String[] args = new String[argList.size()];
+    argList.toArray(args);
+
+    try
+    {
+      int result = helper.invokeImportLDIF(args);
+
+      if (result != 0)
+      {
+        throw new InstallException(
+            InstallException.Type.CONFIGURATION_ERROR,
+            getMsg("error-creating-base-entry"), null);
+      }
+    } catch (RuntimeException re)
+    {
+      throw new InstallException(
+          InstallException.Type.CONFIGURATION_ERROR,
+          getExceptionMsg("error-creating-base-entry", null, re), re);
+    }
+
+    notifyListeners(getHtmlDone());
+  }
+
+  /**
+   * This methods imports the contents of an LDIF file based on the contents of
+   * the UserData object provided in the constructor.
+   * @throws InstallException if something goes wrong.
+   */
+  protected void importLDIF() throws InstallException
+  {
+    String[] arg =
+      { getUserData().getDataOptions().getLDIFPath() };
+    notifyListeners(getHtmlProgress(getMsg("progress-importing-ldif", arg))
+        + LINE_BREAK);
+
+    ArrayList<String> argList = new ArrayList<String>();
+    argList.add("-C");
+    argList.add(CONFIG_CLASS_NAME);
+
+    argList.add("-f");
+    argList.add(getConfigFilePath());
+    argList.add("-n");
+    argList.add(getBackendName());
+    argList.add("-l");
+    argList.add(getUserData().getDataOptions().getLDIFPath());
+
+    String[] args = new String[argList.size()];
+    argList.toArray(args);
+
+    try
+    {
+      InstallerHelper helper = new InstallerHelper();
+      int result = helper.invokeImportLDIF(args);
+
+      if (result != 0)
+      {
+        throw new InstallException(
+            InstallException.Type.CONFIGURATION_ERROR,
+            getMsg("error-importing-ldif"), null);
+      }
+    } catch (RuntimeException re)
+    {
+      throw new InstallException(
+          InstallException.Type.CONFIGURATION_ERROR,
+          getExceptionMsg("error-importing-ldif", null, re), re);
+    }
+  }
+
+  /**
+   * This methods imports automatically generated data based on the contents
+   * of the UserData object provided in the constructor.
+   * @throws InstallException if something goes wrong.
+   */
+  protected void importAutomaticallyGenerated() throws InstallException
+  {
+    File templatePath = createTemplateFile();
+    int nEntries = getUserData().getDataOptions().getNumberEntries();
+    String[] arg =
+      { String.valueOf(nEntries) };
+    notifyListeners(getHtmlProgress(getMsg(
+        "progress-import-automatically-generated", arg))
+        + LINE_BREAK);
+
+    ArrayList<String> argList = new ArrayList<String>();
+    argList.add("-C");
+    argList.add(CONFIG_CLASS_NAME);
+
+    argList.add("-f");
+    argList.add(getConfigFilePath());
+    argList.add("-n");
+    argList.add(getBackendName());
+    argList.add("-t");
+    argList.add(templatePath.getAbsolutePath());
+    argList.add("-S");
+    argList.add("0");
+
+    String[] args = new String[argList.size()];
+    argList.toArray(args);
+
+    try
+    {
+      InstallerHelper helper = new InstallerHelper();
+      int result = helper.invokeImportLDIF(args);
+
+      if (result != 0)
+      {
+        throw new InstallException(
+            InstallException.Type.CONFIGURATION_ERROR,
+            getMsg("error-import-automatically-generated"), null);
+      }
+    } catch (RuntimeException re)
+    {
+      throw new InstallException(
+          InstallException.Type.CONFIGURATION_ERROR,
+          getExceptionMsg("error-import-automatically-generated", null, re),
+          re);
+    }
+  }
+
+  /**
+   * This methods starts the server.
+   * @throws InstallException if something goes wrong.
+   */
+  protected void startServer() throws InstallException
+  {
+    notifyListeners(getHtmlProgress(getMsg("progress-starting")) + LINE_BREAK);
+
+    ArrayList<String> argList = new ArrayList<String>();
+
+    if (Utils.isWindows())
+    {
+      argList.add(Utils.getPath(getBinariesPath(), "start-ds.bat"));
+    } else
+    {
+      argList.add(Utils.getPath(getBinariesPath(), "start-ds"));
+    }
+    String[] env =
+      { "JAVA_HOME=" + System.getProperty("java.home") };
+
+    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);
+
+      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);
+
+      while (!errReader.isFinished() && !outputReader.isFinished())
+      {
+        try
+        {
+          Thread.sleep(100);
+        } catch (InterruptedException ie)
+        {
+        }
+      }
+      // Check if something wrong occurred reading the starting of the server
+      InstallException ex = errReader.getException();
+      if (ex == null)
+      {
+        ex = outputReader.getException();
+      }
+      if (ex != null)
+      {
+        throw ex;
+
+      } else
+      {
+        /*
+         * There are no exceptions from the readers and they are marked as
+         * 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.
+         */
+      }
+
+    } catch (IOException ioe)
+    {
+      throw new InstallException(InstallException.Type.START_ERROR,
+          getExceptionMsg("error-starting-server", ioe), ioe);
+    }
+  }
+
+  /**
+   * Returns the class path (using the class path separator which is platform
+   * dependent) required to run Open DS server.
+   * @return the class path required to run Open DS server.
+   */
+  protected abstract String getOpenDSClassPath();
+
+  /**
+   * Returns the config file path.
+   * @return the config file path.
+   */
+  protected abstract String getConfigFilePath();
+
+  /**
+   * Returns the path to the binaries.
+   * @return the path to the binaries.
+   */
+  protected abstract String getBinariesPath();
+
+  /**
+   * Updates the contents of the provided map with the localized summary
+   * strings.
+   * @param hmSummary the Map to be updated.
+   */
+  protected void initSummaryMap(
+      Map<InstallProgressStep, String> hmSummary)
+  {
+    hmSummary.put(InstallProgressStep.NOT_STARTED,
+        UIFactory.applyFontToHtml(
+        getMsg("summary-not-started"), UIFactory.PROGRESS_FONT));
+    hmSummary.put(InstallProgressStep.DOWNLOADING,
+        UIFactory.applyFontToHtml(
+        getMsg("summary-downloading"), UIFactory.PROGRESS_FONT));
+    hmSummary.put(InstallProgressStep.EXTRACTING,
+        UIFactory.applyFontToHtml(
+        getMsg("summary-extracting"), UIFactory.PROGRESS_FONT));
+    hmSummary.put(InstallProgressStep.CONFIGURING_SERVER,
+        UIFactory.applyFontToHtml(getMsg("summary-configuring"),
+            UIFactory.PROGRESS_FONT));
+    hmSummary.put(InstallProgressStep.CREATING_BASE_ENTRY, UIFactory
+        .applyFontToHtml(getMsg("summary-creating-base-entry"),
+            UIFactory.PROGRESS_FONT));
+    hmSummary.put(InstallProgressStep.IMPORTING_LDIF, UIFactory
+        .applyFontToHtml(getMsg("summary-importing-ldif"),
+            UIFactory.PROGRESS_FONT));
+    hmSummary.put(
+        InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
+        UIFactory.applyFontToHtml(
+            getMsg("summary-importing-automatically-generated"),
+            UIFactory.PROGRESS_FONT));
+    hmSummary.put(InstallProgressStep.STARTING_SERVER, UIFactory
+        .applyFontToHtml(getMsg("summary-starting"),
+            UIFactory.PROGRESS_FONT));
+    hmSummary.put(InstallProgressStep.FINISHED_SUCCESSFULLY, "<html>"
+        + getHtmlSuccess(getMsg("summary-finished-successfully")));
+    hmSummary.put(InstallProgressStep.FINISHED_WITH_ERROR, "<html>"
+        + getHtmlError(getMsg("summary-finished-with-error")));
+  }
+
+  /**
+   * Returns the Message ID indicating that the server has started.
+   * @return the Message ID indicating that the server has started.
+   */
+  private String getStartedId()
+  {
+    InstallerHelper helper = new InstallerHelper();
+    return helper.getStartedId();
+  }
+
+  /**
+   * Returns the default backend name (the one that will be created).
+   * @return the default backend name (the one that will be created).
+   */
+  protected String getBackendName()
+  {
+    return "userRoot";
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
new file mode 100644
index 0000000..bd333a9
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
@@ -0,0 +1,153 @@
+/*
+ * 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.installer;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.webstart.JnlpProperties;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * 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
+ * quicksetup.jar).
+ *
+ * Important note: do not include references to the classes in package
+ * org.opends.server in the import. These classes must be loaded during
+ * Runtime.
+ * The code is written in a way that when we execute the code that uses these
+ * classes the required jar files are already loaded. However these jar files
+ * are not necessarily loaded when we create this class.
+ */
+class InstallerHelper implements JnlpProperties
+{
+
+  /**
+   * Invokes the method ConfigureDS.configMain with the provided parameters.
+   * @param args the arguments to be passed to ConfigureDS.configMain.
+   * @return the return code of the ConfigureDS.configMain method.
+   * @throws InstallException if something goes wrong.
+   * @see org.opends.server.tools.ConfigureDS.configMain(args).
+   */
+  public int invokeConfigureServer(String[] args) throws InstallException
+  {
+    return org.opends.server.tools.ConfigureDS.configMain(args);
+  }
+
+  /**
+   * Invokes the method ImportLDIF.mainImportLDIF with the provided parameters.
+   * @param args the arguments to be passed to ImportLDIF.mainImportLDIF.
+   * @return the return code of the ImportLDIF.mainImportLDIF method.
+   * @throws InstallException if something goes wrong.
+   * @see org.opends.server.tools.ImportLDIF.mainImportLDIF(args).
+   */
+  public int invokeImportLDIF(String[] args) throws InstallException
+  {
+    return org.opends.server.tools.ImportLDIF.mainImportLDIF(args);
+  }
+
+  /**
+   * Returns the Message ID that corresponds to a successfully started server.
+   * @return the Message ID that corresponds to a successfully started server.
+   */
+  public String getStartedId()
+  {
+    return String.valueOf(org.opends.server.messages.CoreMessages.
+        MSGID_DIRECTORY_SERVER_STARTED);
+  }
+
+  private String getExceptionMsg(String key, Exception ex)
+  {
+    return getExceptionMsg(key, null, ex);
+  }
+
+  private String getExceptionMsg(String key, String[] args, Exception ex)
+  {
+    return Utils.getExceptionMsg(ResourceProvider.getInstance(), key, args, ex);
+  }
+
+  /**
+   * Creates a template LDIF file with an entry that has as dn the provided
+   * baseDn.
+   * @param baseDn the dn of the entry that will be created in the LDIF file.
+   * @return the File object pointing to the created temporary file.
+   * @throws InstallException if something goes wrong.
+   */
+  public File createBaseEntryTempFile(String baseDn) throws InstallException
+  {
+    File ldifFile = null;
+    try
+    {
+      ldifFile = File.createTempFile("opends-base-entry", ".ldif");
+      ldifFile.deleteOnExit();
+    } catch (IOException ioe)
+    {
+      String failedMsg = getExceptionMsg("error-creating-temp-file", null, ioe);
+      throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+          failedMsg, ioe);
+    }
+
+    try
+    {
+      org.opends.server.types.LDIFExportConfig exportConfig =
+          new org.opends.server.types.LDIFExportConfig(ldifFile
+              .getAbsolutePath(),
+              org.opends.server.types.ExistingFileBehavior.OVERWRITE);
+
+      org.opends.server.util.LDIFWriter writer =
+          new org.opends.server.util.LDIFWriter(exportConfig);
+
+      org.opends.server.types.DN dn =
+        org.opends.server.types.DN.decode(baseDn);
+      org.opends.server.types.Entry entry =
+          org.opends.server.util.StaticUtils.createEntry(dn);
+
+      writer.writeEntry(entry);
+      writer.close();
+    } catch (org.opends.server.types.DirectoryException de)
+    {
+      throw new InstallException(InstallException.Type.CONFIGURATION_ERROR,
+          getExceptionMsg("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);
+    } catch (IOException ioe)
+    {
+      throw new InstallException(InstallException.Type.CONFIGURATION_ERROR,
+          getExceptionMsg("error-importing-ldif", null, ioe), ioe);
+    } catch (RuntimeException re)
+    {
+      throw new InstallException(InstallException.Type.BUG, getExceptionMsg(
+          "bug-msg", re), re);
+    }
+    return ldifFile;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/LabelFieldDescriptor.java b/opends/src/quicksetup/org/opends/quicksetup/installer/LabelFieldDescriptor.java
new file mode 100644
index 0000000..f4b7bcd
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/LabelFieldDescriptor.java
@@ -0,0 +1,151 @@
+/*
+ * 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.installer;
+
+/**
+ * This is a commodity class used to couple a label and a text component with
+ * a FieldName.  It is mainly used by the QuickSetupStepPanel classes to
+ * retrieve easily the labels and fields associated with a FieldName to provide
+ * its content or to mark the labels as valid or invalid.  It is also used
+ * during the creation of the components as it describes the different
+ * properties.
+ */
+
+public class LabelFieldDescriptor
+{
+  private String label;
+
+  private String tooltip;
+
+  private FieldType type;
+
+  private LabelType labelType;
+
+  private int size;
+
+  /**
+   * This enum contains the different type of labels that can be associated with
+   * this LabelFieldDescriptor.
+   *
+   */
+  public enum LabelType
+  {
+    /**
+     * Primary label.
+     */
+    PRIMARY,
+    /**
+     * Secondary label.
+     */
+    SECONDARY
+  };
+
+  /**
+   * This enum contains the different type of fields that can be associated with
+   * this LabelFieldDescriptor.
+   *
+   */
+  public enum FieldType
+  {
+    /**
+     * Editable text field.
+     */
+    TEXTFIELD,
+    /**
+     * Password field.
+     */
+    PASSWORD,
+    /**
+     * Read only field.
+     */
+    READ_ONLY
+  };
+
+  /**
+   * Constructor of this LabelFieldDescriptor.
+   * @param label the String of the label.
+   * @param tooltip the tooltip of the field.
+   * @param type the type of field.
+   * @param labelType the type of label.
+   * @param size the size of the field.
+   */
+  public LabelFieldDescriptor(String label, String tooltip, FieldType type,
+      LabelType labelType, int size)
+  {
+    this.label = label;
+    this.tooltip = tooltip;
+    this.type = type;
+    this.labelType = labelType;
+    this.size = size;
+  }
+
+  /**
+   * Returns the String displayed by the label.
+   * @return the String displayed by the label.
+   */
+  public String getLabel()
+  {
+    return label;
+  }
+
+  /**
+   * Returns the size of the field.
+   * @return the size of the field.
+   */
+  public int getSize()
+  {
+    return size;
+  }
+
+  /**
+   * Returns the tooltip used in the field.
+   * @return the tooltip used in the field.
+   */
+  public String getTooltip()
+  {
+    return tooltip;
+  }
+
+  /**
+   * Returns the field type.
+   * @return the field type.
+   */
+  public FieldType getType()
+  {
+    return type;
+  }
+
+  /**
+   * Returns the label type.
+   * @return the label type.
+   */
+  public LabelType getLabelType()
+  {
+    return labelType;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallData.java b/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallData.java
new file mode 100644
index 0000000..f427bae
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallData.java
@@ -0,0 +1,166 @@
+/*
+ * 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.installer;
+
+/**
+ * This class is used to provide a data model for the different parameters
+ * that the user can provide in the installation wizard.
+ *
+ * @see DataOptions.
+ *
+ */
+public class UserInstallData
+{
+  private String serverLocation;
+
+  private int serverPort;
+
+  private String directoryManagerDn;
+
+  private String directoryManagerPwd;
+
+  private boolean startServer;
+
+  private DataOptions dataOptions;
+
+  /**
+   * Sets the location of the server (installation path).
+   * @param serverLocation the new server location (installation path).
+   */
+  public void setServerLocation(String serverLocation)
+  {
+    this.serverLocation = serverLocation;
+  }
+
+  /**
+   * Returns the location of the server (installation path).
+   * @return the location of the server (installation path).
+   */
+  public String getServerLocation()
+  {
+    return serverLocation;
+  }
+
+  /**
+   * Sets the server LDAP port.
+   * @param serverPort the new server LDAP port.
+   */
+  public void setServerPort(int serverPort)
+  {
+    this.serverPort = serverPort;
+  }
+
+  /**
+   * Returns the server LDAP port.
+   * @return the server LDAP port.
+   */
+  public int getServerPort()
+  {
+    return serverPort;
+  }
+
+  /**
+   * Returns the Directory Manager DN.
+   * @return the Directory Manager DN.
+   */
+  public String getDirectoryManagerDn()
+  {
+    return directoryManagerDn;
+  }
+
+  /**
+   * Sets the new Directory Manager DN.
+   * @param directoryManagerDn the new Directory Manager DN.
+   */
+  public void setDirectoryManagerDn(String directoryManagerDn)
+  {
+    this.directoryManagerDn = directoryManagerDn;
+  }
+
+  /**
+   * Returns the Directory Manager password.
+   * @return the Directory Manager password.
+   */
+  public String getDirectoryManagerPwd()
+  {
+    return directoryManagerPwd;
+  }
+
+  /**
+   * Sets the new Directory Manager password.
+   * @param directoryManagerPwd the new Directory Manager password.
+   */
+  public void setDirectoryManagerPwd(String directoryManagerPwd)
+  {
+    this.directoryManagerPwd = directoryManagerPwd;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the server must be started once the
+   * installation is finished, <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the server must be started once the
+   * installation is finished, <CODE>false</CODE> if not.
+   */
+  public boolean getStartServer()
+  {
+    return startServer;
+  }
+
+  /**
+   * Sets whether we want to start the server once the installation is finished
+   * or not.
+   * @param startServer the boolean indicating whether to start the server or
+   * not.
+   */
+  public void setStartServer(boolean startServer)
+  {
+    this.startServer = startServer;
+  }
+
+  /**
+   * Returns the DataOptions object representing the data in the Data Options
+   * panel.
+   * @return the DataOptions object representing the data in the Data Options
+   * panel.
+   */
+  public DataOptions getDataOptions()
+  {
+    return dataOptions;
+  }
+
+  /**
+   * Sets the DataOptions object representing the data in the Data Options
+   * panel.
+   * @param dataOptions the DataOptions object representing the data in the Data
+   * Options panel.
+   */
+  public void setDataOptions(DataOptions dataOptions)
+  {
+    this.dataOptions = dataOptions;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallDataException.java b/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallDataException.java
new file mode 100644
index 0000000..df16abe
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallDataException.java
@@ -0,0 +1,75 @@
+/*
+ * 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.installer;
+
+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 UserInstallDataException extends Exception
+{
+  private static final long serialVersionUID = 1798143194655443132L;
+
+  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 UserInstallDataException(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/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java b/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
new file mode 100644
index 0000000..8f5de38
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
@@ -0,0 +1,308 @@
+/*
+ * 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.installer.offline;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.opends.quicksetup.installer.InstallException;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.Installer;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is an implementation of the Installer class that is used to install
+ * the Directory Server from a zip file.  The installer assumes that the zip
+ * file contents have been unzipped.
+ *
+ * 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.
+ *
+ * This class is supposed to be fully independent of the graphical layout.
+ * However it is the most appropriate part of the code to generate well
+ * formatted messages.  So it generates HTML messages in the
+ * ProgressUpdateEvent and to do so uses the UIFactory method.
+ *
+ * TODO pass an object in the constructor that would generate the messages.
+ * The problem of this approach is that the resulting interface of this object
+ * may be quite complex and could impact the lisibility of the code.
+ *
+ */
+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>();
+
+  /* This map contains the summary associated with each step */
+  private HashMap<InstallProgressStep, String> hmSummary =
+      new HashMap<InstallProgressStep, String>();
+
+  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
+   * user.
+   */
+  public OfflineInstaller(UserInstallData userData)
+  {
+    super(userData);
+    initMaps();
+    status = InstallProgressStep.NOT_STARTED;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void start()
+  {
+    Thread t = new Thread(new Runnable()
+    {
+      public void run()
+      {
+        doInstall();
+      }
+    });
+    t.start();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected InstallProgressStep getStatus()
+  {
+    return status;
+  }
+
+  /**
+   * Actually performs the start in this thread.  The thread is blocked.
+   *
+   */
+  private void doInstall()
+  {
+    try
+    {
+      PrintStream err = new ErrorPrintStream();
+      PrintStream out = new OutputPrintStream();
+      System.setErr(err);
+      System.setOut(out);
+
+      status = InstallProgressStep.CONFIGURING_SERVER;
+      configureServer();
+
+      switch (getUserData().getDataOptions().getType())
+      {
+      case CREATE_BASE_ENTRY:
+        status = InstallProgressStep.CREATING_BASE_ENTRY;
+        notifyListeners(UIFactory.HTML_SEPARATOR);
+        createBaseEntry();
+        break;
+      case IMPORT_FROM_LDIF_FILE:
+        status = InstallProgressStep.IMPORTING_LDIF;
+        notifyListeners(UIFactory.HTML_SEPARATOR);
+        importLDIF();
+        break;
+      case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+        status = InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED;
+        notifyListeners(UIFactory.HTML_SEPARATOR);
+        importAutomaticallyGenerated();
+        break;
+      }
+
+      if (getUserData().getStartServer())
+      {
+        notifyListeners(UIFactory.HTML_SEPARATOR);
+        status = InstallProgressStep.STARTING_SERVER;
+        startServer();
+      }
+
+      status = InstallProgressStep.FINISHED_SUCCESSFULLY;
+      notifyListeners(null);
+
+      if (false)
+        throw new InstallException(InstallException.Type.DOWNLOAD_ERROR,
+            getMsg("error-zipinputstreamnull"), null);
+    } catch (InstallException ex)
+    {
+      if (ex.getCause() != null)
+      {
+        ex.getCause().printStackTrace();
+      }
+      status = InstallProgressStep.FINISHED_WITH_ERROR;
+      String html = getHtmlError(ex, true);
+      notifyListeners(html);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Integer getRatio(InstallProgressStep status)
+  {
+    return hmRatio.get(status);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getSummary(InstallProgressStep status)
+  {
+    return hmSummary.get(status);
+  }
+
+  /**
+   * Initialize the different map used in this class.
+   *
+   */
+  private void initMaps()
+  {
+    initSummaryMap(hmSummary);
+
+    /*
+     * hmTime contains the relative time that takes for each task to be
+     * accomplished. For instance if downloading takes twice the time of
+     * extracting, the value for downloading will be the double of the value for
+     * extracting.
+     */
+    HashMap<InstallProgressStep, Integer> hmTime =
+        new HashMap<InstallProgressStep, Integer>();
+    hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5);
+    hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10);
+    hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20);
+    hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
+        20);
+    hmTime.put(InstallProgressStep.STARTING_SERVER, 10);
+
+    int totalTime = 0;
+    ArrayList<InstallProgressStep> steps =
+        new ArrayList<InstallProgressStep>();
+    totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER);
+    steps.add(InstallProgressStep.CONFIGURING_SERVER);
+    switch (getUserData().getDataOptions().getType())
+    {
+    case CREATE_BASE_ENTRY:
+      steps.add(InstallProgressStep.CREATING_BASE_ENTRY);
+      totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY);
+      break;
+    case IMPORT_FROM_LDIF_FILE:
+      steps.add(InstallProgressStep.IMPORTING_LDIF);
+      totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF);
+      break;
+    case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+      steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+      totalTime += hmTime.get(
+              InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+      break;
+    }
+    if (getUserData().getStartServer())
+    {
+      totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER);
+      steps.add(InstallProgressStep.STARTING_SERVER);
+    }
+
+    int cumulatedTime = 0;
+    for (InstallProgressStep s : steps)
+    {
+      Integer statusTime = hmTime.get(s);
+      hmRatio.put(s, (100 * cumulatedTime) / totalTime);
+      if (statusTime != null)
+      {
+        cumulatedTime += statusTime;
+      }
+    }
+    hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100);
+    hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getConfigFilePath()
+  {
+    return CONFIG_FILE_NAME;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getBinariesPath()
+  {
+    return Utils.getPath(FULL_INSTALL_PATH, BINARIES_PATH_RELATIVE);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getOpenDSClassPath()
+  {
+    return System.getProperty("java.class.path");
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java
new file mode 100644
index 0000000..e8fa8d4
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java
@@ -0,0 +1,57 @@
+/*
+ * 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.installer.webstart;
+
+/**
+ * The following properties are set in the OpenDSQuickSetup.jnlp file to provide
+ * informations.
+ *
+ */
+public interface JnlpProperties
+{
+  /**
+   * Java property used to known if we are using web start or not.
+   */
+  public static final String IS_WEBSTART = "org.opends.quicksetup.iswebstart";
+
+  /**
+   * Java property used to know which are the jar files that must be downloaded
+   * lazily.  The current code in WebStartDownloader that uses this property
+   * assumes that the URL are separated with an space.
+   */
+  public static final String LAZY_JAR_URLS =
+      "org.opends.quicksetup.lazyjarurls";
+
+  /**
+   * Java property used to know which is the name of the zip file that must
+   * be unzipped and whose contents must be extracted during the Web Start
+   * based setup.
+   */
+  public static final String ZIP_FILE_NAME =
+      "org.opends.quicksetup.zipfilename";
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java
new file mode 100644
index 0000000..4b82688
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java
@@ -0,0 +1,316 @@
+/*
+ * 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.installer.webstart;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.jnlp.DownloadService;
+import javax.jnlp.DownloadServiceListener;
+import javax.jnlp.ServiceManager;
+import javax.jnlp.UnavailableServiceException;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.InstallException;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to download the files that have been marked as lazy
+ * in the OpenDSQuickSetup.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
+ * will call this class and it will download the jar files.  Until this class is
+ * not finished the WebStartInstaller will be on the
+ * InstallProgressStep.DOWNLOADING step.
+ */
+public class WebStartDownloader implements DownloadServiceListener,
+    JnlpProperties
+{
+  private InstallException ex;
+
+  private boolean isFinished;
+
+  private int downloadPercentage = 0;
+
+  private int currentPercMin = 0;
+
+  private int currentPercMax = 0;
+
+  /**
+   * Starts the downloading of the jar files.  If forceDownload is set to
+   * <CODE>true</CODE> the files will be re-downloaded even if they already
+   * are on cache.
+   *
+   * This method does not block the thread that calls it.
+   *
+   * @param forceDownload used to ignore the case and force download.
+   */
+  public void start(final boolean forceDownload)
+  {
+    isFinished = false;
+    Thread t = new Thread(new Runnable()
+    {
+      public void run()
+      {
+        try
+        {
+          startDownload(forceDownload);
+        } catch (MalformedURLException mfe)
+        {
+          mfe.printStackTrace();
+          // This is a bug
+          ex =
+              new InstallException(InstallException.Type.BUG, getExceptionMsg(
+                  "bug-msg", mfe), mfe);
+        } catch (IOException ioe)
+        {
+          ioe.printStackTrace();
+          StringBuffer buf = new StringBuffer();
+          String[] jars = getJarUrls();
+          for (int i = 0; i < jars.length; i++)
+          {
+            if (i != 0)
+            {
+              buf.append(",");
+            }
+            buf.append(jars[i]);
+          }
+          String[] arg =
+            { buf.toString() };
+          ex =
+              new InstallException(InstallException.Type.DOWNLOAD_ERROR,
+                  getExceptionMsg("downloading-error", arg, ioe), ioe);
+        } catch (RuntimeException re)
+        {
+          re.printStackTrace();
+          // This is a bug
+          ex =
+              new InstallException(InstallException.Type.BUG, getExceptionMsg(
+                  "bug-msg", re), re);
+        }
+      }
+    });
+    t.start();
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the install is finished and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if the install is finished and
+   * <CODE>false</CODE> otherwise.
+   */
+  public boolean isFinished()
+  {
+    return isFinished;
+  }
+
+  /**
+   * Returns the current download percentage.
+   * @return the current download percentage.
+   */
+  public int getDownloadPercentage()
+  {
+    return downloadPercentage;
+  }
+
+  /**
+   * Starts synchronously the downloading on this thread.  The thread calling
+   * this method will be blocked.  If forceDownload is set to
+   * <CODE>true</CODE> the files will be re-downloaded even if they already
+   * are on cache.
+   * @param forceDownload used to ignore the case and force download.
+   * @throws MalformedURLException if there is an error with the URL that we
+   * get from the JnlpProperties.
+   * @throws IOException if a network problem occurs.
+   */
+  private void startDownload(boolean forceDownload)
+      throws MalformedURLException, IOException
+  {
+    DownloadService ds;
+
+    try
+    {
+      ds =
+          (DownloadService) ServiceManager.lookup(
+              "javax.jnlp.DownloadService");
+    } catch (UnavailableServiceException e)
+    {
+      ds = null;
+    }
+
+    if (ds != null)
+    {
+      String[] urls = getJarUrls();
+      String[] versions = getJarVersions();
+
+      for (int i = 0; i < urls.length && (getException() == null); i++)
+      {
+        currentPercMin = (100 * i) / urls.length;
+        currentPercMax = (100 * (i + 1)) / urls.length;
+
+        // determine if a particular resource is cached
+        String sUrl = urls[i];
+        String version = versions[i];
+
+        URL url = new URL(sUrl);
+        boolean cached = ds.isResourceCached(url, version);
+
+        if (cached && forceDownload)
+        {
+          try
+          {
+            ds.removeResource(url, version);
+          } catch (IOException ioe)
+          {
+          }
+          cached = false;
+        }
+
+        if (!cached)
+        {
+          // if not in the cache load the resource into the cache
+          ds.loadResource(url, version, this);
+        }
+      }
+    }
+    isFinished = true;
+  }
+
+  /**
+   * Returns the InstallException that has occurred during the download or
+   * <CODE>null</CODE> if no exception occurred.
+   * @return the InstallException that has occurred during the download or
+   * <CODE>null</CODE> if no exception occurred.
+   */
+  public InstallException getException()
+  {
+    return ex;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void downloadFailed(URL url, String version)
+  {
+    ex =
+        new InstallException(InstallException.Type.DOWNLOAD_ERROR, getMsg(
+            "downloading-error", new String[]
+              { url.toString() }), null);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void progress(URL url, String version, long readSoFar, long total,
+      int overallPercent)
+  {
+    if (overallPercent >= 0)
+    {
+      downloadPercentage = getPercentage(overallPercent);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void upgradingArchive(URL url, String version, int patchPercent,
+      int overallPercent)
+  {
+    if (overallPercent >= 0)
+    {
+      downloadPercentage = getPercentage(overallPercent);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void validating(URL url, String version, long entry, long total,
+      int overallPercent)
+  {
+    if (overallPercent >= 0)
+    {
+      downloadPercentage = getPercentage(overallPercent);
+    }
+  }
+
+  /**
+   * Returns the jar files in a String[] from the System properties.
+   * @return the jar files from the System properties.
+   */
+  private String[] getJarUrls()
+  {
+    String jars = System.getProperty(LAZY_JAR_URLS);
+    return jars.split(" ");
+  }
+
+
+  /**
+   * Returns the downloaded percentage based on how much of the current jar file
+   * has been downloaded.
+   * @param currentJarRatio the download ratio of the jar file that is being
+   * currently downloaded.
+   * @return the downloaded percentage based on how much of the current jar file
+   * has been downloaded.
+   */
+  private int getPercentage(int currentJarRatio)
+  {
+    int perc =
+        currentPercMin
+            + (currentJarRatio * (currentPercMax - currentPercMin) / 100);
+    return perc;
+  }
+
+  /**
+   * Returns the java jar versions in a String[].  Currently just returns some
+   * null strings.
+   * @return the java jar versions in a String[].
+   */
+  private String[] getJarVersions()
+  {
+    return new String[getJarUrls().length];
+  }
+
+  /* Some commodity methods to get localized messages */
+  private String getExceptionMsg(String key, Exception ex)
+  {
+    return getExceptionMsg(key, null, ex);
+  }
+
+  private String getExceptionMsg(String key, String[] args, Exception ex)
+  {
+    return Utils.getExceptionMsg(ResourceProvider.getInstance(), key, args, ex);
+  }
+
+  private String getMsg(String key, String[] args)
+  {
+    return ResourceProvider.getInstance().getMsg(key, args);
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
new file mode 100644
index 0000000..a5cbccb
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
@@ -0,0 +1,647 @@
+/*
+ * 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.installer.webstart;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.opends.quicksetup.installer.InstallException;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.Installer;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is an implementation of the Installer class that is used to install
+ * the Directory Server using Web Start.
+ *
+ * It just takes a UserInstallData object and based on that installs OpenDS.
+ *
+ *
+ * This object has as parameter a WebStartDownloader object that is downloading
+ * some jar files.  Until the WebStartDownloader has not finished downloading
+ * the jar files will be on the InstallProgressStep.DOWNLOADING step because
+ * 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
+ * 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.
+ *
+ *
+ * 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.
+ *
+ * This class is supposed to be fully independent of the graphical layout.
+ * However it is the most appropriate part of the code to generate well
+ * formatted messages.  So it generates HTML messages in the
+ * ProgressUpdateEvent and to do so uses the UIFactory method.
+ *
+ * TODO pass an object in the constructor that would generate the messages.
+ * The problem of this approach is that the resulting interface of this object
+ * may be quite complex and could impact the lisibility of the code.
+ *
+ */
+public class WebStartInstaller extends Installer implements JnlpProperties
+{
+  private HashMap<InstallProgressStep, Integer> hmRatio =
+      new HashMap<InstallProgressStep, Integer>();
+
+  private HashMap<InstallProgressStep, String> hmSummary =
+      new HashMap<InstallProgressStep, String>();
+
+  private InstallProgressStep status;
+
+  private WebStartDownloader loader;
+
+  /**
+   * WebStartInstaller constructor.
+   * @param userData the UserInstallData with the parameters provided by the
+   * user.
+   * @param loader the WebStartLoader that is used to download the remote jar
+   * files.
+   */
+  public WebStartInstaller(UserInstallData userData,
+      WebStartDownloader loader)
+  {
+    super(userData);
+    this.loader = loader;
+    initMaps();
+    status = InstallProgressStep.NOT_STARTED;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void start()
+  {
+    Thread t = new Thread(new Runnable()
+    {
+      public void run()
+      {
+        doInstall();
+      }
+    });
+    t.start();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected InstallProgressStep getStatus()
+  {
+    return status;
+  }
+
+  /**
+   * Actually performs the start in this thread.  The thread is blocked.
+   *
+   */
+  private void doInstall()
+  {
+    try
+    {
+      PrintStream err = new ErrorPrintStream();
+      PrintStream out = new OutputPrintStream();
+      System.setErr(err);
+      System.setOut(out);
+
+      status = InstallProgressStep.DOWNLOADING;
+
+      InputStream in =
+          getZipInputStream(getRatio(InstallProgressStep.EXTRACTING));
+      notifyListeners(UIFactory.HTML_SEPARATOR);
+
+      status = InstallProgressStep.EXTRACTING;
+      extractZipFiles(in, getRatio(InstallProgressStep.EXTRACTING),
+          getRatio(InstallProgressStep.CONFIGURING_SERVER));
+      notifyListeners(UIFactory.HTML_SEPARATOR);
+
+      status = InstallProgressStep.CONFIGURING_SERVER;
+      configureServer();
+
+      switch (getUserData().getDataOptions().getType())
+      {
+      case CREATE_BASE_ENTRY:
+        status = InstallProgressStep.CREATING_BASE_ENTRY;
+        notifyListeners(UIFactory.HTML_SEPARATOR);
+        createBaseEntry();
+        break;
+      case IMPORT_FROM_LDIF_FILE:
+        status = InstallProgressStep.IMPORTING_LDIF;
+        notifyListeners(UIFactory.HTML_SEPARATOR);
+        importLDIF();
+        break;
+      case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+        status = InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED;
+        notifyListeners(UIFactory.HTML_SEPARATOR);
+        importAutomaticallyGenerated();
+        break;
+      }
+
+      if (getUserData().getStartServer())
+      {
+        notifyListeners(UIFactory.HTML_SEPARATOR);
+        status = InstallProgressStep.STARTING_SERVER;
+        startServer();
+      }
+
+      status = InstallProgressStep.FINISHED_SUCCESSFULLY;
+      notifyListeners(null);
+
+    } catch (InstallException ex)
+    {
+      if (ex.getCause() != null)
+      {
+        ex.getCause().printStackTrace();
+      }
+      status = InstallProgressStep.FINISHED_WITH_ERROR;
+      String html = getHtmlError(ex, true);
+      notifyListeners(html);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Integer getRatio(InstallProgressStep status)
+  {
+    return hmRatio.get(status);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getSummary(InstallProgressStep status)
+  {
+    return hmSummary.get(status);
+  }
+
+  /**
+   * Initialize the different map used in this class.
+   *
+   */
+  private void initMaps()
+  {
+    initSummaryMap(hmSummary);
+
+    /*
+     * hmTime contains the relative time that takes for each task to be
+     * accomplished. For instance if downloading takes twice the time of
+     * extracting, the value for downloading will be the double of the value for
+     * extracting.
+     */
+    HashMap<InstallProgressStep, Integer> hmTime =
+        new HashMap<InstallProgressStep, Integer>();
+    hmTime.put(InstallProgressStep.DOWNLOADING, 15);
+    hmTime.put(InstallProgressStep.EXTRACTING, 15);
+    hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5);
+    hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10);
+    hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20);
+    hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
+        20);
+    hmTime.put(InstallProgressStep.STARTING_SERVER, 10);
+
+    int totalTime = 0;
+    ArrayList<InstallProgressStep> steps =
+        new ArrayList<InstallProgressStep>();
+    totalTime += hmTime.get(InstallProgressStep.DOWNLOADING);
+    steps.add(InstallProgressStep.DOWNLOADING);
+    totalTime += hmTime.get(InstallProgressStep.EXTRACTING);
+    steps.add(InstallProgressStep.EXTRACTING);
+    totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER);
+    steps.add(InstallProgressStep.CONFIGURING_SERVER);
+    switch (getUserData().getDataOptions().getType())
+    {
+    case CREATE_BASE_ENTRY:
+      steps.add(InstallProgressStep.CREATING_BASE_ENTRY);
+      totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY);
+      break;
+    case IMPORT_FROM_LDIF_FILE:
+      steps.add(InstallProgressStep.IMPORTING_LDIF);
+      totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF);
+      break;
+    case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+      steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+      totalTime +=hmTime.get(
+              InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+      break;
+    }
+    if (getUserData().getStartServer())
+    {
+      totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER);
+      steps.add(InstallProgressStep.STARTING_SERVER);
+    }
+
+    int cumulatedTime = 0;
+    for (InstallProgressStep s : steps)
+    {
+      Integer statusTime = hmTime.get(s);
+      hmRatio.put(s, (100 * cumulatedTime) / totalTime);
+      if (statusTime != null)
+      {
+        cumulatedTime += statusTime;
+      }
+    }
+
+    hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100);
+    hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100);
+  }
+
+  private InputStream getZipInputStream(Integer maxRatio)
+      throws InstallException
+  {
+    notifyListeners(getHtmlWithPoints(getMsg("progress-downloading")));
+    InputStream in = null;
+
+    waitForLoader(maxRatio);
+
+    in =
+      Installer.class.getClassLoader().getResourceAsStream(getZipFileName());
+
+    if (in == null)
+    {
+      // Retry once
+      loader.start(true);
+      waitForLoader(maxRatio);
+      in =
+          Installer.class.getClassLoader()
+              .getResourceAsStream(getZipFileName());
+
+      if (in == null)
+      {
+        throw new InstallException(InstallException.Type.DOWNLOAD_ERROR,
+            getMsg("error-zipinputstreamnull"), null);
+      }
+    }
+
+    notifyListeners(getHtmlDone());
+    return in;
+  }
+
+  /**
+   * Waits for the loader to be finished.  Every time we have an update in the
+   * percentage that is downloaded we notify the listeners of this.
+   *
+   * @param maxRatio is the integer value that tells us which is the max ratio
+   * that corresponds to the download.  It is used to calculate how the global
+   * installation ratio changes when the download ratio increases.  For instance
+   * if we suppose that the download takes 25 % of the total installation
+   * process, then maxRatio will be 25.  When the download is complete this
+   * method will send a notification to the ProgressUpdateListeners with a ratio
+   * of 25 %.
+   *
+   */
+  private void waitForLoader(Integer maxRatio) throws InstallException
+  {
+    int lastPercentage = -1;
+    while (!loader.isFinished() && (loader.getException() == null))
+    {
+      // Pool until is over
+      int perc = loader.getDownloadPercentage();
+      if (perc != lastPercentage)
+      {
+        lastPercentage = perc;
+        int ratio = (perc * maxRatio) / 100;
+        String[] arg =
+          { String.valueOf(perc) };
+        String summary = getMsg("downloading-ratio", arg);
+        hmSummary.put(InstallProgressStep.DOWNLOADING, summary);
+        notifyListeners(ratio, summary, null);
+
+        try
+        {
+          Thread.sleep(300);
+        } catch (Exception ex)
+        {
+        }
+      }
+    }
+
+    if (loader.getException() != null)
+    {
+      throw loader.getException();
+    }
+  }
+
+  /**
+   * This method extracts the zip file.
+   * @param is the inputstream with the contents of the zip file.
+   * @param minRatio the value of the ratio in the install that corresponds to
+   * the moment where we start extracting the zip files.  Used to update
+   * properly the install progress ratio.
+   * @param maxRatio the value of the ratio in the installation that corresponds
+   * to the moment where we finished extracting the last zip file.  Used to
+   * update properly the install progress ratio.
+   * @throws InstallException if an error occurs.
+   */
+  private void extractZipFiles(InputStream is, int minRatio, int maxRatio)
+      throws InstallException
+  {
+    ZipInputStream zipIn = new ZipInputStream(is);
+    String basePath = getUserData().getServerLocation();
+
+    int nEntries = 1;
+
+    /* This map is updated in the copyZipEntry method with the permissions
+     * of the files that have been copied.  Once all the files have
+     * been copied to the file system we will update the file permissions of
+     * these files.  This is done this way to group the number of calls to
+     * Runtime.exec (which is required to update the file system permissions).
+     */
+    Map<String, ArrayList<String>> permissions =
+        new HashMap<String, ArrayList<String>>();
+
+    String zipFirstPath = null;
+    try
+    {
+      ZipEntry entry = zipIn.getNextEntry();
+      while (entry != null)
+      {
+        int ratioBeforeCompleted = minRatio
+        + ((nEntries - 1) * (maxRatio - minRatio) / getNumberZipEntries());
+        int ratioWhenCompleted =
+          minRatio + (nEntries * (maxRatio - minRatio) / getNumberZipEntries());
+
+        if (nEntries == 1)
+        {
+          zipFirstPath = entry.getName();
+        } else
+        {
+          try
+          {
+            copyZipEntry(entry, basePath, zipFirstPath, zipIn,
+                ratioBeforeCompleted, ratioWhenCompleted, permissions);
+
+          } catch (IOException ioe)
+          {
+            String[] arg =
+              { entry.getName() };
+            String errorMsg = getExceptionMsg("error-copying", arg, ioe);
+
+            throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+                errorMsg, ioe);
+          }
+        }
+
+        zipIn.closeEntry();
+        entry = zipIn.getNextEntry();
+        nEntries++;
+      }
+
+      if (Utils.isUnix())
+      {
+        // Change the permissions for UNIX systems
+        for (String perm : permissions.keySet())
+        {
+          ArrayList<String> paths = permissions.get(perm);
+          try
+          {
+            int result = Utils.setPermissionsUnix(paths, perm);
+            if (result != 0)
+            {
+              throw new IOException("Could not set permissions on files "
+                  + paths + ".  The chmod error code was: " + result);
+            }
+          } catch (InterruptedException ie)
+          {
+            IOException ioe =
+                new IOException("Could not set permissions on files " + paths
+                    + ".  The chmod call returned an InterruptedException.");
+            ioe.initCause(ie);
+            throw ioe;
+          }
+        }
+      }
+
+    } catch (IOException ioe)
+    {
+      String[] arg =
+        { getZipFileName() };
+      String errorMsg = getExceptionMsg("error-zip-stream", arg, ioe);
+      throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+          errorMsg, ioe);
+    }
+  }
+
+  /**
+   * Copies a zip entry in the file system.
+   * @param entry the ZipEntry object.
+   * @param basePath the basePath (the installation path)
+   * @param zipFirstPath the first zip file path.  This is required because the
+   * zip file contain a directory of type
+   * 'OpenDS-(major version).(minor version)' that we want to get rid of.  The
+   * first zip file path corresponds to this path.
+   * @param is the ZipInputStream that contains the contents to be copied.
+   * @param ratioBeforeCompleted the progress ratio before the zip file is
+   * copied.
+   * @param ratioWhenCompleted the progress ratio after the zip file is
+   * copied.
+   * @param permissions an ArrayList with permissions whose contents will be
+   * updated.
+   * @throws IOException if an error occurs.
+   */
+  private void copyZipEntry(ZipEntry entry, String basePath,
+      String zipFirstPath, ZipInputStream is, int ratioBeforeCompleted,
+      int ratioWhenCompleted, Map<String, ArrayList<String>> permissions)
+      throws IOException
+  {
+    String entryName = entry.getName();
+    // Get rid of the zipFirstPath
+    if (entryName.startsWith(zipFirstPath))
+    {
+      entryName = entryName.substring(zipFirstPath.length());
+    }
+    String path = Utils.getPath(basePath, entryName);
+
+    notifyListeners(ratioBeforeCompleted, getSummary(getStatus()),
+        getHtmlWithPoints(getMsg("progress-extracting", new String[]
+          { path })));
+    if (Utils.createParentPath(path))
+    {
+      if (entry.isDirectory())
+      {
+        String perm = getDirectoryFileSystemPermissions(path);
+        ArrayList<String> list = permissions.get(perm);
+        if (list == null)
+        {
+          list = new ArrayList<String>();
+        }
+        list.add(path);
+        permissions.put(perm, list);
+
+        if (!Utils.createDirectory(path))
+        {
+          throw new IOException("Could not create path: " + path);
+        }
+      } else
+      {
+        String perm = getFileSystemPermissions(path);
+        ArrayList<String> list = permissions.get(perm);
+        if (list == null)
+        {
+          list = new ArrayList<String>();
+        }
+        list.add(path);
+        Utils.createFile(path, is);
+      }
+    } else
+    {
+      throw new IOException("Could not create parent path: " + path);
+    }
+    notifyListeners(ratioWhenCompleted, getSummary(getStatus()),
+        getHtmlDone() + LINE_BREAK);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getOpenDSClassPath()
+  {
+    StringBuffer buf = new StringBuffer();
+    String[] jars = getOpenDSJarPaths();
+    for (int i = 0; i < jars.length; i++)
+    {
+      if (i != 0)
+      {
+        buf.append(System.getProperty("path.separator"));
+      }
+      buf.append(jars[i]);
+    }
+    return buf.toString();
+  }
+
+  /**
+   * Returns the jar file paths in the installation.  This is used to launch
+   * command lines that require a classpath.
+   * @return the jar file paths in the installation.
+   */
+  private String[] getOpenDSJarPaths()
+  {
+    String[] jarPaths = new String[OPEN_DS_JAR_RELATIVE_PATHS.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]);
+      jarPaths[i] = f.getAbsolutePath();
+    }
+    return jarPaths;
+  }
+
+  /**
+   * Returns the name of the zip file name that contains all the installation.
+   * @return the name of the zip file name that contains all the installation.
+   */
+  private String getZipFileName()
+  {
+    // Passed as a java option in the JNLP file
+    return System.getProperty(ZIP_FILE_NAME);
+  }
+
+  /**
+   * Returns the file system permissions for a directory.
+   * @param path the directory for which we want the file permissions.
+   * @return the file system permissions for the directory.
+   */
+  private String getDirectoryFileSystemPermissions(String path)
+  {
+    // TODO We should get this dynamically during build?
+    return "755";
+  }
+
+  /**
+   * Returns the file system permissions for a file.
+   * @param path the file for which we want the file permissions.
+   * @return the file system permissions for the file.
+   */
+  private String getFileSystemPermissions(String path)
+  {
+    // TODO We should get this dynamically during build?
+    String perm;
+
+    File file = new File(path);
+    if (file.getParent().endsWith(File.separator + "bin"))
+    {
+      if (path.endsWith(".bat"))
+      {
+        perm = "644";
+      } else
+      {
+        perm = "755";
+      }
+    } else if (path.endsWith(".sh"))
+    {
+      perm = "755";
+    } else
+    {
+      perm = "644";
+    }
+    return perm;
+  }
+
+  /**
+   * Returns the number of entries contained in the zip file.  This is used to
+   * update properly the progress bar ratio.
+   * @return the number of entries contained in the zip file.
+   */
+  private int getNumberZipEntries()
+  {
+    // TODO  we should get this dynamically during build
+    return 83;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getConfigFilePath()
+  {
+    String fullInstallPath = getUserData().getServerLocation();
+
+    return Utils.getPath(fullInstallPath, CONFIG_PATH_RELATIVE);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getBinariesPath()
+  {
+    String fullInstallPath = getUserData().getServerLocation();
+
+    return Utils.getPath(fullInstallPath, BINARIES_PATH_RELATIVE);
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
new file mode 100644
index 0000000..ab7d1b9
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -0,0 +1,365 @@
+#
+# Setup command line messages
+#
+setup-launcher-usage=This utility may be used to setup the Directory Server.\n\
+Usage:  {0} {options}\n        where {options} include:\n\
+--cli\n\    Specifies to use the command line setup.  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   --silentInstall\n    Perform a silent installation.\n\
+-b {baseDN}  or   --baseDN {baseDN}\n\    Specifies the base DN for user \
+information in the Directory Server.\n    Multiple base DNs may be provided by \
+using this option multiple times.\n\
+-a  or   --addBaseEntry\n    Indicates whether to create the base entry in the \
+Directory Server\n    database.\n\
+-i {ldifFile}  or   --importLDIF {ldifFile}\n    Specifies the path to an LDIF \
+file containing data that should be added to\n    the Directory Server \
+database.  Multiple LDIF files may be provided by\n    using this option \
+multiple times.\n\
+-p {port}  or   --ldapPort {port}\n    Specifies the port on which the \
+Directory Server should listen for LDAP\n    communication.\n\
+-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\
+-w {password}  or   --rootUserPassword {password}\n    Specifies the password \
+for the initial root 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.
+setup-launcher-launching-gui=Launching graphical setup...
+setup-launcher-gui-launched-failed=\n\nThe graphical Setup launch failed.\n\n\
+Launching command line Setup...
+
+#
+# Dialog titles
+#
+frame-quicksetup-title=OpenDS QuickSetup
+frame-uninstall-title=OpenDS Uninstall
+
+#
+# Wizard buttons (labels and tooltips)
+#
+next-button-label=Next >
+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
+close-button-label=Close
+close-button-tooltip=Close QuickSetup Window
+quit-button-label=Quit
+quit-button-tooltip=Quit QuickSetup Tool
+
+
+#
+# Confirmation dialogs
+#
+confirm-close-quicksetup-title=Confirmation Required
+confirm-close-quicksetup-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 \
+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?
+#
+# Error dialog title
+#
+error-title=Error
+
+#
+# Browser launching error dialog
+#
+error-browser-display-msg=Could not launch the web browser.<br>You can copy \
+and paste the following URL manually into your web browser:<br>\
+<span style="font-style:italic">{0}</span>
+error-browser-display-title=Error
+error-browser-copy-button-label=Copy URL
+error-browser-copy-button-tooltip=Copies the URL to the system clipboard
+error-browser-close-button-tooltip=Close this window
+
+#
+# Data validation errors
+#
+# Server Settings
+empty-server-location=You must provide the installation path.
+parent-directory-does-not-exist=The parent directory of {0} does not exist.
+file-exists=The file {0} already exists.
+directory-exists-not-empty=The directory {0} is not empty.
+directory-not-writable=You do not have write access on the directory {0}. \
+You must have file right access on the Installation directory.
+not-enough-disk-space=There is not enough free disk space under {0}.\nAt \
+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}.
+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.
+directory-manager-dn-is-config-dn=The provided Administrative User DN is \
+used for the configuration of the Directory Server. 
+not-equal-pwd=The passwords you have provided do not match.
+pwd-too-short=The minimum length required for the Administrative User \
+password is {0} characters.
+# Data Options Panel
+empty-base-dn=You must provide a Directory Base DN.
+not-a-base-dn=The provided Directory Base DN is not a valid DN.
+base-dn-is-configuration-dn=The provided Directory Base DN is used for \
+storing the server configuration data. You must specify a different DN.
+no-ldif-path=You must provide the path of the LDIF file to import.
+ldif-file-does-not-exist=The provided LDIF file does not exist.
+no-number-entries=You must provide the number of user entries to generate \
+automatically.
+invalid-number-entries-range=The number of user entries to generate \
+automatically must be an integer between {0} and {1}.
+
+
+#
+# Steps labels (on the left side of the wizard)
+#
+welcome-step=Welcome
+server-settings-step=Server Settings
+data-options-step=Data Options
+review-step=Review
+progress-step=Progress
+confirm-uninstall-step=Confirm Uninstallation
+
+#
+# Icon descriptions.  Used for accessibility.
+#
+current-step-icon-description=Current Step Indicator.
+splash-icon-description=OpenDS QuickSetup Launching.
+minimized-icon-description=OpenDS QuickSetup minimized.
+background-icon-description=OpenDS QuickSetup.
+warning-icon-description=Warning.
+error-icon-description=Error.
+information-icon-description=Information.
+
+#
+# Icon tooltips.
+#
+current-step-icon-tooltip=Current Step Indicator.
+splash-icon-tooltip=Open DS QuickSetup Launching.
+minimized-icon-tooltip=OpenDS QuickSetup.
+background-icon-tooltip=OpenDS QuickSetup.
+warning-icon-tooltip=Warning.
+error-icon-tooltip=Error.
+information-icon-tooltip=Information.
+
+#
+# Icon paths.  This is done to be able  to provide localizable icons (for 
+# instance for those icons containing a text).  If there is not a localized
+# version of the icon it should be left as it is. 
+# The path specified here are the relative resource name to the images.
+#
+current-step-icon=images/currentstep.png
+minimized-icon=images/opendsminimized.gif
+minimized-mac-icon=images/opendsminimizedmac.png
+splash-icon=images/opendssplash.png
+background-icon=images/opendsbackground.png
+error-icon=images/error.gif
+warning-icon=images/warning.gif
+warning-large-icon=images/warning_large.gif
+information-icon=images/information.gif
+
+#
+# Welcome Panel specific labels
+#
+welcome-panel-title=Welcome
+# 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.
+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 quicksetup command at the top level of the \
+OpenDS directory.  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>
+
+#
+# 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-location-label=Installation Path:
+server-location-parent-tooltip=Enter the full path to the parent location \
+where the server files will be stored
+server-location-relative-tooltip=Enter the relative path to the location \
+where the server files will be stored
+server-port-label=LDAP Listener Port:
+server-port-tooltip=Enter the port number that the server will use to listen \
+for LDAP requests
+server-directory-manager-dn-label=Administrative User DN:
+server-directory-manager-dn-tooltip=Enter the distinguished name (DN) of the \
+Administrative User account that will used for managing OpenDS
+server-directory-manager-pwd-label=Password:
+server-directory-manager-pwd-tooltip=Enter a password for the OpenDS \
+Administrative User account
+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.
+
+
+#
+# Data Options Panel specific labels
+#
+data-options-panel-title=Data Options
+data-options-panel-instructions=Choose options for the LDAP data to be hosted \
+by OpenDS.
+base-dn-label=Directory Base DN:
+base-dn-tooltip=Enter the DN of the top entry where your data will be stored
+directory-data-label=Directory Data:
+create-base-entry-label=Only Create Base Entry ({0})
+create-base-entry-tooltip=Only create the top entry for the Directory Base DN
+leave-database-empty-label=Leave Database Empty
+leave-database-empty-tooltip=Do not create any entry for the Directory Base DN
+import-data-from-ldif-label=Import Data from LDIF File
+import-data-from-ldif-tooltip=Use the contents of an LDIF file to populate the \
+suffix with data
+import-path-label=Path:
+import-path-tooltip=Enter the full path of the LDIF file containing the \
+data to be imported
+import-automatically-generated-label=Import Automatically-Generated Example \
+Data
+import-automatically-generated-tooltip=Populate the suffix with \
+automatically-generated LDAP data
+number-entries-label=Number of User Entries:
+number-entries-tooltip=Enter the number of user entries to be generated
+
+#
+# Review Panel specific labels
+#
+review-panel-title=Review
+review-panel-instructions=Review your settings and click Finish if they are \
+correct.
+review-create-base-entry-label=Only Create Base Entry ({0})
+review-leave-database-empty-label=Leave Database Empty
+review-import-ldif=Import Data from LDIF File ({0})
+review-import-automatically-generated=Import Automatically-Generated Data ({0} \
+Entries)
+start-server-label=Start Server when Configuration has Completed
+start-server-tooltip=Check this check box if you want to start the server once \
+the installation and configuration has completed
+
+#
+# Progress Panel specific labels
+#
+progress-panel-title=Progress
+progress-details-label=Details:
+progressbar-initial-label=Starting Setup...
+progressbar-tooltip=Progress Bar
+
+#
+# Confirm Uninstall Panel specific labels
+#
+confirm-uninstall-panel-title=Confirm uninstall
+# 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>
+
+
+#
+# Miscellaneous labels
+#
+browse-button-label=Browse...
+browse-button-tooltip=Click to display a file system browser
+ldif-files-description=Lightweight Directory Interchange Format (*.ldif)
+open-server-location-dialog-title=Choose Installation Path
+open-ldif-file-dialog-title=Choose an LDIF File
+
+#
+# Progress Summary Labels
+#
+summary-not-started=Starting QuickSetup...
+summary-not-started=Launching Installation...
+summary-downloading=Downloading Binary Files...
+summary-extracting=Extracting Binary Files...
+summary-configuring=Configuring Directory Server...
+summary-creating-base-entry=Creating Base Entry...
+summary-importing-ldif=Importing LDIF File...
+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 <a href="https://opends.dev.java.net/public/docs/index.html"> \
+documentation depot</a> page for guidance on server management and \
+configuration.
+summary-finished-with-error=An error occurred.  Check 'Details' text area for \
+more information.
+
+#
+# Progress messages
+#
+progress-downloading=Downloading
+progress-done=Done.
+progress-points=.....
+progress-extracting=Extracting {0}
+progress-configuring=Configuring Directory Server
+downloading-ratio=Downloading: {0}% Completed.
+progress-creating-base-entry=Creating Base Entry {0}
+progress-importing-ldif=Importing LDIF file {0}:
+progress-import-automatically-generated=Importing Automatically-Generated Data \
+({0} Entries):
+progress-starting=Starting Directory Server:
+
+#
+# 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}.
+downloading-error=An error occurred downloading remote file(s) {0}.
+error-zipinputstreamnull=Could not retrieve zip file.  The input stream \
+is null.
+bug-msg=An unexpected error occurred.
+error-configuring=An error occurred configuring the server.
+error-reflection=An unexpected error occurred while loading classes.
+error-creating-temp-file=An error occurred creating the temporary file.
+error-writing-to-temp-file=An error occurred writing to temporary file {0}.
+error-configuring=Error Configuring Directory Server.
+error-creating-base-entry=Error Creating Base Entry.
+error-importing-ldif=Error Importing LDIF File.
+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-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:
+
+#
+# Install Status: messages displayed in the offline quick setup
+# if server is already installed.
+#
+installstatus-serverrunning=Is currently running on port {0}
+installstatus-dbfileexist=Contains data
+installstatus-configfilemodified=Has already been configured
+installstatus-installed=OpenDS Server Already Configured<br> \
+QuickSetup can only be used with OpenDS Servers that have not yet been \
+configured.  The current server:{0}
+installstatus-not-installed=The Directory Server is not installed.
\ No newline at end of file
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java
new file mode 100644
index 0000000..d8ae55f
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java
@@ -0,0 +1,317 @@
+/*
+ * 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.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import java.util.HashSet;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+
+import org.opends.quicksetup.ButtonName;
+import org.opends.quicksetup.Step;
+import org.opends.quicksetup.event.ButtonActionListener;
+import org.opends.quicksetup.event.ButtonEvent;
+
+/**
+ * This class contains the buttons in the bottom of the Install/Uninstall
+ * dialog.  There is only one of this instances for the QuickSetupDialog.
+ * The layout is updated calling setCurrentStep method.
+ *
+ */
+class ButtonsPanel extends QuickSetupPanel
+{
+  private static final long serialVersionUID = -8460400337486357976L;
+
+  private HashSet<ButtonActionListener> buttonListeners =
+      new HashSet<ButtonActionListener>();
+
+  private JButton nextButton;
+
+  private JButton previousButton;
+
+  private JButton quitButton;
+
+  private JButton closeButton;
+
+  private JButton finishButton;
+
+  /**
+   * Default constructor.
+   *
+   */
+  public ButtonsPanel()
+  {
+    createButtons();
+    layoutButtons();
+  }
+
+  /**
+   * Adds a button listener.  All the button listeners will be notified when
+   * the buttons are clicked (by the user or programatically).
+   * @param l the ButtonActionListener to be added.
+   */
+  public void addButtonActionListener(ButtonActionListener l)
+  {
+    buttonListeners.add(l);
+  }
+
+  /**
+   * Removes a button listener.
+   * @param l the ButtonActionListener to be removed.
+   */
+  public void removeButtonActionListener(ButtonActionListener l)
+  {
+    buttonListeners.remove(l);
+  }
+
+  /**
+   * Updates the layout of the panel so that it corresponds to the Step passed
+   * as parameter.
+   *
+   * @param step the step in the wizard.
+   */
+  public void setDisplayedStep(Step step)
+  {
+    switch (step)
+    {
+    case WELCOME:
+
+      previousButton.setVisible(false);
+      nextButton.setVisible(true);
+      finishButton.setVisible(false);
+      quitButton.setVisible(true);
+      closeButton.setVisible(false);
+
+      break;
+
+    case REVIEW:
+
+      previousButton.setVisible(true);
+      nextButton.setVisible(false);
+      finishButton.setVisible(true);
+      quitButton.setVisible(true);
+      closeButton.setVisible(false);
+
+      break;
+
+    case PROGRESS:
+
+      // TO COMPLETE: if there is an error we might want to change
+      // this
+      // like for instance coming back
+      previousButton.setVisible(false);
+      nextButton.setVisible(false);
+      finishButton.setVisible(false);
+      quitButton.setVisible(false);
+      closeButton.setVisible(true);
+
+      break;
+
+    case CONFIRM_UNINSTALL:
+
+      previousButton.setVisible(false);
+      nextButton.setVisible(false);
+      finishButton.setVisible(true);
+      quitButton.setVisible(true);
+      closeButton.setVisible(false);
+
+      break;
+
+    default:
+
+      previousButton.setVisible(true);
+      nextButton.setVisible(true);
+      finishButton.setVisible(false);
+      quitButton.setVisible(true);
+      closeButton.setVisible(false);
+    }
+  }
+
+  /**
+   * Returns the button corresponding to the buttonName.
+   * @param buttonName the ButtonName for which we want to get the button.
+   * @return the button corresponding to the buttonName.
+   */
+  public JButton getButton(ButtonName buttonName)
+  {
+    JButton b = null;
+    switch (buttonName)
+    {
+    case NEXT:
+      b = nextButton;
+      break;
+
+    case PREVIOUS:
+      b = previousButton;
+      break;
+
+    case QUIT:
+      b = quitButton;
+      break;
+
+    case CLOSE:
+      b = closeButton;
+      break;
+
+    case FINISH:
+      b = finishButton;
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknown button name: " +
+          buttonName);
+    }
+
+    return b;
+  }
+
+  /*
+   * Create the buttons.
+   */
+  private void createButtons()
+  {
+    nextButton =
+        createButton("next-button-label", "next-button-tooltip",
+            ButtonName.NEXT);
+
+    previousButton =
+        createButton("previous-button-label", "previous-button-tooltip",
+            ButtonName.PREVIOUS);
+
+    quitButton =
+        createButton("quit-button-label", "quit-button-tooltip",
+            ButtonName.QUIT);
+
+    closeButton =
+        createButton("close-button-label", "close-button-tooltip",
+            ButtonName.CLOSE);
+
+    finishButton =
+        createButton("finish-button-label", "finish-button-tooltip",
+            ButtonName.FINISH);
+  }
+
+  /**
+   * Do the layout of the panel.
+   *
+   */
+  private void layoutButtons()
+  {
+    setLayout(new GridBagLayout());
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    GridBagConstraints gbcAux = new GridBagConstraints();
+    gbcAux.gridwidth = GridBagConstraints.REMAINDER;
+    gbcAux.fill = GridBagConstraints.HORIZONTAL;
+    JPanel previousPanel = new JPanel(new GridBagLayout());
+    // Set as opaque to inherit the background color of ButtonsPanel
+    previousPanel.setOpaque(false);
+    previousPanel.add(previousButton, gbcAux);
+    int width = (int) previousButton.getPreferredSize().getWidth();
+    previousPanel.add(Box.createHorizontalStrut(width), gbcAux);
+
+    gbc.gridwidth = 4;
+    gbc.weightx = 0.0;
+    gbc.weighty = 0.0;
+    gbc.insets.bottom = 0;
+    gbc.insets.right = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
+    gbc.anchor = GridBagConstraints.WEST;
+    gbc.fill = GridBagConstraints.NONE;
+    add(previousPanel, gbc);
+    gbc.gridwidth--;
+
+    JPanel nextFinishPanel = new JPanel(new GridBagLayout());
+    // Set as opaque to inherit the background color of ButtonsPanel
+    nextFinishPanel.setOpaque(false);
+    nextFinishPanel.add(nextButton, gbcAux);
+    nextFinishPanel.add(finishButton, gbcAux);
+    width =
+        (int) Math.max(nextButton.getPreferredSize().getWidth(), finishButton
+            .getPreferredSize().getWidth());
+    nextFinishPanel.add(Box.createHorizontalStrut(width), gbcAux);
+    add(nextFinishPanel, gbc);
+
+    gbc.gridwidth--;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.insets.right = 0;
+    add(Box.createHorizontalGlue(), gbc);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 0.0;
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
+    JPanel quitClosePanel = 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);
+    width =
+        (int) Math.max(quitButton.getPreferredSize().getWidth(), closeButton
+            .getPreferredSize().getWidth());
+    quitClosePanel.add(Box.createHorizontalStrut(width), gbcAux);
+    add(quitClosePanel, gbc);
+  }
+
+  /**
+   * Create a button.
+   * @param labelKey the key in the properties file for the label.
+   * @param tooltipKey the key in the properties file for the tooltip.
+   * @param buttonName the ButtonName.
+   * @return a new button with the specified parameters.
+   */
+  private JButton createButton(String labelKey, String tooltipKey,
+      ButtonName buttonName)
+  {
+    JButton b = UIFactory.makeJButton(getMsg(labelKey), getMsg(tooltipKey));
+
+    final ButtonName fButtonName = buttonName;
+
+    ActionListener actionListener = new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        ButtonEvent be = new ButtonEvent(ev.getSource(), fButtonName);
+        for (ButtonActionListener li : buttonListeners)
+        {
+          li.buttonActionPerformed(be);
+        }
+      }
+    };
+
+    b.addActionListener(actionListener);
+
+    return b;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java
new file mode 100644
index 0000000..1085350
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java
@@ -0,0 +1,75 @@
+/*
+ * 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.Component;
+
+/**
+ * This is the panel displayed when the user is uninstalling Open DS.  It is
+ * basically a panel with the text informing of the consequences of uninstalling
+ * the server and asking for confirmation.
+ *
+ */
+public class ConfirmUninstallPanel extends QuickSetupStepPanel
+{
+  private static final long serialVersionUID = 81730510134697056L;
+
+  /**
+   * Default constructor.
+   *
+   */
+  public ConfirmUninstallPanel()
+  {
+    createLayout();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getTitle()
+  {
+    return getMsg("confirm-uninstall-panel-title");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Component createInputPanel()
+  {
+    // No input in this panel
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getInstructions()
+  {
+    return getMsg("confirm-uninstall-panel-instructions");
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
new file mode 100644
index 0000000..97f6e26
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
@@ -0,0 +1,185 @@
+/*
+ * 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.CardLayout;
+import java.awt.Dimension;
+
+import java.util.HashMap;
+
+import org.opends.quicksetup.Step;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+
+/**
+ * This is the class that contains the panel on the right-top part of the
+ * QuickSetupDialog).  It uses a CardLayout that contains all
+ * the panels that are specific to each step (WelcomePanel, ReviewPanel, etc.).
+ *
+ * To specify which is the panel to be displayed the method setCurrentStep
+ * method is called.
+ *
+ * There is only one instance of this class for a given QuickSetupDialog (and
+ * there are only 1 instance of each of the panels that are contained in its
+ * CardLayout).
+ *
+ */
+class CurrentStepPanel extends QuickSetupPanel
+{
+  private UserInstallData defaultUserData;
+
+  private static final long serialVersionUID = 5474803491510999334L;
+
+  private HashMap<Step, QuickSetupStepPanel> hmPanels =
+      new HashMap<Step, QuickSetupStepPanel>();
+
+  /**
+   * The constructor of this class.
+   * @param defaultUserData the default data that is used to initialize the
+   * contents of the panels (the proposed values).
+   * @param isUninstall boolean telling whether we are uninstalling or not.
+   */
+  public CurrentStepPanel(UserInstallData defaultUserData,
+      boolean isUninstall)
+  {
+    this.defaultUserData = defaultUserData;
+    createLayout(isUninstall);
+  }
+
+  /**
+   * Returns the value corresponding to the provided FieldName.
+   * @param fieldName the FieldName for which we want to obtain the value.
+   * @return the value corresponding to the provided FieldName.
+   */
+  public Object getFieldValue(FieldName fieldName)
+  {
+    Object value = null;
+    for (Step s : hmPanels.keySet())
+    {
+      value = getPanel(s).getFieldValue(fieldName);
+      if (value != null)
+      {
+        break;
+      }
+    }
+    return value;
+  }
+
+  /**
+   * Marks as invalid (or valid depending on the value of the invalid parameter)
+   * a field corresponding to FieldName.  This basically implies udpating the
+   * style of the JLabel associated with fieldName (the association is done
+   * using the LabelFieldDescriptor class).
+   * @param fieldName the FieldName to be marked as valid or invalid.
+   * @param invalid whether to mark the field as valid or invalid.
+   */
+  public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+  {
+    for (Step s : hmPanels.keySet())
+    {
+      getPanel(s).displayFieldInvalid(fieldName, invalid);
+    }
+  }
+
+  /**
+   * Create the layout of the panel.
+   * @param isUninstall whether this is an install or uninstall panel.
+   */
+  private void createLayout(boolean isUninstall)
+  {
+    if (isUninstall)
+    {
+      hmPanels.put(Step.CONFIRM_UNINSTALL, new ConfirmUninstallPanel());
+      hmPanels.put(Step.PROGRESS, new ProgressPanel());
+    } else
+    {
+      hmPanels.put(Step.WELCOME, new WelcomePanel());
+      hmPanels.put(Step.SERVER_SETTINGS, new ServerSettingsPanel(
+          defaultUserData));
+      hmPanels.put(Step.DATA_OPTIONS,
+          new DataOptionsPanel(defaultUserData));
+      hmPanels.put(Step.REVIEW, new ReviewPanel(defaultUserData));
+      hmPanels.put(Step.PROGRESS, new ProgressPanel());
+    }
+
+    int minWidth = 0;
+    int minHeight = 0;
+    setLayout(new CardLayout());
+    for (Step s : hmPanels.keySet())
+    {
+      minWidth = Math.max(minWidth, getPanel(s).getMinimumWidth());
+      minHeight = Math.max(minHeight, getPanel(s).getMinimumHeight());
+      add(getPanel(s), s.toString());
+    }
+
+    // For aesthetical reasons we add a little bit of height
+    minHeight += UIFactory.EXTRA_DIALOG_HEIGHT;
+
+    setPreferredSize(new Dimension(minWidth, minHeight));
+    setMinimumSize(new Dimension(minWidth, minHeight));
+  }
+
+  /**
+   * Displays the panel corresponding to the provided step.  The panel contents
+   * are updated with the contents of the UserInstallData object.
+   * @param step the step that we want to display.
+   * @param userData the UserInstallData object that must be used to populate
+   * the panels.
+   */
+  public void setDisplayedStep(Step step, UserInstallData userData)
+  {
+    CardLayout cl = (CardLayout) (getLayout());
+    getPanel(step).beginDisplay(userData);
+    cl.show(this, step.toString());
+    getPanel(step).endDisplay();
+  }
+
+  /**
+   * Forwards the different panels the InstallProgressDescriptor so that they
+   * can update their contents accordingly.
+   * @param descriptor the descriptor of the Installation progress.
+   */
+  public void displayProgress(InstallProgressDescriptor 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.
+   */
+  private QuickSetupStepPanel getPanel(Step step)
+  {
+    return hmPanels.get(step);
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/DataOptionsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/DataOptionsPanel.java
new file mode 100644
index 0000000..5c6dce7
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/DataOptionsPanel.java
@@ -0,0 +1,619 @@
+/*
+ * 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.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.event.BrowseActionListener;
+import org.opends.quicksetup.installer.DataOptions;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.LabelFieldDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+
+/**
+ * This is the panel that contains the Data Options: the suffix dn, whether
+ * to import data to the suffix or not, etc.
+ *
+ */
+class DataOptionsPanel extends QuickSetupStepPanel
+{
+  private Component lastFocusComponent;
+
+  private static final long serialVersionUID = 1815782841921928118L;
+
+  private UserInstallData defaultUserData;
+
+  private HashMap<FieldName, JLabel> hmLabels =
+      new HashMap<FieldName, JLabel>();
+
+  private HashMap<FieldName, JTextComponent> hmFields =
+      new HashMap<FieldName, JTextComponent>();
+
+  private HashMap<DataOptions.Type, JRadioButton> hmRadioButtons =
+      new HashMap<DataOptions.Type, JRadioButton>();
+
+  private JButton ldifBrowseButton;
+
+  /**
+   * Constructor of the panel.
+   * @param defaultUserData the default values that must be used to initialize
+   * the fields of the panel.
+   */
+  public DataOptionsPanel(UserInstallData defaultUserData)
+  {
+    this.defaultUserData = defaultUserData;
+    populateComponentMaps();
+    addDocumentListeners();
+    addFocusListeners();
+    createLayout();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Object getFieldValue(FieldName fieldName)
+  {
+    Object value = null;
+
+    if (fieldName == FieldName.DATA_OPTIONS)
+    {
+      for (DataOptions.Type type : hmRadioButtons.keySet())
+      {
+        if (hmRadioButtons.get(type).isSelected())
+        {
+          value = type;
+          break;
+        }
+      }
+
+    } else
+    {
+      JTextComponent field = getField(fieldName);
+      if (field != null)
+      {
+        value = field.getText();
+      }
+    }
+
+    return value;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+  {
+    JLabel label = getLabel(fieldName);
+    if (label != null)
+    {
+      UIFactory.TextStyle style;
+
+      if (fieldName != FieldName.DIRECTORY_BASE_DN)
+      {
+        if (invalid)
+        {
+          style = UIFactory.TextStyle.SECONDARY_FIELD_INVALID;
+        } else
+        {
+          style = UIFactory.TextStyle.SECONDARY_FIELD_VALID;
+        }
+
+      } else
+      {
+        if (invalid)
+        {
+          style = UIFactory.TextStyle.PRIMARY_FIELD_INVALID;
+        } else
+        {
+          style = UIFactory.TextStyle.PRIMARY_FIELD_VALID;
+        }
+      }
+      UIFactory.setTextStyle(label, style);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Component createInputPanel()
+  {
+    JPanel panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+    // Add the server location widgets
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    gbc.insets.top = 0;
+    gbc.insets.left = 0;
+    gbc.anchor = GridBagConstraints.WEST;
+    panel.add(getLabel(FieldName.DIRECTORY_BASE_DN), gbc);
+
+    JPanel auxPanel = new JPanel(new GridBagLayout());
+    auxPanel.setOpaque(false);
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 0.0;
+    auxPanel.add(getField(FieldName.DIRECTORY_BASE_DN), gbc);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets.left = UIFactory.LEFT_INSET_BROWSE;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    auxPanel.add(Box.createHorizontalGlue(), gbc);
+
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    panel.add(auxPanel, gbc);
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    gbc.insets.left = 0;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    panel.add(getLabel(FieldName.DATA_OPTIONS), gbc);
+
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    panel.add(createRadioButtonPanel(), gbc);
+
+    addVerticalGlue(panel);
+
+    return panel;
+  }
+
+  /**
+   * Returns and creates the radio buttons panel.
+   * @return the radio buttons panel.
+   */
+  private JPanel createRadioButtonPanel()
+  {
+    JPanel panel = new JPanel(new GridBagLayout());
+    GridBagConstraints gbc = new GridBagConstraints();
+    panel.setOpaque(false);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    panel.add(getRadioButton(DataOptions.Type.CREATE_BASE_ENTRY), gbc);
+    gbc.insets.top = UIFactory.TOP_INSET_RADIOBUTTON;
+    panel.add(getRadioButton(DataOptions.Type.LEAVE_DATABASE_EMPTY), gbc);
+    panel.add(getRadioButton(DataOptions.Type.IMPORT_FROM_LDIF_FILE), gbc);
+
+    JPanel auxPanel =
+        createBrowseButtonPanel(FieldName.LDIF_PATH, getLDIFBrowseButton());
+
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.insets.top = UIFactory.TOP_INSET_RADIO_SUBORDINATE;
+    gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
+    panel.add(auxPanel, gbc);
+
+    gbc.insets.left = 0;
+    panel.add(getRadioButton(
+            DataOptions.Type.IMPORT_AUTOMATICALLY_GENERATED_DATA),
+        gbc);
+
+    auxPanel = createNumberEntriesPanel();
+
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
+    gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
+    panel.add(auxPanel, gbc);
+
+    return panel;
+  }
+
+  /**
+   * Returns the number entries panel.
+   * @return the number entries panel.
+   */
+  private JPanel createNumberEntriesPanel()
+  {
+    JPanel panel;
+
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+    gbc.gridwidth = 3;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.weightx = 0.0;
+    panel.add(getLabel(FieldName.NUMBER_ENTRIES), gbc);
+
+    gbc.gridwidth--;
+    gbc.weightx = 0.1;
+    gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+    panel.add(getField(FieldName.NUMBER_ENTRIES), gbc);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    panel.add(Box.createHorizontalGlue(), gbc);
+
+    return panel;
+  }
+
+  /**
+   * Creates a panel with a field and a browse button.
+   * @param fieldName the field name of the field.
+   * @param browseButton the browse button.
+   * @return the created panel.
+   */
+  private JPanel createBrowseButtonPanel(FieldName fieldName,
+      JButton browseButton)
+  {
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    JPanel panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = 4;
+    gbc.weightx = 0.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    panel.add(getLabel(fieldName), gbc);
+
+    gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+    gbc.gridwidth--;
+    gbc.weightx = 0.1;
+    panel.add(getField(fieldName), gbc);
+
+    gbc.insets.left = UIFactory.LEFT_INSET_BROWSE;
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    panel.add(browseButton, gbc);
+
+    gbc.weightx = 1.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    panel.add(Box.createHorizontalGlue(), gbc);
+
+    return panel;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getInstructions()
+  {
+    return getMsg("data-options-panel-instructions");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getTitle()
+  {
+    return getMsg("data-options-panel-title");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void endDisplay()
+  {
+    if (lastFocusComponent != null)
+    {
+      lastFocusComponent.requestFocusInWindow();
+    }
+  }
+
+  /**
+   * Returns the default value for the provided field Name.
+   * @param fieldName the field name for which we want to get the default
+   * value.
+   * @return the default value for the provided field Name.
+   */
+  private Object getDefaultValue(FieldName fieldName)
+  {
+    Object value = null;
+    switch (fieldName)
+    {
+    case DIRECTORY_BASE_DN:
+      value = defaultUserData.getDataOptions().getBaseDn();
+      break;
+
+    case DATA_OPTIONS:
+      value = defaultUserData.getDataOptions().getType();
+      break;
+
+    case LDIF_PATH:
+      value = defaultUserData.getDataOptions().getLDIFPath();
+      break;
+
+    case NUMBER_ENTRIES:
+      value = new Integer(defaultUserData.getDataOptions().getNumberEntries());
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknown field name: " +
+          fieldName);
+    }
+
+    return value;
+  }
+
+  /**
+   * Returns the default string value for the provided field Name.
+   * @param fieldName the field name for which we want to get the default
+   * string value.
+   * @return the default value for the provided field Name.
+   */
+  private String getDefaultStringValue(FieldName fieldName)
+  {
+    String value = null;
+
+    Object v = getDefaultValue(fieldName);
+    if (v != null)
+    {
+      if (v instanceof String)
+      {
+        value = (String) v;
+      } else
+      {
+        value = String.valueOf(v);
+      }
+    }
+    return value;
+  }
+
+  /**
+   * Creates the components and populates the Maps with them.
+   */
+  private void populateComponentMaps()
+  {
+    HashMap<FieldName, LabelFieldDescriptor> hm =
+        new HashMap<FieldName, LabelFieldDescriptor>();
+
+    hm.put(FieldName.DIRECTORY_BASE_DN, new LabelFieldDescriptor(
+        getMsg("base-dn-label"), getMsg("base-dn-tooltip"),
+        LabelFieldDescriptor.FieldType.TEXTFIELD,
+        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.DN_FIELD_SIZE));
+
+    hm.put(FieldName.LDIF_PATH, new LabelFieldDescriptor(
+        getMsg("import-path-label"), getMsg("import-path-tooltip"),
+        LabelFieldDescriptor.FieldType.TEXTFIELD,
+        LabelFieldDescriptor.LabelType.SECONDARY, UIFactory.PATH_FIELD_SIZE));
+
+    hm.put(FieldName.NUMBER_ENTRIES, new LabelFieldDescriptor(
+        getMsg("number-entries-label"), getMsg("number-entries-tooltip"),
+        LabelFieldDescriptor.FieldType.TEXTFIELD,
+        LabelFieldDescriptor.LabelType.SECONDARY,
+        UIFactory.NUMBER_ENTRIES_FIELD_SIZE));
+
+    for (FieldName fieldName : hm.keySet())
+    {
+      JTextComponent field;
+      LabelFieldDescriptor desc = hm.get(fieldName);
+
+      String defaultValue = getDefaultStringValue(fieldName);
+      field = makeJTextComponent(desc, defaultValue);
+
+      hmFields.put(fieldName, field);
+
+      JLabel l = makeJLabel(desc);
+
+      l.setLabelFor(field);
+
+      hmLabels.put(fieldName, l);
+    }
+
+    JLabel dataLabel =
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+            getMsg("directory-data-label"),
+            UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+
+    hmLabels.put(FieldName.DATA_OPTIONS, dataLabel);
+
+    String[] arg =
+      { getDefaultStringValue(FieldName.DIRECTORY_BASE_DN) };
+    JRadioButton rb =
+        UIFactory.makeJRadioButton(getMsg("create-base-entry-label", arg),
+            getMsg("create-base-entry-tooltip"),
+            UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+    hmRadioButtons.put(DataOptions.Type.CREATE_BASE_ENTRY, rb);
+
+    dataLabel.setLabelFor(rb);
+
+    rb =
+        UIFactory.makeJRadioButton(getMsg("leave-database-empty-label"),
+            getMsg("leave-database-empty-tooltip"),
+            UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+    hmRadioButtons.put(DataOptions.Type.LEAVE_DATABASE_EMPTY, rb);
+
+    rb =
+        UIFactory.makeJRadioButton(getMsg("import-data-from-ldif-label"),
+            getMsg("import-data-from-ldif-tooltip"),
+            UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+    hmRadioButtons.put(DataOptions.Type.IMPORT_FROM_LDIF_FILE, rb);
+
+    rb =
+        UIFactory.makeJRadioButton(
+            getMsg("import-automatically-generated-label"),
+            getMsg("import-automatically-generated-tooltip"),
+            UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+    hmRadioButtons
+        .put(DataOptions.Type.IMPORT_AUTOMATICALLY_GENERATED_DATA, rb);
+
+    DataOptions.Type defaultType =
+        (DataOptions.Type) getDefaultValue(FieldName.DATA_OPTIONS);
+
+    ButtonGroup buttonGroup = new ButtonGroup();
+    for (DataOptions.Type type : hmRadioButtons.keySet())
+    {
+      rb = hmRadioButtons.get(type);
+      rb.setOpaque(false);
+      rb.setSelected(type == defaultType);
+      buttonGroup.add(rb);
+    }
+  }
+
+  /**
+   * Returns the browse button to browse LDIF files.
+   * If it does not exist creates the browse button to browse LDIF files.
+   * @return the browse button to browse LDIF files.
+   */
+  private JButton getLDIFBrowseButton()
+  {
+    if (ldifBrowseButton == null)
+    {
+      ldifBrowseButton =
+          UIFactory.makeJButton(getMsg("browse-button-label"),
+              getMsg("browse-button-tooltip"));
+
+      BrowseActionListener l =
+          new BrowseActionListener(getField(FieldName.LDIF_PATH),
+              BrowseActionListener.BrowseType.OPEN_LDIF_FILE, getMainWindow());
+      ldifBrowseButton.addActionListener(l);
+    }
+    return ldifBrowseButton;
+  }
+
+
+  /**
+   * Adds all the required document listeners to the fields.
+   */
+  private void addDocumentListeners()
+  {
+    JTextComponent tf = getField(FieldName.DIRECTORY_BASE_DN);
+    tf.getDocument().addDocumentListener(new DocumentListener()
+    {
+      public void changedUpdate(DocumentEvent ev)
+      {
+        String[] arg =
+          { (String) getFieldValue(FieldName.DIRECTORY_BASE_DN) };
+
+        String newLabel = getMsg("create-base-entry-label", arg);
+        JRadioButton rb =
+          getRadioButton(DataOptions.Type.CREATE_BASE_ENTRY);
+        rb.setText(newLabel);
+      }
+
+      public void insertUpdate(DocumentEvent ev)
+      {
+        changedUpdate(ev);
+      }
+
+      public void removeUpdate(DocumentEvent ev)
+      {
+        changedUpdate(ev);
+      }
+    });
+  }
+
+  /**
+   * Adds the required focus listeners to the fields.
+   */
+  private void addFocusListeners()
+  {
+    final FocusListener l = new FocusListener()
+    {
+      public void focusGained(FocusEvent e)
+      {
+        lastFocusComponent = e.getComponent();
+        if (lastFocusComponent == getField(FieldName.LDIF_PATH))
+        {
+          getRadioButton(DataOptions.Type.IMPORT_FROM_LDIF_FILE).setSelected(
+              true);
+        } else if (lastFocusComponent == getField(FieldName.NUMBER_ENTRIES))
+        {
+          getRadioButton(
+              DataOptions.Type.IMPORT_AUTOMATICALLY_GENERATED_DATA)
+              .setSelected(true);
+        }
+      }
+
+      public void focusLost(FocusEvent e)
+      {
+      }
+    };
+
+    for (JTextComponent tf : hmFields.values())
+    {
+      tf.addFocusListener(l);
+    }
+    for (JRadioButton rb : hmRadioButtons.values())
+    {
+      rb.addFocusListener(l);
+    }
+    getLDIFBrowseButton().addFocusListener(l);
+
+    lastFocusComponent = getField(FieldName.DIRECTORY_BASE_DN);
+  }
+
+  /**
+   * Returns the label associated with the given field name.
+   * @param fieldName the field name for which we want to retrieve the JLabel.
+   * @return the label associated with the given field name.
+   */
+  private JLabel getLabel(FieldName fieldName)
+  {
+    return hmLabels.get(fieldName);
+  }
+
+  /**
+   * Returns the JTextComponent associated with the given field name.
+   * @param fieldName the field name for which we want to retrieve the
+   * JTextComponent.
+   * @return the JTextComponent associated with the given field name.
+   */
+  private JTextComponent getField(FieldName fieldName)
+  {
+    return hmFields.get(fieldName);
+  }
+
+  /**
+   * Returns the JRadioButton associated with the given DataOptions.Type.
+   * @param type the DataOptions.Type object for which we want to retrieve the
+   * JRadioButton.
+   * @return the JRadioButton associated with the given DataOptions.Type object.
+   */
+  private JRadioButton getRadioButton(DataOptions.Type type)
+  {
+    return hmRadioButtons.get(type);
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java
new file mode 100644
index 0000000..f82a9a2
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java
@@ -0,0 +1,186 @@
+/*
+ * 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.AlphaComposite;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.Box;
+import javax.swing.Icon;
+import javax.swing.JPanel;
+
+/**
+ * This class is the panel that is displayed in the QuickSetupDialog.  It
+ * contains 3 panels that are passed in the constructor: the steps panel,
+ * the buttons panel and the current step panel (the main panel of the three).
+ *
+ * The only remarkable thing of this class is that is responsible for
+ * implementing the background.  The three subpanels are transparent and
+ * this class sets a background (with the Open DS logo) and uses some basic
+ * transparency effects.
+ *
+ */
+class FramePanel extends JPanel
+{
+  private static final long serialVersionUID = 7733658951410876078L;
+
+  private Icon backgroundIcon;
+
+  private Component stepsPanel;
+
+  private Component buttonsPanel;
+
+  private int buttonsPanelVerticalInsets;
+
+  private int stepsPanelHorizontalInsets;
+
+  /**
+   * The constructor of the FramePanel.
+   * @param stepsPanel the steps panel that on the top-left side of the
+   * QuickSetupDialog.
+   * @param currentStepPanel the current step panel (the panel that displays
+   * what is associated to the current step).  Is the panel that contains all
+   * the input fields and is located on the top-right side of the
+   * QuickSetupDialog.
+   * @param buttonsPanel the buttons panel that appears on the bottom of the
+   * QuickSetupDialog.
+   */
+  public FramePanel(Component stepsPanel, Component currentStepPanel,
+      Component buttonsPanel)
+  {
+    super(new GridBagLayout());
+    setBackground(UIFactory.DEFAULT_BACKGROUND);
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    gbc.weighty = 1.0;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.fill = GridBagConstraints.VERTICAL;
+    gbc.insets = UIFactory.getStepsPanelInsets();
+    add(stepsPanel, gbc);
+
+    stepsPanelHorizontalInsets = gbc.insets.left + gbc.insets.right;
+
+    JPanel currentPanelContainer = new JPanel(new GridBagLayout());
+    currentPanelContainer.setBorder(UIFactory.CURRENT_STEP_PANEL_BORDER);
+    currentPanelContainer
+        .setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+    currentPanelContainer.setOpaque(false);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.weighty = 1.0;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.insets = UIFactory.getCurrentStepPanelInsets();
+    currentPanelContainer.add(currentStepPanel, gbc);
+    gbc.insets = UIFactory.getEmptyInsets();
+    add(currentPanelContainer, gbc);
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    gbc.weighty = 0.0;
+    add(Box.createHorizontalGlue(), gbc);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.weighty = 0.0;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.insets = UIFactory.getButtonsPanelInsets();
+    add(buttonsPanel, gbc);
+
+    buttonsPanelVerticalInsets = gbc.insets.top + gbc.insets.bottom;
+
+    backgroundIcon =
+      UIFactory.getImageIcon(UIFactory.IconType.BACKGROUND);
+
+    this.buttonsPanel = buttonsPanel;
+    this.stepsPanel = stepsPanel;
+    int width =
+        Math.max((int) getPreferredSize().getWidth(), backgroundIcon
+            .getIconWidth()
+            + UIFactory.LEFT_INSET_BACKGROUND
+            + UIFactory.RIGHT_INSET_BACKGROUND);
+    int height =
+        Math.max((int) getPreferredSize().getHeight(), backgroundIcon
+            .getIconHeight()
+            + UIFactory.TOP_INSET_BACKGROUND
+            + UIFactory.BOTTOM_INSET_BACKGROUND);
+    setPreferredSize(new Dimension(width, height));
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   * This method has been overwritten to be able to have a transparency effect
+   * with the OpenDS logo background.
+   */
+  protected void paintComponent(Graphics g)
+  {
+    if (isOpaque())
+    { // paint background
+      g.setColor(UIFactory.DEFAULT_BACKGROUND);
+      int width = getWidth();
+      int height = getHeight();
+      int buttonsTotalHeight =
+          buttonsPanel.getHeight() + buttonsPanelVerticalInsets;
+      int stepsPanelTotalWidth =
+          stepsPanel.getWidth() + stepsPanelHorizontalInsets;
+
+      g.fillRect(0, 0, stepsPanelTotalWidth, height);
+      g.fillRect(stepsPanelTotalWidth, height - buttonsTotalHeight, width,
+          height);
+      g.setColor(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+      g.fillRect(stepsPanelTotalWidth, 0, width, height - buttonsTotalHeight);
+    }
+
+    if (backgroundIcon != null)
+    {
+      // Draw the icon over and over, right aligned.
+      // Copy the Graphics object, which is actually
+      // a Graphics2D object. Cast it so we can
+      // set alpha composite.
+      Graphics2D g2d = (Graphics2D) g.create();
+
+      g2d.setComposite(AlphaComposite
+          .getInstance(AlphaComposite.SRC_OVER, 0.1f));
+
+      backgroundIcon.paintIcon(this, g2d, UIFactory.LEFT_INSET_BACKGROUND,
+          UIFactory.TOP_INSET_BACKGROUND);
+
+      g2d.dispose(); //clean up
+    }
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
new file mode 100644
index 0000000..5b3a03d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
@@ -0,0 +1,211 @@
+/*
+ * 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.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.Box;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.Installer;
+
+/**
+ * This panel is used to show the progress of the install or the uninstall.
+ *
+ */
+public class ProgressPanel extends QuickSetupStepPanel
+{
+  private static final long serialVersionUID = 8129425068163357170L;
+
+  private JEditorPane progressBarLabel;
+
+  private JProgressBar progressBar;
+
+  private JEditorPane detailsTextArea;
+
+  private JScrollPane scroll;
+
+  private String lastText;
+
+  /**
+   * ProgressPanel constructor.
+   */
+  public ProgressPanel()
+  {
+    createLayout();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Component createInputPanel()
+  {
+    JPanel panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+
+    progressBarLabel =
+        UIFactory.makeHtmlPane(getMsg("progressbar-initial-label"),
+            UIFactory.PROGRESS_FONT);
+    progressBarLabel.addHyperlinkListener(this);
+    panel.add(progressBarLabel, gbc);
+
+    gbc.insets.top = UIFactory.TOP_INSET_PROGRESS_BAR;
+    gbc.insets.bottom = UIFactory.BOTTOM_INSET_PROGRESS_BAR;
+    panel.add(createProgressBarPanel(), gbc);
+    progressBar.setToolTipText(getMsg("progressbar-tooltip"));
+
+    JLabel l =
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+            getMsg("progress-details-label"),
+            UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+
+    gbc.insets = UIFactory.getEmptyInsets();
+    panel.add(l, gbc);
+
+    scroll = new JScrollPane();
+    detailsTextArea = UIFactory.makeProgressPane(scroll);
+    detailsTextArea.setBackground(
+        UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+    detailsTextArea.addHyperlinkListener(new HyperlinkListener()
+    {
+      public void hyperlinkUpdate(HyperlinkEvent e)
+      {
+        if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+        {
+          String url = e.getURL().toString();
+          String newText = Installer.getHtmlAfterUrlClick(url, lastText);
+          lastText = newText;
+          detailsTextArea.setText(lastText);
+        }
+      }
+    });
+    detailsTextArea.setAutoscrolls(true);
+    scroll.setViewportView(detailsTextArea);
+
+    scroll.setBorder(UIFactory.TEXT_AREA_BORDER);
+    scroll.setWheelScrollingEnabled(true);
+    l.setLabelFor(detailsTextArea);
+    gbc.insets.top = UIFactory.TOP_INSET_PROGRESS_TEXTAREA;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.weighty = 1.0;
+    panel.add(scroll, gbc);
+
+    return panel;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getInstructions()
+  {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getTitle()
+  {
+    return getMsg("progress-panel-title");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void displayProgress(InstallProgressDescriptor descriptor)
+  {
+    progressBarLabel.setText(UIFactory.applyFontToHtml(descriptor
+        .getProgressBarMsg(), UIFactory.PROGRESS_FONT));
+    InstallProgressStep status = descriptor.getProgressStep();
+    if ((status == InstallProgressStep.FINISHED_WITH_ERROR)
+        || (status == InstallProgressStep.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.
+   */
+  private JPanel createProgressBarPanel()
+  {
+    JPanel panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+
+    progressBar = new JProgressBar();
+    progressBar.setIndeterminate(true);
+    // The ProgressDescriptor provides the ratio in %
+    progressBar.setMaximum(100);
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    panel.add(Box.createHorizontalStrut(UIFactory.PROGRESS_BAR_SIZE), gbc);
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    panel.add(Box.createHorizontalGlue(), gbc);
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    panel.add(progressBar, gbc);
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    panel.add(Box.createHorizontalGlue(), gbc);
+
+    return panel;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
new file mode 100644
index 0000000..4d85afd
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
@@ -0,0 +1,682 @@
+/*
+ * 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.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.HashSet;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.opends.quicksetup.ButtonName;
+import org.opends.quicksetup.CurrentInstallStatus;
+import org.opends.quicksetup.Step;
+import org.opends.quicksetup.event.ButtonActionListener;
+import org.opends.quicksetup.event.ButtonEvent;
+import org.opends.quicksetup.event.MinimumSizeComponentListener;
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class represents the dialog used by installer and the uninstaller.
+ *
+ * In its constructor it gets as parameters an object describing the current
+ * installation status and the default values to be proposed to the user
+ * in the panels.
+ *
+ * If we are installing Open DS and the server has already been installed it
+ * will display an error message.  In the other cases it will display a wizard
+ * (that is different depending on whether we are installing or uninstalling).
+ *
+ */
+public class QuickSetupDialog
+{
+  private JFrame frame;
+
+  private QuickSetupErrorPanel installedPanel;
+
+  private JPanel framePanel;
+
+  private StepsPanel stepsPanel;
+
+  private CurrentStepPanel currentStepPanel;
+
+  private ButtonsPanel buttonsPanel;
+
+  private Step displayedStep;
+
+  private UserInstallData defaultUserData;
+
+  private CurrentInstallStatus installStatus;
+
+  private HashSet<ButtonActionListener> buttonListeners =
+      new HashSet<ButtonActionListener>();
+
+  /**
+   * Constructor of QuickSetupDialog.
+   * @param defaultUserData the default values to be proposed to the user in
+   * the wizard.
+   * @param installStatus the current installation status.
+   */
+  public QuickSetupDialog(UserInstallData defaultUserData,
+      CurrentInstallStatus installStatus)
+  {
+    this.defaultUserData = defaultUserData;
+    this.installStatus = installStatus;
+
+    if (isUninstall())
+    {
+      frame = new JFrame(getMsg("frame-uninstall-title"));
+    } else
+    {
+      frame = new JFrame(getMsg("frame-quicksetup-title"));
+    }
+
+    frame.getContentPane().add(getFramePanel());
+    frame.addWindowListener(new WindowAdapter()
+    {
+      public void windowClosing(WindowEvent e)
+      {
+        if (isUninstall())
+        {
+          if (getDisplayedStep() == Step.PROGRESS)
+          {
+            // Simulate a close button event
+            notifyButtonEvent(ButtonName.CLOSE);
+          } else
+          {
+            // Simulate a quit button event
+            notifyButtonEvent(ButtonName.QUIT);
+          }
+        } else if (isInstalled())
+        {
+          // Simulate a close button event
+          notifyButtonEvent(ButtonName.CLOSE);
+        } else
+        {
+          if (getDisplayedStep() == Step.PROGRESS)
+          {
+            // Simulate a close button event
+            notifyButtonEvent(ButtonName.CLOSE);
+          } else
+          {
+            // Simulate a quit button event
+            notifyButtonEvent(ButtonName.QUIT);
+          }
+        }
+      }
+    });
+    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+    UIFactory.IconType ic;
+    if (Utils.isMacOS())
+    {
+      ic = UIFactory.IconType.MINIMIZED_MAC;
+    } else
+    {
+      ic = UIFactory.IconType.MINIMIZED;
+    }
+    frame.setIconImage(UIFactory.getImageIcon(ic).getImage());
+  }
+
+  /**
+   * Packs and displays this dialog.
+   *
+   */
+  public void packAndShow()
+  {
+    frame.pack();
+    int minWidth = (int) frame.getPreferredSize().getWidth();
+    int minHeight = (int) frame.getPreferredSize().getHeight();
+    Utils.centerOnScreen(frame);
+    if (isUninstall())
+    {
+      setFocusOnButton(ButtonName.FINISH);
+    } else if (!isInstalled())
+    {
+      setFocusOnButton(ButtonName.NEXT);
+    } else
+    {
+      setFocusOnButton(ButtonName.QUIT);
+    }
+
+    frame.addComponentListener(new MinimumSizeComponentListener(frame,
+        minWidth, minHeight));
+
+    frame.setVisible(true);
+  }
+
+  /**
+   * Displays the panel corresponding to the provided step.  The panel contents
+   * are updated with the contents of the UserInstallData object.
+   * @param step the step that we want to display.
+   * @param userData the UserInstallData object that must be used to populate
+   * the panels.
+   */
+  public void setDisplayedStep(Step step, UserInstallData userData)
+  {
+    displayedStep = step;
+    if (isUninstall())
+    {
+      // First call the panels to do the required updates on their layout
+      getButtonsPanel().setDisplayedStep(step);
+      getStepsPanel().setDisplayedStep(step);
+      getCurrentStepPanel().setDisplayedStep(step, userData);
+
+      // Set the default button for the frame
+      switch (step)
+      {
+      case CONFIRM_UNINSTALL:
+        setDefaultButton(ButtonName.FINISH);
+        break;
+
+      case PROGRESS:
+        setDefaultButton(ButtonName.CLOSE);
+        break;
+      }
+
+      // Set the focus for the current step
+      switch (step)
+      {
+      case CONFIRM_UNINSTALL:
+        setFocusOnButton(ButtonName.FINISH);
+        break;
+
+      case PROGRESS:
+        setFocusOnButton(ButtonName.CLOSE);
+        setButtonEnabled(ButtonName.CLOSE, false);
+        break;
+      }
+    } else if (!isInstalled())
+    {
+      // First call the panels to do the required updates on their layout
+      getButtonsPanel().setDisplayedStep(step);
+      getStepsPanel().setDisplayedStep(step);
+      getCurrentStepPanel().setDisplayedStep(step, userData);
+
+      // Set the default button for the frame
+      switch (step)
+      {
+      case REVIEW:
+        setDefaultButton(ButtonName.FINISH);
+        break;
+
+      case PROGRESS:
+        setDefaultButton(ButtonName.CLOSE);
+        break;
+
+      default:
+        setDefaultButton(ButtonName.NEXT);
+      }
+
+      // Set the focus for the current step
+      switch (step)
+      {
+      case WELCOME:
+        setFocusOnButton(ButtonName.NEXT);
+        break;
+
+      case SERVER_SETTINGS:
+        // The focus is set by the panel itself
+        break;
+
+      case DATA_OPTIONS:
+        // The focus is set by the panel itself
+        break;
+
+      case REVIEW:
+        setFocusOnButton(ButtonName.FINISH);
+        break;
+
+      case PROGRESS:
+        setFocusOnButton(ButtonName.CLOSE);
+        setButtonEnabled(ButtonName.CLOSE, false);
+        break;
+      }
+    }
+  }
+
+  /**
+   * Returns the currently displayed step.
+   * @return the currently displayed step.
+   */
+  public Step getDisplayedStep()
+  {
+    return displayedStep;
+  }
+
+  /**
+   * Forwards to the displayed panel the InstallProgressDescriptor so that they
+   * can update their contents accordingly.
+   * @param descriptor the descriptor of the Installation progress.
+   */
+  public void displayProgress(InstallProgressDescriptor descriptor)
+  {
+    getCurrentStepPanel().displayProgress(descriptor);
+    InstallProgressStep status = descriptor.getProgressStep();
+    if ((status == InstallProgressStep.FINISHED_SUCCESSFULLY)
+        || (status == InstallProgressStep.FINISHED_WITH_ERROR))
+    {
+      setButtonEnabled(ButtonName.CLOSE, true);
+    }
+  }
+
+  /**
+   * Displays an error message dialog.
+   *
+   * @param msg
+   *          the error message.
+   * @param title
+   *          the title for the dialog.
+   */
+  public void displayError(String msg, String title)
+  {
+    JOptionPane.showMessageDialog(getFrame(), msg, title,
+        JOptionPane.ERROR_MESSAGE);
+  }
+
+  /**
+   * Displays a confirmation message 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 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
+  }
+
+  /**
+   * Returns the value corresponding to the provided FieldName.
+   * @param fieldName the FieldName for which we want to obtain the value.
+   * @return the value corresponding to the provided FieldName.
+   */
+  public Object getFieldValue(FieldName fieldName)
+  {
+    return getCurrentStepPanel().getFieldValue(fieldName);
+  }
+
+  /**
+   * Marks as invalid (or valid depending on the value of the invalid parameter)
+   * a field corresponding to FieldName.  This basically implies udpating the
+   * style of the JLabel associated with fieldName (the association is done
+   * using the LabelFieldDescriptor class).
+   * @param fieldName the FieldName to be marked as valid or invalid.
+   * @param invalid whether to mark the field as valid or invalid.
+   */
+  public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+  {
+    getCurrentStepPanel().displayFieldInvalid(fieldName, invalid);
+  }
+
+  /**
+   * Adds a button listener.  All the button listeners will be notified when
+   * the buttons are clicked (by the user or programatically).
+   * @param l the ButtonActionListener to be added.
+   */
+  public void addButtonActionListener(ButtonActionListener l)
+  {
+    if (isUninstall())
+    {
+      getButtonsPanel().addButtonActionListener(l);
+    } else if (isInstalled())
+    {
+      getInstalledPanel().addButtonActionListener(l);
+    } else
+    {
+      getButtonsPanel().addButtonActionListener(l);
+    }
+    buttonListeners.add(l);
+  }
+
+  /**
+   * Removes a button listener.
+   * @param l the ButtonActionListener to be removed.
+   */
+  public void removeButtonActionListener(ButtonActionListener l)
+  {
+    if (isUninstall())
+    {
+      getButtonsPanel().removeButtonActionListener(l);
+    } else if (isInstalled())
+    {
+      getInstalledPanel().removeButtonActionListener(l);
+    } else
+    {
+      getButtonsPanel().removeButtonActionListener(l);
+    }
+    buttonListeners.remove(l);
+  }
+
+  /**
+   * This method is called to inform that a worker has started (the QuickSetup
+   * is doing some data validation).  The worker is doing its tasks outside
+   * the event thread to avoid blocking of the painting and this class is
+   * notified of this fact.  The method basically simply the Next and Previous
+   * buttons.
+   *
+   * This method can be called from the event thread or outside the event
+   * thread.
+   *
+   */
+  public void workerStarted()
+  {
+    Runnable r = new Runnable()
+    {
+      public void run()
+      {
+        // TODO: here we could have an animated gif.
+        setButtonEnabled(ButtonName.NEXT, false);
+        setButtonEnabled(ButtonName.PREVIOUS, false);
+      }
+    };
+    runOnEventThread(r);
+  }
+
+  /**
+   * This method is called to inform that a worker has finished. The method just
+   * enables the Next and Previous buttons.
+   *
+   * This method can be called from the event thread or outside the event
+   * thread.
+   *
+   */
+  public void workerFinished()
+  {
+    Runnable r = new Runnable()
+    {
+      public void run()
+      {
+        // TO COMPLETE: here we could have an animated gif.
+        setButtonEnabled(ButtonName.NEXT, true);
+        setButtonEnabled(ButtonName.PREVIOUS, true);
+      }
+    };
+    runOnEventThread(r);
+  }
+
+  /**
+   * Notification from the worker with a message.
+   * @param msg the message sent by the worker.
+   */
+  public void workerMessage(String msg)
+  {
+    // TODO For the moment not used.
+  }
+
+  /**
+   * Notification telling that the installation/uninstallation is finished.
+   * @param successful a boolean telling whether the setup was successful or
+   * not.
+   */
+  public void finished(boolean successful)
+  {
+    setButtonEnabled(ButtonName.CLOSE, true);
+    if (!successful)
+    {
+      // Do nothing... all the error messages
+    }
+  }
+
+  /**
+   * 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.
+   */
+  private void setButtonEnabled(ButtonName buttonName, boolean enable)
+  {
+    getButton(buttonName).setEnabled(enable);
+  }
+
+  /**
+   * 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.
+   */
+  private JPanel getFramePanel()
+  {
+    JPanel p;
+    if (isUninstall())
+    {
+      if (framePanel == null)
+      {
+        framePanel =
+            new FramePanel(getStepsPanel(), getCurrentStepPanel(),
+                getButtonsPanel());
+      }
+      p = framePanel;
+    } else if (isInstalled())
+    {
+      p = getInstalledPanel();
+    } else
+    {
+      if (framePanel == null)
+      {
+        framePanel =
+            new FramePanel(getStepsPanel(), getCurrentStepPanel(),
+                getButtonsPanel());
+      }
+      p = framePanel;
+    }
+    return p;
+  }
+
+  /**
+   * Returns the steps panel.
+   * @return the steps panel.
+   */
+  private StepsPanel getStepsPanel()
+  {
+    if (stepsPanel == null)
+    {
+      stepsPanel = new StepsPanel(isUninstall());
+    }
+    return stepsPanel;
+  }
+
+  /**
+   * Returns the current step panel.
+   * @return the current step panel.
+   */
+  private CurrentStepPanel getCurrentStepPanel()
+  {
+    if (currentStepPanel == null)
+    {
+      currentStepPanel = new CurrentStepPanel(defaultUserData, isUninstall());
+    }
+    return currentStepPanel;
+  }
+
+
+  /**
+   * Returns the buttons panel.
+   * @return the buttons panel.
+   */
+  private ButtonsPanel getButtonsPanel()
+  {
+    if (buttonsPanel == null)
+    {
+      buttonsPanel = new ButtonsPanel();
+    }
+    return buttonsPanel;
+  }
+
+  /* Different commodity methods to retrieve localized messages */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  /**
+   * Returns the button corresponding to the buttonName.
+   * @param buttonName the ButtonName for which we want to get the button.
+   * @return the button corresponding to the buttonName.
+   */
+  private JButton getButton(ButtonName buttonName)
+  {
+    JButton button;
+    if (isUninstall())
+    {
+      button = getButtonsPanel().getButton(buttonName);
+    } else if (isInstalled())
+    {
+      if (buttonName == ButtonName.QUIT)
+      {
+        button = getInstalledPanel().getQuitButton();
+      } else
+      {
+        throw new IllegalStateException("Invalid button name " + buttonName
+            + " if server is installed");
+      }
+    } else
+    {
+      button = getButtonsPanel().getButton(buttonName);
+    }
+    return button;
+  }
+
+  /**
+   * Sets the focus in the button associated with the ButtonName.
+   * @param buttonName the ButtonName associated with the button.
+   */
+  private void setFocusOnButton(ButtonName buttonName)
+  {
+    getButton(buttonName).requestFocusInWindow();
+  }
+
+  /**
+   * Sets the default button for the frame.
+   * @param buttonName the ButtonName associated with the button.
+   */
+  private void setDefaultButton(ButtonName buttonName)
+  {
+    getFrame().getRootPane().setDefaultButton(getButton(buttonName));
+  }
+
+  /**
+   * Method used to execute a Runnable in the event thread.  If we are in the
+   * event thread it will be called synchronously and if we are not it will
+   * be executed asynchronously.
+   *
+   * @param r the Runnable to be executed.
+   */
+  private void runOnEventThread(Runnable r)
+  {
+    if (SwingUtilities.isEventDispatchThread())
+    {
+      r.run();
+    } else
+    {
+      SwingUtilities.invokeLater(r);
+    }
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if this is an uninstallation and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if this is an uninstallation and
+   * <CODE>false</CODE> otherwise.
+   */
+  private boolean isUninstall()
+  {
+    return Utils.isUninstall();
+  }
+
+
+  /**
+   * Returns <CODE>true</CODE> if the server is already installed and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if the server is already installed and
+   * <CODE>false</CODE> otherwise.
+   */
+  private boolean isInstalled()
+  {
+    return installStatus.isInstalled();
+  }
+
+  /**
+   * Returns (and creates if it is not already created) the panel that
+   * informs the user that the server is already installed when the
+   * installation has been launched.
+   * @return the panel that is used
+   * to inform the user that the server is already installed when the
+   * installation has been launched.
+   */
+  private QuickSetupErrorPanel getInstalledPanel()
+  {
+    if (installedPanel == null)
+    {
+      installedPanel =
+          new QuickSetupErrorPanel(installStatus.getInstallationMsg());
+    }
+    return installedPanel;
+  }
+
+  /**
+   * Notifies the ButtonActionListener objects that an ButtonEvent has occurred
+   * in the button associated with buttonName.
+   * @param buttonName the ButtonName associated with the button.
+   */
+  private void notifyButtonEvent(ButtonName buttonName)
+  {
+    ButtonEvent be = new ButtonEvent(this, buttonName);
+    for (ButtonActionListener li : buttonListeners)
+    {
+      li.buttonActionPerformed(be);
+    }
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
new file mode 100644
index 0000000..7a046c8
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
@@ -0,0 +1,160 @@
+/*
+ * 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.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashSet;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.ButtonName;
+import org.opends.quicksetup.event.ButtonActionListener;
+import org.opends.quicksetup.event.ButtonEvent;
+
+/**
+ * This class is a panel that contains an error message and a quit button.
+ * It is used for instance when we try to install Open DS but it is already
+ * installed.
+ *
+ */
+public class QuickSetupErrorPanel extends QuickSetupPanel
+{
+  private static final long serialVersionUID = 1765037717593522233L;
+
+  private HashSet<ButtonActionListener> buttonListeners =
+      new HashSet<ButtonActionListener>();
+
+  private JButton quitButton;
+
+  /**
+   * Constructor of the QuickSetupErrorPanel.
+   *
+   * @param htmlMsg the error message to be displayed.
+   */
+  public QuickSetupErrorPanel(String htmlMsg)
+  {
+    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.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.insets.left = 0;
+    JTextComponent tf =
+        UIFactory.makeHtmlPane(htmlMsg, UIFactory.INSTRUCTIONS_FONT);
+    tf.setOpaque(false);
+    p1.add(tf, gbc);
+
+    gbc.weighty = 1.0;
+    gbc.fill = GridBagConstraints.VERTICAL;
+    p1.add(Box.createVerticalGlue(), gbc);
+
+    JPanel p2 = new JPanel(new GridBagLayout());
+    p2.setOpaque(false);
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 1.0;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    p2.add(Box.createHorizontalGlue(), gbc);
+    quitButton =
+        UIFactory.makeJButton(getMsg("quit-button-label"),
+            getMsg("quit-button-tooltip"));
+
+    final ButtonName fButtonName = ButtonName.QUIT;
+
+    ActionListener actionListener = new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        ButtonEvent be = new ButtonEvent(ev.getSource(), fButtonName);
+        for (ButtonActionListener li : buttonListeners)
+        {
+          li.buttonActionPerformed(be);
+        }
+      }
+    };
+    quitButton.addActionListener(actionListener);
+
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.weightx = 0.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    p2.add(quitButton, gbc);
+
+    setLayout(new GridBagLayout());
+    setBackground(UIFactory.DEFAULT_BACKGROUND);
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.weighty = 1.0;
+    add(p1, gbc);
+    gbc.weighty = 0.0;
+    gbc.insets = UIFactory.getButtonsPanelInsets();
+    add(p2, gbc);
+  }
+
+  /**
+   * Adds a button listener.  All the button listeners will be notified when
+   * the buttons are clicked (by the user or programatically).
+   * @param l the ButtonActionListener to be added.
+   */
+  public void addButtonActionListener(ButtonActionListener l)
+  {
+    buttonListeners.add(l);
+  }
+
+  /**
+   * Removes a button listener.
+   * @param l the ButtonActionListener to be removed.
+   */
+  public void removeButtonActionListener(ButtonActionListener l)
+  {
+    buttonListeners.remove(l);
+  }
+
+  /**
+   * Returns the quit button.
+   * @return the quit button.
+   */
+  public JButton getQuitButton()
+  {
+    return quitButton;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupPanel.java
new file mode 100644
index 0000000..9371bdd
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupPanel.java
@@ -0,0 +1,126 @@
+/*
+ * 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.Component;
+import java.awt.Frame;
+import java.awt.Window;
+
+import javax.swing.JPanel;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+
+/**
+ * This class is an abstract class that provides some commodity methods.
+ *
+ */
+abstract class QuickSetupPanel extends JPanel
+{
+  private static final long serialVersionUID = 2096518919339628055L;
+
+  /**
+   * The basic constructor to be called by the subclasses.
+   *
+   */
+  protected QuickSetupPanel()
+  {
+    super();
+    setOpaque(false);
+  }
+
+  /**
+   * Returns the frame or window containing this panel.
+   * @return the frame or window containing this panel.
+   */
+  public Component getMainWindow()
+  {
+    Component w = null;
+    Component c = this;
+
+    while (w == null)
+    {
+      if (c instanceof Frame || c instanceof Window)
+      {
+        w = c;
+      }
+      if (c.getParent() == null)
+      {
+        w = c;
+      } else
+      {
+        c = c.getParent();
+      }
+    }
+
+    return w;
+  }
+
+  /**
+   * 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.
+   */
+  protected 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.
+   */
+  protected 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();
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
new file mode 100644
index 0000000..0e22ab4
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
@@ -0,0 +1,439 @@
+/*
+ * 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.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.LabelFieldDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.util.URLWorker;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is an abstract class that is extended by all the classes that are in
+ * the CardLayout of CurrentStepPanel.  All the panels that appear on the
+ * top-right side of the dialog extend this class: WelcomePane, ReviewPanel,
+ * etc.
+ *
+ */
+public abstract class QuickSetupStepPanel extends QuickSetupPanel
+implements HyperlinkListener
+{
+  private Component inputPanel;
+
+  // 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 =
+      new HashMap<String, URLWorker>();
+
+  /**
+   * Called just before the panel is shown: used to update the contents of the
+   * panel with new UserData (used in particular in the review panel).
+   *
+   * @param data the new user data.
+   */
+  public void beginDisplay(UserInstallData data)
+  {
+  }
+
+  /**
+   * Called just after the panel is shown: used to set focus properly.
+   */
+  public void endDisplay()
+  {
+  }
+
+  /**
+   * 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 Installation progress.
+   */
+  public void displayProgress(InstallProgressDescriptor descriptor)
+  {
+  }
+
+  /**
+   * Implements HyperlinkListener.  When the user clicks on a link we will
+   * try to display the associated URL in the browser of the user.
+   *
+   * @param e the HyperlinkEvent.
+   */
+  public void hyperlinkUpdate(HyperlinkEvent e)
+  {
+    if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+    {
+      String url = e.getURL().toString();
+      if (!isURLWorkerRunning(url))
+      {
+        /*
+         * Only launch the worker if there is not already a worker trying to
+         * display this URL.
+         */
+        URLWorker worker = new URLWorker(this, url);
+        startWorker(worker);
+      }
+    }
+  }
+
+  /**
+   * Returns the value corresponding to the provided FieldName.
+   * @param fieldName the FieldName for which we want to obtain the value.
+   * @return the value corresponding to the provided FieldName.
+   */
+  public Object getFieldValue(FieldName fieldName)
+  {
+    return null;
+  }
+
+  /**
+   * Sets the specified value in the field associated with the field name.
+   * @param fieldName the field name associated with the field.
+   * @param value the value that must be set.
+   */
+  public void setFieldValue(FieldName fieldName, Object value)
+  {
+  }
+
+  /**
+   * Marks as invalid (or valid depending on the value of the invalid parameter)
+   * a field corresponding to FieldName.  This basically implies udpating the
+   * style of the JLabel associated with fieldName (the association is done
+   * using the LabelFieldDescriptor class).
+   * @param fieldName the FieldName to be marked as valid or invalid.
+   * @param invalid whether to mark the field as valid or invalid.
+   */
+  public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+  {
+  }
+
+  /**
+   * Returns the minimum width of the panel.  This is used to calculate the
+   * minimum widht of the dialog.
+   * @return the minimum width of the panel.
+   */
+  public int getMinimumWidth()
+  {
+    // Just take the preferred width of the inputPanel because the
+    // instructionsPanel
+    // are too wide.
+    int width = 0;
+    if (inputPanel != null)
+    {
+      width = (int) inputPanel.getPreferredSize().getWidth();
+    }
+    return width;
+  }
+
+  /**
+   * Returns the minimum height of the panel.  This is used to calculate the
+   * minimum height of the dialog.
+   * @return the minimum height of the panel.
+   */
+  public int getMinimumHeight()
+  {
+    int height = (int) getPreferredSize().getHeight();
+
+    return height;
+  }
+
+  /**
+   * Creates the layout of the panel.
+   *
+   */
+  protected void createLayout()
+  {
+    setLayout(new GridBagLayout());
+
+    setOpaque(false);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    Component titlePanel = createTitlePanel();
+    Component instructionsPanel = createInstructionsPanel();
+    inputPanel = createInputPanel();
+
+    boolean somethingAdded = false;
+
+    if (titlePanel != null)
+    {
+      gbc.weightx = 1.0;
+      gbc.weighty = 0.0;
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.fill = GridBagConstraints.HORIZONTAL;
+      gbc.anchor = GridBagConstraints.NORTHWEST;
+      gbc.insets.left = 0;
+      add(titlePanel, gbc);
+      somethingAdded = true;
+    }
+
+    if (instructionsPanel != null)
+    {
+      if (somethingAdded)
+      {
+        gbc.insets.top = UIFactory.TOP_INSET_INSTRUCTIONS_SUBPANEL;
+      } else
+      {
+        gbc.insets.top = 0;
+      }
+      gbc.insets.left = 0;
+      gbc.weightx = 1.0;
+      gbc.weighty = 0.0;
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.fill = GridBagConstraints.HORIZONTAL;
+      gbc.anchor = GridBagConstraints.NORTHWEST;
+      add(instructionsPanel, gbc);
+      somethingAdded = true;
+    }
+
+    if (inputPanel != null)
+    {
+      if (somethingAdded)
+      {
+        gbc.insets.top = UIFactory.TOP_INSET_INPUT_SUBPANEL;
+      } else
+      {
+        gbc.insets.top = 0;
+      }
+      gbc.weightx = 1.0;
+      gbc.weighty = 1.0;
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.fill = GridBagConstraints.BOTH;
+      gbc.anchor = GridBagConstraints.NORTHWEST;
+      gbc.insets.left = 0;
+      add(inputPanel, gbc);
+      somethingAdded = true;
+
+    } else
+    {
+      addVerticalGlue(this);
+    }
+  }
+
+  /**
+   * Commodity method that returns a JTextComponent based on a
+   * LabelFieldDescriptor.
+   * @param desc the LabelFieldDescriptor describing the JTextField.
+   * @param defaultValue the default value used to initialize the
+   * JTextComponent.
+   * @return a JTextComponent based on a
+   * LabelFieldDescriptor.
+   */
+  protected JTextComponent makeJTextComponent(LabelFieldDescriptor desc,
+      String defaultValue)
+  {
+    JTextComponent field;
+    switch (desc.getType())
+    {
+    case TEXTFIELD:
+
+      field =
+          UIFactory.makeJTextField(defaultValue, desc.getTooltip(), desc
+              .getSize(), UIFactory.TextStyle.TEXTFIELD);
+      break;
+
+    case PASSWORD:
+
+      field =
+          UIFactory.makeJPasswordField(defaultValue, desc.getTooltip(), desc
+              .getSize(), UIFactory.TextStyle.PASSWORD_FIELD);
+      break;
+
+    case READ_ONLY:
+
+      field =
+          UIFactory.makeTextPane(defaultValue, UIFactory.TextStyle.READ_ONLY);
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknown type: " + desc.getType());
+    }
+    return field;
+  }
+
+  /**
+   * Commodity method that returns a JLabel based on a LabelFieldDescriptor.
+   * @param desc the LabelFieldDescriptor describing the JLabel.
+   * @return a JLabel based on a LabelFieldDescriptor.
+   */
+  protected JLabel makeJLabel(LabelFieldDescriptor desc)
+  {
+    UIFactory.TextStyle style;
+    if (desc.getLabelType() == LabelFieldDescriptor.LabelType.PRIMARY)
+    {
+      style = UIFactory.TextStyle.PRIMARY_FIELD_VALID;
+    } else
+    {
+      style = UIFactory.TextStyle.SECONDARY_FIELD_VALID;
+    }
+    return UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, desc.getLabel(),
+        style);
+  }
+
+  /**
+   * Creates and returns the panel that contains the layout specific to the
+   * panel.
+   * @return the panel that contains the layout specific to the
+   * panel.
+   */
+  protected abstract Component createInputPanel();
+
+  /**
+   * Returns the title of this panel.
+   * @return the title of this panel.
+   */
+  protected abstract String getTitle();
+
+  /**
+   * Returns the instruction of this panel.
+   * @return the instruction of this panel.
+   */
+  protected abstract String getInstructions();
+
+  /**
+   * Commodity method that adds a vertical glue at the bottom of a given panel.
+   * @param panel the panel to which we want to add a vertical glue.
+   */
+  protected void addVerticalGlue(JPanel panel)
+  {
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.weighty = 1.0;
+    gbc.fill = GridBagConstraints.VERTICAL;
+    panel.add(Box.createVerticalGlue(), gbc);
+  }
+
+  /**
+   * This method is called by the URLWorker when it has finished its task.
+   * @param worker the URLWorker that finished its task.
+   */
+  public void urlWorkerFinished(URLWorker worker)
+  {
+    hmURLWorkers.remove(worker.getURL());
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if this is a WebStart based installer and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if this is a WebStart based installer and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean isWebStart()
+  {
+    return Utils.isWebStart();
+  }
+
+  /**
+   * Creates and returns the title panel.
+   * @return the title panel.
+   */
+  private Component createTitlePanel()
+  {
+    Component titlePanel = null;
+    String title = getTitle();
+    if (title != null)
+    {
+      JPanel p = new JPanel(new GridBagLayout());
+      p.setOpaque(false);
+      GridBagConstraints gbc = new GridBagConstraints();
+      gbc.anchor = GridBagConstraints.NORTHWEST;
+      gbc.fill = GridBagConstraints.HORIZONTAL;
+      gbc.weightx = 0.0;
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+
+      JLabel l =
+          UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title,
+              UIFactory.TextStyle.TITLE);
+      p.add(l, gbc);
+
+      gbc.weightx = 1.0;
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      p.add(Box.createHorizontalGlue(), gbc);
+
+      titlePanel = p;
+    }
+    return titlePanel;
+  }
+
+  /**
+   * Creates and returns the instructions panel.
+   * @return the instructions panel.
+   */
+  private Component createInstructionsPanel()
+  {
+    Component instructionsPanel = null;
+    String instructions = getInstructions();
+    if (instructions != null)
+    {
+
+      JEditorPane p =
+          UIFactory.makeHtmlPane(instructions, UIFactory.INSTRUCTIONS_FONT);
+      p.setOpaque(false);
+      p.setEditable(false);
+      p.addHyperlinkListener(this);
+      instructionsPanel = p;
+    }
+    return instructionsPanel;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if there is URLWorker running for the given url
+   * and <CODE>false</CODE> otherwise.
+   * @param url the url.
+   * @return <CODE>true</CODE> if there is URLWorker running for the given url
+   * and <CODE>false</CODE> otherwise.
+   */
+  private boolean isURLWorkerRunning(String url)
+  {
+    return hmURLWorkers.get(url) != null;
+  }
+
+  /**
+   * Starts a worker.
+   * @param worker the URLWorker to be started.
+   */
+  private void startWorker(URLWorker worker)
+  {
+    hmURLWorkers.put(worker.getURL(), worker);
+    worker.startBackgroundTask();
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java
new file mode 100644
index 0000000..efa0922
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java
@@ -0,0 +1,358 @@
+/*
+ * 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.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.HashMap;
+
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.installer.DataOptions;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.LabelFieldDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+
+/**
+ * This is the panel that contains the Review Panel.
+ *
+ */
+class ReviewPanel extends QuickSetupStepPanel
+{
+  private static final long serialVersionUID = -7356174829193265699L;
+
+  private boolean displayServerLocation;
+
+  private UserInstallData defaultUserData;
+
+  private JCheckBox checkBox;
+
+  private HashMap<FieldName, JLabel> hmLabels =
+      new HashMap<FieldName, JLabel>();
+
+  private HashMap<FieldName, JTextComponent> hmFields =
+      new HashMap<FieldName, JTextComponent>();
+
+  /**
+   * Constructor of the panel.
+   * @param defaultUserData the default values that must be used to initialize
+   * the fields of the panel.
+   */
+  public ReviewPanel(UserInstallData defaultUserData)
+  {
+    this.defaultUserData = defaultUserData;
+    this.displayServerLocation = isWebStart();
+    populateLabelAndFieldsMap();
+    createLayout();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void beginDisplay(UserInstallData userData)
+  {
+    if (displayServerLocation)
+    {
+      setFieldValue(FieldName.SERVER_LOCATION, userData.getServerLocation());
+    }
+    setFieldValue(FieldName.SERVER_PORT, String.valueOf(userData
+        .getServerPort()));
+    setFieldValue(FieldName.DIRECTORY_MANAGER_DN, userData
+        .getDirectoryManagerDn());
+    setFieldValue(FieldName.DIRECTORY_BASE_DN, userData.getDataOptions()
+        .getBaseDn());
+    setFieldValue(FieldName.DATA_OPTIONS, getDisplayString(userData
+        .getDataOptions()));
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Object getFieldValue(FieldName fieldName)
+  {
+    Object value = null;
+    if (fieldName == FieldName.SERVER_START)
+    {
+      value = new Boolean(getCheckBox().isSelected());
+    }
+    return value;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Component createInputPanel()
+  {
+    JPanel panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    panel.add(createFieldsPanel(), gbc);
+
+    addVerticalGlue(panel);
+
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    gbc.weighty = 0.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    panel.add(getCheckBox(), gbc);
+
+    return panel;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getInstructions()
+  {
+    return getMsg("review-panel-instructions");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getTitle()
+  {
+    return getMsg("review-panel-title");
+  }
+
+  /**
+   * Create the components and populate the Maps.
+   */
+  private void populateLabelAndFieldsMap()
+  {
+    HashMap<FieldName, LabelFieldDescriptor> hm =
+        new HashMap<FieldName, LabelFieldDescriptor>();
+
+    if (displayServerLocation)
+    {
+      hm.put(FieldName.SERVER_LOCATION, new LabelFieldDescriptor(
+          getMsg("server-location-label"), getMsg("server-port-tooltip"),
+          LabelFieldDescriptor.FieldType.READ_ONLY,
+          LabelFieldDescriptor.LabelType.PRIMARY, 0));
+    }
+
+    hm.put(FieldName.SERVER_PORT, new LabelFieldDescriptor(
+        getMsg("server-port-label"), getMsg("server-port-tooltip"),
+        LabelFieldDescriptor.FieldType.READ_ONLY,
+        LabelFieldDescriptor.LabelType.PRIMARY, 0));
+
+    hm.put(FieldName.DIRECTORY_MANAGER_DN, new LabelFieldDescriptor(
+        getMsg("server-directory-manager-dn-label"),
+        getMsg("server-directory-manager-dn-tooltip"),
+        LabelFieldDescriptor.FieldType.READ_ONLY,
+        LabelFieldDescriptor.LabelType.PRIMARY, 0));
+
+    hm.put(FieldName.DIRECTORY_BASE_DN, new LabelFieldDescriptor(
+        getMsg("base-dn-label"), getMsg("base-dn-tooltip"),
+        LabelFieldDescriptor.FieldType.READ_ONLY,
+        LabelFieldDescriptor.LabelType.PRIMARY, 0));
+
+    hm.put(FieldName.DATA_OPTIONS, new LabelFieldDescriptor(
+        getMsg("directory-data-label"), null,
+        LabelFieldDescriptor.FieldType.READ_ONLY,
+        LabelFieldDescriptor.LabelType.PRIMARY, 0));
+    for (FieldName fieldName : hm.keySet())
+    {
+      LabelFieldDescriptor desc = hm.get(fieldName);
+
+      JTextComponent field = makeJTextComponent(desc, null);
+      field.setOpaque(false);
+      JLabel label = makeJLabel(desc);
+
+      hmFields.put(fieldName, field);
+      label.setLabelFor(field);
+
+      hmLabels.put(fieldName, label);
+    }
+  }
+
+  /**
+   * Returns the label associated with the given field name.
+   * @param fieldName the field name for which we want to retrieve the JLabel.
+   * @return the label associated with the given field name.
+   */
+  private JLabel getLabel(FieldName fieldName)
+  {
+    return hmLabels.get(fieldName);
+  }
+
+  /**
+   * Returns the JTextComponent associated with the given field name.
+   * @param fieldName the field name for which we want to retrieve the
+   * JTextComponent.
+   * @return the JTextComponent associated with the given field name.
+   */
+  private JTextComponent getField(FieldName fieldName)
+  {
+    return hmFields.get(fieldName);
+  }
+
+  /**
+   * Updates the JTextComponent associated with a FieldName with a text value.
+   * @param fieldName the field name of the JTextComponent that we want to
+   * update.
+   * @param value the value to be set.
+   */
+  private void setFieldValue(FieldName fieldName, String value)
+  {
+    getField(fieldName).setText(value);
+  }
+
+  /**
+   * Returns the localized string describing the DataOptions chosen by the user.
+   * @param options the DataOptions of the user.
+   * @return the localized string describing the DataOptions chosen by the user.
+   */
+  private String getDisplayString(DataOptions options)
+  {
+    String msg;
+
+    switch (options.getType())
+    {
+    case CREATE_BASE_ENTRY:
+      msg = getMsg("review-create-base-entry-label", new String[]
+        { options.getBaseDn() });
+
+      break;
+
+    case LEAVE_DATABASE_EMPTY:
+      msg = getMsg("review-leave-database-empty-label");
+      break;
+
+    case IMPORT_FROM_LDIF_FILE:
+      msg = getMsg("review-import-ldif", new String[]
+        { options.getLDIFPath() });
+      break;
+
+    case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+      msg = getMsg("review-import-automatically-generated", new String[]
+        { String.valueOf(options.getNumberEntries()) });
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknow type: " + options.getType());
+
+    }
+
+    return msg;
+  }
+
+  /**
+   * Returns the start server check box.
+   * If it does not exist creates the start server check box.
+   * @return the start server check box.
+   */
+  private JCheckBox getCheckBox()
+  {
+    if (checkBox == null)
+    {
+      checkBox =
+          UIFactory.makeJCheckBox(getMsg("start-server-label"),
+              getMsg("start-server-tooltip"), UIFactory.TextStyle.CHECKBOX);
+      checkBox.setOpaque(false);
+      checkBox.setSelected(defaultUserData.getStartServer());
+    }
+    return checkBox;
+  }
+
+  /**
+   * Returns and creates the fields panel.
+   * @return the fields panel.
+   */
+  private JPanel createFieldsPanel()
+  {
+    JPanel panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    FieldName[] fieldNames;
+    if (displayServerLocation)
+    {
+      fieldNames =
+          new FieldName[]
+            { FieldName.SERVER_LOCATION, FieldName.SERVER_PORT,
+                FieldName.DIRECTORY_MANAGER_DN,
+                FieldName.DIRECTORY_BASE_DN,
+                FieldName.DATA_OPTIONS };
+    } else
+    {
+      fieldNames =
+          new FieldName[]
+            { FieldName.SERVER_PORT, FieldName.DIRECTORY_MANAGER_DN,
+                FieldName.DIRECTORY_BASE_DN, FieldName.DATA_OPTIONS };
+    }
+
+    for (int i = 0; i < fieldNames.length; i++)
+    {
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+      gbc.weightx = 0.0;
+      if (i > 0)
+      {
+        gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+      } else
+      {
+        gbc.insets.top = 0;
+      }
+      gbc.insets.left = 0;
+      gbc.anchor = GridBagConstraints.NORTHWEST;
+      panel.add(getLabel(fieldNames[i]), gbc);
+
+      JPanel auxPanel = new JPanel(new GridBagLayout());
+      auxPanel.setOpaque(false);
+      gbc.weightx = 1.0;
+      gbc.fill = GridBagConstraints.HORIZONTAL;
+      if (i > 0)
+      {
+        gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+      } else
+      {
+        gbc.insets.top = 0;
+      }
+      gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      panel.add(auxPanel, gbc);
+
+      gbc.insets = UIFactory.getEmptyInsets();
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.weightx = 1.0;
+      auxPanel.add(getField(fieldNames[i]), gbc);
+    }
+
+    return panel;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java
new file mode 100644
index 0000000..10d71f9
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java
@@ -0,0 +1,498 @@
+/*
+ * 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.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.io.File;
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.event.BrowseActionListener;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.LabelFieldDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is the panel that contains the Server Settings: the port, the Directory
+ * Manager DN, etc.
+ *
+ */
+class ServerSettingsPanel extends QuickSetupStepPanel
+{
+  private UserInstallData defaultUserData;
+
+  private Component lastFocusComponent;
+
+  private JButton browseButton;
+
+  private boolean displayServerLocation;
+
+  private HashMap<FieldName, JLabel> hmLabels =
+      new HashMap<FieldName, JLabel>();
+
+  private HashMap<FieldName, JTextComponent> hmFields =
+      new HashMap<FieldName, JTextComponent>();
+
+  private JTextComponent tfServerLocationParent;
+
+  private JTextComponent tfServerLocationRelativePath;
+
+  private JLabel lServerLocation;
+
+  private static final long serialVersionUID = -15911406930993035L;
+
+  /**
+   * Constructor of the panel.
+   * @param defaultUserData the default values that must be used to initialize
+   * the fields of the panel.
+   */
+  public ServerSettingsPanel(UserInstallData defaultUserData)
+  {
+    this.defaultUserData = defaultUserData;
+    this.displayServerLocation = isWebStart();
+    populateLabelAndFieldMaps();
+    createLayout();
+    addFocusListeners();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Object getFieldValue(FieldName fieldName)
+  {
+    Object value = null;
+
+    if (fieldName == FieldName.SERVER_LOCATION)
+    {
+      String parent = tfServerLocationParent.getText();
+      String relative = tfServerLocationRelativePath.getText();
+      if ((parent != null) && (parent.length() > 0))
+      {
+        value = parent;
+      }
+      if ((relative != null) && (relative.length() > 0))
+      {
+        if (value == null)
+        {
+          value = File.separator + relative;
+        } else
+        {
+          value = value + File.separator + relative;
+        }
+      }
+
+    } else
+    {
+      JTextComponent field = getField(fieldName);
+      if (field != null)
+      {
+        value = field.getText();
+      }
+    }
+
+    return value;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+  {
+    JLabel label = getLabel(fieldName);
+    if (label != null)
+    {
+      if (invalid)
+      {
+        UIFactory.setTextStyle(label,
+            UIFactory.TextStyle.PRIMARY_FIELD_INVALID);
+      } else
+      {
+        UIFactory
+            .setTextStyle(label, UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+      }
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Component createInputPanel()
+  {
+    JPanel panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    FieldName[] fieldNames =
+          { FieldName.SERVER_PORT, FieldName.DIRECTORY_MANAGER_DN,
+              FieldName.DIRECTORY_MANAGER_PWD,
+              FieldName.DIRECTORY_MANAGER_PWD_CONFIRM };
+
+    JPanel auxPanel;
+    // Add the server location widgets
+    if (displayServerLocation)
+    {
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+      gbc.weightx = 0.0;
+      gbc.insets.top = 0;
+      gbc.insets.left = 0;
+      gbc.anchor = GridBagConstraints.NORTHWEST;
+      panel.add(lServerLocation, gbc);
+
+      gbc.anchor = GridBagConstraints.WEST;
+      auxPanel = new JPanel(new GridBagLayout());
+      auxPanel.setOpaque(false);
+      gbc.weightx = 1.0;
+      gbc.fill = GridBagConstraints.HORIZONTAL;
+      gbc.insets.top = 0;
+      gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      panel.add(auxPanel, gbc);
+
+      gbc.gridwidth = 3;
+      gbc.insets = UIFactory.getEmptyInsets();
+      gbc.weightx = 0.7;
+      auxPanel.add(tfServerLocationParent, gbc);
+
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+      gbc.weightx = 0.0;
+      gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+      auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+          File.separator, UIFactory.TextStyle.TEXTFIELD), gbc);
+
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.weightx = 0.3;
+      auxPanel.add(tfServerLocationRelativePath, gbc);
+
+      gbc.gridwidth = 3;
+      gbc.anchor = GridBagConstraints.NORTHEAST;
+      gbc.insets.top = UIFactory.TOP_INSET_BROWSE;
+      gbc.weightx = 0.0;
+      gbc.fill = GridBagConstraints.NONE;
+      auxPanel.add(getBrowseButton(), gbc);
+    }
+
+    // Add the other widgets
+    for (int i = 0; i < fieldNames.length; i++)
+    {
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+      gbc.weightx = 0.0;
+      gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+      gbc.insets.left = 0;
+      gbc.anchor = GridBagConstraints.WEST;
+      panel.add(getLabel(fieldNames[i]), gbc);
+
+      auxPanel = new JPanel(new GridBagLayout());
+      auxPanel.setOpaque(false);
+      gbc.weightx = 1.0;
+      gbc.fill = GridBagConstraints.HORIZONTAL;
+      gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+      gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      panel.add(auxPanel, gbc);
+
+      boolean isPortField = fieldNames[i] == FieldName.SERVER_PORT;
+      gbc.insets = UIFactory.getEmptyInsets();
+      if (isPortField)
+      {
+        gbc.gridwidth = 3;
+      } else
+      {
+        gbc.gridwidth = GridBagConstraints.RELATIVE;
+      }
+      gbc.weightx = 0.0;
+      auxPanel.add(getField(fieldNames[i]), gbc);
+      if (isPortField)
+      {
+        JLabel l =
+            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);
+      }
+
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.weightx = 1.0;
+      auxPanel.add(Box.createHorizontalGlue(), gbc);
+    }
+    addVerticalGlue(panel);
+    return panel;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getInstructions()
+  {
+    return getMsg("server-settings-panel-instructions");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getTitle()
+  {
+    return getMsg("server-settings-panel-title");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void endDisplay()
+  {
+    if (lastFocusComponent != null)
+    {
+      lastFocusComponent.requestFocusInWindow();
+    }
+  }
+
+  /**
+   * Returns the default value for the provided field Name.
+   * @param fieldName the field name for which we want to get the default
+   * value.
+   * @return the default value for the provided field Name.
+   */
+  private String getDefaultValue(FieldName fieldName)
+  {
+    String value = null;
+    switch (fieldName)
+    {
+    case SERVER_LOCATION:
+      value = defaultUserData.getServerLocation();
+      break;
+
+    case SERVER_PORT:
+      if (defaultUserData.getServerPort() > 0)
+      {
+        value = String.valueOf(defaultUserData.getServerPort());
+      } else
+      {
+        value = "";
+      }
+      break;
+
+    case DIRECTORY_MANAGER_DN:
+      value = defaultUserData.getDirectoryManagerDn();
+      break;
+
+    case DIRECTORY_MANAGER_PWD:
+      value = defaultUserData.getDirectoryManagerPwd();
+      break;
+
+    case DIRECTORY_MANAGER_PWD_CONFIRM:
+      value = defaultUserData.getDirectoryManagerPwd();
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknown field name: " +
+          fieldName);
+    }
+
+    return value;
+  }
+
+  /**
+   * Creates the components and populates the Maps with them.
+   */
+  private void populateLabelAndFieldMaps()
+  {
+    HashMap<FieldName, LabelFieldDescriptor> hm =
+        new HashMap<FieldName, LabelFieldDescriptor>();
+
+    hm.put(FieldName.SERVER_PORT, new LabelFieldDescriptor(
+        getMsg("server-port-label"), getMsg("server-port-tooltip"),
+        LabelFieldDescriptor.FieldType.TEXTFIELD,
+        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PORT_FIELD_SIZE));
+
+    hm.put(FieldName.DIRECTORY_MANAGER_DN, new LabelFieldDescriptor(
+        getMsg("server-directory-manager-dn-label"),
+        getMsg("server-directory-manager-dn-tooltip"),
+        LabelFieldDescriptor.FieldType.TEXTFIELD,
+        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.DN_FIELD_SIZE));
+
+    hm.put(FieldName.DIRECTORY_MANAGER_PWD, new LabelFieldDescriptor(
+        getMsg("server-directory-manager-pwd-label"),
+        getMsg("server-directory-manager-pwd-tooltip"),
+        LabelFieldDescriptor.FieldType.PASSWORD,
+        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PASSWORD_FIELD_SIZE));
+
+    hm.put(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM,
+        new LabelFieldDescriptor(
+        getMsg("server-directory-manager-pwd-confirm-label"),
+        getMsg("server-directory-manager-pwd-confirm-tooltip"),
+        LabelFieldDescriptor.FieldType.PASSWORD,
+        LabelFieldDescriptor.LabelType.PRIMARY,
+        UIFactory.PASSWORD_FIELD_SIZE));
+
+    for (FieldName fieldName : hm.keySet())
+    {
+      LabelFieldDescriptor desc = hm.get(fieldName);
+      String defaultValue = getDefaultValue(fieldName);
+      JTextComponent field = makeJTextComponent(desc, defaultValue);
+      JLabel label = makeJLabel(desc);
+
+      hmFields.put(fieldName, field);
+      label.setLabelFor(field);
+
+      hmLabels.put(fieldName, label);
+    }
+
+    /* Create the elements for the location */
+    LabelFieldDescriptor desc =
+        new LabelFieldDescriptor(getMsg("server-location-label"),
+            getMsg("server-location-parent-tooltip"),
+            LabelFieldDescriptor.FieldType.TEXTFIELD,
+            LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PATH_FIELD_SIZE);
+    lServerLocation = makeJLabel(desc);
+    tfServerLocationParent = makeJTextComponent(desc, "");
+    lServerLocation.setLabelFor(tfServerLocationParent);
+
+    desc =
+        new LabelFieldDescriptor(getMsg("server-location-label"),
+            getMsg("server-location-relative-tooltip"),
+            LabelFieldDescriptor.FieldType.TEXTFIELD,
+            LabelFieldDescriptor.LabelType.PRIMARY,
+            UIFactory.RELATIVE_PATH_FIELD_SIZE);
+    tfServerLocationRelativePath = makeJTextComponent(desc, "");
+    String defaultPath = getDefaultValue(FieldName.SERVER_LOCATION);
+    if (defaultPath != null)
+    {
+      int index = defaultPath.lastIndexOf(File.separator);
+      if (index != -1)
+      {
+        String parent = defaultPath.substring(0, index);
+        String relativeDir = defaultPath.substring(index + 1);
+
+        tfServerLocationParent.setText(parent);
+        tfServerLocationRelativePath.setText(relativeDir);
+      }
+    }
+  }
+
+  /**
+   * Returns the browse button.
+   * If it does not exist creates the browse button.
+   * @return the browse button.
+   */
+  private JButton getBrowseButton()
+  {
+    if (browseButton == null)
+    {
+      browseButton =
+          UIFactory.makeJButton(getMsg("browse-button-label"),
+              getMsg("browse-button-tooltip"));
+
+      BrowseActionListener l =
+          new BrowseActionListener(tfServerLocationParent,
+              BrowseActionListener.BrowseType.LOCATION_DIRECTORY,
+              getMainWindow());
+      browseButton.addActionListener(l);
+    }
+    return browseButton;
+  }
+
+  /**
+   * Returns the label associated with the given field name.
+   * @param fieldName the field name for which we want to retrieve the JLabel.
+   * @return the label associated with the given field name.
+   */
+  private JLabel getLabel(FieldName fieldName)
+  {
+    return hmLabels.get(fieldName);
+  }
+
+  /**
+   * Returns the JTextComponent associated with the given field name.
+   * @param fieldName the field name for which we want to retrieve the
+   * JTextComponent.
+   * @return the JTextComponent associated with the given field name.
+   */
+  private JTextComponent getField(FieldName fieldName)
+  {
+    return hmFields.get(fieldName);
+  }
+
+  /**
+   * Adds the required focus listeners to the fields.
+   */
+  private void addFocusListeners()
+  {
+    final FocusListener l = new FocusListener()
+    {
+      public void focusGained(FocusEvent e)
+      {
+        lastFocusComponent = e.getComponent();
+      }
+
+      public void focusLost(FocusEvent e)
+      {
+      }
+    };
+
+    for (JTextComponent tf : hmFields.values())
+    {
+      tf.addFocusListener(l);
+    }
+    getBrowseButton().addFocusListener(l);
+    lastFocusComponent = getField(FieldName.SERVER_LOCATION);
+  }
+
+  /**
+   * Returns the port help message that we display when we cannot use the
+   * default port (389).
+   * @return the port help message that we display when we cannot use the
+   * default port (389).
+   */
+  private String getPortHelpMessage()
+  {
+    String s = "";
+    if (defaultUserData.getServerPort() <= 0)
+    {
+      if (Utils.isUnix())
+      {
+        s = getMsg("cannot-find-default-port-unix");
+      } else
+      {
+        s = getMsg("cannot-find-default-port-windows");
+      }
+    }
+    return s;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/StepsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/StepsPanel.java
new file mode 100644
index 0000000..2a1475b
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/StepsPanel.java
@@ -0,0 +1,213 @@
+/*
+ * 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.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.opends.quicksetup.Step;
+
+/**
+ * This class displays the different steps of the wizard.  It appears on the
+ * left of the dialog.
+ *
+ * The current step is highlighted using a different label style and an icon.
+ * The current displayed step can be changed calling the method setCurrentStep.
+ *
+ */
+class StepsPanel extends QuickSetupPanel
+{
+  private static final long serialVersionUID = -2003945907121690657L;
+
+  HashMap<Step, JLabel> hmLabels = new HashMap<Step, JLabel>();
+
+  HashMap<Step, JLabel> hmIcons = new HashMap<Step, JLabel>();
+
+  /**
+   * Creates a StepsPanel.
+   * @param isUninstall tells whether we are installing or uninstalling.
+   */
+  public StepsPanel(boolean isUninstall)
+  {
+    createLayout(isUninstall);
+  }
+
+  /**
+   * Updates the layout of the panel so that it corresponds to the Step passed
+   * as parameter.
+   *
+   * @param step the step in the wizard.
+   */
+  public void setDisplayedStep(Step step)
+  {
+    for (Step s : Step.values())
+    {
+      if (s == step)
+      {
+        getIcon(s).setVisible(true);
+        UIFactory.setTextStyle(getLabel(s), UIFactory.TextStyle.CURRENT_STEP);
+      } else
+      {
+        if (getIcon(s) != null)
+        {
+          getIcon(s).setVisible(false);
+        }
+        if (getLabel(s) != null)
+        {
+          UIFactory.setTextStyle(getLabel(s),
+              UIFactory.TextStyle.NOT_CURRENT_STEP);
+        }
+      }
+    }
+  }
+
+  /**
+   * Creates the layout of the panel.
+   * @param isUninstall tells whether we are installing or uninstalling.
+   */
+  private void createLayout(boolean isUninstall)
+  {
+    setLayout(new GridBagLayout());
+
+    JPanel mainPanel = new JPanel(new GridBagLayout());
+    mainPanel.setOpaque(false);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.weightx = 0.0;
+    gbc.weighty = 0.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.anchor = GridBagConstraints.WEST;
+
+    HashMap<Step, String> hmText = new HashMap<Step, String>();
+    ArrayList<Step> orderedSteps = new ArrayList<Step>();
+    if (isUninstall)
+    {
+      hmText.put(Step.CONFIRM_UNINSTALL, getMsg("confirm-uninstall-step"));
+      hmText.put(Step.PROGRESS, getMsg("progress-step"));
+      orderedSteps.add(Step.CONFIRM_UNINSTALL);
+      orderedSteps.add(Step.PROGRESS);
+    } else
+    {
+      hmText.put(Step.WELCOME, getMsg("welcome-step"));
+      hmText.put(Step.SERVER_SETTINGS, getMsg("server-settings-step"));
+      hmText.put(Step.DATA_OPTIONS, getMsg("data-options-step"));
+      hmText.put(Step.REVIEW, getMsg("review-step"));
+      hmText.put(Step.PROGRESS, getMsg("progress-step"));
+      orderedSteps.add(Step.WELCOME);
+      orderedSteps.add(Step.SERVER_SETTINGS);
+      orderedSteps.add(Step.DATA_OPTIONS);
+      orderedSteps.add(Step.REVIEW);
+      orderedSteps.add(Step.PROGRESS);
+    }
+    for (Step s : orderedSteps)
+    {
+      if (s != orderedSteps.get(0))
+      {
+        gbc.insets.top = UIFactory.TOP_INSET_STEP;
+      }
+
+      GridBagConstraints gbcAux = new GridBagConstraints();
+      gbcAux.gridwidth = GridBagConstraints.REMAINDER;
+      gbcAux.fill = GridBagConstraints.HORIZONTAL;
+      JPanel auxPanel = new JPanel(new GridBagLayout());
+      auxPanel.setOpaque(false);
+      JLabel iconLabel =
+          UIFactory.makeJLabel(UIFactory.IconType.CURRENT_STEP, null,
+              UIFactory.TextStyle.NO_STYLE);
+      auxPanel.add(iconLabel, gbcAux);
+      int width = (int) iconLabel.getPreferredSize().getWidth();
+      auxPanel.add(Box.createHorizontalStrut(width), gbcAux);
+
+      hmIcons.put(s, iconLabel);
+
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+      mainPanel.add(auxPanel, gbc);
+
+      JLabel stepLabel =
+          UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, hmText.get(s),
+              UIFactory.TextStyle.CURRENT_STEP);
+      hmLabels.put(s, stepLabel);
+      gbc.insets.left = UIFactory.LEFT_INSET_STEP;
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      mainPanel.add(stepLabel, gbc);
+
+      stepLabel.setLabelFor(this);
+      iconLabel.setLabelFor(stepLabel);
+    }
+
+    gbc.insets.left = 0;
+    gbc.insets.top = 0;
+    gbc.weightx = 1.0;
+    gbc.weighty = 0.0;
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    add(mainPanel, gbc);
+    int mainWidth = (int) mainPanel.getPreferredSize().getWidth();
+
+    // We are creating all the labels with the style
+    // UIFactory.LabelStyle.CURRENT_STEP which is the one
+    // that takes more space. But once we display the dialog only one
+    // of the labels will have that style and the other will have
+    // UIFactory.LabelStyle.NOT_CURRENT_STEP. Adding the strut guarantees
+    // that the width of the panel will always be enough to display the
+    // longest label using UIFactory.LabelStyle.CURRENT_STEP.
+    add(Box.createHorizontalStrut(mainWidth), gbc);
+
+    gbc.fill = GridBagConstraints.VERTICAL;
+    gbc.weighty = 1.0;
+    add(Box.createVerticalGlue(), gbc);
+  }
+
+  /**
+   * Returns the label associated with the given step.
+   * @param step the step for which we want to retrieve the JLabel.
+   * @return the label associated with the given step.
+   */
+  private JLabel getLabel(Step step)
+  {
+    return hmLabels.get(step);
+  }
+
+  /**
+   * Returns the icon associated with the given step.
+   * @param step the step for which we want to retrieve the Icon.
+   * @return the icon associated with the given step.
+   */
+  private JLabel getIcon(Step step)
+  {
+    return hmIcons.get(step);
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java b/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
new file mode 100644
index 0000000..0191168
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
@@ -0,0 +1,1356 @@
+/*
+ * 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.Color;
+import java.awt.Font;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.util.HashMap;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPasswordField;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+
+/**
+ * This class provides constants an methods to create Swing objects and to
+ * generate UI elements with a common look and feel.
+ *
+ * When we want to change a color, a background or a font this is the class
+ * that should be modified.
+ *
+ */
+public class UIFactory
+{
+  private static boolean initialized = false;
+
+  private static String parentPackagePath;
+
+  /**
+   * Specifies the horizontal insets between buttons.
+   */
+  public static final int HORIZONTAL_INSET_BETWEEN_BUTTONS = 5;
+
+  /**
+   * Specifies the top inset for the steps.
+   */
+  public static final int TOP_INSET_STEP = 15;
+
+  /**
+   * Specifies the left inset for the steps.
+   */
+  public static final int LEFT_INSET_STEP = 5;
+
+  /**
+   * Specifies the top inset for the instructions sub panel.
+   */
+  public static final int TOP_INSET_INSTRUCTIONS_SUBPANEL = 10;
+
+  /**
+   * Specifies the top inset for input subpanel.
+   */
+  public static final int TOP_INSET_INPUT_SUBPANEL = 10;
+
+  /**
+   * Specifies the top inset for a primary field.
+   */
+  public static final int TOP_INSET_PRIMARY_FIELD = 10;
+
+  /**
+   * Specifies the top inset for a secondary field.
+   */
+  public static final int TOP_INSET_SECONDARY_FIELD = 5;
+
+  /**
+   * Specifies the top inset for a radio button.
+   */
+  public static final int TOP_INSET_RADIOBUTTON = 0;
+
+  /**
+   * Specifies the top inset for a radio button subordinate panel.
+   */
+  public static final int TOP_INSET_RADIO_SUBORDINATE = 0;
+
+  /**
+   * Specifies the top inset for the progress bar.
+   */
+  public static final int TOP_INSET_PROGRESS_BAR = 5;
+
+  /**
+   * Specifies the top inset for the progress text area.
+   */
+  public static final int TOP_INSET_PROGRESS_TEXTAREA = 4;
+
+  /**
+   * Specifies the top inset for the background image.
+   */
+  public static final int TOP_INSET_BACKGROUND = 70;
+
+  /**
+   * Specifies the top inset for the error message.
+   */
+  public static final int TOP_INSET_ERROR_MESSAGE = 10;
+
+  /**
+   * Specifies the top inset for the browse button.
+   */
+  public static final int TOP_INSET_BROWSE = 5;
+
+  /**
+   * Specifies the right inset for background image.
+   */
+  public static final int RIGHT_INSET_BACKGROUND = 20;
+
+  /**
+   * Specifies the left inset for the primary field.
+   */
+  public static final int LEFT_INSET_PRIMARY_FIELD = 10;
+
+  /**
+   * Specifies the left inset for the browse button.
+   */
+  public static final int LEFT_INSET_BROWSE = 10;
+
+  /**
+   * Specifies the left inset for radio subordinate panel.
+   */
+  public static final int LEFT_INSET_RADIO_SUBORDINATE = 20;
+
+  /**
+   * Specifies the left inset for the secondary field.
+   */
+  public static final int LEFT_INSET_SECONDARY_FIELD = 5;
+
+  /**
+   * Specifies the left inset for the background image.
+   */
+  public static final int LEFT_INSET_BACKGROUND = 20;
+
+  /**
+   * Specifies the left inset for the copy url button.
+   */
+  public static final int LEFT_INSET_COPY_BUTTON = 10;
+
+  /**
+   * Specifies the left inset for the progress bar.
+   */
+  public static final int BOTTOM_INSET_PROGRESS_BAR = 10;
+
+  /**
+   * Specifies the bottom inset for the background image.
+   */
+  public static final int BOTTOM_INSET_BACKGROUND = 30;
+
+  /**
+   * Specifies the number of columns of a text field for a path.
+   */
+  public static final int PATH_FIELD_SIZE = 20;
+
+  /**
+   * Specifies the number of columns of a text field for a relative path.
+   */
+  public static final int RELATIVE_PATH_FIELD_SIZE = 5;
+
+  /**
+   * Specifies the number of columns of a text field for a port.
+   */
+  public static final int PORT_FIELD_SIZE = 5;
+
+  /**
+   * Specifies the number of columns of a text field for a dn.
+   */
+  public static final int DN_FIELD_SIZE = 20;
+
+  /**
+   * Specifies the number of columns of a text field for a password.
+   */
+  public static final int PASSWORD_FIELD_SIZE = 15;
+
+  /**
+   * Specifies the number of columns of a text field for the number of entries.
+   */
+  public static final int NUMBER_ENTRIES_FIELD_SIZE = 7;
+
+  /**
+   * Specifies the number of points for the width of the progress bar.
+   */
+  public static final int PROGRESS_BAR_SIZE = 220;
+
+  /**
+   * Specifies the number of extra points that we add to the minimum size of
+   * the dialog.
+   */
+  public static final int EXTRA_DIALOG_HEIGHT = 75;
+
+  private static final Insets BUTTONS_PANEL_INSETS = new Insets(5, 0, 5, 10);
+
+  private static final Insets STEPS_PANEL_INSETS = new Insets(15, 10, 5, 10);
+
+  private static final Insets CURRENT_STEP_PANEL_INSETS =
+      new Insets(15, 15, 15, 15);
+
+  private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
+
+  /**
+   * Specifies the default background color.
+   */
+  public static final Color DEFAULT_BACKGROUND = new Color(236, 236, 236);
+
+  /**
+   * Specifies the current step background color.
+   */
+  public static final Color CURRENT_STEP_PANEL_BACKGROUND =
+    Color.WHITE;
+
+  /**
+   * Specifies the default label color.
+   */
+  public static final Color DEFAULT_LABEL_COLOR = Color.BLACK;
+
+  /**
+   * Specifies the valid field color.
+   */
+  public static final Color FIELD_VALID_COLOR = Color.BLACK;
+
+  /**
+   * Specifies the invalid field color.
+   */
+  public static final Color FIELD_INVALID_COLOR = Color.RED;
+
+  /**
+   * Specifies the read only text color.
+   */
+  public static final Color READ_ONLY_COLOR = Color.BLACK;
+
+  /**
+   * Specifies the check box text color.
+   */
+  public static final Color CHECKBOX_COLOR = Color.BLACK;
+
+  /**
+   * Specifies the progress text color.
+   */
+  public static final Color PROGRESS_COLOR = Color.BLACK;
+
+  /**
+   * Specifies the text field text color.
+   */
+  public static final Color TEXTFIELD_COLOR = Color.BLACK;
+
+  /**
+   * Specifies the password field text color.
+   */
+  public static final Color PASSWORD_FIELD_COLOR = Color.BLACK;
+
+  /**
+   * Specifies the current step panel border.
+   */
+  public static final Border CURRENT_STEP_PANEL_BORDER =
+    BorderFactory.createMatteBorder(0, 2, 2, 0, new Color(204, 204, 204));
+
+  /**
+   * Specifies the text area border.
+   */
+  public static final Border TEXT_AREA_BORDER =
+    BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK);
+
+  /**
+   * Specifies the dialog border.
+   */
+  public static final Border DIALOG_PANEL_BORDER =
+    BorderFactory.createMatteBorder(0, 0, 2, 0, new Color(204, 204, 204));
+
+  /**
+   * Specifies the font for the step which is not the current one in the steps
+   * panel.
+   */
+  public static final Font NOT_CURRENT_STEP_FONT =
+    Font.decode("Arial-PLAIN-14");
+
+  /**
+   * Specifies the font for the step which is the current one in the steps
+   * panel.
+   */
+  public static final Font CURRENT_STEP_FONT =
+    Font.decode("Arial-BOLD-14");
+
+  /**
+   * Specifies the font for the title of the current panel.
+   */
+  public static final Font TITLE_FONT =
+    Font.decode("Arial-BOLD-14");
+
+  /**
+   * Specifies the font for the instructions of the current panel.
+   */
+  public static final Font INSTRUCTIONS_FONT =
+    Font.decode("Arial-PLAIN-14");
+
+  /**
+   * Specifies the font for the primary valid field.
+   */
+  public static final Font PRIMARY_FIELD_VALID_FONT =
+    Font.decode("Arial-BOLD-12");
+
+  /**
+   * Specifies the font for the secondary valid field.
+   */
+  public static final Font SECONDARY_FIELD_VALID_FONT =
+    Font.decode("Arial-PLAIN-12");
+
+  /**
+   * Specifies the font for the primary invalid field.
+   */
+  public static final Font PRIMARY_FIELD_INVALID_FONT =
+    Font.decode("Arial-BOLDITALIC-12");
+
+  /**
+   * Specifies the font for the secondary invalid field.
+   */
+  public static final Font SECONDARY_FIELD_INVALID_FONT =
+    Font.decode("Arial-ITALIC-12");
+
+  /**
+   * Specifies the font for read only text.
+   */
+  public static final Font READ_ONLY_FONT = Font.decode("Arial-PLAIN-12");
+
+  /**
+   * Specifies the font for the check box text.
+   */
+  public static final Font CHECKBOX_FONT = Font.decode("Arial-PLAIN-12");
+
+  /**
+   * Specifies the font for the progress text.
+   */
+  public static final Font PROGRESS_FONT = Font.decode("Arial-PLAIN-12");
+
+  /**
+   * Specifies the font for the text field text.
+   */
+  public static final Font TEXTFIELD_FONT = Font.decode("Arial-PLAIN-12");
+
+  /**
+   * Specifies the font for the password field text.
+   */
+  public static final Font PASSWORD_FIELD_FONT =
+    Font.decode("Arial-PLAIN-12");
+
+  /**
+   * Specifies the font for the points '....' in the progress panel.
+   */
+  public static final Font PROGRESS_POINTS_FONT =
+    Font.decode("Arial-BOLD-12");
+
+  /**
+   * Specifies the font for the done text 'Done' in the progress panel.
+   */
+  public static final Font PROGRESS_DONE_FONT = PROGRESS_POINTS_FONT;
+
+  /**
+   * Specifies the font for the log messages in the progress panel.
+   */
+  public static final Font PROGRESS_LOG_FONT =
+      Font.decode("Monospaced-PLAIN-12");
+
+  /**
+   * Specifies the font for the error log messages in the progress panel.
+   */
+  public static final Font PROGRESS_LOG_ERROR_FONT =
+      Font.decode("Monospaced-PLAIN-12");
+
+  /**
+   * Specifies the font for the error messages in the progress panel.
+   */
+  public static final Font PROGRESS_ERROR_FONT =
+    Font.decode("Arial-BOLD-12");
+
+  /**
+   * Specifies the font for the warning messages in the progress panel.
+   */
+  public static final Font PROGRESS_WARNING_FONT =
+    Font.decode("Arial-BOLD-12");
+
+  /**
+   * Specifies the font for the stack trace in the progress panel.
+   */
+  public static final Font STACK_FONT = Font.decode("Arial-PLAIN-12");
+
+  /**
+   * Specifies the font for the text in the WebBrowserErrorDialog.
+   */
+  public static final Font BROWSER_ERROR_DIALOG_FONT =
+      Font.decode("Arial-PLAIN-12");
+
+  private static final String SPAN_CLOSE = "</span>";
+
+  private static final String DIV_CLOSE = "</div>";
+
+  private static final String DIV_OPEN_ERROR_BACKGROUND =
+      "<div style=\"color:#000;background-color:#FFFFCC;"
+          + "padding:10px 10px 10px 10px;"
+          + "border-style:solid;border-width:3px;border-color:#E1E1A7;"
+          + "vertical-align:middle;text-align:left\">";
+
+  private static final String DIV_OPEN_WARNING_BACKGROUND =
+      DIV_OPEN_ERROR_BACKGROUND;
+
+  private static final String DIV_OPEN_SUCCESSFUL_BACKGROUND =
+      "<div style=\"color:#000;background-color:#FFFFCC;"
+          + "padding:10px 10px 10px 10px;"
+          + "border-style:solid;border-width:3px;border-color:#E1E1A7;"
+          + "vertical-align:middle;text-align:left\">";
+
+  /**
+   * An HTML separator text that can be used in the progress panel.
+   */
+  public static final String HTML_SEPARATOR =
+      "<div style=\"font-size:1px;background-color:#666666;"
+          + "margin:10px 5px 10px 5px;\"></div>";
+
+  private static final HashMap<IconType, ImageIcon> hmIcons =
+      new HashMap<IconType, ImageIcon>();
+
+  /**
+   * The following enumeration contains the different icons that we can have.
+   *
+   */
+  public enum IconType
+  {
+    /**
+     * Splash Icon.
+     */
+    SPLASH,
+    /**
+     * Current Step Icon.
+     */
+    CURRENT_STEP,
+    /**
+     * The icon displayed by the OS when the dialog is minimized.
+     */
+    MINIMIZED,
+    /**
+     * The icon displayed by the Mac OS when the dialog is minimized.
+     */
+    MINIMIZED_MAC,
+    /**
+     * The background icon.
+     */
+    BACKGROUND,
+    /**
+     * The warning icon.
+     */
+    WARNING,
+    /**
+     * The error icon.
+     */
+    ERROR,
+    /**
+     * The warning large icon.
+     */
+    WARNING_LARGE,
+    /**
+     * The information icon.
+     */
+    INFORMATION,
+    /**
+     * No icon.
+     */
+    NO_ICON
+  }
+
+  /**
+   * The following enumeration contains the different text styles that we can
+   * have.  A text style basically specifies the font and color to be used to
+   * render the text.
+   *
+   */
+  public enum TextStyle
+  {
+    /**
+     * Current Step label style for the steps panel.
+     */
+    CURRENT_STEP,
+    /**
+     * Not current Step label style for the steps panel.
+     */
+    NOT_CURRENT_STEP,
+    /**
+     * Title label style for the current step panel.
+     */
+    TITLE,
+    /**
+     * Primary field valid label style for the current step panel.
+     */
+    PRIMARY_FIELD_VALID,
+    /**
+     * Primary field invalid text style for the current step panel.
+     */
+    PRIMARY_FIELD_INVALID,
+    /**
+     * Secondary field valid text style for the current step panel.
+     */
+    SECONDARY_FIELD_VALID,
+    /**
+     * Secondary field invalid text style for the current step panel.
+     */
+    SECONDARY_FIELD_INVALID,
+    /**
+     * Textfield text style for the current step panel.
+     */
+    TEXTFIELD,
+    /**
+     * Password text style for the current step panel.
+     */
+    PASSWORD_FIELD,
+
+    /**
+     * Read only text style for the current step panel.
+     */
+    READ_ONLY,
+    /**
+     * Check box text text style for the current step panel.
+     */
+    CHECKBOX,
+    /**
+     * Progress messages text style for the current step panel.
+     */
+    PROGRESS,
+    /**
+     * No text style.
+     */
+    NO_STYLE
+  }
+
+  /**
+   * This method initialize the look and feel and UI settings.
+   */
+  public static void initialize()
+  {
+    if (!initialized)
+    {
+      System.setProperty("swing.aatext", "true");
+      try
+      {
+        UIManager.setLookAndFeel(
+            UIManager.getSystemLookAndFeelClassName());
+
+      } catch (Exception ex)
+      {
+        ex.printStackTrace();
+      }
+      JFrame.setDefaultLookAndFeelDecorated(false);
+
+      initialized = true;
+    }
+  }
+
+  /**
+   * Creates a JButton with the given label and tooltip.
+   * @param label the text of the button.
+   * @param tooltip the tooltip of the button.
+   * @return a JButton with the given label and tooltip.
+   */
+  public static JButton makeJButton(String label, String tooltip)
+  {
+    JButton b = new JButton();
+
+    if (label != null)
+    {
+      b.setText(label);
+    }
+
+    if (tooltip != null)
+    {
+      b.setToolTipText(tooltip);
+    }
+
+    return b;
+  }
+
+  /**
+   * Creates a JLabel with the given icon, text and text style.
+   * @param iconName the icon.
+   * @param text the label text.
+   * @param style the text style.
+   * @return a JLabel with the given icon, text and text style.
+   */
+  public static JLabel makeJLabel(IconType iconName, String text,
+      TextStyle style)
+  {
+    JLabel l = new JLabel();
+
+    if (text != null)
+    {
+      l.setText(text);
+    }
+
+    ImageIcon icon = getImageIcon(iconName);
+    l.setIcon(icon);
+    String tooltip = getIconTooltip(iconName);
+
+    if (tooltip != null)
+    {
+      l.setToolTipText(tooltip);
+    }
+
+    setTextStyle(l, style);
+    return l;
+  }
+
+  /**
+   * Creates a JTextField with the given icon, tooltip text, size and text
+   * style.
+   * @param text the text.
+   * @param tooltip the tooltip text.
+   * @param size the number of columns of the JTextField.
+   * @param style the text style.
+   * @return a JTextField with the given icon, tooltip text, size and text
+   * style.
+   */
+  public static JTextField makeJTextField(String text, String tooltip,
+      int size, TextStyle style)
+  {
+    JTextField f = new JTextField();
+    updateTextFieldComponent(f, text, tooltip, size, style);
+    return f;
+  }
+
+  /**
+   * Creates a JPasswordField with the given icon, tooltip text, size and text
+   * style.
+   * @param text the text.
+   * @param tooltip the tooltip text.
+   * @param size the number of columns of the JPasswordField.
+   * @param style the text style.
+   * @return a JPasswordField with the given icon, tooltip text, size and text
+   * style.
+   */
+  public static JPasswordField makeJPasswordField(String text, String tooltip,
+      int size, TextStyle style)
+  {
+    JPasswordField f = new JPasswordField();
+    updateTextFieldComponent(f, text, tooltip, size, style);
+    return f;
+  }
+
+  /**
+   * Creates a JRadioButton with the given text, tooltip text and text
+   * style.
+   * @param text the text of the radio button.
+   * @param tooltip the tooltip text.
+   * @param style the text style.
+   * @return a JRadioButton with the given text, tooltip text and text
+   * style.
+   */
+  public static JRadioButton makeJRadioButton(String text, String tooltip,
+      TextStyle style)
+  {
+    JRadioButton rb = new JRadioButton();
+
+    if (text != null)
+    {
+      rb.setText(text);
+    }
+
+    if (tooltip != null)
+    {
+      rb.setToolTipText(tooltip);
+    }
+
+    setTextStyle(rb, style);
+    return rb;
+  }
+
+  /**
+   * Creates a JCheckBox with the given text, tooltip text and text
+   * style.
+   * @param text the text of the radio button.
+   * @param tooltip the tooltip text.
+   * @param style the text style.
+   * @return a JCheckBox with the given text, tooltip text and text
+   * style.
+   */
+  public static JCheckBox makeJCheckBox(String text, String tooltip,
+      TextStyle style)
+  {
+    JCheckBox cb = new JCheckBox();
+
+    if (text != null)
+    {
+      cb.setText(text);
+    }
+
+    if (tooltip != null)
+    {
+      cb.setToolTipText(tooltip);
+    }
+
+    setTextStyle(cb, style);
+    return cb;
+  }
+
+  /**
+   * Sets the specified text style to the component passed as parameter.
+   * @param l the component to update.
+   * @param style the text style to use.
+   */
+  public static void setTextStyle(JComponent l, TextStyle style)
+  {
+    switch (style)
+    {
+    case NOT_CURRENT_STEP:
+      l.setFont(UIFactory.NOT_CURRENT_STEP_FONT);
+      l.setForeground(DEFAULT_LABEL_COLOR);
+      break;
+
+    case CURRENT_STEP:
+      l.setFont(UIFactory.CURRENT_STEP_FONT);
+      l.setForeground(DEFAULT_LABEL_COLOR);
+      break;
+
+    case TITLE:
+      l.setFont(UIFactory.TITLE_FONT);
+      l.setForeground(DEFAULT_LABEL_COLOR);
+      break;
+
+    case PRIMARY_FIELD_VALID:
+      l.setFont(UIFactory.PRIMARY_FIELD_VALID_FONT);
+      l.setForeground(FIELD_VALID_COLOR);
+      break;
+
+    case PRIMARY_FIELD_INVALID:
+      l.setFont(UIFactory.PRIMARY_FIELD_INVALID_FONT);
+      l.setForeground(FIELD_INVALID_COLOR);
+      break;
+
+    case SECONDARY_FIELD_VALID:
+      l.setFont(UIFactory.SECONDARY_FIELD_VALID_FONT);
+      l.setForeground(FIELD_VALID_COLOR);
+      break;
+
+    case SECONDARY_FIELD_INVALID:
+      l.setFont(UIFactory.SECONDARY_FIELD_INVALID_FONT);
+      l.setForeground(FIELD_INVALID_COLOR);
+      break;
+
+    case READ_ONLY:
+      l.setFont(UIFactory.READ_ONLY_FONT);
+      l.setForeground(READ_ONLY_COLOR);
+      break;
+
+    case CHECKBOX:
+      l.setFont(UIFactory.CHECKBOX_FONT);
+      l.setForeground(CHECKBOX_COLOR);
+      break;
+
+    case PROGRESS:
+      l.setFont(UIFactory.PROGRESS_FONT);
+      l.setForeground(PROGRESS_COLOR);
+      break;
+
+    case TEXTFIELD:
+      l.setFont(UIFactory.TEXTFIELD_FONT);
+      l.setForeground(TEXTFIELD_COLOR);
+      break;
+
+    case PASSWORD_FIELD:
+      l.setFont(UIFactory.PASSWORD_FIELD_FONT);
+      l.setForeground(PASSWORD_FIELD_COLOR);
+      break;
+
+    case NO_STYLE:
+      // Do nothing
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknown textStyle: " + style);
+    }
+  }
+
+  /**
+   * Returns the HTML string representing the provided IconType.
+   * @param iconType the IconType for which we want the HTML representation.
+   * @return the HTML string representing the provided IconType.
+   */
+  public static String getIconHtml(IconType iconType)
+  {
+    String url =
+        String.valueOf(UIFactory.class.getClassLoader().getResource(
+            getIconPath(iconType)));
+    String description = getIconDescription(iconType);
+    String title = getIconTooltip(iconType);
+    return "<img src=\"" + url + "\" alt=\"" + description + " title=\""
+        + title + "\"/>";
+  }
+
+  /**
+   * Returns an ImageIcon object for the provided IconType.
+   * @param iconType the IconType for which we want to obtain the ImageIcon.
+   * @return the ImageIcon.
+   */
+  public static ImageIcon getImageIcon(IconType iconType)
+  {
+    ImageIcon icon = hmIcons.get(iconType);
+    if ((icon == null) && (iconType != IconType.NO_ICON))
+    {
+      String path = getIconPath(iconType);
+      String description = getIconDescription(iconType);
+      try
+      {
+        Image im =
+            Toolkit.getDefaultToolkit().createImage(
+                UIFactory.class.getClassLoader().getResource(path));
+        icon = new ImageIcon(im);
+        icon.setDescription(description);
+
+        hmIcons.put(iconType, icon);
+
+      } catch (Exception ex)
+      {
+        ex.printStackTrace(); // A bug: this should not happen
+        throw new IllegalStateException("Could not load icon for path " + path,
+            ex);
+      }
+    }
+
+    return icon;
+  }
+
+  /**
+   * Returns a JEditorPane that works with the provided scroll.
+   * @see ProgressJEditorPane
+   * @param scroll the scroll that will contain the JEditorPane.
+   * @return a JEditorPane that works with the provided scroll.
+   */
+  public static JEditorPane makeProgressPane(JScrollPane scroll)
+  {
+    return new ProgressJEditorPane(scroll);
+  }
+
+  /**
+   * Returns a read only JEditorPane containing the provided text with the
+   * provided font.  The JEditorPane will assume that the text is HTML text.
+   * @param text the text to be used to initialize the JEditorPane contents.
+   * @param font the font to be used.
+   * @return a read only JEditorPane containing the provided text with the
+   * provided font.
+   */
+  public static JEditorPane makeHtmlPane(String text, Font font)
+  {
+    JEditorPane pane =
+        new JEditorPane("text/html", applyFontToHtmlWithDiv(text, font));
+    pane.setEditable(false);
+    pane.setBorder(new EmptyBorder(0, 0, 0, 0));
+    return pane;
+  }
+
+  /**
+   * Returns a read only JEditorPane containing the provided text with the
+   * provided TextStyle.  The JEditorPane will assume that the text is plain
+   * text.
+   * @param text the text to be used to initialize the JEditorPane contents.
+   * @param style the TextStyle to be used.
+   * @return a read only JEditorPane containing the provided text with the
+   * provided TextStyle.
+   */
+  public static JEditorPane makeTextPane(String text, TextStyle style)
+  {
+    JEditorPane pane = new JEditorPane("text/plain", text);
+    setTextStyle(pane, style);
+    pane.setEditable(false);
+    pane.setBorder(new EmptyBorder(0, 0, 0, 0));
+    return pane;
+  }
+
+  /**
+   * Return empty insets.
+   * @return empty insets.
+   */
+  public static Insets getEmptyInsets()
+  {
+    return (Insets) EMPTY_INSETS.clone();
+  }
+
+  /**
+   * Returns the insets to be used for the button panel.
+   * @return the insets to be used for the button panel.
+   */
+  public static Insets getButtonsPanelInsets()
+  {
+    return (Insets) BUTTONS_PANEL_INSETS.clone();
+  }
+
+  /**
+   * Returns the insets to be used for the steps panel.
+   * @return the insets to be used for the steps panel.
+   */
+  public static Insets getStepsPanelInsets()
+  {
+    return (Insets) STEPS_PANEL_INSETS.clone();
+  }
+
+  /**
+   * Returns the insets to be used for the current step panel.
+   * @return the insets to be used for the current step panel.
+   */
+  public static Insets getCurrentStepPanelInsets()
+  {
+    return (Insets) CURRENT_STEP_PANEL_INSETS.clone();
+  }
+
+  /**
+   * Returns a String that contains the html passed as parameter with a span
+   * applied.  The span style corresponds to the Font specified as parameter.
+   * The goal of this method is to be able to specify a font for an HTML string.
+   *
+   * @param html the original html text.
+   * @param font the font to be used to generate the new HTML.
+   * @return a string that represents the original HTML with the font specified
+   * as parameter.
+   */
+  public static String applyFontToHtml(String html, Font font)
+  {
+    StringBuffer buf = new StringBuffer();
+
+    buf.append("<span style=\"").append(getFontStyle(font)).append("\">")
+        .append(html).append(SPAN_CLOSE);
+
+    return buf.toString();
+  }
+
+  /**
+   * Returns a String that contains the html passed as parameter with a div
+   * applied.  The div style corresponds to the Font specified as parameter.
+   * The goal of this method is to be able to specify a font for an HTML string.
+   *
+   * @param html the original html text.
+   * @param font the font to be used to generate the new HTML.
+   * @return a string that represents the original HTML with the font specified
+   * as parameter.
+   */
+  public static String applyFontToHtmlWithDiv(String html, Font font)
+  {
+    StringBuffer buf = new StringBuffer();
+
+    buf.append("<div style=\"").append(getFontStyle(font)).append("\">")
+        .append(html).append(DIV_CLOSE);
+
+    return buf.toString();
+  }
+
+  /**
+   * Returns the HTML style representation for the given font.
+   * @param font the font for which we want to get an HTML style representation.
+   * @return the HTML style representation for the given font.
+   */
+  private static String getFontStyle(Font font)
+  {
+    StringBuffer buf = new StringBuffer();
+
+    buf.append("font-family:" + font.getName()).append(
+        ";font-size:" + font.getSize() + "pt");
+
+    if (font.isItalic())
+    {
+      buf.append(";font-style:italic");
+    }
+
+    if (font.isBold())
+    {
+      buf.append(";font-weight:bold;");
+    }
+
+    return buf.toString();
+  }
+
+  /**
+   * Returns the html text passed as parameter with the error background
+   * applied to it.
+   * @param html the original html.
+   * @return the html text passed as parameter with the error background
+   * applied to it.
+   */
+  public static String applyErrorBackgroundToHtml(String html)
+  {
+    return DIV_OPEN_ERROR_BACKGROUND + html + DIV_CLOSE;
+  }
+
+  /**
+   * Returns the html text passed as parameter with the warning background
+   * applied to it.
+   * @param html the original html.
+   * @return the html text passed as parameter with the warning background
+   * applied to it.
+   */
+  public static String applyWarningBackgroundToHtml(String html)
+  {
+    return DIV_OPEN_WARNING_BACKGROUND + html + DIV_CLOSE;
+  }
+
+
+  /**
+   * Returns the html text passed as parameter with the success background
+   * applied to it.
+   * @param html the original html.
+   * @return the html text passed as parameter with the success background
+   * applied to it.
+   */
+  public static String applySuccessfulBackgroundToHtml(String html)
+  {
+    return DIV_OPEN_SUCCESSFUL_BACKGROUND + html + DIV_CLOSE;
+  }
+
+
+  /**
+   * Returns the html text passed as parameter with some added margin.
+   * @param html the original html text.
+   * @param top the top margin.
+   * @param right the right margin.
+   * @param bottom the bottom margin.
+   * @param left the left margin.
+   * @return the html text passed as parameter with some added margin.
+   */
+  public static String applyMargin(String html, int top, int right, int bottom,
+      int left)
+  {
+    String result =
+        "<div style=\"margin:" + top + "px " + right + "px " + bottom + "px "
+            + left + "px;\">" + html + DIV_CLOSE;
+    return result;
+  }
+
+  /**
+   * Updates the provided field with all the other arguments.
+   * @param field the field to be modified.
+   * @param text the new text of the field.
+   * @param tooltip the new tooltip text of the field.
+   * @param size the new size of the field.
+   * @param textStyle the new TextStyle of the field.
+   */
+  private static void updateTextFieldComponent(JTextField field, String text,
+      String tooltip, int size, TextStyle textStyle)
+  {
+    field.setColumns(size);
+    if (text != null)
+    {
+      field.setText(text);
+    }
+    if (tooltip != null)
+    {
+      field.setToolTipText(tooltip);
+    }
+    if (textStyle != null)
+    {
+      setTextStyle(field, textStyle);
+    }
+  }
+
+  /* Some commodity methods to retrieve localized messages */
+  private static ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  private static String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  /**
+   * Returns the parent package path.  This is used to retrieve the icon
+   * qualified names.
+   * @return the parent package path.
+   */
+  private static String getParentPackagePath()
+  {
+    if (parentPackagePath == null)
+    {
+      String packageName = UIFactory.class.getPackage().getName();
+      int lastDot = packageName.lastIndexOf('.');
+      String parentPackage = packageName.substring(0, lastDot);
+      parentPackagePath = parentPackage.replace(".", "/");
+    }
+    return parentPackagePath;
+  }
+
+  /**
+   * Returns the path of the icon for the given IconType.
+   * @param iconType the IconType for which we want to get the path.
+   * @return the path of the icon for the given IconType.
+   */
+  private static String getIconPath(IconType iconType)
+  {
+    String key = null;
+    switch (iconType)
+    {
+    case CURRENT_STEP:
+      key = "current-step-icon";
+      break;
+
+    case SPLASH:
+      key = "splash-icon";
+      break;
+
+    case BACKGROUND:
+      key = "background-icon";
+      break;
+
+    case MINIMIZED:
+      key = "minimized-icon";
+      break;
+
+    case MINIMIZED_MAC:
+      key = "minimized-mac-icon";
+      break;
+
+    case WARNING:
+      key = "warning-icon";
+      break;
+
+    case WARNING_LARGE:
+      key = "warning-large-icon";
+      break;
+
+    case INFORMATION:
+      key = "information-icon";
+      break;
+
+    case ERROR:
+      key = "error-icon";
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknow iconName: " + iconType);
+    }
+    return getParentPackagePath() + "/" + getMsg(key);
+  }
+
+  /**
+   * Returns the icon description for the given IconType.
+   * @param iconType the IconType for which we want to get the description.
+   * @return the icon description for the given IconType.
+   */
+  private static String getIconDescription(IconType iconType)
+  {
+    String description = null;
+    switch (iconType)
+    {
+    case CURRENT_STEP:
+      description = getMsg("current-step-icon-description");
+      break;
+
+    case SPLASH:
+      description = getMsg("splash-icon-description");
+      break;
+
+    case BACKGROUND:
+      description = getMsg("background-icon-description");
+      break;
+
+    case MINIMIZED:
+      description = getMsg("minimized-icon-description");
+      break;
+
+    case MINIMIZED_MAC:
+      description = getMsg("minimized-icon-description");
+      break;
+
+    case WARNING:
+      description = "warning-icon-description";
+      break;
+
+    case WARNING_LARGE:
+      description = "warning-icon-description";
+      break;
+
+    case ERROR:
+      description = "error-icon-description";
+      break;
+
+    case INFORMATION:
+      description = "information-icon-description";
+      break;
+
+    case NO_ICON:
+      description = null;
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknow iconName: " + iconType);
+    }
+    return description;
+  }
+
+  /**
+   * Returns the icon tooltip text for the given IconType.
+   * @param iconType the IconType for which we want to get the tooltip text.
+   * @return the icon tooltip text for the given IconType.
+   */
+  private static String getIconTooltip(IconType iconType)
+  {
+    String tooltip;
+    switch (iconType)
+    {
+    case CURRENT_STEP:
+      tooltip = getMsg("current-step-icon-tooltip");
+      break;
+
+    case SPLASH:
+      tooltip = getMsg("splash-icon-tooltip");
+      break;
+
+    case BACKGROUND:
+      tooltip = getMsg("background-icon-tooltip");
+      break;
+
+    case MINIMIZED:
+      tooltip = getMsg("minimized-icon-tooltip");
+      break;
+
+    case MINIMIZED_MAC:
+      tooltip = getMsg("minimized-mac-icon-tooltip");
+      break;
+
+    case WARNING:
+      tooltip = "warning-icon-tooltip";
+      break;
+
+    case WARNING_LARGE:
+      tooltip = "warning-icon-tooltip";
+      break;
+
+    case ERROR:
+      tooltip = "error-icon-tooltip";
+      break;
+
+    case INFORMATION:
+      tooltip = "information-icon-tooltip";
+      break;
+
+    case NO_ICON:
+      tooltip = null;
+      break;
+
+    default:
+      throw new IllegalArgumentException("Unknow iconName: " + iconType);
+    }
+    return tooltip;
+  }
+}
+
+/**
+ * This class has been written to have a better behaviour with the scroll pane
+ * than the one we have by default in the case of the progress panel.
+ *
+ * With the default scroll pane behaviour when we set a new text in a
+ * JEditorPane the scroll bar goes systematically up.  With this implementation
+ * the expected behaviour is:
+ *
+ * If the scroll bar is at the bottom we will display the latest text contained
+ * in the pane.
+ *
+ * If the scroll bar is not at the bottom we will keep on displaying the same
+ * thing that the user is viewing.
+ *
+ * This behaviour allows the user to check the log content even when the
+ * installation/uninstallation is still running and sending new log messages.
+ *
+ */
+class ProgressJEditorPane extends JEditorPane
+{
+  private static final long serialVersionUID = 1221976708322628818L;
+
+  private JScrollPane scroll;
+
+  private boolean ignoreScrollToVisible;
+
+  /**
+   * Constructor for the ProgressJEditorPane.
+   * @param scroll the JScrollPane that will contain this editor pane.
+   */
+  public ProgressJEditorPane(JScrollPane scroll)
+  {
+    super("text/html", null);
+    this.scroll = scroll;
+    setEditable(false);
+    setBorder(new EmptyBorder(3, 3, 3, 3));
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void setText(String text)
+  {
+    // Scroll can be null in constructor
+    if (scroll != null)
+    {
+      /* We apply the following policy: if the user is displaying the latest
+       * part of the JTextArea we assume that when we add text (s)he wants
+       * to see the text that is added, if not we assume that (s)he want to keep
+       * viewing what is visible and so we ignore the next scrollRectToVisible
+       * call (that will be done inside JTextArea.setText method).
+       */
+      JScrollBar vBar = scroll.getVerticalScrollBar();
+      ignoreScrollToVisible =
+          (vBar != null)
+              && ((vBar.getValue() + vBar.getVisibleAmount()) < 0.97 * vBar
+                  .getMaximum());
+      super.setText(text);
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void scrollRectToVisible(Rectangle rect)
+  {
+    if (!ignoreScrollToVisible)
+    {
+      super.scrollRectToVisible(rect);
+      ignoreScrollToVisible = false;
+    }
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java b/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java
new file mode 100644
index 0000000..5f4f499
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java
@@ -0,0 +1,210 @@
+/*
+ * 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.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.util.Utils;
+import org.opends.quicksetup.util.WebBrowserException;
+
+/**
+ * This class is a dialog that appears when we could not launch the user web
+ * browser after the user clicked on a link.
+ *
+ * The dialog displays the URL to be displayed and provides a 'Copy URL' button
+ * to copy it to the system clipboard.  This way (even if not ideal) the user
+ * can view the contents of the URL we display by pasting manually the URL
+ * in his/her browser.
+ *
+ */
+public class WebBrowserErrorDialog extends JDialog
+{
+  private static final long serialVersionUID = 1063837373763193941L;
+
+  private JFrame parent;
+
+  private String url;
+
+  /**
+   * Constructor of the WebBrowserErrorDialog.
+   * @param parent the parent frame for this dialog.
+   * @param ex the WebBrowserException.
+   */
+  public WebBrowserErrorDialog(JFrame parent, WebBrowserException ex)
+  {
+    super(parent);
+    setTitle(getMsg("error-browser-display-title"));
+    this.parent = parent;
+    this.url = ex.getUrl();
+    getContentPane().add(createPanel());
+  }
+
+  /**
+   * Packs and displays this dialog.
+   *
+   */
+  public void packAndShow()
+  {
+    pack();
+    Utils.centerOnComponent(this, parent);
+    setVisible(true);
+  }
+
+  /* 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 = 3;
+    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.gridwidth = GridBagConstraints.RELATIVE;
+    Insets pInsets = UIFactory.getCurrentStepPanelInsets();
+    gbc.insets.left = 0;
+    String msg = getMsg("error-browser-display-msg", new String[]
+      { url });
+    JTextComponent tf =
+        UIFactory.makeHtmlPane(msg,
+            UIFactory.BROWSER_ERROR_DIALOG_FONT);
+    tf.setOpaque(false);
+    p1.add(tf, gbc);
+
+    gbc.weightx = 0.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    JButton copyButton =
+        UIFactory.makeJButton(getMsg("error-browser-copy-button-label"),
+            getMsg("error-browser-copy-button-tooltip"));
+    copyButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        StringSelection s = new StringSelection(url);
+        getToolkit().getSystemClipboard().setContents(s, s);
+      }
+    });
+    gbc.insets.left = UIFactory.LEFT_INSET_COPY_BUTTON;
+    gbc.insets.right = pInsets.right;
+    gbc.fill = GridBagConstraints.NONE;
+    p1.add(copyButton, gbc);
+    gbc.weighty = 1.0;
+    gbc.fill = GridBagConstraints.VERTICAL;
+    p1.add(Box.createVerticalGlue(), gbc);
+
+    JPanel p2 = new JPanel(new GridBagLayout());
+    p2.setOpaque(false);
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 1.0;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    p2.add(Box.createHorizontalGlue(), gbc);
+    JButton closeButton =
+        UIFactory.makeJButton(getMsg("close-button-label"),
+            getMsg("error-browser-close-button-tooltip"));
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.weightx = 0.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    p2.add(closeButton, gbc);
+    closeButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        dispose();
+      }
+    });
+
+    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(p2, gbc);
+    return p;
+  }
+
+  /**
+   * 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();
+      WebBrowserErrorDialog dlg =
+          new WebBrowserErrorDialog(new JFrame(),
+              new WebBrowserException("http://www.yahoo.com", "toto", null));
+      dlg.packAndShow();
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java
new file mode 100644
index 0000000..b672d19
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java
@@ -0,0 +1,80 @@
+/*
+ * 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.Component;
+
+/**
+ * This panel is used to show a welcome message.
+ *
+ */
+class WelcomePanel extends QuickSetupStepPanel
+{
+  private static final long serialVersionUID = 6209217138897900860L;
+
+  /**
+   * Default constructor.
+   *
+   */
+  public WelcomePanel()
+  {
+    createLayout();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getTitle()
+  {
+    return getMsg("welcome-panel-title");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getInstructions()
+  {
+    /*
+     * 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);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Component createInputPanel()
+  {
+    // No input in this panel
+    return null;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressDescriptor.java b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressDescriptor.java
new file mode 100644
index 0000000..885912c
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressDescriptor.java
@@ -0,0 +1,108 @@
+/*
+ * 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 class is used to describe the current state of the uninstallation.
+ * It contains the step in which the uninstallation is, the current progress
+ * ratio, the progress bar message and the details message (the logs).
+ *
+ * This class is used directly by the ProgressPanel to update its content
+ * and has been designed to match the layout of that panel.  However as it
+ * does not contain any dependency in terms of code with any Swing or UI package
+ * component it has been decided to leave it on the uninstaller package.
+ *
+ * In general the progress bar message and the details messages (log) are in
+ * HTML form (but this class is independent of the format we use for the
+ * messages).
+ *
+ */
+public class UninstallProgressDescriptor
+{
+  private UninstallProgressStep step;
+
+  private Integer progressBarRatio;
+
+  private String progressBarMsg;
+
+  private String detailsMsg;
+
+  /**
+   * Constructor for the UninstallProgressDescriptor.
+   * @param step the current uninstall step.
+   * @param progressBarRatio the completed progress ratio (in percentage).
+   * @param progressBarMsg the message to be displayed in the progress bar.
+   * @param detailsMsg the logs.
+   */
+  public UninstallProgressDescriptor(UninstallProgressStep step,
+      Integer progressBarRatio, String progressBarMsg, String detailsMsg)
+  {
+    this.step = step;
+    this.progressBarRatio = progressBarRatio;
+    this.progressBarMsg = progressBarMsg;
+    this.detailsMsg = detailsMsg;
+  }
+
+  /**
+   * Returns the details message (the log message) of the uninstall.
+   * @return the details message (the log message) of the uninstall.
+   */
+  public String getDetailsMsg()
+  {
+    return detailsMsg;
+  }
+
+  /**
+   * Returns the progress bar message.
+   * @return the progress bar message.
+   */
+  public String getProgressBarMsg()
+  {
+    return progressBarMsg;
+  }
+
+  /**
+   * Returns the progress bar ratio (the percentage of the uninstall that is
+   * completed).
+   * @return the progress bar ratio (the percentage of the uninstall that is
+   * completed).
+   */
+  public Integer getProgressBarRatio()
+  {
+    return progressBarRatio;
+  }
+
+  /**
+   * Returns the step of the uninstall on which we are.
+   * @return the step of the uninstall on which we are.
+   */
+  public UninstallProgressStep getProgressStep()
+  {
+    return step;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java
new file mode 100644
index 0000000..3ef8ae4
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java
@@ -0,0 +1,61 @@
+/*
+ * 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 enumeration describes the different uninstallation steps in which we can
+ * be.
+ *
+ */
+public enum UninstallProgressStep
+{
+  /**
+   * Uninstall not started.
+   */
+  NOT_STARTED,
+  /**
+   * Stopping server.
+   */
+  STOPPING_SERVER,
+  /**
+   * Removing Database files.
+   */
+  REMOVING_DATABASE_FILES,
+  /**
+   * Removing external references.
+   */
+  REMOVING_EXTERNAL_REFERENCES,
+  /**
+   * Installation finished successfully.
+   */
+  FINISHED_SUCCESSFULLY,
+  /**
+   * Installation finished with an error.
+   */
+  FINISHED_WITH_ERROR
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java
new file mode 100644
index 0000000..b21091f
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java
@@ -0,0 +1,48 @@
+/*
+ * 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 class is in charge of performing the uninstallation of Open DS.
+ *
+ * TODO implement this class.
+ *
+ */
+public class Uninstaller
+{
+  /**
+   * Returns whether the uninstaller has finished or not.
+   * @return <CODE>true</CODE> if the install is finished or <CODE>false
+   * </CODE> if not.
+   */
+  public boolean isFinished()
+  {
+    /* TODO implement this */
+    return false;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundTask.java b/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundTask.java
new file mode 100644
index 0000000..dab6554
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundTask.java
@@ -0,0 +1,82 @@
+/*
+ * 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;
+
+
+
+/**
+ * This class provides a mechanism for running a task in the background using a
+ * separate thread and providing the caller with notification when it has
+ * completed.
+ */
+public abstract class BackgroundTask
+{
+  /**
+   * Creates a new thread and begins running the task in the background.  When
+   * the task has completed, the {@code backgroundTaskCompleted} method will be
+   * invoked.
+   */
+  public final void startBackgroundTask()
+  {
+    BackgroundTaskThread taskThread = new BackgroundTaskThread(this);
+    taskThread.start();
+  }
+
+
+
+  /**
+   * Performs all processing associated with the task.
+   *
+   * @return  An {@code Object} with information about the processing performed
+   *          for this task, or {@code null} if no return value is needed.
+   *
+   * @throws Exception exception that will be passed through the method
+   *          backgroundTaskCompleted.
+   */
+  public abstract Object processBackgroundTask() throws Exception;
+
+
+
+  /**
+   * This method will be invoked to indicate that the background task has
+   * completed.  If processing completed successfully, then the
+   * {@code Throwable} argument will be {@code null} and the {@code returnValue}
+   * argument will contain the value returned by the
+   * {@code processBackgroundTask} method.  If an exception or error was thrown,
+   * then the {@code throwable} argument will not be {@code null}.
+   *
+   * @param  returnValue  The value returned by the
+   *                      {@code processBackgroundTask} method when processing
+   *                      completed, or {@code null} if no value was returned or
+   *                      an exception was encountered during processing.
+   * @param  throwable    A {@code Throwable} instance (e.g., an exception) that
+   *                      was raised during processing, or {@code null} if all
+   *                      processing completed successfully.
+   */
+  public abstract void backgroundTaskCompleted(Object returnValue,
+                                               Throwable throwable);
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundThreadTask.java b/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundThreadTask.java
new file mode 100644
index 0000000..c76d1e8
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundThreadTask.java
@@ -0,0 +1,71 @@
+/*
+ * 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;
+
+
+
+/**
+ * This class defines a thread that will be used to actually perform the
+ * processing for a background task.
+ */
+class BackgroundTaskThread
+      extends Thread
+{
+  // The background task that is to be processed.
+  private final BackgroundTask backgroundTask;
+
+
+
+  /**
+   * Creates a new background task thread that will be used to process the
+   * provided task.
+   *
+   * @param  backgroundTask  The task to be processed.
+   */
+  public BackgroundTaskThread(BackgroundTask backgroundTask)
+  {
+    this.backgroundTask = backgroundTask;
+  }
+
+
+
+  /**
+   * Performs the processing associated with the background task.
+   */
+  public void run()
+  {
+    try
+    {
+      Object returnValue = backgroundTask.processBackgroundTask();
+      backgroundTask.backgroundTaskCompleted(returnValue, null);
+    }
+    catch (Throwable t)
+    {
+      backgroundTask.backgroundTaskCompleted(null, t);
+    }
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/ExtensionFileFilter.java b/opends/src/quicksetup/org/opends/quicksetup/util/ExtensionFileFilter.java
new file mode 100644
index 0000000..5ff6e0e
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/ExtensionFileFilter.java
@@ -0,0 +1,86 @@
+/*
+ * 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 java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * This is a class used to be able to filter on certain type of files
+ * in the File Browser dialog.
+ *
+ */
+public class ExtensionFileFilter extends FileFilter
+{
+  private String extension;
+
+  private String description;
+
+  /**
+   * The ExtensionFiter constructor.
+   * @param extension the extension of the file we want to filter on.
+   * @param description the description for the extension.
+   */
+  public ExtensionFileFilter(String extension, String description)
+  {
+    this.extension = extension;
+    this.description = description;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean accept(File f)
+  {
+    boolean accept = false;
+    if (f != null)
+    {
+      if (f.isDirectory())
+      {
+        accept = true;
+      } else if (Utils.isWindows())
+      {
+        accept =
+            f.getName().toLowerCase().endsWith("." + extension.toLowerCase());
+      } else
+      {
+        accept = f.getName().endsWith("." + extension);
+      }
+    }
+    return accept;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getDescription()
+  {
+    return description;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java b/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java
new file mode 100644
index 0000000..fa9ed26
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java
@@ -0,0 +1,107 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.util;
+
+import javax.swing.JFrame;
+
+import org.opends.quicksetup.ui.WebBrowserErrorDialog;
+import org.opends.quicksetup.ui.QuickSetupStepPanel;
+
+/**
+ * This class is used to try to launch a URL in the user web browser.
+ *
+ * The class extends SwingWorker and tries to launch the URL using
+ * a WebBrowserLauncher object in the construct method.
+ * If there is a problem launching the user's browser, this class will display
+ * a WebBrowserErrorDialog to allow the user to copy to the system clipboard the
+ * URL we wanted to display.
+ *
+ * When is finished (successfully or unsuccessfully) it notifies the
+ * QuickSetupStepPanel passed in the constructor.
+ *
+ */
+public class URLWorker extends BackgroundTask
+{
+  private QuickSetupStepPanel panel;
+
+  private String url;
+
+  /**
+   * Constructs a URLWorker.
+   * @param panel the panel that created this URLWorker and to which we will
+   * notify when we are over.
+   * @param url the url to be displayed.
+   */
+  public URLWorker(QuickSetupStepPanel panel, String url)
+  {
+    this.panel = panel;
+    this.url = url;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Object processBackgroundTask() throws WebBrowserException
+  {
+    try
+    {
+      WebBrowserLauncher.openURL(url);
+    } catch (RuntimeException re)
+    {
+      throw new WebBrowserException(url, "Bug: run time exception", re);
+    }
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void backgroundTaskCompleted(Object returnValue,
+      Throwable throwable)
+  {
+    WebBrowserException ex = (WebBrowserException) throwable;
+    if (ex != null)
+    {
+      WebBrowserErrorDialog dlg =
+          new WebBrowserErrorDialog((JFrame) panel.getMainWindow(), ex);
+      dlg.setModal(false);
+      dlg.packAndShow();
+    }
+    // Notify to the panel that the worker has finished.
+    panel.urlWorkerFinished(this);
+  }
+
+  /**
+   * Returns the URL that we are trying to launch in the users browser.
+   * @return the URL that we are trying to launch in the users browser.
+   */
+  public String getURL()
+  {
+    return url;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
new file mode 100644
index 0000000..99a67aa
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -0,0 +1,809 @@
+/*
+ * 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 java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapName;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.webstart.JnlpProperties;
+
+
+/**
+ * This class provides some static convenience methods of different nature.
+ *
+ */
+public class Utils
+{
+  private static final int BUFFER_SIZE = 1024;
+
+  private Utils()
+  {
+  }
+
+  /**
+   * Center the component location based on its preferred size. The code
+   * considers the particular case of 2 screens and puts the component on the
+   * center of the left screen
+   *
+   * @param comp the component to be centered.
+   */
+  public static void centerOnScreen(Component comp)
+  {
+    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+
+    int width = (int) comp.getPreferredSize().getWidth();
+    int height = (int) comp.getPreferredSize().getHeight();
+
+    boolean multipleScreen = screenSize.width / screenSize.height >= 2;
+
+    if (multipleScreen)
+    {
+      comp.setLocation((screenSize.width / 4) - (width / 2),
+          (screenSize.height - height) / 2);
+    } else
+    {
+      comp.setLocation((screenSize.width - width) / 2,
+          (screenSize.height - height) / 2);
+    }
+  }
+
+  /**
+   * Center the component location of the ref component.
+   *
+   * @param comp the component to be centered.
+   * @param ref the component to be used as reference.
+   *
+   */
+  public static void centerOnComponent(Window comp, Component ref)
+  {
+    comp.setLocationRelativeTo(ref);
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the provided port is free and we can use it,
+   * <CODE>false</CODE> otherwise.
+   * @param port the port we are analyzing.
+   * @return <CODE>true</CODE> if the provided port is free and we can use it,
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean canUseAsPort(int port)
+  {
+    boolean canUseAsPort = false;
+    ServerSocket serverSocket = null;
+    try
+    {
+      InetSocketAddress socketAddress = new InetSocketAddress(port);
+      serverSocket = new ServerSocket();
+      if (!isWindows())
+      {
+        serverSocket.setReuseAddress(true);
+      }
+      serverSocket.bind(socketAddress);
+      canUseAsPort = true;
+    } catch (IOException ex)
+    {
+      canUseAsPort = false;
+    } finally
+    {
+      try
+      {
+        if (serverSocket != null)
+        {
+          serverSocket.close();
+        }
+      } catch (Exception ex)
+      {
+      }
+    }
+
+    return canUseAsPort;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the provided port is a priviledged port,
+   * <CODE>false</CODE> otherwise.
+   * @param port the port we are analyzing.
+   * @return <CODE>true</CODE> if the provided port is a priviledged port,
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean isPriviledgedPort(int port)
+  {
+    return (port <= 1024) && !isWindows();
+  }
+
+  /**
+   * Returns the absolute path for the given parentPath and relativePath.
+   * @param parentPath the parent path.
+   * @param relativePath the relative path.
+   * @return the absolute path for the given parentPath and relativePath.
+   */
+  public static String getPath(String parentPath, String relativePath)
+  {
+    File f = new File(new File(parentPath), relativePath);
+    return f.toString();
+  }
+
+  /**
+   * 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
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean isWindows()
+  {
+    return containsOsProperty("windows");
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we are running under Mac OS and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we are running under Mac OS and
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean isMacOS()
+  {
+    return containsOsProperty("Mac OS");
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we are running under Unix and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we are running under Unix and
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean isUnix()
+  {
+    return !isWindows();
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the parent directory for the provided path
+   * exists and <CODE>false</CODE> otherwise.
+   * @param path the path that we are analyzing.
+   * @return <CODE>true</CODE> if the parent directory for the provided path
+   * exists and <CODE>false</CODE> otherwise.
+   */
+  public static boolean parentDirectoryExists(String path)
+  {
+    boolean parentExists = false;
+    File f = new File(path);
+    if (f != null)
+    {
+      File parentFile = f.getParentFile();
+      if (parentFile != null)
+      {
+        parentExists = parentFile.isDirectory();
+      }
+    }
+    return parentExists;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the the provided path is a file and exists and
+   * <CODE>false</CODE> otherwise.
+   * @param path the path that we are analyzing.
+   * @return <CODE>true</CODE> if the the provided path is a file and exists and
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean fileExists(String path)
+  {
+    boolean isFile = false;
+    File f = new File(path);
+    if (f != null)
+    {
+      isFile = f.isFile();
+    }
+    return isFile;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the the provided path is a directory, exists
+   * and is not empty <CODE>false</CODE> otherwise.
+   * @param path the path that we are analyzing.
+   * @return <CODE>true</CODE> if the the provided path is a directory, exists
+   * and is not empty <CODE>false</CODE> otherwise.
+   */
+  public static boolean directoryExistsAndIsNotEmpty(String path)
+  {
+    boolean directoryExistsAndIsNotEmpty = false;
+    boolean isDirectory = false;
+
+    File f = new File(path);
+    if (f != null)
+    {
+      isDirectory = f.isDirectory();
+    }
+    if (isDirectory)
+    {
+      String[] ch = f.list();
+
+      directoryExistsAndIsNotEmpty = (ch != null) && (ch.length > 0);
+    }
+
+    return directoryExistsAndIsNotEmpty;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the the provided string is a DN and
+   * <CODE>false</CODE> otherwise.
+   * @param dn the String we are analyzing.
+   * @return <CODE>true</CODE> if the the provided string is a DN and
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean isDn(String dn)
+  {
+    boolean isDn = true;
+    try
+    {
+      new LdapName(dn);
+    } catch (Exception ex)
+    {
+      isDn = false;
+    }
+    return isDn;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the the provided string is a configuration DN
+   * and <CODE>false</CODE> otherwise.
+   * @param dn the String we are analyzing.
+   * @return <CODE>true</CODE> if the the provided string is a configuration DN
+   * and <CODE>false</CODE> otherwise.
+   */
+  public static boolean isConfigurationDn(String dn)
+  {
+    boolean isConfigurationDn = false;
+    String[] configDns =
+      { "cn=config", "cn=schema" };
+    for (int i = 0; i < configDns.length && !isConfigurationDn; i++)
+    {
+      isConfigurationDn = areDnsEqual(dn, configDns[i]);
+    }
+    return isConfigurationDn;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the the provided strings represent the same
+   * DN and <CODE>false</CODE> otherwise.
+   * @param dn1 the first dn to compare.
+   * @param dn2 the second dn to compare.
+   * @return <CODE>true</CODE> if the the provided strings represent the same
+   * DN and <CODE>false</CODE> otherwise.
+   */
+  public static boolean areDnsEqual(String dn1, String dn2)
+  {
+    boolean areDnsEqual = false;
+    try
+    {
+      LdapName name1 = new LdapName(dn1);
+      LdapName name2 = new LdapName(dn2);
+      areDnsEqual = name1.equals(name2);
+    } catch (Exception ex)
+    {
+    }
+
+    return areDnsEqual;
+  }
+
+  /**
+   * Creates the parent path for the provided path.
+   * @param path the path.
+   * @return <CODE>true</CODE> if the parent path was created or already existed
+   * and <CODE>false</CODE> otherwise.
+   */
+  public static boolean createParentPath(String path)
+  {
+    boolean parentPathExists = true;
+    if (!parentDirectoryExists(path))
+    {
+      File f = new File(path);
+      if (f != null)
+      {
+        File parentFile = f.getParentFile();
+        parentPathExists = parentFile.mkdirs();
+      }
+    }
+    return parentPathExists;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we can write on the provided path and
+   * <CODE>false</CODE> otherwise.
+   * @param path the path.
+   * @return <CODE>true</CODE> if we can write on the provided path and
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean canWrite(String path)
+  {
+    boolean canWrite;
+    File file = new File(path);
+    if (file.exists())
+    {
+      canWrite = file.canWrite();
+    } else
+    {
+      File parentFile = file.getParentFile();
+      if (parentFile != null)
+      {
+        canWrite = parentFile.canWrite();
+      } else
+      {
+        canWrite = false;
+      }
+    }
+    return canWrite;
+  }
+
+  /**
+   * Creates the a directory in the provided path.
+   * @param path the path.
+   * @return <CODE>true</CODE> if the path was created or already existed (and
+   * was a directory) and <CODE>false</CODE> otherwise.
+   * @throws IOException if something goes wrong.
+   */
+  public static boolean createDirectory(String path) throws IOException
+  {
+    boolean directoryCreated;
+    File f = new File(path);
+    if (!f.exists())
+    {
+      directoryCreated = f.mkdirs();
+    } else
+    {
+      directoryCreated = f.isDirectory();
+    }
+    return directoryCreated;
+  }
+
+  /**
+   * Creates a file on the specified path with the contents of the provided
+   * stream.
+   * @param path the path where the file will be created.
+   * @param is the InputStream with the contents of the file.
+   * @throws IOException if something goes wrong.
+   */
+  public static void createFile(String path, InputStream is) throws IOException
+  {
+    FileOutputStream out;
+    BufferedOutputStream dest;
+    byte[] data = new byte[BUFFER_SIZE];
+    int count;
+
+    out = new FileOutputStream(path);
+
+    dest = new BufferedOutputStream(out);
+
+    while ((count = is.read(data, 0, BUFFER_SIZE)) != -1)
+    {
+      dest.write(data, 0, count);
+    }
+    dest.flush();
+    dest.close();
+  }
+
+  /**
+   * Creates a file on the specified path with the contents of the provided
+   * String.
+   * @param path the path where the file will be created.
+   * @param content the String with the contents of the file.
+   * @throws IOException if something goes wrong.
+   */
+  public static void createFile(String path, String content) throws IOException
+  {
+    FileWriter file = new FileWriter(path);
+    PrintWriter out = new PrintWriter(file);
+
+    out.println(content);
+
+    out.flush();
+    out.close();
+  }
+
+  /**
+   * 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
+   * in the installation.
+   */
+  public static String getDefaultServerLocation()
+  {
+    String userDir = System.getProperty("user.home");
+    String firstLocation =
+        userDir + File.separator
+            + org.opends.server.util.DynamicConstants.COMPACT_VERSION_STRING;
+    String serverLocation = firstLocation;
+    int i = 1;
+    while (fileExists(serverLocation)
+        || directoryExistsAndIsNotEmpty(serverLocation))
+    {
+      serverLocation = firstLocation + "-" + i;
+      i++;
+    }
+    return serverLocation;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if there is more disk space in the provided path
+   * than what is specified with the bytes parameter.
+   * @param directoryPath the path.
+   * @param bytes the disk space.
+   * @return <CODE>true</CODE> if there is more disk space in the provided path
+   * than what is specified with the bytes parameter.
+   */
+  public static synchronized boolean hasEnoughSpace(String directoryPath,
+      long bytes)
+  {
+    // TODO This does not work with quotas etc. but at least it seems that
+    // we do not write all data on disk if it fails.
+    boolean hasEnoughSpace = false;
+    File file = null;
+    RandomAccessFile raf = null;
+    File directory = new File(directoryPath);
+    boolean deleteDirectory = false;
+    if (!directory.exists())
+    {
+      deleteDirectory = directory.mkdir();
+    }
+    try
+    {
+      file = File.createTempFile("temp" + System.nanoTime(), ".tmp", directory);
+      raf = new RandomAccessFile(file, "rw");
+      raf.setLength(bytes);
+      hasEnoughSpace = true;
+    } catch (IOException ex)
+    {
+    } finally
+    {
+      if (raf != null)
+      {
+        try
+        {
+          raf.close();
+        } catch (IOException ex2)
+        {
+        }
+      }
+      if (file != null)
+      {
+        file.delete();
+      }
+    }
+    if (deleteDirectory)
+    {
+      directory.delete();
+    }
+    return hasEnoughSpace;
+  }
+
+  /**
+   * Returns a localized message for a given properties key an exception.
+   * @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.
+   *
+   * @return a localized message for a given properties key an exception.
+   */
+  public static String getExceptionMsg(ResourceProvider i18n, String key,
+      String[] args, Exception ex)
+  {
+    String msg;
+    if (args != null)
+    {
+      msg = i18n.getMsg(key, args);
+    } else
+    {
+      msg = i18n.getMsg(key);
+    }
+
+    String detail = ex.toString();
+    if (detail != null)
+    {
+      String[] arg =
+        { detail };
+      msg = msg + "  " + i18n.getMsg("exception-details", arg);
+    }
+    return msg;
+  }
+
+  /**
+   * Commodity method to help identifying the OS we are running on.
+   * @param s the String that represents an OS.
+   * @return <CODE>true</CODE> if there is os java property exists and contains
+   * the value specified in s, <CODE>false</CODE> otherwise.
+   */
+  private static boolean containsOsProperty(String s)
+  {
+    boolean containsOsProperty = false;
+
+    String osName = System.getProperty("os.name");
+    if (osName != null)
+    {
+      containsOsProperty = osName.toLowerCase().indexOf(s) != -1;
+    }
+
+    return containsOsProperty;
+  }
+
+  /**
+   * Sets the permissions of the provided paths with the provided permission
+   * String.
+   * @param paths the paths to set permissions on.
+   * @param permissions the UNIX-mode file system permission representation
+   * (for example "644" or "755")
+   * @return the return code of the chmod command.
+   * @throws IOException if something goes wrong.
+   * @throws InterruptedException if the Runtime.exec method is interrupted.
+   */
+  public static int setPermissionsUnix(ArrayList<String> paths,
+      String permissions) throws IOException, InterruptedException
+  {
+    String[] args = new String[paths.size() + 2];
+    args[0] = "chmod";
+    args[1] = permissions;
+    for (int i = 2; i < args.length; i++)
+    {
+      args[i] = paths.get(i - 2);
+    }
+    Process p = Runtime.getRuntime().exec(args);
+    return p.waitFor();
+  }
+
+  // Very limited for the moment: apply only permissions to the current user and
+  // does not work in non-English environments... to work in non English we
+  // should use xcalcs but it does not come in the windows default install...
+  // :-(
+  // This method is not called for the moment, but the code works, so that is
+  // why
+  // is kept.
+  private static int changePermissionsWindows(String path, String unixPerm)
+      throws IOException, InterruptedException
+  {
+    String windowsPerm;
+    int i = Integer.parseInt(unixPerm.substring(0, 1));
+    if (Integer.lowestOneBit(i) == 1)
+    {
+      // Executable: give full permissions
+      windowsPerm = "F";
+    } else if (Integer.highestOneBit(i) == 4)
+    {
+      // Writable
+      windowsPerm = "W";
+    } else if (Integer.highestOneBit(i) == 2)
+    {
+      // Readable
+      windowsPerm = "R";
+    } else
+    {
+      // No permissions
+      windowsPerm = "N";
+    }
+
+    String user = System.getProperty("user.name");
+    String[] args =
+      { "cacls", path, "/P", user + ":" + windowsPerm };
+    Process p = Runtime.getRuntime().exec(args);
+
+    // TODO: This only works in ENGLISH systems!!!!!!
+    p.getOutputStream().write("Y\n".getBytes());
+    p.getOutputStream().flush();
+    return p.waitFor();
+  }
+
+  /**
+   * Indicates whether we are in a web start installation or not.
+   *
+   * @return <CODE>true</CODE> if we are in a web start installation and
+   *         <CODE>false</CODE> if not.
+   */
+  public static boolean isWebStart()
+  {
+    return "true".equals(System.getProperty(JnlpProperties.IS_WEBSTART));
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if this is an uninstallation and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if this is an uninstallation and
+   * <CODE>false</CODE> otherwise.
+   */
+  public static boolean isUninstall()
+  {
+    return "true".equals(System.getProperty("org.opends.quicksetup.uninstall"));
+  }
+
+  /**
+   * 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.
+   *
+   * @param ldapURL
+   *          the target LDAP URL
+   * @param dn
+   *          passed as Context.SECURITY_PRINCIPAL if not null
+   * @param pwd
+   *          passed as Context.SECURITY_CREDENTIALS if not null
+   * @param timeout
+   *          passed as com.sun.jndi.ldap.connect.timeout if > 0
+   * @param env
+   *          null or additional environment properties
+   *
+   * @throws NamingException
+   *           the exception thrown when instantiating InitialLdapContext
+   *
+   * @return the created InitialLdapContext.
+   * @see javax.naming.Context
+   * @see javax.naming.ldap.InitialLdapContext
+   */
+  public static InitialLdapContext createLdapContext(String ldapURL, String dn,
+      String pwd, int timeout, Hashtable<String, String> env)
+      throws NamingException
+  {
+    if (env != null)
+    { // We clone 'env' so that we can modify it freely
+      env = new Hashtable<String, String>(env);
+    } else
+    {
+      env = new Hashtable<String, String>();
+    }
+    env
+        .put(Context.INITIAL_CONTEXT_FACTORY,
+            "com.sun.jndi.ldap.LdapCtxFactory");
+    env.put(Context.PROVIDER_URL, ldapURL);
+    if (timeout >= 1)
+    {
+      env.put("com.sun.jndi.ldap.connect.timeout", String.valueOf(timeout));
+    }
+    if (dn != null)
+    {
+      env.put(Context.SECURITY_PRINCIPAL, dn);
+    }
+    if (pwd != null)
+    {
+      env.put(Context.SECURITY_CREDENTIALS, pwd);
+    }
+
+    /* Contains the DirContext and the Exception if any */
+    final Object[] pair = new Object[]
+      { null, null };
+    final Hashtable fEnv = env;
+    Thread t = new Thread(new Runnable()
+    {
+      public void run()
+      {
+        try
+        {
+          pair[0] = new InitialLdapContext(fEnv, null);
+
+        } catch (NamingException ne)
+        {
+          pair[1] = ne;
+
+        } catch (RuntimeException re)
+        {
+          pair[1] = re;
+        }
+      }
+    });
+    return getInitialLdapContext(t, pair, timeout);
+  }
+  /**
+   * 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.
+   * @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
+   * @throws NamingException if something goes wrong during the creation.
+   */
+  private static InitialLdapContext getInitialLdapContext(Thread t,
+      Object[] pair, int timeout) throws NamingException
+  {
+    try
+    {
+      if (timeout > 0)
+      {
+        t.start();
+        t.join(timeout);
+      } else
+      {
+        t.run();
+      }
+
+    } catch (InterruptedException x)
+    {
+      // This might happen for problems in sockets
+      // so it does not necessarily imply a bug
+    }
+
+    boolean throwException = false;
+
+    if ((timeout > 0) && t.isAlive())
+    {
+      t.interrupt();
+      try
+      {
+        t.join(2000);
+      } catch (InterruptedException x)
+      {
+        // This might happen for problems in sockets
+        // so it does not necessarily imply a bug
+      }
+      throwException = true;
+    }
+
+    if ((pair[0] == null) && (pair[1] == null))
+    {
+      throwException = true;
+    }
+
+    if (throwException)
+    {
+      NamingException xx;
+      ConnectException x = new ConnectException("Connection timed out");
+      xx = new CommunicationException("Connection timed out");
+      xx.initCause(x);
+      throw xx;
+    }
+
+    if (pair[1] != null)
+    {
+      if (pair[1] instanceof NamingException)
+      {
+        throw (NamingException) pair[1];
+
+      } else if (pair[1] instanceof RuntimeException)
+      {
+        throw (RuntimeException) pair[1];
+      }
+    }
+    return (InitialLdapContext) pair[0];
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java b/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java
new file mode 100644
index 0000000..c44614c
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+/**
+ * This class is the exception that we get when we try to launch the user web
+ * browser and we fail.  The exception is generated in WebBrowserLauncher.
+ *
+ */
+public class WebBrowserException extends Exception
+{
+  private static final long serialVersionUID = 4283835325192567244L;
+
+  private String url;
+
+  /**
+   * Constructor of the WebBrowserException.
+   * @param url the url that we were trying to display.
+   * @param msg the error message.
+   * @param rootCause the root cause.
+   */
+  public WebBrowserException(String url, String msg, Exception rootCause)
+  {
+    super(msg, rootCause);
+    this.url = url;
+  }
+
+  /**
+   * Returns the url that we were trying to display when the exception occurred.
+   * @return the url that we were trying to display when the exception occurred.
+   */
+  public String getUrl()
+  {
+    return this.url;
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserLauncher.java b/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserLauncher.java
new file mode 100644
index 0000000..5330752
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserLauncher.java
@@ -0,0 +1,109 @@
+/*
+ * 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 java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * This is a very basic class used to launch the user web browser.
+ *
+ */
+public class WebBrowserLauncher
+{
+  /**
+   * Tries to launch the user web browser with a given URL.
+   * @param url the url to be used to launch the web browser.
+   * @throws WebBrowserException if launching failed.
+   */
+  public static void openURL(String url) throws WebBrowserException
+  {
+    try
+    {
+      if (Utils.isMacOS())
+      {
+        Class<?> fileMgr = Class.forName("com.apple.eio.FileManager");
+        Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[]
+          { String.class });
+        openURL.invoke(null, new Object[]
+          { url });
+
+      } else if (Utils.isWindows())
+      {
+        String[] cmd = {"rundll32", "url.dll,FileProtocolHandler", url};
+        Runtime.getRuntime().exec(cmd);
+
+      } else
+      {
+        // assume Unix or Linux
+        String[] browsers =
+              { "firefox", "opera", "konqueror", "epiphany", "mozilla",
+                  "netscape" };
+        String browser = null;
+        for (int count = 0; count < browsers.length && browser == null;
+        count++)
+        {
+          if (Runtime.getRuntime().exec(new String[]
+            { "which", browsers[count] }).waitFor() == 0)
+          {
+            browser = browsers[count];
+          }
+        }
+
+        if (browser == null)
+        {
+          throw new WebBrowserException(url, "Could not find web browser",
+              null);
+        } else
+        {
+          Runtime.getRuntime().exec(new String[]
+            { browser, url });
+        }
+      }
+    } catch (ClassNotFoundException cnfe)
+    {
+      throw new WebBrowserException(url, "Class Not Found Exception", cnfe);
+    } catch (IOException ioe)
+    {
+      throw new WebBrowserException(url, "IO Exception", ioe);
+    } catch (InterruptedException ie)
+    {
+      throw new WebBrowserException(url, "Interrupted Exception", ie);
+    } catch (NoSuchMethodException nsme)
+    {
+      throw new WebBrowserException(url, "No Such Method Exception", nsme);
+    } catch (InvocationTargetException ite)
+    {
+      throw new WebBrowserException(url, "Invocation Target Exception", ite);
+    } catch (IllegalAccessException iae)
+    {
+      throw new WebBrowserException(url, "Illegal Access Exception", iae);
+    }
+  }
+}
diff --git a/opends/src/server/org/opends/server/tools/ImportLDIF.java b/opends/src/server/org/opends/server/tools/ImportLDIF.java
index 33a3790..640b269 100644
--- a/opends/src/server/org/opends/server/tools/ImportLDIF.java
+++ b/opends/src/server/org/opends/server/tools/ImportLDIF.java
@@ -662,8 +662,12 @@
 
     ArrayList<Backend>     backendList = new ArrayList<Backend>();
     ArrayList<ConfigEntry> entryList   = new ArrayList<ConfigEntry>();
-    ArrayList<List<DN>>    dnList      = new ArrayList<List<DN>>();
-    getBackends(backendList, entryList, dnList);
+    ArrayList<List<DN>> dnList = new ArrayList<List<DN>>();
+    int code = getBackends(backendList, entryList, dnList);
+    if (code != 0)
+    {
+      return code;
+    }
 
     int numBackends = backendList.size();
     for (int i=0; i < numBackends; i++)
@@ -1000,8 +1004,11 @@
    *                      the backends will be placed.
    * @param  dnList       A list into which the set of base DNs for each backend
    *                      will be placed.
+   *
+   * @return 0 if everything went fine. 1 if an error occurred.
+   *
    */
-  private static void getBackends(ArrayList<Backend> backendList,
+  private static int getBackends(ArrayList<Backend> backendList,
                                   ArrayList<ConfigEntry> entryList,
                                   ArrayList<List<DN>> dnList)
   {
@@ -1017,7 +1024,7 @@
       String message = getMessage(msgID, DN_BACKEND_BASE, de.getErrorMessage());
       logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message,
                msgID);
-      System.exit(1);
+      return 1;
     }
     catch (Exception e)
     {
@@ -1026,7 +1033,7 @@
                                   stackTraceToSingleLineString(e));
       logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message,
                msgID);
-      System.exit(1);
+      return 1;
     }
 
     ConfigEntry baseEntry = null;
@@ -1040,7 +1047,7 @@
       String message = getMessage(msgID, DN_BACKEND_BASE, ce.getMessage());
       logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message,
                msgID);
-      System.exit(1);
+      return 1;
     }
     catch (Exception e)
     {
@@ -1049,7 +1056,7 @@
                                   stackTraceToSingleLineString(e));
       logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message,
                msgID);
-      System.exit(1);
+      return 1;
     }
 
 
@@ -1084,7 +1091,7 @@
                                     ce.getMessage());
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                  message, msgID);
-        System.exit(1);
+        return 1;
       }
       catch (Exception e)
       {
@@ -1093,7 +1100,7 @@
                                     stackTraceToSingleLineString(e));
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                  message, msgID);
-        System.exit(1);
+        return 1;
       }
 
 
@@ -1124,7 +1131,7 @@
                                     ce.getMessage());
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                  message, msgID);
-        System.exit(1);
+        return 1;
       }
       catch (Exception e)
       {
@@ -1133,7 +1140,7 @@
                                     stackTraceToSingleLineString(e));
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                  message, msgID);
-        System.exit(1);
+        return 1;
       }
 
       Class backendClass = null;
@@ -1149,7 +1156,7 @@
                                     stackTraceToSingleLineString(e));
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                  message, msgID);
-        System.exit(1);
+        return 1;
       }
 
       Backend backend = null;
@@ -1166,7 +1173,7 @@
                                     stackTraceToSingleLineString(e));
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                  message, msgID);
-        System.exit(1);
+        return 1;
       }
 
 
@@ -1201,7 +1208,7 @@
                                     stackTraceToSingleLineString(e));
         logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                  message, msgID);
-        System.exit(1);
+        return 1;
       }
 
 
@@ -1209,6 +1216,7 @@
       entryList.add(configEntry);
       dnList.add(baseDNs);
     }
+    return 0;
   }
 }
 

--
Gitblit v1.10.0