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