opends/src/quicksetup/org/opends/quicksetup/Application.java
@@ -60,13 +60,11 @@ * Creates an application by instantiating the Application class * denoted by the System property * <code>org.opends.quicksetup.Application.class</code>. * @param formatter ProgressMessageFormatter that will be passed to the * constructor of Application * @return Application object that was newly instantiated * @throws ApplicationException if there was a problem creating * the new Application object */ static public Application create(ProgressMessageFormatter formatter) static public Application create() throws ApplicationException { Application app; String appClassName = opends/src/quicksetup/org/opends/quicksetup/CliApplication.java
New file @@ -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 2007 Sun Microsystems, Inc. */ package org.opends.quicksetup; import org.opends.quicksetup.event.ProgressNotifier; import org.opends.quicksetup.util.ProgressMessageFormatter; /** * Represents a quick setup CLI application. */ public interface CliApplication extends ProgressNotifier, Runnable { /** * Creates a set of user data from command line arguments and installation * status. * @param args String[] of arguments passed in from the command line * @param status the current installation status * @return UserData object populated to reflect the input args and status * @throws UserDataException if something is wrong */ UserData createUserData(String[] args, CurrentInstallStatus status) throws UserDataException; /** * Sets the user data this application will use when running. * @param userData UserData to use when running */ void setUserData(UserData userData); /** * Sets the formatter that will be used to format messages. * @param formatter ProgressMessageFormatter used to format messages */ void setProgressMessageFormatter(ProgressMessageFormatter formatter); /** * Indicates whether or not this applicat is finished running. * @return boolean where true indicates we are not running */ boolean isFinished(); /** * Gets any exception that happened while this application was running. * A null value returned from this method indicates that the execution * of the CLI program is not complete or was successful. * @return an exception that happened while the CLI was running */ ApplicationException getException(); } opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java
New file @@ -0,0 +1,226 @@ /* * 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 2007 Sun Microsystems, Inc. */ package org.opends.quicksetup; import org.opends.quicksetup.util.Utils; import org.opends.quicksetup.i18n.ResourceProvider; import java.io.ByteArrayOutputStream; import java.util.Set; import java.util.ArrayList; import java.util.logging.Logger; /** * Helper class containing useful methods for processing input and output * for a CliApplication. */ public class CliApplicationHelper { static private final Logger LOG = Logger.getLogger(CliApplication.class.getName()); /** * Interactively prompts (on standard output) the user to provide a string * value. Any non-empty string will be allowed (the empty string will * indicate that the default should be used). The method will display the * message until the user provides one of the values in the validValues * parameter. * * @param formatKey Key for access the prompts format string from the * bundle * @param prompt The prompt to present to the user. * @param defaultValue The default value returned if the user clicks enter. * @param validValues The valid values that can be accepted as user input. * * @return The string value read from the user. */ protected String promptConfirm(String formatKey, String prompt, String defaultValue, String[] validValues) { System.out.println(); boolean isValid = false; String response = null; while (!isValid) { String msg = getMsg(formatKey, new String[] {prompt, defaultValue}); System.out.print(msg); System.out.flush(); response = readLine(); if (response.equals("")) { response = defaultValue; } for (int i=0; i<validValues.length && !isValid; i++) { isValid = validValues[i].equalsIgnoreCase(response); } } return response; } /** * Reads a line of text from standard input. * * @return The line of text read from standard input, or <CODE>null</CODE> * if the end of the stream is reached or an error occurs while * attempting to read the response. */ private String readLine() { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); while (true) { int b = System.in.read(); if ((b < 0) || (b == '\n')) { break; } else if (b == '\r') { int b2 = System.in.read(); if (b2 == '\n') { break; } else { baos.write(b); baos.write(b2); } } else { baos.write(b); } } return new String(baos.toByteArray(), "UTF-8"); } catch (Exception e) { System.err.println(getMsg("cli-uninstall-error-reading-stdin")); return null; } } /** * Returns <CODE>true</CODE> if this is a silent uninstall and * <CODE>false</CODE> otherwise. * @param args the arguments passed in the command line. * @return <CODE>true</CODE> if this is a silent uninstall and * <CODE>false</CODE> otherwise. */ protected boolean isSilent(String[] args) { boolean isSilent = false; for (int i=0; i<args.length && !isSilent; i++) { if (args[i].equalsIgnoreCase("--silentUninstall") || args[i].equalsIgnoreCase("-s")) { isSilent = true; } } return isSilent; } /** * Commodity method used to validate the arguments provided by the user in * the command line and updating the UserData object accordingly. * @param userData the UserData object to be updated. * @param args the arguments passed in the command line. * @param validArgs arguments that are acceptable by this application. * @throws org.opends.quicksetup.UserDataException if there is an error with * the data provided by the user. */ protected void validateArguments(UserData userData, String[] args, Set<String> validArgs) throws UserDataException { ArrayList<String> errors = new ArrayList<String>(); for (String arg1 : args) { if (validArgs.contains(arg1)) { // Ignore } else { String[] arg = {arg1}; errors.add(getMsg("cli-uninstall-unknown-argument", arg)); } } if (errors.size() > 0) { String msg = Utils.getStringFromCollection(errors, QuickSetupCli.LINE_SEPARATOR+QuickSetupCli.LINE_SEPARATOR); throw new UserDataException(null, msg); } } /** * The following three methods are just commodity methods to get localized * messages. * @param key String key * @return String message */ protected static String getMsg(String key) { return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key), Utils.getCommandLineMaxLineWidth()); } /** * The following three methods are just commodity methods to get localized * messages. * @param key String key * @param args String[] args * @return String message */ protected static String getMsg(String key, String[] args) { return org.opends.server.util.StaticUtils.wrapText( getI18n().getMsg(key, args), Utils.getCommandLineMaxLineWidth()); } /** * Gets the resource provider instance. * @return ResourceProvider instance */ protected static ResourceProvider getI18n() { return ResourceProvider.getInstance(); } } opends/src/quicksetup/org/opends/quicksetup/Launcher.java
New file @@ -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 2007 Sun Microsystems, Inc. */ package org.opends.quicksetup; import org.opends.quicksetup.util.Utils; import org.opends.quicksetup.i18n.ResourceProvider; import java.io.PrintStream; import java.io.ByteArrayOutputStream; /** * Responsible for providing initial evaluation of command line arguments * and determining whether to launch a CLI, GUI, or print a usage statement. */ public abstract class Launcher { /** Arguments with which this launcher was invoked. */ protected String[] args; /** * Creates a Launcher. * @param args String[] of argument passes from the command line */ public Launcher(String[] args) { if (args == null) { throw new IllegalArgumentException("args cannot be null"); } this.args = args; } /** * Indicates whether or not the launcher should print a usage * statement based on the content of the arguments passed into * the constructor. * @return boolean where true indicates usage should be printed */ protected boolean shouldPrintUsage() { boolean printUsage = false; if (!isCli() && args.length > 0) { printUsage = true; } else { if ((args != null) && (args.length > 0)) { for (String arg : args) { if (arg.equalsIgnoreCase("-H") || arg.equalsIgnoreCase("--help")) { printUsage = true; } } } } return printUsage; } /** * Indicates whether the launcher will launch a command line versus * a graphical application based on the contents of the arguments * passed into the constructor. * @return boolean where true indicates that a CLI application should * be launched */ protected boolean isCli() { boolean isCli = false; for (String arg : args) { if (arg.equalsIgnoreCase("--cli")) { isCli = true; break; } } return isCli; } /** * Creates an internationaized message based on the input key and * properly formatted for the terminal. * @param key for the message in the bundle * @return String message properly formatted for the terminal */ protected String getMsg(String key) { return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key), Utils.getCommandLineMaxLineWidth()); } /** * Prints a usage message to the terminal and exits * with exit code QuickSetupCli.USER_DATA_ERROR. * @param i18nMsg localized user message that will * be printed to std error */ protected void printUsage(String i18nMsg) { System.err.println(i18nMsg); System.exit(QuickSetupCli.USER_DATA_ERROR); } /** * Launches the graphical uninstall. The graphical uninstall is launched in a * different thread that the main thread because if we have a problem with the * graphical system (for instance the DISPLAY environment variable is not * correctly set) the native libraries will call exit. However if we launch * this from another thread, the thread will just be killed. * * This code also assumes that if the call to SplashWindow.main worked (and * the splash screen was displayed) we will never get out of it (we will call * a System.exit() when we close the graphical uninstall dialog). * * @param args String[] 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. */ protected int launchGui(final String[] args) { final int[] returnValue = { -1 }; Thread t = new Thread(new Runnable() { public void run() { // Setup MacOSX native menu bar before AWT is loaded. Utils.setMacOSXMenuBar(getFrameTitle()); 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]; } /** * Gets the frame title of the GUI application that will be used * in some operating systems. * @return internationalized String representing the frame title */ abstract protected String getFrameTitle(); /** * Launches the command line based uninstall. * * @param args the arguments passed * @param cliApp the CLI application to launch * @return 0 if everything worked fine, and an error code if something wrong * occurred. */ protected int launchCli(String[] args, CliApplication cliApp) { System.out.println(getMsg("uninstall-launcher-launching-cli")); System.setProperty("org.opends.quicksetup.cli", "true"); QuickSetupCli cli = new QuickSetupCli(cliApp, args); int returnValue = cli.run(); if (returnValue == QuickSetupCli.USER_DATA_ERROR) { printUsage(); } // Add an extra space systematically System.out.println(); return returnValue; } /** * Prints a usage statement to terminal and exits * with an error code. */ protected abstract void printUsage(); /** * Creates a CLI application that will be run if the * launcher needs to launch a CLI application. * @return CliApplication that will be run */ protected abstract CliApplication createCliApplication(); /** * Called before the launcher launches the GUI. Here * subclasses can do any application specific things * like set system properties of print status messages * that need to be done before the GUI launches. */ protected abstract void willLaunchGui(); /** * Called if launching of the GUI failed. Here * subclasses can so application specific things * like print a message. */ protected abstract void guiLaunchFailed(); /** * The main method which is called by the uninstall command lines. */ public void launch() { if (shouldPrintUsage()) { printUsage(); } else if (isCli()) { int exitCode = launchCli(args, createCliApplication()); if (exitCode != 0) { System.exit(exitCode); } } else { willLaunchGui(); int exitCode = launchGui(args); if (exitCode != 0) { guiLaunchFailed(); exitCode = launchCli(args, createCliApplication()); if (exitCode != 0) { System.exit(exitCode); } } } } /** * This class is used to avoid displaying the error message related to display * problems that we might have when trying to display the SplashWindow. * */ private class EmptyPrintStream extends PrintStream { /** * Default constructor. * */ public EmptyPrintStream() { super(new ByteArrayOutputStream(), true); } /** * {@inheritDoc} */ public void println(String msg) { } } private ResourceProvider getI18n() { return ResourceProvider.getInstance(); } } opends/src/quicksetup/org/opends/quicksetup/QuickSetup.java
@@ -117,7 +117,7 @@ { ProgressMessageFormatter formatter = new HtmlProgressMessageFormatter(); try { application = Application.create(formatter); application = Application.create(); application.setProgressMessageFormatter(formatter); } catch (ApplicationException e) { LOG.log(Level.INFO, "error", e); @@ -135,15 +135,6 @@ } } private Application createApplication(ProgressMessageFormatter formatter) { try { application = Application.create(formatter); } catch (ApplicationException e) { LOG.log(Level.INFO, "error", e); } return application; } /** * Gets the current installation status of the filesystem * bits this quick setup is managing. opends/src/quicksetup/org/opends/quicksetup/QuickSetupCli.java
New file @@ -0,0 +1,209 @@ /* * 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 2007 Sun Microsystems, Inc. */ package org.opends.quicksetup; import org.opends.quicksetup.util.ProgressMessageFormatter; import org.opends.quicksetup.util.PlainTextProgressMessageFormatter; import org.opends.quicksetup.util.Utils; import org.opends.quicksetup.event.ProgressUpdateListener; import org.opends.quicksetup.event.ProgressUpdateEvent; import org.opends.quicksetup.i18n.ResourceProvider; /** * Controller for managing the execution of a CliApplication. */ public class QuickSetupCli { /** * Return code: Uninstall successful. */ static public int SUCCESSFUL = 0; /** * Return code: User Cancelled uninstall. */ static public int CANCELLED = 1; /** * Return code: User provided invalid data. */ static public int USER_DATA_ERROR = 2; /** * Return code: Error accessing file system (reading/writing). */ static public int ERROR_ACCESSING_FILE_SYSTEM = 3; /** * Return code: Error stopping server. */ static public int ERROR_STOPPING_SERVER = 4; /** * Return code: Bug. */ static public int BUG = 5; /** Platform dependent filesystem separator. */ public static String LINE_SEPARATOR = System.getProperty("line.separator"); /** Arguments passed in the command line. */ protected String[] args; private CliApplication cliApp; /** * Creates a QuickSetupCli instance. * @param cliApp the application to be run * @param args arguments passed in from the command line */ public QuickSetupCli(CliApplication cliApp, String[] args) { this.cliApp = cliApp; this.args = args; } /** * Parses the user data and prompts the user for data if required. If the * user provides all the required data it launches the Uninstaller. * * @return the return code (SUCCESSFUL, CANCELLED, USER_DATA_ERROR, * ERROR_ACCESSING_FILE_SYSTEM, ERROR_STOPPING_SERVER or BUG. */ public int run() { int returnValue; // Parse the arguments try { CurrentInstallStatus installStatus = new CurrentInstallStatus(); UserData userData = cliApp.createUserData(args, installStatus); if (userData != null) { ProgressMessageFormatter formatter = new PlainTextProgressMessageFormatter(); cliApp.setUserData(userData); cliApp.setProgressMessageFormatter(formatter); cliApp.addProgressUpdateListener( new ProgressUpdateListener() { /** * ProgressUpdateListener implementation. * @param ev the ProgressUpdateEvent we receive. * */ public void progressUpdate(ProgressUpdateEvent ev) { System.out.print( org.opends.server.util.StaticUtils.wrapText(ev.getNewLogs(), Utils.getCommandLineMaxLineWidth())); } }); new Thread(cliApp).start(); while (!cliApp.isFinished()) { try { Thread.sleep(100); } catch (Exception ex) { } } ApplicationException ue = cliApp.getException(); if (ue != null) { switch (ue.getType()) { case FILE_SYSTEM_ERROR: returnValue = ERROR_ACCESSING_FILE_SYSTEM; break; case STOP_ERROR: returnValue = ERROR_STOPPING_SERVER; break; case BUG: returnValue = BUG; break; default: throw new IllegalStateException( "Unknown ApplicationException type: "+ue.getType()); } } else { returnValue = SUCCESSFUL; } } else { // User cancelled installation. returnValue = CANCELLED; } } catch (UserDataException uude) { System.err.println(LINE_SEPARATOR+uude.getLocalizedMessage()+ LINE_SEPARATOR); returnValue = USER_DATA_ERROR; } return returnValue; } /** * The following three methods are just commodity methods to get localized * messages. * @param key String key * @return String message */ protected static String getMsg(String key) { return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key), Utils.getCommandLineMaxLineWidth()); } /** * The following three methods are just commodity methods to get localized * messages. * @param key String key * @param args String[] args * @return String message */ protected static String getMsg(String key, String[] args) { return org.opends.server.util.StaticUtils.wrapText( getI18n().getMsg(key, args), Utils.getCommandLineMaxLineWidth()); } private static ResourceProvider getI18n() { return ResourceProvider.getInstance(); } } opends/src/quicksetup/org/opends/quicksetup/installer/InstallLauncher.java
@@ -26,12 +26,10 @@ */ package org.opends.quicksetup.installer; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.ArrayList; import org.opends.quicksetup.SplashScreen; import org.opends.quicksetup.i18n.ResourceProvider; import org.opends.quicksetup.Launcher; import org.opends.quicksetup.CliApplication; import org.opends.quicksetup.util.Utils; /** @@ -39,129 +37,132 @@ * 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 InstallLauncher { public class InstallLauncher extends Launcher { /** * 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; } } public static void main(String[] args) { new InstallLauncher(args).launch(); } if (!useCli) { if (args.length > 0) { if (args.length == 2) { /** * Creates a launcher. * * @param args the arguments passed by the command lines. */ public InstallLauncher(String[] args) { super(args); } /** * {@inheritDoc} */ protected boolean shouldPrintUsage() { boolean displayUsage = false; if ((args != null) && (args.length > 0)) { if (!isCli()) { 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")) { if (!args[0].equals("-P")) { displayUsage = true; } } else { } else { displayUsage = true; } } } } if (displayUsage) { String arg; if (Utils.isWindows()) { arg = Utils.getWindowsSetupFileName(); } else { arg = Utils.getUnixSetupFileName(); } /* * This is required because the usage message contains '{' characters that * mess up the MessageFormat.format method. */ String msg; if (Utils.isWindows()) { msg= getMsg("setup-launcher-usage-windows"); } else { msg= getMsg("setup-launcher-usage-unix"); } 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 { System.setProperty("org.opends.quicksetup.Application.class", "org.opends.quicksetup.installer.offline.OfflineInstaller"); 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); } } } return displayUsage; } /** * 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 * {@inheritDoc} */ private static int launchCliSetup(String[] args) { protected void guiLaunchFailed() { System.err.println(getMsg("setup-launcher-gui-launched-failed")); } /** * {@inheritDoc} */ protected void willLaunchGui() { System.out.println(getMsg("setup-launcher-launching-gui")); System.setProperty("org.opends.quicksetup.Application.class", "org.opends.quicksetup.installer.offline.OfflineInstaller"); } /** * {@inheritDoc} */ protected String getFrameTitle() { return getMsg("frame-install-title"); } /** * {@inheritDoc} */ public void printUsage() { String arg; if (Utils.isWindows()) { arg = Utils.getWindowsSetupFileName(); } else { arg = Utils.getUnixSetupFileName(); } /* * This is required because the usage message contains '{' characters that * mess up the MessageFormat.format method. */ String msg; if (Utils.isWindows()) { msg = getMsg("setup-launcher-usage-windows"); } else { msg = getMsg("setup-launcher-usage-unix"); } msg = msg.replace("{0}", arg); printUsage(msg); } /** * {@inheritDoc} */ protected CliApplication createCliApplication() { // Setup currently has no implemented CliApplication // but rather relies on InstallDS from the server // package. Note that launchCli is overloaded // to run this application instead of the default // behavior in Launcher return null; } /** * {@inheritDoc} */ @Override protected int launchCli(String[] args, CliApplication cliApp) { System.setProperty("org.opends.quicksetup.cli", "true"); if (Utils.isWindows()) { if (Utils.isWindows()) { System.setProperty("org.opends.server.scriptName", Utils.getWindowsSetupFileName()); } else { Utils.getWindowsSetupFileName()); } else { System.setProperty("org.opends.server.scriptName", Utils.getUnixSetupFileName()); Utils.getUnixSetupFileName()); } ArrayList<String> newArgList = new ArrayList<String>(); if (args != null) { for (int i = 0; i < args.length; i++) { if (!args[i].equalsIgnoreCase("--cli")) { if (args != null) { for (int i = 0; i < args.length; i++) { if (!args[i].equalsIgnoreCase("--cli")) { newArgList.add(args[i]); } } @@ -177,92 +178,4 @@ 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() { // Setup MacOSX native menu bar before AWT is loaded. Utils.setMacOSXMenuBar(getMsg("frame-install-title")); 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) { } } } opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCli.java
File was deleted opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallCliHelper.java
New file @@ -0,0 +1,408 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.quicksetup.uninstaller; import org.opends.quicksetup.*; import org.opends.quicksetup.util.Utils; import java.util.HashSet; import java.util.Set; /** * The class used to provide some CLI interface in the uninstall. * * This class basically is in charge of parsing the data provided by the user * in the command line and displaying messages asking the user for information. * * Once the user has provided all the required information it calls Uninstaller * and launches it. * */ class UninstallCliHelper extends CliApplicationHelper { static private String FORMAT_KEY = "cli-uninstall-confirm-prompt"; /** * Creates a UserData based in the arguments provided. It asks * user for additional information if what is provided in the arguments is not * enough. * @param args the arguments provided in the command line. * @param installStatus the current install status. * @return the UserData object with what the user wants to uninstall * and null if the user cancels the uninstallation. * @throws UserDataException if there is an error parsing the data * in the arguments. */ public UninstallUserData createUserData(String[] args, CurrentInstallStatus installStatus) throws UserDataException { UninstallUserData userData = new UninstallUserData(); boolean silentUninstall; boolean isCancelled = false; /* Step 1: validate the arguments */ Set<String> validArgs = new HashSet<String>(); validArgs.add("--cli"); validArgs.add("-H"); validArgs.add("--help"); validArgs.add("--silentUninstall"); validArgs.add("-s"); validateArguments(userData, args, validArgs); silentUninstall = isSilent(args); /* Step 2: If this is not a silent install ask for confirmation to delete * the different parts of the installation */ Set<String> outsideDbs = getOutsideDbs(installStatus); Set<String> outsideLogs = getOutsideLogs(installStatus); if (silentUninstall) { userData.setRemoveBackups(true); userData.setRemoveConfigurationAndSchema(true); userData.setRemoveDatabases(true); userData.setRemoveLDIFs(true); userData.setRemoveLibrariesAndTools(true); userData.setRemoveLogs(true); userData.setExternalDbsToRemove(outsideDbs); userData.setExternalLogsToRemove(outsideLogs); } else { isCancelled = askWhatToDelete(userData, outsideDbs, outsideLogs); } /* * Step 3: check if server is running. Depending if it is running and the * OS we are running, ask for authentication information. */ if (!isCancelled) { isCancelled = askConfirmationToStop(userData, silentUninstall); } if (isCancelled) { userData = null; } return userData; } /** * Returns a Set of relative paths containing the db paths outside the * installation. * @param installStatus the Current Install Status object. * @return a Set of relative paths containing the db paths outside the * installation. */ private Set<String> getOutsideDbs(CurrentInstallStatus installStatus) { return Utils.getOutsideDbs(installStatus); } /** * Returns a Set of relative paths containing the log paths outside the * installation. * @param installStatus the Current Install Status object. * @return a Set of relative paths containing the log paths outside the * installation. */ private Set<String> getOutsideLogs(CurrentInstallStatus installStatus) { return Utils.getOutsideLogs(installStatus); } /** * Commodity method used to ask the user to confirm the deletion of certain * parts of the server. It updates the provided UserData object * accordingly. Returns <CODE>true</CODE> if the user cancels and <CODE> * false</CODE> otherwise. * @param userData the UserData object to be updated. * @param outsideDbs the set of relative paths of databases located outside * the installation path of the server. * @param outsideLogs the set of relative paths of log files located outside * the installation path of the server. * @return <CODE>true</CODE> if the user cancels and <CODE>false</CODE> * otherwise. */ private boolean askWhatToDelete(UninstallUserData userData, Set<String> outsideDbs, Set<String> outsideLogs) { boolean cancelled = false; String answer = promptConfirm(FORMAT_KEY, getMsg("cli-uninstall-what-to-delete"), "1", new String[] {"1", "2", "3"}); if ("3".equals(answer)) { cancelled = true; } else if ("1".equals(answer)) { userData.setRemoveBackups(true); userData.setRemoveConfigurationAndSchema(true); userData.setRemoveDatabases(true); userData.setRemoveLDIFs(true); userData.setRemoveLibrariesAndTools(true); userData.setRemoveLogs(true); userData.setExternalDbsToRemove(outsideDbs); userData.setExternalLogsToRemove(outsideLogs); } else { boolean somethingSelected = false; while (!somethingSelected) { // Ask for confirmation for the different items String[] keys = { "cli-uninstall-confirm-libraries-binaries", "cli-uninstall-confirm-databases", "cli-uninstall-confirm-logs", "cli-uninstall-confirm-configuration-schema", "cli-uninstall-confirm-backups", "cli-uninstall-confirm-ldifs", "cli-uninstall-confirm-outsidedbs", "cli-uninstall-confirm-outsidelogs" }; String[] validValues = { getMsg("cli-uninstall-yes-long"), getMsg("cli-uninstall-no-long"), getMsg("cli-uninstall-yes-short"), getMsg("cli-uninstall-no-short") }; boolean[] answers = new boolean[keys.length]; for (int i=0; i<keys.length; i++) { boolean ignore = ((i == 6) && (outsideDbs.size() == 0)) || ((i == 7) && (outsideLogs.size() == 0)); if (!ignore) { String msg; if (i == 6) { String[] arg = {Utils.getStringFromCollection(outsideDbs, QuickSetupCli.LINE_SEPARATOR)}; msg = getMsg(keys[i], arg); } else if (i == 7) { String[] arg = {Utils.getStringFromCollection(outsideLogs, QuickSetupCli.LINE_SEPARATOR)}; msg = getMsg(keys[i], arg); } else { msg = getMsg(keys[i]); } answer = promptConfirm(FORMAT_KEY, msg, getMsg("cli-uninstall-yes-long"), validValues); answers[i] = getMsg("cli-uninstall-yes-long").equalsIgnoreCase(answer) || getMsg("cli-uninstall-yes-short").equalsIgnoreCase(answer); } else { answers[i] = false; } } for (int i=0; i<answers.length; i++) { switch (i) { case 0: userData.setRemoveLibrariesAndTools(answers[i]); break; case 1: userData.setRemoveDatabases(answers[i]); break; case 2: userData.setRemoveLogs(answers[i]); break; case 3: userData.setRemoveConfigurationAndSchema(answers[i]); break; case 4: userData.setRemoveBackups(answers[i]); break; case 5: userData.setRemoveLDIFs(answers[i]); break; case 6: if (answers[i]) { userData.setExternalDbsToRemove(outsideDbs); } break; case 7: if (answers[i]) { userData.setExternalLogsToRemove(outsideLogs); } break; } } if ((userData.getExternalDbsToRemove().size() == 0) && (userData.getExternalLogsToRemove().size() == 0) && !userData.getRemoveLibrariesAndTools() && !userData.getRemoveDatabases() && !userData.getRemoveConfigurationAndSchema() && !userData.getRemoveBackups() && !userData.getRemoveLDIFs() && !userData.getRemoveLogs()) { somethingSelected = false; System.out.println(QuickSetupCli.LINE_SEPARATOR+ getMsg("cli-uninstall-nothing-to-be-uninstalled")); } else { somethingSelected = true; } } } return cancelled; } /** * Commodity method used to ask the user (when necessary) if the server must * be stopped or not. If required it also asks the user authentication to * be able to shut down the server in Windows. * @param userData the UserData object to be updated with the * authentication of the user. * @param silentUninstall boolean telling whether this is a silent uninstall * or not. * @return <CODE>true</CODE> if the user wants to continue with uninstall and * <CODE>false</CODE> otherwise. * @throws UserDataException if there is a problem with the data * provided by the user (in the particular case where we are on silent * uninstall and some data is missing or not valid). */ private boolean askConfirmationToStop(UserData userData, boolean silentUninstall) throws UserDataException { boolean cancelled = false; if (CurrentInstallStatus.isServerRunning()) { if (!silentUninstall) { /* Ask for confirmation to stop server */ cancelled = !confirmToStopServer(); } if (!cancelled) { /* During all the confirmations, the server might be stopped. */ userData.setStopServer(CurrentInstallStatus.isServerRunning()); } } else { userData.setStopServer(false); if (!silentUninstall) { /* Ask for confirmation to delete files */ cancelled = !confirmDeleteFiles(); } } return cancelled; } /** * Ask for confirmation to stop server. * @return <CODE>true</CODE> if the user wants to continue and stop the * server. <CODE>false</CODE> otherwise. */ private boolean confirmToStopServer() { boolean confirm = true; String[] validValues = { getMsg("cli-uninstall-yes-short"), getMsg("cli-uninstall-no-short"), getMsg("cli-uninstall-yes-long"), getMsg("cli-uninstall-no-long") }; String answer = promptConfirm(FORMAT_KEY, getMsg("cli-uninstall-confirm-stop"), getMsg("cli-uninstall-yes-long"), validValues); if (getMsg("cli-uninstall-no-short").equalsIgnoreCase(answer) || getMsg("cli-uninstall-no-long").equalsIgnoreCase(answer)) { confirm = false; } return confirm; } /** * Ask for confirmation to delete files. * @return <CODE>true</CODE> if the user wants to continue and delete the * files. <CODE>false</CODE> otherwise. */ private boolean confirmDeleteFiles() { boolean confirm = true; String[] validValues = { getMsg("cli-uninstall-yes-short"), getMsg("cli-uninstall-no-short"), getMsg("cli-uninstall-yes-long"), getMsg("cli-uninstall-no-long") }; String answer = promptConfirm(FORMAT_KEY, getMsg("cli-uninstall-confirm-delete-files"), getMsg("cli-uninstall-yes-long"), validValues); if (getMsg("cli-uninstall-no-short").equalsIgnoreCase(answer) || getMsg("cli-uninstall-no-long").equalsIgnoreCase(answer)) { confirm = false; } return confirm; } } opends/src/quicksetup/org/opends/quicksetup/uninstaller/UninstallLauncher.java
@@ -27,11 +27,8 @@ package org.opends.quicksetup.uninstaller; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import org.opends.quicksetup.SplashScreen; import org.opends.quicksetup.i18n.ResourceProvider; import org.opends.quicksetup.CliApplication; import org.opends.quicksetup.Launcher; import org.opends.quicksetup.util.Utils; /** @@ -39,198 +36,77 @@ * of the Directory Server. It just checks the command line arguments and the * environment and determines whether the graphical or the command line * based uninstall much be launched. * */ public class UninstallLauncher { public class UninstallLauncher extends Launcher { /** * The main method which is called by the uninstall command lines. * 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) { new UninstallLauncher(args).launch(); } /** * Creates a launcher. * * @param args the arguments passed by the command lines. */ public static void main(String[] args) { boolean printUsage = false; boolean useCli = false; if ((args != null) && (args.length > 0)) { for (int i = 0; i < args.length; i++) { if (args[i].equalsIgnoreCase("--cli")) { useCli = true; } else if (args[i].equalsIgnoreCase("-H") || args[i].equalsIgnoreCase("--help")) { printUsage = true; } } if (!useCli) { if (args.length > 0) { printUsage = true; } } } if (printUsage) { printUsage(); System.exit(1); } else if (useCli) { int exitCode = launchCliUninstall(args); if (exitCode != 0) { System.exit(exitCode); } } else { System.setProperty("org.opends.quicksetup.uninstall", "true"); System.setProperty("org.opends.quicksetup.Application.class", "org.opends.quicksetup.uninstaller.Uninstaller"); int exitCode = launchGuiUninstall(args); if (exitCode != 0) { System.err.println(getMsg("uninstall-launcher-gui-launched-failed")); exitCode = launchCliUninstall(args); if (exitCode != 0) { System.exit(exitCode); } } } public UninstallLauncher(String[] args) { super(args); } /** * Launches the command line based uninstall. * @param args the arguments passed * @return 0 if everything worked fine, and an error code if something wrong * occurred. * {@inheritDoc} */ private static int launchCliUninstall(String[] args) { System.setProperty("org.opends.quicksetup.cli", "true"); UninstallCli cli = new UninstallCli(args); int returnValue = cli.run(); if (returnValue == UninstallCli.USER_DATA_ERROR) { printUsage(); } // Add an extra space systematically System.out.println(); return returnValue; protected void guiLaunchFailed() { System.err.println(getMsg("uninstall-launcher-gui-launched-failed")); } /** * Launches the graphical uninstall. The graphical uninstall is launched in a * different thread that the main thread because if we have a problem with the * graphical system (for instance the DISPLAY environment variable is not * correctly set) the native libraries will call exit. However if we launch * this from another thread, the thread will just be killed. * * This code also assumes that if the call to SplashWindow.main worked (and * the splash screen was displayed) we will never get out of it (we will call * a System.exit() when we close the graphical uninstall dialog). * * @params String[] args the arguments used to call the SplashWindow main * method * @return 0 if everything worked fine, or 1 if we could not display properly * the SplashWindow. * {@inheritDoc} */ private static int launchGuiUninstall(final String[] args) { protected void willLaunchGui() { System.out.println(getMsg("uninstall-launcher-launching-gui")); final int[] returnValue = { -1 }; Thread t = new Thread(new Runnable() { public void run() { // Setup MacOSX native menu bar before AWT is loaded. Utils.setMacOSXMenuBar(getMsg("frame-uninstall-title")); 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]; System.setProperty("org.opends.quicksetup.uninstall", "true"); System.setProperty("org.opends.quicksetup.Application.class", "org.opends.quicksetup.uninstaller.Uninstaller"); } private static void printUsage() { /** * {@inheritDoc} */ protected CliApplication createCliApplication() { return new Uninstaller(); } /** * {@inheritDoc} */ protected String getFrameTitle() { return getMsg("frame-uninstall-title"); } /** * {@inheritDoc} */ protected void printUsage() { String arg; if (Utils.isWindows()) { if (Utils.isWindows()) { arg = Utils.getWindowsUninstallFileName(); } else { } else { arg = Utils.getUnixUninstallFileName(); } String msg = getMsg("uninstall-launcher-usage"); /* * This is required because the usage message contains '{' characters that * mess up the MessageFormat.format method. */ String msg = getMsg("uninstall-launcher-usage"); msg = msg.replace("{0}", arg); System.err.println(msg); printUsage(msg); } /** * The following three methods are just commodity methods to get localized * messages. */ private static String getMsg(String key) { return org.opends.server.util.StaticUtils.wrapText(getI18n().getMsg(key), Utils.getCommandLineMaxLineWidth()); } private static ResourceProvider getI18n() { return ResourceProvider.getInstance(); } /** * This class is used to avoid displaying the error message related to display * problems that we might have when trying to display the SplashWindow. * */ static class EmptyPrintStream extends PrintStream { /** * Default constructor. * */ public EmptyPrintStream() { super(new ByteArrayOutputStream(), true); } /** * {@inheritDoc} */ public void println(String msg) { } } } opends/src/quicksetup/org/opends/quicksetup/uninstaller/Uninstaller.java
@@ -37,7 +37,7 @@ /** * This class is in charge of performing the uninstallation of Open DS. */ public class Uninstaller extends Application { public class Uninstaller extends Application implements CliApplication { private ProgressStep status = UninstallProgressStep.NOT_STARTED; @@ -51,6 +51,8 @@ private Boolean isWindowsServiceEnabled; private UninstallCliHelper cliHelper = new UninstallCliHelper(); /** * {@inheritDoc} */ @@ -61,6 +63,15 @@ /** * {@inheritDoc} */ public UserData createUserData(String[] args, CurrentInstallStatus status) throws UserDataException { return cliHelper.createUserData(args, status); } /** * {@inheritDoc} */ protected String getInstallationPath() { return null; }