From edb7b32eaa2db4a171496d30ed3293bfa06b30c8 Mon Sep 17 00:00:00 2001
From: Violette Roche-Montane <violette.roche-montane@forgerock.com>
Date: Tue, 11 Feb 2014 13:36:41 +0000
Subject: [PATCH] Checkpoint commit for OPENDJ-1303 - added DEFAULT_LDAP_CONNECT_TIMEOUT to constants. - added ClientException, merge it with CLIException. Replaced CLIException calls. (CLIException will disappear soon) - Console application : errors,warnings should be displayed in stdout if interactive mode is enabled. - added unit tests. - removed closeIfNotNull / replaced it by Utils.closeSilently
---
opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java | 7
opendj-cli/src/main/java/com/forgerock/opendj/cli/ClientException.java | 108 ++++++++++++++++++
opendj-cli/src/test/java/com/forgerock/opendj/cli/UtilsTestCase.java | 6
opendj-cli/src/main/java/com/forgerock/opendj/cli/ConsoleApplication.java | 131 ++++++++++-----------
opendj-cli/src/test/java/com/forgerock/opendj/cli/ConsoleApplicationTestCase.java | 58 +++++++++
opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java | 3
6 files changed, 236 insertions(+), 77 deletions(-)
diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java
index 4dc1a78..c32484b 100755
--- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java
+++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/CliConstants.java
@@ -31,6 +31,9 @@
*/
public final class CliConstants {
+ /** Default value for LDAP connection timeout. */
+ public static final int DEFAULT_LDAP_CONNECT_TIMEOUT = 30000;
+
/** Default value for incrementing port number. */
public static final int PORT_INCREMENT = 1000;
diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ClientException.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ClientException.java
new file mode 100644
index 0000000..4848ad5
--- /dev/null
+++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ClientException.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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ *
+ * Copyright 2006-2008 Sun Microsystems, Inc.
+ * Portions Copyright 2014 ForgeRock AS
+ */
+package com.forgerock.opendj.cli;
+
+import static com.forgerock.opendj.cli.CliMessages.ERR_CONSOLE_INPUT_ERROR;
+import org.forgerock.i18n.LocalizableException;
+import org.forgerock.i18n.LocalizableMessage;
+
+/**
+ * This class defines an exception that may be thrown if a local problem occurs in a Directory Server client.
+ */
+public class ClientException extends Exception implements LocalizableException {
+ /**
+ * The serial version identifier required to satisfy the compiler because this class extends
+ * <CODE>java.lang.Exception</CODE>, which implements the <CODE>java.io.Serializable</CODE> interface. This value
+ * was generated using the <CODE>serialver</CODE> command-line utility included with the Java SDK.
+ */
+ private static final long serialVersionUID = 1384120263337669664L;
+
+ /** The return code. */
+ private ReturnCode returnCode;
+
+ /** The message linked to that exception. */
+ private final LocalizableMessage message;
+
+ /**
+ * Adapts any exception that may have occurred whilst reading input from the
+ * console.
+ *
+ * @param cause
+ * The exception that occurred whilst reading input from the
+ * console.
+ * @return Returns a new CLI exception describing a problem that occurred
+ * whilst reading input from the console.
+ */
+ public static ClientException adaptInputException(final Throwable cause) {
+ return new ClientException(ReturnCode.ERROR_USER_DATA, ERR_CONSOLE_INPUT_ERROR.get(cause.getMessage()), cause);
+ }
+
+ /**
+ * Creates a new client exception with the provided message.
+ *
+ * @param exitCode
+ * The exit code that may be used if the client considers this to be a fatal problem.
+ * @param message
+ * The message that explains the problem that occurred.
+ */
+ public ClientException(ReturnCode exitCode, LocalizableMessage message) {
+ super(message.toString());
+ this.returnCode = exitCode;
+ this.message = message;
+ }
+
+ /**
+ * Creates a new client exception with the provided message and root cause.
+ *
+ * @param exitCode
+ * The exit code that may be used if the client considers this to be a fatal problem.
+ * @param message
+ * The message that explains the problem that occurred.
+ * @param cause
+ * The exception that was caught to trigger this exception.
+ */
+ public ClientException(ReturnCode exitCode, LocalizableMessage message, Throwable cause) {
+ super(message.toString(), cause);
+ this.returnCode = exitCode;
+ this.message = message;
+ }
+
+ /**
+ * Retrieves the exit code that the client may use if it considers this to be a fatal problem.
+ *
+ * @return The exit code that the client may use if it considers this to be a fatal problem.
+ */
+ public int getReturnCode() {
+ return returnCode.get();
+ }
+
+ @Override
+ public LocalizableMessage getMessageObject() {
+ return message;
+ }
+
+}
diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConsoleApplication.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConsoleApplication.java
index 883923e..3811989 100755
--- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConsoleApplication.java
+++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConsoleApplication.java
@@ -34,7 +34,6 @@
import static com.forgerock.opendj.cli.Utils.wrapText;
import java.io.BufferedReader;
-import java.io.Closeable;
import java.io.Console;
import java.io.EOFException;
import java.io.IOException;
@@ -45,11 +44,9 @@
import org.forgerock.i18n.LocalizableMessage;
/**
- * This class provides an abstract base class which can be used as the basis of
- * a console-based application.
+ * This class provides an abstract base class which can be used as the basis of a console-based application.
*/
public abstract class ConsoleApplication {
- private final PrintStream err;
private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
@@ -57,6 +54,8 @@
private final PrintStream out;
+ private final PrintStream err;
+
private final Console console = System.console();
/**
@@ -80,27 +79,6 @@
}
/**
- * Closes the provided {@code Closeable}s if they are not {@code null}.
- *
- * @param closeables
- * The closeables to be closed.
- */
- public final void closeIfNotNull(Closeable... closeables) {
- if (closeables == null) {
- return;
- }
- for (Closeable closeable : closeables) {
- if (closeable != null) {
- try {
- closeable.close();
- } catch (Exception ignored) {
- // Do nothing.
- }
- }
- }
- }
-
- /**
* Returns the application error stream.
*
* @return The application error stream.
@@ -128,8 +106,8 @@
}
/**
- * Indicates whether or not the user has requested interactive behavior. The
- * default implementation returns {@code true}.
+ * Indicates whether or not the user has requested interactive behavior. The default implementation returns
+ * {@code true}.
*
* @return {@code true} if the user has requested interactive behavior.
*/
@@ -138,8 +116,7 @@
}
/**
- * Indicates whether or not the user has requested quiet output. The default
- * implementation returns {@code false}.
+ * Indicates whether or not the user has requested quiet output. The default implementation returns {@code false}.
*
* @return {@code true} if the user has requested quiet output.
*/
@@ -148,8 +125,8 @@
}
/**
- * Indicates whether or not the user has requested script-friendly output.
- * The default implementation returns {@code false}.
+ * Indicates whether or not the user has requested script-friendly output. The default implementation returns
+ * {@code false}.
*
* @return {@code true} if the user has requested script-friendly output.
*/
@@ -158,8 +135,7 @@
}
/**
- * Indicates whether or not the user has requested verbose output. The
- * default implementation returns {@code false}.
+ * Indicates whether or not the user has requested verbose output. The default implementation returns {@code false}.
*
* @return {@code true} if the user has requested verbose output.
*/
@@ -168,16 +144,15 @@
}
/**
- * Interactively prompts the user to press return to continue. This method
- * should be called in situations where a user needs to be given a chance to
- * read some documentation before continuing (continuing may cause the
+ * Interactively prompts the user to press return to continue. This method should be called in situations where a
+ * user needs to be given a chance to read some documentation before continuing (continuing may cause the
* documentation to be scrolled out of view).
*/
public final void pressReturnToContinue() {
final LocalizableMessage msg = INFO_MENU_PROMPT_RETURN_TO_CONTINUE.get();
try {
readLineOfInput(msg);
- } catch (final CLIException e) {
+ } catch (final ClientException e) {
// Ignore the exception - applications don't care.
}
}
@@ -189,14 +164,14 @@
* The message.
*/
public final void errPrint(final LocalizableMessage msg) {
- err.print(wrapText(msg, MAX_LINE_WIDTH));
+ getErrStream().print(wrap(msg));
}
/**
* Displays a blank line to the error stream.
*/
public final void errPrintln() {
- err.println();
+ getErrStream().println();
}
/**
@@ -206,12 +181,11 @@
* The message.
*/
public final void errPrintln(final LocalizableMessage msg) {
- err.println(wrapText(msg, MAX_LINE_WIDTH));
+ getErrStream().println(wrap(msg));
}
/**
- * Displays a message to the error stream indented by the specified number
- * of columns.
+ * Displays a message to the error stream indented by the specified number of columns.
*
* @param msg
* The message.
@@ -219,7 +193,7 @@
* The number of columns to indent.
*/
public final void errPrintln(final LocalizableMessage msg, final int indent) {
- err.println(wrapText(msg, MAX_LINE_WIDTH, indent));
+ getErrStream().println(wrapText(msg, MAX_LINE_WIDTH, indent));
}
/**
@@ -229,8 +203,8 @@
* The verbose message.
*/
public final void errPrintVerboseMessage(final LocalizableMessage msg) {
- if (isVerbose() || isInteractive()) {
- err.println(wrapText(msg, MAX_LINE_WIDTH));
+ if (isVerbose()) {
+ getErrStream().println(wrap(msg));
}
}
@@ -241,7 +215,7 @@
* The message.
*/
public final void print(final LocalizableMessage msg) {
- out.print(wrapText(msg, MAX_LINE_WIDTH));
+ out.print(wrap(msg));
}
/**
@@ -258,12 +232,11 @@
* The message.
*/
public final void println(final LocalizableMessage msg) {
- out.println(wrapText(msg, MAX_LINE_WIDTH));
+ out.println(wrap(msg));
}
/**
- * Displays a message to the output stream indented by the specified number
- * of columns.
+ * Displays a message to the output stream indented by the specified number of columns.
*
* @param msg
* The message.
@@ -282,27 +255,24 @@
*/
public final void printVerboseMessage(final LocalizableMessage msg) {
if (isVerbose() || isInteractive()) {
- out.println(wrapText(msg, MAX_LINE_WIDTH));
+ out.println(wrap(msg));
}
}
/**
- * Interactively prompts (on error 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, if there is one).
+ * Interactively prompts (on error 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, if there is one).
*
* @param prompt
* The prompt to present to the user.
* @param defaultValue
- * The default value to assume if the user presses ENTER without
- * typing anything, or {@code null} if there should not be a
- * default and the user must explicitly provide a value.
- * @throws CLIException
+ * The default value to assume if the user presses ENTER without typing anything, or {@code null} if
+ * there should not be a default and the user must explicitly provide a value.
+ * @throws ClientException
* If the line of input could not be retrieved for some reason.
* @return The string value read from the user.
*/
- public final String readInput(LocalizableMessage prompt, final String defaultValue)
- throws CLIException {
+ public final String readInput(LocalizableMessage prompt, final String defaultValue) throws ClientException {
while (true) {
if (defaultValue != null) {
prompt = INFO_PROMPT_SINGLE_DEFAULT.get(prompt.toString(), defaultValue);
@@ -327,13 +297,13 @@
* @param prompt
* The password prompt.
* @return The password.
- * @throws CLIException
+ * @throws ClientException
* If the password could not be retrieved for some reason.
*/
- public final char[] readPassword(final LocalizableMessage prompt) throws CLIException {
+ public final char[] readPassword(final LocalizableMessage prompt) throws ClientException {
if (console != null) {
if (prompt != null) {
- err.print(wrapText(prompt, MAX_LINE_WIDTH));
+ err.print(wrap(prompt));
err.print(" ");
}
try {
@@ -343,7 +313,7 @@
}
return password;
} catch (final Throwable e) {
- throw CLIException.adaptInputException(e);
+ throw ClientException.adaptInputException(e);
}
} else {
// FIXME: should go direct to char[] and avoid the String.
@@ -357,23 +327,48 @@
* @param prompt
* The prompt.
* @return The line of input.
- * @throws CLIException
+ * @throws ClientException
* If the line of input could not be retrieved for some reason.
*/
- private final String readLineOfInput(final LocalizableMessage prompt) throws CLIException {
+ private final String readLineOfInput(final LocalizableMessage prompt) throws ClientException {
if (prompt != null) {
- err.print(wrapText(prompt, MAX_LINE_WIDTH));
+ err.print(wrap(prompt));
err.print(" ");
}
try {
final String s = reader.readLine();
if (s == null) {
- throw CLIException.adaptInputException(new EOFException("End of input"));
+ throw ClientException.adaptInputException(new EOFException("End of input"));
} else {
return s;
}
} catch (final IOException e) {
- throw CLIException.adaptInputException(e);
+ throw ClientException.adaptInputException(e);
+ }
+ }
+
+ /**
+ * Inserts line breaks into the provided buffer to wrap text at no more than the specified column width (80).
+ *
+ * @param msg
+ * The message to wrap.
+ * @return The wrapped message.
+ */
+ private String wrap(final LocalizableMessage msg) {
+ return wrapText(msg, MAX_LINE_WIDTH);
+ }
+
+ /**
+ * Returns the error stream. Effectively, when an application is in "interactive mode" all the informations should
+ * be written in the stdout.
+ *
+ * @return The error stream that should be used with this application.
+ */
+ private PrintStream getErrStream() {
+ if (isInteractive()) {
+ return out;
+ } else {
+ return err;
}
}
diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java
index c1cbd2e..0c48ba0 100644
--- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java
+++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java
@@ -332,14 +332,15 @@
/**
* Checks that the java version.
*
- * @throws CLIException
+ * @throws ClientException
* If the java version we are running on is not compatible.
*/
- public static void checkJavaVersion() throws CLIException {
+ public static void checkJavaVersion() throws ClientException {
final String version = System.getProperty("java.specification.version");
if (!(Float.valueOf(version) >= 1.6)) {
final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
- throw new CLIException(ERR_INCOMPATIBLE_JAVA_VERSION.get("1.6", version, javaBin), null);
+ throw new ClientException(ReturnCode.JAVA_VERSION_INCOMPATIBLE, ERR_INCOMPATIBLE_JAVA_VERSION.get("1.6",
+ version, javaBin), null);
}
}
diff --git a/opendj-cli/src/test/java/com/forgerock/opendj/cli/ConsoleApplicationTestCase.java b/opendj-cli/src/test/java/com/forgerock/opendj/cli/ConsoleApplicationTestCase.java
index f22ad43..f0aa277 100644
--- a/opendj-cli/src/test/java/com/forgerock/opendj/cli/ConsoleApplicationTestCase.java
+++ b/opendj-cli/src/test/java/com/forgerock/opendj/cli/ConsoleApplicationTestCase.java
@@ -33,6 +33,8 @@
import org.testng.annotations.Test;
import static org.fest.assertions.Assertions.assertThat;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
/**
* Unit tests for the console application class.
@@ -80,8 +82,12 @@
return interactive;
}
- public void setVerbose(boolean verbose) {
- this.verbose = verbose;
+ public void setVerbose(boolean v) {
+ verbose = v;
+ }
+
+ public void setInteractive(boolean inter) {
+ interactive = inter;
}
}
@@ -99,7 +105,7 @@
public void testWriteLineInErrorStream() throws UnsupportedEncodingException {
final LocalizableMessage msg = LocalizableMessage.raw("Language is the source of misunderstandings.");
final MockConsoleApplication ca = MockConsoleApplication.getDefault();
- ca.errPrint(msg);
+ ca.errPrintln(msg);
assertThat(ca.getOut()).isEmpty();
assertThat(ca.getErr()).contains(msg.toString());
}
@@ -134,4 +140,50 @@
assertThat(ca.getOut()).isEmpty();
assertThat(ca.getErr()).contains(msg.toString());
}
+
+ /**
+ * In non interactive applications, standard messages should be displayed in the stdout(info) and errors to the
+ * stderr (warnings, errors).
+ *
+ * @throws UnsupportedEncodingException
+ */
+ @Test()
+ public void testNonInteractiveApplicationShouldNotStdoutErrors() throws UnsupportedEncodingException {
+ final LocalizableMessage msg = LocalizableMessage.raw("Language is the source of misunderstandings.");
+ final LocalizableMessage msg2 = LocalizableMessage
+ .raw("If somebody wants a sheep, that is a proof that one exists.");
+ final MockConsoleApplication ca = MockConsoleApplication.getDefault();
+
+ assertFalse(ca.isInteractive());
+ ca.errPrintln(msg);
+ assertThat(ca.getOut()).isEmpty();
+ assertThat(ca.getErr()).contains(msg.toString());
+ ca.println(msg2);
+ assertThat(ca.getOut()).contains(msg2.toString());
+ assertThat(ca.getErr()).doesNotContain(msg2.toString());
+ }
+
+ /**
+ * If an application is interactive, all messages should be redirect to the stdout. (info, warnings, errors).
+ *
+ * @throws UnsupportedEncodingException
+ */
+ @Test()
+ public void testInteractiveApplicationShouldStdoutErrors() throws UnsupportedEncodingException {
+ final LocalizableMessage msg = LocalizableMessage.raw("Language is the source of misunderstandings.");
+ final LocalizableMessage msg2 = LocalizableMessage
+ .raw("If somebody wants a sheep, that is a proof that one exists.");
+
+ final MockConsoleApplication ca = MockConsoleApplication.getDefault();
+
+ assertFalse(ca.isInteractive());
+ ca.setInteractive(true);
+ assertTrue(ca.isInteractive());
+ ca.errPrintln(msg);
+ assertThat(ca.getOut()).contains(msg.toString());
+ assertThat(ca.getErr()).isEmpty();
+ ca.println(msg2);
+ assertThat(ca.getOut()).contains(msg2.toString());
+ assertThat(ca.getErr()).isEmpty();
+ }
}
diff --git a/opendj-cli/src/test/java/com/forgerock/opendj/cli/UtilsTestCase.java b/opendj-cli/src/test/java/com/forgerock/opendj/cli/UtilsTestCase.java
index a1e679e..8df648b 100644
--- a/opendj-cli/src/test/java/com/forgerock/opendj/cli/UtilsTestCase.java
+++ b/opendj-cli/src/test/java/com/forgerock/opendj/cli/UtilsTestCase.java
@@ -29,8 +29,8 @@
public class UtilsTestCase extends CliTestCase {
- @Test(expectedExceptions = CLIException.class)
- public void testInvalidJavaVersion() throws CLIException {
+ @Test(expectedExceptions = ClientException.class)
+ public void testInvalidJavaVersion() throws ClientException {
final String original = System.getProperty("java.specification.version");
System.setProperty("java.specification.version", "1.5");
try {
@@ -41,7 +41,7 @@
}
@Test()
- public void testValidJavaVersion() throws CLIException {
+ public void testValidJavaVersion() throws ClientException {
Utils.checkJavaVersion();
}
}
--
Gitblit v1.10.0