From b7eaa6fa023b868aa8154610c05801a94ed0afea Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Fri, 05 Jan 2007 14:04:45 +0000
Subject: [PATCH] 

---
 opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif                     |    0 
 opends/src/quicksetup/org/opends/quicksetup/images/opends_logo_small.png                 |    0 
 opends/src/statuspanel/org/opends/statuspanel/ui/DatabasesTableModel.java                |  274 +
 opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java    |    4 
 opends/src/quicksetup/org/opends/quicksetup/images/info_small.gif                        |    0 
 opends/src/quicksetup/org/opends/quicksetup/ui/CustomHTMLEditorKit.java                  |  125 
 opends/src/statuspanel/org/opends/statuspanel/ServerStatusPooler.java                    |  408 ++
 opends/src/quicksetup/org/opends/quicksetup/images/error_medium.gif                      |    0 
 opends/src/quicksetup/org/opends/quicksetup/images/error_small.gif                       |    0 
 opends/src/statuspanel/org/opends/statuspanel/ui/StatusPanelDialog.java                  | 1459 +++++++++
 opends/src/statuspanel/org/opends/statuspanel/DatabaseDescriptor.java                    |  113 
 opends/src/quicksetup/org/opends/quicksetup/images/divider-left.png                      |    0 
 opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java |    3 
 opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties             |  179 +
 opends/src/quicksetup/org/opends/quicksetup/images/help_medium.gif                       |    0 
 opends/src/statuspanel/org/opends/statuspanel/ui/ListenersTableModel.java                |  272 +
 opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java                |    8 
 opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java                     |   77 
 opends/src/quicksetup/org/opends/quicksetup/images/warning_medium.gif                    |    0 
 opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java                  |   37 
 opends/src/statuspanel/org/opends/statuspanel/StatusCli.java                             |  943 ++++++
 opends/src/statuspanel/org/opends/statuspanel/StatusPanelController.java                 | 1241 ++++++++
 opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java                            |   93 
 opends/src/statuspanel/org/opends/statuspanel/event/StatusPanelButtonListener.java       |   60 
 opends/src/quicksetup/org/opends/quicksetup/images/error_large.gif                       |    0 
 opends/src/quicksetup/org/opends/quicksetup/images/help_large.gif                        |    0 
 opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties               |   65 
 opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java                     |   26 
 opends/src/statuspanel/org/opends/statuspanel/ui/ProgressDialog.java                     |  375 ++
 opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java                        |  702 ++++
 opends/src/statuspanel/org/opends/statuspanel/StatusPanelLauncher.java                   |  178 +
 opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java      |    4 
 opends/src/statuspanel/org/opends/statuspanel/ServerStatusDescriptor.java                |  356 ++
 opends/src/quicksetup/org/opends/quicksetup/images/info_large.gif                        |    0 
 opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java                     |   15 
 opends/src/statuspanel/org/opends/statuspanel/event/ServerStatusChangeEvent.java         |   63 
 opends/resource/bin/status.bat                                                           |   32 
 opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java                   |    6 
 opends/src/quicksetup/org/opends/quicksetup/images/warning_small.gif                     |    0 
 opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java       |    8 
 opends/resource/bin/statuspanel.bat                                                      |   32 
 opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java                    |   34 
 opends/src/quicksetup/org/opends/quicksetup/images/help_small.gif                        |    0 
 opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java                            |  146 
 opends/src/statuspanel/org/opends/statuspanel/ui/SortableTableModel.java                 |   67 
 opends/resource/bin/status                                                               |   34 
 opends/src/statuspanel/org/opends/statuspanel/SplashScreen.java                          |  111 
 opends/src/statuspanel/org/opends/statuspanel/ui/LoginDialog.java                        |  610 +++
 opends/src/quicksetup/org/opends/quicksetup/ButtonName.java                              |   10 
 opends/resource/bin/statuspanel                                                          |   34 
 opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java                        |   43 
 opends/src/quicksetup/org/opends/quicksetup/images/info_medium.gif                       |    0 
 opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java                 |   53 
 opends/src/statuspanel/org/opends/statuspanel/event/ServerStatusChangeListener.java      |   44 
 opends/src/quicksetup/org/opends/quicksetup/images/divider-right.png                     |    0 
 opends/build.xml                                                                         |   66 
 opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java                |    1 
 opends/src/statuspanel/org/opends/statuspanel/ListenerDescriptor.java                    |  148 
 opends/src/quicksetup/org/opends/quicksetup/util/Utils.java                              |   30 
 opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java                              |   87 
 opends/src/statuspanel/org/opends/statuspanel/ConfigFromFile.java                        |  418 ++
 opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java           |    4 
 opends/src/statuspanel/org/opends/statuspanel/i18n/ResourceProvider.java                 |  192 +
 63 files changed, 9,164 insertions(+), 126 deletions(-)

diff --git a/opends/build.xml b/opends/build.xml
index 2cc0618..6c0f6f3 100644
--- a/opends/build.xml
+++ b/opends/build.xml
@@ -80,6 +80,11 @@
   <property name="quicksetup.src.dir" location="src/quicksetup"       />
   <property name="quicksetup.classes.dir"
             location="${build.dir}/quicksetup/classes"                />
+	
+	<!-- Properties for use with the Status Panel.                      -->
+	  <property name="statuspanel.src.dir" location="src/statuspanel"       />
+	  <property name="statuspanel.classes.dir"
+	            location="${build.dir}/statuspanel/classes"                />
 
   <!-- Properties for code coverage testing.                            -->
   <property name="coverage.dir"         location="build/coverage"            />
@@ -232,17 +237,23 @@
     <taskdef resource="checkstyletask.properties"
          classpath="${checkstyle.dir}/checkstyle-all-4.1.jar" />
 
-  	<checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
+    <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
          failOnViolation="true">
       <fileset dir="${src.dir}" includes="**/*.java" />
       <formatter type="plain" />
     </checkstyle>
-	
+
     <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
          failOnViolation="true">
       <fileset dir="${quicksetup.src.dir}" includes="**/*.java" />
       <formatter type="plain" />
     </checkstyle>
+  	
+  	<checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
+  	         failOnViolation="true">
+  	      <fileset dir="${statuspanel.src.dir}" includes="**/*.java" />
+  	      <formatter type="plain" />
+  	    </checkstyle>
 
     <checkstyle config="${checkstyle.dir}/opends-doctarget-checkstyle.xml"
          failOnViolation="true">
@@ -270,7 +281,7 @@
 
 
   <!-- Compile the Directory Server source files. -->
-  <target name="cleancompile" depends="cleaninit,compile,compilequicksetup"
+  <target name="cleancompile" depends="cleaninit,compile,compilequicksetup,compilestatuspanel"
        description="Recompile the Directory Server source files.">
   </target>
 
@@ -322,6 +333,28 @@
                includes="**/DynamicConstants.class **/SetupUtils.class" />
     </copy>
   </target>
+	
+	<!-- Compile the Status Panel source files. -->
+	  <target name="compilestatuspanel" depends="compilequicksetup"
+	          description="Compile the Status Panel source files.">
+
+	    <mkdir dir="${statuspanel.classes.dir}" />
+	    <javac srcdir="${statuspanel.src.dir}" destdir="${statuspanel.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>
+	        <pathelement path="${classes.dir}"/>
+	        <pathelement path="${quicksetup.classes.dir}"/>
+	      </classpath>
+	    </javac>
+	    <copy todir="${statuspanel.classes.dir}">
+	      <fileset dir="${statuspanel.src.dir}"
+	               includes="**/*.properties, **/*.gif, **/*.png" />
+	    </copy>
+	  </target>
 
   <!--
    ! Rebuild the Directory Server without destroying any existing configuration
@@ -351,6 +384,7 @@
     <delete file="${pdir}.zip" />
     <delete dir="${quicksetup.classes.dir}" />
     <delete file="${package.dir}/lib/quicksetup.jar" />
+  	<delete file="${package.dir}/lib/statuspanel.jar" />
     
     <!-- Recreate the classes directory and recompile into it. -->
     <mkdir dir="${classes.dir}" />
@@ -401,6 +435,29 @@
     <!-- Generate the quicksetup.jar file -->
     <jar jarfile="${pdir}/lib/quicksetup.jar"
          basedir="${quicksetup.classes.dir}" compress="true" index="true" />
+  	
+    <!-- Recreate the controlpanel classes directory and recompile into it. -->
+    <mkdir dir="${controlpanel.classes.dir}" />
+    <javac srcdir="${controlpanel.src.dir}" destdir="${controlpanel.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="${pdir}/lib">
+                <include name="OpenDS.jar" />
+            </fileset>
+        </classpath>
+    </javac>
+
+    <copy todir="${controlpanel.classes.dir}">
+        <fileset dir="${controlpanel.src.dir}"
+            includes="**/*.properties, **/*.gif, **/*.png"/>
+    </copy>
+            	
+  	<!-- Generate the statuspanel.jar file -->
+  	    <jar jarfile="${pdir}/lib/statuspanel.jar"
+  	         basedir="${statuspanel.classes.dir}" compress="true" index="true" />
   </target>
 
 
@@ -436,6 +493,9 @@
     
     <jar jarfile="${pdir}/lib/quicksetup.jar"
          basedir="${quicksetup.classes.dir}" compress="true" index="true" />
+  	
+  	<jar jarfile="${pdir}/lib/statuspanel.jar"
+  	         basedir="${statuspanel.classes.dir}" compress="true" index="true" />
          
     <copy todir="${pdir}/lib">
       <fileset file="${lib.dir}/*.jar" />
diff --git a/opends/resource/bin/status b/opends/resource/bin/status
new file mode 100644
index 0000000..4346d48
--- /dev/null
+++ b/opends/resource/bin/status
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License").  You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at
+# trunk/opends/resource/legal-notices/OpenDS.LICENSE
+# or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at
+# trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+# add the following below this CDDL HEADER, with the fields enclosed
+# by brackets "[]" replaced with your own identifying * information:
+#      Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#      Portions Copyright 2006 Sun Microsystems, Inc.
+
+
+# This script may be used to display the status panel.
+OPENDS_INVOKE_CLASS="org.opends.statuspanel.StatusCli"
+export OPENDS_INVOKE_CLASS
+
+SCRIPT_DIR=`dirname "${0}"`
+"${SCRIPT_DIR}/_server-script.sh" "${@}"
diff --git a/opends/resource/bin/status.bat b/opends/resource/bin/status.bat
new file mode 100644
index 0000000..6b52e7c
--- /dev/null
+++ b/opends/resource/bin/status.bat
@@ -0,0 +1,32 @@
+
+@echo off
+rem CDDL HEADER START
+rem
+rem The contents of this file are subject to the terms of the
+rem Common Development and Distribution License, Version 1.0 only
+rem (the "License").  You may not use this file except in compliance
+rem with the License.
+rem
+rem You can obtain a copy of the license at
+rem trunk/opends/resource/legal-notices/OpenDS.LICENSE
+rem or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+rem See the License for the specific language governing permissions
+rem and limitations under the License.
+rem
+rem When distributing Covered Code, include this CDDL HEADER in each
+rem file and include the License file at
+rem trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+rem add the following below this CDDL HEADER, with the fields enclosed
+rem by brackets "[]" replaced with your own identifying * information:
+rem      Portions Copyright [yyyy] [name of copyright owner]
+rem
+rem CDDL HEADER END
+rem
+rem
+rem      Portions Copyright 2006 Sun Microsystems, Inc.
+
+setlocal
+
+set OPENDS_INVOKE_CLASS="org.opends.statuspanel.StatusCli"
+set SCRIPT_NAME_ARG="-Dorg.opends.server.scriptName=status"
+call "%~dP0\_server-script.bat" %*
diff --git a/opends/resource/bin/statuspanel b/opends/resource/bin/statuspanel
new file mode 100644
index 0000000..0792365
--- /dev/null
+++ b/opends/resource/bin/statuspanel
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License").  You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at
+# trunk/opends/resource/legal-notices/OpenDS.LICENSE
+# or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at
+# trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+# add the following below this CDDL HEADER, with the fields enclosed
+# by brackets "[]" replaced with your own identifying * information:
+#      Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#      Portions Copyright 2006 Sun Microsystems, Inc.
+
+
+# This script may be used to display the status panel.
+OPENDS_INVOKE_CLASS="org.opends.statuspanel.StatusPanelLauncher"
+export OPENDS_INVOKE_CLASS
+
+SCRIPT_DIR=`dirname "${0}"`
+"${SCRIPT_DIR}/_server-script.sh" "${@}"
diff --git a/opends/resource/bin/statuspanel.bat b/opends/resource/bin/statuspanel.bat
new file mode 100644
index 0000000..1fd8501
--- /dev/null
+++ b/opends/resource/bin/statuspanel.bat
@@ -0,0 +1,32 @@
+
+@echo off
+rem CDDL HEADER START
+rem
+rem The contents of this file are subject to the terms of the
+rem Common Development and Distribution License, Version 1.0 only
+rem (the "License").  You may not use this file except in compliance
+rem with the License.
+rem
+rem You can obtain a copy of the license at
+rem trunk/opends/resource/legal-notices/OpenDS.LICENSE
+rem or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+rem See the License for the specific language governing permissions
+rem and limitations under the License.
+rem
+rem When distributing Covered Code, include this CDDL HEADER in each
+rem file and include the License file at
+rem trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+rem add the following below this CDDL HEADER, with the fields enclosed
+rem by brackets "[]" replaced with your own identifying * information:
+rem      Portions Copyright [yyyy] [name of copyright owner]
+rem
+rem CDDL HEADER END
+rem
+rem
+rem      Portions Copyright 2006 Sun Microsystems, Inc.
+
+setlocal
+
+set OPENDS_INVOKE_CLASS="org.opends.statuspanel.StatusPanelLauncher"
+set SCRIPT_NAME_ARG="-Dorg.opends.server.scriptName=statuspanel"
+call "%~dP0\_server-script.bat" %*
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java b/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
index 11132fb..5219ff9 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
@@ -46,6 +46,10 @@
    */
   QUIT,
   /**
+   * The Continue with install button.
+   */
+  CONTINUE_INSTALL,
+  /**
    * The Close button.
    */
   CLOSE,
@@ -56,5 +60,9 @@
   /**
    * The Cancel button.
    */
-  CANCEL
+  CANCEL,
+  /**
+   * The Launch Status Panel button.
+   */
+  LAUNCH_STATUS_PANEL
 }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java b/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
index 22d74b5..d3ea554 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
@@ -52,6 +52,8 @@
 {
   private boolean isInstalled;
 
+  private boolean canOverwriteCurrentInstall;
+
   private String installationMsg;
 
   private String configFileContents;
@@ -77,24 +79,18 @@
       isInstalled = false;
     } else
     {
+      boolean dbFileExists = false;
       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[]
+        msgs.add(getMsg("installstatus-serverrunning", new String[]
             { String.valueOf(getPort()) }));
-        }
       }
 
       if (dbFilesExist())
       {
+        dbFileExists = true;
         msgs.add(getMsg("installstatus-dbfileexist"));
       }
 
@@ -102,8 +98,14 @@
       {
         msgs.add(getMsg("installstatus-configfilemodified"));
       }
+      canOverwriteCurrentInstall = (msgs.size() == 1) && dbFileExists;
       isInstalled = msgs.size() > 0;
-      if (isInstalled)
+      if (canOverwriteCurrentInstall)
+      {
+        installationMsg =
+          getMsg("installstatus-canoverwritecurrentinstall-msg");
+      }
+      else if (isInstalled)
       {
         StringBuffer buf = new StringBuffer();
         buf.append("<ul>");
@@ -134,6 +136,18 @@
   }
 
   /**
+   * Indicates can overwrite current install.
+   *
+   * @return <CODE>true</CODE> if there is something installed under the
+   *         binaries that we are running and we can overwrite it and
+   *         <CODE>false</CODE> if not.
+   */
+  public boolean canOverwriteCurrentInstall()
+  {
+    return canOverwriteCurrentInstall;
+  }
+
+  /**
    * Provides a localized message to be displayed to the user in HTML format
    * informing of the installation status.
    *
diff --git a/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java b/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
index 7eedf95..aa6dc84 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
@@ -27,10 +27,12 @@
 
 package org.opends.quicksetup;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
 import javax.swing.SwingUtilities;
@@ -197,6 +199,10 @@
       quitClicked();
       break;
 
+    case CONTINUE_INSTALL:
+      continueInstallClicked();
+      break;
+
     case PREVIOUS:
       previousClicked();
       break;
@@ -205,6 +211,10 @@
       cancelClicked();
       break;
 
+    case LAUNCH_STATUS_PANEL:
+      launchStatusPanelClicked();
+      break;
+
     default:
       throw new IllegalArgumentException("Unknown button name: "
           + ev.getButtonName());
@@ -557,6 +567,25 @@
   }
 
   /**
+   * Method called when user clicks 'Continue' button in the case where there
+   * is something installed.
+   */
+  private void continueInstallClicked()
+  {
+    Step cStep = getCurrentStep();
+    switch (cStep)
+    {
+    case WELCOME:
+      getDialog().forceToDisplaySetup();
+      setCurrentStep(Step.WELCOME);
+      break;
+    default:
+      throw new IllegalStateException(
+          "Continue only can be clicked on WELCOME step");
+    }
+  }
+
+  /**
    * Method called when user clicks 'Close' button of the wizard.
    *
    */
@@ -612,6 +641,64 @@
     }
   }
 
+  private void launchStatusPanelClicked()
+  {
+    BackgroundTask worker = new BackgroundTask()
+    {
+      public Object processBackgroundTask() throws UserInstallDataException
+      {
+        try
+        {
+          String cmd = Utils.isWindows()?"statuspanel.bat":"statuspanel";
+          String serverPath;
+          if (Utils.isWebStart())
+          {
+            serverPath = getUserInstallData().getServerLocation();
+          }
+          else
+          {
+            serverPath = Utils.getInstallPathFromClasspath();
+          }
+          cmd = Utils.getPath(serverPath, "bin"+File.separator+cmd);
+          ProcessBuilder pb = new ProcessBuilder(new String[]{cmd});
+          Map<String, String> env = pb.environment();
+          env.put("JAVA_HOME", System.getProperty("java.home"));
+          /* Remove JAVA_BIN to be sure that we use the JVM running the
+           * uninstaller JVM to stop the server.
+           */
+          env.remove("JAVA_BIN");
+          Process process = pb.start();
+          int returnValue = process.waitFor();
+
+          if (returnValue != 0)
+          {
+            throw new Error(getMsg("could-not-launch-status-panel-msg"));
+          }
+        }
+        catch (Throwable t)
+        {
+          // This looks like a bug
+          t.printStackTrace();
+          throw new Error(getMsg("could-not-launch-status-panel-msg"));
+        }
+        return null;
+      }
+
+      public void backgroundTaskCompleted(Object returnValue,
+          Throwable throwable)
+      {
+        getDialog().workerFinished();
+
+        if (throwable != null)
+        {
+          displayError(throwable.getMessage(), getMsg("error-title"));
+        }
+      }
+    };
+    getDialog().workerStarted();
+    worker.startBackgroundTask();
+  }
+
   /**
    * 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
diff --git a/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java b/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java
index 74533b6..51b9f2b 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java
@@ -41,12 +41,18 @@
 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 is the class that displays a splash screen and in the background it will
+ * create QuickSetup object.
+ *
+ * The main method of this class is directly called by the Java Web Start
+ * mechanism to launch the JWS setup.
  *
  * 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.
+ *
+ * This class can be reused by simply overwriting the methods
+ * constructApplication() and displayApplication().
  */
 public class SplashScreen extends Window
 {
@@ -54,11 +60,9 @@
 
   private Image image;
 
-  private static SplashScreen splash;
+  private Object quickSetup;
 
-  private static Object quickSetup;
-
-  private static Class<?> quickSetupClass;
+  private Class<?> quickSetupClass;
 
   // Constant for the display of the splash screen
   private static final int MIN_SPLASH_DISPLAY = 3000;
@@ -70,21 +74,8 @@
    */
   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);
-    }
+    SplashScreen screen = new SplashScreen();
+    screen.display(args);
   }
 
   /**
@@ -104,10 +95,10 @@
   }
 
   /**
-   * Private constructor to force to use the main method.
+   * Protected constructor to force to use the main method.
    *
    */
-  private SplashScreen()
+  protected SplashScreen()
   {
     super(new Frame());
     try
@@ -130,6 +121,31 @@
   }
 
   /**
+   * The method used to display the splash screen.  It will also call create
+   * the application associated with this SplashScreen and display it.
+   * It can be called from the event thread and outside the event thread.
+   * @param args arguments to be passed to the method QuickSetup.initialize
+   */
+  protected void display(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);
+    }
+  }
+
+  /**
    * This method creates the image directly instead of using UIFactory to reduce
    * class loading.
    * @return the splash image.
@@ -148,30 +164,29 @@
    *
    * @param args arguments to be passed to the method QuickSetup.initialize.
    */
-  private static void mainOutsideEventThread(String[] args)
+  private void mainOutsideEventThread(String[] args)
   {
     displaySplashScreen();
     long splashDisplayStartTime = System.currentTimeMillis();
-    constructQuickSetup(args);
+    constructApplication(args);
     sleepIfNecessary(splashDisplayStartTime);
     disposeSplashScreen();
-    displayQuickSetup();
+    displayApplication();
   }
 
   /**
    * This methods displays the splash screen.
    * This method assumes that is being called outside the event thread.
    */
-  private static void displaySplashScreen()
+  private void displaySplashScreen()
   {
-    splash = new SplashScreen();
     try
     {
       SwingUtilities.invokeAndWait(new Runnable()
       {
         public void run()
         {
-          splash.setVisible(true);
+          setVisible(true);
         }
       });
     } catch (Exception ex)
@@ -181,11 +196,13 @@
   }
 
   /**
-   * This methods constructs the QuickSetup object.
+   * This methods constructs the objects before displaying them.
    * This method assumes that is being called outside the event thread.
-   * @param args arguments to be passed to the method QuickSetup.initialize.
+   * This method can be overwritten by subclasses to construct other objects
+   * different than the Quick Setup.
+   * @param args arguments passed in the main of this class.
    */
-  private static void constructQuickSetup(String[] args)
+  protected void constructApplication(String[] args)
   {
     try
     {
@@ -207,8 +224,10 @@
    * This method displays the QuickSetup dialog.
    * @see QuickSetup.display.
    * This method assumes that is being called outside the event thread.
+   * This method can be overwritten by subclasses to construct other objects
+   * different than the Quick Setup.
    */
-  private static void displayQuickSetup()
+  protected void displayApplication()
   {
     try
     {
@@ -237,7 +256,7 @@
    * Disposes the splash screen.
    * This method assumes that is being called outside the event thread.
    */
-  private static void disposeSplashScreen()
+  private void disposeSplashScreen()
   {
     try
     {
@@ -245,8 +264,8 @@
       {
         public void run()
         {
-          splash.setVisible(false);
-          splash.dispose();
+          setVisible(false);
+          dispose();
         }
       });
     } catch (Exception ex)
@@ -262,7 +281,7 @@
    * @param splashDisplayStartTime the time in milliseconds when the splash
    * screen started displaying.
    */
-  private static void sleepIfNecessary(long splashDisplayStartTime)
+  private void sleepIfNecessary(long splashDisplayStartTime)
   {
     long t2 = System.currentTimeMillis();
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java b/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
index 873b535..edbe351 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
@@ -49,7 +49,11 @@
   private static final String BUNDLE_NAME =
       "org.opends.quicksetup.resources.Resources";
 
-  private ResourceProvider()
+  /**
+   * This constructor is protected to be able to subclass.
+   *
+   */
+  protected ResourceProvider()
   {
   }
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/divider-left.png b/opends/src/quicksetup/org/opends/quicksetup/images/divider-left.png
new file mode 100644
index 0000000..1246eea
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/divider-left.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/divider-right.png b/opends/src/quicksetup/org/opends/quicksetup/images/divider-right.png
new file mode 100644
index 0000000..bbf7cad
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/divider-right.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/error_large.gif b/opends/src/quicksetup/org/opends/quicksetup/images/error_large.gif
new file mode 100644
index 0000000..1c77d5f
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/error_large.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/error_medium.gif b/opends/src/quicksetup/org/opends/quicksetup/images/error_medium.gif
new file mode 100644
index 0000000..b2adff0
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/error_medium.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/error_small.gif b/opends/src/quicksetup/org/opends/quicksetup/images/error_small.gif
new file mode 100644
index 0000000..fadbec4
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/error_small.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/help_large.gif b/opends/src/quicksetup/org/opends/quicksetup/images/help_large.gif
new file mode 100644
index 0000000..8f9122a
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/help_large.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/help_medium.gif b/opends/src/quicksetup/org/opends/quicksetup/images/help_medium.gif
new file mode 100644
index 0000000..4ea88cb
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/help_medium.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/help_small.gif b/opends/src/quicksetup/org/opends/quicksetup/images/help_small.gif
new file mode 100644
index 0000000..fb3117e
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/help_small.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/info_large.gif b/opends/src/quicksetup/org/opends/quicksetup/images/info_large.gif
new file mode 100644
index 0000000..699ad22
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/info_large.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/info_medium.gif b/opends/src/quicksetup/org/opends/quicksetup/images/info_medium.gif
new file mode 100644
index 0000000..55a2165
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/info_medium.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/info_small.gif b/opends/src/quicksetup/org/opends/quicksetup/images/info_small.gif
new file mode 100644
index 0000000..9677588
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/info_small.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opends_logo_small.png b/opends/src/quicksetup/org/opends/quicksetup/images/opends_logo_small.png
new file mode 100644
index 0000000..0e20fce
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opends_logo_small.png
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
index 8c002bf..7314b3f 100755
--- a/opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/warning_medium.gif b/opends/src/quicksetup/org/opends/quicksetup/images/warning_medium.gif
new file mode 100644
index 0000000..8d66a51
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/warning_medium.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/warning_small.gif b/opends/src/quicksetup/org/opends/quicksetup/images/warning_small.gif
new file mode 100644
index 0000000..50c4d76
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/warning_small.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index aae9180..d299d05 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -41,6 +41,7 @@
 import org.opends.quicksetup.event.InstallProgressUpdateEvent;
 import org.opends.quicksetup.event.InstallProgressUpdateListener;
 import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.ui.UIFactory;
 import org.opends.quicksetup.util.ProgressMessageFormatter;
 import org.opends.quicksetup.util.Utils;
 import org.opends.server.util.SetupUtils;
@@ -1039,10 +1040,20 @@
     hmSummary.put(InstallProgressStep.STARTING_SERVER,
         getFormattedSummary(getMsg("summary-starting")));
 
-    String[] arg = {formatter.getFormattedText(getInstallationPath())};
+    String cmd;
+    if (Utils.isWindows())
+    {
+      cmd = "bin"+File.separator+"statuspanel.bat";
+    }
+    else
+    {
+      cmd = "bin"+File.separator+"statuspanel";
+    }
+    cmd = UIFactory.applyFontToHtml(cmd, UIFactory.INSTRUCTIONS_MONOSPACE_FONT);
+    String[] args = {formatter.getFormattedText(getInstallationPath()), cmd};
     hmSummary.put(InstallProgressStep.FINISHED_SUCCESSFULLY,
         getFormattedSuccess(
-            getMsg("summary-install-finished-successfully", arg)));
+            getMsg("summary-install-finished-successfully", args)));
     hmSummary.put(InstallProgressStep.FINISHED_WITH_ERROR,
         getFormattedError(getMsg("summary-install-finished-with-error")));
   }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java b/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
index e9ac9fd..2473723 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
@@ -109,6 +109,8 @@
    */
   private void doInstall()
   {
+    PrintStream origErr = System.err;
+    PrintStream origOut = System.out;
     try
     {
       PrintStream err = new ErrorPrintStream();
@@ -171,6 +173,8 @@
       String msg = getFormattedError(ex, true);
       notifyListeners(msg);
     }
+    System.setErr(origErr);
+    System.setOut(origOut);
   }
 
   /**
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
index 8efd4f1..d972eb6 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
@@ -129,6 +129,8 @@
    */
   private void doInstall()
   {
+    PrintStream origErr = System.err;
+    PrintStream origOut = System.out;
     try
     {
       PrintStream err = new ErrorPrintStream();
@@ -195,6 +197,8 @@
       String msg = getFormattedError(ex, true);
       notifyListeners(msg);
     }
+    System.setErr(origErr);
+    System.setOut(origOut);
   }
 
   /**
diff --git a/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
index cfb1ba8..2fa88fc 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
+++ b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -1,3 +1,31 @@
+# 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
+#
+#
+# This file contains the primary Directory Server configuration.  It must not
+# be directly edited while the server is online.  The server configuration
+# should only be managed using the administration utilities provided with the
+# Directory Server.
+
 #
 # Setup command line messages
 #
@@ -51,8 +79,8 @@
 -w {password}  or   --rootUserPassword {password}\n    Specifies the password \
 of the Administrative User (Directory Manager) of the Directory Server.\n\
 -W {filename}  or   --rootUserPasswordFile {filename}\n    Specifies the path \
-to a file containing the password for the initial Administrative\n\    User \
-for the Directory Server.\n\
+to a file containing the password for the Administrative\n\    User \
+of the Directory Server.\n\
 -s  or   --silentUninstall\n    Perform a silent uninstall.
 uninstall-launcher-usage-unix=This utility may be used to uninstall the \
 Directory Server.\n\
@@ -156,6 +184,8 @@
 cancel-button-label=Cancel
 cancel-button-uninstall-tooltip=Cancel Uninstall
 shutdown-button-label=Shutdown
+continue-button-label=Continue
+continue-button-install-tooltip=Continue with the QuickSetup Tool
 
 #
 # Confirmation dialogs
@@ -187,6 +217,12 @@
 error-title=Error
 
 #
+# Error when we cannot launch the status panel
+#
+could-not-launch-status-panel-msg=An unexpected error occurred launching the \
+Status Panel.
+
+#
 # Browser launching error dialog
 #
 error-browser-display-msg=Could not launch the web browser.<br>You can copy \
@@ -288,12 +324,16 @@
 warning-icon-description=Warning.
 error-icon-description=Error.
 information-icon-description=Information.
+opends-small-icon-description=OpenDS icon.
+subsection-left-icon-description=Decoration icon.
+subsection-right-icon-description=Decoration icon.
+help-small-icon-description=Help icon.
 
 #
 # Icon tooltips.
 #
 current-step-icon-tooltip=Current Step Indicator
-splash-icon-tooltip=Open DS QuickSetup Launching
+splash-icon-tooltip=OpenDS QuickSetup Launching
 minimized-icon-tooltip=OpenDS QuickSetup
 background-icon-tooltip=OpenDS QuickSetup
 warning-icon-tooltip=Warning
@@ -311,10 +351,16 @@
 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
+error-icon=images/error_small.gif
+error-large-icon=images/error_large.gif
+warning-icon=images/warning_small.gif
 warning-large-icon=images/warning_large.gif
-information-icon=images/information.gif
+information-icon=images/info_small.gif
+information-large-icon=images/info_large.gif
+subsection-left-icon=images/divider-left.png
+subsection-right-icon=images/divider-right.png
+opends-small-icon=images/opends_logo_small.png
+help-small-icon=images/help_small.gif
 
 #
 # Welcome Panel specific labels
@@ -486,7 +532,9 @@
 Successfully.</b><br>OpenDS is now installed in {0}.<br><br>Visit the \
 <a href="https://opends.dev.java.net/public/docs/user-docs/OpenDS-QuickReference.html"> \
 OpenDS Quick Reference</a> page for an overview of server management and \
-configuration.
+configuration.<br>To see basic server configuration status and to start/stop \
+the server, click Launch Status Panel.  Note that you can launch this tool \
+later using {1}.<br><INPUT type="submit" value="Launch Status Panel"></INPUT>
 summary-install-finished-with-error=An error occurred.  Check 'Details' text \
 area for more information.
 summary-stopping=Stopping Directory Server...
@@ -587,3 +635,6 @@
 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.
+installstatus-canoverwritecurrentinstall-msg=The Directory Server contains \
+some database files.<br>If you continue with the setup the contents of these \
+database files will be deleted.
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
index 9155a1e..8bf1674 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
@@ -34,6 +34,7 @@
 
 import org.opends.quicksetup.CurrentInstallStatus;
 import org.opends.quicksetup.Step;
+import org.opends.quicksetup.event.ButtonActionListener;
 import org.opends.quicksetup.installer.FieldName;
 import org.opends.quicksetup.installer.InstallProgressDescriptor;
 import org.opends.quicksetup.installer.UserInstallData;
@@ -167,6 +168,31 @@
   }
 
   /**
+   * 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)
+  {
+    for (Step s : hmPanels.keySet())
+    {
+      getPanel(s).addButtonActionListener(l);
+    }
+  }
+
+  /**
+   * Removes a button listener.
+   * @param l the ButtonActionListener to be removed.
+   */
+  public void removeButtonActionListener(ButtonActionListener l)
+  {
+    for (Step s : hmPanels.keySet())
+    {
+      getPanel(s).removeButtonActionListener(l);
+    }
+  }
+
+  /**
    * 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.
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/CustomHTMLEditorKit.java b/opends/src/quicksetup/org/opends/quicksetup/ui/CustomHTMLEditorKit.java
new file mode 100644
index 0000000..ee5331d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/CustomHTMLEditorKit.java
@@ -0,0 +1,125 @@
+/*
+ * 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.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashSet;
+
+import javax.swing.text.Element;
+import javax.swing.text.View;
+import javax.swing.text.ViewFactory;
+import javax.swing.text.html.FormView;
+import javax.swing.text.html.HTMLEditorKit;
+
+/**
+ * Class used to be able to detect events in the button inside an HTML pane.
+ */
+class CustomHTMLEditorKit extends HTMLEditorKit
+{
+  private HashSet<ActionListener> listeners = new HashSet<ActionListener>();
+  private static final long serialVersionUID = 298103926252426388L;
+
+  /**
+   * Default constructor.
+   */
+  CustomHTMLEditorKit()
+  {
+    super();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public ViewFactory getViewFactory()
+  {
+    return new MyHTMLFactory();
+  }
+
+  /**
+   * Adds an action listener.
+   * @param l the action listener to add.
+   */
+  public void addActionListener(ActionListener l)
+  {
+    listeners.add(l);
+  }
+
+  /**
+   * Removes an action listener.
+   * @param l the action listener to remove.
+   */
+  public void removeActionListener(ActionListener l)
+  {
+    listeners.remove(l);
+  }
+
+  /**
+   * Class used to be able to detect events in the button inside an HTML pane.
+   */
+  class MyHTMLFactory extends HTMLFactory
+  {
+    /**
+     * {@inheritDoc}
+     */
+    public View create(Element elem)
+    {
+      View v = super.create(elem);
+      if (v instanceof FormView)
+      {
+        v = new MyFormView(elem);
+      }
+      return v;
+    }
+  }
+
+  /**
+   * Class used to be able to detect events in the button inside an HTML pane.
+   */
+  class MyFormView extends FormView
+  {
+    /**
+     * {@inheritDoc}
+     */
+    MyFormView(Element elem)
+    {
+      super(elem);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void actionPerformed(ActionEvent ev)
+    {
+      for (ActionListener l: listeners)
+      {
+        l.actionPerformed(ev);
+      }
+    }
+  }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java b/opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java
index c6895b1..b95d54b 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/DirectoryManagerAuthenticationDialog.java
@@ -185,7 +185,7 @@
     gbc.gridwidth = GridBagConstraints.RELATIVE;
     gbc.anchor = GridBagConstraints.NORTHWEST;
     gbc.insets = UIFactory.getCurrentStepPanelInsets();
-    p1.add(UIFactory.makeJLabel(UIFactory.IconType.WARNING_LARGE, null,
+    p1.add(UIFactory.makeJLabel(UIFactory.IconType.INFORMATION_LARGE, null,
         UIFactory.TextStyle.NO_STYLE), gbc);
     gbc.weightx = 1.0;
     gbc.fill = GridBagConstraints.BOTH;
@@ -195,6 +195,7 @@
     JTextComponent textPane =
       UIFactory.makeHtmlPane(msg, UIFactory.INSTRUCTIONS_FONT);
     textPane.setOpaque(false);
+    textPane.setEditable(false);
     p1.add(textPane, gbc);
 
     JPanel p2 = new JPanel(new GridBagLayout());
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
index 3bccf01..76e3663 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
@@ -30,6 +30,8 @@
 import java.awt.Component;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 
 import javax.swing.Box;
 import javax.swing.JEditorPane;
@@ -40,6 +42,8 @@
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
 
+import org.opends.quicksetup.ButtonName;
+import org.opends.quicksetup.event.ButtonEvent;
 import org.opends.quicksetup.installer.InstallProgressDescriptor;
 import org.opends.quicksetup.installer.InstallProgressStep;
 import org.opends.quicksetup.uninstaller.UninstallProgressDescriptor;
@@ -87,9 +91,22 @@
     gbc.weightx = 1.0;
     gbc.fill = GridBagConstraints.HORIZONTAL;
 
-    progressBarLabel =
-        UIFactory.makeHtmlPane(getMsg("progressbar-initial-label"),
-            UIFactory.PROGRESS_FONT);
+    progressBarLabel = UIFactory.makeHtmlPane(
+        getMsg("progressbar-initial-label"), UIFactory.PROGRESS_FONT);
+    progressBarLabel.setOpaque(false);
+    progressBarLabel.setEditable(false);
+    CustomHTMLEditorKit htmlEditor = new CustomHTMLEditorKit();
+    htmlEditor.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        // Assume is the authentication button.
+        ButtonEvent be = new ButtonEvent(ev.getSource(),
+            ButtonName.LAUNCH_STATUS_PANEL);
+        notifyButtonListeners(be);
+      }
+    });
+    progressBarLabel.setEditorKit(htmlEditor);
     progressBarLabel.addHyperlinkListener(this);
     panel.add(progressBarLabel, gbc);
 
@@ -159,9 +176,15 @@
    */
   public void displayProgress(InstallProgressDescriptor descriptor)
   {
-    progressBarLabel.setText(UIFactory.applyFontToHtml(descriptor
-        .getProgressBarMsg(), UIFactory.PROGRESS_FONT));
     InstallProgressStep status = descriptor.getProgressStep();
+    String summaryText = UIFactory.applyFontToHtml(descriptor
+        .getProgressBarMsg(), UIFactory.PROGRESS_FONT);
+    if (status == InstallProgressStep.FINISHED_SUCCESSFULLY)
+    {
+      summaryText = "<form>"+summaryText+"</form>";
+    }
+    progressBarLabel.setText(summaryText);
+
     if ((status == InstallProgressStep.FINISHED_WITH_ERROR)
         || (status == InstallProgressStep.FINISHED_SUCCESSFULLY))
     {
@@ -182,9 +205,15 @@
    */
   public void displayProgress(UninstallProgressDescriptor descriptor)
   {
-    progressBarLabel.setText(UIFactory.applyFontToHtml(descriptor
-        .getProgressBarMsg(), UIFactory.PROGRESS_FONT));
     UninstallProgressStep status = descriptor.getProgressStep();
+    String summaryText = UIFactory.applyFontToHtml(descriptor
+        .getProgressBarMsg(), UIFactory.PROGRESS_FONT);
+    if (status == UninstallProgressStep.FINISHED_SUCCESSFULLY)
+    {
+      summaryText = "<form>"+summaryText+"</form>";
+    }
+    progressBarLabel.setText(summaryText);
+
     if ((status == UninstallProgressStep.FINISHED_WITH_ERROR)
         || (status == UninstallProgressStep.FINISHED_SUCCESSFULLY))
     {
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
index 13bd825..0adfe02 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
@@ -27,6 +27,7 @@
 
 package org.opends.quicksetup.ui;
 
+import java.awt.event.ComponentListener;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.util.HashSet;
@@ -87,6 +88,8 @@
   private HashSet<ButtonActionListener> buttonListeners =
       new HashSet<ButtonActionListener>();
 
+  private boolean forceToDisplaySetup;
+
   /**
    * Constructor of QuickSetupDialog.
    * @param defaultUserData the default values to be proposed to the user in
@@ -123,10 +126,10 @@
             // Simulate a quit button event
             notifyButtonEvent(ButtonName.QUIT);
           }
-        } else if (isInstalled())
+        } else if (isInstalled() && !forceToDisplaySetup)
         {
           // Simulate a close button event
-          notifyButtonEvent(ButtonName.CLOSE);
+          notifyButtonEvent(ButtonName.QUIT);
         } else
         {
           if (getDisplayedStep() == Step.PROGRESS)
@@ -166,12 +169,19 @@
     if (isUninstall())
     {
       setFocusOnButton(ButtonName.FINISH);
-    } else if (!isInstalled())
+    } else if (!isInstalled() || forceToDisplaySetup)
     {
       setFocusOnButton(ButtonName.NEXT);
     } else
     {
-      setFocusOnButton(ButtonName.QUIT);
+      if (installStatus.canOverwriteCurrentInstall())
+      {
+        setFocusOnButton(ButtonName.CONTINUE_INSTALL);
+      }
+      else
+      {
+        setFocusOnButton(ButtonName.QUIT);
+      }
     }
 
     frame.addComponentListener(new MinimumSizeComponentListener(frame,
@@ -181,6 +191,36 @@
   }
 
   /**
+   * This method is called when we detected that there is something installed
+   * we inform of this to the user and the user wants to proceed with the
+   * installation destroying the contents of the data and the configuration
+   * in the current installation.
+   *
+   */
+  public void forceToDisplaySetup()
+  {
+    forceToDisplaySetup = true;
+    frame.getContentPane().removeAll();
+    frame.getContentPane().add(getFramePanel());
+    frame.pack();
+    Utils.centerOnScreen(frame);
+    setFocusOnButton(ButtonName.NEXT);
+    int minWidth = (int) frame.getPreferredSize().getWidth();
+    int minHeight = (int) frame.getPreferredSize().getHeight();
+
+    ComponentListener[] listeners = frame.getComponentListeners();
+    for (int i=0; i<listeners.length; i++)
+    {
+      if (listeners[i] instanceof MinimumSizeComponentListener)
+      {
+        frame.removeComponentListener(listeners[i]);
+      }
+    }
+    frame.addComponentListener(new MinimumSizeComponentListener(frame,
+        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.
@@ -221,7 +261,7 @@
         setButtonEnabled(ButtonName.CLOSE, false);
         break;
       }
-    } else if (!isInstalled())
+    } else if (!isInstalled() || forceToDisplaySetup)
     {
       // First call the panels to do the required updates on their layout
       getButtonsPanel().setDisplayedStep(step);
@@ -380,16 +420,11 @@
    */
   public void addButtonActionListener(ButtonActionListener l)
   {
-    if (isUninstall())
-    {
-      getButtonsPanel().addButtonActionListener(l);
-    } else if (isInstalled())
-    {
-      getInstalledPanel().addButtonActionListener(l);
-    } else
-    {
-      getButtonsPanel().addButtonActionListener(l);
-    }
+    getButtonsPanel().addButtonActionListener(l);
+    getInstalledPanel().addButtonActionListener(l);
+    getButtonsPanel().addButtonActionListener(l);
+    getCurrentStepPanel().addButtonActionListener(l);
+
     buttonListeners.add(l);
   }
 
@@ -402,7 +437,7 @@
     if (isUninstall())
     {
       getButtonsPanel().removeButtonActionListener(l);
-    } else if (isInstalled())
+    } else if (isInstalled() && !forceToDisplaySetup)
     {
       getInstalledPanel().removeButtonActionListener(l);
     } else
@@ -519,7 +554,7 @@
                 getButtonsPanel());
       }
       p = framePanel;
-    } else if (isInstalled())
+    } else if (isInstalled() && !forceToDisplaySetup)
     {
       p = getInstalledPanel();
     } else
@@ -598,11 +633,14 @@
     if (isUninstall())
     {
       button = getButtonsPanel().getButton(buttonName);
-    } else if (isInstalled())
+    } else if (isInstalled() && !forceToDisplaySetup)
     {
       if (buttonName == ButtonName.QUIT)
       {
         button = getInstalledPanel().getQuitButton();
+      } else if (buttonName == ButtonName.CONTINUE_INSTALL)
+      {
+        button = getInstalledPanel().getContinueInstallButton();
       } else
       {
         throw new IllegalStateException("Invalid button name " + buttonName
@@ -686,8 +724,7 @@
   {
     if (installedPanel == null)
     {
-      installedPanel =
-          new QuickSetupErrorPanel(installStatus.getInstallationMsg());
+      installedPanel = new QuickSetupErrorPanel(installStatus);
     }
     return installedPanel;
   }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
index 03a8f8a..a1b8956 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
@@ -39,6 +39,7 @@
 import javax.swing.text.JTextComponent;
 
 import org.opends.quicksetup.ButtonName;
+import org.opends.quicksetup.CurrentInstallStatus;
 import org.opends.quicksetup.event.ButtonActionListener;
 import org.opends.quicksetup.event.ButtonEvent;
 
@@ -56,13 +57,14 @@
       new HashSet<ButtonActionListener>();
 
   private JButton quitButton;
+  private JButton continueButton;
 
   /**
    * Constructor of the QuickSetupErrorPanel.
    *
-   * @param htmlMsg the error message to be displayed.
+   * @param installStatus the current install status.
    */
-  public QuickSetupErrorPanel(String htmlMsg)
+  public QuickSetupErrorPanel(CurrentInstallStatus installStatus)
   {
     JPanel p1 = new JPanel(new GridBagLayout());
     p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
@@ -78,8 +80,10 @@
     gbc.fill = GridBagConstraints.BOTH;
     gbc.insets.left = 0;
     JTextComponent tf =
-        UIFactory.makeHtmlPane(htmlMsg, UIFactory.INSTRUCTIONS_FONT);
+        UIFactory.makeHtmlPane(installStatus.getInstallationMsg(),
+            UIFactory.INSTRUCTIONS_FONT);
     tf.setOpaque(false);
+    tf.setEditable(false);
     p1.add(tf, gbc);
 
     gbc.weighty = 1.0;
@@ -91,29 +95,53 @@
     gbc.fill = GridBagConstraints.HORIZONTAL;
     gbc.weightx = 1.0;
     gbc.insets = UIFactory.getEmptyInsets();
-    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.gridwidth = 3;
     p2.add(Box.createHorizontalGlue(), gbc);
     quitButton =
         UIFactory.makeJButton(getMsg("quit-button-label"),
             getMsg("quit-button-install-tooltip"));
 
-    final ButtonName fButtonName = ButtonName.QUIT;
+    final ButtonName fQuitButtonName = ButtonName.QUIT;
 
-    ActionListener actionListener = new ActionListener()
+    ActionListener quitListener = new ActionListener()
     {
       public void actionPerformed(ActionEvent ev)
       {
-        ButtonEvent be = new ButtonEvent(ev.getSource(), fButtonName);
+        ButtonEvent be = new ButtonEvent(ev.getSource(), fQuitButtonName);
         for (ButtonActionListener li : buttonListeners)
         {
           li.buttonActionPerformed(be);
         }
       }
     };
-    quitButton.addActionListener(actionListener);
+    quitButton.addActionListener(quitListener);
+
+    continueButton =
+      UIFactory.makeJButton(getMsg("continue-button-label"),
+          getMsg("continue-button-install-tooltip"));
+    final ButtonName fContinueButtonName = ButtonName.CONTINUE_INSTALL;
+
+    ActionListener continueListener = new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        ButtonEvent be = new ButtonEvent(ev.getSource(), fContinueButtonName);
+        for (ButtonActionListener li : buttonListeners)
+        {
+          li.buttonActionPerformed(be);
+        }
+      }
+    };
+    continueButton.addActionListener(continueListener);
 
     gbc.fill = GridBagConstraints.NONE;
     gbc.weightx = 0.0;
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    p2.add(continueButton, gbc);
+    continueButton.setVisible(installStatus.canOverwriteCurrentInstall());
+
+    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
     gbc.gridwidth = GridBagConstraints.REMAINDER;
     p2.add(quitButton, gbc);
 
@@ -158,4 +186,13 @@
   {
     return quitButton;
   }
+
+  /**
+   * Returns the continue install button.
+   * @return the continue install button.
+   */
+  public JButton getContinueInstallButton()
+  {
+    return continueButton;
+  }
 }
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
index c247493..c33e227 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
@@ -32,6 +32,7 @@
 import java.awt.GridBagLayout;
 
 import java.util.HashMap;
+import java.util.HashSet;
 
 import javax.swing.Box;
 import javax.swing.JEditorPane;
@@ -41,6 +42,8 @@
 import javax.swing.event.HyperlinkListener;
 import javax.swing.text.JTextComponent;
 
+import org.opends.quicksetup.event.ButtonActionListener;
+import org.opends.quicksetup.event.ButtonEvent;
 import org.opends.quicksetup.installer.FieldName;
 import org.opends.quicksetup.installer.InstallProgressDescriptor;
 import org.opends.quicksetup.installer.LabelFieldDescriptor;
@@ -63,6 +66,9 @@
 {
   private Component inputPanel;
 
+  private HashSet<ButtonActionListener> buttonListeners =
+    new HashSet<ButtonActionListener>();
+
   private ProgressMessageFormatter formatter;
 
   /* We can use a HashMap (not multi-thread safe) because all
@@ -190,6 +196,37 @@
     return height;
   }
 
+
+  /**
+   * 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);
+  }
+
+  /**
+   * Notifies the button action listeners that an event occurred.
+   * @param ev the button event to be notified.
+   */
+  protected void notifyButtonListeners(ButtonEvent ev)
+  {
+    for (ButtonActionListener l : buttonListeners)
+    {
+      l.buttonActionPerformed(ev);
+    }
+  }
   /**
    * Creates the layout of the panel.
    *
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java b/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
index f31edcc..c2d3f4d3 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
@@ -77,6 +77,11 @@
   public static final int HORIZONTAL_INSET_BETWEEN_BUTTONS = 5;
 
   /**
+   * Specifies the horizontal inset for the control panel sub section.
+   */
+  public static final int HORIZONTAL_INSET_CONTROL_PANEL_SUBSECTION = 20;
+
+  /**
    * Specifies the top inset for the steps.
    */
   public static final int TOP_INSET_STEP = 15;
@@ -142,6 +147,11 @@
   public static final int TOP_INSET_BROWSE = 5;
 
   /**
+   * Specifies the top inset for the control panel sub section.
+   */
+  public static final int TOP_INSET_CONTROL_PANEL_SUBSECTION = 30;
+
+  /**
    * Specifies the right inset for background image.
    */
   public static final int RIGHT_INSET_BACKGROUND = 20;
@@ -293,10 +303,15 @@
   public static final Color PASSWORD_FIELD_COLOR = Color.BLACK;
 
   /**
+   * Specifies the panel border color.
+   */
+  public static final Color PANEL_BORDER_COLOR = new Color(204, 204, 204);
+
+  /**
    * 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));
+    BorderFactory.createMatteBorder(0, 2, 2, 0, PANEL_BORDER_COLOR);
 
   /**
    * Specifies the text area border.
@@ -308,7 +323,7 @@
    * Specifies the dialog border.
    */
   public static final Border DIALOG_PANEL_BORDER =
-    BorderFactory.createMatteBorder(0, 0, 2, 0, new Color(204, 204, 204));
+    BorderFactory.createMatteBorder(0, 0, 2, 0, PANEL_BORDER_COLOR);
 
   /**
    * Specifies the font for the step which is not the current one in the steps
@@ -498,18 +513,42 @@
      */
     WARNING,
     /**
-     * The error icon.
-     */
-    ERROR,
-    /**
      * The warning large icon.
      */
     WARNING_LARGE,
     /**
+     * The error icon.
+     */
+    ERROR,
+    /**
+     * The error large icon.
+     */
+    ERROR_LARGE,
+    /**
      * The information icon.
      */
     INFORMATION,
     /**
+     * The information large icon.
+     */
+    INFORMATION_LARGE,
+    /**
+     * Icon of OpenDS.
+     */
+    OPENDS_SMALL,
+    /**
+     * Icon to create subsection title in Status Panel.
+     */
+    SUBSECTION_LEFT,
+    /**
+     * Icon to create subsection title in Status Panel.
+     */
+    SUBSECTION_RIGHT,
+    /**
+     * Question icon.
+     */
+    HELP_SMALL,
+    /**
      * No icon.
      */
     NO_ICON
@@ -1194,12 +1233,36 @@
       key = "information-icon";
       break;
 
+    case INFORMATION_LARGE:
+      key = "information-large-icon";
+      break;
+
+    case OPENDS_SMALL:
+      key = "opends-small-icon";
+      break;
+
+    case SUBSECTION_LEFT:
+      key = "subsection-left-icon";
+      break;
+
+    case SUBSECTION_RIGHT:
+      key = "subsection-right-icon";
+      break;
+
+    case HELP_SMALL:
+      key = "help-small-icon";
+      break;
+
     case ERROR:
       key = "error-icon";
       break;
 
+    case ERROR_LARGE:
+      key = "error-large-icon";
+      break;
+
     default:
-      throw new IllegalArgumentException("Unknow iconName: " + iconType);
+      throw new IllegalArgumentException("Unknown iconName: " + iconType);
     }
     return getParentPackagePath() + "/" + getMsg(key);
   }
@@ -1235,19 +1298,43 @@
       break;
 
     case WARNING:
-      description = "warning-icon-description";
+      description = getMsg("warning-icon-description");
       break;
 
     case WARNING_LARGE:
-      description = "warning-icon-description";
+      description = getMsg("warning-icon-description");
       break;
 
     case ERROR:
-      description = "error-icon-description";
+      description = getMsg("error-icon-description");
+      break;
+
+    case ERROR_LARGE:
+      description = getMsg("error-icon-description");
       break;
 
     case INFORMATION:
-      description = "information-icon-description";
+      description = getMsg("information-icon-description");
+      break;
+
+    case INFORMATION_LARGE:
+      description = getMsg("information-icon-description");
+      break;
+
+    case OPENDS_SMALL:
+      description = getMsg("opends-small-icon-description");
+      break;
+
+    case SUBSECTION_LEFT:
+      description = getMsg("subsection-left-icon-description");
+      break;
+
+    case SUBSECTION_RIGHT:
+      description = getMsg("subsection-right-icon-description");
+      break;
+
+    case HELP_SMALL:
+      description = getMsg("help-small-icon-description");
       break;
 
     case NO_ICON:
@@ -1255,8 +1342,9 @@
       break;
 
     default:
-      throw new IllegalArgumentException("Unknow iconName: " + iconType);
+      throw new IllegalArgumentException("Unknown iconName: " + iconType);
     }
+
     return description;
   }
 
@@ -1291,28 +1379,52 @@
       break;
 
     case WARNING:
-      tooltip = "warning-icon-tooltip";
+      tooltip = getMsg("warning-icon-tooltip");
       break;
 
     case WARNING_LARGE:
-      tooltip = "warning-icon-tooltip";
+      tooltip = getMsg("warning-icon-tooltip");
       break;
 
     case ERROR:
-      tooltip = "error-icon-tooltip";
+      tooltip = getMsg("error-icon-tooltip");
+      break;
+
+    case ERROR_LARGE:
+      tooltip = getMsg("error-icon-tooltip");
       break;
 
     case INFORMATION:
-      tooltip = "information-icon-tooltip";
+      tooltip = getMsg("information-icon-tooltip");
       break;
 
+    case INFORMATION_LARGE:
+      tooltip = getMsg("information-icon-tooltip");
+      break;
+
+    case OPENDS_SMALL:
+      tooltip = null;
+      break;
+
+    case SUBSECTION_LEFT:
+      tooltip = null;
+      break;
+
+    case SUBSECTION_RIGHT:
+      tooltip = null;
+      break;
+
+    case HELP_SMALL:
+      tooltip = null;
+      break;
     case NO_ICON:
       tooltip = null;
       break;
 
     default:
-      throw new IllegalArgumentException("Unknow iconName: " + iconType);
+      throw new IllegalArgumentException("Unknown iconName: " + iconType);
     }
+
     return tooltip;
   }
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java b/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java
index 1f8a2da..e686737 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java
@@ -136,6 +136,7 @@
         UIFactory.makeHtmlPane(msg,
             UIFactory.BROWSER_ERROR_DIALOG_FONT);
     tf.setOpaque(false);
+    tf.setEditable(false);
     p1.add(tf, gbc);
 
     gbc.weightx = 0.0;
diff --git a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java
index d83ae91..ba51251 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java
@@ -79,8 +79,6 @@
   static int BUG = 5;
 
   private static String LINE_SEPARATOR = System.getProperty("line.separator");
-  static int MAX_LINE_WIDTH = 80;
-
 
   private String[] args;
 
@@ -126,7 +124,7 @@
               {
                 System.out.print(
                     org.opends.server.util.StaticUtils.wrapText(ev.getNewLogs(),
-                        MAX_LINE_WIDTH));
+                        Utils.getCommandLineMaxLineWidth()));
               }
             });
         uninstaller.start();
@@ -1092,13 +1090,13 @@
   private static String getMsg(String key)
   {
     return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key),
-        MAX_LINE_WIDTH);
+        Utils.getCommandLineMaxLineWidth());
   }
 
   private static String getMsg(String key, String[] args)
   {
     return org.opends.server.util.StaticUtils.wrapText(
-        getI18n().getMsg(key, args), MAX_LINE_WIDTH);
+        getI18n().getMsg(key, args), Utils.getCommandLineMaxLineWidth());
   }
 
   private static ResourceProvider getI18n()
diff --git a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java
index 73c2bac..b79185e 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java
@@ -210,13 +210,13 @@
   private static String getMsg(String key)
   {
     return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key),
-        UninstallCli.MAX_LINE_WIDTH);
+        Utils.getCommandLineMaxLineWidth());
   }
 
   private static String getMsg(String key, String[] args)
   {
     return org.opends.server.util.StaticUtils.wrapText(
-        getI18n().getMsg(key, args), UninstallCli.MAX_LINE_WIDTH);
+        getI18n().getMsg(key, args), Utils.getCommandLineMaxLineWidth());
   }
 
   private static ResourceProvider getI18n()
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java b/opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java
index 5f05d21..efdc480 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/HtmlProgressMessageFormatter.java
@@ -93,7 +93,7 @@
   public String getFormattedError(String text, boolean applyMargin)
   {
     String html =
-        UIFactory.getIconHtml(UIFactory.IconType.ERROR)
+        UIFactory.getIconHtml(UIFactory.IconType.ERROR_LARGE)
             + SPACE
             + SPACE
             + UIFactory.applyFontToHtml(getHtml(text),
@@ -120,7 +120,7 @@
   public String getFormattedWarning(String text, boolean applyMargin)
   {
     String html =
-        UIFactory.getIconHtml(UIFactory.IconType.WARNING)
+        UIFactory.getIconHtml(UIFactory.IconType.WARNING_LARGE)
             + SPACE
             + SPACE
             + UIFactory.applyFontToHtml(getHtml(text),
@@ -146,7 +146,7 @@
   {
     // Note: the text we get already is in HTML form
     String html =
-        UIFactory.getIconHtml(UIFactory.IconType.INFORMATION) + SPACE
+        UIFactory.getIconHtml(UIFactory.IconType.INFORMATION_LARGE) + SPACE
         + SPACE + UIFactory.applyFontToHtml(text, UIFactory.PROGRESS_FONT);
 
     String result = UIFactory.applySuccessfulBackgroundToHtml(html);
@@ -279,7 +279,7 @@
         closeDiv, false));
 
     String html =
-        UIFactory.getIconHtml(UIFactory.IconType.ERROR) + SPACE + SPACE
+        UIFactory.getIconHtml(UIFactory.IconType.ERROR_LARGE) + SPACE + SPACE
             + buf.toString();
 
     String result;
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
index b416de1..2d989e3 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -72,6 +72,8 @@
 {
   private static final int BUFFER_SIZE = 1024;
 
+  private static final int MAX_LINE_WIDTH = 80;
+
   private static final String[] OPEN_DS_JAR_RELATIVE_PATHS =
     { "lib/quicksetup.jar", "lib/OpenDS.jar", "lib/je.jar" };
 
@@ -950,6 +952,8 @@
    */
   public static String getInstallPathFromClasspath()
   {
+    String installPath;
+
     /* Get the install path from the Class Path */
     String sep = System.getProperty("path.separator");
     String[] classPaths = System.getProperty("java.class.path").split(sep);
@@ -969,7 +973,20 @@
     File f = new File(path).getAbsoluteFile();
     File binariesDir = f.getParentFile();
 
-    return binariesDir.getParent();
+    /*
+     * Do a best effort to avoid having a relative representation (for
+     * instance to avoid having ../../../).
+     */
+    try
+    {
+      installPath = binariesDir.getParentFile().getCanonicalPath();
+    }
+    catch (IOException ioe)
+    {
+      // Best effort
+      installPath = binariesDir.getParent();
+    }
+    return installPath;
   }
 
   /**
@@ -1310,4 +1327,15 @@
     }
     return (InitialLdapContext) pair[0];
   }
+
+  /**
+   * Returns the max size in character of a line to be displayed in the command
+   * line.
+   * @return the max size in character of a line to be displayed in the command
+   * line.
+   */
+  public static int getCommandLineMaxLineWidth()
+  {
+    return MAX_LINE_WIDTH;
+  }
 }
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ConfigFromFile.java b/opends/src/statuspanel/org/opends/statuspanel/ConfigFromFile.java
new file mode 100644
index 0000000..88f633c
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ConfigFromFile.java
@@ -0,0 +1,418 @@
+/*
+ * 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.statuspanel;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.util.LDIFException;
+import org.opends.server.util.LDIFReader;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.Entry;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.ObjectClass;
+import org.opends.statuspanel.i18n.ResourceProvider;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to retrieve configuration information directly from the
+ * config.ldif file.
+ *
+ */
+public class ConfigFromFile
+{
+  private final ObjectClass connectionHandlerOc =
+    DirectoryServer.getObjectClass("ds-cfg-connection-handler", true);
+  private final ObjectClass ldapConnectionHandlerOc =
+    DirectoryServer.getObjectClass("ds-cfg-ldap-connection-handler", true);
+  private final ObjectClass jmxConnectionHandlerOc =
+    DirectoryServer.getObjectClass("ds-cfg-jmx-connection-handler", true);
+  private final ObjectClass backendOc =
+    DirectoryServer.getObjectClass("ds-cfg-backend", true);
+  private final ObjectClass administrativeUserOc =
+    DirectoryServer.getObjectClass("ds-cfg-root-dn", true);
+
+  private HashSet<ListenerDescriptor> listeners =
+    new HashSet<ListenerDescriptor>();
+  private HashSet<DatabaseDescriptor> databases =
+    new HashSet<DatabaseDescriptor>();
+  private HashSet<String> administrativeUsers = new HashSet<String>();
+  private String errorMessage;
+
+
+  /**
+   * Default constructor.
+   *
+   */
+  public ConfigFromFile()
+  {
+  }
+
+  /**
+   * Reads the configuration from the config.ldif file.  When calling this
+   * method the thread is blocked until all the configuration is read.
+   *
+   */
+  public void readConfiguration()
+  {
+    errorMessage = null;
+    try
+    {
+      LDIFImportConfig c = new LDIFImportConfig(
+          Utils.getConfigFileFromClasspath());
+      LDIFReader reader = new LDIFReader(c);
+      for (Entry entry = reader.readEntry(false); entry != null;
+      entry = reader.readEntry(false))
+      {
+        updateConfig(entry);
+      }
+    }
+    catch (IOException ioe)
+    {
+      errorMessage = Utils.getThrowableMsg(getI18n(),
+          "error-reading-config-file", null, ioe);
+    }
+    catch (LDIFException le)
+    {
+      errorMessage = Utils.getThrowableMsg(getI18n(),
+          "error-reading-config-file", null, le);
+    }
+    catch (Throwable t)
+    {
+      // Bug
+      t.printStackTrace();
+      errorMessage = Utils.getThrowableMsg(getI18n(),
+          "error-reading-config-file", null, t);
+    }
+  }
+
+  /**
+   * Returns the Administrative User DNs found in the config.ldif.
+   * @return the Administrative User DNs found in the config.ldif.
+   */
+  public HashSet<String> getAdministrativeUsers()
+  {
+    return administrativeUsers;
+  }
+
+  /**
+   * Returns the database descriptors found in the config.ldif.
+   * @return the database descriptors found in the config.ldif.
+   */
+  public HashSet<DatabaseDescriptor> getDatabases()
+  {
+    return databases;
+  }
+
+  /**
+   * Returns the listener descriptors found in the config.ldif.
+   * @return the listeners descriptors found in the config.ldif.
+   */
+  public HashSet<ListenerDescriptor> getListeners()
+  {
+    return listeners;
+  }
+
+  /**
+   * Returns the error message that we got when retrieving the information
+   * from the config.ldif file.
+   * @return the error message that we got when retrieving the information
+   * from the config.ldif file.
+   */
+  public String getErrorMessage()
+  {
+    return errorMessage;
+  }
+
+  /**
+   * Returns the ldap URL that we can use to connect to the server based in
+   * what we found in the config.ldif file.
+   * @return the ldap URL that we can use to connect to the server based in
+   * what we found in the config.ldif file.
+   */
+  public String getLDAPURL()
+  {
+    String url = null;
+
+    for (ListenerDescriptor desc : getListeners())
+    {
+      if (desc.getState() == ListenerDescriptor.State.ENABLED)
+
+      {
+        int port = -1;
+        try
+        {
+          String addressPort = desc.getAddressPort();
+          int index = addressPort.indexOf(":");
+          if (index != -1)
+          {
+            port = Integer.parseInt(addressPort.substring(index+1));
+          }
+          else
+          {
+            port = Integer.parseInt(addressPort);
+          }
+        }
+        catch (Exception ex)
+        {
+          // Could not get the port
+        }
+
+        if (port != -1)
+        {
+          if (desc.getProtocol() == ListenerDescriptor.Protocol.LDAP)
+          {
+            url = "ldap://localhost:"+port;
+            /* We prefer to test using the LDAP port: do not continue
+             * searching */
+            break;
+          }
+          else if (desc.getProtocol() == ListenerDescriptor.Protocol.LDAPS)
+          {
+            url = "ldaps://localhost:"+port;
+          }
+        }
+      }
+    }
+    return url;
+  }
+
+  /**
+   * An convenience method to know if the provided ID corresponds to a
+   * configuration backend or not.
+   * @param id the backend ID to analyze
+   * @return <CODE>true</CODE> if the the id corresponds to a configuration
+   * backend and <CODE>false</CODE> otherwise.
+   */
+  static boolean isConfigBackend(String id)
+  {
+    return "tasks".equalsIgnoreCase(id) ||
+    "schema".equalsIgnoreCase(id) ||
+    "config".equalsIgnoreCase(id) ||
+    "monitor".equalsIgnoreCase(id) ||
+    "backup".equalsIgnoreCase(id);
+  }
+
+
+  /**
+   * Updates the configuration data we expose to the user with the provided
+   * entry object.
+   * @param entry the entry to analyze.
+   */
+  private void updateConfig(Entry entry)
+  {
+
+   if (entry.hasObjectClass(connectionHandlerOc))
+   {
+     updateConfigWithConnectionHandler(entry);
+   }
+   else if (entry.hasObjectClass(backendOc))
+   {
+     updateConfigWithBackend(entry);
+   }
+   else if (entry.hasObjectClass(administrativeUserOc))
+   {
+     updateConfigWithAdministrativeUser(entry);
+   }
+  }
+
+  /**
+   * Updates the listener configuration data we expose to the user with the
+   * provided entry object.
+   * @param entry the entry to analyze.
+   */
+  private void updateConfigWithConnectionHandler(Entry entry)
+  {
+    String address = getFirstValue(entry, "ds-cfg-listen-address");
+    String port = getFirstValue(entry, "ds-cfg-listen-port");
+    String addressPort;
+
+    boolean isSecure = "true".equalsIgnoreCase(
+        getFirstValue(entry, "ds-cfg-use-ssl"));
+
+    ListenerDescriptor.Protocol protocol;
+    String protocolDescription;
+
+    ListenerDescriptor.State state;
+    if (entry.hasObjectClass(ldapConnectionHandlerOc))
+    {
+      addressPort = address+":"+port;
+      if (isSecure)
+      {
+        protocolDescription = getMsg("ldaps-protocol-label");
+        protocol = ListenerDescriptor.Protocol.LDAPS;
+      }
+      else
+      {
+        protocolDescription = getMsg("ldap-protocol-label");
+        protocol = ListenerDescriptor.Protocol.LDAP;
+      }
+      boolean enabled = "true".equalsIgnoreCase(
+          getFirstValue(entry, "ds-cfg-connection-handler-enabled"));
+      if (enabled)
+      {
+        state = ListenerDescriptor.State.ENABLED;
+      }
+      else
+      {
+        state = ListenerDescriptor.State.DISABLED;
+      }
+    }
+    else if (entry.hasObjectClass(jmxConnectionHandlerOc))
+    {
+      addressPort = "0.0.0.0:"+port;
+      if (isSecure)
+      {
+        protocolDescription = getMsg("jmx-secure-protocol-label");
+        protocol = ListenerDescriptor.Protocol.JMXS;
+      }
+      else
+      {
+        protocolDescription = getMsg("jmx-protocol-label");
+        protocol = ListenerDescriptor.Protocol.JMX;
+      }
+      boolean enabled = "true".equalsIgnoreCase(
+          getFirstValue(entry, "ds-cfg-connection-handler-enabled"));
+      if (enabled)
+      {
+        state = ListenerDescriptor.State.ENABLED;
+      }
+      else
+      {
+        state = ListenerDescriptor.State.DISABLED;
+      }
+    }
+    else
+    {
+      addressPort = getMsg("unknown-label");
+      protocolDescription = null;
+      protocol = ListenerDescriptor.Protocol.OTHER;
+      /* Try to figure a name from the cn */
+      String cn = getFirstValue(entry, "cn");
+      if (cn != null)
+      {
+        int index = cn.toLowerCase().indexOf("connection handler");
+        if (index > 0)
+        {
+          protocolDescription = cn.substring(0, index).trim();
+        }
+        else
+        {
+          protocolDescription = cn;
+        }
+      }
+      else
+      {
+        protocolDescription = getMsg("undefined-protocol-label");
+      }
+      state = ListenerDescriptor.State.UNKNOWN;
+    }
+    listeners.add(new ListenerDescriptor(addressPort, protocol,
+        protocolDescription, state));
+  }
+
+  /**
+   * Updates the database configuration data we expose to the user with the
+   * provided entry object.
+   * @param entry the entry to analyze.
+   */
+  private void updateConfigWithBackend(Entry entry)
+  {
+    String baseDn = getFirstValue(entry, "ds-cfg-backend-base-dn");
+    String id = getFirstValue(entry, "ds-cfg-backend-id");
+    int nEntries = -1; // Unknown
+
+    if (!isConfigBackend(id))
+    {
+      databases.add(new DatabaseDescriptor(id, baseDn, nEntries));
+    }
+  }
+
+  /**
+   * Updates the administrative user configuration data we expose to the user
+   * with the provided entry object.
+   * @param entry the entry to analyze.
+   */
+  private void updateConfigWithAdministrativeUser(Entry entry)
+  {
+    administrativeUsers.addAll(getValues(entry, "ds-cfg-alternate-bind-dn"));
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  /*
+   * The following 2 methods are convenience methods to retrieve String values
+   * from an entry.
+   */
+  private Set<String> getValues(Entry entry, String attrName)
+  {
+    Set<String> values = new HashSet<String>();
+    List<Attribute> attrs = entry.getAttribute(attrName);
+    if ((attrs != null) && attrs.size() > 0)
+    {
+      Attribute attr = attrs.iterator().next();
+      LinkedHashSet<AttributeValue> vs = attr.getValues();
+      if ((vs != null) && (vs.size() > 0))
+      {
+        for (AttributeValue v : vs)
+        {
+          values.add(v.getStringValue());
+        }
+      }
+    }
+    return values;
+  }
+
+  private String getFirstValue(Entry entry, String attrName)
+  {
+    String v = null;
+    Set<String> values = getValues(entry, attrName);
+    if (values.size() > 0)
+    {
+      v = values.iterator().next();
+    }
+    return v;
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java b/opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java
new file mode 100644
index 0000000..daa3ce1
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java
@@ -0,0 +1,702 @@
+/*
+ * 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.statuspanel;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapName;
+
+import org.opends.statuspanel.i18n.ResourceProvider;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to retrieve configuration and monitoring information using
+ * LDAP protocol.
+ *
+ */
+public class ConfigFromLDAP
+{
+  private HashSet<ListenerDescriptor> listeners =
+    new HashSet<ListenerDescriptor>();
+  private HashSet<DatabaseDescriptor> databases =
+    new HashSet<DatabaseDescriptor>();
+  private HashSet<String> administrativeUsers = new HashSet<String>();
+  private String errorMessage;
+
+  private String dn;
+  private String pwd;
+  private String ldapUrl;
+
+  private InitialLdapContext ctx;
+  private String javaVersion;
+  private int openConnections = -1;
+
+  /**
+   * Default constructor.
+   *
+   */
+  public ConfigFromLDAP()
+  {
+  }
+
+  /**
+   * Sets the connection information required to contact the server using LDAP.
+   * @param ldapUrl the LDAP URL of the server.
+   * @param dn the authentication Distinguished Name to bind.
+   * @param pwd the authentication password to bind.
+   */
+  public void setConnectionInfo(String ldapUrl, String dn, String pwd)
+  {
+    if (ldapUrl == null)
+    {
+      throw new IllegalArgumentException("ldapUrl cannot be null.");
+    }
+    if (dn == null)
+    {
+      throw new IllegalArgumentException("dn cannot be null.");
+    }
+    if (pwd == null)
+    {
+      throw new IllegalArgumentException("pwd cannot be null.");
+    }
+    if (!Utils.areDnsEqual(dn, this.dn) ||
+        !pwd.equals(this.pwd) ||
+        !ldapUrl.equals(this.ldapUrl))
+    {
+      if (ctx != null)
+      {
+        try
+        {
+          ctx.close();
+        }
+        catch (Throwable t)
+        {
+        }
+        ctx = null;
+      }
+    }
+
+    this.ldapUrl = ldapUrl;
+    this.dn = dn;
+    this.pwd = pwd;
+  }
+
+  /**
+   * Reads the configuration and monitoring information of the server using
+   * LDAP.
+   * When calling this method the thread is blocked until all the configuration
+   * is read.
+   *
+   * This method assumes that the setConnectionInfo has been called previously.
+   *
+   */
+  public void readConfiguration()
+  {
+    errorMessage = null;
+
+    listeners.clear();
+    databases.clear();
+    administrativeUsers.clear();
+    javaVersion = null;
+    openConnections = -1;
+
+    try
+    {
+      InitialLdapContext ctx = getDirContext();
+      updateAdministrativeUsers(ctx);
+      updateListeners(ctx);
+      updateDatabases(ctx);
+      javaVersion = getJavaVersion(ctx);
+      openConnections = getOpenConnections(ctx);
+    }
+    catch (NamingException ne)
+    {
+      String detail;
+      if (ne.getMessage() != null)
+      {
+        detail = ne.getMessage();
+      }
+      else
+      {
+        detail = ne.toString();
+      }
+      String[] arg = {detail};
+      errorMessage = getMsg("error-reading-config-ldap", arg);
+    }
+    catch (Throwable t)
+    {
+      // Bug
+      t.printStackTrace();
+      String[] arg = {t.toString()};
+      errorMessage = getMsg("error-reading-config-ldap", arg);
+    }
+  }
+
+
+  /**
+   * Returns the Administrative User DNs found using LDAP.
+   * @return the Administrative User DNs found using LDAP.
+   */
+  public HashSet<String> getAdministrativeUsers()
+  {
+    return administrativeUsers;
+  }
+
+  /**
+   * Returns the database descriptors found using LDAP.
+   * @return the database descriptors found using LDAP.
+   */
+  public HashSet<DatabaseDescriptor> getDatabases()
+  {
+    return databases;
+  }
+
+  /**
+   * Returns the listener descriptors found using LDAP.
+   * @return the listeners descriptors found using LDAP.
+   */
+  public HashSet<ListenerDescriptor> getListeners()
+  {
+    return listeners;
+  }
+
+  /**
+   * Return the java version we found using LDAP.
+   * @return the java version we found using LDAP.
+   */
+  public String getJavaVersion()
+  {
+    return javaVersion;
+  }
+
+  /**
+   * Return the number of open connections we found using LDAP.
+   * @return the number of open connections we found using LDAP.
+   */
+  public int getOpenConnections()
+  {
+    return openConnections;
+  }
+
+  /**
+   * Returns the error message that we got when retrieving the information
+   * using LDAP.
+   * @return the error message that we got when retrieving the information
+   * using LDAP.
+   */
+  public String getErrorMessage()
+  {
+    return errorMessage;
+  }
+
+  /**
+   * Returns the InitialLdapContext object to be used to retrieve configuration
+   * and monitoring information.
+   * @return the InitialLdapContext object to be used to retrieve configuration
+   * and monitoring information.
+   * @throws NamingException if we could not get an InitialLdapContext.
+   */
+  private InitialLdapContext getDirContext() throws NamingException
+  {
+    if (ctx != null)
+    {
+      try
+      {
+        pingDirContext(ctx);
+      }
+      catch (NamingException ne)
+      {
+        try
+        {
+          ctx.close();
+        }
+        catch(NamingException xx)
+        {
+        }
+        ctx = null;
+      }
+    }
+    if (ctx == null)
+    {
+      ctx = Utils.createLdapContext(ldapUrl, dn, pwd, 3000, null);
+    }
+    return ctx;
+  }
+
+  /**
+   * Ping the specified InitialLdapContext.
+   * This method sends a search request on the root entry of the DIT
+   * and forward the corresponding exception (if any).
+   * @param ctx the InitialLdapContext to be "pinged".
+   * @throws NamingException if the ping could not be performed.
+   */
+  private void pingDirContext(InitialLdapContext ctx) throws NamingException {
+    SearchControls sc = new SearchControls(
+        SearchControls.OBJECT_SCOPE,
+        0, // count limit
+        0, // time limit
+        new String[0], // No attributes
+        false, // Don't return bound object
+        false // Don't dereference link
+    );
+    ctx.search("", "objectclass=*", sc);
+  }
+
+  /**
+   * Updates the listener configuration data we expose to the user with the
+   * provided InitialLdapContext.
+   * @param ctx the InitialLdapContext to use to update the configuration.
+   * @throws NamingException if there was an error.
+   */
+  private void updateListeners(InitialLdapContext ctx) throws NamingException
+  {
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "ds-cfg-connection-handler-enabled",
+            "ds-cfg-listen-address",
+            "ds-cfg-listen-port",
+            "ds-cfg-use-ssl",
+            "objectclass"
+        });
+    String filter = "(objectclass=ds-cfg-connection-handler)";
+
+    LdapName jndiName = new LdapName("cn=config");
+    NamingEnumeration listeners = ctx.search(jndiName, filter, ctls);
+
+    while(listeners.hasMore())
+    {
+      SearchResult sr = (SearchResult)listeners.next();
+
+      updateConfigWithConnectionHandler(sr);
+
+    }
+  }
+
+  /**
+   * Updates the database configuration data we expose to the user with the
+   * provided InitialLdapContext.
+   * @param ctx the InitialLdapContext to use to update the configuration.
+   * @throws NamingException if there was an error.
+   */
+  private void updateDatabases(InitialLdapContext ctx) throws NamingException
+  {
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "ds-cfg-backend-base-dn",
+            "ds-cfg-backend-id"
+        });
+    String filter = "(objectclass=ds-cfg-backend)";
+
+    LdapName jndiName = new LdapName("cn=config");
+    NamingEnumeration databases = ctx.search(jndiName, filter, ctls);
+
+    while(databases.hasMore())
+    {
+      SearchResult sr = (SearchResult)databases.next();
+
+      updateConfigWithBackend(sr, ctx);
+
+    }
+  }
+
+  /**
+   * Updates the administrative user configuration we expose to the user with
+   * the provided InitialLdapContext.
+   * @param ctx the InitialLdapContext to use to update the configuration.
+   * @throws NamingException if there was an error.
+   */
+  private void updateAdministrativeUsers(InitialLdapContext ctx)
+  throws NamingException
+  {
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "ds-cfg-alternate-bind-dn"
+        });
+    String filter = "(objectclass=ds-cfg-root-dn)";
+
+    LdapName jndiName = new LdapName("cn=config");
+    NamingEnumeration users = ctx.search(jndiName, filter, ctls);
+
+    while(users.hasMore())
+    {
+      SearchResult sr = (SearchResult)users.next();
+
+      updateConfigWithAdministrativeUser(sr);
+
+    }
+  }
+
+  /**
+   * Returns the java version we find using the provided InitialLdapContext.
+   * @param ctx the InitialLdapContext to use to update the configuration.
+   * @return the java version we find using the provided InitialLdapContext.
+   * @throws NamingException if there was an error.
+   */
+  private String getJavaVersion(InitialLdapContext ctx)
+  throws NamingException
+  {
+    String v = null;
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "jvmVersion"
+        });
+    String filter = "(objectclass=*)";
+
+    LdapName jndiName = new LdapName("cn=System Information,cn=monitor");
+    NamingEnumeration listeners = ctx.search(jndiName, filter, ctls);
+
+    while(listeners.hasMore())
+    {
+      SearchResult sr = (SearchResult)listeners.next();
+
+      v = getFirstValue(sr, "jvmVersion");
+
+    }
+    return v;
+  }
+
+  /**
+   * Returns the number of open connections we find using the provided
+   * InitialLdapContext.
+   * @param ctx the InitialLdapContext to use to update the configuration.
+   * @return the number of open connections we find using the provided
+   * InitialLdapContext.
+   * @throws NamingException if there was an error.
+   */
+  private int getOpenConnections(InitialLdapContext ctx)
+  throws NamingException
+  {
+    int nConnections = -1;
+    String v = null;
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "currentConnections"
+        });
+    String filter = "(objectclass=*)";
+
+    LdapName jndiName = new LdapName("cn=monitor");
+    NamingEnumeration listeners = ctx.search(jndiName, filter, ctls);
+
+    while(listeners.hasMore())
+    {
+      SearchResult sr = (SearchResult)listeners.next();
+
+      v = getFirstValue(sr, "currentConnections");
+    }
+    try
+    {
+      nConnections = Integer.parseInt(v);
+    }
+    catch (Exception ex)
+    {
+
+    }
+    return nConnections;
+
+  }
+
+  /**
+   * Returns the number of entries in a given backend using the provided
+   * InitialLdapContext.
+   * @param ctx the InitialLdapContext to use to update the configuration.
+   * @param backenID the id of the backend.
+   * @return the number of entries in the backend.
+   * @throws NamingException if there was an error.
+   */
+  private int getEntryCount(InitialLdapContext ctx, String backendID)
+  throws NamingException
+  {
+    int nEntries = -1;
+    String v = null;
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "ds-backend-entry-count"
+        });
+    String filter = "(ds-backend-id="+backendID+")";
+
+    LdapName jndiName = new LdapName("cn=monitor");
+    NamingEnumeration listeners = ctx.search(jndiName, filter, ctls);
+
+    while(listeners.hasMore())
+    {
+      SearchResult sr = (SearchResult)listeners.next();
+
+      v = getFirstValue(sr, "ds-backend-entry-count");
+    }
+    try
+    {
+      nEntries = Integer.parseInt(v);
+    }
+    catch (Exception ex)
+    {
+
+    }
+    return nEntries;
+
+  }
+
+  /**
+   * Updates the listener configuration data we expose to the user with the
+   * provided SearchResult object.
+   * @param entry the entry to analyze.
+   * @throws NamingException if there was an error.
+   */
+  private void updateConfigWithConnectionHandler(SearchResult entry)
+  throws NamingException
+  {
+    String address = getFirstValue(entry, "ds-cfg-listen-address");
+    String port = getFirstValue(entry, "ds-cfg-listen-port");
+    String addressPort;
+
+    boolean isSecure = "true".equalsIgnoreCase(
+        getFirstValue(entry, "ds-cfg-use-ssl"));
+
+    ListenerDescriptor.Protocol protocol;
+    String protocolDescription;
+
+    ListenerDescriptor.State state;
+    if (hasObjectClass(entry, "ds-cfg-ldap-connection-handler"))
+    {
+      addressPort = address+":"+port;
+      if (isSecure)
+      {
+        protocolDescription = getMsg("ldaps-protocol-label");
+        protocol = ListenerDescriptor.Protocol.LDAPS;
+      }
+      else
+      {
+        protocolDescription = getMsg("ldap-protocol-label");
+        protocol = ListenerDescriptor.Protocol.LDAP;
+      }
+      boolean enabled = "true".equalsIgnoreCase(
+          getFirstValue(entry, "ds-cfg-connection-handler-enabled"));
+      if (enabled)
+      {
+        state = ListenerDescriptor.State.ENABLED;
+      }
+      else
+      {
+        state = ListenerDescriptor.State.DISABLED;
+      }
+    }
+    else if (hasObjectClass(entry, "ds-cfg-jmx-connection-handler"))
+    {
+      addressPort = "0.0.0.0:"+port;
+      if (isSecure)
+      {
+        protocolDescription = getMsg("jmx-secure-protocol-label");
+        protocol = ListenerDescriptor.Protocol.JMXS;
+      }
+      else
+      {
+        protocolDescription = getMsg("jmx-protocol-label");
+        protocol = ListenerDescriptor.Protocol.JMX;
+      }
+      boolean enabled = "true".equalsIgnoreCase(
+          getFirstValue(entry, "ds-cfg-connection-handler-enabled"));
+      if (enabled)
+      {
+        state = ListenerDescriptor.State.ENABLED;
+      }
+      else
+      {
+        state = ListenerDescriptor.State.DISABLED;
+      }
+    }
+    else
+    {
+      addressPort = getMsg("unknown-label");
+      protocolDescription = null;
+      protocol = ListenerDescriptor.Protocol.OTHER;
+      /* Try to figure a name from the cn */
+      String cn = getFirstValue(entry, "cn");
+      if (cn != null)
+      {
+        int index = cn.toLowerCase().indexOf("connection handler");
+        if (index > 0)
+        {
+          protocolDescription = cn.substring(0, index).trim();
+        }
+        else
+        {
+          protocolDescription = cn;
+        }
+      }
+      else
+      {
+        protocolDescription = getMsg("undefined-protocol-label");
+      }
+      state = ListenerDescriptor.State.UNKNOWN;
+    }
+    listeners.add(new ListenerDescriptor(addressPort, protocol,
+        protocolDescription, state));
+  }
+
+  /**
+   * Updates the database configuration data we expose to the user with the
+   * provided SearchResult object.
+   * @param entry the entry to analyze.
+   * @throws NamingException if there was an error.
+   */
+  private void updateConfigWithBackend(SearchResult entry,
+      InitialLdapContext ctx)
+  throws NamingException
+  {
+    String baseDn = getFirstValue(entry, "ds-cfg-backend-base-dn");
+    String id = getFirstValue(entry, "ds-cfg-backend-id");
+
+    if (!isConfigBackend(id))
+    {
+      int nEntries = getEntryCount(ctx, id);
+      databases.add(new DatabaseDescriptor(id, baseDn, nEntries));
+    }
+  }
+
+  /**
+   * Updates the administrative user configuration data we expose to the user
+   * with the provided SearchResult object.
+   * @param entry the entry to analyze.
+   * @throws NamingException if there was an error.
+   */
+  private void updateConfigWithAdministrativeUser(SearchResult entry)
+  throws NamingException
+  {
+    administrativeUsers.addAll(getValues(entry, "ds-cfg-alternate-bind-dn"));
+  }
+
+  /*
+   * The following 2 methods are convenience methods to retrieve String values
+   * from an entry.
+   */
+  private String getFirstValue(SearchResult entry, String attrName)
+  throws NamingException
+  {
+    String v = null;
+    Attributes attrs = entry.getAttributes();
+    if (attrs != null)
+    {
+      Attribute attr = attrs.get(attrName);
+      if ((attr != null) && (attr.size() > 0))
+      {
+        v = (String)attr.get();
+      }
+    }
+    return v;
+  }
+
+  private Set<String> getValues(SearchResult entry, String attrName)
+  throws NamingException
+  {
+    Set<String> values = new HashSet<String>();
+    Attributes attrs = entry.getAttributes();
+    if (attrs != null)
+    {
+      Attribute attr = attrs.get(attrName);
+      if (attr != null)
+      {
+        for (int i=0; i<attr.size(); i++)
+        {
+          values.add((String)attr.get(i));
+        }
+      }
+    }
+    return values;
+  }
+
+  /**
+   * Returns true if the SearchResult object is of a given objectclass.
+   * @param entry the SearchResult to analyze.
+   * @param ocName the objectclass.
+   * @return <CODE>true</CODE> if the SearchResult is of a the objectclass and
+   * <CODE>false</CODE> otherwise.
+   * @throws NamingException if there was an error.
+   */
+  private boolean hasObjectClass(SearchResult entry, String ocName)
+  throws NamingException
+  {
+    boolean hasObjectClass = false;
+    Attributes attrs = entry.getAttributes();
+    if (attrs != null)
+    {
+      Attribute attr = attrs.get("objectclass");
+      if (attr != null)
+      {
+        for (int i=0; i<attr.size() && !hasObjectClass; i++)
+        {
+          hasObjectClass = ocName.equalsIgnoreCase((String)attr.get(i));
+        }
+      }
+    }
+    return hasObjectClass;
+  }
+
+
+  private boolean isConfigBackend(String id)
+  {
+    return ConfigFromFile.isConfigBackend(id);
+  }
+
+  /**
+   * 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/statuspanel/org/opends/statuspanel/DatabaseDescriptor.java b/opends/src/statuspanel/org/opends/statuspanel/DatabaseDescriptor.java
new file mode 100644
index 0000000..dbf69a2
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/DatabaseDescriptor.java
@@ -0,0 +1,113 @@
+/*
+ * 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.statuspanel;
+
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to represent a Database and is aimed to be used by the
+ * classes in the DatabasesTableModel class.
+ */
+public class DatabaseDescriptor
+{
+  private String backendID;
+  private String baseDn;
+  private int entries;
+
+  /**
+   * Constructor for this class.
+   * @param backendID the backend ID of the Database.
+   * @param baseDn the base DN associated with the Database.
+   * @param entries the number of entries in the Database.
+   */
+  public DatabaseDescriptor(String backendID, String baseDn, int entries)
+  {
+    this.backendID = backendID;
+    this.baseDn = baseDn;
+    this.entries = entries;
+  }
+
+  /**
+   * Returns the ID of the Backend.
+   * @return the ID of the Backend.
+   */
+  public String getBackendID()
+  {
+    return backendID;
+  }
+
+  /**
+   * Return the base DN associated with the database.
+   * @return the base DN associated with the database.
+   */
+  public String getBaseDn()
+  {
+    return baseDn;
+  }
+
+  /**
+   * Return the number of entries in the database.
+   * -1 indicates that the number of entries could not be found.
+   * @return the number of entries in the database.
+   */
+  public int getEntries()
+  {
+    return entries;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean equals(Object v)
+  {
+    boolean equals = false;
+    if (this != v)
+    {
+      if (v instanceof DatabaseDescriptor)
+      {
+        DatabaseDescriptor desc = (DatabaseDescriptor)v;
+        equals = getBackendID().equals(desc.getBackendID()) &&
+        Utils.areDnsEqual(getBaseDn(), desc.getBaseDn()) &&
+        (getEntries() == desc.getEntries());
+      }
+    }
+    else
+    {
+      equals = true;
+    }
+    return equals;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int hashCode()
+  {
+    return (getBackendID() + getBaseDn() + getEntries()).hashCode();
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ListenerDescriptor.java b/opends/src/statuspanel/org/opends/statuspanel/ListenerDescriptor.java
new file mode 100644
index 0000000..1828b97
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ListenerDescriptor.java
@@ -0,0 +1,148 @@
+/*
+ * 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.statuspanel;
+
+/**
+ * This class is used to represent a Listener and is aimed to be used by the
+ * classes in the ListenersTableModel class.
+ */
+public class ListenerDescriptor
+{
+  /**
+   * Enumeration used to represent the state of the listener.
+   */
+  public enum State
+  {
+    /**
+     * The listener is enabled.
+     */
+    ENABLED,
+    /**
+     * The listener is disabled.
+     */
+    DISABLED,
+    /**
+     * The state of the listener is unknown.
+     */
+    UNKNOWN
+  };
+
+  /**
+   * Enumeration used to represent the Protocol of the listener.
+   *
+   */
+  public enum Protocol
+  {
+    /**
+     * LDAP protocol.
+     */
+    LDAP,
+    /**
+     * LDAP secure protocol.
+     */
+    LDAPS,
+    /**
+     * JMX protocol.
+     */
+    JMX,
+    /**
+     * JMX secure protocol.
+     */
+    JMXS,
+    /**
+     * Other protocol.
+     */
+    OTHER
+  }
+
+  private State state;
+  private String addressPort;
+  private Protocol protocol;
+  private String protocolDescription;
+
+  /**
+   * Constructor for thid class.
+   * @param addressPort the address port reprentation of the listener.
+   * @param protocol the protocol of the listener.
+   * @param protocolDescription the String used to describe the protocol.
+   * @param state the state of the listener.
+   */
+  public ListenerDescriptor(String addressPort, Protocol protocol,
+      String protocolDescription, State state)
+  {
+    this.addressPort = addressPort;
+    this.protocol = protocol;
+    this.protocolDescription = protocolDescription;
+    this.state = state;
+  }
+
+  /**
+   * Returns the address port representation of the listener.
+   * @return the address port representation of the listener.
+   */
+  public String getAddressPort()
+  {
+    return addressPort;
+  }
+
+  /**
+   * Returns the protocol of the listener.
+   * @return the protocol of the listener.
+   */
+  public Protocol getProtocol()
+  {
+    return protocol;
+  }
+
+  /**
+   * Returns the protocol description of the listener.
+   * @return the protocol description of the listener.
+   */
+  public String getProtocolDescription()
+  {
+    return protocolDescription;
+  }
+
+  /**
+   * Returns the state of the listener.
+   * @return the state of the listener.
+   */
+  public State getState()
+  {
+    return state;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int hashCode()
+  {
+    return (getAddressPort() + getProtocolDescription() +
+        getState()).hashCode();
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ServerStatusDescriptor.java b/opends/src/statuspanel/org/opends/statuspanel/ServerStatusDescriptor.java
new file mode 100644
index 0000000..7ca10f1
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ServerStatusDescriptor.java
@@ -0,0 +1,356 @@
+/*
+ * 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.statuspanel;
+
+import java.io.File;
+import java.util.Set;
+
+/**
+ * This is just a class used to provide a data model describing what the
+ * StatusPanelDialog will show to the user.
+ */
+public class ServerStatusDescriptor
+{
+  private ServerStatus status;
+  private int openConnections;
+  private Set<DatabaseDescriptor> databases;
+  private Set<ListenerDescriptor> listeners;
+  private Set<String> administrativeUsers;
+  private File installPath;
+  private String openDSVersion;
+  private String javaVersion;
+  private String errorMsg;
+  private boolean isAuthenticated;
+
+  /**
+   * Enumeration indicating the status of the server.
+   *
+   */
+  public enum ServerStatus
+  {
+    /**
+     * Server Started.
+     */
+    STARTED,
+    /**
+     * Server Stopped.
+     */
+    STOPPED,
+    /**
+     * Server Starting.
+     */
+    STARTING,
+    /**
+     * Server Stopping.
+     */
+    STOPPING,
+    /**
+     * Status Unknown.
+     */
+    UNKNOWN
+  }
+
+  /**
+   * Default constructor.
+   */
+  public ServerStatusDescriptor()
+  {
+  }
+
+  /**
+   * Return the administrative users.
+   * @return the administrative users.
+   */
+  public Set<String> getAdministrativeUsers()
+  {
+    return administrativeUsers;
+  }
+
+  /**
+   * Set the administrative users.
+   * @param administrativeUsers the administrative users to set
+   */
+  public void setAdministrativeUsers(Set<String> administrativeUsers)
+  {
+    this.administrativeUsers = administrativeUsers;
+  }
+
+  /**
+   * Return the install path where the server is installed.
+   * @return the install path where the server is installed.
+   */
+  public File getInstallPath()
+  {
+    return installPath;
+  }
+
+  /**
+   * Sets the install path where the server is installed.
+   * @param installPath the install path where the server is installed.
+   */
+  public void setInstallPath(File installPath)
+  {
+    this.installPath = installPath;
+  }
+
+  /**
+   * Return the java version used to run the server.
+   * @return the java version used to run the server.
+   */
+  public String getJavaVersion()
+  {
+    return javaVersion;
+  }
+
+  /**
+   * Set the java version used to run the server.
+   * @param javaVersion the java version used to run the server.
+   */
+  public void setJavaVersion(String javaVersion)
+  {
+    this.javaVersion = javaVersion;
+  }
+
+  /**
+   * Returns the number of open connection in the server.
+   * @return the number of open connection in the server.
+   */
+  public int getOpenConnections()
+  {
+    return openConnections;
+  }
+
+  /**
+   * Set the number of open connections.
+   * @param openConnections the number of open connections.
+   */
+  public void setOpenConnections(int openConnections)
+  {
+    this.openConnections = openConnections;
+  }
+
+  /**
+   * Returns the version of the server.
+   * @return the version of the server.
+   */
+  public String getOpenDSVersion()
+  {
+    return openDSVersion;
+  }
+
+  /**
+   * Sets the version of the server.
+   * @param openDSVersion the version of the server.
+   */
+  public void setOpenDSVersion(String openDSVersion)
+  {
+    this.openDSVersion = openDSVersion;
+  }
+
+  /**
+   * Returns the status of the server.
+   * @return the status of the server.
+   */
+  public ServerStatus getStatus()
+  {
+    return status;
+  }
+
+  /**
+   * Sets the status of the server.
+   * @param status the status of the server.
+   */
+  public void setStatus(ServerStatus status)
+  {
+    this.status = status;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean equals(Object o)
+  {
+    boolean equals = false;
+    if (this != o)
+    {
+      if (o instanceof ServerStatusDescriptor)
+      {
+        ServerStatusDescriptor desc = (ServerStatusDescriptor)o;
+        equals = desc.getStatus() == getStatus();
+
+        if (equals)
+        {
+          equals = desc.getOpenConnections() == getOpenConnections();
+        }
+
+        if (equals)
+        {
+          equals = desc.getInstallPath().equals(getInstallPath());
+        }
+
+        if (equals)
+        {
+          if (desc.getJavaVersion() == null)
+          {
+            equals = getJavaVersion() == null;
+          }
+          else
+          {
+            equals = desc.getJavaVersion().equals(getJavaVersion());
+          }
+        }
+
+        if (equals)
+        {
+          equals = desc.getOpenDSVersion().equals(getOpenDSVersion());
+        }
+
+        if (equals)
+        {
+          equals = desc.getAdministrativeUsers().equals(
+              getAdministrativeUsers());
+        }
+
+        if (equals)
+        {
+          equals = desc.getDatabases().equals(getDatabases());
+        }
+
+        if (equals)
+        {
+          if (desc.getErrorMessage() == null)
+          {
+            equals = getErrorMessage() == null;
+          }
+          else
+          {
+            equals = desc.getErrorMessage().equals(getErrorMessage());
+          }
+        }
+      }
+    }
+    else
+    {
+      equals = true;
+    }
+    return equals;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int hashCode()
+  {
+    return status.hashCode() + openConnections + databases.hashCode() +
+    listeners.hashCode() + administrativeUsers.hashCode() +
+    (String.valueOf(
+        installPath+openDSVersion+javaVersion+errorMsg+isAuthenticated)).
+        hashCode();
+  }
+
+  /**
+   * Returns the error message that we encountered generating this server
+   * status descriptor.
+   * @return the error message that we encountered generating this server
+   * status descriptor.
+   */
+  public String getErrorMessage()
+  {
+    return errorMsg;
+  }
+
+  /**
+   * Sets the error message that we encountered generating this server
+   * status descriptor.
+   * @param errorMsg the error message that we encountered generating this
+   * server status descriptor.
+   */
+  public void setErrorMessage(String errorMsg)
+  {
+    this.errorMsg = errorMsg;
+  }
+
+  /**
+   * Return whether we were authenticated when retrieving the information of
+   * this ServerStatusDescriptor.
+   * @return <CODE>true</CODE> if we were authenticated when retrieving the
+   * information of this ServerStatusDescriptor and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean isAuthenticated()
+  {
+    return isAuthenticated;
+  }
+
+  /**
+   * Sets whether we were authenticated when retrieving the information of
+   * this ServerStatusDescriptor.
+   * @param isAuthenticated whether we were authenticated when retrieving the
+   * information of this ServerStatusDescriptor.
+   */
+  public void setAuthenticated(boolean isAuthenticated)
+  {
+    this.isAuthenticated = isAuthenticated;
+  }
+
+  /**
+   * Returns the database descriptors of the server.
+   * @return the database descriptors of the server.
+   */
+  public Set<DatabaseDescriptor> getDatabases()
+  {
+    return databases;
+  }
+
+  /**
+   * Sets the database descriptors of the server.
+   * @param databases the database descriptors to set.
+   */
+  public void setDatabases(Set<DatabaseDescriptor> databases)
+  {
+    this.databases = databases;
+  }
+
+  /**
+   * Returns the listener descriptors of the server.
+   * @return the listener descriptors of the server.
+   */
+  public Set<ListenerDescriptor> getListeners()
+  {
+    return listeners;
+  }
+
+  /**
+   * Sets the listener descriptors of the server.
+   * @param listeners the listener descriptors to set.
+   */
+  public void setListeners(Set<ListenerDescriptor> listeners)
+  {
+    this.listeners = listeners;
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ServerStatusPooler.java b/opends/src/statuspanel/org/opends/statuspanel/ServerStatusPooler.java
new file mode 100644
index 0000000..526a22a
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ServerStatusPooler.java
@@ -0,0 +1,408 @@
+/*
+ * 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.statuspanel;
+
+import java.io.File;
+import java.util.HashSet;
+
+import org.opends.quicksetup.util.Utils;
+import org.opends.statuspanel.event.ServerStatusChangeEvent;
+import org.opends.statuspanel.event.ServerStatusChangeListener;
+import org.opends.statuspanel.i18n.ResourceProvider;
+
+
+/**
+ * This class just reads the status of the server periodically and generates
+ * ServerStatusChangeEvent when the status changes.  To receive this events
+ * other classes must register using the addServerStatusChangeListener method.
+ *
+ */
+public class ServerStatusPooler
+{
+  private String dn;
+  private String pwd;
+  private ServerStatusDescriptor lastDescriptor;
+  private boolean stopPooling;
+  private Thread t;
+  private HashSet<ServerStatusChangeListener> listeners =
+    new HashSet<ServerStatusChangeListener>();
+  private boolean starting;
+  private boolean stopping;
+  private ConfigFromFile offLineConf = new ConfigFromFile();
+  private ConfigFromLDAP onLineConf = new ConfigFromLDAP();
+  private String ldapUrl;
+  private int nTriesWithErrorOnline;
+
+  /* The pooling periods */
+  private static final int OFFLINE_POOLING_PERIOD = 3000;
+  private static final int ONLINE_POOLING_PERIOD = 5000;
+
+  /**
+   * Default constructor.
+   */
+  public ServerStatusPooler()
+  {
+    /* This is required to retrieve the ldap url to be used by the
+     * ConfigFromLDAP class.
+     */
+    offLineConf.readConfiguration();
+    ldapUrl = offLineConf.getLDAPURL();
+  }
+
+  /**
+   * Starts pooling the server status.  This method does not block the thread
+   * that called it.
+   *
+   */
+  public void startPooling()
+  {
+    stopPooling = false;
+    t = new Thread(new Runnable()
+    {
+      public void run()
+      {
+        try
+        {
+          nTriesWithErrorOnline = 0;
+          while (!stopPooling)
+          {
+            long t1 = System.currentTimeMillis();
+
+            ServerStatusDescriptor desc = generateDescriptor();
+            if (!desc.equals(lastDescriptor))
+            {
+              lastDescriptor = desc;
+              notifyListeners(lastDescriptor);
+            }
+            long t2 = System.currentTimeMillis();
+
+            long poolingPeriod =
+              desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED?
+                  ONLINE_POOLING_PERIOD : OFFLINE_POOLING_PERIOD;
+
+            if (t2 - t1 < poolingPeriod)
+            {
+              try
+              {
+                Thread.sleep(poolingPeriod - (t2 - t1));
+              }
+              catch (Exception ex)
+              {
+                if (!stopPooling)
+                {
+                  /* Should not happen. */
+                  throw ex;
+                }
+              }
+            }
+          }
+        }
+        catch (Throwable t)
+        {
+          if (!stopPooling)
+          {
+            /* This is a bug. */
+            t.printStackTrace();
+          }
+        }
+      }
+    });
+    t.start();
+  }
+
+  /**
+   * Returns the last server descriptor found.
+   * @return the last server descriptor found.
+   */
+  public ServerStatusDescriptor getLastDescriptor()
+  {
+    return lastDescriptor;
+  }
+
+  /**
+   * This method is called to notify that the server is being started.
+   */
+  public void beginServerStart()
+  {
+    starting = true;
+  }
+
+  /**
+   * This method is called to notify that the server start operation ended.
+   */
+  public void endServerStart()
+  {
+    starting = false;
+  }
+
+  /**
+   * This method is called to notify that the server is being stopped.
+   */
+  public void beginServerStop()
+  {
+    stopping = true;
+  }
+
+  /**
+   * This method is called to notify that the server stop operation ended.
+   */
+  public void endServerStop()
+  {
+    stopping = false;
+  }
+
+  /**
+   * Adds a ServerStatusChangeListener that will be notified of updates in
+   * the server status.
+   * @param l the ServerStatusChangeListener to be added.
+   */
+  public void addServerStatusChangeListener(ServerStatusChangeListener l)
+  {
+    listeners.add(l);
+  }
+
+  /**
+   * Removes a ServerStatusChangeListener.
+   * @param l the ServerStatusChangeListener to be removed.
+   */
+  public void removeServerStatusChangeListener(ServerStatusChangeListener l)
+  {
+    listeners.remove(l);
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if this class already has authentication
+   * information (setAuthentication method has been called with non-null
+   * parameters).
+   * @return <CODE>true</CODE> if this class already has authentication
+   * information and <CODE>false</CODE> otherwise.
+   */
+  public boolean isAuthenticated()
+  {
+    return (dn != null) && (pwd != null);
+  }
+
+  /**
+   * Sets the authentication information to be used by this class to retrieve
+   * information using LDAP.
+   * @param dn the authentication Distinguished Name to bind.
+   * @param pwd the authentication password to bind.
+   */
+  public void setAuthentication(String dn, String pwd)
+  {
+    this.dn = dn;
+    this.pwd = pwd;
+    if ((ldapUrl != null) && (t != null) && t.isAlive() && !stopPooling)
+    {
+      /* If we are pooling, stop the pooling update the connection information
+       * and restart the pooling.  Set the stopPooling boolean to true to
+       * indicate to the code in the Thread 't' to ignore the
+       * InterruptedExceptions.
+       *
+       */
+      stopPooling = true;
+      t.interrupt();
+      try
+      {
+        t.join(5000);
+      }
+      catch (Throwable t)
+      {
+        /* This should not happen: this thread should not be interrupted. */
+        t.printStackTrace();
+      }
+      t = null;
+      onLineConf.setConnectionInfo(ldapUrl, dn, pwd);
+      startPooling();
+    }
+    else if (ldapUrl != null)
+    {
+      onLineConf.setConnectionInfo(ldapUrl, dn, pwd);
+    }
+  }
+
+  /**
+   * This method notifies the ServerStatusChangeListeners that there was an
+   * update in the installation progress.
+   * @param desc the ServerStatusDescriptor.
+   */
+  private void notifyListeners(ServerStatusDescriptor desc)
+  {
+    ServerStatusChangeEvent ev = new ServerStatusChangeEvent(desc);
+    for (ServerStatusChangeListener l : listeners)
+    {
+      l.statusChanged(ev);
+    }
+  }
+
+  /**
+   * Retrieves information of the server.  The method used will depend on the
+   * status of the server (started or not).
+   * @return a ServerStatusDescriptor object describing the status of the
+   * server.
+   */
+  private ServerStatusDescriptor generateDescriptor()
+  {
+    ServerStatusDescriptor desc = new ServerStatusDescriptor();
+
+    desc.setAuthenticated((dn != null) && (pwd != null));
+
+    if (starting)
+    {
+      desc.setStatus(ServerStatusDescriptor.ServerStatus.STARTING);
+    }
+    else if (stopping)
+    {
+      desc.setStatus(ServerStatusDescriptor.ServerStatus.STOPPING);
+    }
+    else if (Utils.isServerRunning(Utils.getInstallPathFromClasspath()))
+    {
+      desc.setStatus(ServerStatusDescriptor.ServerStatus.STARTED);
+    }
+    else
+    {
+      desc.setStatus(ServerStatusDescriptor.ServerStatus.STOPPED);
+    }
+
+    desc.setInstallPath(new File(Utils.getInstallPathFromClasspath()));
+
+    desc.setOpenDSVersion(
+        org.opends.server.util.DynamicConstants.FULL_VERSION_STRING);
+
+    if (desc.getStatus() != ServerStatusDescriptor.ServerStatus.STARTED)
+    {
+      updateDescriptorWithOffLineInfo(desc);
+    }
+    else
+    {
+      try
+      {
+        if ((dn == null) || (pwd == null))
+        {
+          desc.setAdministrativeUsers(new HashSet<String>());
+          desc.setDatabases(new HashSet<DatabaseDescriptor>());
+          desc.setListeners(new HashSet<ListenerDescriptor>());
+          desc.setOpenConnections(-1);
+        }
+        else if (ldapUrl != null)
+        {
+          updateDescriptorWithOnLineInfo(desc);
+        }
+        else
+        {
+          /* We cannot retrieve an ldapurl from the config file.  Display
+           * what we got in the config file.
+           */
+          updateDescriptorWithOffLineInfo(desc);
+          if (desc.getErrorMessage() != null)
+          {
+            desc.setErrorMessage(getMsg("could-not-find-valid-ldapurl"));
+          }
+        }
+      }
+      catch (Exception ex)
+      {
+        // Bug
+        ex.printStackTrace();
+      }
+    }
+
+    return desc;
+  }
+
+  /**
+   * Updates the ServerStatusDescriptor object using the information in the
+   * config.ldif file (we use a ConfigFromFile object to do this).
+   * @param desc the ServerStatusDescriptor object to be updated.
+   */
+  private void updateDescriptorWithOffLineInfo(ServerStatusDescriptor desc)
+  {
+    /* Read the list of administrative users from CurrentInstallStatus
+     * (which reads directly config.ldif.  This is the best we can do today
+     * when the server is not started.
+     */
+    offLineConf.readConfiguration();
+    desc.setAdministrativeUsers(offLineConf.getAdministrativeUsers());
+    desc.setDatabases(offLineConf.getDatabases());
+    desc.setListeners(offLineConf.getListeners());
+    desc.setErrorMessage(offLineConf.getErrorMessage());
+    ldapUrl = offLineConf.getLDAPURL();
+    if ((ldapUrl != null) && (dn != null) && (pwd != null))
+    {
+      onLineConf.setConnectionInfo(ldapUrl, dn, pwd);
+    }
+    desc.setOpenConnections(-1);
+    desc.setJavaVersion(null);
+  }
+
+  /**
+   * Updates the ServerStatusDescriptor object using the LDAP protocol (we use a
+   * ConfigFromLDAP object to do this).
+   * @param desc the ServerStatusDescriptor object to be updated.
+   */
+  private void updateDescriptorWithOnLineInfo(ServerStatusDescriptor desc)
+  {
+    onLineConf.readConfiguration();
+    desc.setAdministrativeUsers(onLineConf.getAdministrativeUsers());
+    desc.setDatabases(onLineConf.getDatabases());
+    desc.setListeners(onLineConf.getListeners());
+    desc.setErrorMessage(onLineConf.getErrorMessage());
+    desc.setJavaVersion(onLineConf.getJavaVersion());
+    desc.setOpenConnections(onLineConf.getOpenConnections());
+
+    if (desc.getErrorMessage() != null)
+    {
+      nTriesWithErrorOnline++;
+      /* Something happened: if this is the 5th try with the current URL
+       * just try to check if the information has changed in the config.ldif
+       * file.
+       */
+      if (nTriesWithErrorOnline >= 5)
+      {
+        offLineConf.readConfiguration();
+        ldapUrl = offLineConf.getLDAPURL();
+        onLineConf.setConnectionInfo(ldapUrl, dn, pwd);
+        nTriesWithErrorOnline = 0;
+      }
+    }
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/SplashScreen.java b/opends/src/statuspanel/org/opends/statuspanel/SplashScreen.java
new file mode 100644
index 0000000..8a176b3
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/SplashScreen.java
@@ -0,0 +1,111 @@
+/*
+ * 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.statuspanel;
+
+import javax.swing.SwingUtilities;
+
+/**
+ * This class will display a splash screen and in the background it will
+ * create The StatusPanel object.
+ *
+ * This class just extends the org.opends.quicksetup.SplashScreen by
+ * overwritting the construct and display methods.
+ */
+public class SplashScreen extends org.opends.quicksetup.SplashScreen
+{
+  private static final long serialVersionUID = 4472839063380302713L;
+
+  private static Object statusPanel;
+
+  private static Class<?> statusPanelClass;
+
+  /**
+   * 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)
+  {
+    SplashScreen screen = new SplashScreen();
+    screen.display(args);
+  }
+
+  /**
+   * This methods constructs the StatusPanel object.
+   * This method assumes that is being called outside the event thread.
+   * @param args arguments to be passed to the method StatusPanel.initialize.
+   */
+  protected void constructApplication(String[] args)
+  {
+    try
+    {
+      statusPanelClass = Class.forName(
+          "org.opends.statuspanel.StatusPanelController");
+      statusPanel = statusPanelClass.newInstance();
+      statusPanelClass.getMethod("initialize", new Class[]
+        { String[].class }).invoke(statusPanel, new Object[]
+        { args });
+    } catch (Exception e)
+    {
+      InternalError error =
+          new InternalError("Failed to invoke initialize method");
+      error.initCause(e);
+      throw error;
+    }
+  }
+
+  /**
+   * This method displays the StatusPanel dialog.
+   * @see StatusPanelController.display.
+   * This method assumes that is being called outside the event thread.
+   */
+  protected void displayApplication()
+  {
+    try
+    {
+      SwingUtilities.invokeAndWait(new Runnable()
+      {
+        public void run()
+        {
+          try
+          {
+            statusPanelClass.getMethod("display").invoke(statusPanel);
+          } catch (Exception e)
+          {
+            InternalError error =
+                new InternalError("Failed to invoke display method");
+            error.initCause(e);
+            throw error;
+          }
+        }
+      });
+    } catch (Exception ex)
+    {
+    }
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/StatusCli.java b/opends/src/statuspanel/org/opends/statuspanel/StatusCli.java
new file mode 100644
index 0000000..c9ba20f
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/StatusCli.java
@@ -0,0 +1,943 @@
+/*
+ * 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.statuspanel;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.swing.table.TableModel;
+
+import org.opends.quicksetup.util.Utils;
+
+import org.opends.server.core.DirectoryServer;
+
+import org.opends.statuspanel.i18n.ResourceProvider;
+import org.opends.statuspanel.ui.DatabasesTableModel;
+import org.opends.statuspanel.ui.ListenersTableModel;
+
+/**
+ * The class used to provide some CLI interface to display status.
+ *
+ * This class basically is in charge of parsing the data provided by the user
+ * in the command line.
+ *
+ */
+class StatusCli
+{
+  private static String LINE_SEPARATOR = System.getProperty("line.separator");
+
+  private String[] args;
+
+  private boolean displayMustAuthenticateLegend;
+  private boolean displayMustStartLegend;
+
+  /**
+   * Return code: Uninstall successful.
+   */
+  static int SUCCESSFUL = 0;
+  /**
+   * Return code: User provided invalid data.
+   */
+  static int USER_DATA_ERROR = 1;
+  /**
+   * Return code: Bug.
+   */
+  static int BUG = 2;
+
+  private static String COMMAND_NAME_WINDOWS = "status.bat";
+
+  private static String COMMAND_NAME_UNIX = "status";
+
+  /**
+   * The main method which is called by the status command lines.
+   * @param args the arguments passed by the status command lines.
+   */
+  public static void main(String[] args)
+  {
+    StatusCli cli = new StatusCli(args);
+    System.exit(cli.run());
+  }
+
+  /**
+   * The constructor for this object.
+   * @param args the arguments of the status command line.
+   */
+  StatusCli(String[] args)
+  {
+    /* Ignore the first 4 arguments */
+    if ((args != null) && (args.length >= 4))
+    {
+      this.args = new String[args.length - 4];
+      for (int i=0; i<this.args.length; i++)
+      {
+        this.args[i] = args[i+4];
+      }
+    }
+    else
+    {
+      this.args = args;
+    }
+    DirectoryServer.bootstrapClient();
+  }
+
+  /**
+   * Parses the user data and displays usage if something is missing and the
+   * status otherwise.
+   *
+   * @return the return code (SUCCESSFUL, USER_DATA_ERROR or BUG.
+   */
+  int run()
+  {
+    int returnValue = SUCCESSFUL;
+
+    ArrayList<String> errors = new ArrayList<String>();
+
+    boolean printUsage = false;
+
+    String directoryManagerPwd = null;
+    String directoryManagerPwdFile = null;
+    String directoryManagerDn = null;
+
+    for (int i=0; i<args.length; i++)
+    {
+      if (args[i].equalsIgnoreCase("-H") ||
+          args[i].equalsIgnoreCase("--help"))
+      {
+        printUsage = true;
+      }
+      else if (args[i].equalsIgnoreCase("-D") ||
+          args[i].equalsIgnoreCase("--bindDN"))
+      {
+        if (i+1 >= args.length)
+        {
+          errors.add(getMsg("cli-status-root-user-dn-not-provided", true));
+        }
+        else
+        {
+          if (args[i+1].indexOf("-") == 0)
+          {
+            errors.add(getMsg("cli-status-root-user-dn-not-provided", true));
+          }
+          else
+          {
+            directoryManagerDn = args[i+1];
+            i++;
+          }
+        }
+      }
+      else if (args[i].equals("-w") ||
+          args[i].equalsIgnoreCase("--bindPassword"))
+      {
+        if (i+1 >= args.length)
+        {
+          errors.add(getMsg("cli-status-root-user-pwd-not-provided", true));
+        }
+        else
+        {
+          if (args[i+1].indexOf("-") == 0)
+          {
+            errors.add(getMsg("cli-status-root-user-pwd-not-provided", true));
+          }
+          else
+          {
+            directoryManagerPwd = args[i+1];
+            i++;
+          }
+        }
+      }
+      else if (args[i].equals("-j") ||
+          args[i].equalsIgnoreCase("--bindPasswordFile"))
+      {
+        if (i+1 >= args.length)
+        {
+          errors.add(getMsg("cli-status-root-user-pwd-file-not-provided",
+              true));
+        }
+        else
+        {
+          if (args[i+1].indexOf("-") == 0)
+          {
+            errors.add(getMsg("cli-status-root-user-pwd-file-not-provided",
+                true));
+          }
+          else
+          {
+            directoryManagerPwdFile = args[i+1];
+            i++;
+          }
+        }
+      }
+      else
+      {
+        String[] arg = {args[i]};
+        errors.add(getMsg("cli-status-unknown-argument", arg, true));
+      }
+    }
+
+    if ((directoryManagerPwdFile != null) && (directoryManagerPwd != null))
+    {
+      errors.add(getMsg("cli-status-pwd-and-pwd-file-provided", true));
+    }
+    else
+    {
+      if (directoryManagerPwdFile != null)
+      {
+        directoryManagerPwd = readPwdFromFile(directoryManagerPwdFile);
+        if (directoryManagerPwd == null)
+        {
+          String[] arg = {directoryManagerPwdFile};
+          errors.add(getMsg("cli-status-error-reading-pwd-file", arg, true));
+        }
+      }
+    }
+
+    if (printUsage)
+    {
+      printUsage();
+    }
+    else if (errors.size() > 0)
+    {
+      System.err.println(Utils.getStringFromCollection(errors,
+          LINE_SEPARATOR+LINE_SEPARATOR));
+      System.out.println();
+      printUsage();
+      returnValue = USER_DATA_ERROR;
+    }
+    else
+    {
+      boolean isServerRunning =
+        Utils.isServerRunning(Utils.getInstallPathFromClasspath());
+      /* This is required to retrieve the ldap url to be used by the
+       * ConfigFromLDAP class.
+       */
+      ConfigFromFile offLineConf = new ConfigFromFile();
+      offLineConf.readConfiguration();
+
+      ServerStatusDescriptor desc = createServerStatusDescriptor(
+      directoryManagerDn, directoryManagerPwd);
+      if (isServerRunning)
+      {
+        String ldapUrl = offLineConf.getLDAPURL();
+        if (directoryManagerDn == null)
+        {
+          directoryManagerDn = "";
+        }
+        if (directoryManagerPwd == null)
+        {
+          directoryManagerPwd = "";
+        }
+        ConfigFromLDAP onLineConf = new ConfigFromLDAP();
+        onLineConf.setConnectionInfo(ldapUrl, directoryManagerDn,
+            directoryManagerPwd);
+        onLineConf.readConfiguration();
+        updateDescriptorWithOnLineInfo(desc, onLineConf);
+      }
+      else
+      {
+        updateDescriptorWithOffLineInfo(desc, offLineConf);
+      }
+
+      writeStatus(desc);
+    }
+
+    return returnValue;
+  }
+
+  /**
+   * Returns the password stored in a file.  Returns <CODE>null</CODE> if no
+   * password is found.
+   * @param path the path of the file containing the password.
+   * @return the password stored in a file.  Returns <CODE>null</CODE> if no
+   * password is found.
+   */
+  private String readPwdFromFile(String path)
+  {
+    String pwd = null;
+    BufferedReader reader = null;
+    try
+    {
+      reader = new BufferedReader(new FileReader(path));
+      pwd = reader.readLine();
+    }
+    catch (Exception e)
+    {
+    }
+    finally
+    {
+      try
+      {
+        if (reader != null)
+        {
+          reader.close();
+        }
+      } catch (Exception e) {}
+    }
+    return pwd;
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private String getMsg(String key, boolean wrap)
+  {
+    String t = getI18n().getMsg(key);
+    if (wrap)
+    {
+      t= wrap(t);
+    }
+    return t;
+  }
+
+  private String getMsg(String key, String[] args, boolean wrap)
+  {
+    String t = getI18n().getMsg(key, args);
+    if (wrap)
+    {
+      t= wrap(t);
+    }
+    return t;
+  }
+
+  private static ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  private void printUsage()
+  {
+    String arg;
+    if (Utils.isWindows())
+    {
+      arg = COMMAND_NAME_WINDOWS;
+    } else
+    {
+      arg = COMMAND_NAME_UNIX;
+    }
+    /*
+     * This is required because the usage message contains '{' characters that
+     * mess up the MessageFormat.format method.
+     */
+    String msg = getMsg("status-cli-usage", true);
+    msg = msg.replace("{0}", arg);
+    System.err.println(msg);
+  }
+
+  private ServerStatusDescriptor createServerStatusDescriptor(String dn,
+      String pwd)
+  {
+    ServerStatusDescriptor desc = new ServerStatusDescriptor();
+    desc.setAuthenticated((dn != null) && (pwd != null));
+
+    if (Utils.isServerRunning(Utils.getInstallPathFromClasspath()))
+    {
+      desc.setStatus(ServerStatusDescriptor.ServerStatus.STARTED);
+    }
+    else
+    {
+      desc.setStatus(ServerStatusDescriptor.ServerStatus.STOPPED);
+    }
+
+    desc.setInstallPath(new File(Utils.getInstallPathFromClasspath()));
+
+    desc.setOpenDSVersion(
+        org.opends.server.util.DynamicConstants.FULL_VERSION_STRING);
+
+    return desc;
+  }
+
+  /**
+   * Updates the ServerStatusDescriptor object using the information in the
+   * config.ldif file (we use a ConfigFromFile object to do this).
+   * @param desc the ServerStatusDescriptor object to be updated.
+   * @param offLineConf the ConfigFromFile object to be used.
+   */
+  private void updateDescriptorWithOffLineInfo(ServerStatusDescriptor desc,
+      ConfigFromFile offLineConf)
+  {
+    desc.setAdministrativeUsers(offLineConf.getAdministrativeUsers());
+    desc.setDatabases(offLineConf.getDatabases());
+    desc.setListeners(offLineConf.getListeners());
+    desc.setErrorMessage(offLineConf.getErrorMessage());
+    desc.setOpenConnections(-1);
+    desc.setJavaVersion(null);
+  }
+
+  /**
+   * Updates the ServerStatusDescriptor object using the LDAP protocol (we use a
+   * ConfigFromLDAP object to do this).
+   * @param desc the ServerStatusDescriptor object to be updated.
+   * @param onLineConf the ConfigFromLDAP object to be used.
+   */
+  private void updateDescriptorWithOnLineInfo(ServerStatusDescriptor desc,
+      ConfigFromLDAP onLineConf)
+  {
+    desc.setAdministrativeUsers(onLineConf.getAdministrativeUsers());
+    desc.setDatabases(onLineConf.getDatabases());
+    desc.setListeners(onLineConf.getListeners());
+    desc.setErrorMessage(onLineConf.getErrorMessage());
+    desc.setJavaVersion(onLineConf.getJavaVersion());
+    desc.setOpenConnections(onLineConf.getOpenConnections());
+  }
+
+  private void writeStatus(ServerStatusDescriptor desc)
+  {
+    String[] labels =
+      {
+        getMsg("server-status-label", false),
+        getMsg("connections-label", false),
+        getMsg("administrative-users-label", false),
+        getMsg("installation-path-label", false),
+        getMsg("opends-version-label", false),
+        getMsg("java-version-label", false)
+      };
+    int labelWidth = 0;
+    for (int i=0; i<labels.length; i++)
+    {
+      labelWidth = Math.max(labelWidth, labels[i].length());
+    }
+    System.out.println();
+    String title = getMsg("server-status-title", false);
+    System.out.println(centerTitle(title));
+    writeStatusContents(desc, labelWidth);
+    writeCurrentConnectionContents(desc, labelWidth);
+    System.out.println();
+
+    title = getMsg("server-details-title", false);
+    System.out.println(centerTitle(title));
+    writeAdministrativeUserContents(desc, labelWidth);
+    writeInstallPathContents(desc, labelWidth);
+    writeVersionContents(desc, labelWidth);
+    writeJavaVersionContents(desc, labelWidth);
+    System.out.println();
+
+    writeListenerContents(desc);
+    System.out.println();
+
+    writeDatabaseContents(desc);
+
+    writeErrorContents(desc);
+
+    if (displayMustStartLegend)
+    {
+      System.out.println();
+      System.out.println(getMsg("not-available-server-down-cli-legend", true));
+    }
+    else if (displayMustAuthenticateLegend)
+    {
+      System.out.println();
+      System.out.println(
+          getMsg("not-available-authentication-required-cli-legend", true));
+    }
+    System.out.println();
+  }
+
+  /**
+   * Writes the status contents displaying with what is specified in the
+   * provided ServerStatusDescriptor object.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeStatusContents(ServerStatusDescriptor desc,
+      int maxLabelWidth)
+  {
+    String status;
+    switch (desc.getStatus())
+    {
+    case STARTED:
+      status = getMsg("server-started-label", false);
+      break;
+
+    case STOPPED:
+      status = getMsg("server-stopped-label", false);
+      break;
+
+    case STARTING:
+      status = getMsg("server-starting-label", false);
+      break;
+
+    case STOPPING:
+      status = getMsg("server-stopping-label", false);
+      break;
+
+    case UNKNOWN:
+      status = getMsg("server-unknown-status-label", false);
+      break;
+
+    default:
+      throw new IllegalStateException("Unknown status: "+desc.getStatus());
+    }
+    writeLabelValue(getMsg("server-status-label", false), status,
+        maxLabelWidth);
+  }
+
+  /**
+   * Writes the current connection contents displaying with what is specified
+   * in the provided ServerStatusDescriptor object.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeCurrentConnectionContents(ServerStatusDescriptor desc,
+      int maxLabelWidth)
+  {
+    String text;
+    if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+    {
+      int nConn = desc.getOpenConnections();
+      if (nConn >= 0)
+      {
+        text = String.valueOf(nConn);
+      }
+      else
+      {
+        if (!desc.isAuthenticated())
+        {
+          text = getNotAvailableBecauseAuthenticationIsRequiredText();
+        }
+        else
+        {
+          text = getNotAvailableText();
+        }
+      }
+    }
+    else
+    {
+      text = getNotAvailableBecauseServerIsDownText();
+    }
+
+    writeLabelValue(getMsg("connections-label", false), text, maxLabelWidth);
+  }
+
+  /**
+   * Writes the administrative user contents displaying with what is specified
+   * in the provided ServerStatusDescriptor object.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeAdministrativeUserContents(ServerStatusDescriptor desc,
+      int maxLabelWidth)
+  {
+    Set<String> administrators = desc.getAdministrativeUsers();
+    String text;
+    if (administrators.size() > 0)
+    {
+      TreeSet<String> ordered = new TreeSet<String>();
+      ordered.addAll(administrators);
+
+      String first = ordered.iterator().next();
+      writeLabelValue(getMsg("administrative-users-label", false), first,
+          maxLabelWidth);
+
+      Iterator<String> it = ordered.iterator();
+      // First one already printed
+      it.next();
+      while (it.hasNext())
+      {
+        writeLabelValue(getMsg("administrative-users-label", false), it.next(),
+            maxLabelWidth);
+      }
+    }
+    else
+    {
+      if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+      {
+        if (!desc.isAuthenticated())
+        {
+          text = getNotAvailableBecauseAuthenticationIsRequiredText();
+        }
+        else
+        {
+          text = getNotAvailableText();
+        }
+      }
+      else
+      {
+        text = getNotAvailableText();
+      }
+      writeLabelValue(getMsg("administrative-users-label", false), text,
+          maxLabelWidth);
+    }
+  }
+
+  /**
+   * Writes the install path contents displaying with what is specified in the
+   * provided ServerStatusDescriptor object.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeInstallPathContents(ServerStatusDescriptor desc,
+      int maxLabelWidth)
+  {
+    File path = desc.getInstallPath();
+    writeLabelValue(getMsg("installation-path-label", false), path.toString(),
+        maxLabelWidth);
+  }
+
+  /**
+   * Updates the server version contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeVersionContents(ServerStatusDescriptor desc,
+      int maxLabelWidth)
+  {
+    String openDSVersion = desc.getOpenDSVersion();
+    writeLabelValue(getMsg("opends-version-label", false), openDSVersion,
+        maxLabelWidth);
+  }
+
+  /**
+   * Updates the java version contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeJavaVersionContents(ServerStatusDescriptor desc,
+      int maxLabelWidth)
+  {
+    String text;
+    if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+    {
+      text = desc.getJavaVersion();
+      if (text == null)
+      {
+        if (!desc.isAuthenticated())
+        {
+          text = getNotAvailableBecauseAuthenticationIsRequiredText();
+        }
+        else
+        {
+          text = getNotAvailableText();
+        }
+      }
+    }
+    else
+    {
+      text = getNotAvailableBecauseServerIsDownText();
+    }
+    writeLabelValue(getMsg("java-version-label", false), text, maxLabelWidth);
+  }
+
+  /**
+   * Writes the listeners contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeListenerContents(ServerStatusDescriptor desc)
+  {
+    String title = getMsg("listeners-title", false);
+    System.out.println(centerTitle(title));
+
+    Set<ListenerDescriptor> listeners = desc.getListeners();
+
+    if (listeners.size() == 0)
+    {
+      if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+      {
+        if (!desc.isAuthenticated())
+        {
+          System.out.println(
+              getMsg("not-available-authentication-required-cli-label", true));
+        }
+        else
+        {
+          System.out.println(getMsg("no-listeners-found", true));
+        }
+      }
+      else
+      {
+        System.out.println(getMsg("no-listeners-found", true));
+      }
+    }
+    else
+    {
+      ListenersTableModel listenersTableModel = new ListenersTableModel();
+      listenersTableModel.setData(desc.getListeners());
+      writeTableModel(listenersTableModel, desc);
+    }
+  }
+
+  /**
+   * Writes the databases contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeDatabaseContents(ServerStatusDescriptor desc)
+  {
+    String title = getMsg("databases-title", false);
+    System.out.println(centerTitle(title));
+
+    Set<DatabaseDescriptor> databases = desc.getDatabases();
+
+    if (databases.size() == 0)
+    {
+      if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+      {
+        if (!desc.isAuthenticated())
+        {
+          System.out.println(
+              getMsg("not-available-authentication-required-cli-label", true));
+        }
+        else
+        {
+          System.out.println(getMsg("no-dbs-found", true));
+        }
+      }
+      else
+      {
+        System.out.println(getMsg("no-dbs-found", true));
+      }
+    }
+    else
+    {
+      DatabasesTableModel databasesTableModel = new DatabasesTableModel();
+      databasesTableModel.setData(desc.getDatabases());
+
+      writeTableModel(databasesTableModel, desc);
+    }
+  }
+
+  /**
+   * Writes the error label contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void writeErrorContents(ServerStatusDescriptor desc)
+  {
+    String errorMsg = desc.getErrorMessage();
+    if (errorMsg != null)
+    {
+      System.out.println();
+      System.out.println(wrap(errorMsg));
+    }
+  }
+
+  /**
+   * Returns the not available text explaining that the data is not available
+   * because the server is down.
+   * @return the text.
+   */
+  private String getNotAvailableBecauseServerIsDownText()
+  {
+    displayMustStartLegend = true;
+    return getMsg("not-available-server-down-cli-label", false);
+  }
+
+  /**
+   * Returns the not available text explaining that the data is not available
+   * because authentication is required.
+   * @return the text.
+   */
+  private String getNotAvailableBecauseAuthenticationIsRequiredText()
+  {
+    displayMustAuthenticateLegend = true;
+    return getMsg("not-available-authentication-required-cli-label", false);
+  }
+
+  /**
+   * Returns the not available text explaining that the data is not available.
+   * @return the text.
+   */
+  private String getNotAvailableText()
+  {
+    return getMsg("not-available-label", false);
+  }
+
+  private void writeTableModel(TableModel tableModel,
+      ServerStatusDescriptor desc)
+  {
+    int[] maxWidths = new int[tableModel.getColumnCount()];
+    for (int i=0; i<maxWidths.length; i++)
+    {
+      maxWidths[i] = tableModel.getColumnName(i).length();
+    }
+
+    for (int i=0; i<tableModel.getRowCount(); i++)
+    {
+      for (int j=0; j<maxWidths.length; j++)
+      {
+        Object v = tableModel.getValueAt(i, j);
+        if (v != null)
+        {
+          if (v instanceof String)
+          {
+            maxWidths[j] = Math.max(maxWidths[j], ((String)v).length());
+          }
+          else if (v instanceof Integer)
+          {
+            String text;
+            int nEntries = ((Integer)v).intValue();
+            if (nEntries >= 0)
+            {
+              text = String.valueOf(nEntries);
+            }
+            else
+            {
+              if (!desc.isAuthenticated())
+              {
+                text = getNotAvailableBecauseAuthenticationIsRequiredText();
+              }
+              else
+              {
+                text = getNotAvailableText();
+              }
+            }
+            maxWidths[j] = Math.max(maxWidths[j], text.length());
+          }
+          else
+          {
+            throw new IllegalStateException("Unknown object type: "+v);
+          }
+        }
+      }
+    }
+
+    int totalWidth = 0;
+    for (int i=0; i<maxWidths.length; i++)
+    {
+      if (i < maxWidths.length - 1)
+      {
+        maxWidths[i] += 5;
+      }
+      totalWidth += maxWidths[i];
+    }
+
+    StringBuffer headerLine = new StringBuffer();
+    for (int i=0; i<maxWidths.length; i++)
+    {
+      String header = tableModel.getColumnName(i);
+      headerLine.append(header);
+      int extra = maxWidths[i] - header.length();
+      for (int j=0; j<extra; j++)
+      {
+        headerLine.append(" ");
+      }
+    }
+    System.out.println(wrap(headerLine.toString()));
+    StringBuffer t = new StringBuffer();
+    for (int i=0; i<headerLine.length(); i++)
+    {
+      t.append("=");
+    }
+    System.out.println(wrap(t.toString()));
+
+    for (int i=0; i<tableModel.getRowCount(); i++)
+    {
+      StringBuffer line = new StringBuffer();
+      for (int j=0; j<tableModel.getColumnCount(); j++)
+      {
+        int extra = maxWidths[j];
+        Object v = tableModel.getValueAt(i, j);
+        if (v != null)
+        {
+          if (v instanceof String)
+          {
+            line.append(v);
+            extra -= ((String)v).length();
+          }
+          else if (v instanceof Integer)
+          {
+            int nEntries = ((Integer)v).intValue();
+            if (nEntries >= 0)
+            {
+              line.append(nEntries);
+            }
+            else
+            {
+              if (!desc.isAuthenticated())
+              {
+                line.append(
+                    getNotAvailableBecauseAuthenticationIsRequiredText());
+              }
+              else
+              {
+                line.append(getNotAvailableText());
+              }
+            }
+          }
+          else
+          {
+            throw new IllegalStateException("Unknown object type: "+v);
+          }
+
+        }
+        for (int k=0; k<extra; k++)
+        {
+          line.append(" ");
+        }
+      }
+      System.out.println(wrap(line.toString()));
+    }
+  }
+
+  private void writeLabelValue(String label, String value, int maxLabelWidth)
+  {
+    StringBuffer buf = new StringBuffer();
+    buf.append(label);
+
+    int extra = maxLabelWidth - label.length();
+    for (int i = 0; i<extra; i++)
+    {
+      buf.append(" ");
+    }
+    buf.append(" "+value);
+    System.out.println(wrap(buf.toString()));
+
+  }
+
+  private String wrap(String text)
+  {
+    return org.opends.server.util.StaticUtils.wrapText(text,
+        Utils.getCommandLineMaxLineWidth());
+  }
+
+  private String centerTitle(String text)
+  {
+    String centered;
+    if (text.length() <= Utils.getCommandLineMaxLineWidth() - 8)
+    {
+      StringBuffer buf = new StringBuffer();
+      int extra = Math.min(10,
+          (Utils.getCommandLineMaxLineWidth() - 8 - text.length()) / 2);
+      for (int i=0; i<extra; i++)
+      {
+        buf.append(" ");
+      }
+      buf.append("--- "+text+" ---");
+      centered = buf.toString();
+    }
+    else
+    {
+      centered = text;
+    }
+    return centered;
+  }
+}
+
diff --git a/opends/src/statuspanel/org/opends/statuspanel/StatusPanelController.java b/opends/src/statuspanel/org/opends/statuspanel/StatusPanelController.java
new file mode 100644
index 0000000..1f4904d
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/StatusPanelController.java
@@ -0,0 +1,1241 @@
+/*
+ * 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.statuspanel;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Map;
+
+import javax.swing.SwingUtilities;
+
+import org.opends.server.core.DirectoryServer;
+
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.BackgroundTask;
+import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
+import org.opends.quicksetup.util.Utils;
+
+import org.opends.statuspanel.event.ServerStatusChangeEvent;
+import org.opends.statuspanel.event.ServerStatusChangeListener;
+import org.opends.statuspanel.event.StatusPanelButtonListener;
+import org.opends.statuspanel.i18n.ResourceProvider;
+import org.opends.statuspanel.ui.LoginDialog;
+import org.opends.statuspanel.ui.ProgressDialog;
+import org.opends.statuspanel.ui.StatusPanelDialog;
+
+/**
+ * This is the main class of the status panel.
+ *
+ * It is in charge of all the logic behind the displaying of the dialogs and
+ * the one that initializes everything.  This is also the class that ultimately
+ * listens to user events (notably button clicks) and executes the associated
+ * operations with these user events.
+ *
+ */
+public class StatusPanelController implements ServerStatusChangeListener,
+StatusPanelButtonListener
+{
+  private LoginDialog loginDialog;
+  private StatusPanelDialog controlPanelDialog;
+  private ProgressDialog progressDialog;
+  private ServerStatusPooler serverStatusPooler;
+  private HtmlProgressMessageFormatter formatter =
+    new HtmlProgressMessageFormatter();
+
+  private boolean isStarting;
+  private boolean isStopping;
+  private boolean isRestarting;
+
+  private boolean mustDisplayAuthenticateDialog;
+
+  private ServerStatusDescriptor desc;
+
+  private String lastDetail;
+  private String lastSummary;
+
+  private Thread progressUpdater;
+
+//Update period of the progress dialog.
+  private static final int UPDATE_PERIOD = 500;
+
+  /**
+   * This method creates the control panel 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.
+   *
+   * Note that there is no synchronization code between threads.  The
+   * synchronization code is not required as all the start/stop/restart actions
+   * are launched in the event thread so just using booleans that are updated
+   * in the event thread is enough to guarantee that there are no multiple
+   * operations launched at the same time.
+   *
+   * @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)
+  {
+    DirectoryServer.bootstrapClient();
+    initLookAndFeel();
+    /* Call this methods to create the dialogs (the control panel dialog
+     * is generated when we call getLoginDialog()). */
+    getLoginDialog();
+    getProgressDialog();
+    serverStatusPooler = new ServerStatusPooler();
+    serverStatusPooler.addServerStatusChangeListener(this);
+    serverStatusPooler.startPooling();
+    desc = serverStatusPooler.getLastDescriptor();
+    while (desc == null)
+    {
+      try
+      {
+        Thread.sleep(100);
+      }
+      catch (Exception ex)
+      {
+      }
+      desc = serverStatusPooler.getLastDescriptor();
+    }
+  }
+
+  /**
+   * This method displays the required dialog. This method must be called from
+   * the event thread.
+   */
+  public void display()
+  {
+    getStatusPanelDialog().packAndShow();
+    if (!isAuthenticated())
+    {
+      if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+      {
+        authenticateClicked();
+      }
+    }
+  }
+
+  /**
+   * ServerStatusChangeListener implementation.  This method is called when
+   * a new ServerStatusDescriptor has been generated by the ServerStatusPooler.
+   * @param ev the event we receive.
+   */
+  public void statusChanged(final ServerStatusChangeEvent ev)
+  {
+    /* Here we assume that this events are not very frequent (not frequent
+     * at least to generate flickering).  This is acceptable since the
+     * ServerStatusPooler does pooling every second.
+     */
+    if (SwingUtilities.isEventDispatchThread())
+    {
+      getStatusPanelDialog().updateContents(ev.getStatusDescriptor());
+    }
+    else
+    {
+      SwingUtilities.invokeLater(new Runnable()
+      {
+        public void run()
+        {
+          getStatusPanelDialog().updateContents(ev.getStatusDescriptor());
+        }
+      });
+    }
+  }
+
+  /**
+   * Method called when user clicks on Quit button.
+   * StatusPanelButtonListener implementation.
+   */
+  public void quitClicked()
+  {
+    System.exit(0);
+  }
+
+  /**
+   * Method called when user clicks on Start button.
+   * StatusPanelButtonListener implementation.
+   */
+  public void startClicked()
+  {
+    if (isStarting)
+    {
+      if (!getProgressDialog().isVisible())
+      {
+        getProgressDialog().setVisible(true);
+      }
+    }
+    else if (isStopping)
+    {
+      /* Should not happen */
+      Thread.dumpStack();
+    }
+    else if (isRestarting)
+    {
+      /* Should not happen */
+      Thread.dumpStack();
+    }
+    else
+    {
+      isStarting = true;
+      lastDetail = null;
+      getProgressDialog().setSummary(
+          getFormattedSummary(getMsg("summary-starting")));
+      getProgressDialog().setDetails("");
+      serverStatusPooler.beginServerStart();
+      getProgressDialog().setCloseButtonEnabled(false);
+      getStatusPanelDialog().setStartButtonEnabled(false);
+      getStatusPanelDialog().setStopButtonEnabled(false);
+      getStatusPanelDialog().setRestartButtonEnabled(false);
+      getStatusPanelDialog().setAuthenticateButtonEnabled(false);
+
+      if (!getProgressDialog().isVisible())
+      {
+        getProgressDialog().pack();
+        Utils.centerOnComponent(getProgressDialog(), getStatusPanelDialog());
+        getProgressDialog().setVisible(true);
+      }
+
+      BackgroundTask task = new BackgroundTask()
+      {
+        public Object processBackgroundTask()
+        {
+          if (progressUpdater == null)
+          {
+            runProgressUpdater();
+          }
+          mustDisplayAuthenticateDialog = startServer() && !isAuthenticated();
+          serverStatusPooler.endServerStart();
+          return null;
+        }
+        public void backgroundTaskCompleted(Object value, Throwable t)
+        {
+          if (t != null)
+          {
+            // Bug
+            t.printStackTrace();
+          }
+          getStatusPanelDialog().setStartButtonEnabled(true);
+          getStatusPanelDialog().setStopButtonEnabled(true);
+          getStatusPanelDialog().setRestartButtonEnabled(true);
+          getStatusPanelDialog().setAuthenticateButtonEnabled(
+              !isAuthenticated());
+          getProgressDialog().setCloseButtonEnabled(true);
+          isStarting = false;
+        }
+      };
+      task.startBackgroundTask();
+    }
+  }
+
+  /**
+   * Method called when user clicks on Stop button.
+   * StatusPanelButtonListener implementation.
+   */
+  public void stopClicked()
+  {
+    if (isStopping)
+    {
+      if (!getProgressDialog().isVisible())
+      {
+        getProgressDialog().setVisible(true);
+      }
+    }
+    else if (isStarting)
+    {
+      /* Should not happen */
+      Thread.dumpStack();
+    }
+    else if (isRestarting)
+    {
+      /* Should not happen */
+      Thread.dumpStack();
+    }
+    else
+    {
+      boolean stopServer = false;
+      if (requiresAuthenticationToStop())
+      {
+        getLoginDialog().pack();
+        Utils.centerOnComponent(getLoginDialog(), getStatusPanelDialog());
+        getLoginDialog().setVisible(true);
+        if (!getLoginDialog().isCancelled())
+        {
+          serverStatusPooler.setAuthentication(
+              getLoginDialog().getDirectoryManagerDn(),
+              getLoginDialog().getDirectoryManagerPwd());
+          stopServer = confirmStop();
+        }
+      }
+      else
+      {
+        stopServer = confirmStop();
+      }
+
+      if (stopServer)
+      {
+        isStopping = true;
+        lastDetail = null;
+        getProgressDialog().setSummary(
+            getFormattedSummary(getMsg("summary-stopping")));
+        getProgressDialog().setDetails("");
+        serverStatusPooler.beginServerStop();
+        getProgressDialog().setCloseButtonEnabled(false);
+        getStatusPanelDialog().setStartButtonEnabled(false);
+        getStatusPanelDialog().setStopButtonEnabled(false);
+        getStatusPanelDialog().setRestartButtonEnabled(false);
+        getStatusPanelDialog().setAuthenticateButtonEnabled(false);
+
+        if (!getProgressDialog().isVisible())
+        {
+          getProgressDialog().pack();
+          Utils.centerOnComponent(getProgressDialog(), getStatusPanelDialog());
+          getProgressDialog().setVisible(true);
+        }
+
+        BackgroundTask task = new BackgroundTask()
+        {
+          public Object processBackgroundTask()
+          {
+            if (progressUpdater == null)
+            {
+              runProgressUpdater();
+            }
+            stopServer();
+            serverStatusPooler.endServerStop();
+            mustDisplayAuthenticateDialog = false;
+            return null;
+          }
+          public void backgroundTaskCompleted(Object value, Throwable t)
+          {
+            if (t != null)
+            {
+              // Bug
+              t.printStackTrace();
+            }
+            getStatusPanelDialog().setStartButtonEnabled(true);
+            getStatusPanelDialog().setStopButtonEnabled(true);
+            getStatusPanelDialog().setRestartButtonEnabled(true);
+            getStatusPanelDialog().setAuthenticateButtonEnabled(false);
+            getProgressDialog().setCloseButtonEnabled(true);
+            isStopping = false;
+          }
+        };
+        task.startBackgroundTask();
+      }
+    }
+  }
+
+  /**
+   * Method called when user clicks on Restart button.
+   * StatusPanelButtonListener implementation.
+   */
+  public void restartClicked()
+  {
+    if (isRestarting)
+    {
+      if (!getProgressDialog().isVisible())
+      {
+        getProgressDialog().setVisible(true);
+      }
+    }
+    else if (isStopping)
+    {
+      /* Should not happen */
+      Thread.dumpStack();
+    }
+    else if (isStarting)
+    {
+      /* Should not happen */
+      Thread.dumpStack();
+    }
+    else
+    {
+      boolean restartServer = false;
+      if (requiresAuthenticationToRestart())
+      {
+        getLoginDialog().pack();
+        Utils.centerOnComponent(getLoginDialog(), getStatusPanelDialog());
+        getLoginDialog().setVisible(true);
+        if (!getLoginDialog().isCancelled())
+        {
+          serverStatusPooler.setAuthentication(
+              getLoginDialog().getDirectoryManagerDn(),
+              getLoginDialog().getDirectoryManagerPwd());
+          restartServer = confirmRestart();
+        }
+      }
+      else
+      {
+        restartServer = confirmRestart();
+      }
+
+      if (restartServer)
+      {
+        isRestarting = true;
+        lastDetail = null;
+        getProgressDialog().setSummary(
+            getFormattedSummary(getMsg("summary-stopping")));
+        getProgressDialog().setDetails("");
+        serverStatusPooler.beginServerStop();
+        getProgressDialog().setCloseButtonEnabled(false);
+        getStatusPanelDialog().setStartButtonEnabled(false);
+        getStatusPanelDialog().setStopButtonEnabled(false);
+        getStatusPanelDialog().setRestartButtonEnabled(false);
+        getStatusPanelDialog().setAuthenticateButtonEnabled(false);
+
+        if (!getProgressDialog().isVisible())
+        {
+          getProgressDialog().pack();
+          Utils.centerOnComponent(getProgressDialog(), getStatusPanelDialog());
+          getProgressDialog().setVisible(true);
+        }
+
+        BackgroundTask task = new BackgroundTask()
+        {
+          public Object processBackgroundTask()
+          {
+            if (progressUpdater == null)
+            {
+              runProgressUpdater();
+            }
+            if (stopServer())
+            {
+              serverStatusPooler.endServerStop();
+              serverStatusPooler.beginServerStart();
+              mustDisplayAuthenticateDialog = startServer() &&
+              !isAuthenticated();
+              serverStatusPooler.endServerStart();
+            }
+            else
+            {
+              serverStatusPooler.endServerStop();
+              mustDisplayAuthenticateDialog = false;
+            }
+            return null;
+          }
+          public void backgroundTaskCompleted(Object value, Throwable t)
+          {
+            if (t != null)
+            {
+              // Bug
+              t.printStackTrace();
+            }
+            getStatusPanelDialog().setStartButtonEnabled(true);
+            getStatusPanelDialog().setStopButtonEnabled(true);
+            getStatusPanelDialog().setRestartButtonEnabled(true);
+            getStatusPanelDialog().setAuthenticateButtonEnabled(
+                !isAuthenticated());
+            getProgressDialog().setCloseButtonEnabled(true);
+            isRestarting = false;
+          }
+        };
+        task.startBackgroundTask();
+      }
+    }
+  }
+
+  /**
+   * Method called when user clicks on Authenticate button.
+   * StatusPanelButtonListener implementation.
+   */
+  public void authenticateClicked()
+  {
+    getLoginDialog().pack();
+    Utils.centerOnComponent(getLoginDialog(), getStatusPanelDialog());
+    getLoginDialog().setVisible(true);
+    if (!getLoginDialog().isCancelled())
+    {
+      serverStatusPooler.setAuthentication(
+          getLoginDialog().getDirectoryManagerDn(),
+          getLoginDialog().getDirectoryManagerPwd());
+    }
+  }
+
+  /**
+   * A method to initialize the look and feel.
+   *
+   */
+  private void initLookAndFeel()
+  {
+    UIFactory.initialize();
+  }
+
+  /**
+   * Returns the login dialog and creates it if it does not exist.
+   * @return the login dialog.
+   */
+  private LoginDialog getLoginDialog()
+  {
+    if (loginDialog == null)
+    {
+      loginDialog = new LoginDialog(getStatusPanelDialog());
+      loginDialog.setModal(true);
+    }
+    return loginDialog;
+  }
+
+  /**
+   * Returns the progress dialog and creates it if it does not exist.
+   * As we only can run an operation at a time (considering the nature of the
+   * operations we provide today) having a single progress dialog is enough.
+   * @return the progress dialog.
+   */
+  private ProgressDialog getProgressDialog()
+  {
+    if (progressDialog == null)
+    {
+      progressDialog = new ProgressDialog(getStatusPanelDialog());
+      progressDialog.addWindowListener(new WindowAdapter()
+      {
+        public void windowClosed(WindowEvent ev)
+        {
+          if (mustDisplayAuthenticateDialog)
+          {
+            mustDisplayAuthenticateDialog = false;
+            authenticateClicked();
+          }
+        }
+      });
+    }
+    return progressDialog;
+  }
+
+  /**
+   * Returns the status panel dialog and creates it if it does not exist.  This
+   * is the dialog that displays the status information to the user.
+   * @return the status panel dialog.
+   */
+  private StatusPanelDialog getStatusPanelDialog()
+  {
+    if (controlPanelDialog == null)
+    {
+      controlPanelDialog = new StatusPanelDialog();
+      controlPanelDialog.addButtonListener(this);
+    }
+    return controlPanelDialog;
+  }
+
+  /**
+   * This methods starts the server and updates the progress with the start
+   * messages.
+   * @return <CODE>true</CODE> if the server started successfully and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean startServer()
+  {
+    boolean started = false;
+
+    if (isRestarting)
+    {
+      updateProgress(
+          getFormattedSummary(getMsg("summary-starting")),
+          getTaskSeparator());
+    }
+    updateProgress(
+        getFormattedSummary(getMsg("summary-starting")),
+        getFormattedProgress(getMsg("progress-starting")) + getLineBreak());
+
+    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[] args = new String[argList.size()];
+    argList.toArray(args);
+    ProcessBuilder pb = new ProcessBuilder(args);
+    Map<String, String> env = pb.environment();
+    env.put("JAVA_HOME", System.getProperty("java.home"));
+    /* Remove JAVA_BIN to be sure that we use the JVM running the installer
+     * JVM to start the server.
+     */
+    env.remove("JAVA_BIN");
+
+    try
+    {
+      Process process = pb.start();
+
+      BufferedReader err =
+        new BufferedReader(new InputStreamReader(process.getErrorStream()));
+      BufferedReader out =
+        new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+      /* Create these objects to resend the stop process output to the details
+       * area.
+       */
+      new ProgressReader(err, true, true);
+      new ProgressReader(out, false, true);
+
+      int returnValue = process.waitFor();
+
+      if (returnValue == 0)
+      {
+        /*
+         * 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.
+         *
+         * However we can have issues with the firewalls or do not have rights
+         * to connect.  Just check if we can connect to the server.
+         * Try 5 times with an interval of 1 second between try.
+         */
+        boolean running = false;
+        for (int i=0; i<5 && !running; i++)
+        {
+          running = Utils.isServerRunning(
+              Utils.getInstallPathFromClasspath());
+        }
+
+        if (!running)
+        {
+          try
+          {
+            Thread.sleep(1000);
+          }
+          catch (Throwable t)
+          {
+          }
+        }
+        if (!running)
+        {
+          updateProgress(getFormattedError(getMsg("summary-start-error")),
+                getFormattedError(getMsg("error-starting-server-generic"),
+                    true));
+        }
+        else
+        {
+          updateProgress(
+              getFormattedSuccess(getMsg("summary-start-success")),
+              "");
+          started = true;
+        }
+      }
+      else
+      {
+        String[] arg = {String.valueOf(returnValue)};
+        String msg = getMsg("error-starting-server-code", arg);
+
+        /*
+         * The return code is not the one expected, assume the server could
+         * not be started.
+         */
+        updateProgress(
+            getFormattedError(getMsg("summary-start-error")),
+            msg);
+      }
+
+    } catch (IOException ioe)
+    {
+      String msg = getThrowableMsg("error-starting-server", ioe);
+      updateProgress(
+          getFormattedError(getMsg("summary-start-error")),
+          msg);
+    }
+    catch (InterruptedException ie)
+    {
+      String msg = getThrowableMsg("error-starting-server", ie);
+      updateProgress(
+          getFormattedError(getMsg("summary-start-error")),
+          msg);
+    }
+
+    return started;
+  }
+
+  /**
+   * This methods stops the server and updates the progress with the stop
+   * messages.
+   * @return <CODE>true</CODE> if the server stopped successfully and
+   * <CODE>false</CODE> otherwise.
+   */
+  private boolean stopServer()
+  {
+    boolean stopped = false;
+    updateProgress(
+        getFormattedSummary(getMsg("summary-stopping")),
+        getFormattedProgress(getMsg("progress-stopping")) + getLineBreak());
+
+    ArrayList<String> argList = new ArrayList<String>();
+
+    if (Utils.isWindows())
+    {
+      argList.add(Utils.getPath(getBinariesPath(), "stop-ds.bat"));
+      argList.add("--bindDN");
+      argList.add(getLoginDialog().getDirectoryManagerDn());
+      argList.add("--bindPassword");
+      argList.add(getLoginDialog().getDirectoryManagerPwd());
+    } else
+    {
+      argList.add(Utils.getPath(getBinariesPath(), "stop-ds"));
+    }
+    String[] args = new String[argList.size()];
+    argList.toArray(args);
+    ProcessBuilder pb = new ProcessBuilder(args);
+    Map<String, String> env = pb.environment();
+    env.put("JAVA_HOME", System.getProperty("java.home"));
+    /* Remove JAVA_BIN to be sure that we use the JVM running the uninstaller
+     * JVM to stop the server.
+     */
+    env.remove("JAVA_BIN");
+
+    try
+    {
+      Process process = pb.start();
+
+      BufferedReader err =
+          new BufferedReader(new InputStreamReader(process.getErrorStream()));
+      BufferedReader out =
+          new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+      /* Create these objects to resend the stop process output to the details
+       * area.
+       */
+      new ProgressReader(err, true, false);
+      new ProgressReader(out, false, false);
+
+      int returnValue = process.waitFor();
+
+      int clientSideError =
+      org.opends.server.protocols.ldap.LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR;
+      if ((returnValue == clientSideError) || (returnValue == 0))
+      {
+        if (Utils.isWindows())
+        {
+          /*
+           * Sometimes the server keeps some locks on the files.
+           * TODO: remove this code once stop-ds returns properly when server
+           * is stopped.
+           */
+          int nTries = 10;
+          for (int i=0; i<nTries && !stopped; i++)
+          {
+            stopped = !Utils.isServerRunning(
+                Utils.getInstallPathFromClasspath());
+            if (!stopped)
+            {
+              String msg =
+                getFormattedLog(getMsg("progress-server-waiting-to-stop"))+
+              getLineBreak();
+              updateProgress(
+                  getFormattedSummary(getMsg("summary-stopping")),
+                  msg);
+              try
+              {
+                Thread.sleep(5000);
+              }
+              catch (Exception ex)
+              {
+
+              }
+            }
+          }
+          if (!stopped)
+          {
+            returnValue = -1;
+          }
+        }
+      }
+
+      if (returnValue == clientSideError)
+      {
+        String msg = getLineBreak() +
+            getFormattedLog(getMsg("progress-server-already-stopped"))+
+            getLineBreak();
+        if (!isRestarting)
+        {
+          updateProgress(
+              getFormattedSuccess(getMsg("summary-stop-success")),
+              msg);
+        }
+        else
+        {
+          updateProgress(
+              getFormattedSummary(getMsg("summary-stop-success")),
+              msg);
+        }
+        stopped = true;
+      }
+      else if (returnValue != 0)
+      {
+        String[] arg = {String.valueOf(returnValue)};
+        String msg = getMsg("error-stopping-server-code", arg);
+
+        /*
+         * The return code is not the one expected, assume the server could
+         * not be stopped.
+         */
+        updateProgress(
+            getFormattedError(getMsg("summary-stop-error")),
+            msg);
+      }
+      else
+      {
+        String msg = getFormattedLog(getMsg("progress-server-stopped"));
+        if (!isRestarting)
+        {
+          updateProgress(
+              getFormattedSuccess(getMsg("summary-stop-success")),
+              msg);
+        }
+        else
+        {
+          updateProgress(
+              getFormattedSummary(getMsg("summary-stop-success")),
+              msg);
+        }
+        stopped = true;
+      }
+
+    } catch (IOException ioe)
+    {
+      String msg = getThrowableMsg("error-stopping-server", ioe);
+      updateProgress(
+          getFormattedError(getMsg("summary-stop-error")),
+          msg);
+    }
+    catch (InterruptedException ie)
+    {
+      String msg = getThrowableMsg("error-stopping-server", ie);
+      updateProgress(
+          getFormattedError(getMsg("summary-stop-error")),
+          msg);
+    }
+    return stopped;
+  }
+
+
+  /**
+   * Updates the progress variables used to update the progress dialog during
+   * start/stop/restart.
+   *
+   * @param summary the summary for the start/stop/restart operation.
+   * @param newDetail the new detail for the start/stop/restart operation.
+   */
+  private synchronized void updateProgress(final String summary,
+      final String newDetail)
+  {
+    if (lastDetail == null)
+    {
+      lastDetail = newDetail;
+    }
+    else
+    {
+      lastDetail += newDetail;
+    }
+    lastSummary = summary;
+  }
+
+  /**
+   * This method is used to update the progress dialog.
+   *
+   * We are receiving notifications from the installer and uninstaller (this
+   * class is a ProgressListener). However if we lots of notifications updating
+   * the progress panel every time we get a progress update can result of a lot
+   * of flickering. So the idea here is to have a minimal time between 2 updates
+   * of the progress dialog (specified by UPDATE_PERIOD).
+   */
+  private void runProgressUpdater()
+  {
+
+    progressUpdater = new Thread()
+    {
+      public void run()
+      {
+        try
+        {
+        String lastDisplayedSummary = null;
+        String lastDisplayedDetail = null;
+        while (true)
+        {
+          if (lastSummary != null)
+          {
+            if (lastSummary != lastDisplayedSummary)
+            {
+              lastDisplayedSummary = lastSummary;
+              SwingUtilities.invokeLater(new Runnable()
+              {
+                public void run()
+                {
+                  getProgressDialog().setSummary(lastSummary);
+                }
+              });
+            }
+          }
+
+          if (lastDetail != null)
+          {
+            if (lastDetail != lastDisplayedDetail)
+            {
+              lastDisplayedDetail = lastDetail;
+              SwingUtilities.invokeLater(new Runnable()
+              {
+                public void run()
+                {
+                  getProgressDialog().setDetails(lastDetail);
+                }
+              });
+            }
+          }
+
+          try
+          {
+            Thread.sleep(UPDATE_PERIOD);
+          } catch (Exception ex)
+          {
+          }
+        }
+        } catch (Throwable t)
+        {
+          // Bug
+          t.printStackTrace();
+        }
+      }
+    };
+    progressUpdater.start();
+  }
+
+  /**
+   * Returns a localized message for a key value.  In  the properties file we
+   * have something of type:
+   * key=value
+   *
+   * @see ResourceProvider.getMsg(String key)
+   * @param key the key in the properties file.
+   * @return the value associated to the key in the properties file.
+   * properties file.
+   */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  /**
+   * Returns a localized message for a key value.  In  the properties file we
+   * have something of type:
+   * key=value
+   *
+   * For instance if we pass as key "mykey" and as arguments {"value1"} and
+   * in the properties file we have:
+   * mykey=value with argument {0}.
+   *
+   * This method will return "value with argument value1".
+   * @see ResourceProvider.getMsg(String key, String[] args)
+   * @param key the key in the properties file.
+   * @param args the arguments to be passed to generate the resulting value.
+   * @return the value associated to the key in the properties file.
+   */
+  private String getMsg(String key, String[] args)
+  {
+    return getI18n().getMsg(key, args);
+  }
+
+  /**
+   * Returns a ResourceProvider instance.
+   * @return a ResourceProvider instance.
+   */
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  /**
+   * Returns the path to the binaries.
+   * @return the path to the binaries.
+   */
+  private String getBinariesPath()
+  {
+    return Utils.getPath(Utils.getInstallPathFromClasspath(),
+        Utils.getBinariesRelativePath());
+  }
+
+  /**
+   * Returns the formatted representation of the text that is the summary of the
+   * installation process (the one that goes in the UI next to the progress
+   * bar).
+   * @param text the source text from which we want to get the formatted
+   * representation
+   * @return the formatted representation of an error for the given text.
+   */
+  private String getFormattedSummary(String text)
+  {
+    return formatter.getFormattedSummary(text);
+  }
+
+  /**
+   * Returns the formatted representation of a success message for a given text.
+   * @param text the source text from which we want to get the formatted
+   * representation.
+   * @return the formatted representation of an success message for the given
+   * text.
+   */
+  private String getFormattedSuccess(String text)
+  {
+    return formatter.getFormattedSuccess(text);
+  }
+
+  /**
+   * Returns the formatted representation of an error for a given text.
+   * @param text the source text from which we want to get the formatted
+   * representation
+   * @return the formatted representation of an error for the given text.
+   */
+  private String getFormattedError(String text)
+  {
+    return formatter.getFormattedError(text, false);
+  }
+
+  /**
+   * Returns the formatted representation of an error for a given text.
+   * @param text the source text from which we want to get the formatted
+   * representation
+   * @return the formatted representation of an error for the given text.
+   */
+  private String getFormattedError(String text, boolean applyMargin)
+  {
+    return formatter.getFormattedError(text, applyMargin);
+  }
+
+  /**
+   * Returns the formatted representation of a log error message for a given
+   * text.
+   * @param text the source text from which we want to get the formatted
+   * representation
+   * @return the formatted representation of a log error message for the given
+   * text.
+   */
+  private String getFormattedLogError(String text)
+  {
+    return formatter.getFormattedLogError(text);
+  }
+
+  /**
+   * Returns the formatted representation of a log message for a given text.
+   * @param text the source text from which we want to get the formatted
+   * representation
+   * @return the formatted representation of a log message for the given text.
+   */
+  private String getFormattedLog(String text)
+  {
+    return formatter.getFormattedLog(text);
+  }
+
+  /**
+   * Returns the line break formatted.
+   * @return the line break formatted.
+   */
+  private String getLineBreak()
+  {
+    return formatter.getLineBreak();
+  }
+
+  /**
+   * Returns the task separator formatted.
+   * @return the task separator formatted.
+   */
+  private String getTaskSeparator()
+  {
+    return formatter.getTaskSeparator();
+  }
+
+  /**
+   * Returns the formatted representation of a progress message for a given
+   * text.
+   * @param text the source text from which we want to get the formatted
+   * representation
+   * @return the formatted representation of a progress message for the given
+   * text.
+   */
+  private String getFormattedProgress(String text)
+  {
+    return formatter.getFormattedProgress(text);
+  }
+
+  /**
+   * Returns a localized message for a given properties key and throwable.
+   * @param key the key of the message in the properties file.
+   * @param t the throwable for which we want to get a message.
+   * @return a localized message for a given properties key and throwable.
+   */
+  private String getThrowableMsg(String key, Throwable t)
+  {
+    return getThrowableMsg(key, null, t);
+  }
+
+  /**
+   * Returns a localized message for a given properties key and throwable.
+   * @param key the key of the message in the properties file.
+   * @param args the arguments of the message in the properties file.
+   * @param t the throwable for which we want to get a message.
+   *
+   * @return a localized message for a given properties key and throwable.
+   */
+  private String getThrowableMsg(String key, String[] args, Throwable t)
+  {
+    return Utils.getThrowableMsg(getI18n(), key, args, t);
+  }
+
+  /**
+   * This class is used to read the standard error and standard output of the
+   * Stop/Start process.
+   *
+   * When a new log message is found notifies the progress listeners of it. If
+   * an error occurs it also notifies the listeners.
+   *
+   */
+  private class ProgressReader
+  {
+    private boolean isFirstLine;
+    private String errorMsg;
+
+    /**
+     * The protected constructor.
+     * @param reader the BufferedReader of the stop process.
+     * @param isError a boolean indicating whether the BufferedReader
+     * corresponds to the standard error or to the standard output.
+     * @param isStart a boolean indicating whether we are starting or stopping
+     * the server.
+     */
+    public ProgressReader(final BufferedReader reader, final boolean isError,
+        final boolean isStart)
+    {
+      final String errorTag =
+          isError ? "error-reading-erroroutput" : "error-reading-output";
+
+      isFirstLine = true;
+
+      Thread t = new Thread(new Runnable()
+      {
+        public void run()
+        {
+          try
+          {
+            String line = reader.readLine();
+            while (line != null)
+            {
+              StringBuffer buf = new StringBuffer();
+              if (!isFirstLine)
+              {
+                buf.append(formatter.getLineBreak());
+              }
+              if (isError)
+              {
+                buf.append(getFormattedLogError(line));
+              } else
+              {
+                buf.append(getFormattedLog(line));
+              }
+              String summary = isStart?
+                  getFormattedSummary(getMsg("summary-starting")):
+                    getFormattedSummary(getMsg("summary-stopping"));
+              updateProgress(summary, buf.toString());
+              isFirstLine = false;
+
+              line = reader.readLine();
+            }
+          } catch (IOException ioe)
+          {
+            errorMsg = getThrowableMsg(errorTag, ioe);
+
+          } catch (Throwable t)
+          {
+            errorMsg = getThrowableMsg(errorTag, t);
+          }
+        }
+      });
+      t.start();
+    }
+
+    public String getErrorMessage()
+    {
+      return errorMsg;
+    }
+  }
+
+  /**
+   * Displays a confirmation dialog asking the user whether to stop the server
+   * or not.
+   * @return <CODE>true</CODE> if the server confirms that (s)he wants to stop
+   * the server and <CODE>false</CODE> otherwise.
+   */
+  private boolean confirmStop()
+  {
+    return Utils.displayConfirmation(getStatusPanelDialog(),
+        getMsg("confirm-stop-message"), getMsg("confirm-stop-title"));
+  }
+
+  /**
+   * Displays a confirmation dialog asking the user whether to restart the
+   * server or not.
+   * @return <CODE>true</CODE> if the server confirms that (s)he wants to
+   * restart the server and <CODE>false</CODE> otherwise.
+   */
+  private boolean confirmRestart()
+  {
+    return Utils.displayConfirmation(getStatusPanelDialog(),
+        getMsg("confirm-restart-message"), getMsg("confirm-restart-title"));
+  }
+
+  /**
+   * Returns whether the user provided LDAP authentication or not.
+   * @return <CODE>true</CODE> if the server provided LDAP authentication and
+   * <CODE>false</CODE> otherwise.
+   */
+  private boolean isAuthenticated()
+  {
+    return serverStatusPooler.isAuthenticated();
+  }
+
+  private boolean requiresAuthenticationToStop()
+  {
+    boolean requireAuthentication;
+    ServerStatusDescriptor desc = serverStatusPooler.getLastDescriptor();
+    if (desc == null)
+    {
+      requireAuthentication = Utils.isWindows() && !isAuthenticated();
+    }
+    else
+    {
+      requireAuthentication = Utils.isWindows() &&
+      (!isAuthenticated() || desc.getErrorMessage() != null);
+    }
+    return requireAuthentication;
+  }
+
+  private boolean requiresAuthenticationToRestart()
+  {
+    return requiresAuthenticationToStop();
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/StatusPanelLauncher.java b/opends/src/statuspanel/org/opends/statuspanel/StatusPanelLauncher.java
new file mode 100644
index 0000000..cfcd46c
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/StatusPanelLauncher.java
@@ -0,0 +1,178 @@
+/*
+ * 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.statuspanel;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import org.opends.quicksetup.util.Utils;
+import org.opends.statuspanel.i18n.ResourceProvider;
+
+/**
+ * This class is called by the control panel command lines to launch the
+ * control panel of the Directory Server.
+ *
+ */
+public class StatusPanelLauncher
+{
+  private static String COMMAND_NAME_WINDOWS = "statuspanel.bat";
+
+  private static String COMMAND_NAME_UNIX = "statuspanel";
+
+  /**
+   * The main method which is called by the control panel command lines.
+   * @param args the arguments passed by the command lines.
+   */
+  public static void main(String[] args)
+  {
+    boolean printUsage = false;
+    if ((args != null) && (args.length > 4))
+    {
+      printUsage = true;
+    }
+    if (printUsage)
+    {
+      printUsage();
+      System.exit(1);
+
+    } else
+    {
+      int exitCode = launchGuiStatusPanel(args);
+      if (exitCode != 0)
+      {
+        System.err.println(getMsg("status-panel-launcher-gui-launch-failed"));
+        System.exit(exitCode);
+      }
+    }
+  }
+
+  /**
+   * Launches the graphical status panel. It is launched in a
+   * different thread that the main thread because if we have a problem with the
+   * graphical system (for instance the DISPLAY environment variable is not
+   * correctly set) the native libraries will call exit. However if we launch
+   * this from another thread, the thread will just be killed.
+   *
+   * This code also assumes that if the call to SplashWindow.main worked (and
+   * the splash screen was displayed) we will never get out of it (we will call
+   * a System.exit() when we close the graphical uninstall dialog).
+   *
+   * @params String[] args the arguments used to call the SplashWindow main
+   *         method
+   * @return 0 if everything worked fine, or 1 if we could not display properly
+   *         the SplashWindow.
+   */
+  private static int launchGuiStatusPanel(final String[] args)
+  {
+    final int[] returnValue = { -1 };
+    Thread t = new Thread(new Runnable()
+    {
+      public void run()
+      {
+        SplashScreen.main(args);
+        returnValue[0] = 0;
+      }
+    });
+    /*
+     * This is done to avoid displaying the stack that might occur if there are
+     * problems with the display environment.
+     */
+    PrintStream printStream = System.err;
+    //System.setErr(new EmptyPrintStream());
+    t.start();
+    try
+    {
+      t.join();
+    }
+    catch (InterruptedException ie)
+    {
+      /* An error occurred, so the return value will be -1.  We got nothing to
+      do with this exception. */
+    }
+    System.setErr(printStream);
+    return returnValue[0];
+  }
+
+  private static void printUsage()
+  {
+    String arg;
+    if (Utils.isWindows())
+    {
+      arg = COMMAND_NAME_WINDOWS;
+    } else
+    {
+      arg = COMMAND_NAME_UNIX;
+    }
+    /*
+     * This is required because the usage message contains '{' characters that
+     * mess up the MessageFormat.format method.
+     */
+    String msg = getMsg("status-panel-launcher-usage");
+    msg = msg.replace("{0}", arg);
+    System.err.println(msg);
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private static String getMsg(String key)
+  {
+    return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key),
+        Utils.getCommandLineMaxLineWidth());
+  }
+
+  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/statuspanel/org/opends/statuspanel/event/ServerStatusChangeEvent.java b/opends/src/statuspanel/org/opends/statuspanel/event/ServerStatusChangeEvent.java
new file mode 100644
index 0000000..51796ab
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/event/ServerStatusChangeEvent.java
@@ -0,0 +1,63 @@
+/*
+ * 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.statuspanel.event;
+
+import org.opends.statuspanel.ServerStatusDescriptor;
+
+/**
+ * The event that is generated when there is a change of the server status.
+ *
+ * In the current implementation this events are generated by the
+ * ServerStatusPooler object and are notified to the objects implementing
+ * ServerStatusChangeListener (StatusPanelController object).
+ *
+ */
+public class ServerStatusChangeEvent
+{
+  private ServerStatusDescriptor statusDescriptor;
+
+  /**
+   * Constructor of the ServerStatusChangeEvent.
+   * @param statusDescriptor the object describing the current server status
+   * and configuration.
+   */
+  public ServerStatusChangeEvent(ServerStatusDescriptor statusDescriptor)
+  {
+    this.statusDescriptor = statusDescriptor;
+  }
+
+  /**
+   * Returns the ServerStatusDescriptor object.
+   * @return the ServerStatusDescriptor object.
+   */
+  public ServerStatusDescriptor getStatusDescriptor()
+  {
+    return statusDescriptor;
+  }
+
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/event/ServerStatusChangeListener.java b/opends/src/statuspanel/org/opends/statuspanel/event/ServerStatusChangeListener.java
new file mode 100644
index 0000000..0c2a110
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/event/ServerStatusChangeListener.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.statuspanel.event;
+
+/**
+ * Interface that implement the objects that want to receive notifications of
+ * changes in the server status.
+ *
+ */
+public interface ServerStatusChangeListener
+{
+  /**
+   * Method called when an change in the server status occurs.
+   *
+   * @param ev the ServerStatusChangeEvent describing the change that occurred
+   * in the server status.
+   */
+  public void statusChanged(ServerStatusChangeEvent ev);
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/event/StatusPanelButtonListener.java b/opends/src/statuspanel/org/opends/statuspanel/event/StatusPanelButtonListener.java
new file mode 100644
index 0000000..7acb5b3
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/event/StatusPanelButtonListener.java
@@ -0,0 +1,60 @@
+/*
+ * 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.statuspanel.event;
+
+/**
+ * Interface used to be notified of the button actions that can occur in the
+ * StatusPanelDialog.
+ *
+ * In the current implementation StatusPanelController implements this
+ * interface.
+ *
+ */
+public interface StatusPanelButtonListener
+{
+  /**
+   * Method called when user clicks on Authenticate button.
+   */
+  public void authenticateClicked();
+  /**
+   * Method called when user clicks on Start button.
+   */
+  public void startClicked();
+  /**
+   * Method called when user clicks on Restart button.
+   */
+  public void restartClicked();
+  /**
+   * Method called when user clicks on Stop button.
+   */
+  public void stopClicked();
+  /**
+   * Method called when user clicks on Quit button.
+   */
+  public void quitClicked();
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/i18n/ResourceProvider.java b/opends/src/statuspanel/org/opends/statuspanel/i18n/ResourceProvider.java
new file mode 100644
index 0000000..510af41
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/i18n/ResourceProvider.java
@@ -0,0 +1,192 @@
+/*
+ * 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.statuspanel.i18n;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+/**
+ * This class is used to retrieve localized messages from Resources.properties
+ * files.  This class extends org.opends.quicksetup.i18n.ResourceProvider so
+ * that it first looks for properties in the Resources.properties located in
+ * the org.opends.quicksetup.resources package and then if they are not there
+ * looks for properties in org.opends.statuspanel.resources.
+ *
+ * This is done to avoid duplication of properties between the setup and the
+ * status panel.
+ *
+ */
+public class ResourceProvider
+extends org.opends.quicksetup.i18n.ResourceProvider
+{
+  private ResourceBundle bundle;
+
+  private static ResourceProvider instance;
+
+  private static final String BUNDLE_NAME =
+      "org.opends.statuspanel.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
+    {
+      /* First try to quick setup resource provider as it contains most of
+       * the labels.
+       */
+      msg = super.getMsg(key);
+    }
+    catch (Exception ex)
+    {
+      /* Now try with the status panel specific resources.
+       */
+      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
+    {
+      /* First try to quick setup resource provider as it contains most of
+       * the labels.
+       */
+      msg = super.getMsg(key, args);
+    }
+    catch (Exception ex)
+    {
+      /* Now try with the status panel specific resources.
+       */
+      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;
+  }
+
+  /**
+   * 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
+      {
+        bundle =
+          ResourceBundle.getBundle(BUNDLE_NAME, getLocale(), this
+              .getClass().getClassLoader());
+      } catch (java.util.MissingResourceException e)
+      {
+        throw new IllegalStateException("Could not retrieve Resource Bundle: "
+            + BUNDLE_NAME, e);
+
+      }
+    }
+
+    return bundle;
+  }
+}
+
diff --git a/opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties b/opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties
new file mode 100644
index 0000000..404e222
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties
@@ -0,0 +1,179 @@
+# 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
+#
+#
+# This file contains the primary Directory Server configuration.  It must not
+# be directly edited while the server is online.  The server configuration
+# should only be managed using the administration utilities provided with the
+# Directory Server.
+
+#
+# StatusPanel launcher
+#
+status-panel-launcher-usage=This command launches the Status Panel window \
+which displays basic server information and will allow you to start, stop and \
+restart the server.\n\
+Usage:  {0} {options}\n        where {options} include:\n\
+-H  or   --help\n    Displays usage information for this program.
+status-panel-launcher-gui-launch-failed=Could not launch Status Panel.  Check \
+that you have access to the display.
+
+#
+# StatusPanel
+#
+statuspanel-dialog-title=OpenDS Status Panel
+quit-status-panel-button-tooltip=Quit Status Panel
+server-status-title=Server Status
+server-status-label=Server Run Status:
+not-available-label=<not available>
+not-available-server-down-tooltip=<html>Information is only available if \
+server is running and you are authenticated<br>as an administrative user.
+not-available-authentication-required-tooltip=<html>Information is only \
+available if you are authenticated<br>as an administrative user.
+stop-button-label=Stop
+stop-button-tooltip=Stops the Directory Server
+start-button-label=Start
+start-button-tooltip=Starts the Directory Server
+restart-button-label=Restart
+restart-button-tooltip=Restarts the Directory Server
+connections-label=Open Connections:
+server-details-title=Server Details
+administrative-users-label=Administrative Users:
+installation-path-label=Installation Path:
+opends-version-label=OpenDS Version:
+java-version-label=Java Version:
+login-dialog-title=Authentication Required
+login-dialog-windows-msg=You must provide an Administrative User DN and \
+password to retrieve monitoring information and to be able to Stop and Restart \
+the Directory Server.
+server-started-label=Started
+server-stopped-label=Stopped
+server-starting-label=Starting
+server-stopping-label=Stopping
+server-unknown-status-label=Unknown
+cannot-connect-to-login-with-cause=Could not connect to the Directory \
+Server with the provided credentials.  The possible causes for this are:\n{0}
+cannot-connect-to-login-without-cause=Could not connect to the Directory \
+Server with the provided credentials.\nCheck that the Administrative User DN \
+and password are valid.
+error-starting-server-generic=Could not Start server.
+authenticate-button-label=Authenticate
+authenticate-status-panel-button-tooltip=Authenticate as an administrative \
+user to view all monitoring information
+listeners-title=Listener Ports
+address-port-column=Address:Port
+protocol-column=Protocol
+state-column=State
+databases-title=Data Sources
+backendid-column=Backend ID
+basedn-column=Base DN
+number-entries-column=Entries
+enabled-label=Enabled
+disabled-label=Disabled
+unknown-label=--
+ldap-protocol-label=LDAP
+ldaps-protocol-label=LDAPS
+jmx-protocol-label=JMX
+jmx-secure-protocol-label=JMX (Secure)
+undefined-protocol-label=-Unknown-
+error-reading-config-file=Error reading the configuration file.
+could-not-find-valid-ldapurl=Error reading the configuration file.\n\
+This could be caused because there is not an enabled LDAP port to retrieve \
+monitoring information or because you do not have read rights on the \
+configuration file.
+error-reading-config-ldap=Error reading data from server.  Try \
+re-authenticating.\nDetails: {0}
+no-dbs-found=-No LDAP Databases Found-
+no-listeners-found=-No Listener Ports Found-
+
+#
+# Progress Dialog
+#
+close-progress-button-tooltip=Close Progress Dialog
+progress-title=Progress
+summary-starting=Starting Server...
+summary-stopping=Stopping Server...
+summary-start-error=An error occurred Starting Server.  Check 'Details' text \
+area for more information.
+summary-stop-error=An error occurred Stopping Server.  Check 'Details' text \
+area for more information.
+error-starting-server-code=Error Starting Directory Server.  Error code: {0}.
+summary-start-success=OpenDS Started Successfully.
+summary-stop-success=OpenDS Stopped Successfully.
+
+#
+# Confirmation messages
+#
+confirm-stop-message=Are you sure you want to Stop the Directory Server?
+confirm-stop-title=Confirmation Required
+confirm-restart-message=Are you sure you want to Restart the Directory Server?
+confirm-restart-title=Confirmation Required
+
+#
+# Login Dialog
+#
+login-dialog-unix-msg=You must provide an Administrative User DN and password \
+to retrieve monitoring information.
+login-dn-label=Administrative User DN:
+login-dn-tooltip=Enter the distinguished name (DN) of the \
+Administrative User account that will used to retrieve monitoring information
+login-pwd-label=Administrative User Password:
+login-pwd-tooltip=Enter the password of the \
+Administrative User account that will used to retrieve monitoring information
+ok-button-label=OK
+login-dialog-server-not-running-msg=The Directory Server is not running.  \
+Click OK to continue to the Status Panel.
+login-dialog-server-not-running-title=Directory Server not Running
+login-ok-button-tooltip=Proceed with authentication
+login-cancel-button-tooltip=Close Login Dialog
+
+#
+# Status Command Line
+#
+cli-status-root-user-dn-not-provided=You must provide a value for the \
+option -D (or --bindDN)
+cli-status-root-user-pwd-not-provided=You must provide a value for the \
+option -w (or --bindPassword)
+cli-status-root-user-pwd-file-not-provided=You must provide a value for the \
+option -W (or --bindPasswordFile)
+cli-status-unknown-argument=Unknown argument {0}
+cli-status-pwd-and-pwd-file-provided=You cannot provide Bind Password (-w or \
+--bindPassword) and Bind Password File (-W or --bindPasswordFile) at the same \
+time.
+cli-status-error-reading-pwd-file=Could not read the password from \
+file {0}.  Check that the file path is correct, that you have access rights to \
+it and that it contains a password. 
+status-cli-usage=This command displays basic server information.\n\n\
+Usage:  {0} {options}\n        where {options} include:\n\
+-D {bindDN}  or   --bindDN {bindDN}\n    Bind DN\n\
+-w {bindPassword}  or   --bindPassword {bindPassword}\n    Bind password\n\
+-j {bindPasswordFile}  or   --bindPasswordFile {bindPasswordFile}\n    Bind \
+password file\n\
+-H  or   --help\n    Display this usage information.
+not-available-authentication-required-cli-label=<not available> (*)
+not-available-authentication-required-cli-legend=* Information only available \
+if you provide authentication information when launching the status \
+command.
+not-available-server-down-cli-label=<not available> (*)
+not-available-server-down-cli-legend=* Information only available if server is \
+running and you provide authentication information when launching the status \
+command.
\ No newline at end of file
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ui/DatabasesTableModel.java b/opends/src/statuspanel/org/opends/statuspanel/ui/DatabasesTableModel.java
new file mode 100644
index 0000000..3da76fe
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ui/DatabasesTableModel.java
@@ -0,0 +1,274 @@
+/*
+ * 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.statuspanel.ui;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.opends.statuspanel.DatabaseDescriptor;
+import org.opends.statuspanel.i18n.ResourceProvider;
+
+/**
+ * This class is just a table model used to display the information about
+ * databases in a table.
+ *
+ */
+public class DatabasesTableModel extends AbstractTableModel
+implements SortableTableModel, Comparator<DatabaseDescriptor>
+{
+  private static final long serialVersionUID = -5650762484071136983L;
+  private HashSet<DatabaseDescriptor> data = new HashSet<DatabaseDescriptor>();
+  private ArrayList<DatabaseDescriptor> dataArray =
+    new ArrayList<DatabaseDescriptor>();
+  private final String[] COLUMN_NAMES = {
+    getMsg("backendid-column"),
+    getMsg("basedn-column"),
+    getMsg("number-entries-column")
+  };
+  private int sortColumn = 0;
+  private boolean sortAscending = true;
+
+  /**
+   * Sets the data for this table model.
+   * @param newData the data for this table model.
+   */
+  public void setData(Set<DatabaseDescriptor> newData)
+  {
+    if (!newData.equals(data))
+    {
+      data.clear();
+      data.addAll(newData);
+      dataArray.clear();
+      TreeSet<DatabaseDescriptor> sortedSet =
+        new TreeSet<DatabaseDescriptor>(this);
+      sortedSet.addAll(data);
+      dataArray.addAll(sortedSet);
+      fireTableDataChanged();
+    }
+  }
+
+  /**
+   * Updates the table model contents and sorts its contents depending on the
+   * sort options set by the user.
+   */
+  public void forceResort()
+  {
+    dataArray.clear();
+    TreeSet<DatabaseDescriptor> sortedSet =
+      new TreeSet<DatabaseDescriptor>(this);
+    sortedSet.addAll(data);
+    dataArray.addAll(sortedSet);
+    fireTableDataChanged();
+  }
+
+  /**
+   * Comparable implementation.
+   * @param desc1 the first database descriptor to compare.
+   * @param desc2 the second database descriptor to compare.
+   * @return 1 if according to the sorting options set by the user the first
+   * database descriptor must be put before the second descriptor, 0 if they
+   * are equivalent in terms of sorting and -1 if the second descriptor must
+   * be put before the first descriptor.
+   */
+  public int compare(DatabaseDescriptor desc1, DatabaseDescriptor desc2)
+  {
+    int result = 0;
+    if (sortColumn == 0)
+    {
+      result = desc1.getBackendID().compareTo(desc2.getBackendID());
+
+      if (result == 0)
+      {
+        result = desc1.getBaseDn().compareTo(desc2.getBaseDn());
+      }
+
+      if (result == 0)
+      {
+        if (desc1.getEntries() > desc2.getEntries())
+        {
+          result = 1;
+        }
+        else if (desc1.getEntries() < desc2.getEntries())
+        {
+          result = -1;
+        }
+      }
+    }
+    else if (sortColumn == 1)
+    {
+      result = desc1.getBaseDn().compareTo(desc2.getBaseDn());
+
+      if (result == 0)
+      {
+        result = desc1.getBackendID().compareTo(desc2.getBackendID());
+      }
+
+      if (result == 0)
+      {
+        if (desc1.getEntries() > desc2.getEntries())
+        {
+          result = 1;
+        }
+        else if (desc1.getEntries() < desc2.getEntries())
+        {
+          result = -1;
+        }
+      }
+    }
+    else
+    {
+      if (desc1.getEntries() > desc2.getEntries())
+      {
+        result = 1;
+      }
+      else if (desc1.getEntries() < desc2.getEntries())
+      {
+        result = -1;
+      }
+
+      if (result == 0)
+      {
+        result = desc1.getBackendID().compareTo(desc2.getBackendID());
+      }
+
+      if (result == 0)
+      {
+        result = desc1.getBaseDn().compareTo(desc2.getBaseDn());
+      }
+    }
+
+    if (!sortAscending)
+    {
+      result = -result;
+    }
+
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getColumnCount()
+  {
+    return 3;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getRowCount()
+  {
+    return dataArray.size();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Object getValueAt(int row, int col)
+  {
+    Object v;
+    DatabaseDescriptor desc = dataArray.get(row);
+    if (col == 0)
+    {
+      v = desc.getBackendID();
+    }
+    else if (col == 1)
+    {
+      v = desc.getBaseDn();
+    }
+    else
+    {
+      v = new Integer(desc.getEntries());
+    }
+    return v;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getColumnName(int col) {
+    return COLUMN_NAMES[col];
+  }
+
+  /**
+   * Returns whether the sort is ascending or descending.
+   * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean isSortAscending()
+  {
+    return sortAscending;
+  }
+
+  /**
+   * Sets whether to sort ascending of descending.
+   * @param sortAscending whether to sort ascending or descending.
+   */
+  public void setSortAscending(boolean sortAscending)
+  {
+    this.sortAscending = sortAscending;
+  }
+
+  /**
+   * Returns the column index used to sort.
+   * @return the column index used to sort.
+   */
+  public int getSortColumn()
+  {
+    return sortColumn;
+  }
+
+  /**
+   * Sets the column index used to sort.
+   * @param sortColumn column index used to sort..
+   */
+  public void setSortColumn(int sortColumn)
+  {
+    this.sortColumn = sortColumn;
+  }
+
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ui/ListenersTableModel.java b/opends/src/statuspanel/org/opends/statuspanel/ui/ListenersTableModel.java
new file mode 100644
index 0000000..d093eb6
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ui/ListenersTableModel.java
@@ -0,0 +1,272 @@
+/*
+ * 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.statuspanel.ui;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.opends.statuspanel.ListenerDescriptor;
+import org.opends.statuspanel.i18n.ResourceProvider;
+
+/**
+ * This class is just a table model used to display the information about
+ * listeners in a table.
+ *
+ */
+public class ListenersTableModel extends AbstractTableModel
+implements SortableTableModel, Comparator<ListenerDescriptor>
+{
+  private static final long serialVersionUID = -1121308303480078376L;
+  private HashSet<ListenerDescriptor> data = new HashSet<ListenerDescriptor>();
+  private ArrayList<ListenerDescriptor> dataArray =
+    new ArrayList<ListenerDescriptor>();
+  private final String[] COLUMN_NAMES = {
+    getMsg("address-port-column"),
+    getMsg("protocol-column"),
+    getMsg("state-column")
+  };
+  private int sortColumn = 0;
+  private boolean sortAscending = true;
+
+  /**
+   * Sets the data for this table model.
+   * @param newData the data for this table model.
+   */
+  public void setData(Set<ListenerDescriptor> newData)
+  {
+    if (!newData.equals(data))
+    {
+      data.clear();
+      data.addAll(newData);
+      dataArray.clear();
+      TreeSet<ListenerDescriptor> sortedSet =
+        new TreeSet<ListenerDescriptor>(this);
+      sortedSet.addAll(data);
+      dataArray.addAll(sortedSet);
+      fireTableDataChanged();
+    }
+  }
+
+  /**
+   * Updates the table model contents and sorts its contents depending on the
+   * sort options set by the user.
+   */
+  public void forceResort()
+  {
+    dataArray.clear();
+    TreeSet<ListenerDescriptor> sortedSet =
+      new TreeSet<ListenerDescriptor>(this);
+    sortedSet.addAll(data);
+    dataArray.addAll(sortedSet);
+    fireTableDataChanged();
+  }
+
+  /**
+   * Comparable implementation.
+   * @param desc1 the first listener descriptor to compare.
+   * @param desc2 the second listener descriptor to compare.
+   * @return 1 if according to the sorting options set by the user the first
+   * listener descriptor must be put before the second descriptor, 0 if they
+   * are equivalent in terms of sorting and -1 if the second descriptor must
+   * be put before the first descriptor.
+   */
+  public int compare(ListenerDescriptor desc1, ListenerDescriptor desc2)
+  {
+    int result = 0;
+    if (sortColumn == 0)
+    {
+      result = desc1.getAddressPort().compareTo(desc2.getAddressPort());
+
+      if (result == 0)
+      {
+        result = desc1.getProtocolDescription().compareTo(
+            desc2.getProtocolDescription());
+      }
+
+      if (result == 0)
+      {
+        result = desc1.getState().compareTo(desc2.getState());
+      }
+    }
+    else if (sortColumn == 1)
+    {
+      result = desc1.getProtocolDescription().compareTo(
+          desc2.getProtocolDescription());
+
+      if (result == 0)
+      {
+        result = desc1.getAddressPort().compareTo(desc2.getAddressPort());
+      }
+
+      if (result == 0)
+      {
+        result = desc1.getState().compareTo(desc2.getState());
+      }
+    }
+    else
+    {
+      result = desc1.getState().compareTo(desc2.getState());
+
+      if (result == 0)
+      {
+        result = desc1.getAddressPort().compareTo(desc2.getAddressPort());
+      }
+
+      if (result == 0)
+      {
+        result = desc1.getProtocolDescription().compareTo(
+            desc2.getProtocolDescription());
+      }
+    }
+
+    if (!sortAscending)
+    {
+      result = -result;
+    }
+
+    return result;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getColumnCount()
+  {
+    return 3;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getRowCount()
+  {
+    return dataArray.size();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Object getValueAt(int row, int col)
+  {
+    Object v;
+    ListenerDescriptor desc = dataArray.get(row);
+    if (col == 0)
+    {
+      v = desc.getAddressPort();
+    }
+    else if (col == 1)
+    {
+      v = desc.getProtocolDescription().toString();
+    }
+    else
+    {
+      switch (desc.getState())
+      {
+      case ENABLED:
+        v = getMsg("enabled-label");
+        break;
+
+      case DISABLED:
+        v = getMsg("disabled-label");
+        break;
+
+      case UNKNOWN:
+        v = getMsg("unknown-label");
+        break;
+
+        default:
+          throw new IllegalStateException("Unknown state: "+desc.getState());
+      }
+    }
+    return v;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getColumnName(int col) {
+    return COLUMN_NAMES[col];
+  }
+
+
+  /**
+   * Returns whether the sort is ascending or descending.
+   * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean isSortAscending()
+  {
+    return sortAscending;
+  }
+
+  /**
+   * Sets whether to sort ascending of descending.
+   * @param sortAscending whether to sort ascending or descending.
+   */
+  public void setSortAscending(boolean sortAscending)
+  {
+    this.sortAscending = sortAscending;
+  }
+
+  /**
+   * Returns the column index used to sort.
+   * @return the column index used to sort.
+   */
+  public int getSortColumn()
+  {
+    return sortColumn;
+  }
+
+  /**
+   * Sets the column index used to sort.
+   * @param sortColumn column index used to sort..
+   */
+  public void setSortColumn(int sortColumn)
+  {
+    this.sortColumn = sortColumn;
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ui/LoginDialog.java b/opends/src/statuspanel/org/opends/statuspanel/ui/LoginDialog.java
new file mode 100644
index 0000000..cfe48a3
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ui/LoginDialog.java
@@ -0,0 +1,610 @@
+/*
+ * 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.statuspanel.ui;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.naming.NamingException;
+import javax.naming.directory.SearchControls;
+import javax.naming.ldap.InitialLdapContext;
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.event.MinimumSizeComponentListener;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.BackgroundTask;
+import org.opends.quicksetup.util.Utils;
+
+import org.opends.statuspanel.ConfigFromFile;
+import org.opends.statuspanel.i18n.ResourceProvider;
+
+/**
+ * This class is a dialog that appears when the user must provide authentication
+ * to connect to the Directory Server in order to be able to display
+ * information.
+ */
+public class LoginDialog extends JDialog
+{
+  private static final long serialVersionUID = 9049409381101152000L;
+
+  private JFrame parent;
+
+  private JLabel lDn;
+  private JLabel lPwd;
+
+  private JTextField tfDn;
+  private JTextField tfPwd;
+
+  private JButton cancelButton;
+  private JButton okButton;
+
+  private boolean isCancelled = true;
+
+  private ConfigFromFile conf;
+
+  /**
+   * Constructor of the LoginDialog.
+   * @param parent the parent frame for this dialog.
+   */
+  public LoginDialog(JFrame parent)
+  {
+    super(parent);
+    setTitle(getMsg("login-dialog-title"));
+    this.parent = parent;
+    getContentPane().add(createPanel());
+    /*
+     * TODO: find a way to calculate this dynamically.  This is done to avoid
+     * all the text in a single line.
+     */
+    setPreferredSize(new Dimension(500, 250));
+    addComponentListener(new MinimumSizeComponentListener(this, 500, 250));
+    getRootPane().setDefaultButton(okButton);
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if the user clicked on cancel and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if the user clicked on cancel and
+   * <CODE>false</CODE> otherwise.
+   */
+  public boolean isCancelled()
+  {
+    return isCancelled;
+  }
+
+  /**
+   * {@inheritDoc}
+   *
+   */
+  public void setVisible(boolean visible)
+  {
+    cancelButton.setEnabled(true);
+    okButton.setEnabled(true);
+    if (visible)
+    {
+      tfPwd.setText("");
+      tfPwd.requestFocusInWindow();
+      UIFactory.setTextStyle(lDn,
+          UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+      UIFactory.setTextStyle(lPwd,
+          UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+      getRootPane().setDefaultButton(okButton);
+    }
+    super.setVisible(visible);
+  }
+
+  /**
+   * Returns the Directory Manager DN provided by the user.
+   * @return the Directory Manager DN provided by the user.
+   */
+  public String getDirectoryManagerDn()
+  {
+    return tfDn.getText();
+  }
+
+  /**
+   * Returns the Directory Manager password provided by the user.
+   * @return the Directory Manager password provided by the user.
+   */
+  public String getDirectoryManagerPwd()
+  {
+    return tfPwd.getText();
+  }
+
+  /**
+   * Creates and returns the panel of the dialog.
+   * @return the panel of the dialog.
+   */
+  private JPanel createPanel()
+  {
+    JPanel p1 = new JPanel(new GridBagLayout());
+    p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+    p1.setBorder(UIFactory.DIALOG_PANEL_BORDER);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.insets = UIFactory.getCurrentStepPanelInsets();
+    p1.add(UIFactory.makeJLabel(UIFactory.IconType.INFORMATION_LARGE, null,
+        UIFactory.TextStyle.NO_STYLE), gbc);
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets.left = 0;
+    String msg;
+
+    if (Utils.isWindows())
+    {
+      msg = getMsg("login-dialog-windows-msg");
+    }
+    else
+    {
+      msg = getMsg("login-dialog-unix-msg");
+    }
+    JTextComponent textPane =
+      UIFactory.makeHtmlPane(msg, UIFactory.INSTRUCTIONS_FONT);
+    textPane.setOpaque(false);
+    textPane.setEditable(false);
+    p1.add(textPane, gbc);
+
+    JPanel p2 = new JPanel(new GridBagLayout());
+    p2.setOpaque(false);
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    gbc.insets.left = 0;
+    gbc.anchor = GridBagConstraints.WEST;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    lDn = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        getMsg("login-dn-label"),
+        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+    p2.add(lDn, gbc);
+    gbc.weightx = 1.0;
+    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    tfDn = UIFactory.makeJTextField(getProposedAdministrativeUserDn(),
+        getMsg("login-dn-tooltip"),
+        UIFactory.DN_FIELD_SIZE, UIFactory.TextStyle.TEXTFIELD);
+    p2.add(tfDn, gbc);
+
+    gbc.insets.top = 0;
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    gbc.insets.left = 0;
+    lPwd = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        getMsg("login-pwd-label"),
+        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+    p2.add(lPwd, gbc);
+    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    JPanel p3 = new JPanel(new GridBagLayout());
+    p3.setOpaque(false);
+    tfPwd = UIFactory.makeJPasswordField(null,
+        getMsg("login-pwd-tooltip"),
+        UIFactory.PASSWORD_FIELD_SIZE, UIFactory.TextStyle.PASSWORD_FIELD);
+    p2.add(p3, gbc);
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    p3.add(tfPwd, gbc);
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    p3.add(Box.createHorizontalGlue(), gbc);
+
+
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 0.0;
+    gbc.insets.top = 0;
+    p1.add(Box.createHorizontalGlue(), gbc);
+    gbc.weightx = 1.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    p1.add(p2, gbc);
+    gbc.weighty = 1.0;
+    gbc.fill = GridBagConstraints.VERTICAL;
+    p1.add(Box.createVerticalGlue(), gbc);
+
+    JPanel buttonPanel = new JPanel(new GridBagLayout());
+    buttonPanel.setOpaque(false);
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 1.0;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = 3;
+    buttonPanel.add(Box.createHorizontalGlue(), gbc);
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.weightx = 0.0;
+    okButton =
+      UIFactory.makeJButton(getMsg("ok-button-label"),
+          getMsg("login-ok-button-tooltip"));
+    buttonPanel.add(okButton, gbc);
+    okButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        okClicked();
+      }
+    });
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
+    cancelButton =
+      UIFactory.makeJButton(getMsg("cancel-button-label"),
+          getMsg("login-cancel-button-tooltip"));
+    buttonPanel.add(cancelButton, gbc);
+    cancelButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        cancelClicked();
+      }
+    });
+
+    JPanel p = new JPanel(new GridBagLayout());
+    p.setBackground(UIFactory.DEFAULT_BACKGROUND);
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.weighty = 1.0;
+    p.add(p1, gbc);
+    gbc.weighty = 0.0;
+    gbc.insets = UIFactory.getButtonsPanelInsets();
+    p.add(buttonPanel, gbc);
+
+    return p;
+  }
+
+  /**
+   * Returns the first administrative user DN found in the configuration file.
+   * @return the first administrative user DN found in the configuration file.
+   */
+  private String getProposedAdministrativeUserDn()
+  {
+    String dn;
+    Set<String> dns = getAdministrativeUserDns();
+    if (dns.size() > 0)
+    {
+      dn = dns.iterator().next();
+    }
+    else
+    {
+      dn = null;
+    }
+    return dn;
+  }
+
+  /**
+   * Method called when user clicks on cancel.
+   *
+   */
+  private void cancelClicked()
+  {
+    isCancelled = true;
+    dispose();
+  }
+
+  /**
+   * Method called when user clicks on OK.
+   *
+   */
+  private void okClicked()
+  {
+    BackgroundTask worker = new BackgroundTask()
+    {
+      public Object processBackgroundTask() throws NamingException
+      {
+        Boolean isServerRunning = Boolean.TRUE;
+        try
+        {
+          InitialLdapContext ctx = null;
+
+          String ldapUrl = getLDAPURL();
+
+          if (ldapUrl != null)
+          {
+            ctx = Utils.createLdapContext(ldapUrl, tfDn.getText(),
+                  tfPwd.getText(), 3000, null);
+          }
+          else
+          {
+            throw new Error("could-not-find-valid-ldapurl");
+          }
+
+          /*
+           * Search for the config to check that it is the directory manager.
+           */
+          SearchControls searchControls = new SearchControls();
+          searchControls.setCountLimit(1);
+          searchControls.setSearchScope(
+          SearchControls. OBJECT_SCOPE);
+          searchControls.setReturningAttributes(
+          new String[] {"dn"});
+          ctx.search("cn=config", "objectclass=*", searchControls);
+
+        } catch (NamingException ne)
+        {
+          if (isServerRunning())
+          {
+            throw ne;
+          }
+          isServerRunning = Boolean.FALSE;
+        } catch (IllegalStateException ise)
+        {
+          throw ise;
+
+        } catch (Throwable t)
+        {
+          throw new IllegalStateException("Unexpected throwable.", t);
+        }
+        return isServerRunning;
+      }
+
+      public void backgroundTaskCompleted(Object returnValue,
+          Throwable throwable)
+      {
+        if (throwable != null)
+        {
+          if (throwable instanceof NamingException)
+          {
+            boolean dnInvalid = false;
+            boolean pwdInvalid = false;
+
+            String dn = tfDn.getText();
+            ArrayList<String> possibleCauses = new ArrayList<String>();
+            if ("".equals(dn.trim()))
+            {
+              dnInvalid = true;
+              possibleCauses.add(getMsg("empty-directory-manager-dn"));
+            }
+            else if (!Utils.isDn(dn))
+            {
+              dnInvalid = true;
+              possibleCauses.add(getMsg("not-a-directory-manager-dn"));
+            }
+            else
+            {
+              boolean found = false;
+              Iterator<String> it = getAdministrativeUserDns().iterator();
+              while (it.hasNext() && !found)
+              {
+                found = Utils.areDnsEqual(dn, it.next());
+              }
+              if (!found)
+              {
+                dnInvalid = true;
+                possibleCauses.add(getMsg("not-a-directory-manager-in-config"));
+              }
+            }
+
+            if ("".equals(tfPwd.getText()))
+            {
+              pwdInvalid = true;
+              possibleCauses.add(getMsg("empty-pwd"));
+            }
+            if (dnInvalid)
+            {
+              UIFactory.setTextStyle(lDn,
+                UIFactory.TextStyle.PRIMARY_FIELD_INVALID);
+            }
+            else
+            {
+              UIFactory.setTextStyle(lDn,
+                  UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+              pwdInvalid = true;
+            }
+            if (pwdInvalid)
+            {
+              UIFactory.setTextStyle(lPwd,
+                UIFactory.TextStyle.PRIMARY_FIELD_INVALID);
+            }
+            else
+            {
+              UIFactory.setTextStyle(lPwd,
+                  UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+            }
+            if (possibleCauses.size() > 0)
+            {
+              // Message with causes
+              String[] arg = {
+                  Utils.getStringFromCollection(possibleCauses, "\n")
+              };
+              displayError(
+                  getMsg("cannot-connect-to-login-with-cause", arg),
+                  getMsg("error-title"));
+            }
+            else
+            {
+              // Generic message
+              displayError(
+                  getMsg("cannot-connect-to-login-without-cause"),
+                  getMsg("error-title"));
+            }
+          }
+          else if (throwable instanceof Error)
+          {
+            displayError(throwable.getMessage(), getMsg("error-title"));
+          }
+          else
+          {
+            // This is a bug
+            throwable.printStackTrace();
+            displayError(
+                Utils.getThrowableMsg(getI18n(), "bug-msg", null, throwable),
+                getMsg("error-title"));
+          }
+          cancelButton.setEnabled(true);
+          okButton.setEnabled(true);
+        } else
+        {
+          if (Boolean.FALSE.equals(returnValue))
+          {
+            displayInformationMessage(
+                getMsg("login-dialog-server-not-running-msg"),
+                getMsg("login-dialog-server-not-running-title"));
+          }
+          UIFactory.setTextStyle(lDn,
+              UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+          UIFactory.setTextStyle(lPwd,
+              UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+          isCancelled = false;
+          cancelButton.setEnabled(true);
+          okButton.setEnabled(true);
+          dispose();
+        }
+      }
+    };
+    cancelButton.setEnabled(false);
+    okButton.setEnabled(false);
+    worker.startBackgroundTask();
+  }
+
+  /**
+   * Displays an error message dialog.
+   *
+   * @param msg
+   *          the error message.
+   * @param title
+   *          the title for the dialog.
+   */
+  private void displayError(String msg, String title)
+  {
+    Utils.displayError(parent, msg, title);
+    toFront();
+
+  }
+
+  /**
+   * Displays an information message dialog.
+   *
+   * @param msg
+   *          the information message.
+   * @param title
+   *          the title for the dialog.
+   */
+  private void displayInformationMessage(String msg, String title)
+  {
+    Utils.displayInformationMessage(parent, msg, title);
+    toFront();
+  }
+
+  /**
+   * Returns the administrative user DNs found in the config file.
+   * @return the administrative user DNs found in the config file.
+   */
+  private Set<String> getAdministrativeUserDns()
+  {
+    return getConfig().getAdministrativeUsers();
+  }
+
+  /**
+   * Returns whether the server is running or not.
+   * @return <CODE>true</CODE> if the server is running and <CODE>false</CODE>
+   * otherwise.
+   */
+  private boolean isServerRunning()
+  {
+    return Utils.isServerRunning(Utils.getInstallPathFromClasspath());
+  }
+
+  /**
+   * Returns the ldap URL used to log into the server based in the contents
+   * of the config file.
+   * @return the ldap URL used to log into the server based in the contents
+   * of the config file.
+   */
+  private String getLDAPURL()
+  {
+    return getConfig().getLDAPURL();
+  }
+
+  /**
+   * Returns the ConfigFromFile object that contains the configuration read
+   * from the config file.
+   * @return the ConfigFromFile object that contains the configuration read
+   * from the config file.
+   */
+  private ConfigFromFile getConfig()
+  {
+    if (conf == null)
+    {
+      conf = new ConfigFromFile();
+      conf.readConfiguration();
+    }
+    return conf;
+  }
+
+  /* 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();
+  }
+
+  /**
+   * 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();
+      LoginDialog dlg = new LoginDialog(new JFrame());
+      dlg.pack();
+      dlg.setVisible(true);
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ui/ProgressDialog.java b/opends/src/statuspanel/org/opends/statuspanel/ui/ProgressDialog.java
new file mode 100644
index 0000000..e7dcad7
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ui/ProgressDialog.java
@@ -0,0 +1,375 @@
+/*
+ * 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.statuspanel.ui;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+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.JEditorPane;
+import javax.swing.JFrame;
+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.event.MinimumSizeComponentListener;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
+import org.opends.quicksetup.util.ProgressMessageFormatter;
+
+import org.opends.statuspanel.i18n.ResourceProvider;
+
+/**
+ * This panel is used to show the progress of the start/stop/restart operations.
+ *
+ */
+public class ProgressDialog extends JDialog
+{
+  private static final long serialVersionUID = 8635080171100378470L;
+
+  private JEditorPane progressBarLabel;
+
+  private JProgressBar progressBar;
+
+  private JEditorPane detailsTextArea;
+
+  private JScrollPane scroll;
+
+  private String lastText;
+
+  private JFrame parent;
+
+  private JButton closeButton;
+
+  private String panelTitle = getMsg("progress-title");
+
+  private ProgressMessageFormatter formatter =
+    new HtmlProgressMessageFormatter();
+
+  /**
+   * ProgressDialog constructor.
+   * @param frame the parent frame for this dialog.
+   */
+  public ProgressDialog(JFrame frame)
+  {
+    super(frame);
+    this.parent = frame;
+    setTitle(getMsg("statuspanel-dialog-title"));
+    createLayout();
+  }
+
+  /**
+   * Prepares size for this dialog.
+   *
+   */
+  public void pack()
+  {
+    /*
+     * TODO: find a way to calculate this dynamically.
+     */
+    setPreferredSize(new Dimension(500, 300));
+    addComponentListener(new MinimumSizeComponentListener(this, 500, 300));
+    super.pack();
+    closeButton.requestFocusInWindow();
+    getRootPane().setDefaultButton(closeButton);
+  }
+
+  /**
+   * Returns the parent for this dialog.
+   * @return the parent for this dialog.
+   */
+  public JFrame getFrame()
+  {
+    return parent;
+  }
+
+  /**
+   * Sets the title of the panel.
+   * @param title the title of the panel.
+   */
+  public void setPanelTitle(String title)
+  {
+    this.panelTitle = title;
+  }
+
+  /**
+   * Returns the title of the panel.
+   * @return the title of the panel
+   */
+  public String getPanelTitle()
+  {
+    return panelTitle;
+  }
+
+  /**
+   * Sets the enable state of the close button.
+   * @param enable whether to enable or disable the button.
+   */
+  public void setCloseButtonEnabled(boolean enable)
+  {
+    closeButton.setEnabled(enable);
+  }
+
+  /**
+   * Sets the text in the summary label.  The text can be in HTML format.
+   * @param text the text to be set.
+   */
+  public void setSummary(String text)
+  {
+    progressBarLabel.setText(text);
+  }
+
+  /**
+   * Sets the text in the details text pane.  The text can be in HTML format.
+   * @param text the text to be set.
+   */
+  public void setDetails(String text)
+  {
+    detailsTextArea.setText(text);
+  }
+
+  /**
+   * Returns the formatter that will be used to display the messages in this
+   * panel.
+   * @return the formatter that will be used to display the messages in this
+   * panel.
+   */
+  private ProgressMessageFormatter getFormatter()
+  {
+    if (formatter == null)
+    {
+      formatter = new HtmlProgressMessageFormatter();
+    }
+    return formatter;
+  }
+
+  /**
+   * Creates the layout of the dialog panel.
+   *
+   */
+  private void createLayout()
+  {
+    /* Create title panel */
+    JPanel titlePanel = new JPanel(new GridBagLayout());
+    titlePanel.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 0.0;
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+
+    String title = getPanelTitle();
+
+    JLabel l =
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title,
+            UIFactory.TextStyle.TITLE);
+    l.setOpaque(false);
+    titlePanel.add(l, gbc);
+
+    gbc.weightx = 1.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    titlePanel.add(Box.createHorizontalGlue(), gbc);
+
+    /* Create input panel. */
+    JPanel mainPanel = new JPanel(new GridBagLayout());
+    mainPanel.setOpaque(false);
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    mainPanel.add(titlePanel, gbc);
+
+    gbc.insets.top = UIFactory.TOP_INSET_INSTRUCTIONS_SUBPANEL;
+    progressBarLabel =
+        UIFactory.makeHtmlPane(getMsg("progressbar-initial-label"),
+            UIFactory.PROGRESS_FONT);
+    progressBarLabel.setOpaque(false);
+    progressBarLabel.setEditable(false);
+    mainPanel.add(progressBarLabel, gbc);
+
+    gbc.insets.top = UIFactory.TOP_INSET_PROGRESS_BAR;
+    gbc.insets.bottom = UIFactory.BOTTOM_INSET_PROGRESS_BAR;
+    mainPanel.add(createProgressBarPanel(), gbc);
+    progressBar.setToolTipText(getMsg("progressbar-tooltip"));
+
+    l =
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+            getMsg("progress-details-label"),
+            UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+
+    gbc.insets = UIFactory.getEmptyInsets();
+    mainPanel.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 = getFormatter().getFormattedAfterUrlClick(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;
+    mainPanel.add(scroll, gbc);
+
+    /* Create buttons panel */
+    JPanel buttonsPanel = new JPanel(new GridBagLayout());
+    buttonsPanel.setBackground(UIFactory.DEFAULT_BACKGROUND);
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 1.0;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    buttonsPanel.add(Box.createHorizontalGlue(), gbc);
+    closeButton =
+        UIFactory.makeJButton(getMsg("close-button-label"),
+            getMsg("close-progress-button-tooltip"));
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.weightx = 0.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    buttonsPanel.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;
+    gbc.insets = UIFactory.getEmptyInsets();
+    JPanel p1 = new JPanel(new GridBagLayout());
+    p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+    p1.setBorder(UIFactory.DIALOG_PANEL_BORDER);
+    gbc.insets = UIFactory.getCurrentStepPanelInsets();
+    p1.add(mainPanel, gbc);
+    gbc.insets = UIFactory.getEmptyInsets();
+    p.add(p1, gbc);
+    gbc.weighty = 0.0;
+    gbc.insets = UIFactory.getButtonsPanelInsets();
+    p.add(buttonsPanel, gbc);
+
+    getContentPane().add(p);
+  }
+
+  /**
+   * 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;
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  /**
+   * Method written for testing purposes.
+   * @param args the arguments to be passed to the test program.
+   */
+  public static void main(String[] args)
+  {
+    try
+    {
+      ProgressDialog dlg = new ProgressDialog(new JFrame());
+      dlg.pack();
+      dlg.setVisible(true);
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ui/SortableTableModel.java b/opends/src/statuspanel/org/opends/statuspanel/ui/SortableTableModel.java
new file mode 100644
index 0000000..ea556c9
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ui/SortableTableModel.java
@@ -0,0 +1,67 @@
+/*
+ * 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.statuspanel.ui;
+
+import javax.swing.table.TableModel;
+
+/**
+ * A generic interface that must implement table models that are sortable.
+ */
+interface SortableTableModel extends TableModel
+{
+  /**
+   * Returns whether the sort is ascending or descending.
+   * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean isSortAscending();
+
+  /**
+   * Sets whether to sort ascending of descending.
+   * @param sortAscending whether to sort ascending or descending.
+   */
+  public void setSortAscending(boolean sortAscending);
+
+  /**
+   * Returns the column index used to sort.
+   * @return the column index used to sort.
+   */
+  public int getSortColumn();
+
+  /**
+   * Sets the column index used to sort.
+   * @param sortColumn column index used to sort..
+   */
+  public void setSortColumn(int sortColumn);
+
+  /**
+   * Updates the table model contents and sorts its contents depending on the
+   * sort options set by the user.
+   */
+  public void forceResort();
+}
diff --git a/opends/src/statuspanel/org/opends/statuspanel/ui/StatusPanelDialog.java b/opends/src/statuspanel/org/opends/statuspanel/ui/StatusPanelDialog.java
new file mode 100644
index 0000000..9cea3bb
--- /dev/null
+++ b/opends/src/statuspanel/org/opends/statuspanel/ui/StatusPanelDialog.java
@@ -0,0 +1,1459 @@
+/*
+ * 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.statuspanel.ui;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JToolTip;
+import javax.swing.Popup;
+import javax.swing.PopupFactory;
+import javax.swing.SwingConstants;
+import javax.swing.ToolTipManager;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+
+import org.opends.quicksetup.event.MinimumSizeComponentListener;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
+import org.opends.quicksetup.util.Utils;
+
+import org.opends.statuspanel.ServerStatusDescriptor;
+import org.opends.statuspanel.event.StatusPanelButtonListener;
+import org.opends.statuspanel.i18n.ResourceProvider;
+
+/**
+ * This panel is used to display basic information about the server status.
+ *
+ */
+public class StatusPanelDialog extends JFrame
+{
+  private static final long serialVersionUID = 6832422469078074151L;
+
+  private ServerStatusDescriptor lastDescriptor;
+
+  private HashSet<StatusPanelButtonListener> listeners =
+    new HashSet<StatusPanelButtonListener>();
+
+  private JButton quitButton;
+  private JButton authenticateButton;
+
+  private JLabel lServerStatus;
+  private JLabel lCurrentConnections;
+  private JLabel lAdministrativeUsers;
+  private JLabel lInstallPath;
+  private JLabel lOpenDSVersion;
+  private JLabel lJavaVersion;
+  private JLabel lDbTableEmpty;
+  private JLabel lListenersTableEmpty;
+  private JEditorPane lError;
+
+  private JButton stopButton;
+  private JButton startButton;
+  private JButton restartButton;
+
+  private HtmlProgressMessageFormatter formatter =
+    new HtmlProgressMessageFormatter();
+
+  private HashSet<JLabel> subsectionLabels = new HashSet<JLabel>();
+
+  private DatabasesTableModel dbTableModel;
+  private JTable dbTable;
+
+  private ListenersTableModel listenersTableModel;
+  private JTable listenersTable;
+
+  private InstantaneousToolTipManager toolTipManager;
+
+  private final String NOT_AVAILABLE = getMsg("not-available-label");
+
+  private final int MAXIMAL_WIDTH = 1000;
+  private final int MAXIMAL_HEIGHT = 1000;
+
+  /**
+   * ProgressDialog constructor.
+   */
+  public StatusPanelDialog()
+  {
+    super();
+    setTitle(getMsg("statuspanel-dialog-title"));
+    createLayout();
+
+    addWindowListener(new WindowAdapter()
+    {
+      public void windowClosing(WindowEvent e)
+      {
+        quitClicked();
+      }
+    });
+    setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+    UIFactory.IconType ic;
+    if (Utils.isMacOS())
+    {
+      ic = UIFactory.IconType.MINIMIZED_MAC;
+    } else
+    {
+      ic = UIFactory.IconType.MINIMIZED;
+    }
+    setIconImage(UIFactory.getImageIcon(ic).getImage());
+  }
+
+  /**
+   * Packs and displays this dialog.
+   *
+   */
+  public void packAndShow()
+  {
+    pack();
+    int packedMinWidth = (int) getPreferredSize().getWidth();
+    int packedMinHeight = (int) getPreferredSize().getHeight();
+
+    int minWidth = Math.min(packedMinWidth, MAXIMAL_WIDTH);
+    int minHeight = Math.min(packedMinHeight, MAXIMAL_HEIGHT);
+
+
+    addComponentListener(new MinimumSizeComponentListener(this,
+        minWidth, minHeight));
+    if ((minWidth != packedMinWidth) || (minHeight != packedMinHeight))
+    {
+      setPreferredSize(new Dimension(minWidth, minHeight));
+      pack();
+    }
+    Utils.centerOnScreen(this);
+
+    setVisible(true);
+  }
+
+  /**
+   * Updates the contents displaying with what is specified in the provided
+   * ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  public void updateContents(ServerStatusDescriptor desc)
+  {
+    lastDescriptor = desc;
+
+    updateStatusContents(desc);
+
+    updateCurrentConnectionContents(desc);
+
+    updateAdministrativeUserContents(desc);
+
+    updateInstallPathContents(desc);
+
+    updateVersionContents(desc);
+
+    updateJavaVersionContents(desc);
+
+    updateListenerContents(desc);
+
+    updateDatabaseContents(desc);
+
+    updateErrorContents(desc);
+  }
+
+  /**
+   * Adds a StatusPanelButtonListener that will be notified of clicks in
+   * the control panel dialog.
+   * @param l the StatusPanelButtonListener to be added.
+   */
+  public void addButtonListener(StatusPanelButtonListener l)
+  {
+    listeners.add(l);
+  }
+
+  /**
+   * Removes a StatusPanelButtonListener.
+   * @param l the StatusPanelButtonListener to be removed.
+   */
+  public void removeButtonListener(StatusPanelButtonListener l)
+  {
+    listeners.remove(l);
+  }
+
+  /**
+   * Sets the enable state of the authenticate button.
+   * @param enable whether to enable or disable the button.
+   */
+  public void setAuthenticateButtonEnabled(boolean enable)
+  {
+    authenticateButton.setEnabled(enable);
+  }
+
+  /**
+   * Sets the enable state of the start button.
+   * @param enable whether to enable or disable the button.
+   */
+  public void setStartButtonEnabled(boolean enable)
+  {
+    startButton.setEnabled(enable);
+  }
+
+  /**
+   * Sets the enable state of the stop button.
+   * @param enable whether to enable or disable the button.
+   */
+  public void setStopButtonEnabled(boolean enable)
+  {
+    stopButton.setEnabled(enable);
+  }
+
+  /**
+   * Sets the enable state of the restart button.
+   * @param enable whether to enable or disable the button.
+   */
+  public void setRestartButtonEnabled(boolean enable)
+  {
+    restartButton.setEnabled(enable);
+  }
+
+  /**
+   * Creates the layout of the dialog panel.
+   *
+   */
+  private void createLayout()
+  {
+    toolTipManager = new InstantaneousToolTipManager();
+
+    /* Create input panel. */
+    JPanel inputPanel = new JPanel(new GridBagLayout());
+    inputPanel.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;
+
+    gbc.insets.bottom = UIFactory.BOTTOM_INSET_PROGRESS_BAR;
+    lError = UIFactory.makeHtmlPane("", UIFactory.PROGRESS_FONT);
+    lError.setOpaque(false);
+    lError.setEditable(false);
+    inputPanel.add(lError, gbc);
+    gbc.insets.bottom = 0;
+    gbc.insets.top = UIFactory.TOP_INSET_CONTROL_PANEL_SUBSECTION -
+    UIFactory.getCurrentStepPanelInsets().top;
+    inputPanel.add(createServerStatusPanel(), gbc);
+
+    inputPanel.add(createServerDetailsPanel(), gbc);
+
+    inputPanel.add(createListenersPanel(), gbc);
+
+    inputPanel.add(createDatabasesPanel(), gbc);
+
+    gbc.weighty = 1.0;
+    inputPanel.add(Box.createVerticalGlue(), gbc);
+
+    /* Create buttons panel */
+    JPanel buttonsPanel = new JPanel(new GridBagLayout());
+    buttonsPanel.setOpaque(false);
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.anchor = GridBagConstraints.SOUTH;
+    gbc.gridwidth = 4;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.insets.left = UIFactory.getCurrentStepPanelInsets().left;
+    buttonsPanel.add(UIFactory.makeJLabel(UIFactory.IconType.OPENDS_SMALL,
+        null, UIFactory.TextStyle.NO_STYLE), gbc);
+    gbc.weightx = 1.0;
+    gbc.gridwidth--;
+    gbc.insets.left = 0;
+    buttonsPanel.add(Box.createHorizontalGlue(), gbc);
+
+    authenticateButton =
+      UIFactory.makeJButton(getMsg("authenticate-button-label"),
+          getMsg("authenticate-status-panel-button-tooltip"));
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.weightx = 0.0;
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    buttonsPanel.add(authenticateButton, gbc);
+    authenticateButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        authenticateClicked();
+      }
+    });
+
+    quitButton =
+        UIFactory.makeJButton(getMsg("quit-button-label"),
+            getMsg("quit-status-panel-button-tooltip"));
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.weightx = 0.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
+    buttonsPanel.add(quitButton, gbc);
+    quitButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        quitClicked();
+      }
+    });
+
+    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;
+    JPanel p1 = new JPanel(new GridBagLayout());
+    p1.setBorder(UIFactory.DIALOG_PANEL_BORDER);
+    p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+    gbc.insets = UIFactory.getCurrentStepPanelInsets();
+    p1.add(inputPanel, gbc);
+    gbc.insets = UIFactory.getEmptyInsets();
+    p.add(new JScrollPane(p1), gbc);
+    gbc.weighty = 0.0;
+    gbc.insets = UIFactory.getButtonsPanelInsets();
+    p.add(buttonsPanel, gbc);
+
+    getContentPane().add(p);
+
+    /* Update the preferred sizes of labels */
+    int maxWidth = 0;
+    for (JLabel l : subsectionLabels)
+    {
+      int width = (int) l.getPreferredSize().getWidth();
+
+      if (maxWidth <= width)
+      {
+        maxWidth = width;
+      }
+    }
+
+    for (JLabel l : subsectionLabels)
+    {
+      int height = (int) l.getPreferredSize().getHeight();
+
+      l.setPreferredSize(new Dimension(maxWidth, height));
+    }
+  }
+
+
+  /**
+   * Method called when start button is clicked.
+   */
+  private void startClicked()
+  {
+    for (StatusPanelButtonListener l : listeners)
+    {
+      l.startClicked();
+    }
+  }
+
+  /**
+   * Method called when quit button is clicked.
+   */
+  private void quitClicked()
+  {
+    for (StatusPanelButtonListener l : listeners)
+    {
+      l.quitClicked();
+    }
+  }
+
+  /**
+   * Method called when authenticate button is clicked.
+   */
+  private void authenticateClicked()
+  {
+    for (StatusPanelButtonListener l : listeners)
+    {
+      l.authenticateClicked();
+    }
+  }
+
+  /**
+   * Method called when stop button is clicked.
+   */
+  private void stopClicked()
+  {
+    for (StatusPanelButtonListener l : listeners)
+    {
+      l.stopClicked();
+    }
+  }
+
+  /**
+   * Method called when restart button is clicked.
+   */
+  private void restartClicked()
+  {
+    for (StatusPanelButtonListener l : listeners)
+    {
+      l.restartClicked();
+    }
+  }
+
+  /**
+   * Method usedto create the subsection title with two decoration icons
+   * surrounding the text.
+   * @param title the title of the subsection.
+   */
+  private JPanel createSubsectionTitle(String title)
+  {
+    JPanel p = new JPanel(new GridBagLayout());
+    p.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = 5;
+    gbc.weightx  = 0.5;
+    p.add(Box.createHorizontalGlue(), gbc);
+    gbc.weightx = 0.0;
+    gbc.gridwidth--;
+    p.add(UIFactory.makeJLabel(UIFactory.IconType.SUBSECTION_LEFT, null,
+        UIFactory.TextStyle.NO_STYLE), gbc);
+    gbc.weightx = 0.0;
+    gbc.gridwidth--;
+    gbc.insets.left = UIFactory.HORIZONTAL_INSET_CONTROL_PANEL_SUBSECTION;
+    JLabel l = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title,
+        UIFactory.TextStyle.TITLE);
+    l.setHorizontalAlignment(SwingConstants.CENTER);
+    subsectionLabels.add(l);
+    p.add(l, gbc);
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    p.add(UIFactory.makeJLabel(UIFactory.IconType.SUBSECTION_RIGHT, null,
+        UIFactory.TextStyle.NO_STYLE), gbc);
+    gbc.weightx = 0.5;
+    gbc.insets.left = 0;
+    p.add(Box.createHorizontalGlue(), gbc);
+
+    return p;
+  }
+
+  /**
+   * Creates the server status subsection panel.
+   * @return the server status subsection panel.
+   */
+  private JPanel createServerStatusPanel()
+  {
+    JPanel p = new JPanel(new GridBagLayout());
+    p.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.insets = UIFactory.getEmptyInsets();
+
+    p.add(createSubsectionTitle(getMsg("server-status-title")), gbc);
+
+    JPanel auxPanel = new JPanel(new GridBagLayout());
+    auxPanel.setOpaque(false);
+    gbc.anchor = GridBagConstraints.WEST;
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        getMsg("server-status-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID),
+        gbc);
+
+    JPanel statusPanel = new JPanel(new GridBagLayout());
+    statusPanel.setOpaque(false);
+    gbc.gridwidth = 6;
+    gbc.weightx = 0.0;
+    lServerStatus = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY);
+    statusPanel.add(lServerStatus, gbc);
+    toolTipManager.registerComponent(lServerStatus);
+    gbc.gridwidth--;
+
+    stopButton = UIFactory.makeJButton(getMsg("stop-button-label"),
+        getMsg("stop-button-tooltip"));
+    stopButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        stopClicked();
+      }
+    });
+    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+    statusPanel.add(stopButton, gbc);
+
+    gbc.gridwidth--;
+    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
+    startButton = UIFactory.makeJButton(getMsg("start-button-label"),
+        getMsg("start-button-tooltip"));
+    statusPanel.add(startButton, gbc);
+    startButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        startClicked();
+      }
+    });
+
+    gbc.gridwidth--;
+    restartButton = UIFactory.makeJButton(getMsg("restart-button-label"),
+        getMsg("restart-button-tooltip"));
+    restartButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        restartClicked();
+      }
+    });
+    statusPanel.add(restartButton, gbc);
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.weightx = 1.0;
+    gbc.insets.left = 0;
+    statusPanel.add(Box.createHorizontalGlue(), gbc);
+
+    int maxButtonHeight = 0;
+    maxButtonHeight = Math.max(maxButtonHeight,
+        (int)startButton.getPreferredSize().getHeight());
+    maxButtonHeight = Math.max(maxButtonHeight,
+        (int)restartButton.getPreferredSize().getHeight());
+    maxButtonHeight = Math.max(maxButtonHeight,
+        (int)stopButton.getPreferredSize().getHeight());
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 0.0;
+    statusPanel.add(Box.createVerticalStrut(maxButtonHeight), gbc);
+
+    gbc.weightx = 1.0;
+    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+    auxPanel.add(statusPanel, gbc);
+
+    gbc.insets.left = 0;
+    gbc.weightx = 0.0;
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        getMsg("connections-label"), UIFactory.TextStyle.PRIMARY_FIELD_VALID),
+        gbc);
+    lCurrentConnections = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY);
+    toolTipManager.registerComponent(lCurrentConnections);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+    auxPanel.add(lCurrentConnections, gbc);
+
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    gbc.insets.left = 0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    p.add(auxPanel, gbc);
+
+    return p;
+  }
+
+  /**
+   * Creates the server details subsection panel.
+   * @return the server details subsection panel.
+   */
+  private JPanel createServerDetailsPanel()
+  {
+    JPanel p = new JPanel(new GridBagLayout());
+    p.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+
+    p.add(createSubsectionTitle(getMsg("server-details-title")), gbc);
+
+    JPanel auxPanel = new JPanel(new GridBagLayout());
+    auxPanel.setOpaque(false);
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.weightx = 0.0;
+    JLabel[] leftLabels =
+      {
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+            getMsg("administrative-users-label"),
+            UIFactory.TextStyle.PRIMARY_FIELD_VALID),
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+            getMsg("installation-path-label"),
+            UIFactory.TextStyle.PRIMARY_FIELD_VALID),
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+            getMsg("opends-version-label"),
+            UIFactory.TextStyle.PRIMARY_FIELD_VALID),
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+            getMsg("java-version-label"),
+            UIFactory.TextStyle.PRIMARY_FIELD_VALID)
+      };
+
+    lAdministrativeUsers = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY);
+    lInstallPath = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY);
+    lOpenDSVersion = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY);
+    lJavaVersion = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+        NOT_AVAILABLE, UIFactory.TextStyle.READ_ONLY);
+
+    JLabel[] rightLabels =
+      {
+        lAdministrativeUsers, lInstallPath, lOpenDSVersion, lJavaVersion
+      };
+
+
+    for (int i=0; i<leftLabels.length; i++)
+    {
+      gbc.insets.left = 0;
+      if (i != 0)
+      {
+        gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+      }
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+      auxPanel.add(leftLabels[i], gbc);
+
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+      auxPanel.add(rightLabels[i], gbc);
+      toolTipManager.registerComponent(rightLabels[i]);
+    }
+
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    gbc.insets.left = 0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    p.add(auxPanel, gbc);
+
+    return p;
+  }
+
+  /**
+   * Creates the server listeners subsection panel.
+   * @return the server listeners subsection panel.
+   */
+  private JPanel createListenersPanel()
+  {
+    JPanel p = new JPanel(new GridBagLayout());
+    p.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+
+    p.add(createSubsectionTitle(getMsg("listeners-title")), gbc);
+
+    listenersTableModel = new ListenersTableModel();
+    listenersTable = createTable(listenersTableModel,
+        new ListenersCellRenderer(),
+        new HeaderRenderer());
+
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    p.add(listenersTable.getTableHeader(), gbc);
+    int height = (int)
+    listenersTable.getTableHeader().getPreferredSize().getHeight();
+    listenersTable.setRowHeight(height);
+    gbc.insets.top = 0;
+    p.add(listenersTable, gbc);
+
+    lListenersTableEmpty = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, "",
+        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    p.add(lListenersTableEmpty, gbc);
+    lListenersTableEmpty.setVisible(false);
+    toolTipManager.registerComponent(lListenersTableEmpty);
+    return p;
+  }
+
+  /**
+   * Creates the server databases subsection panel.
+   * @return the server databases subsection panel.
+   */
+  private JPanel createDatabasesPanel()
+  {
+    JPanel p = new JPanel(new GridBagLayout());
+    p.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+
+    p.add(createSubsectionTitle(getMsg("databases-title")), gbc);
+
+    dbTableModel = new DatabasesTableModel();
+    dbTable = createTable(dbTableModel, new DatabasesCellRenderer(),
+        new HeaderRenderer());
+    toolTipManager.registerComponent(dbTable);
+
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    p.add(dbTable.getTableHeader(), gbc);
+    int height = (int)dbTable.getTableHeader().getPreferredSize().getHeight();
+    dbTable.setRowHeight(height);
+    gbc.insets.top = 0;
+    p.add(dbTable, gbc);
+
+    gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+    lDbTableEmpty = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, "",
+        UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+    p.add(lDbTableEmpty, gbc);
+    lDbTableEmpty.setVisible(false);
+    toolTipManager.registerComponent(lDbTableEmpty);
+    return p;
+  }
+
+
+  /**
+   * Sets the not available text to a label and associates a help icon and
+   * a tooltip explaining that the data is not available because the server is
+   * down.
+   * @param l the label.
+   */
+  private void setNotAvailableBecauseServerIsDown(JLabel l)
+  {
+    l.setText(NOT_AVAILABLE);
+    l.setIcon(UIFactory.getImageIcon(UIFactory.IconType.HELP_SMALL));
+    l.setToolTipText(getMsg("not-available-server-down-tooltip"));
+    l.setHorizontalTextPosition(SwingConstants.LEFT);
+  }
+
+  /**
+   * Sets the not available text to a label and associates a help icon and
+   * a tooltip explaining that the data is not available because authentication
+   * is required.
+   * @param l the label.
+   */
+  private void setNotAvailableBecauseAuthenticationIsRequired(JLabel l)
+  {
+    l.setText(NOT_AVAILABLE);
+    l.setIcon(UIFactory.getImageIcon(UIFactory.IconType.HELP_SMALL));
+    l.setToolTipText(getMsg("not-available-authentication-required-tooltip"));
+    l.setHorizontalTextPosition(SwingConstants.LEFT);
+  }
+
+  /**
+   * Sets the not available text to a label with no icon nor tooltip.
+   * @param l the label.
+   */
+  private void setNotAvailable(JLabel l)
+  {
+    l.setText(NOT_AVAILABLE);
+    l.setIcon(null);
+    l.setToolTipText(null);
+  }
+
+  /**
+   * Sets the a text to a label with no icon nor tooltip.
+   * @param l the label.
+   */
+  private void setTextValue(JLabel l, String text)
+  {
+    l.setText(text);
+    l.setIcon(null);
+    l.setToolTipText(null);
+  }
+
+  /**
+   * Returns a table created with the provided model and renderers.
+   * @param tableModel the table model.
+   * @param renderer the cell renderer.
+   * @param headerRenderer the header renderer.
+   * @return a table created with the provided model and renderers.
+   */
+  private JTable createTable(final SortableTableModel tableModel,
+      TableCellRenderer renderer,
+      TableCellRenderer headerRenderer)
+  {
+    final JTable table = new JTable(tableModel);
+    table.setShowGrid(true);
+    table.setGridColor(UIFactory.PANEL_BORDER_COLOR);
+    table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
+    table.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+    table.getTableHeader().setBackground(UIFactory.DEFAULT_BACKGROUND);
+    table.setRowMargin(0);
+
+    for (int i=0; i<tableModel.getColumnCount(); i++)
+    {
+      TableColumn col = table.getColumn(table.getColumnName(i));
+      col.setCellRenderer(renderer);
+      col.setHeaderRenderer(headerRenderer);
+    }
+    MouseAdapter listMouseListener = new MouseAdapter() {
+      public void mouseClicked(MouseEvent e) {
+        TableColumnModel columnModel = table.getColumnModel();
+        int viewColumn = columnModel.getColumnIndexAtX(e.getX());
+        int sortedBy = table.convertColumnIndexToModel(viewColumn);
+        if (e.getClickCount() == 1 && sortedBy != -1) {
+          tableModel.setSortAscending(!tableModel.isSortAscending());
+          tableModel.setSortColumn(sortedBy);
+          tableModel.forceResort();
+        }
+      }
+    };
+    table.getTableHeader().addMouseListener(listMouseListener);
+    return table;
+  }
+
+  /**
+   * Updates the status contents displaying with what is specified in the
+   * provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateStatusContents(ServerStatusDescriptor desc)
+  {
+    String status;
+    switch (desc.getStatus())
+    {
+    case STARTED:
+      status = getMsg("server-started-label");
+      startButton.setVisible(false);
+      restartButton.setVisible(true);
+      stopButton.setVisible(true);
+      break;
+
+    case STOPPED:
+      status = getMsg("server-stopped-label");
+      startButton.setVisible(true);
+      restartButton.setVisible(false);
+      stopButton.setVisible(false);
+      break;
+
+    case STARTING:
+      status = getMsg("server-starting-label");
+      startButton.setVisible(false);
+      restartButton.setVisible(false);
+      stopButton.setVisible(false);
+      break;
+
+    case STOPPING:
+      status = getMsg("server-stopping-label");
+      startButton.setVisible(false);
+      restartButton.setVisible(false);
+      stopButton.setVisible(false);
+      break;
+
+    case UNKNOWN:
+      status = getMsg("server-unknown-status-label");
+      startButton.setVisible(false);
+      restartButton.setVisible(true);
+      stopButton.setVisible(true);
+      break;
+
+    default:
+      throw new IllegalStateException("Unknown status: "+desc.getStatus());
+    }
+    lServerStatus.setText(status);
+
+    /* Enable authenticate button only if the server is started AND we have
+     * no authentication (or the authentication we have does not seem to work
+     * because we get an error).
+     */
+    authenticateButton.setVisible(
+        (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED) &&
+        (!desc.isAuthenticated() || (desc.getErrorMessage() != null)));
+  }
+
+  /**
+   * Updates the current connection contents displaying with what is specified
+   * in the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateCurrentConnectionContents(ServerStatusDescriptor desc)
+  {
+    if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+    {
+      int nConn = desc.getOpenConnections();
+      if (nConn >= 0)
+      {
+        setTextValue(lCurrentConnections, String.valueOf(nConn));
+      }
+      else
+      {
+        if (!desc.isAuthenticated())
+        {
+          setNotAvailableBecauseAuthenticationIsRequired(lCurrentConnections);
+        }
+        else
+        {
+          setNotAvailable(lCurrentConnections);
+        }
+      }
+    }
+    else
+    {
+      setNotAvailableBecauseServerIsDown(lCurrentConnections);
+    }
+  }
+
+  /**
+   * Updates the admiinistrative user contents displaying with what is specified
+   * in the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateAdministrativeUserContents(ServerStatusDescriptor desc)
+  {
+    Set<String> administrators = desc.getAdministrativeUsers();
+    if (administrators.size() > 0)
+    {
+      TreeSet<String> ordered = new TreeSet<String>();
+      for (String name: administrators)
+      {
+        ordered.add(formatter.getFormattedText(name));
+      }
+
+      setTextValue(lAdministrativeUsers,"<html>"+
+          Utils.getStringFromCollection(ordered, "<br>"));
+    }
+    else
+    {
+      if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+      {
+        if (!desc.isAuthenticated())
+        {
+          setNotAvailableBecauseAuthenticationIsRequired(lAdministrativeUsers);
+        }
+        else
+        {
+          setNotAvailable(lAdministrativeUsers);
+        }
+      }
+      else
+      {
+        setNotAvailable(lAdministrativeUsers);
+      }
+    }
+  }
+
+  /**
+   * Updates the install path contents displaying with what is specified in the
+   * provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateInstallPathContents(ServerStatusDescriptor desc)
+  {
+    File path = desc.getInstallPath();
+    lInstallPath.setText(path.toString());
+  }
+
+  /**
+   * Updates the server version contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateVersionContents(ServerStatusDescriptor desc)
+  {
+    String openDSVersion = desc.getOpenDSVersion();
+    lOpenDSVersion.setText(openDSVersion);
+  }
+
+  /**
+   * Updates the java version contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateJavaVersionContents(ServerStatusDescriptor desc)
+  {
+    if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+    {
+      String javaVersion = desc.getJavaVersion();
+      if (javaVersion != null)
+      {
+        setTextValue(lJavaVersion, javaVersion);
+
+      }
+      else
+      {
+        if (!desc.isAuthenticated())
+        {
+          setNotAvailableBecauseAuthenticationIsRequired(lJavaVersion);
+        }
+        else
+        {
+          setNotAvailable(lJavaVersion);
+        }
+      }
+    }
+    else
+    {
+      setNotAvailableBecauseServerIsDown(lJavaVersion);
+    }
+  }
+
+  /**
+   * Updates the listeners contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateListenerContents(ServerStatusDescriptor desc)
+  {
+    listenersTableModel.setData(desc.getListeners());
+
+    if (listenersTableModel.getRowCount() == 0)
+    {
+      listenersTable.setVisible(false);
+      listenersTable.getTableHeader().setVisible(false);
+      lListenersTableEmpty.setVisible(true);
+      if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+      {
+        if (!desc.isAuthenticated())
+        {
+          setNotAvailableBecauseAuthenticationIsRequired(lListenersTableEmpty);
+        }
+        else
+        {
+          setTextValue(lListenersTableEmpty, getMsg("no-listeners-found"));
+        }
+      }
+      else
+      {
+        setTextValue(lListenersTableEmpty, getMsg("no-listeners-found"));
+      }
+    }
+    else
+    {
+      listenersTable.setVisible(true);
+      listenersTable.getTableHeader().setVisible(true);
+      lListenersTableEmpty.setVisible(false);
+    }
+  }
+
+  /**
+   * Updates the databases contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateDatabaseContents(ServerStatusDescriptor desc)
+  {
+    dbTableModel.setData(desc.getDatabases());
+
+    if (dbTableModel.getRowCount() == 0)
+    {
+      dbTable.setVisible(false);
+      dbTable.getTableHeader().setVisible(false);
+      lDbTableEmpty.setVisible(true);
+      if (desc.getStatus() == ServerStatusDescriptor.ServerStatus.STARTED)
+      {
+        if (!desc.isAuthenticated())
+        {
+          setNotAvailableBecauseAuthenticationIsRequired(lDbTableEmpty);
+        }
+        else
+        {
+          setTextValue(lDbTableEmpty, getMsg("no-dbs-found"));
+        }
+      }
+      else
+      {
+        setTextValue(lDbTableEmpty, getMsg("no-dbs-found"));
+      }
+    }
+    else
+    {
+      dbTable.setVisible(true);
+      dbTable.getTableHeader().setVisible(true);
+      lDbTableEmpty.setVisible(false);
+    }
+  }
+
+  /**
+   * Updates the error label contents displaying with what is specified in
+   * the provided ServerStatusDescriptor object.
+   * This method must be called from the event thread.
+   * @param desc the ServerStatusDescriptor object.
+   */
+  private void updateErrorContents(ServerStatusDescriptor desc)
+  {
+    String errorMsg = desc.getErrorMessage();
+    if (errorMsg == null)
+    {
+      lError.setVisible(false);
+    }
+    else
+    {
+
+      lError.setVisible(true);
+      lError.setText(formatter.getFormattedError(errorMsg, false));
+    }
+  }
+
+  /**
+   * The following three methods are just commodity methods to get localized
+   * messages.
+   */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  /**
+   * 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();
+      StatusPanelDialog dlg = new StatusPanelDialog();
+      dlg.packAndShow();
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+
+  /**
+   * Class used to render the databases table cells.
+   */
+  class DatabasesCellRenderer extends JLabel implements TableCellRenderer
+  {
+    private static final long serialVersionUID = -256719167426289735L;
+
+    /**
+     * Default constructor.
+     */
+    public DatabasesCellRenderer()
+    {
+      super();
+      UIFactory.setTextStyle(this, UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Component getTableCellRendererComponent(JTable table, Object value,
+        boolean isSelected, boolean hasFocus, int row, int column) {
+      if (value instanceof String)
+      {
+        setTextValue(this, (String)value);
+      }
+      else
+      {
+        /* Is the number of entries: check if it is available or not */
+        if (lastDescriptor.getStatus() ==
+          ServerStatusDescriptor.ServerStatus.STARTED)
+        {
+          int nEntries = (Integer)value;
+          if (nEntries >= 0)
+          {
+            setTextValue(this, String.valueOf(nEntries));
+          }
+          else
+          {
+            if (!lastDescriptor.isAuthenticated())
+            {
+              setNotAvailableBecauseAuthenticationIsRequired(this);
+            }
+            else
+            {
+              setNotAvailable(this);
+            }
+          }
+        }
+        else
+        {
+          setNotAvailableBecauseServerIsDown(this);
+        }
+      }
+      if (column == 0)
+      {
+        setBorder(BorderFactory.createCompoundBorder(
+            BorderFactory.createMatteBorder(0, 1, 0, 0,
+                UIFactory.PANEL_BORDER_COLOR),
+                BorderFactory.createEmptyBorder(4, 4, 4, 4)));
+      }
+      else
+      {
+        setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
+      }
+      return this;
+    }
+  }
+
+  /**
+   * Class used to render the listeners table cells.
+   */
+  class ListenersCellRenderer extends JLabel implements TableCellRenderer
+  {
+    private static final long serialVersionUID = -256719167426289735L;
+
+    /**
+     * Default constructor.
+     */
+    public ListenersCellRenderer()
+    {
+      super();
+      UIFactory.setTextStyle(this, UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Component getTableCellRendererComponent(JTable table, Object value,
+        boolean isSelected, boolean hasFocus, int row, int column) {
+
+      setTextValue(this, (String)value);
+      if (column == 0)
+      {
+        setBorder(BorderFactory.createCompoundBorder(
+            BorderFactory.createMatteBorder(0, 1, 0, 0,
+                UIFactory.PANEL_BORDER_COLOR),
+                BorderFactory.createEmptyBorder(4, 4, 4, 4)));
+      }
+      else
+      {
+        setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
+      }
+      return this;
+    }
+  }
+
+  /**
+   * Class used to render the table headers.
+   */
+  class HeaderRenderer extends JLabel implements TableCellRenderer
+  {
+    private static final long serialVersionUID = -8604332267021523835L;
+
+    /**
+     * Default constructor.
+     */
+    public HeaderRenderer()
+    {
+      super();
+      UIFactory.setTextStyle(this, UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Component getTableCellRendererComponent(JTable table, Object value,
+        boolean isSelected, boolean hasFocus, int row, int column) {
+      setTextValue(this, (String)value);
+      if (column == 0)
+      {
+        setBorder(BorderFactory.createCompoundBorder(
+            BorderFactory.createMatteBorder(1, 1, 1, 1,
+                UIFactory.PANEL_BORDER_COLOR),
+                BorderFactory.createEmptyBorder(4, 4, 4, 4)));
+      }
+      else
+      {
+        setBorder(BorderFactory.createCompoundBorder(
+            BorderFactory.createMatteBorder(1, 0, 1, 1,
+                UIFactory.PANEL_BORDER_COLOR),
+                BorderFactory.createEmptyBorder(4, 4, 4, 4)));
+      }
+      return this;
+    }
+  }
+}
+
+/**
+ * This class is used to be able to have an instantaneous tooltip displayed
+ * in the 'not available' labels.  It replaces the default ToolTipManager class.
+ *
+ */
+class InstantaneousToolTipManager extends MouseAdapter
+implements MouseMotionListener
+{
+  private ToolTipManager ttipManager = ToolTipManager.sharedInstance();
+  private Popup tipWindow;
+  private boolean isVisible;
+
+  /**
+   * The default constructor.
+   */
+  public InstantaneousToolTipManager()
+  {
+  }
+
+  /**
+   * Register a component that will use this tool tip manager to display tool
+   * tips.
+   * @param comp the component to be registered.
+   */
+  public void registerComponent(JComponent comp)
+  {
+    ttipManager.unregisterComponent(comp);
+    comp.removeMouseListener(this);
+    comp.addMouseListener(this);
+    comp.removeMouseMotionListener(this);
+    comp.addMouseMotionListener(this);
+  }
+
+  /**
+   * Unregisters a component.  Calling this method makes the component to be
+   * registered by the default tool tip manager.
+   * @param comp the component to be unregistered.
+   */
+  public void unregisterComponent(JComponent comp)
+  {
+    ttipManager.registerComponent(comp);
+    comp.removeMouseListener(this);
+    comp.removeMouseMotionListener(this);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void mouseDragged(MouseEvent event)
+  {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void mouseEntered(MouseEvent event)
+  {
+    displayToolTip(event);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void mouseExited(MouseEvent event)
+  {
+    hideToolTip(event);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void mouseMoved(MouseEvent event)
+  {
+    hideToolTip(event);
+    displayToolTip(event);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void mousePressed(MouseEvent event)
+  {
+    if (isVisible)
+    {
+      hideToolTip(event);
+    }
+    else
+    {
+      hideToolTip(event);
+      displayToolTip(event);
+    }
+  }
+
+  /**
+   * Displays a tooltip depending on the MouseEvent received.
+   * @param event the mouse event.
+   */
+  private void displayToolTip(MouseEvent event)
+  {
+    JComponent component = (JComponent)event.getSource();
+    String toolTipText = component.getToolTipText(event);
+    if (toolTipText != null)
+    {
+      Point preferredLocation = component.getToolTipLocation(event);
+      Rectangle sBounds = component.getGraphicsConfiguration().
+      getBounds();
+
+      JToolTip tip = component.createToolTip();
+      tip.setTipText(toolTipText);
+      Dimension size = tip.getPreferredSize();
+      Point location = new Point();
+
+      Point screenLocation = component.getLocationOnScreen();
+      if(preferredLocation != null)
+      {
+        location.x = screenLocation.x + preferredLocation.x;
+        location.y = screenLocation.y + preferredLocation.y;
+      }
+      else
+      {
+        location.x = screenLocation.x + event.getX();
+        location.y = screenLocation.y + event.getY() + 20;
+      }
+
+      if (location.x < sBounds.x) {
+        location.x = sBounds.x;
+      }
+      else if (location.x - sBounds.x + size.width > sBounds.width) {
+        location.x = sBounds.x + Math.max(0, sBounds.width - size.width);
+      }
+      if (location.y < sBounds.y) {
+        location.y = sBounds.y;
+      }
+      else if (location.y - sBounds.y + size.height > sBounds.height) {
+        location.y = sBounds.y + Math.max(0, sBounds.height - size.height);
+      }
+
+      PopupFactory popupFactory = PopupFactory.getSharedInstance();
+      tipWindow = popupFactory.getPopup(component, tip, location.x, location.y);
+      tipWindow.show();
+    }
+    isVisible = true;
+  }
+
+  /**
+   * Hides the tooltip if we are displaying it.
+   * @param event the mouse event.
+   */
+  private void hideToolTip(MouseEvent event)
+  {
+    if (tipWindow != null)
+    {
+      tipWindow.hide();
+      tipWindow = null;
+    }
+    isVisible = false;
+  }
+}

--
Gitblit v1.10.0