From 8a1a1478c28acdc7376fc7e57d76cca61b901441 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Fri, 17 Nov 2006 17:40:50 +0000
Subject: [PATCH] The modifications basically do the following:
---
opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java | 358 +
opends/ext/build-tools.jar | 0
opends/build-tools/src/javax/jnlp/UnavailableServiceException.java | 51
opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif | 0
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java | 647 ++
opends/build-tools/src/javax/jnlp/ServiceManager.java | 54
opends/src/quicksetup/org/opends/quicksetup/util/ExtensionFileFilter.java | 86
opends/src/quicksetup/org/opends/quicksetup/images/error.gif | 0
opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallDataException.java | 75
opends/src/server/org/opends/server/tools/ImportLDIF.java | 36
opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java | 153
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java | 316 +
opends/src/quicksetup/org/opends/quicksetup/images/currentstep.gif | 0
opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java | 498 ++
opends/build-tools/src/javax/jnlp/DownloadServiceListener.java | 57
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java | 682 ++
opends/src/quicksetup/org/opends/quicksetup/installer/DataOptions.java | 142
opends/src/quicksetup/org/opends/quicksetup/ui/StepsPanel.java | 213
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java | 439 +
opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java | 57
opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java | 48
opends/src/quicksetup/org/opends/quicksetup/images/information.gif | 0
opends/resource/setup.bat | 2
opends/src/quicksetup/org/opends/quicksetup/util/BackgroundThreadTask.java | 71
opends/src/quicksetup/org/opends/quicksetup/images/currentstep.png | 0
opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java | 281 +
opends/src/quicksetup/org/opends/quicksetup/util/BackgroundTask.java | 82
opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java | 44
opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties | 365 +
opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java | 185
opends/src/quicksetup/org/opends/quicksetup/images/opendsminimizedmac.png | 0
opends/build-tools/src/org/opends/build/tools/PrepTestNG.java | 26
opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressDescriptor.java | 108
opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java | 308 +
opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java | 75
opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java | 78
opends/src/quicksetup/org/opends/quicksetup/event/ButtonActionListener.java | 43
opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java | 317 +
opends/src/quicksetup/org/opends/quicksetup/Step.java | 62
opends/build-tools/src/javax/jnlp/DownloadService.java | 55
opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java | 1429 +++++
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressDescriptor.java | 108
opends/resource/setup.sh | 5
opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java | 202
opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java | 61
opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java | 107
opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java | 299 +
opends/src/quicksetup/org/opends/quicksetup/images/warning.gif | 0
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupPanel.java | 126
opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java | 1356 +++++
opends/src/quicksetup/org/opends/quicksetup/event/ButtonEvent.java | 64
opends/src/quicksetup/org/opends/quicksetup/images/opendssplash.png | 0
opends/src/quicksetup/org/opends/quicksetup/ButtonName.java | 56
opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java | 107
opends/src/quicksetup/org/opends/quicksetup/installer/LabelFieldDescriptor.java | 151
opends/src/quicksetup/org/opends/quicksetup/ui/DataOptionsPanel.java | 619 ++
opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java | 211
opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallData.java | 166
opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java | 107
opends/src/quicksetup/org/opends/quicksetup/images/opendsbackground.png | 0
opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java | 82
opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java | 160
opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java | 80
opends/build.xml | 89
opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java | 257 +
opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java | 210
opends/src/quicksetup/org/opends/quicksetup/util/Utils.java | 809 +++
opends/src/quicksetup/org/opends/quicksetup/event/BrowseActionListener.java | 177
opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java | 186
opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java | 61
opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java | 1164 ++++
opends/src/quicksetup/org/opends/quicksetup/event/MinimumSizeComponentListener.java | 131
opends/src/quicksetup/org/opends/quicksetup/images/opendsminimized.gif | 0
opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserLauncher.java | 109
74 files changed, 14,647 insertions(+), 56 deletions(-)
diff --git a/opends/build-tools/src/javax/jnlp/DownloadService.java b/opends/build-tools/src/javax/jnlp/DownloadService.java
new file mode 100644
index 0000000..d142ee6
--- /dev/null
+++ b/opends/build-tools/src/javax/jnlp/DownloadService.java
@@ -0,0 +1,55 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package javax.jnlp;
+
+/**
+ * This is just an empty implementation of DownloadService. It does define
+ * only the methods of the JNLP API used in the class
+ * org.opends.quicksetup.webstart.WebstartDownloader.
+ *
+ * We have chosen to do this because we we require the JNLP API to be compiled
+ * but the location of the javaws.jar depends on the java distribution, so
+ * instead of trying to figure out where javaws.jar is on the java distribution
+ * that is being used to compile the source, we just add these classes to the
+ * build-tools.jar file that will be used to compile que QuickSetup.
+ *
+ * It must be noted that the class
+ * org.opends.quicksetup.webstart.WebstartDownloader will be only executed in
+ * the context of a Java Web Start application and that in this case the
+ * javaws.jar will be provided by the Java Web Start Runtime environment. So
+ * we are not providing the javaws-stub.jar during runtime: it is used only
+ * for compilation.
+ *
+ */
+public interface DownloadService {
+ public boolean isResourceCached(java.net.URL url, String version);
+ public void removeResource(java.net.URL url, String version)
+ throws java.io.IOException;
+ public void loadResource(java.net.URL ref, String version,
+ DownloadServiceListener listener) throws java.io.IOException;
+}
diff --git a/opends/build-tools/src/javax/jnlp/DownloadServiceListener.java b/opends/build-tools/src/javax/jnlp/DownloadServiceListener.java
new file mode 100644
index 0000000..aed1c12
--- /dev/null
+++ b/opends/build-tools/src/javax/jnlp/DownloadServiceListener.java
@@ -0,0 +1,57 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package javax.jnlp;
+
+/**
+ * This is the interface definition of DownloadServiceListener.
+ *
+ * We have chosen to do this because we we require the JNLP API to be compiled
+ * but the location of the javaws.jar depends on the java distribution, so
+ * instead of trying to figure out where javaws.jar is on the java distribution
+ * that is being used to compile the source, we just add these classes to the
+ * build-tools.jar file that will be used to compile que QuickSetup.
+ *
+ * It must be noted that the class
+ * org.opends.quicksetup.webstart.WebstartDownloader will be only executed in
+ * the context of a Java Web Start application and that in this case the
+ * javaws.jar will be provided by the Java Web Start Runtime environment. So
+ * we are not providing the javaws-stub.jar during runtime: it is used only
+ * for compilation.
+ *
+ */
+import java.net.URL;
+
+public interface DownloadServiceListener {
+ public void downloadFailed(URL url, String version);
+ public void progress(URL url, String version, long readSoFar, long total,
+ int overallPercent);
+ public void upgradingArchive(URL url, String version, int patchPercent,
+ int overallPercent);
+ public void validating(URL url, String version, long entry, long total,
+ int overallPercent);
+}
diff --git a/opends/build-tools/src/javax/jnlp/ServiceManager.java b/opends/build-tools/src/javax/jnlp/ServiceManager.java
new file mode 100644
index 0000000..0d57b6d
--- /dev/null
+++ b/opends/build-tools/src/javax/jnlp/ServiceManager.java
@@ -0,0 +1,54 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package javax.jnlp;
+
+/**
+ * This is just an empty implementation of ServiceManager. It does define
+ * only the methods of the JNLP API used in the class
+ * org.opends.quicksetup.webstart.WebstartDownloader.
+ *
+ * We have chosen to do this because we we require the JNLP API to be compiled
+ * but the location of the javaws.jar depends on the java distribution, so
+ * instead of trying to figure out where javaws.jar is on the java distribution
+ * that is being used to compile the source, we just add these classes to the
+ * build-tools.jar file that will be used to compile que QuickSetup.
+ *
+ * It must be noted that the class
+ * org.opends.quicksetup.webstart.WebstartDownloader will be only executed in
+ * the context of a Java Web Start application and that in this case the
+ * javaws.jar will be provided by the Java Web Start Runtime environment. So
+ * we are not providing the javaws-stub.jar during runtime: it is used only
+ * for compilation.
+ *
+ */
+public class ServiceManager {
+ public static Object lookup(String name) throws UnavailableServiceException
+ {
+ return null;
+ }
+}
diff --git a/opends/build-tools/src/javax/jnlp/UnavailableServiceException.java b/opends/build-tools/src/javax/jnlp/UnavailableServiceException.java
new file mode 100644
index 0000000..54f6e10
--- /dev/null
+++ b/opends/build-tools/src/javax/jnlp/UnavailableServiceException.java
@@ -0,0 +1,51 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package javax.jnlp;
+
+/**
+ * This is just an empty implementation of UnavailableServiceException. This
+ * class is used in the class
+ * org.opends.quicksetup.webstart.WebstartDownloader.
+ *
+ * We have chosen to do this because we we require the JNLP API to be compiled
+ * but the location of the javaws.jar depends on the java distribution, so
+ * instead of trying to figure out where javaws.jar is on the java distribution
+ * that is being used to compile the source, we just add these classes to the
+ * build-tools.jar file that will be used to compile que QuickSetup.
+ *
+ * It must be noted that the class
+ * org.opends.quicksetup.webstart.WebstartDownloader will be only executed in
+ * the context of a Java Web Start application and that in this case the
+ * javaws.jar will be provided by the Java Web Start Runtime environment. So
+ * we are not providing the javaws-stub.jar during runtime: it is used only
+ * for compilation.
+ *
+ */
+public class UnavailableServiceException extends Exception {
+ private static final long serialVersionUID = 286996071734385910L;
+}
diff --git a/opends/build-tools/src/org/opends/build/tools/PrepTestNG.java b/opends/build-tools/src/org/opends/build/tools/PrepTestNG.java
index bcaed48..27d43ed 100644
--- a/opends/build-tools/src/org/opends/build/tools/PrepTestNG.java
+++ b/opends/build-tools/src/org/opends/build/tools/PrepTestNG.java
@@ -24,32 +24,6 @@
*
* Portions Copyright 2006 Sun Microsystems, Inc.
*/
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying * information:
- * Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- * Portions Copyright 2006 Sun Microsystems, Inc.
- */
package org.opends.build.tools;
diff --git a/opends/build.xml b/opends/build.xml
index 889b0ff..4ba6399 100644
--- a/opends/build.xml
+++ b/opends/build.xml
@@ -76,6 +76,10 @@
<property name="dsml.gen.dir" location="${build.dir}/dsml/gen" />
<property name="dsml.classes.dir" location="${build.dir}/dsml/classes" />
+ <!-- Properties for use with the Quick Setup. -->
+ <property name="quicksetup.src.dir" location="src/quicksetup" />
+ <property name="quicksetup.classes.dir" location="${build.dir}/quicksetup/classes" />
+
<!-- Properties for code coverage testing. -->
<property name="coverage.dir" location="build/coverage" />
<property name="coverage.report.dir"
@@ -226,12 +230,18 @@
<taskdef resource="checkstyletask.properties"
classpath="${checkstyle.dir}/checkstyle-all-4.1.jar" />
-
+
<checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
failOnViolation="true">
<fileset dir="${src.dir}" includes="**/*.java" />
<formatter type="plain" />
</checkstyle>
+
+ <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
+ failOnViolation="true">
+ <fileset dir="${quicksetup.src.dir}" includes="**/*.java" />
+ <formatter type="plain" />
+ </checkstyle>
<checkstyle config="${checkstyle.dir}/opends-doctarget-checkstyle.xml"
failOnViolation="true">
@@ -259,7 +269,7 @@
<!-- Compile the Directory Server source files. -->
- <target name="cleancompile" depends="cleaninit,compile"
+ <target name="cleancompile" depends="cleaninit,compile,compilequicksetup"
description="Recompile the Directory Server source files.">
</target>
@@ -284,11 +294,36 @@
</javac>
</target>
+ <!-- Compile the Quick Setup source files. -->
+ <target name="compilequicksetup"
+ depends="buildtools,compile"
+ description="Compile the Quick Setup source files.">
+
+ <mkdir dir="${quicksetup.classes.dir}" />
+ <javac srcdir="${quicksetup.src.dir}" destdir="${quicksetup.classes.dir}" optimize="true"
+ debug="on" debuglevel="lines,source" source="1.5" target="1.5"
+ deprecation="true" fork="true" memoryInitialSize="${MEM}"
+ memoryMaximumSize="${MEM}">
+ <compilerarg value="-Xlint:all" />
-
-
+ <classpath>
+ <fileset dir="${ext.dir}">
+ <include name="build-tools.jar" />
+ </fileset>
+ <pathelement path="${classes.dir}"/>
+ </classpath>
+ </javac>
+ <copy todir="${quicksetup.classes.dir}">
+ <fileset dir="${quicksetup.src.dir}" includes="**/*.properties, **/*.gif, **/*.png" />
+ </copy>
+ <copy todir="${quicksetup.classes.dir}">
+ <fileset dir="${classes.dir}"
+ includes="**/DynamicConstants.class"/>
+ </copy>
+ </target>
+
<!--
- ! Rebuild the Directory Server without destorying any existing configuration
+ ! Rebuild the Directory Server without destroying any existing configuration
! or data. It will only overwrite the libraries, classes, and scripts, and
! it will not re-package. It will also not do a complete initialization, so
! DynamicConstants.java won't be regenerated.
@@ -313,7 +348,9 @@
<delete dir="${classes.dir}" />
<delete file="${package.dir}/lib/OpenDS.jar" />
<delete file="${pdir}.zip" />
-
+ <delete dir="${quicksetup.classes.dir}" />
+ <delete file="${package.dir}/lib/quicksetup.jar" />
+
<!-- Recreate the classes directory and recompile into it. -->
<mkdir dir="${classes.dir}" />
<javac srcdir="${src.dir}" destdir="${classes.dir}" optimize="true"
@@ -332,6 +369,37 @@
<!-- Generate the OpenDS.jar file -->
<jar jarfile="${pdir}/lib/OpenDS.jar"
basedir="${classes.dir}" compress="true" index="true" />
+
+ <!-- Recreate the quicksetup classes directory and recompile into it. -->
+ <mkdir dir="${quicksetup.classes.dir}" />
+ <javac srcdir="${quicksetup.src.dir}" destdir="${quicksetup.classes.dir}" optimize="true"
+ debug="on" debuglevel="lines,source" source="1.5" target="1.5"
+ deprecation="true" fork="true" memoryInitialSize="${MEM}"
+ memoryMaximumSize="${MEM}">
+ <compilerarg value="-Xlint:all" />
+ <classpath>
+ <fileset dir="${ext.dir}">
+ <include name="build-tools.jar" />
+ </fileset>
+ <fileset dir="${pdir}/lib">
+ <include name="OpenDS.jar" />
+ </fileset>
+ </classpath>
+ </javac>
+
+ <copy todir="${quicksetup.classes.dir}">
+ <fileset dir="${quicksetup.src.dir}"
+ includes="**/*.properties, **/*.gif, **/*.png"/>
+ </copy>
+
+ <copy todir="${quicksetup.classes.dir}">
+ <fileset dir="${classes.dir}"
+ includes="**/DynamicConstants.class"/>
+ </copy>
+
+ <!-- Generate the quicksetup.jar file -->
+ <jar jarfile="${pdir}/lib/quicksetup.jar"
+ basedir="${quicksetup.classes.dir}" compress="true" index="true" />
</target>
@@ -365,7 +433,10 @@
<jar jarfile="${pdir}/lib/OpenDS.jar"
basedir="${classes.dir}" compress="true" index="true" />
-
+
+ <jar jarfile="${pdir}/lib/quicksetup.jar"
+ basedir="${quicksetup.classes.dir}" compress="true" index="true" />
+
<copy todir="${pdir}/lib">
<fileset file="${lib.dir}/*.jar" />
</copy>
@@ -434,9 +505,6 @@
</zip>
</target>
-
-
-
<!-- Prepare the Directory Server DSML library. -->
<target name="predsml" depends="prepackage"
description="Prepare the Directory Server DSML library.">
@@ -794,4 +862,3 @@
</target>
</project>
-
diff --git a/opends/ext/build-tools.jar b/opends/ext/build-tools.jar
index 484deea..dee1b38 100644
--- a/opends/ext/build-tools.jar
+++ b/opends/ext/build-tools.jar
Binary files differ
diff --git a/opends/resource/setup.bat b/opends/resource/setup.bat
index ef636b8..912385c 100644
--- a/opends/resource/setup.bat
+++ b/opends/resource/setup.bat
@@ -49,7 +49,7 @@
set PATH=%SystemRoot%
-%JAVA_BIN% %JAVA_ARGS% -Dorg.opends.server.scriptName=setup org.opends.server.tools.InstallDS --configClass org.opends.server.extensions.ConfigFileHandler --configFile "%DIR_HOME%\config\config.ldif" -P setup.bat %*
+%JAVA_BIN% %JAVA_ARGS% org.opends.quicksetup.SetupLauncher -P setup.bat %*
:end
diff --git a/opends/resource/setup.sh b/opends/resource/setup.sh
index e3195a6..9ddac4c 100755
--- a/opends/resource/setup.sh
+++ b/opends/resource/setup.sh
@@ -111,8 +111,5 @@
# Launch the setup process.
-"${JAVA_BIN}" ${JAVA_ARGS} -Dorg.opends.server.scriptName=setup \
- org.opends.server.tools.InstallDS \
- --configClass org.opends.server.extensions.ConfigFileHandler \
- --configFile "${INSTANCE_ROOT}/config/config.ldif" -P "${0}" "${@}"
+"${JAVA_BIN}" org.opends.quicksetup.SetupLauncher -P setup.sh "${@}"
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java b/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
new file mode 100644
index 0000000..3ee5135
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ButtonName.java
@@ -0,0 +1,56 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup;
+
+/**
+ * This enumeration defines the logical names of the buttons that appear on the
+ * bottom of the wizard dialog.
+ */
+public enum ButtonName
+{
+ /**
+ * The Next button.
+ */
+ NEXT,
+ /**
+ * The Previous button.
+ */
+ PREVIOUS,
+ /**
+ * The Quit button.
+ */
+ QUIT,
+ /**
+ * The Close button.
+ */
+ CLOSE,
+ /**
+ * The Finish button.
+ */
+ FINISH
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java b/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
new file mode 100644
index 0000000..f13b349
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/CurrentInstallStatus.java
@@ -0,0 +1,299 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import javax.naming.NamingException;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.offline.OfflineInstaller;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to know which is the status of the install. This class is
+ * not used when we install Open DS using java web start. However it is required
+ * when do an offline installation after the user has unzipped the zip file. The
+ * main goal of the class is to help identifying whether there is already
+ * something installed or not.
+ *
+ * This class assumes that we are running in the case of an offline install.
+ */
+
+public class CurrentInstallStatus
+{
+ private boolean isInstalled;
+
+ private String installationMsg;
+
+ private String configFileContents;
+
+ /**
+ * The constructor of a CurrentInstallStatus object.
+ *
+ */
+ public CurrentInstallStatus()
+ {
+ if (Utils.isWebStart())
+ {
+ isInstalled = false;
+ } else
+ {
+ ArrayList<String> msgs = new ArrayList<String>();
+
+ if (isServerRunning())
+ {
+ if (isConfigFileModified() || (getPort() != 389))
+ {
+ /*
+ * If the config file is not modified and the port is 389 the common
+ * case is that there is already a server running on the default port,
+ * so it does not correspond to this install.
+ */
+ msgs.add(getMsg("installstatus-serverrunning", new String[]
+ { String.valueOf(getPort()) }));
+ }
+ }
+
+ if (dbFilesExist())
+ {
+ msgs.add(getMsg("installstatus-dbfileexist"));
+ }
+
+ if (isConfigFileModified())
+ {
+ msgs.add(getMsg("installstatus-configfilemodified"));
+ }
+ isInstalled = msgs.size() > 0;
+ if (isInstalled)
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append("<ul>");
+ for (String msg : msgs)
+ {
+ buf.append("\n<li>").append(msg).append("</li>");
+ }
+ buf.append("</ul>");
+ installationMsg = getMsg("installstatus-installed", new String[]
+ { buf.toString() });
+ }
+ }
+ if (!isInstalled)
+ {
+ installationMsg = getMsg("installstatus-not-installed");
+ }
+ }
+
+ /**
+ * Indicates whether there is something installed or not.
+ *
+ * @return <CODE>true</CODE> if there is something installed under the
+ * binaries that we are running, or <CODE>false</CODE> if not.
+ */
+ public boolean isInstalled()
+ {
+ return isInstalled;
+ }
+
+ /**
+ * Provides a localized message to be displayed to the user in HTML format
+ * informing of the installation status.
+ *
+ * @return an String in HTML format describing the status of the installation.
+ */
+ public String getInstallationMsg()
+ {
+ return installationMsg;
+ }
+
+ /**
+ * Provides the config file path (path to config.ldif file).
+ *
+ * @return the config file path.
+ */
+ private String getConfigFilePath()
+ {
+ return OfflineInstaller.CONFIG_FILE_NAME;
+ }
+
+ /**
+ * Provides the LDAP port as is specified in the config.ldif file.
+ *
+ * @return the LDAP port specified in the config.ldif file.
+ */
+ private int getPort()
+ {
+ int port = -1;
+
+ int index = getConfigFileContents().indexOf("cn=ldap connection handler");
+
+ if (index != -1)
+ {
+ String portAttr = "ds-cfg-listen-port:";
+ int index1 = getConfigFileContents().indexOf(portAttr, index);
+ if (index1 != -1)
+ {
+ int index2 =
+ getConfigFileContents().indexOf(
+ System.getProperty("line.separator"), index1);
+ if (index2 != -1)
+ {
+ String sPort =
+ getConfigFileContents().substring(portAttr.length() + index1,
+ index2).trim();
+ try
+ {
+ port = Integer.parseInt(sPort);
+ } catch (NumberFormatException nfe)
+ {
+ }
+ }
+ }
+ }
+ return port;
+ }
+
+ /**
+ * Indicates whether there is the server is running in the localhost on the
+ * LDAP port specified in config.ldif file.
+ *
+ * @return <CODE>true</CODE> if the server is running, or <CODE>false</CODE>
+ * if not.
+ */
+ private boolean isServerRunning()
+ {
+ boolean isServerRunning = false;
+
+ int port = getPort();
+
+ if (port > 0)
+ {
+ String ldapURL = "ldap://localhost:" + port;
+
+ try
+ {
+ Utils.createLdapContext(ldapURL, null, null, 3000, null);
+ isServerRunning = true;
+ } catch (NamingException ne)
+ {
+ }
+ }
+ return isServerRunning;
+ }
+
+ /**
+ * Indicates whether there are database files under this installation.
+ *
+ * @return <CODE>true</CODE> if there are database files, or
+ * <CODE>false</CODE> if not.
+ */
+ private boolean dbFilesExist()
+ {
+ boolean dbFilesExist = false;
+ File dbDir = new File(OfflineInstaller.FULL_INSTALL_PATH, "db");
+ File[] children = dbDir.listFiles();
+ if ((children != null) && (children.length > 0))
+ {
+ dbFilesExist = true;
+ }
+ return dbFilesExist;
+ }
+
+ /**
+ * Indicates whether the config.ldif file has been modified (compared to what
+ * we had in the zip file). This is used to know if we have configured the
+ * current binaries or not.
+ *
+ * @return <CODE>true</CODE> if the config.ldif file has been modified, or
+ * <CODE>false</CODE> if not.
+ */
+ private boolean isConfigFileModified()
+ {
+ boolean isConfigFileModified = getPort() != 389;
+
+ if (!isConfigFileModified)
+ {
+ // TODO: this is not really stable
+ isConfigFileModified =
+ getConfigFileContents().indexOf("# cddl header start") == -1;
+ }
+
+ return isConfigFileModified;
+ }
+
+ /**
+ * Provides the contents of the config.ldif file in a String.
+ *
+ * @return a String representing the contents of the config.ldif file.
+ */
+ private String getConfigFileContents()
+ {
+ if (configFileContents == null)
+ {
+ StringBuffer buf = new StringBuffer();
+ try
+ {
+ BufferedReader in =
+ new BufferedReader(new FileReader(getConfigFilePath()));
+ String line;
+ // We do not care about encoding: we are just interested in the ports
+ while ((line = in.readLine()) != null)
+ {
+ buf.append(line + System.getProperty("line.separator"));
+ }
+ configFileContents = buf.toString().toLowerCase();
+ } catch (IOException ioe)
+ {
+ }
+ }
+ return configFileContents;
+ }
+
+ /**
+ * The following three methods are just commodity methods to get localized
+ * messages.
+ */
+ private String getMsg(String key)
+ {
+ return getI18n().getMsg(key);
+ }
+
+ private String getMsg(String key, String[] args)
+ {
+ return getI18n().getMsg(key, args);
+ }
+
+ private ResourceProvider getI18n()
+ {
+ return ResourceProvider.getInstance();
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java b/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
new file mode 100644
index 0000000..d156a3b
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
@@ -0,0 +1,1164 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Iterator;
+
+import javax.swing.SwingUtilities;
+
+import org.opends.quicksetup.event.ButtonActionListener;
+import org.opends.quicksetup.event.ButtonEvent;
+import org.opends.quicksetup.event.ProgressUpdateEvent;
+import org.opends.quicksetup.event.ProgressUpdateListener;
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.DataOptions;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.Installer;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.installer.UserInstallDataException;
+import org.opends.quicksetup.installer.offline.OfflineInstaller;
+import org.opends.quicksetup.installer.webstart.WebStartDownloader;
+import org.opends.quicksetup.installer.webstart.WebStartInstaller;
+import org.opends.quicksetup.ui.QuickSetupDialog;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.uninstaller.Uninstaller;
+import org.opends.quicksetup.util.BackgroundTask;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is responsible for doing the following:
+ *
+ * Check whether we are installing or uninstalling and which type of
+ * installation we are running.
+ *
+ * Performs all the checks and validation of the data provided by the user
+ * during the setup.
+ *
+ * It will launch also the installation once the user clicks on 'Finish' if we
+ * are installing the product.
+ *
+ * If we are running a web start installation it will start the background
+ * downloading of the jar files that are required to perform the installation
+ * (OpenDS.jar, je.jar, etc.). The global idea is to force the user to
+ * download just one jar file (quicksetup.jar) to launch the Web Start
+ * installer. Then QuickSetup will call WebStartDownloader to download the jar
+ * files. Until this class is not finished the WebStart Installer will be on
+ * the InstallProgressStep.DOWNLOADING step.
+ *
+ */
+class QuickSetup implements ButtonActionListener, ProgressUpdateListener
+{
+ // Contains the data provided by the user
+ private UserInstallData userData;
+
+ private Installer installer;
+
+ private Uninstaller uninstaller;
+
+ private WebStartDownloader jnlpDownloader;
+
+ private CurrentInstallStatus installStatus;
+
+ private Step currentStep = Step.WELCOME;
+
+ private QuickSetupDialog dialog;
+
+ private StringBuffer progressDetails = new StringBuffer();
+
+ private InstallProgressDescriptor lastDescriptor;
+
+ private InstallProgressDescriptor lastDisplayedDescriptor;
+
+ private InstallProgressDescriptor descriptorToDisplay;
+
+ // Constants used to do checks
+ private static final int MIN_DIRECTORY_MANAGER_PWD = 1;
+
+ private static final int MIN_PORT_VALUE = 1;
+
+ private static final int MAX_PORT_VALUE = 65535;
+
+ private static final int MIN_NUMBER_ENTRIES = 1;
+
+ private static final int MAX_NUMBER_ENTRIES = 10000000;
+
+ // Update period of the dialogs.
+ private static final int UPDATE_PERIOD = 500;
+
+ /**
+ * This method creates the install/uninstall dialogs and to check the current
+ * install status. This method must be called outside the event thread because
+ * it can perform long operations which can make the user think that the UI is
+ * blocked.
+ *
+ * @param args for the moment this parameter is not used but we keep it in
+ * order to (in case of need) pass parameters through the command line.
+ */
+ public void initialize(String[] args)
+ {
+ if (isWebStart())
+ {
+ jnlpDownloader = new WebStartDownloader();
+ jnlpDownloader.start(false);
+ }
+ installStatus = new CurrentInstallStatus();
+ initLookAndFeel();
+ if (Utils.isUninstall())
+ {
+ setCurrentStep(Step.CONFIRM_UNINSTALL);
+ } else
+ {
+ setCurrentStep(Step.WELCOME);
+ }
+ }
+
+ /**
+ * This method displays the setup dialog. This method must be called from the
+ * event thread.
+ */
+ public void display()
+ {
+ getDialog().packAndShow();
+ }
+
+ /**
+ * ButtonActionListener implementation. It assumes that we are called in the
+ * event thread.
+ *
+ * @param ev the ButtonEvent we receive.
+ */
+ public void buttonActionPerformed(ButtonEvent ev)
+ {
+ switch (ev.getButtonName())
+ {
+ case NEXT:
+ nextClicked();
+ break;
+
+ case CLOSE:
+ closeClicked();
+ break;
+
+ case FINISH:
+ finishClicked();
+ break;
+
+ case QUIT:
+ quitClicked();
+ break;
+
+ case PREVIOUS:
+ previousClicked();
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown button name: "
+ + ev.getButtonName());
+ }
+ }
+
+ /**
+ * ProgressUpdateListener implementation. Here we take the ProgressUpdateEvent
+ * and create a ProgressDescriptor that will be used to update the progress
+ * dialog.
+ *
+ * @param ev the ProgressUpdateEvent we receive.
+ *
+ * @see #runDisplayUpdater()
+ */
+ public void progressUpdate(ProgressUpdateEvent ev)
+ {
+ synchronized (this)
+ {
+ InstallProgressDescriptor desc = createProgressDescriptor(ev);
+ boolean isLastDescriptor =
+ desc.getProgressStep() == InstallProgressStep.FINISHED_SUCCESSFULLY
+ || desc.getProgressStep() ==
+ InstallProgressStep.FINISHED_WITH_ERROR;
+ if (isLastDescriptor)
+ {
+ lastDescriptor = desc;
+ }
+
+ descriptorToDisplay = desc;
+ }
+ }
+
+ /**
+ * This method is used to update the progress dialog.
+ *
+ * We are receiving notifications from the installer (this class is a
+ * ProgressListener). However if we lots of notifications updating the
+ * progress panel every time we get a progress update can result of a lot of
+ * flickering. So the idea here is to have a minimal time between 2 updates of
+ * the progress dialog (specified by UPDATE_PERIOD).
+ *
+ * @see #progressUpdate(ProgressUpdateEvent ev)
+ *
+ */
+ private void runDisplayUpdater()
+ {
+ boolean doPool = true;
+ while (doPool)
+ {
+ try
+ {
+ Thread.sleep(UPDATE_PERIOD);
+ } catch (Exception ex)
+ {
+ }
+ synchronized (this)
+ {
+ final InstallProgressDescriptor desc = descriptorToDisplay;
+ if (desc != null)
+ {
+ if (desc != lastDisplayedDescriptor)
+ {
+ lastDisplayedDescriptor = desc;
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ getDialog().displayProgress(desc);
+ }
+ });
+ }
+ doPool = desc != lastDescriptor;
+ }
+ }
+ }
+ }
+
+ /**
+ * Method called when user clicks 'Next' button of the wizard.
+ *
+ */
+ private void nextClicked()
+ {
+ final Step cStep = getCurrentStep();
+ switch (cStep)
+ {
+ case PROGRESS:
+ throw new IllegalStateException(
+ "Cannot click on next from progress step");
+
+ case REVIEW:
+ throw new IllegalStateException("Cannot click on next from review step");
+
+ default:
+ BackgroundTask worker = new BackgroundTask()
+ {
+ public Object processBackgroundTask() throws UserInstallDataException
+ {
+ try
+ {
+ updateUserData(cStep);
+ } catch (RuntimeException re)
+ {
+ throw new UserInstallDataException(getCurrentStep(),
+ getExceptionMsg("bug-msg", re));
+ }
+ return null;
+ }
+
+ public void backgroundTaskCompleted(Object returnValue,
+ Throwable throwable)
+ {
+ getDialog().workerFinished();
+ UserInstallDataException ude = (UserInstallDataException)throwable;
+ if (ude != null)
+ {
+ displayError(ude.getLocalizedMessage(), getMsg("error-title"));
+ } else
+ {
+ setCurrentStep(nextStep(cStep));
+ }
+ }
+ };
+ getDialog().workerStarted();
+ worker.startBackgroundTask();
+ }
+ }
+
+ /**
+ * Method called when user clicks 'Finish' button of the wizard.
+ *
+ */
+ private void finishClicked()
+ {
+ Step cStep = getCurrentStep();
+ switch (cStep)
+ {
+ case REVIEW:
+ updateUserDataForReviewPanel();
+ launchInstallation();
+ setCurrentStep(Step.PROGRESS);
+ break;
+
+ case CONFIRM_UNINSTALL:
+ launchUninstallation();
+ setCurrentStep(Step.PROGRESS);
+ break;
+
+ default:
+ throw new IllegalStateException(
+ "Cannot click on finish when we are not in the Review window");
+ }
+ }
+
+ /**
+ * Method called when user clicks 'Previous' button of the wizard.
+ *
+ */
+ private void previousClicked()
+ {
+ Step cStep = getCurrentStep();
+ switch (cStep)
+ {
+ case WELCOME:
+ throw new IllegalStateException(
+ "Cannot click on previous from progress step");
+
+ case PROGRESS:
+ throw new IllegalStateException(
+ "Cannot click on previous from progress step");
+
+ default:
+ setCurrentStep(previousStep(cStep));
+ }
+ }
+
+ /**
+ * Method called when user clicks 'Quit' button of the wizard.
+ *
+ */
+ private void quitClicked()
+ {
+ Step cStep = getCurrentStep();
+ switch (cStep)
+ {
+ case PROGRESS:
+ throw new IllegalStateException(
+ "Cannot click on quit from progress step");
+
+ default:
+ if (installStatus.isInstalled())
+ {
+ quit();
+ } else if (displayConfirmation(getMsg("confirm-quit-quicksetup-msg"),
+ getMsg("confirm-quit-quicksetup-title")))
+ {
+ quit();
+ }
+ }
+ }
+
+ /**
+ * Method called when user clicks 'Close' button of the wizard.
+ *
+ */
+ private void closeClicked()
+ {
+ Step cStep = getCurrentStep();
+ switch (cStep)
+ {
+ case PROGRESS:
+ if (Utils.isUninstall())
+ {
+ boolean finished = uninstaller.isFinished();
+ if (finished
+ || displayConfirmation(getMsg("confirm-close-uninstall-msg"),
+ getMsg("confirm-close-uninstall-title")))
+ {
+ quit();
+ }
+ } else
+ {
+ boolean finished = installer.isFinished();
+ if (finished
+ || displayConfirmation(getMsg("confirm-close-quicksetup-msg"),
+ getMsg("confirm-close-quicksetup-title")))
+ {
+ quit();
+ }
+ }
+ break;
+
+ default:
+ throw new IllegalStateException(
+ "Close only can be clicked on PROGRESS step");
+ }
+ }
+
+ /**
+ * Method called when we want to quit the setup (for instance when the user
+ * clicks on 'Close' or 'Quit' buttons and has confirmed that (s)he wants to
+ * quit the program.
+ *
+ */
+ private void quit()
+ {
+ System.exit(0);
+ }
+
+ /**
+ * These methods validate the data provided by the user in the panels and
+ * update the UserData object according to that content.
+ *
+ * @param cStep
+ * the current step of the wizard
+ *
+ * @throws an
+ * UserInstallDataException if the data provided by the user is not
+ * valid.
+ *
+ */
+ private void updateUserData(Step cStep) throws UserInstallDataException
+ {
+ switch (cStep)
+ {
+ case SERVER_SETTINGS:
+ updateUserDataForServerSettingsPanel();
+ break;
+
+ case DATA_OPTIONS:
+ updateUserDataForDataOptionsPanel();
+ break;
+
+ case REVIEW:
+ updateUserDataForReviewPanel();
+ break;
+ }
+ }
+
+ /**
+ * Validate the data provided by the user in the server settings panel and
+ * update the UserData object according to that content.
+ *
+ * @throws an
+ * UserInstallDataException if the data provided by the user is not
+ * valid.
+ *
+ */
+ private void updateUserDataForServerSettingsPanel()
+ throws UserInstallDataException
+ {
+ ArrayList<String> errorMsgs = new ArrayList<String>();
+
+ if (isWebStart())
+ {
+ // Check the server location
+ String serverLocation = getFieldStringValue(FieldName.SERVER_LOCATION);
+
+ if ((serverLocation == null) || ("".equals(serverLocation.trim())))
+ {
+ errorMsgs.add(getMsg("empty-server-location"));
+ displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+ } else if (!Utils.parentDirectoryExists(serverLocation))
+ {
+ String[] arg =
+ { serverLocation };
+ errorMsgs.add(getMsg("parent-directory-does-not-exist", arg));
+ displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+ } else if (Utils.fileExists(serverLocation))
+ {
+ String[] arg =
+ { serverLocation };
+ errorMsgs.add(getMsg("file-exists", arg));
+ displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+ } else if (Utils.directoryExistsAndIsNotEmpty(serverLocation))
+ {
+ String[] arg =
+ { serverLocation };
+ errorMsgs.add(getMsg("directory-exists-not-empty", arg));
+ displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+ } else if (!Utils.canWrite(serverLocation))
+ {
+ String[] arg =
+ { serverLocation };
+ errorMsgs.add(getMsg("directory-not-writable", arg));
+ displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+
+ } else if (!Utils.hasEnoughSpace(serverLocation,
+ getRequiredInstallSpace()))
+ {
+ long requiredInMb = getRequiredInstallSpace() / (1024 * 1024);
+ String[] args =
+ { serverLocation, String.valueOf(requiredInMb) };
+ errorMsgs.add(getMsg("not-enough-disk-space", args));
+ displayFieldInvalid(FieldName.SERVER_LOCATION, true);
+
+ } else
+ {
+ getUserData().setServerLocation(serverLocation);
+ displayFieldInvalid(FieldName.SERVER_LOCATION, false);
+ }
+ }
+
+ // Check the port
+ String sPort = getFieldStringValue(FieldName.SERVER_PORT);
+ try
+ {
+ int port = Integer.parseInt(sPort);
+ if ((port < MIN_PORT_VALUE) || (port > MAX_PORT_VALUE))
+ {
+ String[] args =
+ { String.valueOf(MIN_PORT_VALUE), String.valueOf(MAX_PORT_VALUE) };
+ errorMsgs.add(getMsg("invalid-port-value-range", args));
+ displayFieldInvalid(FieldName.SERVER_PORT, true);
+ } else if (!Utils.canUseAsPort(port))
+ {
+ if (Utils.isPriviledgedPort(port))
+ {
+ errorMsgs.add(getMsg("cannot-bind-priviledged-port", new String[]
+ { String.valueOf(port) }));
+ } else
+ {
+ errorMsgs.add(getMsg("cannot-bind-port", new String[]
+ { String.valueOf(port) }));
+ }
+ displayFieldInvalid(FieldName.SERVER_PORT, true);
+
+ } else
+ {
+ getUserData().setServerPort(port);
+ displayFieldInvalid(FieldName.SERVER_PORT, false);
+ }
+
+ } catch (NumberFormatException nfe)
+ {
+ String[] args =
+ { String.valueOf(MIN_PORT_VALUE), String.valueOf(MAX_PORT_VALUE) };
+ errorMsgs.add(getMsg("invalid-port-value-range", args));
+ displayFieldInvalid(FieldName.SERVER_PORT, true);
+ }
+
+ // Check the Directory Manager DN
+ String dmDn = getFieldStringValue(FieldName.DIRECTORY_MANAGER_DN);
+
+ if ((dmDn == null) || (dmDn.trim().length() == 0))
+ {
+ errorMsgs.add(getMsg("empty-directory-manager-dn"));
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true);
+ } else if (!Utils.isDn(dmDn))
+ {
+ errorMsgs.add(getMsg("not-a-directory-manager-dn"));
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true);
+ } else if (Utils.isConfigurationDn(dmDn))
+ {
+ errorMsgs.add(getMsg("directory-manager-dn-is-config-dn"));
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, true);
+ } else
+ {
+ getUserData().setDirectoryManagerDn(dmDn);
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_DN, false);
+ }
+
+ // Check the provided passwords
+ String pwd1 = getFieldStringValue(FieldName.DIRECTORY_MANAGER_PWD);
+ String pwd2 = getFieldStringValue(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM);
+ if (pwd1 == null)
+ {
+ pwd1 = "";
+ }
+
+ boolean pwdValid = true;
+ if (!pwd1.equals(pwd2))
+ {
+ errorMsgs.add(getMsg("not-equal-pwd"));
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, true);
+ pwdValid = false;
+
+ }
+ if (pwd1.length() < MIN_DIRECTORY_MANAGER_PWD)
+ {
+ errorMsgs.add(getMsg(("pwd-too-short"), new String[]
+ { String.valueOf(MIN_DIRECTORY_MANAGER_PWD) }));
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD, true);
+ if ((pwd2 == null) || (pwd2.length() < MIN_DIRECTORY_MANAGER_PWD))
+ {
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, true);
+ }
+ pwdValid = false;
+ }
+
+ if (pwdValid)
+ {
+ getUserData().setDirectoryManagerPwd(pwd1);
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD, false);
+ displayFieldInvalid(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM, false);
+ }
+
+ if (errorMsgs.size() > 0)
+ {
+ throw new UserInstallDataException(Step.SERVER_SETTINGS,
+ getStringFromCollection(errorMsgs));
+ }
+ }
+
+ /**
+ * Validate the data provided by the user in the data options panel and update
+ * the UserData object according to that content.
+ *
+ * @throws an
+ * UserInstallDataException if the data provided by the user is not
+ * valid.
+ *
+ */
+ private void updateUserDataForDataOptionsPanel()
+ throws UserInstallDataException
+ {
+ ArrayList<String> errorMsgs = new ArrayList<String>();
+
+ DataOptions dataOptions = null;
+
+ // Check the base dn
+ boolean validBaseDn = false;
+ String baseDn = getFieldStringValue(FieldName.DIRECTORY_BASE_DN);
+ if ((baseDn == null) || (baseDn.trim().length() == 0))
+ {
+ errorMsgs.add(getMsg("empty-base-dn"));
+ displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, true);
+ } else if (!Utils.isDn(baseDn))
+ {
+ errorMsgs.add(getMsg("not-a-base-dn"));
+ displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, true);
+ } else if (Utils.isConfigurationDn(baseDn))
+ {
+ errorMsgs.add(getMsg("base-dn-is-configuration-dn"));
+ displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, true);
+ } else
+ {
+ displayFieldInvalid(FieldName.DIRECTORY_BASE_DN, false);
+ validBaseDn = true;
+ }
+
+ // Check the data options
+ DataOptions.Type type =
+ (DataOptions.Type) getFieldValue(FieldName.DATA_OPTIONS);
+
+ switch (type)
+ {
+ case IMPORT_FROM_LDIF_FILE:
+ String ldifPath = getFieldStringValue(FieldName.LDIF_PATH);
+ if ((ldifPath == null) || (ldifPath.trim().equals("")))
+ {
+ errorMsgs.add(getMsg("no-ldif-path"));
+ displayFieldInvalid(FieldName.LDIF_PATH, true);
+ } else if (!Utils.fileExists(ldifPath))
+ {
+ errorMsgs.add(getMsg("ldif-file-does-not-exist"));
+ displayFieldInvalid(FieldName.LDIF_PATH, true);
+ } else if (validBaseDn)
+ {
+ dataOptions = new DataOptions(type, baseDn, ldifPath);
+ displayFieldInvalid(FieldName.LDIF_PATH, false);
+ }
+ break;
+
+ case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+ // variable used to know if everything went ok during these
+ // checks
+ int startErrors = errorMsgs.size();
+
+ // Check the number of entries
+ String nEntries = getFieldStringValue(FieldName.NUMBER_ENTRIES);
+ if ((nEntries == null) || (nEntries.trim().equals("")))
+ {
+ errorMsgs.add(getMsg("no-number-entries"));
+ displayFieldInvalid(FieldName.NUMBER_ENTRIES, true);
+ } else
+ {
+ boolean nEntriesValid = false;
+ try
+ {
+ int n = Integer.parseInt(nEntries);
+
+ nEntriesValid = n >= MIN_NUMBER_ENTRIES && n <= MAX_NUMBER_ENTRIES;
+ } catch (NumberFormatException nfe)
+ {
+ }
+
+ if (!nEntriesValid)
+ {
+ String[] args =
+ { String.valueOf(MIN_NUMBER_ENTRIES),
+ String.valueOf(MAX_NUMBER_ENTRIES) };
+ errorMsgs.add(getMsg("invalid-number-entries-range", args));
+ displayFieldInvalid(FieldName.NUMBER_ENTRIES, true);
+ } else
+ {
+ displayFieldInvalid(FieldName.NUMBER_ENTRIES, false);
+ }
+ }
+ if (startErrors == errorMsgs.size() && validBaseDn)
+ {
+ // No validation errors
+ dataOptions = new DataOptions(type, baseDn, new Integer(nEntries));
+ }
+ break;
+
+ default:
+ displayFieldInvalid(FieldName.LDIF_PATH, false);
+ displayFieldInvalid(FieldName.NUMBER_ENTRIES, false);
+ if (validBaseDn)
+ {
+ dataOptions = new DataOptions(type, baseDn);
+ }
+ }
+
+ if (dataOptions != null)
+ {
+ getUserData().setDataOptions(dataOptions);
+ }
+
+ if (errorMsgs.size() > 0)
+ {
+ throw new UserInstallDataException(Step.DATA_OPTIONS,
+ getStringFromCollection(errorMsgs));
+ }
+ }
+
+ /**
+ * Update the UserData object according to the content of the review panel.
+ *
+ */
+ private void updateUserDataForReviewPanel()
+ {
+ Boolean b = (Boolean) getFieldValue(FieldName.SERVER_START);
+ getUserData().setStartServer(b.booleanValue());
+ }
+
+ /**
+ * Launch the installation of Open DS. Depending on whether we are running a
+ * web start or not it will use on Installer object or other.
+ *
+ */
+ private void launchInstallation()
+ {
+ if (isWebStart())
+ {
+ installer = new WebStartInstaller(getUserData(), jnlpDownloader);
+ } else
+ {
+ installer = new OfflineInstaller(getUserData());
+ }
+ installer.addProgressUpdateListener(this);
+ installer.start();
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ runDisplayUpdater();
+ }
+ });
+ t.start();
+ }
+
+ /**
+ * Launch the uninstallation of Open DS.
+ *
+ */
+ private void launchUninstallation()
+ {
+ uninstaller = new Uninstaller();
+ // TO COMPLETE
+ }
+
+ /**
+ * Provides the object representing the data provided by the user in the
+ * install.
+ *
+ * @return the UserInstallData representing the data provided by the user in
+ * the Install wizard.
+ */
+ private UserInstallData getUserData()
+ {
+ if (userData == null)
+ {
+ userData = new UserInstallData();
+ }
+ return userData;
+ }
+
+ /**
+ * Provides an object representing the default data/install parameters that
+ * will be proposed to the user in the Installation wizard. This data includes
+ * elements such as the default dn of the directory manager or the default
+ * install location.
+ *
+ * @return the UserInstallData representing the default data/parameters that
+ * will be proposed to the user.
+ */
+ private UserInstallData getDefaultUserData()
+ {
+ UserInstallData defaultUserData = new UserInstallData();
+
+ DataOptions defaultDataOptions = new DefaultDataOptions();
+
+ defaultUserData.setServerLocation(Utils.getDefaultServerLocation());
+ // See what we can propose as port
+ int defaultPort = getDefaultPort();
+ if (defaultPort != -1)
+ {
+ defaultUserData.setServerPort(defaultPort);
+ }
+ defaultUserData.setDirectoryManagerDn("cn=Directory Manager");
+
+ defaultUserData.setDataOptions(defaultDataOptions);
+ defaultUserData.setStartServer(true);
+
+ return defaultUserData;
+ }
+
+ /**
+ * The following three methods are just commodity methods to get localized
+ * messages.
+ */
+ private String getMsg(String key)
+ {
+ return getI18n().getMsg(key);
+ }
+
+ private String getMsg(String key, String[] args)
+ {
+ return getI18n().getMsg(key, args);
+ }
+
+ private String getExceptionMsg(String key, Exception ex)
+ {
+ return Utils.getExceptionMsg(getI18n(), key, null, ex);
+ }
+
+ private ResourceProvider getI18n()
+ {
+ return ResourceProvider.getInstance();
+ }
+
+ /**
+ * Get the current step.
+ *
+ * @return the currently displayed Step of the wizard.
+ */
+ private Step getCurrentStep()
+ {
+ return currentStep;
+ }
+
+ /**
+ * Set the current step. This will basically make the required calls in the
+ * dialog to display the panel that corresponds to the step passed as
+ * argument.
+ *
+ * @param step.
+ * The step to be displayed.
+ */
+ private void setCurrentStep(Step step)
+ {
+ if (step == null)
+ {
+ throw new NullPointerException("step is null");
+ }
+ currentStep = step;
+ getDialog().setDisplayedStep(step, getUserData());
+ }
+
+ /**
+ * Gets the next step corresponding to the step passed as parameter.
+ *
+ * @param step,
+ * the step of which we want to get the new step.
+ * @return the next step for the current step.
+ * @throws IllegalArgumentException
+ * if the current step has not a next step.
+ */
+ private Step nextStep(Step step)
+ {
+ Iterator<Step> it = EnumSet.range(step, Step.PROGRESS).iterator();
+ it.next();
+ if (!it.hasNext())
+ {
+ throw new IllegalArgumentException("No next for step: " + step);
+ }
+ return it.next();
+ }
+
+ /**
+ * Gets the previous step corresponding to the step passed as parameter.
+ *
+ * @param step,
+ * the step of which we want to get the previous step.
+ * @return the next step for the current step.
+ * @throws IllegalArgumentException
+ * if the current step has not a previous step.
+ */
+ private Step previousStep(Step step)
+ {
+ Step previous = null;
+ for (Step s : Step.values())
+ {
+ if (s == step)
+ {
+ return previous;
+ }
+ previous = s;
+ }
+ throw new IllegalArgumentException("No previous for step: " + step);
+ }
+
+ /**
+ * Get the dialog that is displayed.
+ *
+ * @return the dialog.
+ */
+ private QuickSetupDialog getDialog()
+ {
+ if (dialog == null)
+ {
+ dialog = new QuickSetupDialog(getDefaultUserData(), installStatus);
+ dialog.addButtonActionListener(this);
+ }
+ return dialog;
+ }
+
+ /**
+ * Displays an error message dialog.
+ *
+ * @param msg
+ * the error message.
+ * @param title
+ * the title for the dialog.
+ */
+ private void displayError(String msg, String title)
+ {
+ getDialog().displayError(msg, title);
+ }
+
+ /**
+ * Displays a confirmation message dialog.
+ *
+ * @param msg
+ * the confirmation message.
+ * @param title
+ * the title of the dialog.
+ * @return <CODE>true</CODE> if the user confirms the message, or
+ * <CODE>false</CODE> if not.
+ */
+ private boolean displayConfirmation(String msg, String title)
+ {
+ return getDialog().displayConfirmation(msg, title);
+ }
+
+ /**
+ * Gets the string value for a given field name.
+ *
+ * @param fieldName
+ * the field name object.
+ * @return the string value for the field name.
+ */
+ private String getFieldStringValue(FieldName fieldName)
+ {
+ String sValue = null;
+
+ Object value = getFieldValue(fieldName);
+ if (value != null)
+ {
+ if (value instanceof String)
+ {
+ sValue = (String) value;
+ } else
+ {
+ sValue = String.valueOf(value);
+ }
+ }
+ return sValue;
+ }
+
+ /**
+ * Gets the value for a given field name.
+ *
+ * @param fieldName
+ * the field name object.
+ * @return the value for the field name.
+ */
+ private Object getFieldValue(FieldName fieldName)
+ {
+ return getDialog().getFieldValue(fieldName);
+ }
+
+ /**
+ * Marks the fieldName as valid or invalid depending on the value of the
+ * invalid parameter. With the current implementation this implies basically
+ * using a red color in the label associated with the fieldName object. The
+ * color/style used to mark the label invalid is specified in UIFactory.
+ *
+ * @param fieldName
+ * the field name object.
+ * @param invalid
+ * whether to mark the field valid or invalid.
+ */
+ private void displayFieldInvalid(FieldName fieldName, boolean invalid)
+ {
+ getDialog().displayFieldInvalid(fieldName, invalid);
+ }
+
+ /**
+ * This is a helper method that gets a String representation of the elements
+ * in the Collection. The String will display the different elements separated
+ * by a '\n' character.
+ *
+ * @param col
+ * the collection containing the String.
+ * @return the String representation for the collection.
+ */
+ private String getStringFromCollection(Collection<String> col)
+ {
+ String msg = null;
+ for (String m : col)
+ {
+ if (msg == null)
+ {
+ msg = m;
+ } else
+ {
+ msg += "\n" + m;
+ }
+ }
+ return msg;
+ }
+
+ /**
+ * A method to initialize the look and feel.
+ *
+ */
+ private void initLookAndFeel()
+ {
+ UIFactory.initialize();
+ }
+
+ /**
+ * A methods that creates a InstallProgressDescriptor based on the value of a
+ * ProgressUpdateEvent.
+ *
+ * @param ev
+ * the ProgressUpdateEvent used to generate the
+ * InstallProgressDescriptor.
+ * @return the InstallProgressDescriptor.
+ */
+ private InstallProgressDescriptor createProgressDescriptor(
+ ProgressUpdateEvent ev)
+ {
+ InstallProgressStep status = ev.getProgressStep();
+ String newProgressLabel = ev.getCurrentPhaseSummary();
+ String additionalDetails = ev.getNewLogs();
+ Integer ratio = ev.getProgressRatio();
+
+ if (additionalDetails != null)
+ {
+ progressDetails.append(additionalDetails);
+ }
+
+ return new InstallProgressDescriptor(status, ratio, newProgressLabel,
+ progressDetails.toString());
+ }
+
+ /**
+ * Indicates whether we are in a web start installation or not.
+ *
+ * @return <CODE>true</CODE> if we are in a web start installation and
+ * <CODE>false</CODE> if not.
+ */
+ private boolean isWebStart()
+ {
+ return Utils.isWebStart();
+ }
+
+ /**
+ * Provides the port that will be proposed to the user in the second page of
+ * the installation wizard. It will check whether we can use 389 and if not it
+ * will return -1.
+ *
+ * @return the port 389 if it is available and we can use and -1 if not.
+ */
+ private int getDefaultPort()
+ {
+ int defaultPort = -1;
+ if (Utils.canUseAsPort(389))
+ {
+ defaultPort = 389;
+ }
+ return defaultPort;
+ }
+
+ /**
+ * Returns the number of free disk space in bytes required to install Open DS
+ *
+ * For the moment we just return 15 Megabytes. TODO we might want to have
+ * something dynamic to calculate the required free disk space for the
+ * installation.
+ *
+ * @return the number of free disk space required to install Open DS.
+ */
+ private long getRequiredInstallSpace()
+ {
+ return 15 * 1024 * 1024;
+ }
+}
+
+/**
+ * This class is just used to specify which are the default values that will be
+ * proposed to the user in the Data Options panel of the Installation wizard.
+ *
+ */
+class DefaultDataOptions extends DataOptions
+{
+ /**
+ * Default constructor.
+ *
+ */
+ public DefaultDataOptions()
+ {
+ super(Type.CREATE_BASE_ENTRY, "dc=example,dc=com");
+ }
+
+ /**
+ * Get the number of entries that will be automatically generated.
+ *
+ * @return the number of entries that will be automatically generated.
+ */
+ public int getNumberEntries()
+ {
+ return 2000;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java b/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java
new file mode 100644
index 0000000..8c61e6d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/SetupLauncher.java
@@ -0,0 +1,257 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.quicksetup;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.offline.OfflineInstaller;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is called by the setup command lines to launch the installation of
+ * the Directory Server. It just checks the command line arguments and the
+ * environment and determines whether the graphical or the command line
+ * based setup much be launched.
+ *
+ */
+public class SetupLauncher
+{
+ private static String COMMAND_NAME_WINDOWS = "setup.bat";
+
+ private static String COMMAND_NAME_UNIX = "setup.sh";
+
+ /**
+ * The main method which is called by the setup command lines.
+ * @param args the arguments passed by the command lines. In the case
+ * we want to launch the cli setup they are basically the arguments that we
+ * will pass to the org.opends.server.tools.InstallDS class.
+ */
+ public static void main(String[] args)
+ {
+ boolean displayUsage = false;
+ boolean useCli = false;
+ if ((args != null) && (args.length > 0))
+ {
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i].equals("--cli"))
+ {
+ useCli = true;
+ }
+ }
+
+ if (!useCli)
+ {
+ if (args.length > 0)
+ {
+ if (args.length == 2)
+ {
+ /*
+ * Just ignore the -P argument that is passed by the setup command
+ * line.
+ */
+ if (!args[0].equals("-P"))
+ {
+ displayUsage = true;
+ }
+ } else
+ {
+ displayUsage = true;
+ }
+ }
+ }
+ }
+ if (displayUsage)
+ {
+ String arg;
+ if (Utils.isWindows())
+ {
+ arg = COMMAND_NAME_WINDOWS;
+ } else
+ {
+ arg = COMMAND_NAME_UNIX;
+ }
+ /*
+ * This is required because the usage message contains '{' characters that
+ * mess up the MessageFormat.format method.
+ */
+ String msg = getMsg("setup-launcher-usage");
+ msg = msg.replace("{0}", arg);
+ System.err.println(msg);
+ System.exit(1);
+ } else if (useCli)
+ {
+ int exitCode = launchCliSetup(args);
+ if (exitCode != 0)
+ {
+ System.exit(exitCode);
+ }
+ } else
+ {
+ int exitCode = launchGuiSetup(args);
+ if (exitCode != 0)
+ {
+ System.err.println(getMsg("setup-launcher-gui-launched-failed"));
+ exitCode = launchCliSetup(args);
+ if (exitCode != 0)
+ {
+ System.exit(exitCode);
+ }
+ }
+ }
+ }
+
+ /**
+ * Launches the command line based setup.
+ * @param args the arguments passed
+ * @return 0 if everything worked fine, and an error code if something wrong
+ * occurred (as specified in org.opends.server.tools.InstallDS).
+ * @see org.opends.server.tools.InstallDS
+ */
+ private static int launchCliSetup(String[] args)
+ {
+ if (Utils.isWindows())
+ {
+ System.setProperty("org.opends.server.scriptName",
+ COMMAND_NAME_WINDOWS);
+ } else
+ {
+ System.setProperty("org.opends.server.scriptName",
+ COMMAND_NAME_UNIX);
+ }
+ ArrayList<String> newArgList = new ArrayList<String>();
+ if (args != null)
+ {
+ for (int i = 0; i < args.length; i++)
+ {
+ if (!args[i].equalsIgnoreCase("--cli"))
+ {
+ newArgList.add(args[i]);
+ }
+ }
+ }
+ newArgList.add("--configClass");
+ newArgList.add("org.opends.server.extensions.ConfigFileHandler");
+ newArgList.add("--configFile");
+ newArgList.add(OfflineInstaller.CONFIG_FILE_NAME);
+
+ String[] newArgs = new String[newArgList.size()];
+ newArgList.toArray(newArgs);
+
+ return org.opends.server.tools.InstallDS.installMain(newArgs);
+ }
+
+ /**
+ * Launches the graphical setup. The graphical setup is launched in a
+ * different thread that the main thread because if we have a problem with the
+ * graphical system (for instance the DISPLAY environment variable is not
+ * correctly set) the native libraries will call exit. However if we launch
+ * this from another thread, the thread will just be killed.
+ *
+ * This code also assumes that if the call to SplashWindow.main worked (and
+ * the splash screen was displayed) we will never get out of it (we will call
+ * a System.exit() when we close the graphical setup dialog).
+ *
+ * @params String[] args the arguments used to call the SplashWindow main
+ * method
+ * @return 0 if everything worked fine, or 1 if we could not display properly
+ * the SplashWindow.
+ */
+ private static int launchGuiSetup(final String[] args)
+ {
+ System.out.println(getMsg("setup-launcher-launching-gui"));
+ final int[] returnValue =
+ { -1 };
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ SplashScreen.main(args);
+ returnValue[0] = 0;
+ }
+ });
+ /*
+ * This is done to avoid displaying the stack that might occur if there are
+ * problems with the display environment.
+ */
+ PrintStream printStream = System.err;
+ System.setErr(new EmptyPrintStream());
+ t.start();
+ try
+ {
+ t.join();
+ }
+ catch (InterruptedException ie)
+ {
+ /* An error occurred, so the return value will be -1. We got nothing to
+ do with this exception. */
+ }
+ System.setErr(printStream);
+ return returnValue[0];
+ }
+
+ /**
+ * The following three methods are just commodity methods to get localized
+ * messages.
+ */
+ private static String getMsg(String key)
+ {
+ return getI18n().getMsg(key);
+ }
+
+ private static ResourceProvider getI18n()
+ {
+ return ResourceProvider.getInstance();
+ }
+
+ /**
+ * This class is used to avoid displaying the error message related to display
+ * problems that we might have when trying to display the SplashWindow.
+ *
+ */
+ static class EmptyPrintStream extends PrintStream
+ {
+ /**
+ * Default constructor.
+ *
+ */
+ public EmptyPrintStream()
+ {
+ super(new ByteArrayOutputStream(), true);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void println(String msg)
+ {
+ }
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java b/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java
new file mode 100644
index 0000000..74533b6
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/SplashScreen.java
@@ -0,0 +1,281 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup;
+
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.awt.Toolkit;
+import java.awt.Window;
+
+import javax.swing.SwingUtilities;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is the class that is called to launch QuickSetup. It will display a
+ * splash screen and in the background it will create QuickSetup object.
+ *
+ * This class tries to minimize the time to be displayed. So it does the loading
+ * of the setup class in runtime once we already have displayed the splash
+ * screen. This is why the quickSetup variable is of type Object.
+ */
+public class SplashScreen extends Window
+{
+ private static final long serialVersionUID = 8918803902867388766L;
+
+ private Image image;
+
+ private static SplashScreen splash;
+
+ private static Object quickSetup;
+
+ private static Class<?> quickSetupClass;
+
+ // Constant for the display of the splash screen
+ private static final int MIN_SPLASH_DISPLAY = 3000;
+
+ /**
+ * The main method for this class.
+ * It can be called from the event thread and outside the event thread.
+ * @param args arguments to be passed to the method QuickSetup.initialize
+ */
+ public static void main(String[] args)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ final String[] fArgs = args;
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ mainOutsideEventThread(fArgs);
+ }
+ });
+ t.start();
+ } else
+ {
+ mainOutsideEventThread(args);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void update(Graphics g)
+ {
+ paint(g);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void paint(Graphics g)
+ {
+ g.drawImage(image, 0, 0, this);
+ }
+
+ /**
+ * Private constructor to force to use the main method.
+ *
+ */
+ private SplashScreen()
+ {
+ super(new Frame());
+ try
+ {
+ image = getSplashImage();
+ MediaTracker mt = new MediaTracker(this);
+ mt.addImage(image, 0);
+ mt.waitForID(0);
+
+ int width = image.getWidth(this);
+ int height = image.getHeight(this);
+ setPreferredSize(new Dimension(width, height));
+ setSize(width, height);
+ Utils.centerOnScreen(this);
+
+ } catch (Exception ex)
+ {
+ ex.printStackTrace(); // Bug
+ }
+ }
+
+ /**
+ * This method creates the image directly instead of using UIFactory to reduce
+ * class loading.
+ * @return the splash image.
+ */
+ private Image getSplashImage()
+ {
+ String resource = ResourceProvider.getInstance().getMsg("splash-icon");
+ resource = "org/opends/quicksetup/" + resource;
+ return Toolkit.getDefaultToolkit().createImage(
+ this.getClass().getClassLoader().getResource(resource));
+ }
+
+ /**
+ * This is basically the method that is execute in SplashScreen.main but it
+ * it assumes that is being called outside the event thread.
+ *
+ * @param args arguments to be passed to the method QuickSetup.initialize.
+ */
+ private static void mainOutsideEventThread(String[] args)
+ {
+ displaySplashScreen();
+ long splashDisplayStartTime = System.currentTimeMillis();
+ constructQuickSetup(args);
+ sleepIfNecessary(splashDisplayStartTime);
+ disposeSplashScreen();
+ displayQuickSetup();
+ }
+
+ /**
+ * This methods displays the splash screen.
+ * This method assumes that is being called outside the event thread.
+ */
+ private static void displaySplashScreen()
+ {
+ splash = new SplashScreen();
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable()
+ {
+ public void run()
+ {
+ splash.setVisible(true);
+ }
+ });
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * This methods constructs the QuickSetup object.
+ * This method assumes that is being called outside the event thread.
+ * @param args arguments to be passed to the method QuickSetup.initialize.
+ */
+ private static void constructQuickSetup(String[] args)
+ {
+ try
+ {
+ quickSetupClass = Class.forName("org.opends.quicksetup.QuickSetup");
+ quickSetup = quickSetupClass.newInstance();
+ quickSetupClass.getMethod("initialize", new Class[]
+ { String[].class }).invoke(quickSetup, new Object[]
+ { args });
+ } catch (Exception e)
+ {
+ InternalError error =
+ new InternalError("Failed to invoke initialize method");
+ error.initCause(e);
+ throw error;
+ }
+ }
+
+ /**
+ * This method displays the QuickSetup dialog.
+ * @see QuickSetup.display.
+ * This method assumes that is being called outside the event thread.
+ */
+ private static void displayQuickSetup()
+ {
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ quickSetupClass.getMethod("display").invoke(quickSetup);
+ } catch (Exception e)
+ {
+ InternalError error =
+ new InternalError("Failed to invoke display method");
+ error.initCause(e);
+ throw error;
+ }
+ }
+ });
+ } catch (Exception ex)
+ {
+ }
+ }
+
+ /**
+ * Disposes the splash screen.
+ * This method assumes that is being called outside the event thread.
+ */
+ private static void disposeSplashScreen()
+ {
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable()
+ {
+ public void run()
+ {
+ splash.setVisible(false);
+ splash.dispose();
+ }
+ });
+ } catch (Exception ex)
+ {
+ }
+ }
+
+ /**
+ * This method just executes an sleep depending on how long the splash
+ * screen has been displayed. The idea of calling this method is to have the
+ * splash screen displayed a minimum time (specified by
+ * MIN_SPLASH_DISPLAY).
+ * @param splashDisplayStartTime the time in milliseconds when the splash
+ * screen started displaying.
+ */
+ private static void sleepIfNecessary(long splashDisplayStartTime)
+ {
+ long t2 = System.currentTimeMillis();
+
+ long sleepTime = MIN_SPLASH_DISPLAY - (t2 - splashDisplayStartTime);
+
+ if (sleepTime > 0)
+ {
+ try
+ {
+ Thread.sleep(sleepTime);
+ } catch (Exception ex)
+ {
+ }
+ }
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/Step.java b/opends/src/quicksetup/org/opends/quicksetup/Step.java
new file mode 100644
index 0000000..bf590bb
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/Step.java
@@ -0,0 +1,62 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup;
+
+/**
+ * This enumeration just represents the different steps that we can have in
+ * the installation and uninstallation wizards.
+ *
+ */
+public enum Step
+
+{
+ /**
+ * Welcome step for the installation.
+ */
+ WELCOME,
+ /**
+ * Server Settings step (path, port, etc.).
+ */
+ SERVER_SETTINGS,
+ /**
+ * Data Options panel (suffix dn, LDIF path, etc.).
+ */
+ DATA_OPTIONS,
+ /**
+ * Review panel for the install.
+ */
+ REVIEW,
+ /**
+ * Progress panel.
+ */
+ PROGRESS,
+ /**
+ * Confirmation panel for the uninstallation.
+ */
+ CONFIRM_UNINSTALL
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/BrowseActionListener.java b/opends/src/quicksetup/org/opends/quicksetup/event/BrowseActionListener.java
new file mode 100644
index 0000000..159e9f7
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/BrowseActionListener.java
@@ -0,0 +1,177 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.event;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JFileChooser;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.util.ExtensionFileFilter;
+
+/**
+ * This class is an action listener used to update a text component. When the
+ * class receives an ActionEvent it will display a File Browser Dialog and will
+ * update the text field depending on what the user chooses in the browser
+ * dialog.
+ *
+ * The class is used generally by adding it as ActionListener of a 'Browse'
+ * button.
+ *
+ */
+public class BrowseActionListener implements ActionListener
+{
+ private JFileChooser fc;
+
+ private JTextComponent field;
+
+ private Component parent;
+
+ private BrowseType type;
+
+ /**
+ * Enumeration used to specify which kind of file browser dialog must be
+ * displayed.
+ *
+ */
+ public enum BrowseType
+ {
+ /**
+ * The Browser is used to retrieve a directory.
+ */
+ LOCATION_DIRECTORY,
+ /**
+ * The Browser is used to retrieve an LDIF file.
+ */
+ OPEN_LDIF_FILE
+ }
+
+ /**
+ * Constructor for the BrowseActionListener.
+ *
+ * @param field
+ * the text component that will be updated when the user selects
+ * something in the file browser dialog.
+ * @param type
+ * the type of file browse dialog that will be displayed.
+ * @param parent
+ * component that will be used as reference to display the file
+ * browse dialog.
+ */
+ public BrowseActionListener(JTextComponent field, BrowseType type,
+ Component parent)
+ {
+ this.field = field;
+ this.type = type;
+ this.parent = parent;
+
+ ResourceProvider i18n = ResourceProvider.getInstance();
+
+ fc = new JFileChooser();
+ switch (type)
+ {
+ case LOCATION_DIRECTORY:
+ fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ fc.setDialogType(JFileChooser.OPEN_DIALOG);
+ fc.setDialogTitle(i18n.getMsg("open-server-location-dialog-title"));
+ break;
+
+ case OPEN_LDIF_FILE:
+ fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ fc.setDialogType(JFileChooser.OPEN_DIALOG);
+ fc.setDialogTitle(i18n.getMsg("open-ldif-file-dialog-title"));
+ ExtensionFileFilter ldifFiles =
+ new ExtensionFileFilter("ldif",
+ i18n.getMsg("ldif-files-description"));
+
+ fc.addChoosableFileFilter(ldifFiles);
+ fc.setFileFilter(ldifFiles);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown BrowseType: " + type);
+ }
+ }
+
+ /**
+ * ActionListener implementation. It will display a file browser dialog and
+ * then will update the text component if the user selects something on the
+ * dialog.
+ *
+ * @param e the ActionEvent we receive.
+ *
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ int returnVal;
+
+ /* If we can get the current field parent directory set to it */
+ String path = field.getText();
+ if (path != null)
+ {
+ if (path.trim().length() > 0)
+ {
+ File f = new File(path);
+ while ((f != null) && !f.isDirectory())
+ {
+ f = f.getParentFile();
+ }
+ if (f != null)
+ {
+ fc.setCurrentDirectory(f);
+ }
+ }
+ }
+
+ switch (type)
+ {
+ case LOCATION_DIRECTORY:
+ returnVal = fc.showSaveDialog(parent);
+ break;
+
+ case OPEN_LDIF_FILE:
+ returnVal = fc.showOpenDialog(parent);
+ break;
+
+ default:
+ throw new IllegalStateException("Unknown type: " + type);
+ }
+
+ if (returnVal == JFileChooser.APPROVE_OPTION)
+ {
+ File file = fc.getSelectedFile();
+ field.setText(file.getAbsolutePath());
+ field.requestFocusInWindow();
+ field.selectAll();
+ }
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/ButtonActionListener.java b/opends/src/quicksetup/org/opends/quicksetup/event/ButtonActionListener.java
new file mode 100644
index 0000000..9ae9cb0
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/ButtonActionListener.java
@@ -0,0 +1,43 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.event;
+
+/**
+ * Interface used for the actions that are done in the wizard buttons (those
+ * specified in org.opends.quicksetup.ButtonName).
+ *
+ */
+public interface ButtonActionListener
+{
+ /**
+ * Method called when the user clicks on one of the buttons specifid in
+ * org.opends.quicksetup.ButtonName.
+ * @param event the button event
+ */
+ public void buttonActionPerformed(ButtonEvent event);
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/ButtonEvent.java b/opends/src/quicksetup/org/opends/quicksetup/event/ButtonEvent.java
new file mode 100644
index 0000000..e0fc9d8
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/ButtonEvent.java
@@ -0,0 +1,64 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.event;
+
+import java.util.EventObject;
+
+import org.opends.quicksetup.ButtonName;
+
+/**
+ * The event that is generated when the user clicks in one of the wizard buttons
+ * specified in org.opends.quicksetup.ButtonName.
+ *
+ */
+public class ButtonEvent extends EventObject
+{
+ private static final long serialVersionUID = -4411929136433332009L;
+
+ private ButtonName buttonName;
+
+ /**
+ * Constructor.
+ * @param source the button that generated the event
+ * @param buttonName the button name.
+ */
+ public ButtonEvent(Object source, ButtonName buttonName)
+ {
+ super(source);
+ this.buttonName = buttonName;
+ }
+
+ /**
+ * Gets the ButtonName of the button that generated the event.
+ * @return the ButtonName of the button that generated the event.
+ */
+ public ButtonName getButtonName()
+ {
+ return buttonName;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/MinimumSizeComponentListener.java b/opends/src/quicksetup/org/opends/quicksetup/event/MinimumSizeComponentListener.java
new file mode 100644
index 0000000..76dec7c
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/MinimumSizeComponentListener.java
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.event;
+
+import java.awt.Component;
+import java.awt.Window;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+
+/**
+ * This class is used to not allowing the user to reduce the size of a component
+ * below a certain size. When we want to set a minimum size on an object we
+ * just create the object and then we add it as ComponentListener of the object.
+ *
+ * This is used basically by the QuickSetupDialog dialog.
+ *
+ */
+public class MinimumSizeComponentListener implements ComponentListener
+{
+ private Component comp;
+
+ private int minWidth;
+
+ private int minHeight;
+
+ /**
+ * Constructor for the MinimumSizeComponentListener.
+ *
+ * @param comp the component for which we want to set a minimum size
+ * @param minWidth the minimum width for the component
+ * @param minHeight the minimum height for the component
+ */
+ public MinimumSizeComponentListener(Component comp, int minWidth,
+ int minHeight)
+ {
+ this.comp = comp;
+ this.minWidth = minWidth + 2;
+ // It seems that we must add two points to the minWidth (the border of
+ // the frame)
+ if (comp instanceof Window)
+ {
+ this.minWidth += 2;
+ }
+
+ this.minHeight = minHeight;
+ }
+
+ /**
+ * ComponentListener implementation.
+ *
+ * When the method is called check the size and if it is below the minimum
+ * size specified in the constructor, resize it to the minimum size.
+ *
+ * @param ev the component event.
+ */
+ public void componentResized(ComponentEvent ev)
+ {
+ int width = comp.getWidth();
+ int height = comp.getHeight();
+ boolean resize = false;
+ if (width < minWidth)
+ {
+ resize = true;
+ width = minWidth;
+ }
+ if (height < minHeight)
+ {
+ resize = true;
+ height = minHeight;
+ }
+ if (resize)
+ {
+ comp.setSize(width, height);
+ }
+ }
+
+ /**
+ * ComponentListener implementation.
+ *
+ * Empty implementation.
+ * @param ev the component event.
+ */
+ public void componentMoved(ComponentEvent ev)
+ {
+ }
+
+ /**
+ * ComponentListener implementation.
+ *
+ * Empty implementation.
+ * @param ev the component event.
+ */
+ public void componentShown(ComponentEvent ev)
+ {
+ }
+
+ /**
+ * ComponentListener implementation.
+ *
+ * Empty implementation.
+ * @param ev the component event.
+ */
+ public void componentHidden(ComponentEvent ev)
+ {
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java b/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
new file mode 100644
index 0000000..f3c0e69
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateEvent.java
@@ -0,0 +1,107 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.event;
+
+import org.opends.quicksetup.installer.InstallProgressStep;
+
+/**
+ * The event that is generated when there is a change during the installation
+ * process (we get a new log message when starting the server, or we finished
+ * configuring the server for instance).
+ *
+ * In the current implementation this events are generated by the Installer
+ * objects and are notified to the objects implementing ProgressUpdateListener
+ * (QuickSetup object).
+ *
+ */
+public class ProgressUpdateEvent
+{
+ private InstallProgressStep step;
+
+ private Integer progressRatio;
+
+ private String currentPhaseSummary;
+
+ private String newLogs;
+
+ /**
+ * Constructor of the ProgressUpdateEvent.
+ * @param step the InstallProgressStep object describing in which step
+ * of the installation we are (configuring server, starting server, etc.)
+ * @param progressRatio the integer that specifies which percentage of
+ * the whole installation has been completed.
+ * @param currentPhaseSummary the localized summary message for the
+ * current installation progress.
+ * @param newLogs the new log messages that we have for the installation.
+ */
+ public ProgressUpdateEvent(InstallProgressStep step,
+ Integer progressRatio, String currentPhaseSummary, String newLogs)
+ {
+ this.step = step;
+ this.progressRatio = progressRatio;
+ this.currentPhaseSummary = currentPhaseSummary;
+ this.newLogs = newLogs;
+ }
+
+ /**
+ * Gets a localized message summary describing the install progress
+ * status.
+ * @return the localized message summary describing the progress status.
+ */
+ public String getCurrentPhaseSummary()
+ {
+ return currentPhaseSummary;
+ }
+
+ /**
+ * Gets the new logs for the install progress.
+ * @return the new logs for the current install progress.
+ */
+ public String getNewLogs()
+ {
+ return newLogs;
+ }
+
+ /**
+ * Gets the progress ratio for the install progress.
+ * @return the progress ratio for the install progress.
+ */
+ public Integer getProgressRatio()
+ {
+ return progressRatio;
+ }
+
+ /**
+ * Gets the current progress step.
+ * @return the current progress step.
+ */
+ public InstallProgressStep getProgressStep()
+ {
+ return step;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java b/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
new file mode 100644
index 0000000..5556a63
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/event/ProgressUpdateListener.java
@@ -0,0 +1,44 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.event;
+
+/**
+ * Interface that implement the objects that want to receive notifications of
+ * updates in the installation progress.
+ *
+ */
+public interface ProgressUpdateListener
+{
+ /**
+ * Method called when an update in the installation progress occurs.
+ *
+ * @param ev the ProgressUpdateEvent describing the update that occurred in
+ * the installation progress.
+ */
+ public void progressUpdate(ProgressUpdateEvent ev);
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java b/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
new file mode 100644
index 0000000..0d90ee8
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/i18n/ResourceProvider.java
@@ -0,0 +1,202 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.i18n;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to retrieve localized messages from Resources.properties
+ * files. The locale used currently is the default Locale of the JVM.
+ *
+ */
+public class ResourceProvider
+{
+ private ResourceBundle bundle;
+
+ private static ResourceProvider instance;
+
+ private static final String BUNDLE_NAME =
+ "org.opends.quicksetup.resources.Resources";
+
+ private ResourceProvider()
+ {
+ }
+
+ /**
+ * Provides an instance of the ResourceProvider. The instance is unique for
+ * this process (which implies that during the process lifetime we can only
+ * have messages in one language).
+ *
+ * @return an instance of ResourceProvider.
+ */
+ public static ResourceProvider getInstance()
+ {
+ if (instance == null)
+ {
+ instance = new ResourceProvider();
+ }
+ return instance;
+ }
+
+ /**
+ * Gets a localized message for a key value. In the properties file we have
+ * something of type:
+ * key=value
+ * @param key the key in the properties file.
+ * @return the value associated to the key in the properties file.
+ * @throws IllegalArgumentException if the key could not be found in the
+ * properties file.
+ */
+ public String getMsg(String key) throws IllegalArgumentException
+ {
+ String msg;
+ try
+ {
+ msg = getResourceBundle().getString(key);
+
+ } catch (java.util.MissingResourceException e)
+ {
+ // The less brutal alternative here is to do msg = key instead
+ // of
+ // throwing an exception but this helps being strict with
+ // resources
+ // (so I prefer to keep it as it is at least at the beginning)
+ throw new IllegalArgumentException("Unknown Resource Bundle key: " +
+ key);
+ }
+ return msg;
+ }
+
+ /**
+ * Gets a localized message for a key value. In the properties file we have
+ * something of type:
+ * key=value
+ *
+ * For instance if we pass as key "mykey" and as arguments {"value1"} and
+ * in the properties file we have:
+ * mykey=value with argument {0}.
+ *
+ * This method will return "value with argument value1".
+ *
+ * @param key the key in the properties file.
+ * @param args the arguments to be passed to generate the resulting value.
+ * @return the value associated to the key in the properties file.
+ * @throws IllegalArgumentException if the key could not be found in the
+ * properties file.
+ */
+ public String getMsg(String key, String[] args)
+ throws IllegalArgumentException
+ {
+ String msg;
+ try
+ {
+ String pattern = getResourceBundle().getString(key);
+ MessageFormat mf = new MessageFormat(pattern);
+
+ msg = mf.format(args);
+ } catch (java.util.MissingResourceException e)
+ {
+ // The less brutal alternative here is to do msg = key instead
+ // of
+ // throwing an exception but this helps being strict with
+ // resources
+ // (so I prefer to keep it as it is at least at the beginning)
+ throw new IllegalArgumentException("Unknown Resource Bundle key: " +
+ key);
+ }
+
+ return msg;
+ }
+
+ /**
+ * Indicates which is the Locale that will be used to determine the language
+ * of the messages.
+ *
+ * @return the Locale that will be used to determine the language of
+ * the messages.
+ */
+ public Locale getLocale()
+ {
+ return Locale.getDefault();
+ }
+
+ /**
+ * The ResourceBundle that will be used to get the localized messages.
+ * @return the ResourceBundle that will be used to get the localized
+ * messages.
+ */
+ private ResourceBundle getResourceBundle()
+ {
+ if (bundle == null)
+ {
+ try
+ {
+ if (Utils.isWebStart())
+ {
+ /*
+ * Construct a URLClassLoader using only the jar of quicksetup.jar
+ * when we are using Web Start. If we use the current classloader all
+ * the jars (including those marked as lazy) will be downloaded.
+ */
+ URL[] urls = new URL[]
+ { getQuickSetupJarURL() };
+ bundle =
+ ResourceBundle.getBundle(BUNDLE_NAME, getLocale(),
+ new URLClassLoader(urls));
+ } else
+ {
+ bundle =
+ ResourceBundle.getBundle(BUNDLE_NAME, getLocale(), this
+ .getClass().getClassLoader());
+ }
+ } catch (java.util.MissingResourceException e)
+ {
+ throw new IllegalStateException("Missing Resource Bundle: "
+ + BUNDLE_NAME);
+
+ }
+ }
+
+ return bundle;
+ }
+
+ /**
+ * Returns the URL of the Jar file that was used to retrieve this class.
+ * @return the URL of the Jar file that was used to retrieve this class.
+ */
+ private URL getQuickSetupJarURL()
+ {
+ return this.getClass().getProtectionDomain().getCodeSource().getLocation();
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.gif b/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.gif
new file mode 100644
index 0000000..668c644
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.png b/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.png
new file mode 100644
index 0000000..925ca3d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/currentstep.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/error.gif b/opends/src/quicksetup/org/opends/quicksetup/images/error.gif
new file mode 100644
index 0000000..c217b20
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/error.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/information.gif b/opends/src/quicksetup/org/opends/quicksetup/images/information.gif
new file mode 100644
index 0000000..3e39ea0
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/information.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opendsbackground.png b/opends/src/quicksetup/org/opends/quicksetup/images/opendsbackground.png
new file mode 100644
index 0000000..d911533
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opendsbackground.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimized.gif b/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimized.gif
new file mode 100644
index 0000000..e6a1fc0
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimized.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimizedmac.png b/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimizedmac.png
new file mode 100644
index 0000000..7e8c236
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opendsminimizedmac.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/opendssplash.png b/opends/src/quicksetup/org/opends/quicksetup/images/opendssplash.png
new file mode 100644
index 0000000..5237a7a
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/opendssplash.png
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/warning.gif b/opends/src/quicksetup/org/opends/quicksetup/images/warning.gif
new file mode 100644
index 0000000..42cc02d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/warning.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif b/opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif
new file mode 100755
index 0000000..8c002bf
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/images/warning_large.gif
Binary files differ
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/DataOptions.java b/opends/src/quicksetup/org/opends/quicksetup/installer/DataOptions.java
new file mode 100644
index 0000000..5b37cd6
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/DataOptions.java
@@ -0,0 +1,142 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+
+package org.opends.quicksetup.installer;
+
+/**
+ * This class is used to provide a data model for the Data Options panel of the
+ * installer.
+ *
+ */
+public class DataOptions
+{
+ /**
+ * This enumeration is used to know what the user wants to do for the data
+ * (import data or not, what use as source of the data...).
+ *
+ */
+ public enum Type
+ {
+ /**
+ * Create base entry.
+ */
+ CREATE_BASE_ENTRY,
+ /**
+ * Do not add any entry to the suffix.
+ */
+ LEAVE_DATABASE_EMPTY,
+ /**
+ * Import data from an LDIF file.
+ */
+ IMPORT_FROM_LDIF_FILE,
+ /**
+ * Generate data and import it to the suffix.
+ */
+ IMPORT_AUTOMATICALLY_GENERATED_DATA
+ }
+
+ private Type type;
+
+ private String baseDn;
+
+ private String ldifPath;
+
+ private int numberEntries;
+
+ /**
+ * Constructor for the DataOptions object.
+ *
+ * If the Data Options is IMPORT_FROM_LDIF_FILE the args are the baseDn and
+ * a String with the ldif location.
+ *
+ * If the Data Options is IMPORT_AUTOMATICALLY_GENERATED_DATA the args
+ * are the baseDn and an Integer with the number of entries.
+ *
+ * For the rest of the types the args are just the baseDn.
+ *
+ * @param type the Type of DataOptions.
+ * @param args the different argument objects (depending on the Type
+ * specified)
+ */
+ public DataOptions(Type type, Object... args)
+ {
+ this.type = type;
+ baseDn = (String) args[0];
+
+ switch (type)
+ {
+ case IMPORT_FROM_LDIF_FILE:
+ ldifPath = (String) args[1];
+ break;
+
+ case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+ numberEntries = ((Integer) args[1]).intValue();
+ break;
+ }
+ }
+
+ /**
+ * Returns the type of DataOptions represented by this object (import data or
+ * not, what use as source of the data...).
+ *
+ * @return the type of DataOptions.
+ */
+ public Type getType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the path of the LDIF file used to import data.
+ * @return the path of the LDIF file used to import data.
+ */
+ public String getLDIFPath()
+ {
+ return ldifPath;
+ }
+
+ /**
+ * Returns the number of entries that will be automatically generated.
+ *
+ * @return the number of entries that will be automatically generated.
+ */
+ public int getNumberEntries()
+ {
+ return numberEntries;
+ }
+
+ /**
+ * Returns the base DN of the suffix that will be created in the server.
+ *
+ * @return the base DN of the suffix that will be created in the server.
+ */
+ public String getBaseDn()
+ {
+ return baseDn;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java b/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java
new file mode 100644
index 0000000..c3d9dcf
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/FieldName.java
@@ -0,0 +1,82 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+/**
+ * This is an enumeration used to identify the different fields that we have
+ * in the Installation wizard.
+ *
+ * Note that each field is not necessarily associated
+ * with a single Swing component (for instance we have two text fields for
+ * the server location). This enumeration is used to retrieve information from
+ * the panels without having any knowledge of the actual graphical layout.
+ *
+ */
+public enum FieldName
+{
+ /**
+ * The value associated with this is a String.
+ */
+ SERVER_LOCATION,
+ /**
+ * The value associated with this is a String.
+ */
+ SERVER_PORT,
+ /**
+ * The value associated with this is a String.
+ */
+ DIRECTORY_MANAGER_DN,
+ /**
+ * The value associated with this is a String.
+ */
+ DIRECTORY_MANAGER_PWD,
+ /**
+ * The value associated with this is a String.
+ */
+ DIRECTORY_MANAGER_PWD_CONFIRM,
+ /**
+ * The value associated with this is a String.
+ */
+ DIRECTORY_BASE_DN, // the value associated with this is a String
+ /**
+ * The value associated with this is a DataOptions.Type.
+ */
+ DATA_OPTIONS,
+ /**
+ * The value associated with this is a String.
+ */
+ LDIF_PATH,
+ /**
+ * The value associated with this is a String.
+ */
+ NUMBER_ENTRIES,
+ /**
+ * The value associated with this is a Boolean.
+ */
+ SERVER_START
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java
new file mode 100644
index 0000000..6642d4e
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallException.java
@@ -0,0 +1,107 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+/**
+ * This exception is used to encapsulate all the error that we might have
+ * during the installation.
+ *
+ * @see Installer, WebStartInstaller, OfflineInstaller.
+ *
+ */
+public class InstallException extends Exception
+{
+ private static final long serialVersionUID = -3527273444231560341L;
+
+ private Type type;
+
+ /**
+ * This enum contains the different type of InstallException that we can
+ * have.
+ *
+ */
+ public enum Type
+ {
+ /**
+ * Error related to file system error: IOException writing files, permission
+ * errors, etc.
+ */
+ FILE_SYSTEM_ERROR,
+ /**
+ * Error downloading jar files from web start server. This is specific
+ * to the web start installation.
+ */
+ DOWNLOAD_ERROR,
+ /**
+ * Error during the configuration of the Directory Server.
+ */
+ CONFIGURATION_ERROR,
+ /**
+ * Error during the import of data (base entry, from LDIF file or
+ * automatically generated data).
+ */
+ IMPORT_ERROR,
+ /**
+ * Error starting the Open DS server.
+ */
+ START_ERROR,
+ /**
+ * A bug (for instance when we throw an IllegalStateException).
+ */
+ BUG
+ };
+
+ /**
+ * The constructor of the InstallException.
+ * @param type the type of error we have.
+ * @param localizedMsg a localized string describing the problem.
+ * @param rootCause the root cause of this exception.
+ */
+ public InstallException(Type type, String localizedMsg, Exception rootCause)
+ {
+ super(localizedMsg, rootCause);
+ this.type = type;
+ }
+
+ /**
+ * Returns the Type of this exception.
+ * @return the Type of this exception.
+ */
+ public Type getType()
+ {
+ return type;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return getMessage();
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressDescriptor.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressDescriptor.java
new file mode 100644
index 0000000..e87340f
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressDescriptor.java
@@ -0,0 +1,108 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+/**
+ * This class is used to describe the current state of the installation.
+ * It contains the step in which the installation is, the current progress
+ * ratio, the progress bar message and the details message (the logs).
+ *
+ * This class is used directly by the ProgressPanel to update its content
+ * and has been designed to match the layout of that panel. However as it
+ * does not contain any dependency in terms of code with any Swing or UI package
+ * component it has been decided to leave it on the installer package.
+ *
+ * In general the progress bar message and the details messages (log) are in
+ * HTML form (but this class is independent of the format we use for the
+ * messages).
+ *
+ */
+public class InstallProgressDescriptor
+{
+ private InstallProgressStep step;
+
+ private Integer progressBarRatio;
+
+ private String progressBarMsg;
+
+ private String detailsMsg;
+
+ /**
+ * Constructor for the InstallProgressDescriptor.
+ * @param step the current install step.
+ * @param progressBarRatio the completed progress ratio (in percentage).
+ * @param progressBarMsg the message to be displayed in the progress bar.
+ * @param detailsMsg the logs.
+ */
+ public InstallProgressDescriptor(InstallProgressStep step,
+ Integer progressBarRatio, String progressBarMsg, String detailsMsg)
+ {
+ this.step = step;
+ this.progressBarRatio = progressBarRatio;
+ this.progressBarMsg = progressBarMsg;
+ this.detailsMsg = detailsMsg;
+ }
+
+ /**
+ * Returns the details message (the log message) of the install.
+ * @return the details message (the log message) of the install.
+ */
+ public String getDetailsMsg()
+ {
+ return detailsMsg;
+ }
+
+ /**
+ * Returns the progress bar message.
+ * @return the progress bar message.
+ */
+ public String getProgressBarMsg()
+ {
+ return progressBarMsg;
+ }
+
+ /**
+ * Returns the progress bar ratio (the percentage of the install that is
+ * completed).
+ * @return the progress bar ratio (the percentage of the install that is
+ * completed).
+ */
+ public Integer getProgressBarRatio()
+ {
+ return progressBarRatio;
+ }
+
+ /**
+ * Returns the step of the install on which we are.
+ * @return the step of the install on which we are.
+ */
+ public InstallProgressStep getProgressStep()
+ {
+ return step;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java
new file mode 100644
index 0000000..0855f0d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java
@@ -0,0 +1,78 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+/**
+ * This enumeration describes the different installation steps in which we can
+ * be.
+ */
+public enum InstallProgressStep
+{
+ /**
+ * Install not started.
+ */
+ NOT_STARTED,
+ /**
+ * Downloading the remote jar files (this step is specific to the Web Start
+ * installation).
+ */
+ DOWNLOADING,
+ /**
+ * Extracting the zip file (this step is specific to the Web Start
+ * installation).
+ */
+ EXTRACTING,
+ /**
+ * Configuring server.
+ */
+ CONFIGURING_SERVER,
+ /**
+ * Creating base entry for the suffix.
+ */
+ CREATING_BASE_ENTRY,
+ /**
+ * Importing the contents of an LDIF file into the suffix.
+ */
+ IMPORTING_LDIF,
+ /**
+ * Importing generated data into the suffix.
+ */
+ IMPORTING_AUTOMATICALLY_GENERATED,
+ /**
+ * Starting Open DS server.
+ */
+ STARTING_SERVER,
+ /**
+ * Installation finished successfully.
+ */
+ FINISHED_SUCCESSFULLY,
+ /**
+ * Installation finished with an error.
+ */
+ FINISHED_WITH_ERROR
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
new file mode 100644
index 0000000..12110c7
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -0,0 +1,1429 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.quicksetup.installer;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.opends.quicksetup.event.ProgressUpdateEvent;
+import org.opends.quicksetup.event.ProgressUpdateListener;
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is an abstract class that is in charge of actually performing the
+ * installation.
+ *
+ * It just takes a UserInstallData object and based on that installs OpenDS.
+ *
+ * When there is an update during the installation it will notify the
+ * ProgressUpdateListener objects that have been added to it. The notification
+ * will send a ProgressUpdateEvent.
+ *
+ * This class is supposed to be fully independent of the graphical layout.
+ * However it is the most appropriate part of the code to generate well
+ * formatted messages. So it generates HTML messages in the
+ * ProgressUpdateEvent and to do so uses the UIFactory method.
+ *
+ * TODO pass an object in the constructor that would generate the messages.
+ * The problem of this approach is that the resulting interface of this object
+ * may be quite complex and could impact the lisibility of the code.
+ *
+ */
+public abstract class Installer
+{
+ /**
+ * The path to the Configuration LDIF file.
+ */
+ protected static final String CONFIG_PATH_RELATIVE =
+ "config" + File.separator + "config.ldif";
+
+ /**
+ * The relative path where all the binaries (scripts) are.
+ */
+ protected static final String BINARIES_PATH_RELATIVE = "bin";
+
+ /**
+ * The relative paths to the jar files required by the install.
+ */
+ protected static final String[] OPEN_DS_JAR_RELATIVE_PATHS =
+ { "lib/OpenDS.jar", "lib/je.jar" };
+
+ private HashSet<ProgressUpdateListener> listeners =
+ new HashSet<ProgressUpdateListener>();
+
+ private UserInstallData userData;
+
+ private String doneHtml;
+
+ /**
+ * The line break in HTML.
+ */
+ protected static String LINE_BREAK = "<br>";
+
+ /**
+ * The space in HTML.
+ */
+ protected static String SPACE = " ";
+
+ /**
+ * Constructor to be used by the subclasses.
+ * @param userData the user data definining the parameters of the
+ * installation.
+ */
+ protected Installer(UserInstallData userData)
+ {
+ this.userData = userData;
+ }
+
+ /**
+ * Adds a ProgressUpdateListener that will be notified of updates in the
+ * install progress.
+ * @param l the ProgressUpdateListener to be added.
+ */
+ public void addProgressUpdateListener(ProgressUpdateListener l)
+ {
+ listeners.add(l);
+ }
+
+ /**
+ * Removes a ProgressUpdateListener.
+ * @param l the ProgressUpdateListener to be removed.
+ */
+ public void removeProgressUpdateListener(ProgressUpdateListener l)
+ {
+ listeners.remove(l);
+ }
+
+ /**
+ * Returns whether the installer has finished or not.
+ * @return <CODE>true</CODE> if the install is finished or <CODE>false
+ * </CODE> if not.
+ */
+ public boolean isFinished()
+ {
+ return getStatus() == InstallProgressStep.FINISHED_SUCCESSFULLY
+ || getStatus() == InstallProgressStep.FINISHED_WITH_ERROR;
+ }
+
+ /**
+ * Start the installation process. This method will not block the thread on
+ * which is invoked.
+ */
+ public abstract void start();
+
+ /**
+ * An static String that contains the class name of ConfigFileHandler.
+ */
+ protected static final String CONFIG_CLASS_NAME =
+ "org.opends.server.extensions.ConfigFileHandler";
+
+
+ /**
+ * Returns the UserInstallData object representing the parameters provided by
+ * the user to do the installation.
+ *
+ * @return the UserInstallData object representing the parameters provided
+ * by the user to do the installation.
+ */
+ protected UserInstallData getUserData()
+ {
+ return userData;
+ }
+
+ /**
+ * This method notifies the ProgressUpdateListeners that there was an update
+ * in the installation progress.
+ * @param ratio the integer that specifies which percentage of
+ * the whole installation has been completed.
+ * @param currentPhaseSummary the localized summary message for the
+ * current installation progress in HTML form.
+ * @param newLogDetail the new log messages that we have for the
+ * installation in HTML form.
+ */
+ protected void notifyListeners(Integer ratio, String currentPhaseSummary,
+ String newLogDetail)
+ {
+ ProgressUpdateEvent ev =
+ new ProgressUpdateEvent(getStatus(), ratio, currentPhaseSummary,
+ newLogDetail);
+ for (ProgressUpdateListener l : listeners)
+ {
+ l.progressUpdate(ev);
+ }
+ }
+
+ /**
+ * Returns a localized message for a key value. In the properties file we
+ * have something of type:
+ * key=value
+ *
+ * @see ResourceProvider.getMsg(String key)
+ * @param key the key in the properties file.
+ * @return the value associated to the key in the properties file.
+ * properties file.
+ */
+ protected String getMsg(String key)
+ {
+ return getI18n().getMsg(key);
+ }
+
+ /**
+ * Returns a localized message for a key value. In the properties file we
+ * have something of type:
+ * key=value
+ *
+ * For instance if we pass as key "mykey" and as arguments {"value1"} and
+ * in the properties file we have:
+ * mykey=value with argument {0}.
+ *
+ * This method will return "value with argument value1".
+ * @see ResourceProvider.getMsg(String key, String[] args)
+ * @param key the key in the properties file.
+ * @param args the arguments to be passed to generate the resulting value.
+ * @return the value associated to the key in the properties file.
+ */
+ protected String getMsg(String key, String[] args)
+ {
+ return getI18n().getMsg(key, args);
+ }
+
+ /**
+ * Returns a ResourceProvider instance.
+ * @return a ResourceProvider instance.
+ */
+ protected ResourceProvider getI18n()
+ {
+ return ResourceProvider.getInstance();
+ }
+
+ /**
+ * Returns a localized message for a given properties key an exception.
+ * @param key the key of the message in the properties file.
+ * @param ex the exception for which we want to get a message.
+ * @return a localized message for a given properties key an exception.
+ */
+ protected String getExceptionMsg(String key, Exception ex)
+ {
+ return getExceptionMsg(key, null, ex);
+ }
+
+ /**
+ * Returns a localized message for a given properties key an exception.
+ * @param key the key of the message in the properties file.
+ * @param args the arguments of the message in the properties file.
+ * @param ex the exception for which we want to get a message.
+ *
+ * @return a localized message for a given properties key an exception.
+ */
+ protected String getExceptionMsg(String key, String[] args, Exception ex)
+ {
+ return Utils.getExceptionMsg(getI18n(), key, args, ex);
+ }
+
+ /**
+ * Returns the HTML representation of an error for a given text.
+ * @param text the source text from which we want to get the HTML
+ * representation
+ * @return the HTML representation of an error for the given text.
+ */
+ protected String getHtmlError(String text)
+ {
+ String html =
+ UIFactory.getIconHtml(UIFactory.IconType.ERROR)
+ + SPACE
+ + SPACE
+ + UIFactory.applyFontToHtml(getHtml(text),
+ UIFactory.PROGRESS_ERROR_FONT);
+
+ String result = UIFactory.applyErrorBackgroundToHtml(html);
+ return result;
+ }
+
+ /**
+ * Returns the HTML representation of an warning for a given text.
+ * @param text the source text from which we want to get the HTML
+ * representation
+ * @return the HTML representation of an warning for the given text.
+ */
+ protected String getHtmlWarning(String text)
+ {
+ String html =
+ UIFactory.getIconHtml(UIFactory.IconType.WARNING)
+ + SPACE
+ + SPACE
+ + UIFactory.applyFontToHtml(getHtml(text),
+ UIFactory.PROGRESS_WARNING_FONT);
+
+ String result = UIFactory.applyWarningBackgroundToHtml(html);
+ return result;
+ }
+
+ /**
+ * Returns the HTML representation of a success message for a given text.
+ * @param text the source text from which we want to get the HTML
+ * representation
+ * @return the HTML representation of an success message for the given text.
+ */
+ protected String getHtmlSuccess(String text)
+ {
+ // Note: the text we get already is in HTML form
+ String html =
+ UIFactory.getIconHtml(UIFactory.IconType.INFORMATION) + SPACE
+ + SPACE + UIFactory.applyFontToHtml(text, UIFactory.PROGRESS_FONT);
+
+ String result = UIFactory.applySuccessfulBackgroundToHtml(html);
+ return result;
+ }
+
+ /**
+ * Returns the HTML representation of a log error message for a given text.
+ * @param text the source text from which we want to get the HTML
+ * representation
+ * @return the HTML representation of a log error message for the given text.
+ */
+ protected String getHtmlLogError(String text)
+ {
+ String html = getHtml(text);
+ return UIFactory.applyFontToHtml(html,
+ UIFactory.PROGRESS_LOG_ERROR_FONT);
+ }
+
+ /**
+ * Returns the HTML representation of a log message for a given text.
+ * @param text the source text from which we want to get the HTML
+ * representation
+ * @return the HTML representation of a log message for the given text.
+ */
+ protected String getHtmlLog(String text)
+ {
+ String html = getHtml(text);
+ return UIFactory.applyFontToHtml(html, UIFactory.PROGRESS_LOG_FONT);
+ }
+
+ /**
+ * Returns the HTML representation of the 'Done' text string.
+ * @return the HTML representation of the 'Done' text string.
+ */
+ protected String getHtmlDone()
+ {
+ if (doneHtml == null)
+ {
+ String html = getHtml(getMsg("progress-done"));
+ doneHtml = UIFactory.applyFontToHtml(html,
+ UIFactory.PROGRESS_DONE_FONT);
+ }
+ return doneHtml;
+ }
+
+ /**
+ * Returns the HTML representation of the argument text to which we add
+ * points. For instance if we pass as argument 'Configuring Server' the
+ * return value will be 'Configuring Server <B>.....</B>'.
+ * @param text the String to which add points.
+ * @return the HTML representation of the '.....' text string.
+ */
+ protected String getHtmlWithPoints(String text)
+ {
+ String html = getHtml(text);
+ String points = SPACE + getHtml(getMsg("progress-points")) + SPACE;
+
+ StringBuffer buf = new StringBuffer();
+ buf.append(UIFactory.applyFontToHtml(html, UIFactory.PROGRESS_FONT))
+ .append(
+ UIFactory.applyFontToHtml(points, UIFactory.PROGRESS_POINTS_FONT));
+
+ return buf.toString();
+ }
+
+ /**
+ * Returns the HTML representation for a given text. without adding any kind
+ * of font or style elements. Just escapes the problematic characters
+ * (like '<') and transform the break lines into '\n' characters.
+ *
+ * @param text the source text from which we want to get the HTML
+ * representation
+ * @return the HTML representation for the given text.
+ */
+ protected String getHtml(String text)
+ {
+ StringBuffer buffer = new StringBuffer();
+ text = text.replaceAll("\r\n", "\n");
+ String[] lines = text.split("[\n\r\u0085\u2028\u2029]");
+ for (int i = 0; i < lines.length; i++)
+ {
+ if (i != 0)
+ {
+ buffer.append("<br>");
+ }
+ buffer.append(escape(lines[i]));
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the HTML representation of a progress message for a given text.
+ * @param text the source text from which we want to get the HTML
+ * representation
+ * @return the HTML representation of a progress message for the given text.
+ */
+ protected String getHtmlProgress(String text)
+ {
+ return UIFactory.applyFontToHtml(getHtml(text),
+ UIFactory.PROGRESS_FONT);
+ }
+
+ /**
+ * Returns the HTML representation of an error message for a given exception.
+ * This method applies a margin if the applyMargin parameter is
+ * <CODE>true</CODE>.
+ * @param ex the exception.
+ * @param applyMargin specifies whether we apply a margin or not to the
+ * resulting HTML.
+ * @return the HTML representation of an error message for the given
+ * exception.
+ */
+ protected String getHtmlError(Exception ex, boolean applyMargin)
+ {
+ String openDiv = "<div style=\"margin-left:5px; margin-top:10px\">";
+ String hideText =
+ UIFactory.applyFontToHtml(getMsg("hide-exception-details"),
+ UIFactory.PROGRESS_FONT);
+ String showText =
+ UIFactory.applyFontToHtml(getMsg("show-exception-details"),
+ UIFactory.PROGRESS_FONT);
+ String closeDiv = "</div>";
+
+ StringBuffer stackBuf = new StringBuffer();
+ stackBuf.append(getHtmlStack(ex));
+ Throwable root = ex.getCause();
+ while (root != null)
+ {
+ stackBuf.append(getHtml(getMsg("exception-root-cause")) + LINE_BREAK);
+ stackBuf.append(getHtmlStack(root));
+ root = root.getCause();
+ }
+ String stackText =
+ UIFactory.applyFontToHtml(stackBuf.toString(), UIFactory.STACK_FONT);
+
+ StringBuffer buf = new StringBuffer();
+
+ String msg = ex.getMessage();
+ if (msg != null)
+ {
+ buf.append(UIFactory.applyFontToHtml(getHtml(ex.getMessage()),
+ UIFactory.PROGRESS_ERROR_FONT)
+ + LINE_BREAK);
+ } else
+ {
+ buf.append(ex.toString() + LINE_BREAK);
+ }
+ buf.append(getErrorWithStackHtml(openDiv, hideText, showText, stackText,
+ closeDiv, false));
+
+ String html =
+ UIFactory.getIconHtml(UIFactory.IconType.ERROR) + SPACE + SPACE
+ + buf.toString();
+
+ String result;
+ if (applyMargin)
+ {
+ result =
+ UIFactory.applyMargin(UIFactory.applyErrorBackgroundToHtml(html),
+ UIFactory.TOP_INSET_ERROR_MESSAGE, 0, 0, 0);
+ } else
+ {
+ result = UIFactory.applyErrorBackgroundToHtml(html);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a HTML representation of the stack trace of a Throwable object.
+ * @param ex the throwable object from which we want to obtain the stack
+ * trace HTML representation.
+ * @return a HTML representation of the stack trace of a Throwable object.
+ */
+ private String getHtmlStack(Throwable ex)
+ {
+ StringBuffer buf = new StringBuffer();
+ StackTraceElement[] stack = ex.getStackTrace();
+ for (int i = 0; i < stack.length; i++)
+ {
+ buf.append(SPACE + SPACE + SPACE + SPACE + SPACE + SPACE + SPACE +
+ SPACE + SPACE + SPACE + getHtml(stack[i].toString()) + LINE_BREAK);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Returns the HTML representation of a plain text string which is obtained
+ * by converting some special characters (like '<') into its equivalent
+ * escaped HTML representation.
+ *
+ * @param rawString the String from which we want to obtain the HTML
+ * representation.
+ * @return the HTML representation of the plain text string.
+ */
+ private String escape(String rawString)
+ {
+ int toto;
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < rawString.length(); i++)
+ {
+ char c = rawString.charAt(i);
+ switch (c)
+ {
+ case '<':
+ buffer.append("<");
+ break;
+
+ case '>':
+ buffer.append(">");
+ break;
+
+ case '&':
+ buffer.append("&");
+ break;
+
+ case '"':
+ buffer.append(""");
+ break;
+
+ default:
+ buffer.append(c);
+ break;
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the HTML representation of an exception in the
+ * progress log.<BR>
+ * We can have something of type:<BR><BR>
+ *
+ * An error occurred. java.io.IOException could not connect to server.<BR>
+ * <A HREF="">Show Details</A>
+ *
+ * When the user clicks on 'Show Details' the whole stack will be displayed.
+ *
+ * An error occurred. java.io.IOException could not connect to server.<BR>
+ * <A HREF="">Hide Details</A><BR>
+ * ... And here comes all the stack trace representation<BR>
+ *
+ *
+ * As the object that listens to this hyperlink events is not here (it is
+ * QuickSetupStepPanel) we must include all the information somewhere. The
+ * chosen solution is to include everything in the URL using parameters.
+ * This everything consists of:
+ * The open div tag for the text.
+ * The text that we display when we do not display the exception.
+ * The text that we display when we display the exception.
+ * The stack trace text.
+ * The closing div.
+ * A boolean informing if we are hiding the exception or not (to know in the
+ * next event what must be displayed).
+ *
+ * @param openDiv the open div tag for the text.
+ * @param hideText the text that we display when we do not display the
+ * exception.
+ * @param showText the text that we display when we display the exception.
+ * @param stackText the stack trace text.
+ * @param closeDiv the closing div.
+ * @param hide a boolean informing if we are hiding the exception or not.
+ * @return the HTML representation of an error message with an stack trace.
+ */
+ private static String getErrorWithStackHtml(String openDiv, String hideText,
+ String showText, String stackText, String closeDiv, boolean hide)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ String params =
+ getUrlParams(openDiv, hideText, showText, stackText, closeDiv, hide);
+ try
+ {
+ String text = hide ? hideText : showText;
+ buf.append(openDiv + "<a href=\"http://").append(
+ URLEncoder.encode(params, "UTF-8") + "\">" + text + "</a>");
+ if (hide)
+ {
+ buf.append(LINE_BREAK + stackText);
+ }
+ buf.append(closeDiv);
+
+ } catch (UnsupportedEncodingException uee)
+ {
+ // Bug
+ throw new IllegalStateException("UTF-8 is not supported ", uee);
+ }
+
+ return buf.toString();
+ }
+
+ private static String PARAM_SEPARATOR = "&&&&";
+
+ /**
+ * Gets the url parameters of the href we construct in getErrorWithStackHtml.
+ * @see getErrorWithStackHtml
+ * @param openDiv the open div tag for the text.
+ * @param hideText the text that we display when we do not display the
+ * exception.
+ * @param showText the text that we display when we display the exception.
+ * @param stackText the stack trace text.
+ * @param closeDiv the closing div.
+ * @param hide a boolean informing if we are hiding the exception or not.
+ * @return the url parameters of the href we construct in getHrefString.
+ */
+ private static String getUrlParams(String openDiv, String hideText,
+ String showText, String stackText, String closeDiv, boolean hide)
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append(openDiv + PARAM_SEPARATOR);
+ buf.append(hideText + PARAM_SEPARATOR);
+ buf.append(showText + PARAM_SEPARATOR);
+ buf.append(stackText + PARAM_SEPARATOR);
+ buf.append(closeDiv + PARAM_SEPARATOR);
+ buf.append(hide);
+ return buf.toString();
+ }
+
+ /**
+ * Returns the log HTML representation after the user has clicked on a url.
+ *
+ * @see getErrorWithStackHtml
+ * @param url that has been clicked
+ * @param lastText the HTML representation of the log before clicking on the
+ * url.
+ * @return the log HTML representation after the user has clicked on a url.
+ */
+ public static String getHtmlAfterUrlClick(String url, String lastText)
+ {
+ String urlText = getErrorWithStackHtml(url, false);
+ String newUrlText = getErrorWithStackHtml(url, true);
+
+ int index = lastText.indexOf(urlText);
+ if (index == -1)
+ {
+ System.out.println("lastText: " + lastText);
+ System.out.println("does not contain: " + urlText);
+ } else
+ {
+ lastText =
+ lastText.substring(0, index) + newUrlText
+ + lastText.substring(index + urlText.length());
+ }
+ return lastText;
+ }
+
+ /**
+ * Returns the HTML representation of an exception in the
+ * progress log for a given url.
+ * @see getHrefString
+ * @param url the url containing all the information required to retrieve
+ * the HTML representation.
+ * @param inverse indicates whether we want to 'inverse' the representation
+ * or not. For instance if the url specifies that the stack is being hidden
+ * and this parameter is <CODE>true</CODE> the resulting HTML will display
+ * the stack.
+ * @return the HTML representation of an exception in the progress log for a
+ * given url.
+ */
+ private static String getErrorWithStackHtml(String url, boolean inverse)
+ {
+ String p = url.substring("http://".length());
+ try
+ {
+ p = URLDecoder.decode(p, "UTF-8");
+ } catch (UnsupportedEncodingException uee)
+ {
+ // Bug
+ throw new IllegalStateException("UTF-8 is not supported ", uee);
+ }
+ String params[] = p.split(PARAM_SEPARATOR);
+ int i = 0;
+ String openDiv = params[i++];
+ String hideText = params[i++];
+ String showText = params[i++];
+ String stackText = params[i++];
+ String closeDiv = params[i++];
+ boolean isHide = new Boolean(params[i]);
+
+ if (isHide)
+ {
+ return getErrorWithStackHtml(openDiv, hideText, showText, stackText,
+ closeDiv, !inverse);
+ } else
+ {
+ return getErrorWithStackHtml(openDiv, hideText, showText, stackText,
+ closeDiv, inverse);
+ }
+ }
+
+ /**
+ * Creates a template file based in the contents of the UserData object.
+ * This template file is used to generate automatically data. To generate
+ * the template file the code will basically take into account the value of
+ * the base dn and the number of entries to be generated.
+ *
+ * @return the file object pointing to the create template file.
+ * @throws InstallException if an error occurs.
+ */
+ protected File createTemplateFile() throws InstallException
+ {
+ File templateFile = null;
+ String baseDn = getUserData().getDataOptions().getBaseDn();
+ int nEntries = getUserData().getDataOptions().getNumberEntries();
+ try
+ {
+ templateFile = File.createTempFile("opends-template-file", ".template");
+ templateFile.deleteOnExit();
+ } catch (IOException ioe)
+ {
+ String failedMsg = getExceptionMsg("error-creating-temp-file", null, ioe);
+ throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+ failedMsg, ioe);
+ }
+
+ StringBuffer buf = new StringBuffer();
+ buf.append("define suffix=" + baseDn);
+ if (nEntries > 0)
+ {
+ buf.append("\ndefine numusers=" + nEntries);
+ }
+
+ buf.append("\n").append("\nbranch: [suffix]").append("\n");
+ buf.append("\nbranch: ou=People,[suffix]");
+
+ if (nEntries > 0)
+ {
+ buf.append("\nsubordinateTemplate: person:[numusers]")
+ .append("\n")
+ .append("\ntemplate: person")
+ .append("\nrdnAttr: uid")
+ .append("\nobjectClass: top")
+ .append("\nobjectClass: person")
+ .append("\nobjectClass: organizationalPerson")
+ .append("\nobjectClass: inetOrgPerson")
+ .append("\ngivenName: <first>")
+ .append("\nsn: <last>")
+ .append("\ncn: {givenName} {sn}")
+ .append("\ninitials: {givenName:1}")
+ .append("<random:chars:ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}")
+ .append("\nemployeeNumber: <sequential:0>")
+ .append("\nuid: user.{employeeNumber}")
+ .append("\nmail: {uid}@maildomain.net")
+ .append("\nuserPassword: password")
+ .append("\ntelephoneNumber: <random:telephone>")
+ .append("\nhomePhone: <random:telephone>")
+ .append("\npager: <random:telephone>")
+ .append("\nmobile: <random:telephone>")
+ .append("\nstreet: <random:numeric:5> <file:streets> Street")
+ .append("\nl: <file:cities>")
+ .append("\nst: <file:states>")
+ .append("\npostalCode: <random:numeric:5>")
+ .append("\npostalAddress: {cn}${street}${l}, {st} {postalCode}")
+ .append("\ndescription: This is the description for {cn}.");
+ }
+
+ String path = templateFile.getAbsolutePath();
+ try
+ {
+ Utils.createFile(path, buf.toString());
+ } catch (IOException ioe)
+ {
+ String[] arg =
+ { path };
+ String failedMsg =
+ getExceptionMsg("error-writing-to-temp-file", arg, ioe);
+ throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+ failedMsg, ioe);
+ }
+
+ return templateFile;
+ }
+
+ /**
+ * This method is called when a new log message has been received. It will
+ * notify the ProgressUpdateListeners of this fact.
+ * @param newLogDetail the new log detail.
+ */
+ protected void notifyListeners(String newLogDetail)
+ {
+ Integer ratio = getRatio(getStatus());
+ String currentPhaseSummary = getSummary(getStatus());
+ notifyListeners(ratio, currentPhaseSummary, newLogDetail);
+ }
+
+ /**
+ * Returns the current InstallProgressStep of the installation process.
+ * @return the current InstallProgressStep of the installation process.
+ */
+ protected abstract InstallProgressStep getStatus();
+
+ /**
+ * Returns an integer that specifies which percentage of the whole
+ * installation has been completed.
+ * @param step the InstallProgressStep for which we want to get the ratio.
+ * @return an integer that specifies which percentage of the whole
+ * installation has been completed.
+ */
+ protected abstract Integer getRatio(InstallProgressStep step);
+
+ /**
+ * Returns an HTML representation of the summary for the specified
+ * InstallProgressStep.
+ * @param step the InstallProgressStep for which we want to get the summary
+ * @return an HTML representation of the summary for the specified
+ * InstallProgressStep.
+ */
+ protected abstract String getSummary(InstallProgressStep step);
+
+ /**
+ * This class is used to read the standard error and standard output of the
+ * Start process.
+ *
+ * When a new log message is found notifies the ProgressUpdateListeners of
+ * it. If an error occurs it also notifies the listeners.
+ *
+ */
+ abstract class StartReader
+ {
+ private InstallException ex;
+
+ private boolean isFinished;
+
+ private boolean isFirstLine;
+
+ /**
+ * The protected constructor.
+ * @param reader the BufferedReader of the start process.
+ * @param startedId the message ID that this class can use to know whether
+ * the start is over or not.
+ * @param isError a boolean indicating whether the BufferedReader
+ * corresponds to the standard error or to the standard output.
+ */
+ protected StartReader(final BufferedReader reader, final String startedId,
+ final boolean isError)
+ {
+ final String errorTag =
+ isError ? "error-reading-erroroutput" : "error-reading-output";
+
+ isFirstLine = true;
+
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ String line = reader.readLine();
+ while (line != null)
+ {
+ StringBuffer buf = new StringBuffer();
+ if (!isFirstLine)
+ {
+ buf.append(LINE_BREAK);
+ }
+ if (isError)
+ {
+ buf.append(getHtmlLogError(line));
+ } else
+ {
+ buf.append(getHtmlLog(line));
+ }
+ notifyListeners(buf.toString());
+ isFirstLine = false;
+
+ if (line.indexOf("id=" + startedId) != -1)
+ {
+ isFinished = true;
+ }
+ line = reader.readLine();
+ }
+ } catch (IOException ioe)
+ {
+ String errorMsg = getExceptionMsg(errorTag, ioe);
+ ex =
+ new InstallException(InstallException.Type.START_ERROR,
+ errorMsg, ioe);
+
+ } catch (RuntimeException re)
+ {
+ String errorMsg = getExceptionMsg(errorTag, re);
+ ex =
+ new InstallException(InstallException.Type.START_ERROR,
+ errorMsg, re);
+ }
+ isFinished = true;
+ }
+ });
+ t.start();
+ }
+
+ /**
+ * Returns the InstallException that occurred reading the Start error and
+ * output or <CODE>null</CODE> if no exception occurred.
+ * @return the exception that occurred reading or <CODE>null</CODE> if
+ * no exception occurred.
+ */
+ public InstallException getException()
+ {
+ return ex;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the server starting process finished
+ * (successfully or not) and <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if the server starting process finished
+ * (successfully or not) and <CODE>false</CODE> otherwise.
+ */
+ public boolean isFinished()
+ {
+ return isFinished;
+ }
+ }
+
+ /**
+ * A subclass of the StartReader class used to read the standard error of the
+ * server start.
+ *
+ */
+ protected class StartErrorReader extends StartReader
+ {
+ /**
+ * Constructor of the StartErrorReader.
+ * @param reader the BufferedReader that reads the standard error of the
+ * Start process.
+ * @param startedId the Message ID that
+ */
+ public StartErrorReader(BufferedReader reader, String startedId)
+ {
+ super(reader, startedId, true);
+ }
+ }
+
+ /**
+ * A subclass of the StartReader class used to read the standard output of
+ * the server start.
+ *
+ */
+ protected class StartOutputReader extends StartReader
+ {
+ /**
+ * Constructor of the StartOutputReader.
+ * @param reader the BufferedReader that reads the standard output of the
+ * Start process.
+ * @param startedId the Message ID that
+ */
+ public StartOutputReader(BufferedReader reader, String startedId)
+ {
+ super(reader, startedId, false);
+ }
+ }
+
+ /**
+ * This class is used to notify the ProgressUpdateListeners of events that
+ * are written to the standard error. It is used in WebStartInstaller and in
+ * OfflineInstaller. These classes just create a ErrorPrintStream and then
+ * they do a call to System.err with it.
+ *
+ * The class just reads what is written to the standard error, obtains an
+ * HTML representation of it and then notifies the ProgressUpdateListeners
+ * with the HTML messages.
+ *
+ */
+ protected class ErrorPrintStream extends PrintStream
+ {
+ private boolean isFirstLine;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public ErrorPrintStream()
+ {
+ super(new ByteArrayOutputStream(), true);
+ isFirstLine = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void println(String msg)
+ {
+ if (isFirstLine)
+ {
+ notifyListeners(getHtmlLogError(msg));
+ } else
+ {
+ notifyListeners(LINE_BREAK + getHtmlLogError(msg));
+ }
+ isFirstLine = false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void write(byte[] b, int off, int len)
+ {
+ if (b == null)
+ {
+ throw new NullPointerException("b is null");
+ }
+
+ if (off + len > b.length)
+ {
+ throw new IndexOutOfBoundsException(
+ "len + off are bigger than the length of the byte array");
+ }
+ println(new String(b, off, len));
+ }
+ }
+
+ /**
+ * This class is used to notify the ProgressUpdateListeners of events that are
+ * written to the standard output. It is used in WebStartInstaller and in
+ * OfflineInstaller. These classes just create a OutputPrintStream and then
+ * they do a call to System.err with it.
+ *
+ * The class just reads what is written to the standard output, obtains an
+ * HTML representation of it and then notifies the ProgressUpdateListeners
+ * with the HTML messages.
+ *
+ */
+ protected class OutputPrintStream extends PrintStream
+ {
+ private boolean isFirstLine;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public OutputPrintStream()
+ {
+ super(new ByteArrayOutputStream(), true);
+ isFirstLine = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void println(String msg)
+ {
+ if (isFirstLine)
+ {
+ notifyListeners(getHtmlLog(msg));
+ } else
+ {
+ notifyListeners(LINE_BREAK + getHtmlLog(msg));
+ }
+ isFirstLine = false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void write(byte[] b, int off, int len)
+ {
+ if (b == null)
+ {
+ throw new NullPointerException("b is null");
+ }
+
+ if (off + len > b.length)
+ {
+ throw new IndexOutOfBoundsException(
+ "len + off are bigger than the length of the byte array");
+ }
+
+ println(new String(b, off, len));
+ }
+ }
+
+ /**
+ * This methods configures the server based on the contents of the UserData
+ * object provided in the constructor.
+ * @throws InstallException if something goes wrong.
+ */
+ protected void configureServer() throws InstallException
+ {
+ notifyListeners(getHtmlWithPoints(getMsg("progress-configuring")));
+
+ ArrayList<String> argList = new ArrayList<String>();
+ argList.add("-C");
+ argList.add(CONFIG_CLASS_NAME);
+
+ argList.add("-c");
+ argList.add(getConfigFilePath());
+ argList.add("-p");
+ argList.add(String.valueOf(getUserData().getServerPort()));
+
+ argList.add("-D");
+ argList.add(getUserData().getDirectoryManagerDn());
+
+ argList.add("-w");
+ argList.add(getUserData().getDirectoryManagerPwd());
+
+ argList.add("-b");
+ argList.add(getUserData().getDataOptions().getBaseDn());
+
+ String[] args = new String[argList.size()];
+ argList.toArray(args);
+ try
+ {
+ InstallerHelper helper = new InstallerHelper();
+ int result = helper.invokeConfigureServer(args);
+
+ if (result != 0)
+ {
+ throw new InstallException(
+ InstallException.Type.CONFIGURATION_ERROR,
+ getMsg("error-configuring"), null);
+ }
+ } catch (RuntimeException re)
+ {
+ throw new InstallException(
+ InstallException.Type.CONFIGURATION_ERROR,
+ getExceptionMsg("error-configuring", null, re), re);
+ }
+ }
+
+ /**
+ * This methods creates the base entry for the suffix based on the contents of
+ * the UserData object provided in the constructor.
+ * @throws InstallException if something goes wrong.
+ */
+ protected void createBaseEntry() throws InstallException
+ {
+ String[] arg =
+ { getUserData().getDataOptions().getBaseDn() };
+ notifyListeners(getHtmlWithPoints(getMsg("progress-creating-base-entry",
+ arg)));
+
+ InstallerHelper helper = new InstallerHelper();
+ String baseDn = getUserData().getDataOptions().getBaseDn();
+ File tempFile = helper.createBaseEntryTempFile(baseDn);
+
+ ArrayList<String> argList = new ArrayList<String>();
+ argList.add("-C");
+ argList.add(CONFIG_CLASS_NAME);
+
+ argList.add("-f");
+ argList.add(getConfigFilePath());
+
+ argList.add("-n");
+ argList.add(getBackendName());
+
+ argList.add("-l");
+ argList.add(tempFile.getAbsolutePath());
+
+ argList.add("-q");
+
+ String[] args = new String[argList.size()];
+ argList.toArray(args);
+
+ try
+ {
+ int result = helper.invokeImportLDIF(args);
+
+ if (result != 0)
+ {
+ throw new InstallException(
+ InstallException.Type.CONFIGURATION_ERROR,
+ getMsg("error-creating-base-entry"), null);
+ }
+ } catch (RuntimeException re)
+ {
+ throw new InstallException(
+ InstallException.Type.CONFIGURATION_ERROR,
+ getExceptionMsg("error-creating-base-entry", null, re), re);
+ }
+
+ notifyListeners(getHtmlDone());
+ }
+
+ /**
+ * This methods imports the contents of an LDIF file based on the contents of
+ * the UserData object provided in the constructor.
+ * @throws InstallException if something goes wrong.
+ */
+ protected void importLDIF() throws InstallException
+ {
+ String[] arg =
+ { getUserData().getDataOptions().getLDIFPath() };
+ notifyListeners(getHtmlProgress(getMsg("progress-importing-ldif", arg))
+ + LINE_BREAK);
+
+ ArrayList<String> argList = new ArrayList<String>();
+ argList.add("-C");
+ argList.add(CONFIG_CLASS_NAME);
+
+ argList.add("-f");
+ argList.add(getConfigFilePath());
+ argList.add("-n");
+ argList.add(getBackendName());
+ argList.add("-l");
+ argList.add(getUserData().getDataOptions().getLDIFPath());
+
+ String[] args = new String[argList.size()];
+ argList.toArray(args);
+
+ try
+ {
+ InstallerHelper helper = new InstallerHelper();
+ int result = helper.invokeImportLDIF(args);
+
+ if (result != 0)
+ {
+ throw new InstallException(
+ InstallException.Type.CONFIGURATION_ERROR,
+ getMsg("error-importing-ldif"), null);
+ }
+ } catch (RuntimeException re)
+ {
+ throw new InstallException(
+ InstallException.Type.CONFIGURATION_ERROR,
+ getExceptionMsg("error-importing-ldif", null, re), re);
+ }
+ }
+
+ /**
+ * This methods imports automatically generated data based on the contents
+ * of the UserData object provided in the constructor.
+ * @throws InstallException if something goes wrong.
+ */
+ protected void importAutomaticallyGenerated() throws InstallException
+ {
+ File templatePath = createTemplateFile();
+ int nEntries = getUserData().getDataOptions().getNumberEntries();
+ String[] arg =
+ { String.valueOf(nEntries) };
+ notifyListeners(getHtmlProgress(getMsg(
+ "progress-import-automatically-generated", arg))
+ + LINE_BREAK);
+
+ ArrayList<String> argList = new ArrayList<String>();
+ argList.add("-C");
+ argList.add(CONFIG_CLASS_NAME);
+
+ argList.add("-f");
+ argList.add(getConfigFilePath());
+ argList.add("-n");
+ argList.add(getBackendName());
+ argList.add("-t");
+ argList.add(templatePath.getAbsolutePath());
+ argList.add("-S");
+ argList.add("0");
+
+ String[] args = new String[argList.size()];
+ argList.toArray(args);
+
+ try
+ {
+ InstallerHelper helper = new InstallerHelper();
+ int result = helper.invokeImportLDIF(args);
+
+ if (result != 0)
+ {
+ throw new InstallException(
+ InstallException.Type.CONFIGURATION_ERROR,
+ getMsg("error-import-automatically-generated"), null);
+ }
+ } catch (RuntimeException re)
+ {
+ throw new InstallException(
+ InstallException.Type.CONFIGURATION_ERROR,
+ getExceptionMsg("error-import-automatically-generated", null, re),
+ re);
+ }
+ }
+
+ /**
+ * This methods starts the server.
+ * @throws InstallException if something goes wrong.
+ */
+ protected void startServer() throws InstallException
+ {
+ notifyListeners(getHtmlProgress(getMsg("progress-starting")) + LINE_BREAK);
+
+ ArrayList<String> argList = new ArrayList<String>();
+
+ if (Utils.isWindows())
+ {
+ argList.add(Utils.getPath(getBinariesPath(), "start-ds.bat"));
+ } else
+ {
+ argList.add(Utils.getPath(getBinariesPath(), "start-ds"));
+ }
+ String[] env =
+ { "JAVA_HOME=" + System.getProperty("java.home") };
+
+ try
+ {
+ String startedId = getStartedId();
+
+ String[] args = new String[argList.size()];
+ argList.toArray(args);
+ // Process process = Runtime.getRuntime().exec(args);
+ Process process = Runtime.getRuntime().exec(args, env);
+
+ BufferedReader err =
+ new BufferedReader(new InputStreamReader(process.getErrorStream()));
+ BufferedReader out =
+ new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+ StartErrorReader errReader = new StartErrorReader(err, startedId);
+ StartOutputReader outputReader = new StartOutputReader(out, startedId);
+
+ while (!errReader.isFinished() && !outputReader.isFinished())
+ {
+ try
+ {
+ Thread.sleep(100);
+ } catch (InterruptedException ie)
+ {
+ }
+ }
+ // Check if something wrong occurred reading the starting of the server
+ InstallException ex = errReader.getException();
+ if (ex == null)
+ {
+ ex = outputReader.getException();
+ }
+ if (ex != null)
+ {
+ throw ex;
+
+ } else
+ {
+ /*
+ * There are no exceptions from the readers and they are marked as
+ * finished. This means that the server has written in its output the
+ * message id informing that it started. So it seems that everything
+ * went fine.
+ */
+ }
+
+ } catch (IOException ioe)
+ {
+ throw new InstallException(InstallException.Type.START_ERROR,
+ getExceptionMsg("error-starting-server", ioe), ioe);
+ }
+ }
+
+ /**
+ * Returns the class path (using the class path separator which is platform
+ * dependent) required to run Open DS server.
+ * @return the class path required to run Open DS server.
+ */
+ protected abstract String getOpenDSClassPath();
+
+ /**
+ * Returns the config file path.
+ * @return the config file path.
+ */
+ protected abstract String getConfigFilePath();
+
+ /**
+ * Returns the path to the binaries.
+ * @return the path to the binaries.
+ */
+ protected abstract String getBinariesPath();
+
+ /**
+ * Updates the contents of the provided map with the localized summary
+ * strings.
+ * @param hmSummary the Map to be updated.
+ */
+ protected void initSummaryMap(
+ Map<InstallProgressStep, String> hmSummary)
+ {
+ hmSummary.put(InstallProgressStep.NOT_STARTED,
+ UIFactory.applyFontToHtml(
+ getMsg("summary-not-started"), UIFactory.PROGRESS_FONT));
+ hmSummary.put(InstallProgressStep.DOWNLOADING,
+ UIFactory.applyFontToHtml(
+ getMsg("summary-downloading"), UIFactory.PROGRESS_FONT));
+ hmSummary.put(InstallProgressStep.EXTRACTING,
+ UIFactory.applyFontToHtml(
+ getMsg("summary-extracting"), UIFactory.PROGRESS_FONT));
+ hmSummary.put(InstallProgressStep.CONFIGURING_SERVER,
+ UIFactory.applyFontToHtml(getMsg("summary-configuring"),
+ UIFactory.PROGRESS_FONT));
+ hmSummary.put(InstallProgressStep.CREATING_BASE_ENTRY, UIFactory
+ .applyFontToHtml(getMsg("summary-creating-base-entry"),
+ UIFactory.PROGRESS_FONT));
+ hmSummary.put(InstallProgressStep.IMPORTING_LDIF, UIFactory
+ .applyFontToHtml(getMsg("summary-importing-ldif"),
+ UIFactory.PROGRESS_FONT));
+ hmSummary.put(
+ InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
+ UIFactory.applyFontToHtml(
+ getMsg("summary-importing-automatically-generated"),
+ UIFactory.PROGRESS_FONT));
+ hmSummary.put(InstallProgressStep.STARTING_SERVER, UIFactory
+ .applyFontToHtml(getMsg("summary-starting"),
+ UIFactory.PROGRESS_FONT));
+ hmSummary.put(InstallProgressStep.FINISHED_SUCCESSFULLY, "<html>"
+ + getHtmlSuccess(getMsg("summary-finished-successfully")));
+ hmSummary.put(InstallProgressStep.FINISHED_WITH_ERROR, "<html>"
+ + getHtmlError(getMsg("summary-finished-with-error")));
+ }
+
+ /**
+ * Returns the Message ID indicating that the server has started.
+ * @return the Message ID indicating that the server has started.
+ */
+ private String getStartedId()
+ {
+ InstallerHelper helper = new InstallerHelper();
+ return helper.getStartedId();
+ }
+
+ /**
+ * Returns the default backend name (the one that will be created).
+ * @return the default backend name (the one that will be created).
+ */
+ protected String getBackendName()
+ {
+ return "userRoot";
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
new file mode 100644
index 0000000..bd333a9
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
@@ -0,0 +1,153 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.webstart.JnlpProperties;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is the only class that uses classes in org.opends.server (excluding the
+ * case of org.opends.server.util.DynamicConstants which is already included in
+ * quicksetup.jar).
+ *
+ * Important note: do not include references to the classes in package
+ * org.opends.server in the import. These classes must be loaded during
+ * Runtime.
+ * The code is written in a way that when we execute the code that uses these
+ * classes the required jar files are already loaded. However these jar files
+ * are not necessarily loaded when we create this class.
+ */
+class InstallerHelper implements JnlpProperties
+{
+
+ /**
+ * Invokes the method ConfigureDS.configMain with the provided parameters.
+ * @param args the arguments to be passed to ConfigureDS.configMain.
+ * @return the return code of the ConfigureDS.configMain method.
+ * @throws InstallException if something goes wrong.
+ * @see org.opends.server.tools.ConfigureDS.configMain(args).
+ */
+ public int invokeConfigureServer(String[] args) throws InstallException
+ {
+ return org.opends.server.tools.ConfigureDS.configMain(args);
+ }
+
+ /**
+ * Invokes the method ImportLDIF.mainImportLDIF with the provided parameters.
+ * @param args the arguments to be passed to ImportLDIF.mainImportLDIF.
+ * @return the return code of the ImportLDIF.mainImportLDIF method.
+ * @throws InstallException if something goes wrong.
+ * @see org.opends.server.tools.ImportLDIF.mainImportLDIF(args).
+ */
+ public int invokeImportLDIF(String[] args) throws InstallException
+ {
+ return org.opends.server.tools.ImportLDIF.mainImportLDIF(args);
+ }
+
+ /**
+ * Returns the Message ID that corresponds to a successfully started server.
+ * @return the Message ID that corresponds to a successfully started server.
+ */
+ public String getStartedId()
+ {
+ return String.valueOf(org.opends.server.messages.CoreMessages.
+ MSGID_DIRECTORY_SERVER_STARTED);
+ }
+
+ private String getExceptionMsg(String key, Exception ex)
+ {
+ return getExceptionMsg(key, null, ex);
+ }
+
+ private String getExceptionMsg(String key, String[] args, Exception ex)
+ {
+ return Utils.getExceptionMsg(ResourceProvider.getInstance(), key, args, ex);
+ }
+
+ /**
+ * Creates a template LDIF file with an entry that has as dn the provided
+ * baseDn.
+ * @param baseDn the dn of the entry that will be created in the LDIF file.
+ * @return the File object pointing to the created temporary file.
+ * @throws InstallException if something goes wrong.
+ */
+ public File createBaseEntryTempFile(String baseDn) throws InstallException
+ {
+ File ldifFile = null;
+ try
+ {
+ ldifFile = File.createTempFile("opends-base-entry", ".ldif");
+ ldifFile.deleteOnExit();
+ } catch (IOException ioe)
+ {
+ String failedMsg = getExceptionMsg("error-creating-temp-file", null, ioe);
+ throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+ failedMsg, ioe);
+ }
+
+ try
+ {
+ org.opends.server.types.LDIFExportConfig exportConfig =
+ new org.opends.server.types.LDIFExportConfig(ldifFile
+ .getAbsolutePath(),
+ org.opends.server.types.ExistingFileBehavior.OVERWRITE);
+
+ org.opends.server.util.LDIFWriter writer =
+ new org.opends.server.util.LDIFWriter(exportConfig);
+
+ org.opends.server.types.DN dn =
+ org.opends.server.types.DN.decode(baseDn);
+ org.opends.server.types.Entry entry =
+ org.opends.server.util.StaticUtils.createEntry(dn);
+
+ writer.writeEntry(entry);
+ writer.close();
+ } catch (org.opends.server.types.DirectoryException de)
+ {
+ throw new InstallException(InstallException.Type.CONFIGURATION_ERROR,
+ getExceptionMsg("error-importing-ldif", null, de), de);
+ } catch (org.opends.server.util.LDIFException le)
+ {
+ throw new InstallException(InstallException.Type.CONFIGURATION_ERROR,
+ getExceptionMsg("error-importing-ldif", null, le), le);
+ } catch (IOException ioe)
+ {
+ throw new InstallException(InstallException.Type.CONFIGURATION_ERROR,
+ getExceptionMsg("error-importing-ldif", null, ioe), ioe);
+ } catch (RuntimeException re)
+ {
+ throw new InstallException(InstallException.Type.BUG, getExceptionMsg(
+ "bug-msg", re), re);
+ }
+ return ldifFile;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/LabelFieldDescriptor.java b/opends/src/quicksetup/org/opends/quicksetup/installer/LabelFieldDescriptor.java
new file mode 100644
index 0000000..f4b7bcd
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/LabelFieldDescriptor.java
@@ -0,0 +1,151 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+/**
+ * This is a commodity class used to couple a label and a text component with
+ * a FieldName. It is mainly used by the QuickSetupStepPanel classes to
+ * retrieve easily the labels and fields associated with a FieldName to provide
+ * its content or to mark the labels as valid or invalid. It is also used
+ * during the creation of the components as it describes the different
+ * properties.
+ */
+
+public class LabelFieldDescriptor
+{
+ private String label;
+
+ private String tooltip;
+
+ private FieldType type;
+
+ private LabelType labelType;
+
+ private int size;
+
+ /**
+ * This enum contains the different type of labels that can be associated with
+ * this LabelFieldDescriptor.
+ *
+ */
+ public enum LabelType
+ {
+ /**
+ * Primary label.
+ */
+ PRIMARY,
+ /**
+ * Secondary label.
+ */
+ SECONDARY
+ };
+
+ /**
+ * This enum contains the different type of fields that can be associated with
+ * this LabelFieldDescriptor.
+ *
+ */
+ public enum FieldType
+ {
+ /**
+ * Editable text field.
+ */
+ TEXTFIELD,
+ /**
+ * Password field.
+ */
+ PASSWORD,
+ /**
+ * Read only field.
+ */
+ READ_ONLY
+ };
+
+ /**
+ * Constructor of this LabelFieldDescriptor.
+ * @param label the String of the label.
+ * @param tooltip the tooltip of the field.
+ * @param type the type of field.
+ * @param labelType the type of label.
+ * @param size the size of the field.
+ */
+ public LabelFieldDescriptor(String label, String tooltip, FieldType type,
+ LabelType labelType, int size)
+ {
+ this.label = label;
+ this.tooltip = tooltip;
+ this.type = type;
+ this.labelType = labelType;
+ this.size = size;
+ }
+
+ /**
+ * Returns the String displayed by the label.
+ * @return the String displayed by the label.
+ */
+ public String getLabel()
+ {
+ return label;
+ }
+
+ /**
+ * Returns the size of the field.
+ * @return the size of the field.
+ */
+ public int getSize()
+ {
+ return size;
+ }
+
+ /**
+ * Returns the tooltip used in the field.
+ * @return the tooltip used in the field.
+ */
+ public String getTooltip()
+ {
+ return tooltip;
+ }
+
+ /**
+ * Returns the field type.
+ * @return the field type.
+ */
+ public FieldType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the label type.
+ * @return the label type.
+ */
+ public LabelType getLabelType()
+ {
+ return labelType;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallData.java b/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallData.java
new file mode 100644
index 0000000..f427bae
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallData.java
@@ -0,0 +1,166 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+/**
+ * This class is used to provide a data model for the different parameters
+ * that the user can provide in the installation wizard.
+ *
+ * @see DataOptions.
+ *
+ */
+public class UserInstallData
+{
+ private String serverLocation;
+
+ private int serverPort;
+
+ private String directoryManagerDn;
+
+ private String directoryManagerPwd;
+
+ private boolean startServer;
+
+ private DataOptions dataOptions;
+
+ /**
+ * Sets the location of the server (installation path).
+ * @param serverLocation the new server location (installation path).
+ */
+ public void setServerLocation(String serverLocation)
+ {
+ this.serverLocation = serverLocation;
+ }
+
+ /**
+ * Returns the location of the server (installation path).
+ * @return the location of the server (installation path).
+ */
+ public String getServerLocation()
+ {
+ return serverLocation;
+ }
+
+ /**
+ * Sets the server LDAP port.
+ * @param serverPort the new server LDAP port.
+ */
+ public void setServerPort(int serverPort)
+ {
+ this.serverPort = serverPort;
+ }
+
+ /**
+ * Returns the server LDAP port.
+ * @return the server LDAP port.
+ */
+ public int getServerPort()
+ {
+ return serverPort;
+ }
+
+ /**
+ * Returns the Directory Manager DN.
+ * @return the Directory Manager DN.
+ */
+ public String getDirectoryManagerDn()
+ {
+ return directoryManagerDn;
+ }
+
+ /**
+ * Sets the new Directory Manager DN.
+ * @param directoryManagerDn the new Directory Manager DN.
+ */
+ public void setDirectoryManagerDn(String directoryManagerDn)
+ {
+ this.directoryManagerDn = directoryManagerDn;
+ }
+
+ /**
+ * Returns the Directory Manager password.
+ * @return the Directory Manager password.
+ */
+ public String getDirectoryManagerPwd()
+ {
+ return directoryManagerPwd;
+ }
+
+ /**
+ * Sets the new Directory Manager password.
+ * @param directoryManagerPwd the new Directory Manager password.
+ */
+ public void setDirectoryManagerPwd(String directoryManagerPwd)
+ {
+ this.directoryManagerPwd = directoryManagerPwd;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the server must be started once the
+ * installation is finished, <CODE>false</CODE> if not.
+ * @return <CODE>true</CODE> if the server must be started once the
+ * installation is finished, <CODE>false</CODE> if not.
+ */
+ public boolean getStartServer()
+ {
+ return startServer;
+ }
+
+ /**
+ * Sets whether we want to start the server once the installation is finished
+ * or not.
+ * @param startServer the boolean indicating whether to start the server or
+ * not.
+ */
+ public void setStartServer(boolean startServer)
+ {
+ this.startServer = startServer;
+ }
+
+ /**
+ * Returns the DataOptions object representing the data in the Data Options
+ * panel.
+ * @return the DataOptions object representing the data in the Data Options
+ * panel.
+ */
+ public DataOptions getDataOptions()
+ {
+ return dataOptions;
+ }
+
+ /**
+ * Sets the DataOptions object representing the data in the Data Options
+ * panel.
+ * @param dataOptions the DataOptions object representing the data in the Data
+ * Options panel.
+ */
+ public void setDataOptions(DataOptions dataOptions)
+ {
+ this.dataOptions = dataOptions;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallDataException.java b/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallDataException.java
new file mode 100644
index 0000000..df16abe
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/UserInstallDataException.java
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer;
+
+import org.opends.quicksetup.Step;
+
+/**
+ * This exception is used when there is an error with the data provided by
+ * the user. It will be thrown by the class that is in charge of validating
+ * the user data (QuickSetup).
+ *
+ */
+public class UserInstallDataException extends Exception
+{
+ private static final long serialVersionUID = 1798143194655443132L;
+
+ private Step step;
+
+ private String localizedMessage;
+
+ /**
+ * Constructor for UserInstallDataException.
+ * @param step the step in the wizard where the exception occurred.
+ * @param localizedMessage the localized message describing the error.
+ */
+ public UserInstallDataException(Step step, String localizedMessage)
+ {
+ super(localizedMessage);
+ this.step = step;
+ this.localizedMessage = localizedMessage;
+ }
+
+ /**
+ * Returns the localized message describing the error that occurred.
+ * @return the localized message describing the error that occurred.
+ */
+ public String getLocalizedMessage()
+ {
+ return localizedMessage;
+ }
+
+ /**
+ * Returns the step of the wizard in which this exception occurred.
+ * @return the step of the wizard in which this exception occurred.
+ */
+ public Step getStep()
+ {
+ return step;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java b/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
new file mode 100644
index 0000000..8f5de38
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
@@ -0,0 +1,308 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer.offline;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.opends.quicksetup.installer.InstallException;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.Installer;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is an implementation of the Installer class that is used to install
+ * the Directory Server from a zip file. The installer assumes that the zip
+ * file contents have been unzipped.
+ *
+ * It just takes a UserInstallData object and based on that installs OpenDS.
+ *
+ * When there is an update during the installation it will notify the
+ * ProgressUpdateListener objects that have been added to it. The notification
+ * will send a ProgressUpdateEvent.
+ *
+ * This class is supposed to be fully independent of the graphical layout.
+ * However it is the most appropriate part of the code to generate well
+ * formatted messages. So it generates HTML messages in the
+ * ProgressUpdateEvent and to do so uses the UIFactory method.
+ *
+ * TODO pass an object in the constructor that would generate the messages.
+ * The problem of this approach is that the resulting interface of this object
+ * may be quite complex and could impact the lisibility of the code.
+ *
+ */
+public class OfflineInstaller extends Installer
+{
+ private static String fullInstallPath;
+
+ /* This map contains the ratio associated with each step */
+ private HashMap<InstallProgressStep, Integer> hmRatio =
+ new HashMap<InstallProgressStep, Integer>();
+
+ /* This map contains the summary associated with each step */
+ private HashMap<InstallProgressStep, String> hmSummary =
+ new HashMap<InstallProgressStep, String>();
+
+ private InstallProgressStep status;
+
+ static
+ {
+ /* Get the install path from the Class Path */
+ String sep = System.getProperty("path.separator");
+ String[] classPaths = System.getProperty("java.class.path").split(sep);
+ String path = null;
+ for (int i = 0; i < classPaths.length && (path == null); i++)
+ {
+ for (int j = 0; j < OPEN_DS_JAR_RELATIVE_PATHS.length &&
+ (path == null); j++)
+ {
+ String normPath = classPaths[i].replace(File.separatorChar, '/');
+ if (normPath.endsWith(OPEN_DS_JAR_RELATIVE_PATHS[j]))
+ {
+ path = classPaths[i];
+ }
+ }
+ }
+ File f = new File(path);
+ File binariesDir = f.getParentFile();
+ fullInstallPath = binariesDir.getParent();
+ }
+ /**
+ * A constant used to retrieve the full install path.
+ */
+ public static String FULL_INSTALL_PATH = fullInstallPath;
+
+ /**
+ * A constant used to retrieve the config file name.
+ */
+ public static String CONFIG_FILE_NAME =
+ Utils.getPath(FULL_INSTALL_PATH, CONFIG_PATH_RELATIVE);
+
+ /**
+ * OfflineInstaller constructor.
+ * @param userData the UserInstallData with the parameters provided by the
+ * user.
+ */
+ public OfflineInstaller(UserInstallData userData)
+ {
+ super(userData);
+ initMaps();
+ status = InstallProgressStep.NOT_STARTED;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void start()
+ {
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ doInstall();
+ }
+ });
+ t.start();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected InstallProgressStep getStatus()
+ {
+ return status;
+ }
+
+ /**
+ * Actually performs the start in this thread. The thread is blocked.
+ *
+ */
+ private void doInstall()
+ {
+ try
+ {
+ PrintStream err = new ErrorPrintStream();
+ PrintStream out = new OutputPrintStream();
+ System.setErr(err);
+ System.setOut(out);
+
+ status = InstallProgressStep.CONFIGURING_SERVER;
+ configureServer();
+
+ switch (getUserData().getDataOptions().getType())
+ {
+ case CREATE_BASE_ENTRY:
+ status = InstallProgressStep.CREATING_BASE_ENTRY;
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+ createBaseEntry();
+ break;
+ case IMPORT_FROM_LDIF_FILE:
+ status = InstallProgressStep.IMPORTING_LDIF;
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+ importLDIF();
+ break;
+ case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+ status = InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED;
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+ importAutomaticallyGenerated();
+ break;
+ }
+
+ if (getUserData().getStartServer())
+ {
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+ status = InstallProgressStep.STARTING_SERVER;
+ startServer();
+ }
+
+ status = InstallProgressStep.FINISHED_SUCCESSFULLY;
+ notifyListeners(null);
+
+ if (false)
+ throw new InstallException(InstallException.Type.DOWNLOAD_ERROR,
+ getMsg("error-zipinputstreamnull"), null);
+ } catch (InstallException ex)
+ {
+ if (ex.getCause() != null)
+ {
+ ex.getCause().printStackTrace();
+ }
+ status = InstallProgressStep.FINISHED_WITH_ERROR;
+ String html = getHtmlError(ex, true);
+ notifyListeners(html);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Integer getRatio(InstallProgressStep status)
+ {
+ return hmRatio.get(status);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getSummary(InstallProgressStep status)
+ {
+ return hmSummary.get(status);
+ }
+
+ /**
+ * Initialize the different map used in this class.
+ *
+ */
+ private void initMaps()
+ {
+ initSummaryMap(hmSummary);
+
+ /*
+ * hmTime contains the relative time that takes for each task to be
+ * accomplished. For instance if downloading takes twice the time of
+ * extracting, the value for downloading will be the double of the value for
+ * extracting.
+ */
+ HashMap<InstallProgressStep, Integer> hmTime =
+ new HashMap<InstallProgressStep, Integer>();
+ hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5);
+ hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10);
+ hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20);
+ hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
+ 20);
+ hmTime.put(InstallProgressStep.STARTING_SERVER, 10);
+
+ int totalTime = 0;
+ ArrayList<InstallProgressStep> steps =
+ new ArrayList<InstallProgressStep>();
+ totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER);
+ steps.add(InstallProgressStep.CONFIGURING_SERVER);
+ switch (getUserData().getDataOptions().getType())
+ {
+ case CREATE_BASE_ENTRY:
+ steps.add(InstallProgressStep.CREATING_BASE_ENTRY);
+ totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY);
+ break;
+ case IMPORT_FROM_LDIF_FILE:
+ steps.add(InstallProgressStep.IMPORTING_LDIF);
+ totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF);
+ break;
+ case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+ steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+ totalTime += hmTime.get(
+ InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+ break;
+ }
+ if (getUserData().getStartServer())
+ {
+ totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER);
+ steps.add(InstallProgressStep.STARTING_SERVER);
+ }
+
+ int cumulatedTime = 0;
+ for (InstallProgressStep s : steps)
+ {
+ Integer statusTime = hmTime.get(s);
+ hmRatio.put(s, (100 * cumulatedTime) / totalTime);
+ if (statusTime != null)
+ {
+ cumulatedTime += statusTime;
+ }
+ }
+ hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100);
+ hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getConfigFilePath()
+ {
+ return CONFIG_FILE_NAME;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getBinariesPath()
+ {
+ return Utils.getPath(FULL_INSTALL_PATH, BINARIES_PATH_RELATIVE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getOpenDSClassPath()
+ {
+ return System.getProperty("java.class.path");
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java
new file mode 100644
index 0000000..e8fa8d4
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/JnlpProperties.java
@@ -0,0 +1,57 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer.webstart;
+
+/**
+ * The following properties are set in the OpenDSQuickSetup.jnlp file to provide
+ * informations.
+ *
+ */
+public interface JnlpProperties
+{
+ /**
+ * Java property used to known if we are using web start or not.
+ */
+ public static final String IS_WEBSTART = "org.opends.quicksetup.iswebstart";
+
+ /**
+ * Java property used to know which are the jar files that must be downloaded
+ * lazily. The current code in WebStartDownloader that uses this property
+ * assumes that the URL are separated with an space.
+ */
+ public static final String LAZY_JAR_URLS =
+ "org.opends.quicksetup.lazyjarurls";
+
+ /**
+ * Java property used to know which is the name of the zip file that must
+ * be unzipped and whose contents must be extracted during the Web Start
+ * based setup.
+ */
+ public static final String ZIP_FILE_NAME =
+ "org.opends.quicksetup.zipfilename";
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java
new file mode 100644
index 0000000..4b82688
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartDownloader.java
@@ -0,0 +1,316 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer.webstart;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.jnlp.DownloadService;
+import javax.jnlp.DownloadServiceListener;
+import javax.jnlp.ServiceManager;
+import javax.jnlp.UnavailableServiceException;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.InstallException;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to download the files that have been marked as lazy
+ * in the OpenDSQuickSetup.jnlp file.
+ *
+ * The global idea is to force the user to download just one jar file
+ * (quicksetup.jar) to display the Web Start installer dialog. Then QuickSetup
+ * will call this class and it will download the jar files. Until this class is
+ * not finished the WebStartInstaller will be on the
+ * InstallProgressStep.DOWNLOADING step.
+ */
+public class WebStartDownloader implements DownloadServiceListener,
+ JnlpProperties
+{
+ private InstallException ex;
+
+ private boolean isFinished;
+
+ private int downloadPercentage = 0;
+
+ private int currentPercMin = 0;
+
+ private int currentPercMax = 0;
+
+ /**
+ * Starts the downloading of the jar files. If forceDownload is set to
+ * <CODE>true</CODE> the files will be re-downloaded even if they already
+ * are on cache.
+ *
+ * This method does not block the thread that calls it.
+ *
+ * @param forceDownload used to ignore the case and force download.
+ */
+ public void start(final boolean forceDownload)
+ {
+ isFinished = false;
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ startDownload(forceDownload);
+ } catch (MalformedURLException mfe)
+ {
+ mfe.printStackTrace();
+ // This is a bug
+ ex =
+ new InstallException(InstallException.Type.BUG, getExceptionMsg(
+ "bug-msg", mfe), mfe);
+ } catch (IOException ioe)
+ {
+ ioe.printStackTrace();
+ StringBuffer buf = new StringBuffer();
+ String[] jars = getJarUrls();
+ for (int i = 0; i < jars.length; i++)
+ {
+ if (i != 0)
+ {
+ buf.append(",");
+ }
+ buf.append(jars[i]);
+ }
+ String[] arg =
+ { buf.toString() };
+ ex =
+ new InstallException(InstallException.Type.DOWNLOAD_ERROR,
+ getExceptionMsg("downloading-error", arg, ioe), ioe);
+ } catch (RuntimeException re)
+ {
+ re.printStackTrace();
+ // This is a bug
+ ex =
+ new InstallException(InstallException.Type.BUG, getExceptionMsg(
+ "bug-msg", re), re);
+ }
+ }
+ });
+ t.start();
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the install is finished and
+ * <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if the install is finished and
+ * <CODE>false</CODE> otherwise.
+ */
+ public boolean isFinished()
+ {
+ return isFinished;
+ }
+
+ /**
+ * Returns the current download percentage.
+ * @return the current download percentage.
+ */
+ public int getDownloadPercentage()
+ {
+ return downloadPercentage;
+ }
+
+ /**
+ * Starts synchronously the downloading on this thread. The thread calling
+ * this method will be blocked. If forceDownload is set to
+ * <CODE>true</CODE> the files will be re-downloaded even if they already
+ * are on cache.
+ * @param forceDownload used to ignore the case and force download.
+ * @throws MalformedURLException if there is an error with the URL that we
+ * get from the JnlpProperties.
+ * @throws IOException if a network problem occurs.
+ */
+ private void startDownload(boolean forceDownload)
+ throws MalformedURLException, IOException
+ {
+ DownloadService ds;
+
+ try
+ {
+ ds =
+ (DownloadService) ServiceManager.lookup(
+ "javax.jnlp.DownloadService");
+ } catch (UnavailableServiceException e)
+ {
+ ds = null;
+ }
+
+ if (ds != null)
+ {
+ String[] urls = getJarUrls();
+ String[] versions = getJarVersions();
+
+ for (int i = 0; i < urls.length && (getException() == null); i++)
+ {
+ currentPercMin = (100 * i) / urls.length;
+ currentPercMax = (100 * (i + 1)) / urls.length;
+
+ // determine if a particular resource is cached
+ String sUrl = urls[i];
+ String version = versions[i];
+
+ URL url = new URL(sUrl);
+ boolean cached = ds.isResourceCached(url, version);
+
+ if (cached && forceDownload)
+ {
+ try
+ {
+ ds.removeResource(url, version);
+ } catch (IOException ioe)
+ {
+ }
+ cached = false;
+ }
+
+ if (!cached)
+ {
+ // if not in the cache load the resource into the cache
+ ds.loadResource(url, version, this);
+ }
+ }
+ }
+ isFinished = true;
+ }
+
+ /**
+ * Returns the InstallException that has occurred during the download or
+ * <CODE>null</CODE> if no exception occurred.
+ * @return the InstallException that has occurred during the download or
+ * <CODE>null</CODE> if no exception occurred.
+ */
+ public InstallException getException()
+ {
+ return ex;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void downloadFailed(URL url, String version)
+ {
+ ex =
+ new InstallException(InstallException.Type.DOWNLOAD_ERROR, getMsg(
+ "downloading-error", new String[]
+ { url.toString() }), null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void progress(URL url, String version, long readSoFar, long total,
+ int overallPercent)
+ {
+ if (overallPercent >= 0)
+ {
+ downloadPercentage = getPercentage(overallPercent);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void upgradingArchive(URL url, String version, int patchPercent,
+ int overallPercent)
+ {
+ if (overallPercent >= 0)
+ {
+ downloadPercentage = getPercentage(overallPercent);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void validating(URL url, String version, long entry, long total,
+ int overallPercent)
+ {
+ if (overallPercent >= 0)
+ {
+ downloadPercentage = getPercentage(overallPercent);
+ }
+ }
+
+ /**
+ * Returns the jar files in a String[] from the System properties.
+ * @return the jar files from the System properties.
+ */
+ private String[] getJarUrls()
+ {
+ String jars = System.getProperty(LAZY_JAR_URLS);
+ return jars.split(" ");
+ }
+
+
+ /**
+ * Returns the downloaded percentage based on how much of the current jar file
+ * has been downloaded.
+ * @param currentJarRatio the download ratio of the jar file that is being
+ * currently downloaded.
+ * @return the downloaded percentage based on how much of the current jar file
+ * has been downloaded.
+ */
+ private int getPercentage(int currentJarRatio)
+ {
+ int perc =
+ currentPercMin
+ + (currentJarRatio * (currentPercMax - currentPercMin) / 100);
+ return perc;
+ }
+
+ /**
+ * Returns the java jar versions in a String[]. Currently just returns some
+ * null strings.
+ * @return the java jar versions in a String[].
+ */
+ private String[] getJarVersions()
+ {
+ return new String[getJarUrls().length];
+ }
+
+ /* Some commodity methods to get localized messages */
+ private String getExceptionMsg(String key, Exception ex)
+ {
+ return getExceptionMsg(key, null, ex);
+ }
+
+ private String getExceptionMsg(String key, String[] args, Exception ex)
+ {
+ return Utils.getExceptionMsg(ResourceProvider.getInstance(), key, args, ex);
+ }
+
+ private String getMsg(String key, String[] args)
+ {
+ return ResourceProvider.getInstance().getMsg(key, args);
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
new file mode 100644
index 0000000..a5cbccb
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
@@ -0,0 +1,647 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer.webstart;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.opends.quicksetup.installer.InstallException;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.Installer;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is an implementation of the Installer class that is used to install
+ * the Directory Server using Web Start.
+ *
+ * It just takes a UserInstallData object and based on that installs OpenDS.
+ *
+ *
+ * This object has as parameter a WebStartDownloader object that is downloading
+ * some jar files. Until the WebStartDownloader has not finished downloading
+ * the jar files will be on the InstallProgressStep.DOWNLOADING step because
+ * we require all the jar files to be downloaded in order to install and
+ * configure the Directory Server.
+ *
+ * Based on the Java properties set through the OpenDSQuickSetup.jnlp file this
+ * class will retrieve the zip file containing the install, unzip it and extract
+ * it in the path specified by the user and that is contained in the
+ * UserInstallData object.
+ *
+ *
+ * When there is an update during the installation it will notify the
+ * ProgressUpdateListener objects that have been added to it. The notification
+ * will send a ProgressUpdateEvent.
+ *
+ * This class is supposed to be fully independent of the graphical layout.
+ * However it is the most appropriate part of the code to generate well
+ * formatted messages. So it generates HTML messages in the
+ * ProgressUpdateEvent and to do so uses the UIFactory method.
+ *
+ * TODO pass an object in the constructor that would generate the messages.
+ * The problem of this approach is that the resulting interface of this object
+ * may be quite complex and could impact the lisibility of the code.
+ *
+ */
+public class WebStartInstaller extends Installer implements JnlpProperties
+{
+ private HashMap<InstallProgressStep, Integer> hmRatio =
+ new HashMap<InstallProgressStep, Integer>();
+
+ private HashMap<InstallProgressStep, String> hmSummary =
+ new HashMap<InstallProgressStep, String>();
+
+ private InstallProgressStep status;
+
+ private WebStartDownloader loader;
+
+ /**
+ * WebStartInstaller constructor.
+ * @param userData the UserInstallData with the parameters provided by the
+ * user.
+ * @param loader the WebStartLoader that is used to download the remote jar
+ * files.
+ */
+ public WebStartInstaller(UserInstallData userData,
+ WebStartDownloader loader)
+ {
+ super(userData);
+ this.loader = loader;
+ initMaps();
+ status = InstallProgressStep.NOT_STARTED;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void start()
+ {
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ doInstall();
+ }
+ });
+ t.start();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected InstallProgressStep getStatus()
+ {
+ return status;
+ }
+
+ /**
+ * Actually performs the start in this thread. The thread is blocked.
+ *
+ */
+ private void doInstall()
+ {
+ try
+ {
+ PrintStream err = new ErrorPrintStream();
+ PrintStream out = new OutputPrintStream();
+ System.setErr(err);
+ System.setOut(out);
+
+ status = InstallProgressStep.DOWNLOADING;
+
+ InputStream in =
+ getZipInputStream(getRatio(InstallProgressStep.EXTRACTING));
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+
+ status = InstallProgressStep.EXTRACTING;
+ extractZipFiles(in, getRatio(InstallProgressStep.EXTRACTING),
+ getRatio(InstallProgressStep.CONFIGURING_SERVER));
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+
+ status = InstallProgressStep.CONFIGURING_SERVER;
+ configureServer();
+
+ switch (getUserData().getDataOptions().getType())
+ {
+ case CREATE_BASE_ENTRY:
+ status = InstallProgressStep.CREATING_BASE_ENTRY;
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+ createBaseEntry();
+ break;
+ case IMPORT_FROM_LDIF_FILE:
+ status = InstallProgressStep.IMPORTING_LDIF;
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+ importLDIF();
+ break;
+ case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+ status = InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED;
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+ importAutomaticallyGenerated();
+ break;
+ }
+
+ if (getUserData().getStartServer())
+ {
+ notifyListeners(UIFactory.HTML_SEPARATOR);
+ status = InstallProgressStep.STARTING_SERVER;
+ startServer();
+ }
+
+ status = InstallProgressStep.FINISHED_SUCCESSFULLY;
+ notifyListeners(null);
+
+ } catch (InstallException ex)
+ {
+ if (ex.getCause() != null)
+ {
+ ex.getCause().printStackTrace();
+ }
+ status = InstallProgressStep.FINISHED_WITH_ERROR;
+ String html = getHtmlError(ex, true);
+ notifyListeners(html);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Integer getRatio(InstallProgressStep status)
+ {
+ return hmRatio.get(status);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getSummary(InstallProgressStep status)
+ {
+ return hmSummary.get(status);
+ }
+
+ /**
+ * Initialize the different map used in this class.
+ *
+ */
+ private void initMaps()
+ {
+ initSummaryMap(hmSummary);
+
+ /*
+ * hmTime contains the relative time that takes for each task to be
+ * accomplished. For instance if downloading takes twice the time of
+ * extracting, the value for downloading will be the double of the value for
+ * extracting.
+ */
+ HashMap<InstallProgressStep, Integer> hmTime =
+ new HashMap<InstallProgressStep, Integer>();
+ hmTime.put(InstallProgressStep.DOWNLOADING, 15);
+ hmTime.put(InstallProgressStep.EXTRACTING, 15);
+ hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5);
+ hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10);
+ hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20);
+ hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
+ 20);
+ hmTime.put(InstallProgressStep.STARTING_SERVER, 10);
+
+ int totalTime = 0;
+ ArrayList<InstallProgressStep> steps =
+ new ArrayList<InstallProgressStep>();
+ totalTime += hmTime.get(InstallProgressStep.DOWNLOADING);
+ steps.add(InstallProgressStep.DOWNLOADING);
+ totalTime += hmTime.get(InstallProgressStep.EXTRACTING);
+ steps.add(InstallProgressStep.EXTRACTING);
+ totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER);
+ steps.add(InstallProgressStep.CONFIGURING_SERVER);
+ switch (getUserData().getDataOptions().getType())
+ {
+ case CREATE_BASE_ENTRY:
+ steps.add(InstallProgressStep.CREATING_BASE_ENTRY);
+ totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY);
+ break;
+ case IMPORT_FROM_LDIF_FILE:
+ steps.add(InstallProgressStep.IMPORTING_LDIF);
+ totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF);
+ break;
+ case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+ steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+ totalTime +=hmTime.get(
+ InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+ break;
+ }
+ if (getUserData().getStartServer())
+ {
+ totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER);
+ steps.add(InstallProgressStep.STARTING_SERVER);
+ }
+
+ int cumulatedTime = 0;
+ for (InstallProgressStep s : steps)
+ {
+ Integer statusTime = hmTime.get(s);
+ hmRatio.put(s, (100 * cumulatedTime) / totalTime);
+ if (statusTime != null)
+ {
+ cumulatedTime += statusTime;
+ }
+ }
+
+ hmRatio.put(InstallProgressStep.FINISHED_SUCCESSFULLY, 100);
+ hmRatio.put(InstallProgressStep.FINISHED_WITH_ERROR, 100);
+ }
+
+ private InputStream getZipInputStream(Integer maxRatio)
+ throws InstallException
+ {
+ notifyListeners(getHtmlWithPoints(getMsg("progress-downloading")));
+ InputStream in = null;
+
+ waitForLoader(maxRatio);
+
+ in =
+ Installer.class.getClassLoader().getResourceAsStream(getZipFileName());
+
+ if (in == null)
+ {
+ // Retry once
+ loader.start(true);
+ waitForLoader(maxRatio);
+ in =
+ Installer.class.getClassLoader()
+ .getResourceAsStream(getZipFileName());
+
+ if (in == null)
+ {
+ throw new InstallException(InstallException.Type.DOWNLOAD_ERROR,
+ getMsg("error-zipinputstreamnull"), null);
+ }
+ }
+
+ notifyListeners(getHtmlDone());
+ return in;
+ }
+
+ /**
+ * Waits for the loader to be finished. Every time we have an update in the
+ * percentage that is downloaded we notify the listeners of this.
+ *
+ * @param maxRatio is the integer value that tells us which is the max ratio
+ * that corresponds to the download. It is used to calculate how the global
+ * installation ratio changes when the download ratio increases. For instance
+ * if we suppose that the download takes 25 % of the total installation
+ * process, then maxRatio will be 25. When the download is complete this
+ * method will send a notification to the ProgressUpdateListeners with a ratio
+ * of 25 %.
+ *
+ */
+ private void waitForLoader(Integer maxRatio) throws InstallException
+ {
+ int lastPercentage = -1;
+ while (!loader.isFinished() && (loader.getException() == null))
+ {
+ // Pool until is over
+ int perc = loader.getDownloadPercentage();
+ if (perc != lastPercentage)
+ {
+ lastPercentage = perc;
+ int ratio = (perc * maxRatio) / 100;
+ String[] arg =
+ { String.valueOf(perc) };
+ String summary = getMsg("downloading-ratio", arg);
+ hmSummary.put(InstallProgressStep.DOWNLOADING, summary);
+ notifyListeners(ratio, summary, null);
+
+ try
+ {
+ Thread.sleep(300);
+ } catch (Exception ex)
+ {
+ }
+ }
+ }
+
+ if (loader.getException() != null)
+ {
+ throw loader.getException();
+ }
+ }
+
+ /**
+ * This method extracts the zip file.
+ * @param is the inputstream with the contents of the zip file.
+ * @param minRatio the value of the ratio in the install that corresponds to
+ * the moment where we start extracting the zip files. Used to update
+ * properly the install progress ratio.
+ * @param maxRatio the value of the ratio in the installation that corresponds
+ * to the moment where we finished extracting the last zip file. Used to
+ * update properly the install progress ratio.
+ * @throws InstallException if an error occurs.
+ */
+ private void extractZipFiles(InputStream is, int minRatio, int maxRatio)
+ throws InstallException
+ {
+ ZipInputStream zipIn = new ZipInputStream(is);
+ String basePath = getUserData().getServerLocation();
+
+ int nEntries = 1;
+
+ /* This map is updated in the copyZipEntry method with the permissions
+ * of the files that have been copied. Once all the files have
+ * been copied to the file system we will update the file permissions of
+ * these files. This is done this way to group the number of calls to
+ * Runtime.exec (which is required to update the file system permissions).
+ */
+ Map<String, ArrayList<String>> permissions =
+ new HashMap<String, ArrayList<String>>();
+
+ String zipFirstPath = null;
+ try
+ {
+ ZipEntry entry = zipIn.getNextEntry();
+ while (entry != null)
+ {
+ int ratioBeforeCompleted = minRatio
+ + ((nEntries - 1) * (maxRatio - minRatio) / getNumberZipEntries());
+ int ratioWhenCompleted =
+ minRatio + (nEntries * (maxRatio - minRatio) / getNumberZipEntries());
+
+ if (nEntries == 1)
+ {
+ zipFirstPath = entry.getName();
+ } else
+ {
+ try
+ {
+ copyZipEntry(entry, basePath, zipFirstPath, zipIn,
+ ratioBeforeCompleted, ratioWhenCompleted, permissions);
+
+ } catch (IOException ioe)
+ {
+ String[] arg =
+ { entry.getName() };
+ String errorMsg = getExceptionMsg("error-copying", arg, ioe);
+
+ throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+ errorMsg, ioe);
+ }
+ }
+
+ zipIn.closeEntry();
+ entry = zipIn.getNextEntry();
+ nEntries++;
+ }
+
+ if (Utils.isUnix())
+ {
+ // Change the permissions for UNIX systems
+ for (String perm : permissions.keySet())
+ {
+ ArrayList<String> paths = permissions.get(perm);
+ try
+ {
+ int result = Utils.setPermissionsUnix(paths, perm);
+ if (result != 0)
+ {
+ throw new IOException("Could not set permissions on files "
+ + paths + ". The chmod error code was: " + result);
+ }
+ } catch (InterruptedException ie)
+ {
+ IOException ioe =
+ new IOException("Could not set permissions on files " + paths
+ + ". The chmod call returned an InterruptedException.");
+ ioe.initCause(ie);
+ throw ioe;
+ }
+ }
+ }
+
+ } catch (IOException ioe)
+ {
+ String[] arg =
+ { getZipFileName() };
+ String errorMsg = getExceptionMsg("error-zip-stream", arg, ioe);
+ throw new InstallException(InstallException.Type.FILE_SYSTEM_ERROR,
+ errorMsg, ioe);
+ }
+ }
+
+ /**
+ * Copies a zip entry in the file system.
+ * @param entry the ZipEntry object.
+ * @param basePath the basePath (the installation path)
+ * @param zipFirstPath the first zip file path. This is required because the
+ * zip file contain a directory of type
+ * 'OpenDS-(major version).(minor version)' that we want to get rid of. The
+ * first zip file path corresponds to this path.
+ * @param is the ZipInputStream that contains the contents to be copied.
+ * @param ratioBeforeCompleted the progress ratio before the zip file is
+ * copied.
+ * @param ratioWhenCompleted the progress ratio after the zip file is
+ * copied.
+ * @param permissions an ArrayList with permissions whose contents will be
+ * updated.
+ * @throws IOException if an error occurs.
+ */
+ private void copyZipEntry(ZipEntry entry, String basePath,
+ String zipFirstPath, ZipInputStream is, int ratioBeforeCompleted,
+ int ratioWhenCompleted, Map<String, ArrayList<String>> permissions)
+ throws IOException
+ {
+ String entryName = entry.getName();
+ // Get rid of the zipFirstPath
+ if (entryName.startsWith(zipFirstPath))
+ {
+ entryName = entryName.substring(zipFirstPath.length());
+ }
+ String path = Utils.getPath(basePath, entryName);
+
+ notifyListeners(ratioBeforeCompleted, getSummary(getStatus()),
+ getHtmlWithPoints(getMsg("progress-extracting", new String[]
+ { path })));
+ if (Utils.createParentPath(path))
+ {
+ if (entry.isDirectory())
+ {
+ String perm = getDirectoryFileSystemPermissions(path);
+ ArrayList<String> list = permissions.get(perm);
+ if (list == null)
+ {
+ list = new ArrayList<String>();
+ }
+ list.add(path);
+ permissions.put(perm, list);
+
+ if (!Utils.createDirectory(path))
+ {
+ throw new IOException("Could not create path: " + path);
+ }
+ } else
+ {
+ String perm = getFileSystemPermissions(path);
+ ArrayList<String> list = permissions.get(perm);
+ if (list == null)
+ {
+ list = new ArrayList<String>();
+ }
+ list.add(path);
+ Utils.createFile(path, is);
+ }
+ } else
+ {
+ throw new IOException("Could not create parent path: " + path);
+ }
+ notifyListeners(ratioWhenCompleted, getSummary(getStatus()),
+ getHtmlDone() + LINE_BREAK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getOpenDSClassPath()
+ {
+ StringBuffer buf = new StringBuffer();
+ String[] jars = getOpenDSJarPaths();
+ for (int i = 0; i < jars.length; i++)
+ {
+ if (i != 0)
+ {
+ buf.append(System.getProperty("path.separator"));
+ }
+ buf.append(jars[i]);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Returns the jar file paths in the installation. This is used to launch
+ * command lines that require a classpath.
+ * @return the jar file paths in the installation.
+ */
+ private String[] getOpenDSJarPaths()
+ {
+ String[] jarPaths = new String[OPEN_DS_JAR_RELATIVE_PATHS.length];
+ File parentDir = new File(getUserData().getServerLocation());
+ for (int i = 0; i < jarPaths.length; i++)
+ {
+ File f = new File(parentDir, OPEN_DS_JAR_RELATIVE_PATHS[i]);
+ jarPaths[i] = f.getAbsolutePath();
+ }
+ return jarPaths;
+ }
+
+ /**
+ * Returns the name of the zip file name that contains all the installation.
+ * @return the name of the zip file name that contains all the installation.
+ */
+ private String getZipFileName()
+ {
+ // Passed as a java option in the JNLP file
+ return System.getProperty(ZIP_FILE_NAME);
+ }
+
+ /**
+ * Returns the file system permissions for a directory.
+ * @param path the directory for which we want the file permissions.
+ * @return the file system permissions for the directory.
+ */
+ private String getDirectoryFileSystemPermissions(String path)
+ {
+ // TODO We should get this dynamically during build?
+ return "755";
+ }
+
+ /**
+ * Returns the file system permissions for a file.
+ * @param path the file for which we want the file permissions.
+ * @return the file system permissions for the file.
+ */
+ private String getFileSystemPermissions(String path)
+ {
+ // TODO We should get this dynamically during build?
+ String perm;
+
+ File file = new File(path);
+ if (file.getParent().endsWith(File.separator + "bin"))
+ {
+ if (path.endsWith(".bat"))
+ {
+ perm = "644";
+ } else
+ {
+ perm = "755";
+ }
+ } else if (path.endsWith(".sh"))
+ {
+ perm = "755";
+ } else
+ {
+ perm = "644";
+ }
+ return perm;
+ }
+
+ /**
+ * Returns the number of entries contained in the zip file. This is used to
+ * update properly the progress bar ratio.
+ * @return the number of entries contained in the zip file.
+ */
+ private int getNumberZipEntries()
+ {
+ // TODO we should get this dynamically during build
+ return 83;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getConfigFilePath()
+ {
+ String fullInstallPath = getUserData().getServerLocation();
+
+ return Utils.getPath(fullInstallPath, CONFIG_PATH_RELATIVE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getBinariesPath()
+ {
+ String fullInstallPath = getUserData().getServerLocation();
+
+ return Utils.getPath(fullInstallPath, BINARIES_PATH_RELATIVE);
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
new file mode 100644
index 0000000..ab7d1b9
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -0,0 +1,365 @@
+#
+# Setup command line messages
+#
+setup-launcher-usage=This utility may be used to setup the Directory Server.\n\
+Usage: {0} {options}\n where {options} include:\n\
+--cli\n\ Specifies to use the command line setup. If not specified the \
+graphical\n\ interface will be launched.\n\
+-H or --help\n Displays usage information for this program.\n\n\
+The following options will only be taken into account if the option --cli \n\
+(command line) is specified\n\
+-s or --silentInstall\n Perform a silent installation.\n\
+-b {baseDN} or --baseDN {baseDN}\n\ Specifies the base DN for user \
+information in the Directory Server.\n Multiple base DNs may be provided by \
+using this option multiple times.\n\
+-a or --addBaseEntry\n Indicates whether to create the base entry in the \
+Directory Server\n database.\n\
+-i {ldifFile} or --importLDIF {ldifFile}\n Specifies the path to an LDIF \
+file containing data that should be added to\n the Directory Server \
+database. Multiple LDIF files may be provided by\n using this option \
+multiple times.\n\
+-p {port} or --ldapPort {port}\n Specifies the port on which the \
+Directory Server should listen for LDAP\n communication.\n\
+-S or --skipPortCheck\n Skip the check to determine whether the \
+specified LDAP port is usable.\n\
+-D {rootDN} or --rootUserDN {rootDN}\n Specifies the DN for the initial \
+root user for the Directory Server.\n\
+-w {password} or --rootUserPassword {password}\n Specifies the password \
+for the initial root user for the Directory Server.\n\
+-W {filename} or --rootUserPasswordFile {filename}\n Specifies the path \
+to a file containing the password for the initial root\n\ user for the \
+Directory Server.
+setup-launcher-launching-gui=Launching graphical setup...
+setup-launcher-gui-launched-failed=\n\nThe graphical Setup launch failed.\n\n\
+Launching command line Setup...
+
+#
+# Dialog titles
+#
+frame-quicksetup-title=OpenDS QuickSetup
+frame-uninstall-title=OpenDS Uninstall
+
+#
+# Wizard buttons (labels and tooltips)
+#
+next-button-label=Next >
+next-button-tooltip=Go to Next Step
+previous-button-label=< Previous
+previous-button-tooltip=Go to Previous Step
+finish-button-label=Finish
+finish-button-tooltip=Finish Installation and Setup
+close-button-label=Close
+close-button-tooltip=Close QuickSetup Window
+quit-button-label=Quit
+quit-button-tooltip=Quit QuickSetup Tool
+
+
+#
+# Confirmation dialogs
+#
+confirm-close-quicksetup-title=Confirmation Required
+confirm-close-quicksetup-msg=OpenDS QuickSetup has not yet completed.\nAre you \
+sure you want to close the QuickSetup Window?
+confirm-quit-quicksetup-title=Confirmation Required
+confirm-quit-quicksetup-msg=Are you sure you want to quit OpenDS \
+QuickSetup?\nIf you click 'Yes' nothing will be installed on your system.
+confirm-close-uninstall-title=Confirmation Required
+confirm-close-uninstall-msg=OpenDS Uninstall has not yet completed.\nAre you \
+sure you want to close the Uninstall Window?
+#
+# Error dialog title
+#
+error-title=Error
+
+#
+# Browser launching error dialog
+#
+error-browser-display-msg=Could not launch the web browser.<br>You can copy \
+and paste the following URL manually into your web browser:<br>\
+<span style="font-style:italic">{0}</span>
+error-browser-display-title=Error
+error-browser-copy-button-label=Copy URL
+error-browser-copy-button-tooltip=Copies the URL to the system clipboard
+error-browser-close-button-tooltip=Close this window
+
+#
+# Data validation errors
+#
+# Server Settings
+empty-server-location=You must provide the installation path.
+parent-directory-does-not-exist=The parent directory of {0} does not exist.
+file-exists=The file {0} already exists.
+directory-exists-not-empty=The directory {0} is not empty.
+directory-not-writable=You do not have write access on the directory {0}. \
+You must have file right access on the Installation directory.
+not-enough-disk-space=There is not enough free disk space under {0}.\nAt \
+least {1} megabytes of free disk space are required to install OpenDS.
+invalid-port-value-range=The LDAP Listener Port must be an integer between \
+{0} and {1}.
+cannot-bind-priviledged-port=Cannot bind to privileged port {0}.
+cannot-bind-port=Cannot bind to port {0}.
+empty-directory-manager-dn=You must provide an Administrative User DN.
+not-a-directory-manager-dn=The provided Administrative User DN is not a valid \
+DN.
+directory-manager-dn-is-config-dn=The provided Administrative User DN is \
+used for the configuration of the Directory Server.
+not-equal-pwd=The passwords you have provided do not match.
+pwd-too-short=The minimum length required for the Administrative User \
+password is {0} characters.
+# Data Options Panel
+empty-base-dn=You must provide a Directory Base DN.
+not-a-base-dn=The provided Directory Base DN is not a valid DN.
+base-dn-is-configuration-dn=The provided Directory Base DN is used for \
+storing the server configuration data. You must specify a different DN.
+no-ldif-path=You must provide the path of the LDIF file to import.
+ldif-file-does-not-exist=The provided LDIF file does not exist.
+no-number-entries=You must provide the number of user entries to generate \
+automatically.
+invalid-number-entries-range=The number of user entries to generate \
+automatically must be an integer between {0} and {1}.
+
+
+#
+# Steps labels (on the left side of the wizard)
+#
+welcome-step=Welcome
+server-settings-step=Server Settings
+data-options-step=Data Options
+review-step=Review
+progress-step=Progress
+confirm-uninstall-step=Confirm Uninstallation
+
+#
+# Icon descriptions. Used for accessibility.
+#
+current-step-icon-description=Current Step Indicator.
+splash-icon-description=OpenDS QuickSetup Launching.
+minimized-icon-description=OpenDS QuickSetup minimized.
+background-icon-description=OpenDS QuickSetup.
+warning-icon-description=Warning.
+error-icon-description=Error.
+information-icon-description=Information.
+
+#
+# Icon tooltips.
+#
+current-step-icon-tooltip=Current Step Indicator.
+splash-icon-tooltip=Open DS QuickSetup Launching.
+minimized-icon-tooltip=OpenDS QuickSetup.
+background-icon-tooltip=OpenDS QuickSetup.
+warning-icon-tooltip=Warning.
+error-icon-tooltip=Error.
+information-icon-tooltip=Information.
+
+#
+# Icon paths. This is done to be able to provide localizable icons (for
+# instance for those icons containing a text). If there is not a localized
+# version of the icon it should be left as it is.
+# The path specified here are the relative resource name to the images.
+#
+current-step-icon=images/currentstep.png
+minimized-icon=images/opendsminimized.gif
+minimized-mac-icon=images/opendsminimizedmac.png
+splash-icon=images/opendssplash.png
+background-icon=images/opendsbackground.png
+error-icon=images/error.gif
+warning-icon=images/warning.gif
+warning-large-icon=images/warning_large.gif
+information-icon=images/information.gif
+
+#
+# Welcome Panel specific labels
+#
+welcome-panel-title=Welcome
+# The following line contains some HTML tags. translators should respect them.
+# Concerning the URL, depending on how works the product page translators
+# have to modify it or not: if the server uses the locale of the browser to display
+# a language there is no translation to be done but if we have specific URL for
+# each language the URL must be localized.
+welcome-panel-instructions=The OpenDS QuickSetup tool will ask you for some \
+basic server and data configuration settings and will get your server up \
+and running quickly.<br><br>If you are running this tool via Java Web Start, \
+QuickSetup will install and configure the latest weekly build. You can also \
+use QuickSetup to set up a weekly build you have downloaded manually. To run \
+QuickSetup in this case, use the quicksetup command at the top level of the \
+OpenDS directory. This instance of QuickSetup will use the following OpenDS \
+build: {0} (Build ID: {1}) <br><br> \
+OpenDS requires a Java SE 5.0 or higher runtime.<br><br> \
+Additional information on QuickSetup is available in the <a href="https://opends.dev.java.net/public/docs/index.html"> \
+Documentation Depot</a> section of OpenDS project web site.<br><br>
+
+#
+# Server Settings Panel specific labels
+#
+server-settings-panel-title=Server Settings
+server-settings-panel-instructions=Choose a location for the server files and \
+enter a password for the OpenDS administrative user.
+server-location-label=Installation Path:
+server-location-parent-tooltip=Enter the full path to the parent location \
+where the server files will be stored
+server-location-relative-tooltip=Enter the relative path to the location \
+where the server files will be stored
+server-port-label=LDAP Listener Port:
+server-port-tooltip=Enter the port number that the server will use to listen \
+for LDAP requests
+server-directory-manager-dn-label=Administrative User DN:
+server-directory-manager-dn-tooltip=Enter the distinguished name (DN) of the \
+Administrative User account that will used for managing OpenDS
+server-directory-manager-pwd-label=Password:
+server-directory-manager-pwd-tooltip=Enter a password for the OpenDS \
+Administrative User account
+server-directory-manager-pwd-confirm-label=Password (confirm):
+server-directory-manager-pwd-confirm-tooltip=Re-enter the password for the \
+OpenDS Administrative User account
+cannot-find-default-port-unix=Note: Cannot use port 389.
+cannot-find-default-port-windows=Note: Port 389 is already in use.
+
+
+#
+# Data Options Panel specific labels
+#
+data-options-panel-title=Data Options
+data-options-panel-instructions=Choose options for the LDAP data to be hosted \
+by OpenDS.
+base-dn-label=Directory Base DN:
+base-dn-tooltip=Enter the DN of the top entry where your data will be stored
+directory-data-label=Directory Data:
+create-base-entry-label=Only Create Base Entry ({0})
+create-base-entry-tooltip=Only create the top entry for the Directory Base DN
+leave-database-empty-label=Leave Database Empty
+leave-database-empty-tooltip=Do not create any entry for the Directory Base DN
+import-data-from-ldif-label=Import Data from LDIF File
+import-data-from-ldif-tooltip=Use the contents of an LDIF file to populate the \
+suffix with data
+import-path-label=Path:
+import-path-tooltip=Enter the full path of the LDIF file containing the \
+data to be imported
+import-automatically-generated-label=Import Automatically-Generated Example \
+Data
+import-automatically-generated-tooltip=Populate the suffix with \
+automatically-generated LDAP data
+number-entries-label=Number of User Entries:
+number-entries-tooltip=Enter the number of user entries to be generated
+
+#
+# Review Panel specific labels
+#
+review-panel-title=Review
+review-panel-instructions=Review your settings and click Finish if they are \
+correct.
+review-create-base-entry-label=Only Create Base Entry ({0})
+review-leave-database-empty-label=Leave Database Empty
+review-import-ldif=Import Data from LDIF File ({0})
+review-import-automatically-generated=Import Automatically-Generated Data ({0} \
+Entries)
+start-server-label=Start Server when Configuration has Completed
+start-server-tooltip=Check this check box if you want to start the server once \
+the installation and configuration has completed
+
+#
+# Progress Panel specific labels
+#
+progress-panel-title=Progress
+progress-details-label=Details:
+progressbar-initial-label=Starting Setup...
+progressbar-tooltip=Progress Bar
+
+#
+# Confirm Uninstall Panel specific labels
+#
+confirm-uninstall-panel-title=Confirm uninstall
+# The following line contains some HTML tags. translators should respect them.
+# Concerning the URL, depending on how works the product page translators
+# have to modify it or not: if the server uses the locale of the browser to display
+# a language there is no translation to be done but if we have specific URL for
+# each language the URL must be localized.
+confirm-uninstall-panel-instructions=The OpenDS Uninstall tool will \
+stop the OpenDS server if it is running and will delete all the user data \
+from it. All the binary files will also be deleted.<br><br> \
+Click on 'Finish' to start the uninstallation of OpenDS.<br><br> \
+Additional information on QuickSetup is available in the <a href="https://opends.dev.java.net/public/docs/index.html"> \
+Documentation Depot</a> section of OpenDS project web site.<br><br>
+
+
+#
+# Miscellaneous labels
+#
+browse-button-label=Browse...
+browse-button-tooltip=Click to display a file system browser
+ldif-files-description=Lightweight Directory Interchange Format (*.ldif)
+open-server-location-dialog-title=Choose Installation Path
+open-ldif-file-dialog-title=Choose an LDIF File
+
+#
+# Progress Summary Labels
+#
+summary-not-started=Starting QuickSetup...
+summary-not-started=Launching Installation...
+summary-downloading=Downloading Binary Files...
+summary-extracting=Extracting Binary Files...
+summary-configuring=Configuring Directory Server...
+summary-creating-base-entry=Creating Base Entry...
+summary-importing-ldif=Importing LDIF File...
+summary-importing-automatically-generated=Importing Automatically-Generated \
+Data...
+summary-starting=Starting Directory Server...
+summary-finished-successfully=<b>OpenDS QuickSetup completed successfully.</b>\
+<br> Visit the <a href="https://opends.dev.java.net/public/docs/index.html"> \
+documentation depot</a> page for guidance on server management and \
+configuration.
+summary-finished-with-error=An error occurred. Check 'Details' text area for \
+more information.
+
+#
+# Progress messages
+#
+progress-downloading=Downloading
+progress-done=Done.
+progress-points=.....
+progress-extracting=Extracting {0}
+progress-configuring=Configuring Directory Server
+downloading-ratio=Downloading: {0}% Completed.
+progress-creating-base-entry=Creating Base Entry {0}
+progress-importing-ldif=Importing LDIF file {0}:
+progress-import-automatically-generated=Importing Automatically-Generated Data \
+({0} Entries):
+progress-starting=Starting Directory Server:
+
+#
+# Progress errors
+#
+error-copying=An unexpected error occurred extracting file {0}.
+error-zip-stream=An unexpected error occurred reading the zip file {0}.
+exception-details=Details: {0}.
+downloading-error=An error occurred downloading remote file(s) {0}.
+error-zipinputstreamnull=Could not retrieve zip file. The input stream \
+is null.
+bug-msg=An unexpected error occurred.
+error-configuring=An error occurred configuring the server.
+error-reflection=An unexpected error occurred while loading classes.
+error-creating-temp-file=An error occurred creating the temporary file.
+error-writing-to-temp-file=An error occurred writing to temporary file {0}.
+error-configuring=Error Configuring Directory Server.
+error-creating-base-entry=Error Creating Base Entry.
+error-importing-ldif=Error Importing LDIF File.
+error-import-automatically-generated=Error Importing Automatically- Generated \
+Data.
+error-starting-server=Error Starting Directory Server.
+error-starting-server-code=Error Starting Directory Server. Error code: {0}.
+error-reading-erroroutput=Error Reading error output.
+error-reading-output=Error Reading output.
+hide-exception-details=Hide Details
+show-exception-details=Show Details
+exception-root-cause=Root Cause:
+
+#
+# Install Status: messages displayed in the offline quick setup
+# if server is already installed.
+#
+installstatus-serverrunning=Is currently running on port {0}
+installstatus-dbfileexist=Contains data
+installstatus-configfilemodified=Has already been configured
+installstatus-installed=OpenDS Server Already Configured<br> \
+QuickSetup can only be used with OpenDS Servers that have not yet been \
+configured. The current server:{0}
+installstatus-not-installed=The Directory Server is not installed.
\ No newline at end of file
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java
new file mode 100644
index 0000000..d8ae55f
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ButtonsPanel.java
@@ -0,0 +1,317 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import java.util.HashSet;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+
+import org.opends.quicksetup.ButtonName;
+import org.opends.quicksetup.Step;
+import org.opends.quicksetup.event.ButtonActionListener;
+import org.opends.quicksetup.event.ButtonEvent;
+
+/**
+ * This class contains the buttons in the bottom of the Install/Uninstall
+ * dialog. There is only one of this instances for the QuickSetupDialog.
+ * The layout is updated calling setCurrentStep method.
+ *
+ */
+class ButtonsPanel extends QuickSetupPanel
+{
+ private static final long serialVersionUID = -8460400337486357976L;
+
+ private HashSet<ButtonActionListener> buttonListeners =
+ new HashSet<ButtonActionListener>();
+
+ private JButton nextButton;
+
+ private JButton previousButton;
+
+ private JButton quitButton;
+
+ private JButton closeButton;
+
+ private JButton finishButton;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public ButtonsPanel()
+ {
+ createButtons();
+ layoutButtons();
+ }
+
+ /**
+ * Adds a button listener. All the button listeners will be notified when
+ * the buttons are clicked (by the user or programatically).
+ * @param l the ButtonActionListener to be added.
+ */
+ public void addButtonActionListener(ButtonActionListener l)
+ {
+ buttonListeners.add(l);
+ }
+
+ /**
+ * Removes a button listener.
+ * @param l the ButtonActionListener to be removed.
+ */
+ public void removeButtonActionListener(ButtonActionListener l)
+ {
+ buttonListeners.remove(l);
+ }
+
+ /**
+ * Updates the layout of the panel so that it corresponds to the Step passed
+ * as parameter.
+ *
+ * @param step the step in the wizard.
+ */
+ public void setDisplayedStep(Step step)
+ {
+ switch (step)
+ {
+ case WELCOME:
+
+ previousButton.setVisible(false);
+ nextButton.setVisible(true);
+ finishButton.setVisible(false);
+ quitButton.setVisible(true);
+ closeButton.setVisible(false);
+
+ break;
+
+ case REVIEW:
+
+ previousButton.setVisible(true);
+ nextButton.setVisible(false);
+ finishButton.setVisible(true);
+ quitButton.setVisible(true);
+ closeButton.setVisible(false);
+
+ break;
+
+ case PROGRESS:
+
+ // TO COMPLETE: if there is an error we might want to change
+ // this
+ // like for instance coming back
+ previousButton.setVisible(false);
+ nextButton.setVisible(false);
+ finishButton.setVisible(false);
+ quitButton.setVisible(false);
+ closeButton.setVisible(true);
+
+ break;
+
+ case CONFIRM_UNINSTALL:
+
+ previousButton.setVisible(false);
+ nextButton.setVisible(false);
+ finishButton.setVisible(true);
+ quitButton.setVisible(true);
+ closeButton.setVisible(false);
+
+ break;
+
+ default:
+
+ previousButton.setVisible(true);
+ nextButton.setVisible(true);
+ finishButton.setVisible(false);
+ quitButton.setVisible(true);
+ closeButton.setVisible(false);
+ }
+ }
+
+ /**
+ * Returns the button corresponding to the buttonName.
+ * @param buttonName the ButtonName for which we want to get the button.
+ * @return the button corresponding to the buttonName.
+ */
+ public JButton getButton(ButtonName buttonName)
+ {
+ JButton b = null;
+ switch (buttonName)
+ {
+ case NEXT:
+ b = nextButton;
+ break;
+
+ case PREVIOUS:
+ b = previousButton;
+ break;
+
+ case QUIT:
+ b = quitButton;
+ break;
+
+ case CLOSE:
+ b = closeButton;
+ break;
+
+ case FINISH:
+ b = finishButton;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown button name: " +
+ buttonName);
+ }
+
+ return b;
+ }
+
+ /*
+ * Create the buttons.
+ */
+ private void createButtons()
+ {
+ nextButton =
+ createButton("next-button-label", "next-button-tooltip",
+ ButtonName.NEXT);
+
+ previousButton =
+ createButton("previous-button-label", "previous-button-tooltip",
+ ButtonName.PREVIOUS);
+
+ quitButton =
+ createButton("quit-button-label", "quit-button-tooltip",
+ ButtonName.QUIT);
+
+ closeButton =
+ createButton("close-button-label", "close-button-tooltip",
+ ButtonName.CLOSE);
+
+ finishButton =
+ createButton("finish-button-label", "finish-button-tooltip",
+ ButtonName.FINISH);
+ }
+
+ /**
+ * Do the layout of the panel.
+ *
+ */
+ private void layoutButtons()
+ {
+ setLayout(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ GridBagConstraints gbcAux = new GridBagConstraints();
+ gbcAux.gridwidth = GridBagConstraints.REMAINDER;
+ gbcAux.fill = GridBagConstraints.HORIZONTAL;
+ JPanel previousPanel = new JPanel(new GridBagLayout());
+ // Set as opaque to inherit the background color of ButtonsPanel
+ previousPanel.setOpaque(false);
+ previousPanel.add(previousButton, gbcAux);
+ int width = (int) previousButton.getPreferredSize().getWidth();
+ previousPanel.add(Box.createHorizontalStrut(width), gbcAux);
+
+ gbc.gridwidth = 4;
+ gbc.weightx = 0.0;
+ gbc.weighty = 0.0;
+ gbc.insets.bottom = 0;
+ gbc.insets.right = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
+ gbc.anchor = GridBagConstraints.WEST;
+ gbc.fill = GridBagConstraints.NONE;
+ add(previousPanel, gbc);
+ gbc.gridwidth--;
+
+ JPanel nextFinishPanel = new JPanel(new GridBagLayout());
+ // Set as opaque to inherit the background color of ButtonsPanel
+ nextFinishPanel.setOpaque(false);
+ nextFinishPanel.add(nextButton, gbcAux);
+ nextFinishPanel.add(finishButton, gbcAux);
+ width =
+ (int) Math.max(nextButton.getPreferredSize().getWidth(), finishButton
+ .getPreferredSize().getWidth());
+ nextFinishPanel.add(Box.createHorizontalStrut(width), gbcAux);
+ add(nextFinishPanel, gbc);
+
+ gbc.gridwidth--;
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets.right = 0;
+ add(Box.createHorizontalGlue(), gbc);
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 0.0;
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
+ JPanel quitClosePanel = new JPanel(new GridBagLayout());
+ // Set as opaque to inherit the background color of ButtonsPanel
+ quitClosePanel.setOpaque(false);
+ quitClosePanel.add(quitButton, gbcAux);
+ quitClosePanel.add(closeButton, gbcAux);
+ width =
+ (int) Math.max(quitButton.getPreferredSize().getWidth(), closeButton
+ .getPreferredSize().getWidth());
+ quitClosePanel.add(Box.createHorizontalStrut(width), gbcAux);
+ add(quitClosePanel, gbc);
+ }
+
+ /**
+ * Create a button.
+ * @param labelKey the key in the properties file for the label.
+ * @param tooltipKey the key in the properties file for the tooltip.
+ * @param buttonName the ButtonName.
+ * @return a new button with the specified parameters.
+ */
+ private JButton createButton(String labelKey, String tooltipKey,
+ ButtonName buttonName)
+ {
+ JButton b = UIFactory.makeJButton(getMsg(labelKey), getMsg(tooltipKey));
+
+ final ButtonName fButtonName = buttonName;
+
+ ActionListener actionListener = new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ev)
+ {
+ ButtonEvent be = new ButtonEvent(ev.getSource(), fButtonName);
+ for (ButtonActionListener li : buttonListeners)
+ {
+ li.buttonActionPerformed(be);
+ }
+ }
+ };
+
+ b.addActionListener(actionListener);
+
+ return b;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java
new file mode 100644
index 0000000..1085350
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ConfirmUninstallPanel.java
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Component;
+
+/**
+ * This is the panel displayed when the user is uninstalling Open DS. It is
+ * basically a panel with the text informing of the consequences of uninstalling
+ * the server and asking for confirmation.
+ *
+ */
+public class ConfirmUninstallPanel extends QuickSetupStepPanel
+{
+ private static final long serialVersionUID = 81730510134697056L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public ConfirmUninstallPanel()
+ {
+ createLayout();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getTitle()
+ {
+ return getMsg("confirm-uninstall-panel-title");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Component createInputPanel()
+ {
+ // No input in this panel
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getInstructions()
+ {
+ return getMsg("confirm-uninstall-panel-instructions");
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
new file mode 100644
index 0000000..97f6e26
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/CurrentStepPanel.java
@@ -0,0 +1,185 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.CardLayout;
+import java.awt.Dimension;
+
+import java.util.HashMap;
+
+import org.opends.quicksetup.Step;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+
+/**
+ * This is the class that contains the panel on the right-top part of the
+ * QuickSetupDialog). It uses a CardLayout that contains all
+ * the panels that are specific to each step (WelcomePanel, ReviewPanel, etc.).
+ *
+ * To specify which is the panel to be displayed the method setCurrentStep
+ * method is called.
+ *
+ * There is only one instance of this class for a given QuickSetupDialog (and
+ * there are only 1 instance of each of the panels that are contained in its
+ * CardLayout).
+ *
+ */
+class CurrentStepPanel extends QuickSetupPanel
+{
+ private UserInstallData defaultUserData;
+
+ private static final long serialVersionUID = 5474803491510999334L;
+
+ private HashMap<Step, QuickSetupStepPanel> hmPanels =
+ new HashMap<Step, QuickSetupStepPanel>();
+
+ /**
+ * The constructor of this class.
+ * @param defaultUserData the default data that is used to initialize the
+ * contents of the panels (the proposed values).
+ * @param isUninstall boolean telling whether we are uninstalling or not.
+ */
+ public CurrentStepPanel(UserInstallData defaultUserData,
+ boolean isUninstall)
+ {
+ this.defaultUserData = defaultUserData;
+ createLayout(isUninstall);
+ }
+
+ /**
+ * Returns the value corresponding to the provided FieldName.
+ * @param fieldName the FieldName for which we want to obtain the value.
+ * @return the value corresponding to the provided FieldName.
+ */
+ public Object getFieldValue(FieldName fieldName)
+ {
+ Object value = null;
+ for (Step s : hmPanels.keySet())
+ {
+ value = getPanel(s).getFieldValue(fieldName);
+ if (value != null)
+ {
+ break;
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Marks as invalid (or valid depending on the value of the invalid parameter)
+ * a field corresponding to FieldName. This basically implies udpating the
+ * style of the JLabel associated with fieldName (the association is done
+ * using the LabelFieldDescriptor class).
+ * @param fieldName the FieldName to be marked as valid or invalid.
+ * @param invalid whether to mark the field as valid or invalid.
+ */
+ public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+ {
+ for (Step s : hmPanels.keySet())
+ {
+ getPanel(s).displayFieldInvalid(fieldName, invalid);
+ }
+ }
+
+ /**
+ * Create the layout of the panel.
+ * @param isUninstall whether this is an install or uninstall panel.
+ */
+ private void createLayout(boolean isUninstall)
+ {
+ if (isUninstall)
+ {
+ hmPanels.put(Step.CONFIRM_UNINSTALL, new ConfirmUninstallPanel());
+ hmPanels.put(Step.PROGRESS, new ProgressPanel());
+ } else
+ {
+ hmPanels.put(Step.WELCOME, new WelcomePanel());
+ hmPanels.put(Step.SERVER_SETTINGS, new ServerSettingsPanel(
+ defaultUserData));
+ hmPanels.put(Step.DATA_OPTIONS,
+ new DataOptionsPanel(defaultUserData));
+ hmPanels.put(Step.REVIEW, new ReviewPanel(defaultUserData));
+ hmPanels.put(Step.PROGRESS, new ProgressPanel());
+ }
+
+ int minWidth = 0;
+ int minHeight = 0;
+ setLayout(new CardLayout());
+ for (Step s : hmPanels.keySet())
+ {
+ minWidth = Math.max(minWidth, getPanel(s).getMinimumWidth());
+ minHeight = Math.max(minHeight, getPanel(s).getMinimumHeight());
+ add(getPanel(s), s.toString());
+ }
+
+ // For aesthetical reasons we add a little bit of height
+ minHeight += UIFactory.EXTRA_DIALOG_HEIGHT;
+
+ setPreferredSize(new Dimension(minWidth, minHeight));
+ setMinimumSize(new Dimension(minWidth, minHeight));
+ }
+
+ /**
+ * Displays the panel corresponding to the provided step. The panel contents
+ * are updated with the contents of the UserInstallData object.
+ * @param step the step that we want to display.
+ * @param userData the UserInstallData object that must be used to populate
+ * the panels.
+ */
+ public void setDisplayedStep(Step step, UserInstallData userData)
+ {
+ CardLayout cl = (CardLayout) (getLayout());
+ getPanel(step).beginDisplay(userData);
+ cl.show(this, step.toString());
+ getPanel(step).endDisplay();
+ }
+
+ /**
+ * Forwards the different panels the InstallProgressDescriptor so that they
+ * can update their contents accordingly.
+ * @param descriptor the descriptor of the Installation progress.
+ */
+ public void displayProgress(InstallProgressDescriptor descriptor)
+ {
+ for (Step s : hmPanels.keySet())
+ {
+ getPanel(s).displayProgress(descriptor);
+ }
+ }
+
+ /**
+ * Retrieves the panel for the provided step.
+ * @param step the step for which we want to get the panel.
+ * @return the panel for the provided step.
+ */
+ private QuickSetupStepPanel getPanel(Step step)
+ {
+ return hmPanels.get(step);
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/DataOptionsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/DataOptionsPanel.java
new file mode 100644
index 0000000..5c6dce7
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/DataOptionsPanel.java
@@ -0,0 +1,619 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.event.BrowseActionListener;
+import org.opends.quicksetup.installer.DataOptions;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.LabelFieldDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+
+/**
+ * This is the panel that contains the Data Options: the suffix dn, whether
+ * to import data to the suffix or not, etc.
+ *
+ */
+class DataOptionsPanel extends QuickSetupStepPanel
+{
+ private Component lastFocusComponent;
+
+ private static final long serialVersionUID = 1815782841921928118L;
+
+ private UserInstallData defaultUserData;
+
+ private HashMap<FieldName, JLabel> hmLabels =
+ new HashMap<FieldName, JLabel>();
+
+ private HashMap<FieldName, JTextComponent> hmFields =
+ new HashMap<FieldName, JTextComponent>();
+
+ private HashMap<DataOptions.Type, JRadioButton> hmRadioButtons =
+ new HashMap<DataOptions.Type, JRadioButton>();
+
+ private JButton ldifBrowseButton;
+
+ /**
+ * Constructor of the panel.
+ * @param defaultUserData the default values that must be used to initialize
+ * the fields of the panel.
+ */
+ public DataOptionsPanel(UserInstallData defaultUserData)
+ {
+ this.defaultUserData = defaultUserData;
+ populateComponentMaps();
+ addDocumentListeners();
+ addFocusListeners();
+ createLayout();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getFieldValue(FieldName fieldName)
+ {
+ Object value = null;
+
+ if (fieldName == FieldName.DATA_OPTIONS)
+ {
+ for (DataOptions.Type type : hmRadioButtons.keySet())
+ {
+ if (hmRadioButtons.get(type).isSelected())
+ {
+ value = type;
+ break;
+ }
+ }
+
+ } else
+ {
+ JTextComponent field = getField(fieldName);
+ if (field != null)
+ {
+ value = field.getText();
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+ {
+ JLabel label = getLabel(fieldName);
+ if (label != null)
+ {
+ UIFactory.TextStyle style;
+
+ if (fieldName != FieldName.DIRECTORY_BASE_DN)
+ {
+ if (invalid)
+ {
+ style = UIFactory.TextStyle.SECONDARY_FIELD_INVALID;
+ } else
+ {
+ style = UIFactory.TextStyle.SECONDARY_FIELD_VALID;
+ }
+
+ } else
+ {
+ if (invalid)
+ {
+ style = UIFactory.TextStyle.PRIMARY_FIELD_INVALID;
+ } else
+ {
+ style = UIFactory.TextStyle.PRIMARY_FIELD_VALID;
+ }
+ }
+ UIFactory.setTextStyle(label, style);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Component createInputPanel()
+ {
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setOpaque(false);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ // Add the server location widgets
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ gbc.insets.top = 0;
+ gbc.insets.left = 0;
+ gbc.anchor = GridBagConstraints.WEST;
+ panel.add(getLabel(FieldName.DIRECTORY_BASE_DN), gbc);
+
+ JPanel auxPanel = new JPanel(new GridBagLayout());
+ auxPanel.setOpaque(false);
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 0.0;
+ auxPanel.add(getField(FieldName.DIRECTORY_BASE_DN), gbc);
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.insets.left = UIFactory.LEFT_INSET_BROWSE;
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ auxPanel.add(Box.createHorizontalGlue(), gbc);
+
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ panel.add(auxPanel, gbc);
+
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+ gbc.insets.left = 0;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ panel.add(getLabel(FieldName.DATA_OPTIONS), gbc);
+
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+ gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ panel.add(createRadioButtonPanel(), gbc);
+
+ addVerticalGlue(panel);
+
+ return panel;
+ }
+
+ /**
+ * Returns and creates the radio buttons panel.
+ * @return the radio buttons panel.
+ */
+ private JPanel createRadioButtonPanel()
+ {
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+ panel.setOpaque(false);
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ panel.add(getRadioButton(DataOptions.Type.CREATE_BASE_ENTRY), gbc);
+ gbc.insets.top = UIFactory.TOP_INSET_RADIOBUTTON;
+ panel.add(getRadioButton(DataOptions.Type.LEAVE_DATABASE_EMPTY), gbc);
+ panel.add(getRadioButton(DataOptions.Type.IMPORT_FROM_LDIF_FILE), gbc);
+
+ JPanel auxPanel =
+ createBrowseButtonPanel(FieldName.LDIF_PATH, getLDIFBrowseButton());
+
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.insets.top = UIFactory.TOP_INSET_RADIO_SUBORDINATE;
+ gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
+ panel.add(auxPanel, gbc);
+
+ gbc.insets.left = 0;
+ panel.add(getRadioButton(
+ DataOptions.Type.IMPORT_AUTOMATICALLY_GENERATED_DATA),
+ gbc);
+
+ auxPanel = createNumberEntriesPanel();
+
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
+ gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
+ panel.add(auxPanel, gbc);
+
+ return panel;
+ }
+
+ /**
+ * Returns the number entries panel.
+ * @return the number entries panel.
+ */
+ private JPanel createNumberEntriesPanel()
+ {
+ JPanel panel;
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ panel = new JPanel(new GridBagLayout());
+ panel.setOpaque(false);
+ gbc.gridwidth = 3;
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.weightx = 0.0;
+ panel.add(getLabel(FieldName.NUMBER_ENTRIES), gbc);
+
+ gbc.gridwidth--;
+ gbc.weightx = 0.1;
+ gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+ panel.add(getField(FieldName.NUMBER_ENTRIES), gbc);
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ panel.add(Box.createHorizontalGlue(), gbc);
+
+ return panel;
+ }
+
+ /**
+ * Creates a panel with a field and a browse button.
+ * @param fieldName the field name of the field.
+ * @param browseButton the browse button.
+ * @return the created panel.
+ */
+ private JPanel createBrowseButtonPanel(FieldName fieldName,
+ JButton browseButton)
+ {
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setOpaque(false);
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.gridwidth = 4;
+ gbc.weightx = 0.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ panel.add(getLabel(fieldName), gbc);
+
+ gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+ gbc.gridwidth--;
+ gbc.weightx = 0.1;
+ panel.add(getField(fieldName), gbc);
+
+ gbc.insets.left = UIFactory.LEFT_INSET_BROWSE;
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ panel.add(browseButton, gbc);
+
+ gbc.weightx = 1.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ panel.add(Box.createHorizontalGlue(), gbc);
+
+ return panel;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getInstructions()
+ {
+ return getMsg("data-options-panel-instructions");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getTitle()
+ {
+ return getMsg("data-options-panel-title");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endDisplay()
+ {
+ if (lastFocusComponent != null)
+ {
+ lastFocusComponent.requestFocusInWindow();
+ }
+ }
+
+ /**
+ * Returns the default value for the provided field Name.
+ * @param fieldName the field name for which we want to get the default
+ * value.
+ * @return the default value for the provided field Name.
+ */
+ private Object getDefaultValue(FieldName fieldName)
+ {
+ Object value = null;
+ switch (fieldName)
+ {
+ case DIRECTORY_BASE_DN:
+ value = defaultUserData.getDataOptions().getBaseDn();
+ break;
+
+ case DATA_OPTIONS:
+ value = defaultUserData.getDataOptions().getType();
+ break;
+
+ case LDIF_PATH:
+ value = defaultUserData.getDataOptions().getLDIFPath();
+ break;
+
+ case NUMBER_ENTRIES:
+ value = new Integer(defaultUserData.getDataOptions().getNumberEntries());
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown field name: " +
+ fieldName);
+ }
+
+ return value;
+ }
+
+ /**
+ * Returns the default string value for the provided field Name.
+ * @param fieldName the field name for which we want to get the default
+ * string value.
+ * @return the default value for the provided field Name.
+ */
+ private String getDefaultStringValue(FieldName fieldName)
+ {
+ String value = null;
+
+ Object v = getDefaultValue(fieldName);
+ if (v != null)
+ {
+ if (v instanceof String)
+ {
+ value = (String) v;
+ } else
+ {
+ value = String.valueOf(v);
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Creates the components and populates the Maps with them.
+ */
+ private void populateComponentMaps()
+ {
+ HashMap<FieldName, LabelFieldDescriptor> hm =
+ new HashMap<FieldName, LabelFieldDescriptor>();
+
+ hm.put(FieldName.DIRECTORY_BASE_DN, new LabelFieldDescriptor(
+ getMsg("base-dn-label"), getMsg("base-dn-tooltip"),
+ LabelFieldDescriptor.FieldType.TEXTFIELD,
+ LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.DN_FIELD_SIZE));
+
+ hm.put(FieldName.LDIF_PATH, new LabelFieldDescriptor(
+ getMsg("import-path-label"), getMsg("import-path-tooltip"),
+ LabelFieldDescriptor.FieldType.TEXTFIELD,
+ LabelFieldDescriptor.LabelType.SECONDARY, UIFactory.PATH_FIELD_SIZE));
+
+ hm.put(FieldName.NUMBER_ENTRIES, new LabelFieldDescriptor(
+ getMsg("number-entries-label"), getMsg("number-entries-tooltip"),
+ LabelFieldDescriptor.FieldType.TEXTFIELD,
+ LabelFieldDescriptor.LabelType.SECONDARY,
+ UIFactory.NUMBER_ENTRIES_FIELD_SIZE));
+
+ for (FieldName fieldName : hm.keySet())
+ {
+ JTextComponent field;
+ LabelFieldDescriptor desc = hm.get(fieldName);
+
+ String defaultValue = getDefaultStringValue(fieldName);
+ field = makeJTextComponent(desc, defaultValue);
+
+ hmFields.put(fieldName, field);
+
+ JLabel l = makeJLabel(desc);
+
+ l.setLabelFor(field);
+
+ hmLabels.put(fieldName, l);
+ }
+
+ JLabel dataLabel =
+ UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+ getMsg("directory-data-label"),
+ UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+
+ hmLabels.put(FieldName.DATA_OPTIONS, dataLabel);
+
+ String[] arg =
+ { getDefaultStringValue(FieldName.DIRECTORY_BASE_DN) };
+ JRadioButton rb =
+ UIFactory.makeJRadioButton(getMsg("create-base-entry-label", arg),
+ getMsg("create-base-entry-tooltip"),
+ UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+ hmRadioButtons.put(DataOptions.Type.CREATE_BASE_ENTRY, rb);
+
+ dataLabel.setLabelFor(rb);
+
+ rb =
+ UIFactory.makeJRadioButton(getMsg("leave-database-empty-label"),
+ getMsg("leave-database-empty-tooltip"),
+ UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+ hmRadioButtons.put(DataOptions.Type.LEAVE_DATABASE_EMPTY, rb);
+
+ rb =
+ UIFactory.makeJRadioButton(getMsg("import-data-from-ldif-label"),
+ getMsg("import-data-from-ldif-tooltip"),
+ UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+ hmRadioButtons.put(DataOptions.Type.IMPORT_FROM_LDIF_FILE, rb);
+
+ rb =
+ UIFactory.makeJRadioButton(
+ getMsg("import-automatically-generated-label"),
+ getMsg("import-automatically-generated-tooltip"),
+ UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+ hmRadioButtons
+ .put(DataOptions.Type.IMPORT_AUTOMATICALLY_GENERATED_DATA, rb);
+
+ DataOptions.Type defaultType =
+ (DataOptions.Type) getDefaultValue(FieldName.DATA_OPTIONS);
+
+ ButtonGroup buttonGroup = new ButtonGroup();
+ for (DataOptions.Type type : hmRadioButtons.keySet())
+ {
+ rb = hmRadioButtons.get(type);
+ rb.setOpaque(false);
+ rb.setSelected(type == defaultType);
+ buttonGroup.add(rb);
+ }
+ }
+
+ /**
+ * Returns the browse button to browse LDIF files.
+ * If it does not exist creates the browse button to browse LDIF files.
+ * @return the browse button to browse LDIF files.
+ */
+ private JButton getLDIFBrowseButton()
+ {
+ if (ldifBrowseButton == null)
+ {
+ ldifBrowseButton =
+ UIFactory.makeJButton(getMsg("browse-button-label"),
+ getMsg("browse-button-tooltip"));
+
+ BrowseActionListener l =
+ new BrowseActionListener(getField(FieldName.LDIF_PATH),
+ BrowseActionListener.BrowseType.OPEN_LDIF_FILE, getMainWindow());
+ ldifBrowseButton.addActionListener(l);
+ }
+ return ldifBrowseButton;
+ }
+
+
+ /**
+ * Adds all the required document listeners to the fields.
+ */
+ private void addDocumentListeners()
+ {
+ JTextComponent tf = getField(FieldName.DIRECTORY_BASE_DN);
+ tf.getDocument().addDocumentListener(new DocumentListener()
+ {
+ public void changedUpdate(DocumentEvent ev)
+ {
+ String[] arg =
+ { (String) getFieldValue(FieldName.DIRECTORY_BASE_DN) };
+
+ String newLabel = getMsg("create-base-entry-label", arg);
+ JRadioButton rb =
+ getRadioButton(DataOptions.Type.CREATE_BASE_ENTRY);
+ rb.setText(newLabel);
+ }
+
+ public void insertUpdate(DocumentEvent ev)
+ {
+ changedUpdate(ev);
+ }
+
+ public void removeUpdate(DocumentEvent ev)
+ {
+ changedUpdate(ev);
+ }
+ });
+ }
+
+ /**
+ * Adds the required focus listeners to the fields.
+ */
+ private void addFocusListeners()
+ {
+ final FocusListener l = new FocusListener()
+ {
+ public void focusGained(FocusEvent e)
+ {
+ lastFocusComponent = e.getComponent();
+ if (lastFocusComponent == getField(FieldName.LDIF_PATH))
+ {
+ getRadioButton(DataOptions.Type.IMPORT_FROM_LDIF_FILE).setSelected(
+ true);
+ } else if (lastFocusComponent == getField(FieldName.NUMBER_ENTRIES))
+ {
+ getRadioButton(
+ DataOptions.Type.IMPORT_AUTOMATICALLY_GENERATED_DATA)
+ .setSelected(true);
+ }
+ }
+
+ public void focusLost(FocusEvent e)
+ {
+ }
+ };
+
+ for (JTextComponent tf : hmFields.values())
+ {
+ tf.addFocusListener(l);
+ }
+ for (JRadioButton rb : hmRadioButtons.values())
+ {
+ rb.addFocusListener(l);
+ }
+ getLDIFBrowseButton().addFocusListener(l);
+
+ lastFocusComponent = getField(FieldName.DIRECTORY_BASE_DN);
+ }
+
+ /**
+ * Returns the label associated with the given field name.
+ * @param fieldName the field name for which we want to retrieve the JLabel.
+ * @return the label associated with the given field name.
+ */
+ private JLabel getLabel(FieldName fieldName)
+ {
+ return hmLabels.get(fieldName);
+ }
+
+ /**
+ * Returns the JTextComponent associated with the given field name.
+ * @param fieldName the field name for which we want to retrieve the
+ * JTextComponent.
+ * @return the JTextComponent associated with the given field name.
+ */
+ private JTextComponent getField(FieldName fieldName)
+ {
+ return hmFields.get(fieldName);
+ }
+
+ /**
+ * Returns the JRadioButton associated with the given DataOptions.Type.
+ * @param type the DataOptions.Type object for which we want to retrieve the
+ * JRadioButton.
+ * @return the JRadioButton associated with the given DataOptions.Type object.
+ */
+ private JRadioButton getRadioButton(DataOptions.Type type)
+ {
+ return hmRadioButtons.get(type);
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java
new file mode 100644
index 0000000..f82a9a2
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java
@@ -0,0 +1,186 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.AlphaComposite;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.Box;
+import javax.swing.Icon;
+import javax.swing.JPanel;
+
+/**
+ * This class is the panel that is displayed in the QuickSetupDialog. It
+ * contains 3 panels that are passed in the constructor: the steps panel,
+ * the buttons panel and the current step panel (the main panel of the three).
+ *
+ * The only remarkable thing of this class is that is responsible for
+ * implementing the background. The three subpanels are transparent and
+ * this class sets a background (with the Open DS logo) and uses some basic
+ * transparency effects.
+ *
+ */
+class FramePanel extends JPanel
+{
+ private static final long serialVersionUID = 7733658951410876078L;
+
+ private Icon backgroundIcon;
+
+ private Component stepsPanel;
+
+ private Component buttonsPanel;
+
+ private int buttonsPanelVerticalInsets;
+
+ private int stepsPanelHorizontalInsets;
+
+ /**
+ * The constructor of the FramePanel.
+ * @param stepsPanel the steps panel that on the top-left side of the
+ * QuickSetupDialog.
+ * @param currentStepPanel the current step panel (the panel that displays
+ * what is associated to the current step). Is the panel that contains all
+ * the input fields and is located on the top-right side of the
+ * QuickSetupDialog.
+ * @param buttonsPanel the buttons panel that appears on the bottom of the
+ * QuickSetupDialog.
+ */
+ public FramePanel(Component stepsPanel, Component currentStepPanel,
+ Component buttonsPanel)
+ {
+ super(new GridBagLayout());
+ setBackground(UIFactory.DEFAULT_BACKGROUND);
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ gbc.weighty = 1.0;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.fill = GridBagConstraints.VERTICAL;
+ gbc.insets = UIFactory.getStepsPanelInsets();
+ add(stepsPanel, gbc);
+
+ stepsPanelHorizontalInsets = gbc.insets.left + gbc.insets.right;
+
+ JPanel currentPanelContainer = new JPanel(new GridBagLayout());
+ currentPanelContainer.setBorder(UIFactory.CURRENT_STEP_PANEL_BORDER);
+ currentPanelContainer
+ .setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+ currentPanelContainer.setOpaque(false);
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.insets = UIFactory.getCurrentStepPanelInsets();
+ currentPanelContainer.add(currentStepPanel, gbc);
+ gbc.insets = UIFactory.getEmptyInsets();
+ add(currentPanelContainer, gbc);
+
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ gbc.weighty = 0.0;
+ add(Box.createHorizontalGlue(), gbc);
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ gbc.weighty = 0.0;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets = UIFactory.getButtonsPanelInsets();
+ add(buttonsPanel, gbc);
+
+ buttonsPanelVerticalInsets = gbc.insets.top + gbc.insets.bottom;
+
+ backgroundIcon =
+ UIFactory.getImageIcon(UIFactory.IconType.BACKGROUND);
+
+ this.buttonsPanel = buttonsPanel;
+ this.stepsPanel = stepsPanel;
+ int width =
+ Math.max((int) getPreferredSize().getWidth(), backgroundIcon
+ .getIconWidth()
+ + UIFactory.LEFT_INSET_BACKGROUND
+ + UIFactory.RIGHT_INSET_BACKGROUND);
+ int height =
+ Math.max((int) getPreferredSize().getHeight(), backgroundIcon
+ .getIconHeight()
+ + UIFactory.TOP_INSET_BACKGROUND
+ + UIFactory.BOTTOM_INSET_BACKGROUND);
+ setPreferredSize(new Dimension(width, height));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This method has been overwritten to be able to have a transparency effect
+ * with the OpenDS logo background.
+ */
+ protected void paintComponent(Graphics g)
+ {
+ if (isOpaque())
+ { // paint background
+ g.setColor(UIFactory.DEFAULT_BACKGROUND);
+ int width = getWidth();
+ int height = getHeight();
+ int buttonsTotalHeight =
+ buttonsPanel.getHeight() + buttonsPanelVerticalInsets;
+ int stepsPanelTotalWidth =
+ stepsPanel.getWidth() + stepsPanelHorizontalInsets;
+
+ g.fillRect(0, 0, stepsPanelTotalWidth, height);
+ g.fillRect(stepsPanelTotalWidth, height - buttonsTotalHeight, width,
+ height);
+ g.setColor(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+ g.fillRect(stepsPanelTotalWidth, 0, width, height - buttonsTotalHeight);
+ }
+
+ if (backgroundIcon != null)
+ {
+ // Draw the icon over and over, right aligned.
+ // Copy the Graphics object, which is actually
+ // a Graphics2D object. Cast it so we can
+ // set alpha composite.
+ Graphics2D g2d = (Graphics2D) g.create();
+
+ g2d.setComposite(AlphaComposite
+ .getInstance(AlphaComposite.SRC_OVER, 0.1f));
+
+ backgroundIcon.paintIcon(this, g2d, UIFactory.LEFT_INSET_BACKGROUND,
+ UIFactory.TOP_INSET_BACKGROUND);
+
+ g2d.dispose(); //clean up
+ }
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
new file mode 100644
index 0000000..5b3a03d
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ProgressPanel.java
@@ -0,0 +1,211 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.Box;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.Installer;
+
+/**
+ * This panel is used to show the progress of the install or the uninstall.
+ *
+ */
+public class ProgressPanel extends QuickSetupStepPanel
+{
+ private static final long serialVersionUID = 8129425068163357170L;
+
+ private JEditorPane progressBarLabel;
+
+ private JProgressBar progressBar;
+
+ private JEditorPane detailsTextArea;
+
+ private JScrollPane scroll;
+
+ private String lastText;
+
+ /**
+ * ProgressPanel constructor.
+ */
+ public ProgressPanel()
+ {
+ createLayout();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Component createInputPanel()
+ {
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setOpaque(false);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+
+ progressBarLabel =
+ UIFactory.makeHtmlPane(getMsg("progressbar-initial-label"),
+ UIFactory.PROGRESS_FONT);
+ progressBarLabel.addHyperlinkListener(this);
+ panel.add(progressBarLabel, gbc);
+
+ gbc.insets.top = UIFactory.TOP_INSET_PROGRESS_BAR;
+ gbc.insets.bottom = UIFactory.BOTTOM_INSET_PROGRESS_BAR;
+ panel.add(createProgressBarPanel(), gbc);
+ progressBar.setToolTipText(getMsg("progressbar-tooltip"));
+
+ JLabel l =
+ UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+ getMsg("progress-details-label"),
+ UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+
+ gbc.insets = UIFactory.getEmptyInsets();
+ panel.add(l, gbc);
+
+ scroll = new JScrollPane();
+ detailsTextArea = UIFactory.makeProgressPane(scroll);
+ detailsTextArea.setBackground(
+ UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+ detailsTextArea.addHyperlinkListener(new HyperlinkListener()
+ {
+ public void hyperlinkUpdate(HyperlinkEvent e)
+ {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+ {
+ String url = e.getURL().toString();
+ String newText = Installer.getHtmlAfterUrlClick(url, lastText);
+ lastText = newText;
+ detailsTextArea.setText(lastText);
+ }
+ }
+ });
+ detailsTextArea.setAutoscrolls(true);
+ scroll.setViewportView(detailsTextArea);
+
+ scroll.setBorder(UIFactory.TEXT_AREA_BORDER);
+ scroll.setWheelScrollingEnabled(true);
+ l.setLabelFor(detailsTextArea);
+ gbc.insets.top = UIFactory.TOP_INSET_PROGRESS_TEXTAREA;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.weighty = 1.0;
+ panel.add(scroll, gbc);
+
+ return panel;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getInstructions()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getTitle()
+ {
+ return getMsg("progress-panel-title");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void displayProgress(InstallProgressDescriptor descriptor)
+ {
+ progressBarLabel.setText(UIFactory.applyFontToHtml(descriptor
+ .getProgressBarMsg(), UIFactory.PROGRESS_FONT));
+ InstallProgressStep status = descriptor.getProgressStep();
+ if ((status == InstallProgressStep.FINISHED_WITH_ERROR)
+ || (status == InstallProgressStep.FINISHED_SUCCESSFULLY))
+ {
+ progressBar.setVisible(false);
+ }
+ int v = descriptor.getProgressBarRatio().intValue();
+ if (v > 0)
+ {
+ progressBar.setIndeterminate(false);
+ progressBar.setValue(v);
+ }
+ lastText = descriptor.getDetailsMsg();
+ detailsTextArea.setText(lastText);
+ }
+
+ /**
+ * Creates the progress bar panel.
+ * @return the created panel.
+ */
+ private JPanel createProgressBarPanel()
+ {
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setOpaque(false);
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+
+ progressBar = new JProgressBar();
+ progressBar.setIndeterminate(true);
+ // The ProgressDescriptor provides the ratio in %
+ progressBar.setMaximum(100);
+
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ panel.add(Box.createHorizontalStrut(UIFactory.PROGRESS_BAR_SIZE), gbc);
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ panel.add(Box.createHorizontalGlue(), gbc);
+
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ panel.add(progressBar, gbc);
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ panel.add(Box.createHorizontalGlue(), gbc);
+
+ return panel;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
new file mode 100644
index 0000000..4d85afd
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
@@ -0,0 +1,682 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.HashSet;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.opends.quicksetup.ButtonName;
+import org.opends.quicksetup.CurrentInstallStatus;
+import org.opends.quicksetup.Step;
+import org.opends.quicksetup.event.ButtonActionListener;
+import org.opends.quicksetup.event.ButtonEvent;
+import org.opends.quicksetup.event.MinimumSizeComponentListener;
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.InstallProgressStep;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class represents the dialog used by installer and the uninstaller.
+ *
+ * In its constructor it gets as parameters an object describing the current
+ * installation status and the default values to be proposed to the user
+ * in the panels.
+ *
+ * If we are installing Open DS and the server has already been installed it
+ * will display an error message. In the other cases it will display a wizard
+ * (that is different depending on whether we are installing or uninstalling).
+ *
+ */
+public class QuickSetupDialog
+{
+ private JFrame frame;
+
+ private QuickSetupErrorPanel installedPanel;
+
+ private JPanel framePanel;
+
+ private StepsPanel stepsPanel;
+
+ private CurrentStepPanel currentStepPanel;
+
+ private ButtonsPanel buttonsPanel;
+
+ private Step displayedStep;
+
+ private UserInstallData defaultUserData;
+
+ private CurrentInstallStatus installStatus;
+
+ private HashSet<ButtonActionListener> buttonListeners =
+ new HashSet<ButtonActionListener>();
+
+ /**
+ * Constructor of QuickSetupDialog.
+ * @param defaultUserData the default values to be proposed to the user in
+ * the wizard.
+ * @param installStatus the current installation status.
+ */
+ public QuickSetupDialog(UserInstallData defaultUserData,
+ CurrentInstallStatus installStatus)
+ {
+ this.defaultUserData = defaultUserData;
+ this.installStatus = installStatus;
+
+ if (isUninstall())
+ {
+ frame = new JFrame(getMsg("frame-uninstall-title"));
+ } else
+ {
+ frame = new JFrame(getMsg("frame-quicksetup-title"));
+ }
+
+ frame.getContentPane().add(getFramePanel());
+ frame.addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent e)
+ {
+ if (isUninstall())
+ {
+ if (getDisplayedStep() == Step.PROGRESS)
+ {
+ // Simulate a close button event
+ notifyButtonEvent(ButtonName.CLOSE);
+ } else
+ {
+ // Simulate a quit button event
+ notifyButtonEvent(ButtonName.QUIT);
+ }
+ } else if (isInstalled())
+ {
+ // Simulate a close button event
+ notifyButtonEvent(ButtonName.CLOSE);
+ } else
+ {
+ if (getDisplayedStep() == Step.PROGRESS)
+ {
+ // Simulate a close button event
+ notifyButtonEvent(ButtonName.CLOSE);
+ } else
+ {
+ // Simulate a quit button event
+ notifyButtonEvent(ButtonName.QUIT);
+ }
+ }
+ }
+ });
+ frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ UIFactory.IconType ic;
+ if (Utils.isMacOS())
+ {
+ ic = UIFactory.IconType.MINIMIZED_MAC;
+ } else
+ {
+ ic = UIFactory.IconType.MINIMIZED;
+ }
+ frame.setIconImage(UIFactory.getImageIcon(ic).getImage());
+ }
+
+ /**
+ * Packs and displays this dialog.
+ *
+ */
+ public void packAndShow()
+ {
+ frame.pack();
+ int minWidth = (int) frame.getPreferredSize().getWidth();
+ int minHeight = (int) frame.getPreferredSize().getHeight();
+ Utils.centerOnScreen(frame);
+ if (isUninstall())
+ {
+ setFocusOnButton(ButtonName.FINISH);
+ } else if (!isInstalled())
+ {
+ setFocusOnButton(ButtonName.NEXT);
+ } else
+ {
+ setFocusOnButton(ButtonName.QUIT);
+ }
+
+ frame.addComponentListener(new MinimumSizeComponentListener(frame,
+ minWidth, minHeight));
+
+ frame.setVisible(true);
+ }
+
+ /**
+ * Displays the panel corresponding to the provided step. The panel contents
+ * are updated with the contents of the UserInstallData object.
+ * @param step the step that we want to display.
+ * @param userData the UserInstallData object that must be used to populate
+ * the panels.
+ */
+ public void setDisplayedStep(Step step, UserInstallData userData)
+ {
+ displayedStep = step;
+ if (isUninstall())
+ {
+ // First call the panels to do the required updates on their layout
+ getButtonsPanel().setDisplayedStep(step);
+ getStepsPanel().setDisplayedStep(step);
+ getCurrentStepPanel().setDisplayedStep(step, userData);
+
+ // Set the default button for the frame
+ switch (step)
+ {
+ case CONFIRM_UNINSTALL:
+ setDefaultButton(ButtonName.FINISH);
+ break;
+
+ case PROGRESS:
+ setDefaultButton(ButtonName.CLOSE);
+ break;
+ }
+
+ // Set the focus for the current step
+ switch (step)
+ {
+ case CONFIRM_UNINSTALL:
+ setFocusOnButton(ButtonName.FINISH);
+ break;
+
+ case PROGRESS:
+ setFocusOnButton(ButtonName.CLOSE);
+ setButtonEnabled(ButtonName.CLOSE, false);
+ break;
+ }
+ } else if (!isInstalled())
+ {
+ // First call the panels to do the required updates on their layout
+ getButtonsPanel().setDisplayedStep(step);
+ getStepsPanel().setDisplayedStep(step);
+ getCurrentStepPanel().setDisplayedStep(step, userData);
+
+ // Set the default button for the frame
+ switch (step)
+ {
+ case REVIEW:
+ setDefaultButton(ButtonName.FINISH);
+ break;
+
+ case PROGRESS:
+ setDefaultButton(ButtonName.CLOSE);
+ break;
+
+ default:
+ setDefaultButton(ButtonName.NEXT);
+ }
+
+ // Set the focus for the current step
+ switch (step)
+ {
+ case WELCOME:
+ setFocusOnButton(ButtonName.NEXT);
+ break;
+
+ case SERVER_SETTINGS:
+ // The focus is set by the panel itself
+ break;
+
+ case DATA_OPTIONS:
+ // The focus is set by the panel itself
+ break;
+
+ case REVIEW:
+ setFocusOnButton(ButtonName.FINISH);
+ break;
+
+ case PROGRESS:
+ setFocusOnButton(ButtonName.CLOSE);
+ setButtonEnabled(ButtonName.CLOSE, false);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns the currently displayed step.
+ * @return the currently displayed step.
+ */
+ public Step getDisplayedStep()
+ {
+ return displayedStep;
+ }
+
+ /**
+ * Forwards to the displayed panel the InstallProgressDescriptor so that they
+ * can update their contents accordingly.
+ * @param descriptor the descriptor of the Installation progress.
+ */
+ public void displayProgress(InstallProgressDescriptor descriptor)
+ {
+ getCurrentStepPanel().displayProgress(descriptor);
+ InstallProgressStep status = descriptor.getProgressStep();
+ if ((status == InstallProgressStep.FINISHED_SUCCESSFULLY)
+ || (status == InstallProgressStep.FINISHED_WITH_ERROR))
+ {
+ setButtonEnabled(ButtonName.CLOSE, true);
+ }
+ }
+
+ /**
+ * Displays an error message dialog.
+ *
+ * @param msg
+ * the error message.
+ * @param title
+ * the title for the dialog.
+ */
+ public void displayError(String msg, String title)
+ {
+ JOptionPane.showMessageDialog(getFrame(), msg, title,
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ /**
+ * Displays a confirmation message dialog.
+ *
+ * @param msg
+ * the confirmation message.
+ * @param title
+ * the title of the dialog.
+ * @return <CODE>true</CODE> if the user confirms the message, or
+ * <CODE>false</CODE> if not.
+ */
+ public boolean displayConfirmation(String msg, String title)
+ {
+ return JOptionPane.YES_OPTION == JOptionPane.showOptionDialog(
+ getFrame(), msg, title, JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE, null, // don't use a custom
+ // Icon
+ null, // the titles of buttons
+ null); // default button title
+ }
+
+ /**
+ * Returns the value corresponding to the provided FieldName.
+ * @param fieldName the FieldName for which we want to obtain the value.
+ * @return the value corresponding to the provided FieldName.
+ */
+ public Object getFieldValue(FieldName fieldName)
+ {
+ return getCurrentStepPanel().getFieldValue(fieldName);
+ }
+
+ /**
+ * Marks as invalid (or valid depending on the value of the invalid parameter)
+ * a field corresponding to FieldName. This basically implies udpating the
+ * style of the JLabel associated with fieldName (the association is done
+ * using the LabelFieldDescriptor class).
+ * @param fieldName the FieldName to be marked as valid or invalid.
+ * @param invalid whether to mark the field as valid or invalid.
+ */
+ public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+ {
+ getCurrentStepPanel().displayFieldInvalid(fieldName, invalid);
+ }
+
+ /**
+ * Adds a button listener. All the button listeners will be notified when
+ * the buttons are clicked (by the user or programatically).
+ * @param l the ButtonActionListener to be added.
+ */
+ public void addButtonActionListener(ButtonActionListener l)
+ {
+ if (isUninstall())
+ {
+ getButtonsPanel().addButtonActionListener(l);
+ } else if (isInstalled())
+ {
+ getInstalledPanel().addButtonActionListener(l);
+ } else
+ {
+ getButtonsPanel().addButtonActionListener(l);
+ }
+ buttonListeners.add(l);
+ }
+
+ /**
+ * Removes a button listener.
+ * @param l the ButtonActionListener to be removed.
+ */
+ public void removeButtonActionListener(ButtonActionListener l)
+ {
+ if (isUninstall())
+ {
+ getButtonsPanel().removeButtonActionListener(l);
+ } else if (isInstalled())
+ {
+ getInstalledPanel().removeButtonActionListener(l);
+ } else
+ {
+ getButtonsPanel().removeButtonActionListener(l);
+ }
+ buttonListeners.remove(l);
+ }
+
+ /**
+ * This method is called to inform that a worker has started (the QuickSetup
+ * is doing some data validation). The worker is doing its tasks outside
+ * the event thread to avoid blocking of the painting and this class is
+ * notified of this fact. The method basically simply the Next and Previous
+ * buttons.
+ *
+ * This method can be called from the event thread or outside the event
+ * thread.
+ *
+ */
+ public void workerStarted()
+ {
+ Runnable r = new Runnable()
+ {
+ public void run()
+ {
+ // TODO: here we could have an animated gif.
+ setButtonEnabled(ButtonName.NEXT, false);
+ setButtonEnabled(ButtonName.PREVIOUS, false);
+ }
+ };
+ runOnEventThread(r);
+ }
+
+ /**
+ * This method is called to inform that a worker has finished. The method just
+ * enables the Next and Previous buttons.
+ *
+ * This method can be called from the event thread or outside the event
+ * thread.
+ *
+ */
+ public void workerFinished()
+ {
+ Runnable r = new Runnable()
+ {
+ public void run()
+ {
+ // TO COMPLETE: here we could have an animated gif.
+ setButtonEnabled(ButtonName.NEXT, true);
+ setButtonEnabled(ButtonName.PREVIOUS, true);
+ }
+ };
+ runOnEventThread(r);
+ }
+
+ /**
+ * Notification from the worker with a message.
+ * @param msg the message sent by the worker.
+ */
+ public void workerMessage(String msg)
+ {
+ // TODO For the moment not used.
+ }
+
+ /**
+ * Notification telling that the installation/uninstallation is finished.
+ * @param successful a boolean telling whether the setup was successful or
+ * not.
+ */
+ public void finished(boolean successful)
+ {
+ setButtonEnabled(ButtonName.CLOSE, true);
+ if (!successful)
+ {
+ // Do nothing... all the error messages
+ }
+ }
+
+ /**
+ * Enables a button associated with the given Button Name.
+ * @param buttonName the button name of the button.
+ * @param enable boolean indicating to enable or to disable the button.
+ */
+ private void setButtonEnabled(ButtonName buttonName, boolean enable)
+ {
+ getButton(buttonName).setEnabled(enable);
+ }
+
+ /**
+ * Returns the frame containing the dialog.
+ * @return the frame containing the dialog.
+ */
+ private JFrame getFrame()
+ {
+ return frame;
+ }
+
+ /**
+ * Returns the panel of the dialog.
+ * @return the panel of the dialog.
+ */
+ private JPanel getFramePanel()
+ {
+ JPanel p;
+ if (isUninstall())
+ {
+ if (framePanel == null)
+ {
+ framePanel =
+ new FramePanel(getStepsPanel(), getCurrentStepPanel(),
+ getButtonsPanel());
+ }
+ p = framePanel;
+ } else if (isInstalled())
+ {
+ p = getInstalledPanel();
+ } else
+ {
+ if (framePanel == null)
+ {
+ framePanel =
+ new FramePanel(getStepsPanel(), getCurrentStepPanel(),
+ getButtonsPanel());
+ }
+ p = framePanel;
+ }
+ return p;
+ }
+
+ /**
+ * Returns the steps panel.
+ * @return the steps panel.
+ */
+ private StepsPanel getStepsPanel()
+ {
+ if (stepsPanel == null)
+ {
+ stepsPanel = new StepsPanel(isUninstall());
+ }
+ return stepsPanel;
+ }
+
+ /**
+ * Returns the current step panel.
+ * @return the current step panel.
+ */
+ private CurrentStepPanel getCurrentStepPanel()
+ {
+ if (currentStepPanel == null)
+ {
+ currentStepPanel = new CurrentStepPanel(defaultUserData, isUninstall());
+ }
+ return currentStepPanel;
+ }
+
+
+ /**
+ * Returns the buttons panel.
+ * @return the buttons panel.
+ */
+ private ButtonsPanel getButtonsPanel()
+ {
+ if (buttonsPanel == null)
+ {
+ buttonsPanel = new ButtonsPanel();
+ }
+ return buttonsPanel;
+ }
+
+ /* Different commodity methods to retrieve localized messages */
+ private String getMsg(String key)
+ {
+ return getI18n().getMsg(key);
+ }
+
+ private ResourceProvider getI18n()
+ {
+ return ResourceProvider.getInstance();
+ }
+
+ /**
+ * Returns the button corresponding to the buttonName.
+ * @param buttonName the ButtonName for which we want to get the button.
+ * @return the button corresponding to the buttonName.
+ */
+ private JButton getButton(ButtonName buttonName)
+ {
+ JButton button;
+ if (isUninstall())
+ {
+ button = getButtonsPanel().getButton(buttonName);
+ } else if (isInstalled())
+ {
+ if (buttonName == ButtonName.QUIT)
+ {
+ button = getInstalledPanel().getQuitButton();
+ } else
+ {
+ throw new IllegalStateException("Invalid button name " + buttonName
+ + " if server is installed");
+ }
+ } else
+ {
+ button = getButtonsPanel().getButton(buttonName);
+ }
+ return button;
+ }
+
+ /**
+ * Sets the focus in the button associated with the ButtonName.
+ * @param buttonName the ButtonName associated with the button.
+ */
+ private void setFocusOnButton(ButtonName buttonName)
+ {
+ getButton(buttonName).requestFocusInWindow();
+ }
+
+ /**
+ * Sets the default button for the frame.
+ * @param buttonName the ButtonName associated with the button.
+ */
+ private void setDefaultButton(ButtonName buttonName)
+ {
+ getFrame().getRootPane().setDefaultButton(getButton(buttonName));
+ }
+
+ /**
+ * Method used to execute a Runnable in the event thread. If we are in the
+ * event thread it will be called synchronously and if we are not it will
+ * be executed asynchronously.
+ *
+ * @param r the Runnable to be executed.
+ */
+ private void runOnEventThread(Runnable r)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ r.run();
+ } else
+ {
+ SwingUtilities.invokeLater(r);
+ }
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if this is an uninstallation and
+ * <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if this is an uninstallation and
+ * <CODE>false</CODE> otherwise.
+ */
+ private boolean isUninstall()
+ {
+ return Utils.isUninstall();
+ }
+
+
+ /**
+ * Returns <CODE>true</CODE> if the server is already installed and
+ * <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if the server is already installed and
+ * <CODE>false</CODE> otherwise.
+ */
+ private boolean isInstalled()
+ {
+ return installStatus.isInstalled();
+ }
+
+ /**
+ * Returns (and creates if it is not already created) the panel that
+ * informs the user that the server is already installed when the
+ * installation has been launched.
+ * @return the panel that is used
+ * to inform the user that the server is already installed when the
+ * installation has been launched.
+ */
+ private QuickSetupErrorPanel getInstalledPanel()
+ {
+ if (installedPanel == null)
+ {
+ installedPanel =
+ new QuickSetupErrorPanel(installStatus.getInstallationMsg());
+ }
+ return installedPanel;
+ }
+
+ /**
+ * Notifies the ButtonActionListener objects that an ButtonEvent has occurred
+ * in the button associated with buttonName.
+ * @param buttonName the ButtonName associated with the button.
+ */
+ private void notifyButtonEvent(ButtonName buttonName)
+ {
+ ButtonEvent be = new ButtonEvent(this, buttonName);
+ for (ButtonActionListener li : buttonListeners)
+ {
+ li.buttonActionPerformed(be);
+ }
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
new file mode 100644
index 0000000..7a046c8
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupErrorPanel.java
@@ -0,0 +1,160 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashSet;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.ButtonName;
+import org.opends.quicksetup.event.ButtonActionListener;
+import org.opends.quicksetup.event.ButtonEvent;
+
+/**
+ * This class is a panel that contains an error message and a quit button.
+ * It is used for instance when we try to install Open DS but it is already
+ * installed.
+ *
+ */
+public class QuickSetupErrorPanel extends QuickSetupPanel
+{
+ private static final long serialVersionUID = 1765037717593522233L;
+
+ private HashSet<ButtonActionListener> buttonListeners =
+ new HashSet<ButtonActionListener>();
+
+ private JButton quitButton;
+
+ /**
+ * Constructor of the QuickSetupErrorPanel.
+ *
+ * @param htmlMsg the error message to be displayed.
+ */
+ public QuickSetupErrorPanel(String htmlMsg)
+ {
+ JPanel p1 = new JPanel(new GridBagLayout());
+ p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+ p1.setBorder(UIFactory.DIALOG_PANEL_BORDER);
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.insets = UIFactory.getCurrentStepPanelInsets();
+ p1.add(UIFactory.makeJLabel(UIFactory.IconType.WARNING_LARGE, null,
+ UIFactory.TextStyle.NO_STYLE), gbc);
+ gbc.weightx = 1.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.insets.left = 0;
+ JTextComponent tf =
+ UIFactory.makeHtmlPane(htmlMsg, UIFactory.INSTRUCTIONS_FONT);
+ tf.setOpaque(false);
+ p1.add(tf, gbc);
+
+ gbc.weighty = 1.0;
+ gbc.fill = GridBagConstraints.VERTICAL;
+ p1.add(Box.createVerticalGlue(), gbc);
+
+ JPanel p2 = new JPanel(new GridBagLayout());
+ p2.setOpaque(false);
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 1.0;
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ p2.add(Box.createHorizontalGlue(), gbc);
+ quitButton =
+ UIFactory.makeJButton(getMsg("quit-button-label"),
+ getMsg("quit-button-tooltip"));
+
+ final ButtonName fButtonName = ButtonName.QUIT;
+
+ ActionListener actionListener = new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ev)
+ {
+ ButtonEvent be = new ButtonEvent(ev.getSource(), fButtonName);
+ for (ButtonActionListener li : buttonListeners)
+ {
+ li.buttonActionPerformed(be);
+ }
+ }
+ };
+ quitButton.addActionListener(actionListener);
+
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.weightx = 0.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ p2.add(quitButton, gbc);
+
+ setLayout(new GridBagLayout());
+ setBackground(UIFactory.DEFAULT_BACKGROUND);
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ add(p1, gbc);
+ gbc.weighty = 0.0;
+ gbc.insets = UIFactory.getButtonsPanelInsets();
+ add(p2, gbc);
+ }
+
+ /**
+ * Adds a button listener. All the button listeners will be notified when
+ * the buttons are clicked (by the user or programatically).
+ * @param l the ButtonActionListener to be added.
+ */
+ public void addButtonActionListener(ButtonActionListener l)
+ {
+ buttonListeners.add(l);
+ }
+
+ /**
+ * Removes a button listener.
+ * @param l the ButtonActionListener to be removed.
+ */
+ public void removeButtonActionListener(ButtonActionListener l)
+ {
+ buttonListeners.remove(l);
+ }
+
+ /**
+ * Returns the quit button.
+ * @return the quit button.
+ */
+ public JButton getQuitButton()
+ {
+ return quitButton;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupPanel.java
new file mode 100644
index 0000000..9371bdd
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupPanel.java
@@ -0,0 +1,126 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Component;
+import java.awt.Frame;
+import java.awt.Window;
+
+import javax.swing.JPanel;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+
+/**
+ * This class is an abstract class that provides some commodity methods.
+ *
+ */
+abstract class QuickSetupPanel extends JPanel
+{
+ private static final long serialVersionUID = 2096518919339628055L;
+
+ /**
+ * The basic constructor to be called by the subclasses.
+ *
+ */
+ protected QuickSetupPanel()
+ {
+ super();
+ setOpaque(false);
+ }
+
+ /**
+ * Returns the frame or window containing this panel.
+ * @return the frame or window containing this panel.
+ */
+ public Component getMainWindow()
+ {
+ Component w = null;
+ Component c = this;
+
+ while (w == null)
+ {
+ if (c instanceof Frame || c instanceof Window)
+ {
+ w = c;
+ }
+ if (c.getParent() == null)
+ {
+ w = c;
+ } else
+ {
+ c = c.getParent();
+ }
+ }
+
+ return w;
+ }
+
+ /**
+ * Returns a localized message for a key value. In the properties file we
+ * have something of type:
+ * key=value
+ *
+ * @see ResourceProvider.getMsg(String key)
+ * @param key the key in the properties file.
+ * @return the value associated to the key in the properties file.
+ * properties file.
+ */
+ protected String getMsg(String key)
+ {
+ return getI18n().getMsg(key);
+ }
+
+ /**
+ * Returns a localized message for a key value. In the properties file we
+ * have something of type:
+ * key=value
+ *
+ * For instance if we pass as key "mykey" and as arguments {"value1"} and
+ * in the properties file we have:
+ * mykey=value with argument {0}.
+ *
+ * This method will return "value with argument value1".
+ * @see ResourceProvider.getMsg(String key, String[] args)
+ * @param key the key in the properties file.
+ * @param args the arguments to be passed to generate the resulting value.
+ * @return the value associated to the key in the properties file.
+ */
+ protected String getMsg(String key, String[] args)
+ {
+ return getI18n().getMsg(key, args);
+ }
+
+ /**
+ * Returns a ResourceProvider instance.
+ * @return a ResourceProvider instance.
+ */
+ private ResourceProvider getI18n()
+ {
+ return ResourceProvider.getInstance();
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
new file mode 100644
index 0000000..0e22ab4
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupStepPanel.java
@@ -0,0 +1,439 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.InstallProgressDescriptor;
+import org.opends.quicksetup.installer.LabelFieldDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.util.URLWorker;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is an abstract class that is extended by all the classes that are in
+ * the CardLayout of CurrentStepPanel. All the panels that appear on the
+ * top-right side of the dialog extend this class: WelcomePane, ReviewPanel,
+ * etc.
+ *
+ */
+public abstract class QuickSetupStepPanel extends QuickSetupPanel
+implements HyperlinkListener
+{
+ private Component inputPanel;
+
+ // We can use a HashMap (not multi-thread safe) because all
+ // the calls to this object are done in the event-thread.
+ private HashMap<String, URLWorker> hmURLWorkers =
+ new HashMap<String, URLWorker>();
+
+ /**
+ * Called just before the panel is shown: used to update the contents of the
+ * panel with new UserData (used in particular in the review panel).
+ *
+ * @param data the new user data.
+ */
+ public void beginDisplay(UserInstallData data)
+ {
+ }
+
+ /**
+ * Called just after the panel is shown: used to set focus properly.
+ */
+ public void endDisplay()
+ {
+ }
+
+ /**
+ * Called when a progress change must be reflected in the panels. Only
+ * ProgressPanel overwrites this method and for all the others it stays empty.
+ * @param descriptor the descriptor of the Installation progress.
+ */
+ public void displayProgress(InstallProgressDescriptor descriptor)
+ {
+ }
+
+ /**
+ * Implements HyperlinkListener. When the user clicks on a link we will
+ * try to display the associated URL in the browser of the user.
+ *
+ * @param e the HyperlinkEvent.
+ */
+ public void hyperlinkUpdate(HyperlinkEvent e)
+ {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+ {
+ String url = e.getURL().toString();
+ if (!isURLWorkerRunning(url))
+ {
+ /*
+ * Only launch the worker if there is not already a worker trying to
+ * display this URL.
+ */
+ URLWorker worker = new URLWorker(this, url);
+ startWorker(worker);
+ }
+ }
+ }
+
+ /**
+ * Returns the value corresponding to the provided FieldName.
+ * @param fieldName the FieldName for which we want to obtain the value.
+ * @return the value corresponding to the provided FieldName.
+ */
+ public Object getFieldValue(FieldName fieldName)
+ {
+ return null;
+ }
+
+ /**
+ * Sets the specified value in the field associated with the field name.
+ * @param fieldName the field name associated with the field.
+ * @param value the value that must be set.
+ */
+ public void setFieldValue(FieldName fieldName, Object value)
+ {
+ }
+
+ /**
+ * Marks as invalid (or valid depending on the value of the invalid parameter)
+ * a field corresponding to FieldName. This basically implies udpating the
+ * style of the JLabel associated with fieldName (the association is done
+ * using the LabelFieldDescriptor class).
+ * @param fieldName the FieldName to be marked as valid or invalid.
+ * @param invalid whether to mark the field as valid or invalid.
+ */
+ public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+ {
+ }
+
+ /**
+ * Returns the minimum width of the panel. This is used to calculate the
+ * minimum widht of the dialog.
+ * @return the minimum width of the panel.
+ */
+ public int getMinimumWidth()
+ {
+ // Just take the preferred width of the inputPanel because the
+ // instructionsPanel
+ // are too wide.
+ int width = 0;
+ if (inputPanel != null)
+ {
+ width = (int) inputPanel.getPreferredSize().getWidth();
+ }
+ return width;
+ }
+
+ /**
+ * Returns the minimum height of the panel. This is used to calculate the
+ * minimum height of the dialog.
+ * @return the minimum height of the panel.
+ */
+ public int getMinimumHeight()
+ {
+ int height = (int) getPreferredSize().getHeight();
+
+ return height;
+ }
+
+ /**
+ * Creates the layout of the panel.
+ *
+ */
+ protected void createLayout()
+ {
+ setLayout(new GridBagLayout());
+
+ setOpaque(false);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ Component titlePanel = createTitlePanel();
+ Component instructionsPanel = createInstructionsPanel();
+ inputPanel = createInputPanel();
+
+ boolean somethingAdded = false;
+
+ if (titlePanel != null)
+ {
+ gbc.weightx = 1.0;
+ gbc.weighty = 0.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.insets.left = 0;
+ add(titlePanel, gbc);
+ somethingAdded = true;
+ }
+
+ if (instructionsPanel != null)
+ {
+ if (somethingAdded)
+ {
+ gbc.insets.top = UIFactory.TOP_INSET_INSTRUCTIONS_SUBPANEL;
+ } else
+ {
+ gbc.insets.top = 0;
+ }
+ gbc.insets.left = 0;
+ gbc.weightx = 1.0;
+ gbc.weighty = 0.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ add(instructionsPanel, gbc);
+ somethingAdded = true;
+ }
+
+ if (inputPanel != null)
+ {
+ if (somethingAdded)
+ {
+ gbc.insets.top = UIFactory.TOP_INSET_INPUT_SUBPANEL;
+ } else
+ {
+ gbc.insets.top = 0;
+ }
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.insets.left = 0;
+ add(inputPanel, gbc);
+ somethingAdded = true;
+
+ } else
+ {
+ addVerticalGlue(this);
+ }
+ }
+
+ /**
+ * Commodity method that returns a JTextComponent based on a
+ * LabelFieldDescriptor.
+ * @param desc the LabelFieldDescriptor describing the JTextField.
+ * @param defaultValue the default value used to initialize the
+ * JTextComponent.
+ * @return a JTextComponent based on a
+ * LabelFieldDescriptor.
+ */
+ protected JTextComponent makeJTextComponent(LabelFieldDescriptor desc,
+ String defaultValue)
+ {
+ JTextComponent field;
+ switch (desc.getType())
+ {
+ case TEXTFIELD:
+
+ field =
+ UIFactory.makeJTextField(defaultValue, desc.getTooltip(), desc
+ .getSize(), UIFactory.TextStyle.TEXTFIELD);
+ break;
+
+ case PASSWORD:
+
+ field =
+ UIFactory.makeJPasswordField(defaultValue, desc.getTooltip(), desc
+ .getSize(), UIFactory.TextStyle.PASSWORD_FIELD);
+ break;
+
+ case READ_ONLY:
+
+ field =
+ UIFactory.makeTextPane(defaultValue, UIFactory.TextStyle.READ_ONLY);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown type: " + desc.getType());
+ }
+ return field;
+ }
+
+ /**
+ * Commodity method that returns a JLabel based on a LabelFieldDescriptor.
+ * @param desc the LabelFieldDescriptor describing the JLabel.
+ * @return a JLabel based on a LabelFieldDescriptor.
+ */
+ protected JLabel makeJLabel(LabelFieldDescriptor desc)
+ {
+ UIFactory.TextStyle style;
+ if (desc.getLabelType() == LabelFieldDescriptor.LabelType.PRIMARY)
+ {
+ style = UIFactory.TextStyle.PRIMARY_FIELD_VALID;
+ } else
+ {
+ style = UIFactory.TextStyle.SECONDARY_FIELD_VALID;
+ }
+ return UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, desc.getLabel(),
+ style);
+ }
+
+ /**
+ * Creates and returns the panel that contains the layout specific to the
+ * panel.
+ * @return the panel that contains the layout specific to the
+ * panel.
+ */
+ protected abstract Component createInputPanel();
+
+ /**
+ * Returns the title of this panel.
+ * @return the title of this panel.
+ */
+ protected abstract String getTitle();
+
+ /**
+ * Returns the instruction of this panel.
+ * @return the instruction of this panel.
+ */
+ protected abstract String getInstructions();
+
+ /**
+ * Commodity method that adds a vertical glue at the bottom of a given panel.
+ * @param panel the panel to which we want to add a vertical glue.
+ */
+ protected void addVerticalGlue(JPanel panel)
+ {
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.weighty = 1.0;
+ gbc.fill = GridBagConstraints.VERTICAL;
+ panel.add(Box.createVerticalGlue(), gbc);
+ }
+
+ /**
+ * This method is called by the URLWorker when it has finished its task.
+ * @param worker the URLWorker that finished its task.
+ */
+ public void urlWorkerFinished(URLWorker worker)
+ {
+ hmURLWorkers.remove(worker.getURL());
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if this is a WebStart based installer and
+ * <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if this is a WebStart based installer and
+ * <CODE>false</CODE> otherwise.
+ */
+ protected boolean isWebStart()
+ {
+ return Utils.isWebStart();
+ }
+
+ /**
+ * Creates and returns the title panel.
+ * @return the title panel.
+ */
+ private Component createTitlePanel()
+ {
+ Component titlePanel = null;
+ String title = getTitle();
+ if (title != null)
+ {
+ JPanel p = new JPanel(new GridBagLayout());
+ p.setOpaque(false);
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 0.0;
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+
+ JLabel l =
+ UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title,
+ UIFactory.TextStyle.TITLE);
+ p.add(l, gbc);
+
+ gbc.weightx = 1.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ p.add(Box.createHorizontalGlue(), gbc);
+
+ titlePanel = p;
+ }
+ return titlePanel;
+ }
+
+ /**
+ * Creates and returns the instructions panel.
+ * @return the instructions panel.
+ */
+ private Component createInstructionsPanel()
+ {
+ Component instructionsPanel = null;
+ String instructions = getInstructions();
+ if (instructions != null)
+ {
+
+ JEditorPane p =
+ UIFactory.makeHtmlPane(instructions, UIFactory.INSTRUCTIONS_FONT);
+ p.setOpaque(false);
+ p.setEditable(false);
+ p.addHyperlinkListener(this);
+ instructionsPanel = p;
+ }
+ return instructionsPanel;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if there is URLWorker running for the given url
+ * and <CODE>false</CODE> otherwise.
+ * @param url the url.
+ * @return <CODE>true</CODE> if there is URLWorker running for the given url
+ * and <CODE>false</CODE> otherwise.
+ */
+ private boolean isURLWorkerRunning(String url)
+ {
+ return hmURLWorkers.get(url) != null;
+ }
+
+ /**
+ * Starts a worker.
+ * @param worker the URLWorker to be started.
+ */
+ private void startWorker(URLWorker worker)
+ {
+ hmURLWorkers.put(worker.getURL(), worker);
+ worker.startBackgroundTask();
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java
new file mode 100644
index 0000000..efa0922
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java
@@ -0,0 +1,358 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.HashMap;
+
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.installer.DataOptions;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.LabelFieldDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+
+/**
+ * This is the panel that contains the Review Panel.
+ *
+ */
+class ReviewPanel extends QuickSetupStepPanel
+{
+ private static final long serialVersionUID = -7356174829193265699L;
+
+ private boolean displayServerLocation;
+
+ private UserInstallData defaultUserData;
+
+ private JCheckBox checkBox;
+
+ private HashMap<FieldName, JLabel> hmLabels =
+ new HashMap<FieldName, JLabel>();
+
+ private HashMap<FieldName, JTextComponent> hmFields =
+ new HashMap<FieldName, JTextComponent>();
+
+ /**
+ * Constructor of the panel.
+ * @param defaultUserData the default values that must be used to initialize
+ * the fields of the panel.
+ */
+ public ReviewPanel(UserInstallData defaultUserData)
+ {
+ this.defaultUserData = defaultUserData;
+ this.displayServerLocation = isWebStart();
+ populateLabelAndFieldsMap();
+ createLayout();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void beginDisplay(UserInstallData userData)
+ {
+ if (displayServerLocation)
+ {
+ setFieldValue(FieldName.SERVER_LOCATION, userData.getServerLocation());
+ }
+ setFieldValue(FieldName.SERVER_PORT, String.valueOf(userData
+ .getServerPort()));
+ setFieldValue(FieldName.DIRECTORY_MANAGER_DN, userData
+ .getDirectoryManagerDn());
+ setFieldValue(FieldName.DIRECTORY_BASE_DN, userData.getDataOptions()
+ .getBaseDn());
+ setFieldValue(FieldName.DATA_OPTIONS, getDisplayString(userData
+ .getDataOptions()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getFieldValue(FieldName fieldName)
+ {
+ Object value = null;
+ if (fieldName == FieldName.SERVER_START)
+ {
+ value = new Boolean(getCheckBox().isSelected());
+ }
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Component createInputPanel()
+ {
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setOpaque(false);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ panel.add(createFieldsPanel(), gbc);
+
+ addVerticalGlue(panel);
+
+ gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+ gbc.weighty = 0.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ panel.add(getCheckBox(), gbc);
+
+ return panel;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getInstructions()
+ {
+ return getMsg("review-panel-instructions");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getTitle()
+ {
+ return getMsg("review-panel-title");
+ }
+
+ /**
+ * Create the components and populate the Maps.
+ */
+ private void populateLabelAndFieldsMap()
+ {
+ HashMap<FieldName, LabelFieldDescriptor> hm =
+ new HashMap<FieldName, LabelFieldDescriptor>();
+
+ if (displayServerLocation)
+ {
+ hm.put(FieldName.SERVER_LOCATION, new LabelFieldDescriptor(
+ getMsg("server-location-label"), getMsg("server-port-tooltip"),
+ LabelFieldDescriptor.FieldType.READ_ONLY,
+ LabelFieldDescriptor.LabelType.PRIMARY, 0));
+ }
+
+ hm.put(FieldName.SERVER_PORT, new LabelFieldDescriptor(
+ getMsg("server-port-label"), getMsg("server-port-tooltip"),
+ LabelFieldDescriptor.FieldType.READ_ONLY,
+ LabelFieldDescriptor.LabelType.PRIMARY, 0));
+
+ hm.put(FieldName.DIRECTORY_MANAGER_DN, new LabelFieldDescriptor(
+ getMsg("server-directory-manager-dn-label"),
+ getMsg("server-directory-manager-dn-tooltip"),
+ LabelFieldDescriptor.FieldType.READ_ONLY,
+ LabelFieldDescriptor.LabelType.PRIMARY, 0));
+
+ hm.put(FieldName.DIRECTORY_BASE_DN, new LabelFieldDescriptor(
+ getMsg("base-dn-label"), getMsg("base-dn-tooltip"),
+ LabelFieldDescriptor.FieldType.READ_ONLY,
+ LabelFieldDescriptor.LabelType.PRIMARY, 0));
+
+ hm.put(FieldName.DATA_OPTIONS, new LabelFieldDescriptor(
+ getMsg("directory-data-label"), null,
+ LabelFieldDescriptor.FieldType.READ_ONLY,
+ LabelFieldDescriptor.LabelType.PRIMARY, 0));
+ for (FieldName fieldName : hm.keySet())
+ {
+ LabelFieldDescriptor desc = hm.get(fieldName);
+
+ JTextComponent field = makeJTextComponent(desc, null);
+ field.setOpaque(false);
+ JLabel label = makeJLabel(desc);
+
+ hmFields.put(fieldName, field);
+ label.setLabelFor(field);
+
+ hmLabels.put(fieldName, label);
+ }
+ }
+
+ /**
+ * Returns the label associated with the given field name.
+ * @param fieldName the field name for which we want to retrieve the JLabel.
+ * @return the label associated with the given field name.
+ */
+ private JLabel getLabel(FieldName fieldName)
+ {
+ return hmLabels.get(fieldName);
+ }
+
+ /**
+ * Returns the JTextComponent associated with the given field name.
+ * @param fieldName the field name for which we want to retrieve the
+ * JTextComponent.
+ * @return the JTextComponent associated with the given field name.
+ */
+ private JTextComponent getField(FieldName fieldName)
+ {
+ return hmFields.get(fieldName);
+ }
+
+ /**
+ * Updates the JTextComponent associated with a FieldName with a text value.
+ * @param fieldName the field name of the JTextComponent that we want to
+ * update.
+ * @param value the value to be set.
+ */
+ private void setFieldValue(FieldName fieldName, String value)
+ {
+ getField(fieldName).setText(value);
+ }
+
+ /**
+ * Returns the localized string describing the DataOptions chosen by the user.
+ * @param options the DataOptions of the user.
+ * @return the localized string describing the DataOptions chosen by the user.
+ */
+ private String getDisplayString(DataOptions options)
+ {
+ String msg;
+
+ switch (options.getType())
+ {
+ case CREATE_BASE_ENTRY:
+ msg = getMsg("review-create-base-entry-label", new String[]
+ { options.getBaseDn() });
+
+ break;
+
+ case LEAVE_DATABASE_EMPTY:
+ msg = getMsg("review-leave-database-empty-label");
+ break;
+
+ case IMPORT_FROM_LDIF_FILE:
+ msg = getMsg("review-import-ldif", new String[]
+ { options.getLDIFPath() });
+ break;
+
+ case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+ msg = getMsg("review-import-automatically-generated", new String[]
+ { String.valueOf(options.getNumberEntries()) });
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknow type: " + options.getType());
+
+ }
+
+ return msg;
+ }
+
+ /**
+ * Returns the start server check box.
+ * If it does not exist creates the start server check box.
+ * @return the start server check box.
+ */
+ private JCheckBox getCheckBox()
+ {
+ if (checkBox == null)
+ {
+ checkBox =
+ UIFactory.makeJCheckBox(getMsg("start-server-label"),
+ getMsg("start-server-tooltip"), UIFactory.TextStyle.CHECKBOX);
+ checkBox.setOpaque(false);
+ checkBox.setSelected(defaultUserData.getStartServer());
+ }
+ return checkBox;
+ }
+
+ /**
+ * Returns and creates the fields panel.
+ * @return the fields panel.
+ */
+ private JPanel createFieldsPanel()
+ {
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setOpaque(false);
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ FieldName[] fieldNames;
+ if (displayServerLocation)
+ {
+ fieldNames =
+ new FieldName[]
+ { FieldName.SERVER_LOCATION, FieldName.SERVER_PORT,
+ FieldName.DIRECTORY_MANAGER_DN,
+ FieldName.DIRECTORY_BASE_DN,
+ FieldName.DATA_OPTIONS };
+ } else
+ {
+ fieldNames =
+ new FieldName[]
+ { FieldName.SERVER_PORT, FieldName.DIRECTORY_MANAGER_DN,
+ FieldName.DIRECTORY_BASE_DN, FieldName.DATA_OPTIONS };
+ }
+
+ for (int i = 0; i < fieldNames.length; i++)
+ {
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ if (i > 0)
+ {
+ gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+ } else
+ {
+ gbc.insets.top = 0;
+ }
+ gbc.insets.left = 0;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ panel.add(getLabel(fieldNames[i]), gbc);
+
+ JPanel auxPanel = new JPanel(new GridBagLayout());
+ auxPanel.setOpaque(false);
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ if (i > 0)
+ {
+ gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+ } else
+ {
+ gbc.insets.top = 0;
+ }
+ gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ panel.add(auxPanel, gbc);
+
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ auxPanel.add(getField(fieldNames[i]), gbc);
+ }
+
+ return panel;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java
new file mode 100644
index 0000000..10d71f9
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/ServerSettingsPanel.java
@@ -0,0 +1,498 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.io.File;
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.event.BrowseActionListener;
+import org.opends.quicksetup.installer.FieldName;
+import org.opends.quicksetup.installer.LabelFieldDescriptor;
+import org.opends.quicksetup.installer.UserInstallData;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This is the panel that contains the Server Settings: the port, the Directory
+ * Manager DN, etc.
+ *
+ */
+class ServerSettingsPanel extends QuickSetupStepPanel
+{
+ private UserInstallData defaultUserData;
+
+ private Component lastFocusComponent;
+
+ private JButton browseButton;
+
+ private boolean displayServerLocation;
+
+ private HashMap<FieldName, JLabel> hmLabels =
+ new HashMap<FieldName, JLabel>();
+
+ private HashMap<FieldName, JTextComponent> hmFields =
+ new HashMap<FieldName, JTextComponent>();
+
+ private JTextComponent tfServerLocationParent;
+
+ private JTextComponent tfServerLocationRelativePath;
+
+ private JLabel lServerLocation;
+
+ private static final long serialVersionUID = -15911406930993035L;
+
+ /**
+ * Constructor of the panel.
+ * @param defaultUserData the default values that must be used to initialize
+ * the fields of the panel.
+ */
+ public ServerSettingsPanel(UserInstallData defaultUserData)
+ {
+ this.defaultUserData = defaultUserData;
+ this.displayServerLocation = isWebStart();
+ populateLabelAndFieldMaps();
+ createLayout();
+ addFocusListeners();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getFieldValue(FieldName fieldName)
+ {
+ Object value = null;
+
+ if (fieldName == FieldName.SERVER_LOCATION)
+ {
+ String parent = tfServerLocationParent.getText();
+ String relative = tfServerLocationRelativePath.getText();
+ if ((parent != null) && (parent.length() > 0))
+ {
+ value = parent;
+ }
+ if ((relative != null) && (relative.length() > 0))
+ {
+ if (value == null)
+ {
+ value = File.separator + relative;
+ } else
+ {
+ value = value + File.separator + relative;
+ }
+ }
+
+ } else
+ {
+ JTextComponent field = getField(fieldName);
+ if (field != null)
+ {
+ value = field.getText();
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+ {
+ JLabel label = getLabel(fieldName);
+ if (label != null)
+ {
+ if (invalid)
+ {
+ UIFactory.setTextStyle(label,
+ UIFactory.TextStyle.PRIMARY_FIELD_INVALID);
+ } else
+ {
+ UIFactory
+ .setTextStyle(label, UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Component createInputPanel()
+ {
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setOpaque(false);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ FieldName[] fieldNames =
+ { FieldName.SERVER_PORT, FieldName.DIRECTORY_MANAGER_DN,
+ FieldName.DIRECTORY_MANAGER_PWD,
+ FieldName.DIRECTORY_MANAGER_PWD_CONFIRM };
+
+ JPanel auxPanel;
+ // Add the server location widgets
+ if (displayServerLocation)
+ {
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ gbc.insets.top = 0;
+ gbc.insets.left = 0;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ panel.add(lServerLocation, gbc);
+
+ gbc.anchor = GridBagConstraints.WEST;
+ auxPanel = new JPanel(new GridBagLayout());
+ auxPanel.setOpaque(false);
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets.top = 0;
+ gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ panel.add(auxPanel, gbc);
+
+ gbc.gridwidth = 3;
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.weightx = 0.7;
+ auxPanel.add(tfServerLocationParent, gbc);
+
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+ auxPanel.add(UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+ File.separator, UIFactory.TextStyle.TEXTFIELD), gbc);
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 0.3;
+ auxPanel.add(tfServerLocationRelativePath, gbc);
+
+ gbc.gridwidth = 3;
+ gbc.anchor = GridBagConstraints.NORTHEAST;
+ gbc.insets.top = UIFactory.TOP_INSET_BROWSE;
+ gbc.weightx = 0.0;
+ gbc.fill = GridBagConstraints.NONE;
+ auxPanel.add(getBrowseButton(), gbc);
+ }
+
+ // Add the other widgets
+ for (int i = 0; i < fieldNames.length; i++)
+ {
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.weightx = 0.0;
+ gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+ gbc.insets.left = 0;
+ gbc.anchor = GridBagConstraints.WEST;
+ panel.add(getLabel(fieldNames[i]), gbc);
+
+ auxPanel = new JPanel(new GridBagLayout());
+ auxPanel.setOpaque(false);
+ gbc.weightx = 1.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+ gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ panel.add(auxPanel, gbc);
+
+ boolean isPortField = fieldNames[i] == FieldName.SERVER_PORT;
+ gbc.insets = UIFactory.getEmptyInsets();
+ if (isPortField)
+ {
+ gbc.gridwidth = 3;
+ } else
+ {
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ }
+ gbc.weightx = 0.0;
+ auxPanel.add(getField(fieldNames[i]), gbc);
+ if (isPortField)
+ {
+ JLabel l =
+ UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+ getPortHelpMessage(),
+ UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+ auxPanel.add(l, gbc);
+ }
+
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ auxPanel.add(Box.createHorizontalGlue(), gbc);
+ }
+ addVerticalGlue(panel);
+ return panel;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getInstructions()
+ {
+ return getMsg("server-settings-panel-instructions");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getTitle()
+ {
+ return getMsg("server-settings-panel-title");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endDisplay()
+ {
+ if (lastFocusComponent != null)
+ {
+ lastFocusComponent.requestFocusInWindow();
+ }
+ }
+
+ /**
+ * Returns the default value for the provided field Name.
+ * @param fieldName the field name for which we want to get the default
+ * value.
+ * @return the default value for the provided field Name.
+ */
+ private String getDefaultValue(FieldName fieldName)
+ {
+ String value = null;
+ switch (fieldName)
+ {
+ case SERVER_LOCATION:
+ value = defaultUserData.getServerLocation();
+ break;
+
+ case SERVER_PORT:
+ if (defaultUserData.getServerPort() > 0)
+ {
+ value = String.valueOf(defaultUserData.getServerPort());
+ } else
+ {
+ value = "";
+ }
+ break;
+
+ case DIRECTORY_MANAGER_DN:
+ value = defaultUserData.getDirectoryManagerDn();
+ break;
+
+ case DIRECTORY_MANAGER_PWD:
+ value = defaultUserData.getDirectoryManagerPwd();
+ break;
+
+ case DIRECTORY_MANAGER_PWD_CONFIRM:
+ value = defaultUserData.getDirectoryManagerPwd();
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown field name: " +
+ fieldName);
+ }
+
+ return value;
+ }
+
+ /**
+ * Creates the components and populates the Maps with them.
+ */
+ private void populateLabelAndFieldMaps()
+ {
+ HashMap<FieldName, LabelFieldDescriptor> hm =
+ new HashMap<FieldName, LabelFieldDescriptor>();
+
+ hm.put(FieldName.SERVER_PORT, new LabelFieldDescriptor(
+ getMsg("server-port-label"), getMsg("server-port-tooltip"),
+ LabelFieldDescriptor.FieldType.TEXTFIELD,
+ LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PORT_FIELD_SIZE));
+
+ hm.put(FieldName.DIRECTORY_MANAGER_DN, new LabelFieldDescriptor(
+ getMsg("server-directory-manager-dn-label"),
+ getMsg("server-directory-manager-dn-tooltip"),
+ LabelFieldDescriptor.FieldType.TEXTFIELD,
+ LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.DN_FIELD_SIZE));
+
+ hm.put(FieldName.DIRECTORY_MANAGER_PWD, new LabelFieldDescriptor(
+ getMsg("server-directory-manager-pwd-label"),
+ getMsg("server-directory-manager-pwd-tooltip"),
+ LabelFieldDescriptor.FieldType.PASSWORD,
+ LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PASSWORD_FIELD_SIZE));
+
+ hm.put(FieldName.DIRECTORY_MANAGER_PWD_CONFIRM,
+ new LabelFieldDescriptor(
+ getMsg("server-directory-manager-pwd-confirm-label"),
+ getMsg("server-directory-manager-pwd-confirm-tooltip"),
+ LabelFieldDescriptor.FieldType.PASSWORD,
+ LabelFieldDescriptor.LabelType.PRIMARY,
+ UIFactory.PASSWORD_FIELD_SIZE));
+
+ for (FieldName fieldName : hm.keySet())
+ {
+ LabelFieldDescriptor desc = hm.get(fieldName);
+ String defaultValue = getDefaultValue(fieldName);
+ JTextComponent field = makeJTextComponent(desc, defaultValue);
+ JLabel label = makeJLabel(desc);
+
+ hmFields.put(fieldName, field);
+ label.setLabelFor(field);
+
+ hmLabels.put(fieldName, label);
+ }
+
+ /* Create the elements for the location */
+ LabelFieldDescriptor desc =
+ new LabelFieldDescriptor(getMsg("server-location-label"),
+ getMsg("server-location-parent-tooltip"),
+ LabelFieldDescriptor.FieldType.TEXTFIELD,
+ LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PATH_FIELD_SIZE);
+ lServerLocation = makeJLabel(desc);
+ tfServerLocationParent = makeJTextComponent(desc, "");
+ lServerLocation.setLabelFor(tfServerLocationParent);
+
+ desc =
+ new LabelFieldDescriptor(getMsg("server-location-label"),
+ getMsg("server-location-relative-tooltip"),
+ LabelFieldDescriptor.FieldType.TEXTFIELD,
+ LabelFieldDescriptor.LabelType.PRIMARY,
+ UIFactory.RELATIVE_PATH_FIELD_SIZE);
+ tfServerLocationRelativePath = makeJTextComponent(desc, "");
+ String defaultPath = getDefaultValue(FieldName.SERVER_LOCATION);
+ if (defaultPath != null)
+ {
+ int index = defaultPath.lastIndexOf(File.separator);
+ if (index != -1)
+ {
+ String parent = defaultPath.substring(0, index);
+ String relativeDir = defaultPath.substring(index + 1);
+
+ tfServerLocationParent.setText(parent);
+ tfServerLocationRelativePath.setText(relativeDir);
+ }
+ }
+ }
+
+ /**
+ * Returns the browse button.
+ * If it does not exist creates the browse button.
+ * @return the browse button.
+ */
+ private JButton getBrowseButton()
+ {
+ if (browseButton == null)
+ {
+ browseButton =
+ UIFactory.makeJButton(getMsg("browse-button-label"),
+ getMsg("browse-button-tooltip"));
+
+ BrowseActionListener l =
+ new BrowseActionListener(tfServerLocationParent,
+ BrowseActionListener.BrowseType.LOCATION_DIRECTORY,
+ getMainWindow());
+ browseButton.addActionListener(l);
+ }
+ return browseButton;
+ }
+
+ /**
+ * Returns the label associated with the given field name.
+ * @param fieldName the field name for which we want to retrieve the JLabel.
+ * @return the label associated with the given field name.
+ */
+ private JLabel getLabel(FieldName fieldName)
+ {
+ return hmLabels.get(fieldName);
+ }
+
+ /**
+ * Returns the JTextComponent associated with the given field name.
+ * @param fieldName the field name for which we want to retrieve the
+ * JTextComponent.
+ * @return the JTextComponent associated with the given field name.
+ */
+ private JTextComponent getField(FieldName fieldName)
+ {
+ return hmFields.get(fieldName);
+ }
+
+ /**
+ * Adds the required focus listeners to the fields.
+ */
+ private void addFocusListeners()
+ {
+ final FocusListener l = new FocusListener()
+ {
+ public void focusGained(FocusEvent e)
+ {
+ lastFocusComponent = e.getComponent();
+ }
+
+ public void focusLost(FocusEvent e)
+ {
+ }
+ };
+
+ for (JTextComponent tf : hmFields.values())
+ {
+ tf.addFocusListener(l);
+ }
+ getBrowseButton().addFocusListener(l);
+ lastFocusComponent = getField(FieldName.SERVER_LOCATION);
+ }
+
+ /**
+ * Returns the port help message that we display when we cannot use the
+ * default port (389).
+ * @return the port help message that we display when we cannot use the
+ * default port (389).
+ */
+ private String getPortHelpMessage()
+ {
+ String s = "";
+ if (defaultUserData.getServerPort() <= 0)
+ {
+ if (Utils.isUnix())
+ {
+ s = getMsg("cannot-find-default-port-unix");
+ } else
+ {
+ s = getMsg("cannot-find-default-port-windows");
+ }
+ }
+ return s;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/StepsPanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/StepsPanel.java
new file mode 100644
index 0000000..2a1475b
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/StepsPanel.java
@@ -0,0 +1,213 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.opends.quicksetup.Step;
+
+/**
+ * This class displays the different steps of the wizard. It appears on the
+ * left of the dialog.
+ *
+ * The current step is highlighted using a different label style and an icon.
+ * The current displayed step can be changed calling the method setCurrentStep.
+ *
+ */
+class StepsPanel extends QuickSetupPanel
+{
+ private static final long serialVersionUID = -2003945907121690657L;
+
+ HashMap<Step, JLabel> hmLabels = new HashMap<Step, JLabel>();
+
+ HashMap<Step, JLabel> hmIcons = new HashMap<Step, JLabel>();
+
+ /**
+ * Creates a StepsPanel.
+ * @param isUninstall tells whether we are installing or uninstalling.
+ */
+ public StepsPanel(boolean isUninstall)
+ {
+ createLayout(isUninstall);
+ }
+
+ /**
+ * Updates the layout of the panel so that it corresponds to the Step passed
+ * as parameter.
+ *
+ * @param step the step in the wizard.
+ */
+ public void setDisplayedStep(Step step)
+ {
+ for (Step s : Step.values())
+ {
+ if (s == step)
+ {
+ getIcon(s).setVisible(true);
+ UIFactory.setTextStyle(getLabel(s), UIFactory.TextStyle.CURRENT_STEP);
+ } else
+ {
+ if (getIcon(s) != null)
+ {
+ getIcon(s).setVisible(false);
+ }
+ if (getLabel(s) != null)
+ {
+ UIFactory.setTextStyle(getLabel(s),
+ UIFactory.TextStyle.NOT_CURRENT_STEP);
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates the layout of the panel.
+ * @param isUninstall tells whether we are installing or uninstalling.
+ */
+ private void createLayout(boolean isUninstall)
+ {
+ setLayout(new GridBagLayout());
+
+ JPanel mainPanel = new JPanel(new GridBagLayout());
+ mainPanel.setOpaque(false);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.weightx = 0.0;
+ gbc.weighty = 0.0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.anchor = GridBagConstraints.WEST;
+
+ HashMap<Step, String> hmText = new HashMap<Step, String>();
+ ArrayList<Step> orderedSteps = new ArrayList<Step>();
+ if (isUninstall)
+ {
+ hmText.put(Step.CONFIRM_UNINSTALL, getMsg("confirm-uninstall-step"));
+ hmText.put(Step.PROGRESS, getMsg("progress-step"));
+ orderedSteps.add(Step.CONFIRM_UNINSTALL);
+ orderedSteps.add(Step.PROGRESS);
+ } else
+ {
+ hmText.put(Step.WELCOME, getMsg("welcome-step"));
+ hmText.put(Step.SERVER_SETTINGS, getMsg("server-settings-step"));
+ hmText.put(Step.DATA_OPTIONS, getMsg("data-options-step"));
+ hmText.put(Step.REVIEW, getMsg("review-step"));
+ hmText.put(Step.PROGRESS, getMsg("progress-step"));
+ orderedSteps.add(Step.WELCOME);
+ orderedSteps.add(Step.SERVER_SETTINGS);
+ orderedSteps.add(Step.DATA_OPTIONS);
+ orderedSteps.add(Step.REVIEW);
+ orderedSteps.add(Step.PROGRESS);
+ }
+ for (Step s : orderedSteps)
+ {
+ if (s != orderedSteps.get(0))
+ {
+ gbc.insets.top = UIFactory.TOP_INSET_STEP;
+ }
+
+ GridBagConstraints gbcAux = new GridBagConstraints();
+ gbcAux.gridwidth = GridBagConstraints.REMAINDER;
+ gbcAux.fill = GridBagConstraints.HORIZONTAL;
+ JPanel auxPanel = new JPanel(new GridBagLayout());
+ auxPanel.setOpaque(false);
+ JLabel iconLabel =
+ UIFactory.makeJLabel(UIFactory.IconType.CURRENT_STEP, null,
+ UIFactory.TextStyle.NO_STYLE);
+ auxPanel.add(iconLabel, gbcAux);
+ int width = (int) iconLabel.getPreferredSize().getWidth();
+ auxPanel.add(Box.createHorizontalStrut(width), gbcAux);
+
+ hmIcons.put(s, iconLabel);
+
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ mainPanel.add(auxPanel, gbc);
+
+ JLabel stepLabel =
+ UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, hmText.get(s),
+ UIFactory.TextStyle.CURRENT_STEP);
+ hmLabels.put(s, stepLabel);
+ gbc.insets.left = UIFactory.LEFT_INSET_STEP;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ mainPanel.add(stepLabel, gbc);
+
+ stepLabel.setLabelFor(this);
+ iconLabel.setLabelFor(stepLabel);
+ }
+
+ gbc.insets.left = 0;
+ gbc.insets.top = 0;
+ gbc.weightx = 1.0;
+ gbc.weighty = 0.0;
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ add(mainPanel, gbc);
+ int mainWidth = (int) mainPanel.getPreferredSize().getWidth();
+
+ // We are creating all the labels with the style
+ // UIFactory.LabelStyle.CURRENT_STEP which is the one
+ // that takes more space. But once we display the dialog only one
+ // of the labels will have that style and the other will have
+ // UIFactory.LabelStyle.NOT_CURRENT_STEP. Adding the strut guarantees
+ // that the width of the panel will always be enough to display the
+ // longest label using UIFactory.LabelStyle.CURRENT_STEP.
+ add(Box.createHorizontalStrut(mainWidth), gbc);
+
+ gbc.fill = GridBagConstraints.VERTICAL;
+ gbc.weighty = 1.0;
+ add(Box.createVerticalGlue(), gbc);
+ }
+
+ /**
+ * Returns the label associated with the given step.
+ * @param step the step for which we want to retrieve the JLabel.
+ * @return the label associated with the given step.
+ */
+ private JLabel getLabel(Step step)
+ {
+ return hmLabels.get(step);
+ }
+
+ /**
+ * Returns the icon associated with the given step.
+ * @param step the step for which we want to retrieve the Icon.
+ * @return the icon associated with the given step.
+ */
+ private JLabel getIcon(Step step)
+ {
+ return hmIcons.get(step);
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java b/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
new file mode 100644
index 0000000..0191168
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
@@ -0,0 +1,1356 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.util.HashMap;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPasswordField;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+
+/**
+ * This class provides constants an methods to create Swing objects and to
+ * generate UI elements with a common look and feel.
+ *
+ * When we want to change a color, a background or a font this is the class
+ * that should be modified.
+ *
+ */
+public class UIFactory
+{
+ private static boolean initialized = false;
+
+ private static String parentPackagePath;
+
+ /**
+ * Specifies the horizontal insets between buttons.
+ */
+ public static final int HORIZONTAL_INSET_BETWEEN_BUTTONS = 5;
+
+ /**
+ * Specifies the top inset for the steps.
+ */
+ public static final int TOP_INSET_STEP = 15;
+
+ /**
+ * Specifies the left inset for the steps.
+ */
+ public static final int LEFT_INSET_STEP = 5;
+
+ /**
+ * Specifies the top inset for the instructions sub panel.
+ */
+ public static final int TOP_INSET_INSTRUCTIONS_SUBPANEL = 10;
+
+ /**
+ * Specifies the top inset for input subpanel.
+ */
+ public static final int TOP_INSET_INPUT_SUBPANEL = 10;
+
+ /**
+ * Specifies the top inset for a primary field.
+ */
+ public static final int TOP_INSET_PRIMARY_FIELD = 10;
+
+ /**
+ * Specifies the top inset for a secondary field.
+ */
+ public static final int TOP_INSET_SECONDARY_FIELD = 5;
+
+ /**
+ * Specifies the top inset for a radio button.
+ */
+ public static final int TOP_INSET_RADIOBUTTON = 0;
+
+ /**
+ * Specifies the top inset for a radio button subordinate panel.
+ */
+ public static final int TOP_INSET_RADIO_SUBORDINATE = 0;
+
+ /**
+ * Specifies the top inset for the progress bar.
+ */
+ public static final int TOP_INSET_PROGRESS_BAR = 5;
+
+ /**
+ * Specifies the top inset for the progress text area.
+ */
+ public static final int TOP_INSET_PROGRESS_TEXTAREA = 4;
+
+ /**
+ * Specifies the top inset for the background image.
+ */
+ public static final int TOP_INSET_BACKGROUND = 70;
+
+ /**
+ * Specifies the top inset for the error message.
+ */
+ public static final int TOP_INSET_ERROR_MESSAGE = 10;
+
+ /**
+ * Specifies the top inset for the browse button.
+ */
+ public static final int TOP_INSET_BROWSE = 5;
+
+ /**
+ * Specifies the right inset for background image.
+ */
+ public static final int RIGHT_INSET_BACKGROUND = 20;
+
+ /**
+ * Specifies the left inset for the primary field.
+ */
+ public static final int LEFT_INSET_PRIMARY_FIELD = 10;
+
+ /**
+ * Specifies the left inset for the browse button.
+ */
+ public static final int LEFT_INSET_BROWSE = 10;
+
+ /**
+ * Specifies the left inset for radio subordinate panel.
+ */
+ public static final int LEFT_INSET_RADIO_SUBORDINATE = 20;
+
+ /**
+ * Specifies the left inset for the secondary field.
+ */
+ public static final int LEFT_INSET_SECONDARY_FIELD = 5;
+
+ /**
+ * Specifies the left inset for the background image.
+ */
+ public static final int LEFT_INSET_BACKGROUND = 20;
+
+ /**
+ * Specifies the left inset for the copy url button.
+ */
+ public static final int LEFT_INSET_COPY_BUTTON = 10;
+
+ /**
+ * Specifies the left inset for the progress bar.
+ */
+ public static final int BOTTOM_INSET_PROGRESS_BAR = 10;
+
+ /**
+ * Specifies the bottom inset for the background image.
+ */
+ public static final int BOTTOM_INSET_BACKGROUND = 30;
+
+ /**
+ * Specifies the number of columns of a text field for a path.
+ */
+ public static final int PATH_FIELD_SIZE = 20;
+
+ /**
+ * Specifies the number of columns of a text field for a relative path.
+ */
+ public static final int RELATIVE_PATH_FIELD_SIZE = 5;
+
+ /**
+ * Specifies the number of columns of a text field for a port.
+ */
+ public static final int PORT_FIELD_SIZE = 5;
+
+ /**
+ * Specifies the number of columns of a text field for a dn.
+ */
+ public static final int DN_FIELD_SIZE = 20;
+
+ /**
+ * Specifies the number of columns of a text field for a password.
+ */
+ public static final int PASSWORD_FIELD_SIZE = 15;
+
+ /**
+ * Specifies the number of columns of a text field for the number of entries.
+ */
+ public static final int NUMBER_ENTRIES_FIELD_SIZE = 7;
+
+ /**
+ * Specifies the number of points for the width of the progress bar.
+ */
+ public static final int PROGRESS_BAR_SIZE = 220;
+
+ /**
+ * Specifies the number of extra points that we add to the minimum size of
+ * the dialog.
+ */
+ public static final int EXTRA_DIALOG_HEIGHT = 75;
+
+ private static final Insets BUTTONS_PANEL_INSETS = new Insets(5, 0, 5, 10);
+
+ private static final Insets STEPS_PANEL_INSETS = new Insets(15, 10, 5, 10);
+
+ private static final Insets CURRENT_STEP_PANEL_INSETS =
+ new Insets(15, 15, 15, 15);
+
+ private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
+
+ /**
+ * Specifies the default background color.
+ */
+ public static final Color DEFAULT_BACKGROUND = new Color(236, 236, 236);
+
+ /**
+ * Specifies the current step background color.
+ */
+ public static final Color CURRENT_STEP_PANEL_BACKGROUND =
+ Color.WHITE;
+
+ /**
+ * Specifies the default label color.
+ */
+ public static final Color DEFAULT_LABEL_COLOR = Color.BLACK;
+
+ /**
+ * Specifies the valid field color.
+ */
+ public static final Color FIELD_VALID_COLOR = Color.BLACK;
+
+ /**
+ * Specifies the invalid field color.
+ */
+ public static final Color FIELD_INVALID_COLOR = Color.RED;
+
+ /**
+ * Specifies the read only text color.
+ */
+ public static final Color READ_ONLY_COLOR = Color.BLACK;
+
+ /**
+ * Specifies the check box text color.
+ */
+ public static final Color CHECKBOX_COLOR = Color.BLACK;
+
+ /**
+ * Specifies the progress text color.
+ */
+ public static final Color PROGRESS_COLOR = Color.BLACK;
+
+ /**
+ * Specifies the text field text color.
+ */
+ public static final Color TEXTFIELD_COLOR = Color.BLACK;
+
+ /**
+ * Specifies the password field text color.
+ */
+ public static final Color PASSWORD_FIELD_COLOR = Color.BLACK;
+
+ /**
+ * Specifies the current step panel border.
+ */
+ public static final Border CURRENT_STEP_PANEL_BORDER =
+ BorderFactory.createMatteBorder(0, 2, 2, 0, new Color(204, 204, 204));
+
+ /**
+ * Specifies the text area border.
+ */
+ public static final Border TEXT_AREA_BORDER =
+ BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK);
+
+ /**
+ * Specifies the dialog border.
+ */
+ public static final Border DIALOG_PANEL_BORDER =
+ BorderFactory.createMatteBorder(0, 0, 2, 0, new Color(204, 204, 204));
+
+ /**
+ * Specifies the font for the step which is not the current one in the steps
+ * panel.
+ */
+ public static final Font NOT_CURRENT_STEP_FONT =
+ Font.decode("Arial-PLAIN-14");
+
+ /**
+ * Specifies the font for the step which is the current one in the steps
+ * panel.
+ */
+ public static final Font CURRENT_STEP_FONT =
+ Font.decode("Arial-BOLD-14");
+
+ /**
+ * Specifies the font for the title of the current panel.
+ */
+ public static final Font TITLE_FONT =
+ Font.decode("Arial-BOLD-14");
+
+ /**
+ * Specifies the font for the instructions of the current panel.
+ */
+ public static final Font INSTRUCTIONS_FONT =
+ Font.decode("Arial-PLAIN-14");
+
+ /**
+ * Specifies the font for the primary valid field.
+ */
+ public static final Font PRIMARY_FIELD_VALID_FONT =
+ Font.decode("Arial-BOLD-12");
+
+ /**
+ * Specifies the font for the secondary valid field.
+ */
+ public static final Font SECONDARY_FIELD_VALID_FONT =
+ Font.decode("Arial-PLAIN-12");
+
+ /**
+ * Specifies the font for the primary invalid field.
+ */
+ public static final Font PRIMARY_FIELD_INVALID_FONT =
+ Font.decode("Arial-BOLDITALIC-12");
+
+ /**
+ * Specifies the font for the secondary invalid field.
+ */
+ public static final Font SECONDARY_FIELD_INVALID_FONT =
+ Font.decode("Arial-ITALIC-12");
+
+ /**
+ * Specifies the font for read only text.
+ */
+ public static final Font READ_ONLY_FONT = Font.decode("Arial-PLAIN-12");
+
+ /**
+ * Specifies the font for the check box text.
+ */
+ public static final Font CHECKBOX_FONT = Font.decode("Arial-PLAIN-12");
+
+ /**
+ * Specifies the font for the progress text.
+ */
+ public static final Font PROGRESS_FONT = Font.decode("Arial-PLAIN-12");
+
+ /**
+ * Specifies the font for the text field text.
+ */
+ public static final Font TEXTFIELD_FONT = Font.decode("Arial-PLAIN-12");
+
+ /**
+ * Specifies the font for the password field text.
+ */
+ public static final Font PASSWORD_FIELD_FONT =
+ Font.decode("Arial-PLAIN-12");
+
+ /**
+ * Specifies the font for the points '....' in the progress panel.
+ */
+ public static final Font PROGRESS_POINTS_FONT =
+ Font.decode("Arial-BOLD-12");
+
+ /**
+ * Specifies the font for the done text 'Done' in the progress panel.
+ */
+ public static final Font PROGRESS_DONE_FONT = PROGRESS_POINTS_FONT;
+
+ /**
+ * Specifies the font for the log messages in the progress panel.
+ */
+ public static final Font PROGRESS_LOG_FONT =
+ Font.decode("Monospaced-PLAIN-12");
+
+ /**
+ * Specifies the font for the error log messages in the progress panel.
+ */
+ public static final Font PROGRESS_LOG_ERROR_FONT =
+ Font.decode("Monospaced-PLAIN-12");
+
+ /**
+ * Specifies the font for the error messages in the progress panel.
+ */
+ public static final Font PROGRESS_ERROR_FONT =
+ Font.decode("Arial-BOLD-12");
+
+ /**
+ * Specifies the font for the warning messages in the progress panel.
+ */
+ public static final Font PROGRESS_WARNING_FONT =
+ Font.decode("Arial-BOLD-12");
+
+ /**
+ * Specifies the font for the stack trace in the progress panel.
+ */
+ public static final Font STACK_FONT = Font.decode("Arial-PLAIN-12");
+
+ /**
+ * Specifies the font for the text in the WebBrowserErrorDialog.
+ */
+ public static final Font BROWSER_ERROR_DIALOG_FONT =
+ Font.decode("Arial-PLAIN-12");
+
+ private static final String SPAN_CLOSE = "</span>";
+
+ private static final String DIV_CLOSE = "</div>";
+
+ private static final String DIV_OPEN_ERROR_BACKGROUND =
+ "<div style=\"color:#000;background-color:#FFFFCC;"
+ + "padding:10px 10px 10px 10px;"
+ + "border-style:solid;border-width:3px;border-color:#E1E1A7;"
+ + "vertical-align:middle;text-align:left\">";
+
+ private static final String DIV_OPEN_WARNING_BACKGROUND =
+ DIV_OPEN_ERROR_BACKGROUND;
+
+ private static final String DIV_OPEN_SUCCESSFUL_BACKGROUND =
+ "<div style=\"color:#000;background-color:#FFFFCC;"
+ + "padding:10px 10px 10px 10px;"
+ + "border-style:solid;border-width:3px;border-color:#E1E1A7;"
+ + "vertical-align:middle;text-align:left\">";
+
+ /**
+ * An HTML separator text that can be used in the progress panel.
+ */
+ public static final String HTML_SEPARATOR =
+ "<div style=\"font-size:1px;background-color:#666666;"
+ + "margin:10px 5px 10px 5px;\"></div>";
+
+ private static final HashMap<IconType, ImageIcon> hmIcons =
+ new HashMap<IconType, ImageIcon>();
+
+ /**
+ * The following enumeration contains the different icons that we can have.
+ *
+ */
+ public enum IconType
+ {
+ /**
+ * Splash Icon.
+ */
+ SPLASH,
+ /**
+ * Current Step Icon.
+ */
+ CURRENT_STEP,
+ /**
+ * The icon displayed by the OS when the dialog is minimized.
+ */
+ MINIMIZED,
+ /**
+ * The icon displayed by the Mac OS when the dialog is minimized.
+ */
+ MINIMIZED_MAC,
+ /**
+ * The background icon.
+ */
+ BACKGROUND,
+ /**
+ * The warning icon.
+ */
+ WARNING,
+ /**
+ * The error icon.
+ */
+ ERROR,
+ /**
+ * The warning large icon.
+ */
+ WARNING_LARGE,
+ /**
+ * The information icon.
+ */
+ INFORMATION,
+ /**
+ * No icon.
+ */
+ NO_ICON
+ }
+
+ /**
+ * The following enumeration contains the different text styles that we can
+ * have. A text style basically specifies the font and color to be used to
+ * render the text.
+ *
+ */
+ public enum TextStyle
+ {
+ /**
+ * Current Step label style for the steps panel.
+ */
+ CURRENT_STEP,
+ /**
+ * Not current Step label style for the steps panel.
+ */
+ NOT_CURRENT_STEP,
+ /**
+ * Title label style for the current step panel.
+ */
+ TITLE,
+ /**
+ * Primary field valid label style for the current step panel.
+ */
+ PRIMARY_FIELD_VALID,
+ /**
+ * Primary field invalid text style for the current step panel.
+ */
+ PRIMARY_FIELD_INVALID,
+ /**
+ * Secondary field valid text style for the current step panel.
+ */
+ SECONDARY_FIELD_VALID,
+ /**
+ * Secondary field invalid text style for the current step panel.
+ */
+ SECONDARY_FIELD_INVALID,
+ /**
+ * Textfield text style for the current step panel.
+ */
+ TEXTFIELD,
+ /**
+ * Password text style for the current step panel.
+ */
+ PASSWORD_FIELD,
+
+ /**
+ * Read only text style for the current step panel.
+ */
+ READ_ONLY,
+ /**
+ * Check box text text style for the current step panel.
+ */
+ CHECKBOX,
+ /**
+ * Progress messages text style for the current step panel.
+ */
+ PROGRESS,
+ /**
+ * No text style.
+ */
+ NO_STYLE
+ }
+
+ /**
+ * This method initialize the look and feel and UI settings.
+ */
+ public static void initialize()
+ {
+ if (!initialized)
+ {
+ System.setProperty("swing.aatext", "true");
+ try
+ {
+ UIManager.setLookAndFeel(
+ UIManager.getSystemLookAndFeelClassName());
+
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ JFrame.setDefaultLookAndFeelDecorated(false);
+
+ initialized = true;
+ }
+ }
+
+ /**
+ * Creates a JButton with the given label and tooltip.
+ * @param label the text of the button.
+ * @param tooltip the tooltip of the button.
+ * @return a JButton with the given label and tooltip.
+ */
+ public static JButton makeJButton(String label, String tooltip)
+ {
+ JButton b = new JButton();
+
+ if (label != null)
+ {
+ b.setText(label);
+ }
+
+ if (tooltip != null)
+ {
+ b.setToolTipText(tooltip);
+ }
+
+ return b;
+ }
+
+ /**
+ * Creates a JLabel with the given icon, text and text style.
+ * @param iconName the icon.
+ * @param text the label text.
+ * @param style the text style.
+ * @return a JLabel with the given icon, text and text style.
+ */
+ public static JLabel makeJLabel(IconType iconName, String text,
+ TextStyle style)
+ {
+ JLabel l = new JLabel();
+
+ if (text != null)
+ {
+ l.setText(text);
+ }
+
+ ImageIcon icon = getImageIcon(iconName);
+ l.setIcon(icon);
+ String tooltip = getIconTooltip(iconName);
+
+ if (tooltip != null)
+ {
+ l.setToolTipText(tooltip);
+ }
+
+ setTextStyle(l, style);
+ return l;
+ }
+
+ /**
+ * Creates a JTextField with the given icon, tooltip text, size and text
+ * style.
+ * @param text the text.
+ * @param tooltip the tooltip text.
+ * @param size the number of columns of the JTextField.
+ * @param style the text style.
+ * @return a JTextField with the given icon, tooltip text, size and text
+ * style.
+ */
+ public static JTextField makeJTextField(String text, String tooltip,
+ int size, TextStyle style)
+ {
+ JTextField f = new JTextField();
+ updateTextFieldComponent(f, text, tooltip, size, style);
+ return f;
+ }
+
+ /**
+ * Creates a JPasswordField with the given icon, tooltip text, size and text
+ * style.
+ * @param text the text.
+ * @param tooltip the tooltip text.
+ * @param size the number of columns of the JPasswordField.
+ * @param style the text style.
+ * @return a JPasswordField with the given icon, tooltip text, size and text
+ * style.
+ */
+ public static JPasswordField makeJPasswordField(String text, String tooltip,
+ int size, TextStyle style)
+ {
+ JPasswordField f = new JPasswordField();
+ updateTextFieldComponent(f, text, tooltip, size, style);
+ return f;
+ }
+
+ /**
+ * Creates a JRadioButton with the given text, tooltip text and text
+ * style.
+ * @param text the text of the radio button.
+ * @param tooltip the tooltip text.
+ * @param style the text style.
+ * @return a JRadioButton with the given text, tooltip text and text
+ * style.
+ */
+ public static JRadioButton makeJRadioButton(String text, String tooltip,
+ TextStyle style)
+ {
+ JRadioButton rb = new JRadioButton();
+
+ if (text != null)
+ {
+ rb.setText(text);
+ }
+
+ if (tooltip != null)
+ {
+ rb.setToolTipText(tooltip);
+ }
+
+ setTextStyle(rb, style);
+ return rb;
+ }
+
+ /**
+ * Creates a JCheckBox with the given text, tooltip text and text
+ * style.
+ * @param text the text of the radio button.
+ * @param tooltip the tooltip text.
+ * @param style the text style.
+ * @return a JCheckBox with the given text, tooltip text and text
+ * style.
+ */
+ public static JCheckBox makeJCheckBox(String text, String tooltip,
+ TextStyle style)
+ {
+ JCheckBox cb = new JCheckBox();
+
+ if (text != null)
+ {
+ cb.setText(text);
+ }
+
+ if (tooltip != null)
+ {
+ cb.setToolTipText(tooltip);
+ }
+
+ setTextStyle(cb, style);
+ return cb;
+ }
+
+ /**
+ * Sets the specified text style to the component passed as parameter.
+ * @param l the component to update.
+ * @param style the text style to use.
+ */
+ public static void setTextStyle(JComponent l, TextStyle style)
+ {
+ switch (style)
+ {
+ case NOT_CURRENT_STEP:
+ l.setFont(UIFactory.NOT_CURRENT_STEP_FONT);
+ l.setForeground(DEFAULT_LABEL_COLOR);
+ break;
+
+ case CURRENT_STEP:
+ l.setFont(UIFactory.CURRENT_STEP_FONT);
+ l.setForeground(DEFAULT_LABEL_COLOR);
+ break;
+
+ case TITLE:
+ l.setFont(UIFactory.TITLE_FONT);
+ l.setForeground(DEFAULT_LABEL_COLOR);
+ break;
+
+ case PRIMARY_FIELD_VALID:
+ l.setFont(UIFactory.PRIMARY_FIELD_VALID_FONT);
+ l.setForeground(FIELD_VALID_COLOR);
+ break;
+
+ case PRIMARY_FIELD_INVALID:
+ l.setFont(UIFactory.PRIMARY_FIELD_INVALID_FONT);
+ l.setForeground(FIELD_INVALID_COLOR);
+ break;
+
+ case SECONDARY_FIELD_VALID:
+ l.setFont(UIFactory.SECONDARY_FIELD_VALID_FONT);
+ l.setForeground(FIELD_VALID_COLOR);
+ break;
+
+ case SECONDARY_FIELD_INVALID:
+ l.setFont(UIFactory.SECONDARY_FIELD_INVALID_FONT);
+ l.setForeground(FIELD_INVALID_COLOR);
+ break;
+
+ case READ_ONLY:
+ l.setFont(UIFactory.READ_ONLY_FONT);
+ l.setForeground(READ_ONLY_COLOR);
+ break;
+
+ case CHECKBOX:
+ l.setFont(UIFactory.CHECKBOX_FONT);
+ l.setForeground(CHECKBOX_COLOR);
+ break;
+
+ case PROGRESS:
+ l.setFont(UIFactory.PROGRESS_FONT);
+ l.setForeground(PROGRESS_COLOR);
+ break;
+
+ case TEXTFIELD:
+ l.setFont(UIFactory.TEXTFIELD_FONT);
+ l.setForeground(TEXTFIELD_COLOR);
+ break;
+
+ case PASSWORD_FIELD:
+ l.setFont(UIFactory.PASSWORD_FIELD_FONT);
+ l.setForeground(PASSWORD_FIELD_COLOR);
+ break;
+
+ case NO_STYLE:
+ // Do nothing
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown textStyle: " + style);
+ }
+ }
+
+ /**
+ * Returns the HTML string representing the provided IconType.
+ * @param iconType the IconType for which we want the HTML representation.
+ * @return the HTML string representing the provided IconType.
+ */
+ public static String getIconHtml(IconType iconType)
+ {
+ String url =
+ String.valueOf(UIFactory.class.getClassLoader().getResource(
+ getIconPath(iconType)));
+ String description = getIconDescription(iconType);
+ String title = getIconTooltip(iconType);
+ return "<img src=\"" + url + "\" alt=\"" + description + " title=\""
+ + title + "\"/>";
+ }
+
+ /**
+ * Returns an ImageIcon object for the provided IconType.
+ * @param iconType the IconType for which we want to obtain the ImageIcon.
+ * @return the ImageIcon.
+ */
+ public static ImageIcon getImageIcon(IconType iconType)
+ {
+ ImageIcon icon = hmIcons.get(iconType);
+ if ((icon == null) && (iconType != IconType.NO_ICON))
+ {
+ String path = getIconPath(iconType);
+ String description = getIconDescription(iconType);
+ try
+ {
+ Image im =
+ Toolkit.getDefaultToolkit().createImage(
+ UIFactory.class.getClassLoader().getResource(path));
+ icon = new ImageIcon(im);
+ icon.setDescription(description);
+
+ hmIcons.put(iconType, icon);
+
+ } catch (Exception ex)
+ {
+ ex.printStackTrace(); // A bug: this should not happen
+ throw new IllegalStateException("Could not load icon for path " + path,
+ ex);
+ }
+ }
+
+ return icon;
+ }
+
+ /**
+ * Returns a JEditorPane that works with the provided scroll.
+ * @see ProgressJEditorPane
+ * @param scroll the scroll that will contain the JEditorPane.
+ * @return a JEditorPane that works with the provided scroll.
+ */
+ public static JEditorPane makeProgressPane(JScrollPane scroll)
+ {
+ return new ProgressJEditorPane(scroll);
+ }
+
+ /**
+ * Returns a read only JEditorPane containing the provided text with the
+ * provided font. The JEditorPane will assume that the text is HTML text.
+ * @param text the text to be used to initialize the JEditorPane contents.
+ * @param font the font to be used.
+ * @return a read only JEditorPane containing the provided text with the
+ * provided font.
+ */
+ public static JEditorPane makeHtmlPane(String text, Font font)
+ {
+ JEditorPane pane =
+ new JEditorPane("text/html", applyFontToHtmlWithDiv(text, font));
+ pane.setEditable(false);
+ pane.setBorder(new EmptyBorder(0, 0, 0, 0));
+ return pane;
+ }
+
+ /**
+ * Returns a read only JEditorPane containing the provided text with the
+ * provided TextStyle. The JEditorPane will assume that the text is plain
+ * text.
+ * @param text the text to be used to initialize the JEditorPane contents.
+ * @param style the TextStyle to be used.
+ * @return a read only JEditorPane containing the provided text with the
+ * provided TextStyle.
+ */
+ public static JEditorPane makeTextPane(String text, TextStyle style)
+ {
+ JEditorPane pane = new JEditorPane("text/plain", text);
+ setTextStyle(pane, style);
+ pane.setEditable(false);
+ pane.setBorder(new EmptyBorder(0, 0, 0, 0));
+ return pane;
+ }
+
+ /**
+ * Return empty insets.
+ * @return empty insets.
+ */
+ public static Insets getEmptyInsets()
+ {
+ return (Insets) EMPTY_INSETS.clone();
+ }
+
+ /**
+ * Returns the insets to be used for the button panel.
+ * @return the insets to be used for the button panel.
+ */
+ public static Insets getButtonsPanelInsets()
+ {
+ return (Insets) BUTTONS_PANEL_INSETS.clone();
+ }
+
+ /**
+ * Returns the insets to be used for the steps panel.
+ * @return the insets to be used for the steps panel.
+ */
+ public static Insets getStepsPanelInsets()
+ {
+ return (Insets) STEPS_PANEL_INSETS.clone();
+ }
+
+ /**
+ * Returns the insets to be used for the current step panel.
+ * @return the insets to be used for the current step panel.
+ */
+ public static Insets getCurrentStepPanelInsets()
+ {
+ return (Insets) CURRENT_STEP_PANEL_INSETS.clone();
+ }
+
+ /**
+ * Returns a String that contains the html passed as parameter with a span
+ * applied. The span style corresponds to the Font specified as parameter.
+ * The goal of this method is to be able to specify a font for an HTML string.
+ *
+ * @param html the original html text.
+ * @param font the font to be used to generate the new HTML.
+ * @return a string that represents the original HTML with the font specified
+ * as parameter.
+ */
+ public static String applyFontToHtml(String html, Font font)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ buf.append("<span style=\"").append(getFontStyle(font)).append("\">")
+ .append(html).append(SPAN_CLOSE);
+
+ return buf.toString();
+ }
+
+ /**
+ * Returns a String that contains the html passed as parameter with a div
+ * applied. The div style corresponds to the Font specified as parameter.
+ * The goal of this method is to be able to specify a font for an HTML string.
+ *
+ * @param html the original html text.
+ * @param font the font to be used to generate the new HTML.
+ * @return a string that represents the original HTML with the font specified
+ * as parameter.
+ */
+ public static String applyFontToHtmlWithDiv(String html, Font font)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ buf.append("<div style=\"").append(getFontStyle(font)).append("\">")
+ .append(html).append(DIV_CLOSE);
+
+ return buf.toString();
+ }
+
+ /**
+ * Returns the HTML style representation for the given font.
+ * @param font the font for which we want to get an HTML style representation.
+ * @return the HTML style representation for the given font.
+ */
+ private static String getFontStyle(Font font)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ buf.append("font-family:" + font.getName()).append(
+ ";font-size:" + font.getSize() + "pt");
+
+ if (font.isItalic())
+ {
+ buf.append(";font-style:italic");
+ }
+
+ if (font.isBold())
+ {
+ buf.append(";font-weight:bold;");
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * Returns the html text passed as parameter with the error background
+ * applied to it.
+ * @param html the original html.
+ * @return the html text passed as parameter with the error background
+ * applied to it.
+ */
+ public static String applyErrorBackgroundToHtml(String html)
+ {
+ return DIV_OPEN_ERROR_BACKGROUND + html + DIV_CLOSE;
+ }
+
+ /**
+ * Returns the html text passed as parameter with the warning background
+ * applied to it.
+ * @param html the original html.
+ * @return the html text passed as parameter with the warning background
+ * applied to it.
+ */
+ public static String applyWarningBackgroundToHtml(String html)
+ {
+ return DIV_OPEN_WARNING_BACKGROUND + html + DIV_CLOSE;
+ }
+
+
+ /**
+ * Returns the html text passed as parameter with the success background
+ * applied to it.
+ * @param html the original html.
+ * @return the html text passed as parameter with the success background
+ * applied to it.
+ */
+ public static String applySuccessfulBackgroundToHtml(String html)
+ {
+ return DIV_OPEN_SUCCESSFUL_BACKGROUND + html + DIV_CLOSE;
+ }
+
+
+ /**
+ * Returns the html text passed as parameter with some added margin.
+ * @param html the original html text.
+ * @param top the top margin.
+ * @param right the right margin.
+ * @param bottom the bottom margin.
+ * @param left the left margin.
+ * @return the html text passed as parameter with some added margin.
+ */
+ public static String applyMargin(String html, int top, int right, int bottom,
+ int left)
+ {
+ String result =
+ "<div style=\"margin:" + top + "px " + right + "px " + bottom + "px "
+ + left + "px;\">" + html + DIV_CLOSE;
+ return result;
+ }
+
+ /**
+ * Updates the provided field with all the other arguments.
+ * @param field the field to be modified.
+ * @param text the new text of the field.
+ * @param tooltip the new tooltip text of the field.
+ * @param size the new size of the field.
+ * @param textStyle the new TextStyle of the field.
+ */
+ private static void updateTextFieldComponent(JTextField field, String text,
+ String tooltip, int size, TextStyle textStyle)
+ {
+ field.setColumns(size);
+ if (text != null)
+ {
+ field.setText(text);
+ }
+ if (tooltip != null)
+ {
+ field.setToolTipText(tooltip);
+ }
+ if (textStyle != null)
+ {
+ setTextStyle(field, textStyle);
+ }
+ }
+
+ /* Some commodity methods to retrieve localized messages */
+ private static ResourceProvider getI18n()
+ {
+ return ResourceProvider.getInstance();
+ }
+
+ private static String getMsg(String key)
+ {
+ return getI18n().getMsg(key);
+ }
+
+ /**
+ * Returns the parent package path. This is used to retrieve the icon
+ * qualified names.
+ * @return the parent package path.
+ */
+ private static String getParentPackagePath()
+ {
+ if (parentPackagePath == null)
+ {
+ String packageName = UIFactory.class.getPackage().getName();
+ int lastDot = packageName.lastIndexOf('.');
+ String parentPackage = packageName.substring(0, lastDot);
+ parentPackagePath = parentPackage.replace(".", "/");
+ }
+ return parentPackagePath;
+ }
+
+ /**
+ * Returns the path of the icon for the given IconType.
+ * @param iconType the IconType for which we want to get the path.
+ * @return the path of the icon for the given IconType.
+ */
+ private static String getIconPath(IconType iconType)
+ {
+ String key = null;
+ switch (iconType)
+ {
+ case CURRENT_STEP:
+ key = "current-step-icon";
+ break;
+
+ case SPLASH:
+ key = "splash-icon";
+ break;
+
+ case BACKGROUND:
+ key = "background-icon";
+ break;
+
+ case MINIMIZED:
+ key = "minimized-icon";
+ break;
+
+ case MINIMIZED_MAC:
+ key = "minimized-mac-icon";
+ break;
+
+ case WARNING:
+ key = "warning-icon";
+ break;
+
+ case WARNING_LARGE:
+ key = "warning-large-icon";
+ break;
+
+ case INFORMATION:
+ key = "information-icon";
+ break;
+
+ case ERROR:
+ key = "error-icon";
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknow iconName: " + iconType);
+ }
+ return getParentPackagePath() + "/" + getMsg(key);
+ }
+
+ /**
+ * Returns the icon description for the given IconType.
+ * @param iconType the IconType for which we want to get the description.
+ * @return the icon description for the given IconType.
+ */
+ private static String getIconDescription(IconType iconType)
+ {
+ String description = null;
+ switch (iconType)
+ {
+ case CURRENT_STEP:
+ description = getMsg("current-step-icon-description");
+ break;
+
+ case SPLASH:
+ description = getMsg("splash-icon-description");
+ break;
+
+ case BACKGROUND:
+ description = getMsg("background-icon-description");
+ break;
+
+ case MINIMIZED:
+ description = getMsg("minimized-icon-description");
+ break;
+
+ case MINIMIZED_MAC:
+ description = getMsg("minimized-icon-description");
+ break;
+
+ case WARNING:
+ description = "warning-icon-description";
+ break;
+
+ case WARNING_LARGE:
+ description = "warning-icon-description";
+ break;
+
+ case ERROR:
+ description = "error-icon-description";
+ break;
+
+ case INFORMATION:
+ description = "information-icon-description";
+ break;
+
+ case NO_ICON:
+ description = null;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknow iconName: " + iconType);
+ }
+ return description;
+ }
+
+ /**
+ * Returns the icon tooltip text for the given IconType.
+ * @param iconType the IconType for which we want to get the tooltip text.
+ * @return the icon tooltip text for the given IconType.
+ */
+ private static String getIconTooltip(IconType iconType)
+ {
+ String tooltip;
+ switch (iconType)
+ {
+ case CURRENT_STEP:
+ tooltip = getMsg("current-step-icon-tooltip");
+ break;
+
+ case SPLASH:
+ tooltip = getMsg("splash-icon-tooltip");
+ break;
+
+ case BACKGROUND:
+ tooltip = getMsg("background-icon-tooltip");
+ break;
+
+ case MINIMIZED:
+ tooltip = getMsg("minimized-icon-tooltip");
+ break;
+
+ case MINIMIZED_MAC:
+ tooltip = getMsg("minimized-mac-icon-tooltip");
+ break;
+
+ case WARNING:
+ tooltip = "warning-icon-tooltip";
+ break;
+
+ case WARNING_LARGE:
+ tooltip = "warning-icon-tooltip";
+ break;
+
+ case ERROR:
+ tooltip = "error-icon-tooltip";
+ break;
+
+ case INFORMATION:
+ tooltip = "information-icon-tooltip";
+ break;
+
+ case NO_ICON:
+ tooltip = null;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknow iconName: " + iconType);
+ }
+ return tooltip;
+ }
+}
+
+/**
+ * This class has been written to have a better behaviour with the scroll pane
+ * than the one we have by default in the case of the progress panel.
+ *
+ * With the default scroll pane behaviour when we set a new text in a
+ * JEditorPane the scroll bar goes systematically up. With this implementation
+ * the expected behaviour is:
+ *
+ * If the scroll bar is at the bottom we will display the latest text contained
+ * in the pane.
+ *
+ * If the scroll bar is not at the bottom we will keep on displaying the same
+ * thing that the user is viewing.
+ *
+ * This behaviour allows the user to check the log content even when the
+ * installation/uninstallation is still running and sending new log messages.
+ *
+ */
+class ProgressJEditorPane extends JEditorPane
+{
+ private static final long serialVersionUID = 1221976708322628818L;
+
+ private JScrollPane scroll;
+
+ private boolean ignoreScrollToVisible;
+
+ /**
+ * Constructor for the ProgressJEditorPane.
+ * @param scroll the JScrollPane that will contain this editor pane.
+ */
+ public ProgressJEditorPane(JScrollPane scroll)
+ {
+ super("text/html", null);
+ this.scroll = scroll;
+ setEditable(false);
+ setBorder(new EmptyBorder(3, 3, 3, 3));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setText(String text)
+ {
+ // Scroll can be null in constructor
+ if (scroll != null)
+ {
+ /* We apply the following policy: if the user is displaying the latest
+ * part of the JTextArea we assume that when we add text (s)he wants
+ * to see the text that is added, if not we assume that (s)he want to keep
+ * viewing what is visible and so we ignore the next scrollRectToVisible
+ * call (that will be done inside JTextArea.setText method).
+ */
+ JScrollBar vBar = scroll.getVerticalScrollBar();
+ ignoreScrollToVisible =
+ (vBar != null)
+ && ((vBar.getValue() + vBar.getVisibleAmount()) < 0.97 * vBar
+ .getMaximum());
+ super.setText(text);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void scrollRectToVisible(Rectangle rect)
+ {
+ if (!ignoreScrollToVisible)
+ {
+ super.scrollRectToVisible(rect);
+ ignoreScrollToVisible = false;
+ }
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java b/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java
new file mode 100644
index 0000000..5f4f499
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/WebBrowserErrorDialog.java
@@ -0,0 +1,210 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.text.JTextComponent;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.util.Utils;
+import org.opends.quicksetup.util.WebBrowserException;
+
+/**
+ * This class is a dialog that appears when we could not launch the user web
+ * browser after the user clicked on a link.
+ *
+ * The dialog displays the URL to be displayed and provides a 'Copy URL' button
+ * to copy it to the system clipboard. This way (even if not ideal) the user
+ * can view the contents of the URL we display by pasting manually the URL
+ * in his/her browser.
+ *
+ */
+public class WebBrowserErrorDialog extends JDialog
+{
+ private static final long serialVersionUID = 1063837373763193941L;
+
+ private JFrame parent;
+
+ private String url;
+
+ /**
+ * Constructor of the WebBrowserErrorDialog.
+ * @param parent the parent frame for this dialog.
+ * @param ex the WebBrowserException.
+ */
+ public WebBrowserErrorDialog(JFrame parent, WebBrowserException ex)
+ {
+ super(parent);
+ setTitle(getMsg("error-browser-display-title"));
+ this.parent = parent;
+ this.url = ex.getUrl();
+ getContentPane().add(createPanel());
+ }
+
+ /**
+ * Packs and displays this dialog.
+ *
+ */
+ public void packAndShow()
+ {
+ pack();
+ Utils.centerOnComponent(this, parent);
+ setVisible(true);
+ }
+
+ /* The following three methods are just commodity methods to retrieve
+ * localized messages */
+ private String getMsg(String key)
+ {
+ return getI18n().getMsg(key);
+ }
+
+ private String getMsg(String key, String[] args)
+ {
+ return getI18n().getMsg(key, args);
+ }
+
+ private ResourceProvider getI18n()
+ {
+ return ResourceProvider.getInstance();
+ }
+
+ /**
+ * Creates and returns the panel of the dialog.
+ * @return the panel of the dialog.
+ */
+ private JPanel createPanel()
+ {
+ JPanel p1 = new JPanel(new GridBagLayout());
+ p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+ p1.setBorder(UIFactory.DIALOG_PANEL_BORDER);
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.gridwidth = 3;
+ gbc.anchor = GridBagConstraints.NORTHWEST;
+ gbc.insets = UIFactory.getCurrentStepPanelInsets();
+ p1.add(UIFactory.makeJLabel(UIFactory.IconType.WARNING_LARGE, null,
+ UIFactory.TextStyle.NO_STYLE), gbc);
+ gbc.weightx = 1.0;
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ Insets pInsets = UIFactory.getCurrentStepPanelInsets();
+ gbc.insets.left = 0;
+ String msg = getMsg("error-browser-display-msg", new String[]
+ { url });
+ JTextComponent tf =
+ UIFactory.makeHtmlPane(msg,
+ UIFactory.BROWSER_ERROR_DIALOG_FONT);
+ tf.setOpaque(false);
+ p1.add(tf, gbc);
+
+ gbc.weightx = 0.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ JButton copyButton =
+ UIFactory.makeJButton(getMsg("error-browser-copy-button-label"),
+ getMsg("error-browser-copy-button-tooltip"));
+ copyButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ev)
+ {
+ StringSelection s = new StringSelection(url);
+ getToolkit().getSystemClipboard().setContents(s, s);
+ }
+ });
+ gbc.insets.left = UIFactory.LEFT_INSET_COPY_BUTTON;
+ gbc.insets.right = pInsets.right;
+ gbc.fill = GridBagConstraints.NONE;
+ p1.add(copyButton, gbc);
+ gbc.weighty = 1.0;
+ gbc.fill = GridBagConstraints.VERTICAL;
+ p1.add(Box.createVerticalGlue(), gbc);
+
+ JPanel p2 = new JPanel(new GridBagLayout());
+ p2.setOpaque(false);
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 1.0;
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.gridwidth = GridBagConstraints.RELATIVE;
+ p2.add(Box.createHorizontalGlue(), gbc);
+ JButton closeButton =
+ UIFactory.makeJButton(getMsg("close-button-label"),
+ getMsg("error-browser-close-button-tooltip"));
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.weightx = 0.0;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ p2.add(closeButton, gbc);
+ closeButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ev)
+ {
+ dispose();
+ }
+ });
+
+ JPanel p = new JPanel(new GridBagLayout());
+ p.setBackground(UIFactory.DEFAULT_BACKGROUND);
+ gbc.insets = UIFactory.getEmptyInsets();
+ gbc.fill = GridBagConstraints.BOTH;
+ gbc.gridwidth = GridBagConstraints.REMAINDER;
+ gbc.weightx = 1.0;
+ gbc.weighty = 1.0;
+ p.add(p1, gbc);
+ gbc.weighty = 0.0;
+ gbc.insets = UIFactory.getButtonsPanelInsets();
+ p.add(p2, gbc);
+ return p;
+ }
+
+ /**
+ * Method written for testing purposes.
+ * @param args the arguments to be passed to the test program.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ // UIFactory.initialize();
+ WebBrowserErrorDialog dlg =
+ new WebBrowserErrorDialog(new JFrame(),
+ new WebBrowserException("http://www.yahoo.com", "toto", null));
+ dlg.packAndShow();
+ } catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java b/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java
new file mode 100644
index 0000000..b672d19
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/ui/WelcomePanel.java
@@ -0,0 +1,80 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.Component;
+
+/**
+ * This panel is used to show a welcome message.
+ *
+ */
+class WelcomePanel extends QuickSetupStepPanel
+{
+ private static final long serialVersionUID = 6209217138897900860L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public WelcomePanel()
+ {
+ createLayout();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getTitle()
+ {
+ return getMsg("welcome-panel-title");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected String getInstructions()
+ {
+ /*
+ * We can use org.opends.server.util.DynamicConstants without problems as it
+ * has been added to quicksetup.jar during build time.
+ */
+ String[] args =
+ { org.opends.server.util.DynamicConstants.COMPACT_VERSION_STRING,
+ org.opends.server.util.DynamicConstants.BUILD_ID };
+ return getMsg("welcome-panel-instructions", args);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Component createInputPanel()
+ {
+ // No input in this panel
+ return null;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressDescriptor.java b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressDescriptor.java
new file mode 100644
index 0000000..885912c
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressDescriptor.java
@@ -0,0 +1,108 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.uninstaller;
+
+/**
+ * This class is used to describe the current state of the uninstallation.
+ * It contains the step in which the uninstallation is, the current progress
+ * ratio, the progress bar message and the details message (the logs).
+ *
+ * This class is used directly by the ProgressPanel to update its content
+ * and has been designed to match the layout of that panel. However as it
+ * does not contain any dependency in terms of code with any Swing or UI package
+ * component it has been decided to leave it on the uninstaller package.
+ *
+ * In general the progress bar message and the details messages (log) are in
+ * HTML form (but this class is independent of the format we use for the
+ * messages).
+ *
+ */
+public class UninstallProgressDescriptor
+{
+ private UninstallProgressStep step;
+
+ private Integer progressBarRatio;
+
+ private String progressBarMsg;
+
+ private String detailsMsg;
+
+ /**
+ * Constructor for the UninstallProgressDescriptor.
+ * @param step the current uninstall step.
+ * @param progressBarRatio the completed progress ratio (in percentage).
+ * @param progressBarMsg the message to be displayed in the progress bar.
+ * @param detailsMsg the logs.
+ */
+ public UninstallProgressDescriptor(UninstallProgressStep step,
+ Integer progressBarRatio, String progressBarMsg, String detailsMsg)
+ {
+ this.step = step;
+ this.progressBarRatio = progressBarRatio;
+ this.progressBarMsg = progressBarMsg;
+ this.detailsMsg = detailsMsg;
+ }
+
+ /**
+ * Returns the details message (the log message) of the uninstall.
+ * @return the details message (the log message) of the uninstall.
+ */
+ public String getDetailsMsg()
+ {
+ return detailsMsg;
+ }
+
+ /**
+ * Returns the progress bar message.
+ * @return the progress bar message.
+ */
+ public String getProgressBarMsg()
+ {
+ return progressBarMsg;
+ }
+
+ /**
+ * Returns the progress bar ratio (the percentage of the uninstall that is
+ * completed).
+ * @return the progress bar ratio (the percentage of the uninstall that is
+ * completed).
+ */
+ public Integer getProgressBarRatio()
+ {
+ return progressBarRatio;
+ }
+
+ /**
+ * Returns the step of the uninstall on which we are.
+ * @return the step of the uninstall on which we are.
+ */
+ public UninstallProgressStep getProgressStep()
+ {
+ return step;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java
new file mode 100644
index 0000000..3ef8ae4
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallProgressStep.java
@@ -0,0 +1,61 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.uninstaller;
+
+/**
+ * This enumeration describes the different uninstallation steps in which we can
+ * be.
+ *
+ */
+public enum UninstallProgressStep
+{
+ /**
+ * Uninstall not started.
+ */
+ NOT_STARTED,
+ /**
+ * Stopping server.
+ */
+ STOPPING_SERVER,
+ /**
+ * Removing Database files.
+ */
+ REMOVING_DATABASE_FILES,
+ /**
+ * Removing external references.
+ */
+ REMOVING_EXTERNAL_REFERENCES,
+ /**
+ * Installation finished successfully.
+ */
+ FINISHED_SUCCESSFULLY,
+ /**
+ * Installation finished with an error.
+ */
+ FINISHED_WITH_ERROR
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java
new file mode 100644
index 0000000..b21091f
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.uninstaller;
+
+/**
+ * This class is in charge of performing the uninstallation of Open DS.
+ *
+ * TODO implement this class.
+ *
+ */
+public class Uninstaller
+{
+ /**
+ * Returns whether the uninstaller has finished or not.
+ * @return <CODE>true</CODE> if the install is finished or <CODE>false
+ * </CODE> if not.
+ */
+ public boolean isFinished()
+ {
+ /* TODO implement this */
+ return false;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundTask.java b/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundTask.java
new file mode 100644
index 0000000..dab6554
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundTask.java
@@ -0,0 +1,82 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.quicksetup.util;
+
+
+
+/**
+ * This class provides a mechanism for running a task in the background using a
+ * separate thread and providing the caller with notification when it has
+ * completed.
+ */
+public abstract class BackgroundTask
+{
+ /**
+ * Creates a new thread and begins running the task in the background. When
+ * the task has completed, the {@code backgroundTaskCompleted} method will be
+ * invoked.
+ */
+ public final void startBackgroundTask()
+ {
+ BackgroundTaskThread taskThread = new BackgroundTaskThread(this);
+ taskThread.start();
+ }
+
+
+
+ /**
+ * Performs all processing associated with the task.
+ *
+ * @return An {@code Object} with information about the processing performed
+ * for this task, or {@code null} if no return value is needed.
+ *
+ * @throws Exception exception that will be passed through the method
+ * backgroundTaskCompleted.
+ */
+ public abstract Object processBackgroundTask() throws Exception;
+
+
+
+ /**
+ * This method will be invoked to indicate that the background task has
+ * completed. If processing completed successfully, then the
+ * {@code Throwable} argument will be {@code null} and the {@code returnValue}
+ * argument will contain the value returned by the
+ * {@code processBackgroundTask} method. If an exception or error was thrown,
+ * then the {@code throwable} argument will not be {@code null}.
+ *
+ * @param returnValue The value returned by the
+ * {@code processBackgroundTask} method when processing
+ * completed, or {@code null} if no value was returned or
+ * an exception was encountered during processing.
+ * @param throwable A {@code Throwable} instance (e.g., an exception) that
+ * was raised during processing, or {@code null} if all
+ * processing completed successfully.
+ */
+ public abstract void backgroundTaskCompleted(Object returnValue,
+ Throwable throwable);
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundThreadTask.java b/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundThreadTask.java
new file mode 100644
index 0000000..c76d1e8
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/BackgroundThreadTask.java
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.quicksetup.util;
+
+
+
+/**
+ * This class defines a thread that will be used to actually perform the
+ * processing for a background task.
+ */
+class BackgroundTaskThread
+ extends Thread
+{
+ // The background task that is to be processed.
+ private final BackgroundTask backgroundTask;
+
+
+
+ /**
+ * Creates a new background task thread that will be used to process the
+ * provided task.
+ *
+ * @param backgroundTask The task to be processed.
+ */
+ public BackgroundTaskThread(BackgroundTask backgroundTask)
+ {
+ this.backgroundTask = backgroundTask;
+ }
+
+
+
+ /**
+ * Performs the processing associated with the background task.
+ */
+ public void run()
+ {
+ try
+ {
+ Object returnValue = backgroundTask.processBackgroundTask();
+ backgroundTask.backgroundTaskCompleted(returnValue, null);
+ }
+ catch (Throwable t)
+ {
+ backgroundTask.backgroundTaskCompleted(null, t);
+ }
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/ExtensionFileFilter.java b/opends/src/quicksetup/org/opends/quicksetup/util/ExtensionFileFilter.java
new file mode 100644
index 0000000..5ff6e0e
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/ExtensionFileFilter.java
@@ -0,0 +1,86 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.util;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * This is a class used to be able to filter on certain type of files
+ * in the File Browser dialog.
+ *
+ */
+public class ExtensionFileFilter extends FileFilter
+{
+ private String extension;
+
+ private String description;
+
+ /**
+ * The ExtensionFiter constructor.
+ * @param extension the extension of the file we want to filter on.
+ * @param description the description for the extension.
+ */
+ public ExtensionFileFilter(String extension, String description)
+ {
+ this.extension = extension;
+ this.description = description;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean accept(File f)
+ {
+ boolean accept = false;
+ if (f != null)
+ {
+ if (f.isDirectory())
+ {
+ accept = true;
+ } else if (Utils.isWindows())
+ {
+ accept =
+ f.getName().toLowerCase().endsWith("." + extension.toLowerCase());
+ } else
+ {
+ accept = f.getName().endsWith("." + extension);
+ }
+ }
+ return accept;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDescription()
+ {
+ return description;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java b/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java
new file mode 100644
index 0000000..fa9ed26
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/URLWorker.java
@@ -0,0 +1,107 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.util;
+
+import javax.swing.JFrame;
+
+import org.opends.quicksetup.ui.WebBrowserErrorDialog;
+import org.opends.quicksetup.ui.QuickSetupStepPanel;
+
+/**
+ * This class is used to try to launch a URL in the user web browser.
+ *
+ * The class extends SwingWorker and tries to launch the URL using
+ * a WebBrowserLauncher object in the construct method.
+ * If there is a problem launching the user's browser, this class will display
+ * a WebBrowserErrorDialog to allow the user to copy to the system clipboard the
+ * URL we wanted to display.
+ *
+ * When is finished (successfully or unsuccessfully) it notifies the
+ * QuickSetupStepPanel passed in the constructor.
+ *
+ */
+public class URLWorker extends BackgroundTask
+{
+ private QuickSetupStepPanel panel;
+
+ private String url;
+
+ /**
+ * Constructs a URLWorker.
+ * @param panel the panel that created this URLWorker and to which we will
+ * notify when we are over.
+ * @param url the url to be displayed.
+ */
+ public URLWorker(QuickSetupStepPanel panel, String url)
+ {
+ this.panel = panel;
+ this.url = url;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object processBackgroundTask() throws WebBrowserException
+ {
+ try
+ {
+ WebBrowserLauncher.openURL(url);
+ } catch (RuntimeException re)
+ {
+ throw new WebBrowserException(url, "Bug: run time exception", re);
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void backgroundTaskCompleted(Object returnValue,
+ Throwable throwable)
+ {
+ WebBrowserException ex = (WebBrowserException) throwable;
+ if (ex != null)
+ {
+ WebBrowserErrorDialog dlg =
+ new WebBrowserErrorDialog((JFrame) panel.getMainWindow(), ex);
+ dlg.setModal(false);
+ dlg.packAndShow();
+ }
+ // Notify to the panel that the worker has finished.
+ panel.urlWorkerFinished(this);
+ }
+
+ /**
+ * Returns the URL that we are trying to launch in the users browser.
+ * @return the URL that we are trying to launch in the users browser.
+ */
+ public String getURL()
+ {
+ return url;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
new file mode 100644
index 0000000..99a67aa
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -0,0 +1,809 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.quicksetup.util;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapName;
+
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.installer.webstart.JnlpProperties;
+
+
+/**
+ * This class provides some static convenience methods of different nature.
+ *
+ */
+public class Utils
+{
+ private static final int BUFFER_SIZE = 1024;
+
+ private Utils()
+ {
+ }
+
+ /**
+ * Center the component location based on its preferred size. The code
+ * considers the particular case of 2 screens and puts the component on the
+ * center of the left screen
+ *
+ * @param comp the component to be centered.
+ */
+ public static void centerOnScreen(Component comp)
+ {
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+
+ int width = (int) comp.getPreferredSize().getWidth();
+ int height = (int) comp.getPreferredSize().getHeight();
+
+ boolean multipleScreen = screenSize.width / screenSize.height >= 2;
+
+ if (multipleScreen)
+ {
+ comp.setLocation((screenSize.width / 4) - (width / 2),
+ (screenSize.height - height) / 2);
+ } else
+ {
+ comp.setLocation((screenSize.width - width) / 2,
+ (screenSize.height - height) / 2);
+ }
+ }
+
+ /**
+ * Center the component location of the ref component.
+ *
+ * @param comp the component to be centered.
+ * @param ref the component to be used as reference.
+ *
+ */
+ public static void centerOnComponent(Window comp, Component ref)
+ {
+ comp.setLocationRelativeTo(ref);
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the provided port is free and we can use it,
+ * <CODE>false</CODE> otherwise.
+ * @param port the port we are analyzing.
+ * @return <CODE>true</CODE> if the provided port is free and we can use it,
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean canUseAsPort(int port)
+ {
+ boolean canUseAsPort = false;
+ ServerSocket serverSocket = null;
+ try
+ {
+ InetSocketAddress socketAddress = new InetSocketAddress(port);
+ serverSocket = new ServerSocket();
+ if (!isWindows())
+ {
+ serverSocket.setReuseAddress(true);
+ }
+ serverSocket.bind(socketAddress);
+ canUseAsPort = true;
+ } catch (IOException ex)
+ {
+ canUseAsPort = false;
+ } finally
+ {
+ try
+ {
+ if (serverSocket != null)
+ {
+ serverSocket.close();
+ }
+ } catch (Exception ex)
+ {
+ }
+ }
+
+ return canUseAsPort;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the provided port is a priviledged port,
+ * <CODE>false</CODE> otherwise.
+ * @param port the port we are analyzing.
+ * @return <CODE>true</CODE> if the provided port is a priviledged port,
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean isPriviledgedPort(int port)
+ {
+ return (port <= 1024) && !isWindows();
+ }
+
+ /**
+ * Returns the absolute path for the given parentPath and relativePath.
+ * @param parentPath the parent path.
+ * @param relativePath the relative path.
+ * @return the absolute path for the given parentPath and relativePath.
+ */
+ public static String getPath(String parentPath, String relativePath)
+ {
+ File f = new File(new File(parentPath), relativePath);
+ return f.toString();
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if we are running under windows and
+ * <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if we are running under windows and
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean isWindows()
+ {
+ return containsOsProperty("windows");
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if we are running under Mac OS and
+ * <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if we are running under Mac OS and
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean isMacOS()
+ {
+ return containsOsProperty("Mac OS");
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if we are running under Unix and
+ * <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if we are running under Unix and
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean isUnix()
+ {
+ return !isWindows();
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the parent directory for the provided path
+ * exists and <CODE>false</CODE> otherwise.
+ * @param path the path that we are analyzing.
+ * @return <CODE>true</CODE> if the parent directory for the provided path
+ * exists and <CODE>false</CODE> otherwise.
+ */
+ public static boolean parentDirectoryExists(String path)
+ {
+ boolean parentExists = false;
+ File f = new File(path);
+ if (f != null)
+ {
+ File parentFile = f.getParentFile();
+ if (parentFile != null)
+ {
+ parentExists = parentFile.isDirectory();
+ }
+ }
+ return parentExists;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the the provided path is a file and exists and
+ * <CODE>false</CODE> otherwise.
+ * @param path the path that we are analyzing.
+ * @return <CODE>true</CODE> if the the provided path is a file and exists and
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean fileExists(String path)
+ {
+ boolean isFile = false;
+ File f = new File(path);
+ if (f != null)
+ {
+ isFile = f.isFile();
+ }
+ return isFile;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the the provided path is a directory, exists
+ * and is not empty <CODE>false</CODE> otherwise.
+ * @param path the path that we are analyzing.
+ * @return <CODE>true</CODE> if the the provided path is a directory, exists
+ * and is not empty <CODE>false</CODE> otherwise.
+ */
+ public static boolean directoryExistsAndIsNotEmpty(String path)
+ {
+ boolean directoryExistsAndIsNotEmpty = false;
+ boolean isDirectory = false;
+
+ File f = new File(path);
+ if (f != null)
+ {
+ isDirectory = f.isDirectory();
+ }
+ if (isDirectory)
+ {
+ String[] ch = f.list();
+
+ directoryExistsAndIsNotEmpty = (ch != null) && (ch.length > 0);
+ }
+
+ return directoryExistsAndIsNotEmpty;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the the provided string is a DN and
+ * <CODE>false</CODE> otherwise.
+ * @param dn the String we are analyzing.
+ * @return <CODE>true</CODE> if the the provided string is a DN and
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean isDn(String dn)
+ {
+ boolean isDn = true;
+ try
+ {
+ new LdapName(dn);
+ } catch (Exception ex)
+ {
+ isDn = false;
+ }
+ return isDn;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the the provided string is a configuration DN
+ * and <CODE>false</CODE> otherwise.
+ * @param dn the String we are analyzing.
+ * @return <CODE>true</CODE> if the the provided string is a configuration DN
+ * and <CODE>false</CODE> otherwise.
+ */
+ public static boolean isConfigurationDn(String dn)
+ {
+ boolean isConfigurationDn = false;
+ String[] configDns =
+ { "cn=config", "cn=schema" };
+ for (int i = 0; i < configDns.length && !isConfigurationDn; i++)
+ {
+ isConfigurationDn = areDnsEqual(dn, configDns[i]);
+ }
+ return isConfigurationDn;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if the the provided strings represent the same
+ * DN and <CODE>false</CODE> otherwise.
+ * @param dn1 the first dn to compare.
+ * @param dn2 the second dn to compare.
+ * @return <CODE>true</CODE> if the the provided strings represent the same
+ * DN and <CODE>false</CODE> otherwise.
+ */
+ public static boolean areDnsEqual(String dn1, String dn2)
+ {
+ boolean areDnsEqual = false;
+ try
+ {
+ LdapName name1 = new LdapName(dn1);
+ LdapName name2 = new LdapName(dn2);
+ areDnsEqual = name1.equals(name2);
+ } catch (Exception ex)
+ {
+ }
+
+ return areDnsEqual;
+ }
+
+ /**
+ * Creates the parent path for the provided path.
+ * @param path the path.
+ * @return <CODE>true</CODE> if the parent path was created or already existed
+ * and <CODE>false</CODE> otherwise.
+ */
+ public static boolean createParentPath(String path)
+ {
+ boolean parentPathExists = true;
+ if (!parentDirectoryExists(path))
+ {
+ File f = new File(path);
+ if (f != null)
+ {
+ File parentFile = f.getParentFile();
+ parentPathExists = parentFile.mkdirs();
+ }
+ }
+ return parentPathExists;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if we can write on the provided path and
+ * <CODE>false</CODE> otherwise.
+ * @param path the path.
+ * @return <CODE>true</CODE> if we can write on the provided path and
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean canWrite(String path)
+ {
+ boolean canWrite;
+ File file = new File(path);
+ if (file.exists())
+ {
+ canWrite = file.canWrite();
+ } else
+ {
+ File parentFile = file.getParentFile();
+ if (parentFile != null)
+ {
+ canWrite = parentFile.canWrite();
+ } else
+ {
+ canWrite = false;
+ }
+ }
+ return canWrite;
+ }
+
+ /**
+ * Creates the a directory in the provided path.
+ * @param path the path.
+ * @return <CODE>true</CODE> if the path was created or already existed (and
+ * was a directory) and <CODE>false</CODE> otherwise.
+ * @throws IOException if something goes wrong.
+ */
+ public static boolean createDirectory(String path) throws IOException
+ {
+ boolean directoryCreated;
+ File f = new File(path);
+ if (!f.exists())
+ {
+ directoryCreated = f.mkdirs();
+ } else
+ {
+ directoryCreated = f.isDirectory();
+ }
+ return directoryCreated;
+ }
+
+ /**
+ * Creates a file on the specified path with the contents of the provided
+ * stream.
+ * @param path the path where the file will be created.
+ * @param is the InputStream with the contents of the file.
+ * @throws IOException if something goes wrong.
+ */
+ public static void createFile(String path, InputStream is) throws IOException
+ {
+ FileOutputStream out;
+ BufferedOutputStream dest;
+ byte[] data = new byte[BUFFER_SIZE];
+ int count;
+
+ out = new FileOutputStream(path);
+
+ dest = new BufferedOutputStream(out);
+
+ while ((count = is.read(data, 0, BUFFER_SIZE)) != -1)
+ {
+ dest.write(data, 0, count);
+ }
+ dest.flush();
+ dest.close();
+ }
+
+ /**
+ * Creates a file on the specified path with the contents of the provided
+ * String.
+ * @param path the path where the file will be created.
+ * @param content the String with the contents of the file.
+ * @throws IOException if something goes wrong.
+ */
+ public static void createFile(String path, String content) throws IOException
+ {
+ FileWriter file = new FileWriter(path);
+ PrintWriter out = new PrintWriter(file);
+
+ out.println(content);
+
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Returns the default server location that will be proposed to the user
+ * in the installation.
+ * @return the default server location that will be proposed to the user
+ * in the installation.
+ */
+ public static String getDefaultServerLocation()
+ {
+ String userDir = System.getProperty("user.home");
+ String firstLocation =
+ userDir + File.separator
+ + org.opends.server.util.DynamicConstants.COMPACT_VERSION_STRING;
+ String serverLocation = firstLocation;
+ int i = 1;
+ while (fileExists(serverLocation)
+ || directoryExistsAndIsNotEmpty(serverLocation))
+ {
+ serverLocation = firstLocation + "-" + i;
+ i++;
+ }
+ return serverLocation;
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if there is more disk space in the provided path
+ * than what is specified with the bytes parameter.
+ * @param directoryPath the path.
+ * @param bytes the disk space.
+ * @return <CODE>true</CODE> if there is more disk space in the provided path
+ * than what is specified with the bytes parameter.
+ */
+ public static synchronized boolean hasEnoughSpace(String directoryPath,
+ long bytes)
+ {
+ // TODO This does not work with quotas etc. but at least it seems that
+ // we do not write all data on disk if it fails.
+ boolean hasEnoughSpace = false;
+ File file = null;
+ RandomAccessFile raf = null;
+ File directory = new File(directoryPath);
+ boolean deleteDirectory = false;
+ if (!directory.exists())
+ {
+ deleteDirectory = directory.mkdir();
+ }
+ try
+ {
+ file = File.createTempFile("temp" + System.nanoTime(), ".tmp", directory);
+ raf = new RandomAccessFile(file, "rw");
+ raf.setLength(bytes);
+ hasEnoughSpace = true;
+ } catch (IOException ex)
+ {
+ } finally
+ {
+ if (raf != null)
+ {
+ try
+ {
+ raf.close();
+ } catch (IOException ex2)
+ {
+ }
+ }
+ if (file != null)
+ {
+ file.delete();
+ }
+ }
+ if (deleteDirectory)
+ {
+ directory.delete();
+ }
+ return hasEnoughSpace;
+ }
+
+ /**
+ * Returns a localized message for a given properties key an exception.
+ * @param key the key of the message in the properties file.
+ * @param i18n the ResourceProvider to be used.
+ * @param args the arguments of the message in the properties file.
+ * @param ex the exception for which we want to get a message.
+ *
+ * @return a localized message for a given properties key an exception.
+ */
+ public static String getExceptionMsg(ResourceProvider i18n, String key,
+ String[] args, Exception ex)
+ {
+ String msg;
+ if (args != null)
+ {
+ msg = i18n.getMsg(key, args);
+ } else
+ {
+ msg = i18n.getMsg(key);
+ }
+
+ String detail = ex.toString();
+ if (detail != null)
+ {
+ String[] arg =
+ { detail };
+ msg = msg + " " + i18n.getMsg("exception-details", arg);
+ }
+ return msg;
+ }
+
+ /**
+ * Commodity method to help identifying the OS we are running on.
+ * @param s the String that represents an OS.
+ * @return <CODE>true</CODE> if there is os java property exists and contains
+ * the value specified in s, <CODE>false</CODE> otherwise.
+ */
+ private static boolean containsOsProperty(String s)
+ {
+ boolean containsOsProperty = false;
+
+ String osName = System.getProperty("os.name");
+ if (osName != null)
+ {
+ containsOsProperty = osName.toLowerCase().indexOf(s) != -1;
+ }
+
+ return containsOsProperty;
+ }
+
+ /**
+ * Sets the permissions of the provided paths with the provided permission
+ * String.
+ * @param paths the paths to set permissions on.
+ * @param permissions the UNIX-mode file system permission representation
+ * (for example "644" or "755")
+ * @return the return code of the chmod command.
+ * @throws IOException if something goes wrong.
+ * @throws InterruptedException if the Runtime.exec method is interrupted.
+ */
+ public static int setPermissionsUnix(ArrayList<String> paths,
+ String permissions) throws IOException, InterruptedException
+ {
+ String[] args = new String[paths.size() + 2];
+ args[0] = "chmod";
+ args[1] = permissions;
+ for (int i = 2; i < args.length; i++)
+ {
+ args[i] = paths.get(i - 2);
+ }
+ Process p = Runtime.getRuntime().exec(args);
+ return p.waitFor();
+ }
+
+ // Very limited for the moment: apply only permissions to the current user and
+ // does not work in non-English environments... to work in non English we
+ // should use xcalcs but it does not come in the windows default install...
+ // :-(
+ // This method is not called for the moment, but the code works, so that is
+ // why
+ // is kept.
+ private static int changePermissionsWindows(String path, String unixPerm)
+ throws IOException, InterruptedException
+ {
+ String windowsPerm;
+ int i = Integer.parseInt(unixPerm.substring(0, 1));
+ if (Integer.lowestOneBit(i) == 1)
+ {
+ // Executable: give full permissions
+ windowsPerm = "F";
+ } else if (Integer.highestOneBit(i) == 4)
+ {
+ // Writable
+ windowsPerm = "W";
+ } else if (Integer.highestOneBit(i) == 2)
+ {
+ // Readable
+ windowsPerm = "R";
+ } else
+ {
+ // No permissions
+ windowsPerm = "N";
+ }
+
+ String user = System.getProperty("user.name");
+ String[] args =
+ { "cacls", path, "/P", user + ":" + windowsPerm };
+ Process p = Runtime.getRuntime().exec(args);
+
+ // TODO: This only works in ENGLISH systems!!!!!!
+ p.getOutputStream().write("Y\n".getBytes());
+ p.getOutputStream().flush();
+ return p.waitFor();
+ }
+
+ /**
+ * Indicates whether we are in a web start installation or not.
+ *
+ * @return <CODE>true</CODE> if we are in a web start installation and
+ * <CODE>false</CODE> if not.
+ */
+ public static boolean isWebStart()
+ {
+ return "true".equals(System.getProperty(JnlpProperties.IS_WEBSTART));
+ }
+
+ /**
+ * Returns <CODE>true</CODE> if this is an uninstallation and
+ * <CODE>false</CODE> otherwise.
+ * @return <CODE>true</CODE> if this is an uninstallation and
+ * <CODE>false</CODE> otherwise.
+ */
+ public static boolean isUninstall()
+ {
+ return "true".equals(System.getProperty("org.opends.quicksetup.uninstall"));
+ }
+
+ /**
+ * Creates a clear LDAP connection and returns the corresponding LdapContext.
+ * This methods uses the specified parameters to create a JNDI environment
+ * hashtable and creates an InitialLdapContext instance.
+ *
+ * @param ldapURL
+ * the target LDAP URL
+ * @param dn
+ * passed as Context.SECURITY_PRINCIPAL if not null
+ * @param pwd
+ * passed as Context.SECURITY_CREDENTIALS if not null
+ * @param timeout
+ * passed as com.sun.jndi.ldap.connect.timeout if > 0
+ * @param env
+ * null or additional environment properties
+ *
+ * @throws NamingException
+ * the exception thrown when instantiating InitialLdapContext
+ *
+ * @return the created InitialLdapContext.
+ * @see javax.naming.Context
+ * @see javax.naming.ldap.InitialLdapContext
+ */
+ public static InitialLdapContext createLdapContext(String ldapURL, String dn,
+ String pwd, int timeout, Hashtable<String, String> env)
+ throws NamingException
+ {
+ if (env != null)
+ { // We clone 'env' so that we can modify it freely
+ env = new Hashtable<String, String>(env);
+ } else
+ {
+ env = new Hashtable<String, String>();
+ }
+ env
+ .put(Context.INITIAL_CONTEXT_FACTORY,
+ "com.sun.jndi.ldap.LdapCtxFactory");
+ env.put(Context.PROVIDER_URL, ldapURL);
+ if (timeout >= 1)
+ {
+ env.put("com.sun.jndi.ldap.connect.timeout", String.valueOf(timeout));
+ }
+ if (dn != null)
+ {
+ env.put(Context.SECURITY_PRINCIPAL, dn);
+ }
+ if (pwd != null)
+ {
+ env.put(Context.SECURITY_CREDENTIALS, pwd);
+ }
+
+ /* Contains the DirContext and the Exception if any */
+ final Object[] pair = new Object[]
+ { null, null };
+ final Hashtable fEnv = env;
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ pair[0] = new InitialLdapContext(fEnv, null);
+
+ } catch (NamingException ne)
+ {
+ pair[1] = ne;
+
+ } catch (RuntimeException re)
+ {
+ pair[1] = re;
+ }
+ }
+ });
+ return getInitialLdapContext(t, pair, timeout);
+ }
+ /**
+ * This is just a commodity method used to try to get an InitialLdapContext.
+ * @param t the Thread to be used to create the InitialLdapContext.
+ * @param pair an Object[] array that contains the InitialLdapContext and the
+ * Exception if any occurred.
+ * @param timeout the timeout. If we do not get to create the connection
+ * before the timeout a CommunicationException will be thrown.
+ * @return the created InitialLdapContext
+ * @throws NamingException if something goes wrong during the creation.
+ */
+ private static InitialLdapContext getInitialLdapContext(Thread t,
+ Object[] pair, int timeout) throws NamingException
+ {
+ try
+ {
+ if (timeout > 0)
+ {
+ t.start();
+ t.join(timeout);
+ } else
+ {
+ t.run();
+ }
+
+ } catch (InterruptedException x)
+ {
+ // This might happen for problems in sockets
+ // so it does not necessarily imply a bug
+ }
+
+ boolean throwException = false;
+
+ if ((timeout > 0) && t.isAlive())
+ {
+ t.interrupt();
+ try
+ {
+ t.join(2000);
+ } catch (InterruptedException x)
+ {
+ // This might happen for problems in sockets
+ // so it does not necessarily imply a bug
+ }
+ throwException = true;
+ }
+
+ if ((pair[0] == null) && (pair[1] == null))
+ {
+ throwException = true;
+ }
+
+ if (throwException)
+ {
+ NamingException xx;
+ ConnectException x = new ConnectException("Connection timed out");
+ xx = new CommunicationException("Connection timed out");
+ xx.initCause(x);
+ throw xx;
+ }
+
+ if (pair[1] != null)
+ {
+ if (pair[1] instanceof NamingException)
+ {
+ throw (NamingException) pair[1];
+
+ } else if (pair[1] instanceof RuntimeException)
+ {
+ throw (RuntimeException) pair[1];
+ }
+ }
+ return (InitialLdapContext) pair[0];
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java b/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java
new file mode 100644
index 0000000..c44614c
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserException.java
@@ -0,0 +1,61 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.util;
+
+/**
+ * This class is the exception that we get when we try to launch the user web
+ * browser and we fail. The exception is generated in WebBrowserLauncher.
+ *
+ */
+public class WebBrowserException extends Exception
+{
+ private static final long serialVersionUID = 4283835325192567244L;
+
+ private String url;
+
+ /**
+ * Constructor of the WebBrowserException.
+ * @param url the url that we were trying to display.
+ * @param msg the error message.
+ * @param rootCause the root cause.
+ */
+ public WebBrowserException(String url, String msg, Exception rootCause)
+ {
+ super(msg, rootCause);
+ this.url = url;
+ }
+
+ /**
+ * Returns the url that we were trying to display when the exception occurred.
+ * @return the url that we were trying to display when the exception occurred.
+ */
+ public String getUrl()
+ {
+ return this.url;
+ }
+}
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserLauncher.java b/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserLauncher.java
new file mode 100644
index 0000000..5330752
--- /dev/null
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/WebBrowserLauncher.java
@@ -0,0 +1,109 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.util;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * This is a very basic class used to launch the user web browser.
+ *
+ */
+public class WebBrowserLauncher
+{
+ /**
+ * Tries to launch the user web browser with a given URL.
+ * @param url the url to be used to launch the web browser.
+ * @throws WebBrowserException if launching failed.
+ */
+ public static void openURL(String url) throws WebBrowserException
+ {
+ try
+ {
+ if (Utils.isMacOS())
+ {
+ Class<?> fileMgr = Class.forName("com.apple.eio.FileManager");
+ Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[]
+ { String.class });
+ openURL.invoke(null, new Object[]
+ { url });
+
+ } else if (Utils.isWindows())
+ {
+ String[] cmd = {"rundll32", "url.dll,FileProtocolHandler", url};
+ Runtime.getRuntime().exec(cmd);
+
+ } else
+ {
+ // assume Unix or Linux
+ String[] browsers =
+ { "firefox", "opera", "konqueror", "epiphany", "mozilla",
+ "netscape" };
+ String browser = null;
+ for (int count = 0; count < browsers.length && browser == null;
+ count++)
+ {
+ if (Runtime.getRuntime().exec(new String[]
+ { "which", browsers[count] }).waitFor() == 0)
+ {
+ browser = browsers[count];
+ }
+ }
+
+ if (browser == null)
+ {
+ throw new WebBrowserException(url, "Could not find web browser",
+ null);
+ } else
+ {
+ Runtime.getRuntime().exec(new String[]
+ { browser, url });
+ }
+ }
+ } catch (ClassNotFoundException cnfe)
+ {
+ throw new WebBrowserException(url, "Class Not Found Exception", cnfe);
+ } catch (IOException ioe)
+ {
+ throw new WebBrowserException(url, "IO Exception", ioe);
+ } catch (InterruptedException ie)
+ {
+ throw new WebBrowserException(url, "Interrupted Exception", ie);
+ } catch (NoSuchMethodException nsme)
+ {
+ throw new WebBrowserException(url, "No Such Method Exception", nsme);
+ } catch (InvocationTargetException ite)
+ {
+ throw new WebBrowserException(url, "Invocation Target Exception", ite);
+ } catch (IllegalAccessException iae)
+ {
+ throw new WebBrowserException(url, "Illegal Access Exception", iae);
+ }
+ }
+}
diff --git a/opends/src/server/org/opends/server/tools/ImportLDIF.java b/opends/src/server/org/opends/server/tools/ImportLDIF.java
index 33a3790..640b269 100644
--- a/opends/src/server/org/opends/server/tools/ImportLDIF.java
+++ b/opends/src/server/org/opends/server/tools/ImportLDIF.java
@@ -662,8 +662,12 @@
ArrayList<Backend> backendList = new ArrayList<Backend>();
ArrayList<ConfigEntry> entryList = new ArrayList<ConfigEntry>();
- ArrayList<List<DN>> dnList = new ArrayList<List<DN>>();
- getBackends(backendList, entryList, dnList);
+ ArrayList<List<DN>> dnList = new ArrayList<List<DN>>();
+ int code = getBackends(backendList, entryList, dnList);
+ if (code != 0)
+ {
+ return code;
+ }
int numBackends = backendList.size();
for (int i=0; i < numBackends; i++)
@@ -1000,8 +1004,11 @@
* the backends will be placed.
* @param dnList A list into which the set of base DNs for each backend
* will be placed.
+ *
+ * @return 0 if everything went fine. 1 if an error occurred.
+ *
*/
- private static void getBackends(ArrayList<Backend> backendList,
+ private static int getBackends(ArrayList<Backend> backendList,
ArrayList<ConfigEntry> entryList,
ArrayList<List<DN>> dnList)
{
@@ -1017,7 +1024,7 @@
String message = getMessage(msgID, DN_BACKEND_BASE, de.getErrorMessage());
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message,
msgID);
- System.exit(1);
+ return 1;
}
catch (Exception e)
{
@@ -1026,7 +1033,7 @@
stackTraceToSingleLineString(e));
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message,
msgID);
- System.exit(1);
+ return 1;
}
ConfigEntry baseEntry = null;
@@ -1040,7 +1047,7 @@
String message = getMessage(msgID, DN_BACKEND_BASE, ce.getMessage());
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message,
msgID);
- System.exit(1);
+ return 1;
}
catch (Exception e)
{
@@ -1049,7 +1056,7 @@
stackTraceToSingleLineString(e));
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR, message,
msgID);
- System.exit(1);
+ return 1;
}
@@ -1084,7 +1091,7 @@
ce.getMessage());
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- System.exit(1);
+ return 1;
}
catch (Exception e)
{
@@ -1093,7 +1100,7 @@
stackTraceToSingleLineString(e));
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- System.exit(1);
+ return 1;
}
@@ -1124,7 +1131,7 @@
ce.getMessage());
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- System.exit(1);
+ return 1;
}
catch (Exception e)
{
@@ -1133,7 +1140,7 @@
stackTraceToSingleLineString(e));
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- System.exit(1);
+ return 1;
}
Class backendClass = null;
@@ -1149,7 +1156,7 @@
stackTraceToSingleLineString(e));
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- System.exit(1);
+ return 1;
}
Backend backend = null;
@@ -1166,7 +1173,7 @@
stackTraceToSingleLineString(e));
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- System.exit(1);
+ return 1;
}
@@ -1201,7 +1208,7 @@
stackTraceToSingleLineString(e));
logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- System.exit(1);
+ return 1;
}
@@ -1209,6 +1216,7 @@
entryList.add(configEntry);
dnList.add(baseDNs);
}
+ return 0;
}
}
--
Gitblit v1.10.0